При автоматизации работы с общим журналом документов часто возникает типовая прикладная задача: необходимо применить фильтр по определенному реквизиту (например, по штрихкоду картриджа), а если подходящих документов в базе нет, автоматически переключить отбор на другую графу или другое значение. Разберем особенности платформы 1С:Предприятие 7.7 и выясним, как правильно решить эту задачу без снижения производительности системы.
Проанализируем механику работы табличной части журнала документов в платформе 1С 7.7. Разработчики нередко пытаются вызвать метод вроде КоличествоСтрок() непосредственно у формы журнала или проверить реквизит ТекущийДокумент сразу после команды УстановитьОтбор(). Однако этот путь приводит к ошибкам по следующим причинам:
ТаблицаЗначений и не хранится в оперативной памяти целиком. Это визуальный курсор базы данных, считывающий записи порциями только для отображения на экране. Штатного контекстного метода для подсчета строк в открытом журнале не существует.УстановитьОтбор() лишь инициирует фильтрацию строк в интерфейсе, не возвращая булевого признака успешности или числа найденных позиций.ТекущийДокумент в модуле может по-прежнему ссылаться на документ, активный до применения фильтра.Поэтому правильный алгоритмический подход заключается в предварительной проверке: сначала программно выясняем, есть ли данные в базе по первому критерию, и только затем применяем соответствующий отбор к журналу.
Рассмотрим самый быстрый штатный способ проверки существования документов по графе отбора. Вместо выполнения тяжелых запросов к базе данных воспользуемся специализированным методом объекта Документ — методом ВыбратьПоЗначению().
Метод ВыбратьПоЗначению(<Дата1>, <Дата2>, <ИмяОтбора>, <Знач>) работает напрямую с системными индексами документов и возвращает числовое значение:
1 — если в указанном временном интервале обнаружен хотя бы один документ с искомым значением;0 — если ни одного документа по заданному отбору не найдено.Посмотрим на практический пример реализации в модуле формы общего журнала:
Док = СоздатьОбъект("Документ");
// Проверяем наличие документов в границах установленного периода журнала
Если Док.ВыбратьПоЗначению(НачалоИнтервала(), КонецИнтервала(), "ШККартриджа", ШтК) = 1 Тогда
УстановитьОтбор("ШККартриджа", ШтК);
Иначе
// Если документов не найдено, устанавливаем альтернативный отбор
УстановитьОтбор("ДругаяГрафа", ДругоеЗначение);
КонецЕсли;
Разберем ключевые технические нюансы этого кода:
НачалоИнтервала() и КонецИнтервала(). Журнал отображает документы только за выбранный пользователем интервал. Если выполнить поиск по всей базе, отбор в журнале все равно может оказаться пустым из-за ограничения периода. Функции контекста возвращают пустые даты, если период в журнале отключен, что корректно обрабатывается методом выборки.СоздатьОбъект("Документ"). При попытке применить метод к объекту вида СоздатьОбъект("Документ.ПриходнаяНакладная") платформа вызовет синтаксическую ошибку времени выполнения.ШККартриджа должен быть добавлен в конфигураторе в состав графы отбора или объявлен общим реквизитом документов с включенным свойством отбора.Разберем ситуацию, когда проверку необходимо выполнить с помощью встроенного механизма запросов 1С 7.7. Как справедливо отмечалось при обсуждении проблемы, в запросе критически важно не выбирать все строки документов в оперативную память, а агрегировать данные.
Посмотрим на пример формирования запроса на подсчет количества:
ТекстЗапроса = "
|Период с (НачалоИнтервала()) по (КонецИнтервала());
|ОбрабатыватьДокументы Все;
|ТекДок = Журнал.ТекущийДокумент;
|Условие (Журнал.ШККартриджа = ШтК);
|Группировка Всего;
|Функция КолДок = Количество(ТекДок);
|";
Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
Если Запрос.Группировка(1) = 1 Тогда
Если Запрос.КолДок > 0 Тогда
УстановитьОтбор("ШККартриджа", ШтК);
Иначе
УстановитьОтбор("ДругаяГрафа", ДругоеЗначение);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Обратим внимание: использование метода ВыбратьПоЗначению() предпочтительнее текстового запроса, поскольку он не тратит процессорное время на компиляцию текста запроса внутренним генератором и сразу позиционируется по системному индексу базы данных.
Если в процессе разработки требуется не просто переключить отбор, а постоянно взаимодействовать со списком и точно знать число отображаемых строк на форме, рассмотрим два альтернативных архитектурных подхода:
КоличествоСтрок(), однако теряется встроенный механизм постраничного листания больших объемов базы.SELECT TOP 1 ... к таблице журнала документов _1SJOURN отрабатывает за доли миллисекунды даже на базах объемом в сотни гигабайт.