Как в модуле менеджера получить документы за день даты текущего документа

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Причина проблемы с контекстом в модуле менеджера

В отличие от модуля объекта или модуля формы, в модуле менеджера нет неявного контекста и нет свойства ЭтотОбъект. Модуль менеджера описывает общую логику сущности конфигурации, а не конкретный экземпляр.

В типовых конфигурациях экспортная процедура печати (например, Печать) всегда принимает на вход коллекцию ссылок на печатаемые документы — параметр обычно называется МассивОбъектов, либо передается одиночная Ссылка. Соответственно, получить дату исходного документа можно только через переданную ссылку.

Разбор распространенных ошибок

Проанализируем две распространенные ошибки, с которыми столкнулся автор темы:

  1. Ошибка «Неопознанная переменная (Дата)»: возникает при попытке обратиться к переменной Дата напрямую в кодовой части модуля менеджера. Поскольку контекста конкретного объекта нет, обращаться необходимо к свойству через ссылку (например, МассивОбъектов[0].Дата) либо использовать дату прямо внутри текста запроса.
  2. Ошибка «Несоответствие типов (параметр номер 1)» в методе Выбрать(): метод Выбрать() у объекта РезультатЗапроса принимает параметры ОбходРезультатаЗапроса, имя группировки и тип обхода для таблицы. Передача выражений вида НачалоДня(...) в метод Выбрать() недопустима. Вся фильтрация данных в платформе 1С должна выполняться в тексте запроса в секции ГДЕ.

Способ 1. Получение данных и фильтрация целиком в одном запросе (рекомендуемый)

Наиболее производительным и надежным решением является отказ от промежуточных расчетов даты в коде 1С. Язык запросов платформы содержит встроенные функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА. Это позволяет запросить требуемые документы, связав их по дате непосредственно на уровне СУБД.

Рассмотрим пример запроса, когда в процедуру печати передан массив ссылок МассивОбъектов:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Док1.Ссылка КАК ДокументОснование,
    |   Док2.Ссылка КАК СвязанныйДокумент,
    |   Док2.Номер КАК Номер,
    |   Док2.Дата КАК Дата
    |ИЗ
    |   Документ.Документ1 КАК Док1
    |       ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Документ2 КАК Док2
    |       ПО Док2.Дата МЕЖДУ НАЧАЛОПЕРИОДА(Док1.Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(Док1.Дата, ДЕНЬ)
    |ГДЕ
    |   Док1.Ссылка В(&МассивОбъектов)";

Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Заполнение параметров макета и вывод печатной формы
    Шапка.Параметры.Заполнить(Выборка);
    ТабДок.Вывести(Шапка);
КонецЦикла;

Преимущества этого способа:

  1. Корректно обрабатывается пакетная печать: если пользователь выбрал несколько документов за разные даты, каждый документ свяжется именно со своими сутками.
  2. База данных выполняет оптимизированную выборку за один заход без лишних обращений через точку во встроенном языке.

Способ 2. Передача границ дня через параметры запроса

Если печать выполняется строго для одного документа, либо дату исходного документа необходимо обработать в коде перед выполнением запроса, границы дня можно рассчитать стандартными функциями встроенного языка НачалоДня() и КонецДня().

Разберем по шагам реализацию данного подхода:


// Предполагаем, что СсылкаНаДокумент получена из параметров процедуры печати
ДатаИсходногоДокумента = СсылкаНаДокумент.Дата;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Док2.Ссылка КАК Ссылка,
    |   Док2.Номер КАК Номер,
    |   Док2.Дата КАК Дата,
    |   Док2.Контрагент КАК Контрагент
    |ИЗ
    |   Документ.Документ2 КАК Док2
    |ГДЕ
    |   Док2.Дата МЕЖДУ &ДатаНач И &ДатаКон";

Запрос.УстановитьПараметр("ДатаНач", НачалоДня(ДатаИсходногоДокумента));
Запрос.УстановитьПараметр("ДатаКон", КонецДня(ДатаИсходногоДокумента));

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    Шапка.Параметры.Заполнить(Выборка);
    ТабДок.Вывести(Шапка);
КонецЦикла;

Важные нюансы при работе с датами в печатных формах

При проектировании алгоритмов печати в модуле менеджера обратите внимание на следующие особенности:

  1. Несохраненные изменения в форме: если пользователь изменил дату документа в форме и нажал кнопку печати без предварительной записи, модуль менеджера прочитает из базы старую дату (по ссылке). Печать всегда формируется по записанным данным базы, если иное не предусмотрено передачей параметров формы в модуль менеджера.
  2. Понятие рабочей даты: свойство РабочаяДата не должно использоваться для привязки к датам документов. Рабочая дата служит лишь вспомогательным ориентиром для подстановки по умолчанию при интерактивном вводе новых документов и может не совпадать с реальной датой печатаемого объекта.
← На главную