При разработке печатных форм в модуле менеджера разработчики часто сталкиваются с задачей отобрать связанные или подчиненные документы за ту же дату, что и исходный документ. На этом этапе нередко возникают две типичные трудности: непонимание того, откуда взять дату текущего документа без объектного контекста, и ошибки при попытке наложить фильтр по дате не в запросе, а в методе Выбрать().
Разберем детально, почему модуль менеджера не видит свойства напрямую, как избежать типичных ошибок типизации и как правильно составить запрос для выборки данных за конкретный день.
В отличие от модуля объекта или модуля формы, в модуле менеджера нет неявного контекста и нет свойства ЭтотОбъект. Модуль менеджера описывает общую логику сущности конфигурации, а не конкретный экземпляр.
В типовых конфигурациях экспортная процедура печати (например, Печать) всегда принимает на вход коллекцию ссылок на печатаемые документы — параметр обычно называется МассивОбъектов, либо передается одиночная Ссылка. Соответственно, получить дату исходного документа можно только через переданную ссылку.
Проанализируем две распространенные ошибки, с которыми столкнулся автор темы:
Дата напрямую в кодовой части модуля менеджера. Поскольку контекста конкретного объекта нет, обращаться необходимо к свойству через ссылку (например, МассивОбъектов[0].Дата) либо использовать дату прямо внутри текста запроса.Выбрать(): метод Выбрать() у объекта РезультатЗапроса принимает параметры ОбходРезультатаЗапроса, имя группировки и тип обхода для таблицы. Передача выражений вида НачалоДня(...) в метод Выбрать() недопустима. Вся фильтрация данных в платформе 1С должна выполняться в тексте запроса в секции ГДЕ.Наиболее производительным и надежным решением является отказ от промежуточных расчетов даты в коде 1С. Язык запросов платформы содержит встроенные функции НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА. Это позволяет запросить требуемые документы, связав их по дате непосредственно на уровне СУБД.
Рассмотрим пример запроса, когда в процедуру печати передан массив ссылок МассивОбъектов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док1.Ссылка КАК ДокументОснование,
| Док2.Ссылка КАК СвязанныйДокумент,
| Док2.Номер КАК Номер,
| Док2.Дата КАК Дата
|ИЗ
| Документ.Документ1 КАК Док1
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Документ2 КАК Док2
| ПО Док2.Дата МЕЖДУ НАЧАЛОПЕРИОДА(Док1.Дата, ДЕНЬ) И КОНЕЦПЕРИОДА(Док1.Дата, ДЕНЬ)
|ГДЕ
| Док1.Ссылка В(&МассивОбъектов)";
Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Заполнение параметров макета и вывод печатной формы
Шапка.Параметры.Заполнить(Выборка);
ТабДок.Вывести(Шапка);
КонецЦикла;
Преимущества этого способа:
Если печать выполняется строго для одного документа, либо дату исходного документа необходимо обработать в коде перед выполнением запроса, границы дня можно рассчитать стандартными функциями встроенного языка НачалоДня() и КонецДня().
Разберем по шагам реализацию данного подхода:
// Предполагаем, что СсылкаНаДокумент получена из параметров процедуры печати
ДатаИсходногоДокумента = СсылкаНаДокумент.Дата;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док2.Ссылка КАК Ссылка,
| Док2.Номер КАК Номер,
| Док2.Дата КАК Дата,
| Док2.Контрагент КАК Контрагент
|ИЗ
| Документ.Документ2 КАК Док2
|ГДЕ
| Док2.Дата МЕЖДУ &ДатаНач И &ДатаКон";
Запрос.УстановитьПараметр("ДатаНач", НачалоДня(ДатаИсходногоДокумента));
Запрос.УстановитьПараметр("ДатаКон", КонецДня(ДатаИсходногоДокумента));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Шапка.Параметры.Заполнить(Выборка);
ТабДок.Вывести(Шапка);
КонецЦикла;
При проектировании алгоритмов печати в модуле менеджера обратите внимание на следующие особенности:
РабочаяДата не должно использоваться для привязки к датам документов. Рабочая дата служит лишь вспомогательным ориентиром для подстановки по умолчанию при интерактивном вводе новых документов и может не совпадать с реальной датой печатаемого объекта.