При разработке печатных форм в среде «1С:Предприятие 8» начинающие программисты часто сталкиваются с ситуацией, когда табличный документ выводится, области макета отображаются, но значения параметров (например, номер документа, дата, контрагент) остаются пустыми. Рассмотрим подробнее, почему это происходит, и разберем правильные алгоритмы работы с выборкой результата запроса.
Проанализируем типичный фрагмент кода, в котором возникает проблема. Программист выполняет запрос, получает результат и сразу пытается обратиться к свойствам выборки:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
// Ошибка здесь:
ОбластьШапка.Параметры.Номер = Выборка.Номер;
ОбластьШапка.Параметры.Организация = Выборка.Организация;
Выясним причину, по которой этот код не работает. Метод Выбрать() возвращает объект ВыборкаИзРезультатаЗапроса, но в этот момент «курсор» (указатель на текущую запись) находится перед первой записью. Чтобы получить доступ к данным, необходимо переместить курсор на первую строку. Это делается с помощью метода Следующий().
Для того чтобы данные в шапке заполнились, нам нужно один раз вызвать метод Следующий(). Если в результате запроса гарантированно есть хотя бы одна строка (например, мы печатаем существующий документ), код должен выглядеть так:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Позиционируемся на первую запись
Если Выборка.Следующий() Тогда
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Номер = Выборка.Номер;
ОбластьШапка.Параметры.Организация = Выборка.Организация;
ТабДок.Вывести(ОбластьШапка);
КонецЕсли;
Однако возникает следующая задача: после того как мы заполнили шапку, нам нужно вывести строки табличной части (детальные записи). Но курсор уже стоит на первой строке, и если мы начнем цикл Пока Выборка.Следующий() Цикл, то пропустим первую запись или получим некорректный обход.
Здесь на помощь приходит метод Сбросить(). Он возвращает указатель выборки в исходное состояние (перед первой записью), что позволяет нам снова пройтись по данным в цикле:
Выборка.Сбросить(); // Возвращаемся в начало
Пока Выборка.Следующий() Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Номенклатура = Выборка.ВидРаботыНаименование;
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
Для ускорения написания кода и уменьшения количества ошибок рекомендуется использовать метод Заполнить() для параметров области. Этот метод автоматически сопоставляет имена параметров в макете с именами полей в объекте (в данном случае — в выборке).
Разберем по шагам, как это упрощает работу:
ТЧ.Ссылка.Контрагент КАК Контрагент).
Если Выборка.Следующий() Тогда
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
// Автоматически заполнит Номер, Организацию, Контрагента, если имена совпали
ОбластьШапка.Параметры.Заполнить(Выборка);
ТабДок.Вывести(ОбластьШапка);
КонецЕсли;
Это не только сокращает объем текста в модуле, но и работает производительнее на стороне сервера 1С.
Если печатная форма сложная, лучше всего использовать структуру запроса с итогами или группировками. Проанализируем ситуацию, когда данные шапки выносятся в отдельную группировку. Это позволяет избежать использования метода Сбросить().
Пример построения кода с обходом по группировкам:
// В запросе добавляем ИТОГИ ПО Ссылка
РезультатЗапроса = Запрос.Выполнить();
ВыборкаПоДокументам = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаПоДокументам.Следующий() Цикл
// Заполняем шапку из данных группировки
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.Заполнить(ВыборкаПоДокументам);
ТабДок.Вывести(ОбластьШапка);
// Получаем вложенную выборку по детальным записям (строкам ТЧ)
ВыборкаСтроки = ВыборкаПоДокументам.Выбрать();
Пока ВыборкаСтроки.Следующий() Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Заполнить(ВыборкаСтроки);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
КонецЦикла;
Такой подход считается наиболее правильным в архитектуре 1С, так как он логически разделяет данные заголовка документа и его содержимого.
Чтобы ваша печатная форма выглядела профессионально и корректно работала у пользователя, обратите внимание на следующие моменты:
РезультатЗапроса.Пустой(). Если данных нет, лучше вывести предупреждение Сообщить("Нет данных для печати"), чем показывать пустой лист.ЧислоПрописью(). Помните, что её лучше вызывать в самом конце формирования отчета, когда все итоги уже посчитаны.ТабДок.АвтоМасштаб = Истина.ТабДок.ТолькоПросмотр = Истина.Подведем итог: главная причина отсутствия данных в шапке — попытка чтения из объекта ВыборкаИзРезультатаЗапроса без предварительного вызова Следующий(). Используйте либо метод Сбросить() для повторного обхода, либо структуру запроса с группировками для более чистого и эффективного кода.