Многие, вероятно сталкивались с такой задачей, как построение в памяти быстрого индекса и поиска в нем по нескольким реквизитам. В платформе 8.х худо-бедно этот вопрос решается на уровне запросов и данных, а в 7.7 он «красиво» не решается никак, и вобще не решается для операций с данными которые динамически находятся в памяти.
Попытавшись решать его когда-то на уровне слияния уникальных строк вроде: ЗначениеВСтрокуВнутр(..), я столкнулся с тем, что построение индекса для нескольких параметров растет катастрофически, длина строки в памяти для 1С ограничена, а при работе со списками где присутствует от 1000 строк и более, этот способ совсем плох.
Немного почитав документации и собрав в кучу остатки знаний по разработке в среде Delphi я наваял простенькую библиотеку, которую можно вызывать как из среды 7.7 так и 8.х. Скорость ее работы зависит от длины параметра, но достаточно велика, что отладчик иногда считает что время ее выполнения близко к нулю 😉
Регистрация библиотеки стандартная:
regsvr32 AddIn.dll
После этого в коде своей конфигурации вы можете производить с ней манипуляции обратившись к экземпляру объекта
«AddIn.AddInHasher»
Поскольку я практически применял ее только в разработке конфигураций на базе 1С версии 7.7, предлагаю краткий пример ее работы. Метод у внешней компоненты один
ВзятьХеш(_Параметр)
где: _Параметр — строка любой длины, которую вы сможете передать в вызываемый метод. Возвращает функция строку размером 20 символов. Внимание: на первых порах частой ошибкой сравнения результатов вычисления хеш-функции было то, что во входных параметрах оставались незначащие пробелы по краям (например при вводе из форм диалогов типа «Строка»), будьте внимательны к тому какие данные вы даете функции, т.к. даже незначительное различие входных строк, вызывает разный результат расчета.
Если в конфигурации объявлена переменная, которая всегда проинициализирована как объект этой библиотеки, то в табло 7.7 вы можете попробовать выполнить подобный пример:
_глпХешер.ВзятьХеш(«qwe») = dtgCJGEfyRml1U8P+fuk
СтрДлина(_глпХешер.ВзятьХеш(«qwe»)) = 20
Я намеренно сократил выводимое значение хеш-функции до 20 символов на низком уровне, это немного снижает вероятность неповторяемости оригинального алгоритма (даже 10#k8SjZc9Dxk-20 степени это вероятность космического масштаба ;), однако снимает необходимость усечения итоговой строки для применения в качестве индекса отборов в журналах документов, индекс которых, для реквизитов строкового типа, доблестные программисты 1С, вычисляют только у 20 первых символов — как бы вы не старались. Если кому интересно об этом приеме сообщу ниже.
Итак, пример кода для запуска в собственных разработках:
//Пример дакларации глобальной переменной
Перем _глпХешер Экспорт;
//Инициализация переменной для использования
_глпХешер = СоздатьОбъект(«AddIn.AddInHasher»);
//Рассчитывает кумулятивный хеш от серии до пяти входных параметров для запроса (например) реляций колонок из ТЗ
Функция _глПолучитьРасчетХешаОтПараметров(_Пар1, _Пар2=«», _Пар3=»», _Пар4=«», _Пар5=«») Экспорт
Возврат _глпХешер.ВзятьХеш(ЗначениеВСтрокуВнутр(_Пар1) +
?(_Пар2=«», «», ЗначениеВСтрокуВнутр(_Пар2)) +
?(_Пар3=«», «», ЗначениеВСтрокуВнутр(_Пар3)) +
?(_Пар4=«», «», ЗначениеВСтрокуВнутр(_Пар4)) +
?(_Пар5=«», «», ЗначениеВСтрокуВнутр(_Пар5)));
КонецФункции
Примеров применения на самом деле очень много, и это видимо повод для отдельной статьи. Но раз обещал, подробнее расскажу про отборы в журналах документов:
Многие «избалованные» программисты на платформе 8.х )) сейчас не очень озадачены тем, что бы в журнале документов иметь возможность отбирать список журнала по нескольким реквизитам. В 7.7 стандартными средствами эта задача не решается вообще, а ковырять bkend.dll для того что бы подставлять запросы к SQL или заниматься по советам некоторых любителей ковыряниями в самих индексах и отображениях внутри SQL для разрабатываемой базы, я счел крайне неприемлемыми. Итак: «как это работает» с использованием стандартных средств и приведенной DLL?
Приведу пример в форме описания методологии:
Предположим, нам необходимо сделать перекрестный отбор по комбинациям полей «МОЛ» и «Склад» в документах «Приходная накладная», «Перемещение ТМЦ» и «Реализация ТМЦ».
1. Вводим в каждый из этих документов строковый реквизит размером 20 символов (больше не имеет смысла), назовем ее «_ршОтборМОЛСклад».
2. Для каждого документа в модуле «ПриЗаписи» вычисляем значение хеш-функции от реквизитов «МОЛ» и «Склад». Пример:
_ршОтборМОЛСкладу = _глПолучитьРасчетХешаОтПараметров(МОЛ, Склад);
Для уже наполненной базы придется написать временную обработку, которая заполнит указанным хешем требуемые документы.
4. В разделе «Журналы» вводим графу отбора «_гоОтборМОЛСклад», от поля «_ршОтборМОЛСклад» в которую включаем строковые реквизиты шапки названных документов.
3. Создаем общий журнал с интерфейсом, где пользователь в форме журнала, выбирает произвольные значения «МОЛ» и «Склад» и по выбору каждого из реквизитов, вызываем модуль, который выполняет примерно следующее:
_пХешМОЛСклад = _глПолучитьРасчетХешаОтПараметров(МОЛ, Склад);
УстановитьОтбор(«_гоОтборМОЛСклад», _пХешМОЛСклад);
Собственно все — после этого вы обладаете мощным инструментом отбора документов в журнале не менее функционального чем в средствах 8.х.
Скажу, что это частный, наиболее простой пример применения. Я на самом деле использую этот инструмент для отбора по нескольким измерениям в справочниках, для отбора по виду документа в регистре (операция Вид() крайне медлительная для запрососв в 10-100 тыс. строк). При построении собственных систем учета заработной платы и многих других примерениях, которые стандартными средствами неразрешимы или требуют в несколько раз больше вычислительных ресурсов, если применять встроенный язык и проводить сравнения операцией логичского «И» в условиях.
Надеюсь, я был понятен, если есть вопросы, с удовольствием отвечу. Желаю удачи.
Самописная внешняя компонента, разработанная в среде Delphi, для расчета хеш-функции и пример применения в приложениях. Работает действительно быстро, особенно если сравнивать с пробегающими здесь алгоритмами написанными на встроенном языке 1С.
Перейти к публикации
Под 8.2 устойчиво работает? И не теряется ли время засчёт обращения к внешней компоненте и работе с ней?
Не проверял, но судя по тому что спецификация на InProc-OLE одинакова даже для MS Office и VBasic, то проблем быть не должно. На 7.7 она работает железобетонно уже больше 9 лет, я по доброте душевной решил поделиться, раз тут правила требуют )) Таких безобразий, как утечки памяти или деление на ноль, в ней не было никогда.
Зачем же внешняя компонента?
http://forum.mista.ru/topic.php?id=209284
Код на 1С с использованием объекта ScriptControl — на Мисте много информации, вот например:
Работает на ура, проверено (создавали ссылки для оплаты банковскими картами в системе payonlinesystem.com).
Быстрее ваш вариант с мисты работать по определению не может, т.к. там запускается скрипт который перед выполнением еще необходимо интерпретировать. Думаю любой тест покажет что мой вариант быстрее. Если речь идет о скорости, как приоритете, то мой вариант выиграет.
Интересно. а расчета SHA1 не планируется ?
За ваши деньги — любой каприз.. )) На самом деле, это очень старая библиотека, исходники не сохранил.. хотя библиотека chiper (для Delphi) которая шла на одном из дисков к журналу «Компьютер-пресс» — у меня есть. Могу презентовать, там есть на паскале библиотека более 40 функций в т.ч. SHA1. Теоретически скомпилировать новую либу для 1С, которая будет содержать интерфейс доступа через COM.
Напоминаю, даже этот MD5 на самом деле «обрезанный» под длину строки индекса в журнале 1С, это не полный хеш.
теперь эта функция встроена в 1С
(3) mikhailovaew, Только на стороне x64 сервера данный метод не работает, нет 64х-разрядного ScriptControl.
(8) спасибо, учту )
а как ее подключить в 8.2?
Кто-то пробовал, эта компонента работает на стороне x64 сервера?
Очень надо знать.
Переехал на x64 и все, все ScriptControl-ы перестали работать.
(11) mvgfirst, так это еще с апреляhttp://forum.infostart.ru/forum24/topic82319/message886543/#message886543 . компоненту ты так и не проверил, как я понял. а я ее забросил, поскольку мне лично она не нужна.