Разберем ситуацию, с которой часто сталкиваются разработчики на платформе 1С:Предприятие 7.7 при попытке расширить стандартный функционал журналов документов. Одной из самых востребованных задач является организация отбора документов одновременно по нескольким критериям (например, по Складу и ВидуДокумента). Стандартными средствами платформы 7.7 отбор в журнале возможен только по одной графе отбора. Мы проанализируем, как обойти это ограничение, изучим технические причины ошибок позиционирования в DBF-файлах и выясним причину странного поведения "линейки прокрутки", когда документы внезапно исчезают из списка.
Рассмотрим ситуацию: вы создали общий строковый реквизит, включили его в отбор и записываете туда составную строку (код склада + название вида документа). На первый взгляд, все работает, но при попытке переместить бегунок прокрутки мышкой список "схлопывается", оставляя одну пустую строку. Выясним причину этого поведения.
В платформе 1С 7.7 механизм позиционирования в списках при установленном отборе напрямую зависит от работы индекса в файлах .DBF (или таблиц в SQL). Когда длина индексируемого строкового поля превышает определенный порог (обычно это 30–50 символов), алгоритм аппроксимации положения курсора начинает давать сбой. Платформа не может корректно вычислить "процентный вес" текущей записи в общем массиве данных индекса 1SJOURN.CDX. В результате при "захвате" бегунка мышкой система пытается позиционироваться на некорректный участок индекса, что приводит к визуальному исчезному данных.
Важный вывод: Для стабильной работы визуальных списков 1С 7.7 длина строки, по которой установлен отбор, должна быть минимально возможной. Оптимально — до 20-25 символов.
Вместо использования длинных наименований или кодов справочников, которые могут достигать большой длины, проанализируем возможность использования внутренних идентификаторов объектов. В 1С 7.7 каждый объект имеет уникальный ID (идентификатор), который в системе Base36 всегда занимает фиксированное количество символов. Используя методику работы с внутренними идентификаторами (Base36) для сокращения индексов, можно добиться максимальной производительности.
Посмотрим, как сформировать максимально короткую и надежную строку для отбора. Вместо кода склада (5-10 символов) и названия вида документа (20-30 символов) мы будем использовать внутренний ID склада и код типа документа. Рассмотрим пример кода, который можно поместить в модуль формы документа или в процедуру ПриЗаписи:
// Пример формирования компактного ключа для отбора
Процедура ПриЗаписи()
// Получаем внутренний идентификатор склада (13 символов)
ИдСклада = ЗначениеВСтрокуВнутр(Склад);
// Извлекаем только значимую часть ID (убираем лишние символы типа {"B","0","0",...})
// Для простоты можно использовать ЗначениеИзСтрокиВнутр или вспомогательные функции
// Получаем код вида документа (числовой идентификатор метаданных)
КодВида = НомерВидаДокумента(Контекст);
// Формируем реквизит "СтрОтбор"
СтрОтбор = ИдСклада + "_" + Строка(КодВида);
// Теперь этот реквизит можно использовать в графе отбора
КонецПроцедуры
Такой подход сокращает длину реквизита до 15-18 символов, что полностью устраняет глюки с линейкой прокрутки и ускоряет работу индексов.
Проанализируем более сложный, но "чистый" с точки зрения архитектуры метод. Если нам нужно делать отборы по очень сложным условиям, создание бесконечного количества общих реквизитов приведет к раздуванию таблицы 1SJOURN и замедлению всей системы. В этом случае лучше применить архитектуру вспомогательных справочников для реализации сложных связей. Для автоматизации наполнения таких структур данными из внешних источников может быть полезен импорт XML в 1С 7.7 во временный справочник, что упростит манипуляции с объектами через стандартные запросы.
КлючиОтбора с реквизитами Документ, Склад, ВидДокумента.Этот метод позволяет не только реализовать AND (И) условия, но и строить гораздо более гибкие фильтры, не нагружая основной файл журнала документов.
Чтобы не прописывать логику формирования строки отбора в каждом из 100 существующих видов документов, рассмотрим использование внешних компонент, таких как FormEx или 1C++. Для этого изучите руководство по внедрению глобальных перехватчиков событий, которые позволяют автоматизировать управление отборами без изменения метаданных каждого объекта. Чтобы вносить подобные изменения, не прерывая работу пользователей, удобно применять универсальный вызов отчетов и обработок, позволяющий обновлять логику без сохранения всей конфигурации.
Посмотрим на пример логики перехвата через класс-перехватчик. Нам необходимо создать глобальный объект, который будет "слушать" запись документов:
// В Глобальном модуле или стартовой обработке
Перехватчик = СоздатьОбъект("Перехватчик");
Перехватчик.ПерехватитьСобытияГК(Контекст);
// В классе перехватчика (обработка)
Процедура ПослеЗаписи(Конт)
Если ТипЗначенияСтр(Конт) = "Документ" Тогда
// Автоматически обновляем наш реквизит отбора
Конт.ОбщийРеквизитОтбора = СформироватьКлюч(Конт.Склад, Конт.Вид());
// Важно: использовать методы, не вызывающие бесконечную рекурсию записи
КонецЕсли;
КонецПроцедуры
Обратите внимание на важный нюанс: при использование перехватчиков событий отладчик 1С 7.7 часто не может "зайти" внутрь перехваченной процедуры. Рекомендуется выносить основную логику в Глобальный модуль для удобства отладки.
Разберем еще несколько технических моментов, которые помогут сделать работу пользователя комфортной:
ВидыОтбора() позволяет управлять списком доступных полей. Однако, программно удалить одну графу из стандартной кнопки сложно — проще создать свою кнопку "Фильтр" и вызывать УстановитьОтбор("ИмяГрафы", ЗначениеКлюча)..DBF файлам. Для отладки таких запросов на SQL-версиях платформы отлично подойдет консоль запросов, не требующая установки дополнительных компонент.1SJOURN.CDX. Если документов миллионы, это может стать критичным фактором. Всегда старайтесь использовать идентификаторы вместо строк.Подведем итог: глюк с прокруткой в 1С 7.7 — это прямое следствие избыточной длины индекса. Сокращение длины строки отбора и переход на внутренние ID объектов не только исправляет визуальные баги, но и значительно повышает производительность системы в целом.