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