Как в общем журнале документов 1С 7.7 проверить наличие строк и переключить отбор

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При автоматизации работы с общим журналом документов часто возникает типовая прикладная задача: необходимо применить фильтр по определенному реквизиту (например, по штрихкоду картриджа), а если подходящих документов в базе нет, автоматически переключить отбор на другую графу или другое значение. Разберем особенности платформы 1С:Предприятие 7.7 и выясним, как правильно решить эту задачу без снижения производительности системы.

Почему нельзя получить количество строк непосредственно из журнала

Проанализируем механику работы табличной части журнала документов в платформе 1С 7.7. Разработчики нередко пытаются вызвать метод вроде КоличествоСтрок() непосредственно у формы журнала или проверить реквизит ТекущийДокумент сразу после команды УстановитьОтбор(). Однако этот путь приводит к ошибкам по следующим причинам:

  1. Динамическая подгрузка данных: Таблица журнала в 1С 7.7 не является объектом ТаблицаЗначений и не хранится в оперативной памяти целиком. Это визуальный курсор базы данных, считывающий записи порциями только для отображения на экране. Штатного контекстного метода для подсчета строк в открытом журнале не существует.
  2. Особенности метода отбора: Процедура УстановитьОтбор() лишь инициирует фильтрацию строк в интерфейсе, не возвращая булевого признака успешности или числа найденных позиций.
  3. Асинхронность позиционирования: Перерисовка формы списка и позиционирование курсора происходят после завершения исполняемого блока кода, поэтому сразу после вызова процедуры отбора значение ТекущийДокумент в модуле может по-прежнему ссылаться на документ, активный до применения фильтра.

Поэтому правильный алгоритмический подход заключается в предварительной проверке: сначала программно выясняем, есть ли данные в базе по первому критерию, и только затем применяем соответствующий отбор к журналу.

Оптимальное решение через метод ВыбратьПоЗначению

Рассмотрим самый быстрый штатный способ проверки существования документов по графе отбора. Вместо выполнения тяжелых запросов к базе данных воспользуемся специализированным методом объекта Документ — методом ВыбратьПоЗначению().

Метод ВыбратьПоЗначению(<Дата1>, <Дата2>, <ИмяОтбора>, <Знач>) работает напрямую с системными индексами документов и возвращает числовое значение:

  1. 1 — если в указанном временном интервале обнаружен хотя бы один документ с искомым значением;
  2. 0 — если ни одного документа по заданному отбору не найдено.

Посмотрим на практический пример реализации в модуле формы общего журнала:


Док = СоздатьОбъект("Документ");

// Проверяем наличие документов в границах установленного периода журнала
Если Док.ВыбратьПоЗначению(НачалоИнтервала(), КонецИнтервала(), "ШККартриджа", ШтК) = 1 Тогда
    УстановитьОтбор("ШККартриджа", ШтК);
Иначе
    // Если документов не найдено, устанавливаем альтернативный отбор
    УстановитьОтбор("ДругаяГрафа", ДругоеЗначение);
КонецЕсли;

Разберем ключевые технические нюансы этого кода:

  1. Учет периода журнала: Обязательно используем функции НачалоИнтервала() и КонецИнтервала(). Журнал отображает документы только за выбранный пользователем интервал. Если выполнить поиск по всей базе, отбор в журнале все равно может оказаться пустым из-за ограничения периода. Функции контекста возвращают пустые даты, если период в журнале отключен, что корректно обрабатывается методом выборки.
  2. Тип объекта: Объект создается исключительно как документ неопределенного вида: СоздатьОбъект("Документ"). При попытке применить метод к объекту вида СоздатьОбъект("Документ.ПриходнаяНакладная") платформа вызовет синтаксическую ошибку времени выполнения.
  3. Настройка метаданных: Реквизит ШККартриджа должен быть добавлен в конфигураторе в состав графы отбора или объявлен общим реквизитом документов с включенным свойством отбора.

Альтернативный вариант: использование объекта Запрос

Разберем ситуацию, когда проверку необходимо выполнить с помощью встроенного механизма запросов 1С 7.7. Как справедливо отмечалось при обсуждении проблемы, в запросе критически важно не выбирать все строки документов в оперативную память, а агрегировать данные.

Посмотрим на пример формирования запроса на подсчет количества:


ТекстЗапроса = "
|Период с (НачалоИнтервала()) по (КонецИнтервала());
|ОбрабатыватьДокументы Все;
|ТекДок = Журнал.ТекущийДокумент;
|Условие (Журнал.ШККартриджа = ШтК);
|Группировка Всего;
|Функция КолДок = Количество(ТекДок);
|";

Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 1 Тогда
    Если Запрос.Группировка(1) = 1 Тогда
        Если Запрос.КолДок > 0 Тогда
            УстановитьОтбор("ШККартриджа", ШтК);
        Иначе
            УстановитьОтбор("ДругаяГрафа", ДругоеЗначение);
        КонецЕсли;
    КонецЕсли;
КонецЕсли;

Обратим внимание: использование метода ВыбратьПоЗначению() предпочтительнее текстового запроса, поскольку он не тратит процессорное время на компиляцию текста запроса внутренним генератором и сразу позиционируется по системному индексу базы данных.

Решения для нестандартных сценариев

Если в процессе разработки требуется не просто переключить отбор, а постоянно взаимодействовать со списком и точно знать число отображаемых строк на форме, рассмотрим два альтернативных архитектурных подхода:

  1. Форма на основе Таблицы Значений: Стандартный журнал документов заменяется диалоговой обработкой. На форме размещается таблица значений, в которую данные подгружаются запросом. В таком случае число записей всегда известно через метод КоличествоСтрок(), однако теряется встроенный механизм постраничного листания больших объемов базы.
  2. Прямой SQL-запрос (для клиент-серверного варианта): При работе с базой данных на MS SQL Server проверку наличия записей можно выполнить с помощью внешних компонент (таких как 1S++). Прямой запрос SELECT TOP 1 ... к таблице журнала документов _1SJOURN отрабатывает за доли миллисекунды даже на базах объемом в сотни гигабайт.
← На главную