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