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