Разработка собственных отчетов "с нуля" без использования Системы компоновки данных (СКД) — это отличный способ глубже понять внутренние механизмы платформы 1С:Предприятие 8. Однако начинающие программисты часто сталкиваются с ситуацией, когда вместо ожидаемых данных отчет выдает пустую форму или ошибку. В этой статье мы подробно разберем, почему отчет может не выводить данные, проанализируем типичные ошибки в логике запросов и научимся правильно работать с макетами и периодами.
Одной из самых частых ошибок является неправильная установка параметров &НачалоПериода и &КонецПериода. Проанализируем фрагмент кода, с которым возникли сложности:
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", ДобавитьМесяц(ТекущаяДата(), -6));
Здесь кроется критическая логическая ошибка. Функция НачалоМесяца(ТекущаяДата()) возвращает первое число текущего месяца (например, 01.10.2023). Функция ДобавитьМесяц(ТекущаяДата(), -6) возвращает дату на полгода назад (например, 01.04.2023). В языке запросов 1С оператор МЕЖДУ работает корректно только тогда, когда первое значение меньше второго. Если вы передадите в начало периода "октябрь", а в конец "апрель", запрос вернет пустой результат, так как в этом временном интервале нет ни одного дня.
Решение: Всегда следите за тем, чтобы НачалоПериода было хронологически раньше, чем КонецПериода.
Рассмотрим следующую ошибку, которая часто приводит к тому, что условия в цикле обхода результата запроса не срабатывают. В коде автора было написано:
ОбластьМакета.Параметры.ТекущийМесяц = Формат(ТекущаяДата(),"ДФ='MMMM yyyy'");
// ... позже в цикле ...
Если ОбластьМакета.Параметры.ТекущийМесяц = НачалоМесяца(ТекущаяДата()) Тогда
Проанализируем ситуацию. В первом случае в параметр макета записывается Строка (например, "Октябрь 2023"). Во втором случае мы пытаемся сравнить эту строку с результатом функции НачалоМесяца(), которая возвращает тип Дата. В 1С строка никогда не будет равна дате, поэтому условие Если всегда будет ложным, и данные в макет не попадут.
Решение: Для логических проверок всегда используйте чистые типы Дата. Преобразовывайте их в строку с помощью функции Формат() только в самый последний момент — непосредственно при выводе в ячейку макета для пользователя.
Когда мы работаем с документами и их табличными частями, в результате запроса могут появиться значения NULL. Это происходит, если данные по ссылке отсутствуют или используются сложные соединения. Попытка применить функцию НачалоМесяца() к значению NULL в коде приведет к ошибке "Преобразование в тип Дата не может быть выполнено".
Рассмотрим более правильный вариант запроса, который сразу группирует данные по месяцам, что избавляет нас от громоздких конструкций Если...ИначеЕсли:
Запрос.Текст = "ВЫБРАТЬ
| НАЧАЛОПЕРИОДА(СчетФактура.Дата, МЕСЯЦ) КАК ПериодМесяц,
| СчетФактура.Ссылка КАК Документ,
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ СчетФактура.Ссылка) КАК КолВо
|ИЗ
| Документ.СчетФактураПолученный КАК СчетФактура
|ГДЕ
| СчетФактура.Дата МЕЖДУ &НачалоПериода И &КонецПериода
|СГРУППИРОВАТЬ ПО
| НАЧАЛОПЕРИОДА(СчетФактура.Дата, МЕСЯЦ),
| СчетФактура.Ссылка";
Использование функции НАЧАЛОПЕРИОДА внутри самого запроса позволяет нам сразу получать унифицированную дату начала месяца для каждой записи. Это значительно упрощает последующую обработку.
Выясним причину, по которой даже при наличии данных отчет может казаться пустым. Это часто связано с неправильным вызовом методов Вывести() и Присоединить().
Разберем алгоритм работы с областями:
Область = Макет.ПолучитьОбласть("Строка").Область.Параметры.Тип = Результат.ТипДокумента.ТабДок.Вывести(Область).Если вы сначала выведете пустую область, а потом начнете менять ее параметры, в уже выведенном на экран отчете ничего не изменится. Также важно убедиться, что имена областей в конфигураторе (в макете) в точности совпадают с именами, которые вы вызываете в коде. Ошибка в одной букве приведет к тому, что область не будет найдена.
Если задача стоит вывести 6 месяцев в ряд (как колонки), использование ИначеЕсли для каждого месяца — плохая практика. Рассмотрим, как сделать это профессионально с помощью метода Присоединить():
// Выводим фиксированную левую часть (названия типов документов)
ТабДок.Вывести(ОбластьТипДокумента);
// В цикле присоединяем колонки месяцев справа
Для н = 0 По 5 Цикл
ТекущийМесяцПериода = ДобавитьМесяц(НачалоМесяца(ДатаНачала), н);
ОбластьМесяц = Макет.ПолучитьОбласть("КолонкаМесяц");
ОбластьМесяц.Параметры.НазваниеМесяца = Формат(ТекущийМесяцПериода, "ДФ='MMMM yyyy'");
ТабДок.Присоединить(ОбластьМесяц);
КонецЦикла;
Такой подход позволяет легко изменить глубину отчета (например, с 6 до 12 месяцев), просто изменив параметры цикла, не переписывая всю логику программы.
Проанализируем ситуацию: код написан, ошибок нет, но данных все равно нет. Что делать?
ГДЕ или в отсутствии данных в базе.Пока Результат.Следующий() Цикл. Если отладчик "проскакивает" цикл, значит, выборка пуста.Результат.Дата. Если там стоит NULL, функции типа НачалоМесяца() работать не будут.Помните, что для формирования сложных отчетов в современной 1С лучше использовать СКД. Она автоматически берет на себя управление периодами, группировками и корректным выводом в табличный документ, избавляя разработчика от рутинных ошибок, разобранных выше.