Как вывести номера колонок в отчете СКД без использования макетов?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с требованием заказчика вывести под шапкой таблицы строку с порядковыми номерами колонок (1, 2, 3 и так далее). Такое оформление стандартно для многих регламентированных и статистических форм. Первая реакция разработчика — нарисовать собственный макет шапки на вкладке «Макеты» в схеме компоновки. Однако этот путь имеет огромный минус: отчет теряет гибкость. Если пользователь решит скрыть часть колонок, поменять их местами или добавить новые пользовательские поля, жестко заданный макет либо «сломается», либо отобразит некорректные данные.

В этой статье мы подробно разберем, как элегантно решить задачу автоматической нумерации колонок в СКД, сохранив полную интерактивность и настраиваемость отчета. Мы изучим три способа: современный архитектурный подход для управляемого приложения, классический метод для обычных форм и декларативный метод средствами самой СКД.

Почему стандартные макеты оформления СКД не подходят?

Когда мы создаем фиксированный макет для заголовков столбцов, платформа 1С привязывает вывод полей к конкретным ячейкам макета. В результате:

  1. Теряется возможность динамического изменения состава колонок пользователем через «Изменить вариант».
  2. Пропадает корректный расчет ширины колонок в зависимости от выводимых данных.
  3. Механизм автовыравнивания и группировки колонок начинает работать непредсказуемо.

Для сохранения всех преимуществ динамической компоновки нам необходимо позволить СКД сформировать отчет в стандартном режиме, а затем скорректировать результат.

---

Способ 1. Современный подход: Постобработка в модуле объекта (Управляемые формы)

В управляемом приложении привязывать логику формирования отчета к модулю формы (как предлагалось в некоторых сообщениях на форуме) считается плохой практикой. Если отчет будет вызван программно — например, в фоновом задании, при рассылке отчетов или через API — код формы просто не выполнится. Правильным архитектурным решением является перенос логики в Модуль объекта отчета, в предопределенный обработчик ПриКомпоновкеРезультата. Для изучения других практических приёмов разработки полезно использовать сборник примеров программной работы с СКД и управляемыми формами.

Рассмотрим этот метод подробнее. Нам не нужно вручную воссоздавать шрифты и цвета границ для новой строки. Метод табличного документа ВставитьОбласть при копировании строки шапки автоматически перенесет все оформление (цвета, рамки, шрифты) согласно выбранному пользователем макету оформления отчета.

Откроем модуль объекта нашего отчета и пропишем следующий код:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
	
	// Отключаем стандартный вывод, так как будем выводить отчет программно
	СтандартнаяОбработка = Ложь;
	
	// Инициализируем компоновщик макета и формируем макет компоновки
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
	
	// Инициализируем процессор компоновки данных
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
	
	// Выводим результат в табличный документ
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
	// Начало постобработки табличного документа
	// Определяем высоту шапки по свойству ФиксацияСверху
	КоличествоСтрокШапки = ДокументРезультат.ФиксацияСверху;
	
	// Если фиксация не задана программно или в настройках, попытаемся определить ее автоматически
	Если КоличествоСтрокШапки = 0 Тогда
		// В простейших отчетах шапка обычно занимает первые строки. 
		// Если структура сложная, рекомендуется явно настроить фиксацию шапки в СКД.
		Возврат; 
	КонецЕсли;
	
	КоличествоКолонок = ДокументРезультат.ШиринаТаблицы;
	
	// Выделяем область последней строки шапки для копирования её стиля
	ИсходнаяОбласть = ДокументРезультат.Область(КоличествоСтрокШапки, , КоличествоСтрокШапки);
	
	// Выделяем область под шапкой, куда будет вставлена строка нумерации
	ОбластьПриемник = ДокументРезультат.Область(КоличествоСтрокШапки + 1, , КоличествоСтрокШапки + 1);
	
	// Вставляем строку. Она унаследует высоту, шрифты, границы и фоновые цвета шапки
	ДокументРезультат.ВставитьОбласть(ИсходнаяОбласть, ОбластьПриемник, ТипСмещенияТабличногоДокумента.ПоВертикали, Ложь);
	
	// Заполняем вставленную строку номерами колонок по порядку
	Для НомерКолонки = 1 По КоличествоКолонок Цикл
		
		ЯчейкаНомера = ДокументРезультат.Область(КоличествоСтрокШапки + 1, НомерКолонки);
		ЯчейкаНомера.Текст = Строка(НомерКолонки);
		
		// Центрируем текст по горизонтали и вертикали для красивого отображения
		ЯчейкаНомера.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
		ЯчейкаНомера.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
		
	КонецЦикла;
	
	// Корректируем фиксацию строк на одну строку вниз, чтобы строка с номерами тоже закреплялась при прокрутке
	ДокументРезультат.ФиксацияСверху = КоличествоСтрокШапки + 1;
	
КонецПроцедуры

Важное примечание: Чтобы этот алгоритм отработал корректно, в настройках СКД (вкладка «Другие настройки») должно быть включено свойство «Фиксация сверху» в значение Кнопка или Авто, либо оно должно определяться структурой отчета. Именно по значению свойства ФиксацияСверху наш алгоритм безошибочно находит границу, где заканчивается шапка и начинаются данные.

---

Способ 2. Классический подход через анализ Макета Оформления (для обычных форм)

Если вы работаете в старых конфигурациях на обычных формах (например, УПП 1.3 или КА 1.1) и вывод инициируется нажатием кнопки на форме, вы можете использовать детальный разбор макета оформления. Этот метод позволяет явно вытащить параметры оформления (шрифт, цвет фона, цвет границ) текущего стиля отчета и применить их к ячейкам.

Разберем пример кода, который вешается на обработчик события кнопки ДействияФормыСформировать в модуле формы отчета:


Процедура ДействияФормыСформировать(Кнопка)
	
	// Очищаем результирующий табличный документ на форме
	ТабДокумент = ЭлементыФормы.Результат;
	ТабДокумент.Очистить();
	
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, ДанныеРасшифровки);
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ТабДокумент);
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
	// Анализируем примененный макет оформления для точной настройки цветов и шрифтов
	МакетОформления = Новый МакетОформленияКомпоновкиДанных;
	ПараметрМакетаОформления = КомпоновщикНастроек.Настройки.ПараметрыВывода.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("МакетОформления"));
	
	Если ПараметрМакетаОформления.Использование Тогда
		МакетОформления = БиблиотекаМакетовОформленияКомпоновкиДанных[ПараметрМакетаОформления.Значение].ПолучитьМакет();
	Иначе
		МакетОформления = БиблиотекаМакетовОформленияКомпоновкиДанных["Основной"].ПолучитьМакет();
	КонецЕсли;
	
	// Получаем параметры стиля для заголовка таблицы
	ОформлениеЗаголовкаТаблицы = МакетОформления.Элементы.Найти("ЗаголовокТаблицы").Значение;
	
	Если ОформлениеЗаголовкаТаблицы = Неопределено Тогда
		// Если стиль не определен (например, макет "Без оформления") - задаем стандартный вид
		ЦветФона = Новый Цвет(255, 255, 255);
		ЦветРамки = Новый Цвет(0, 0, 0);
		ЦветТекста = Новый Цвет(0, 0, 0);
		Шрифт = Новый Шрифт("Arial", 10, Ложь, Ложь, Ложь, Ложь);
		Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, 1);
	Иначе
		ЦветФона = ОформлениеЗаголовкаТаблицы[0].Оформление.Элементы.Найти("ЦветФона").Значение;
		ЦветРамки = ОформлениеЗаголовкаТаблицы[0].Оформление.Элементы.Найти("ЦветГраницы").Значение;
		ЦветТекста = ОформлениеЗаголовкаТаблицы[0].Оформление.Элементы.Найти("ЦветТекста").Значение;
		Шрифт = ОформлениеЗаголовкаТаблицы[0].Оформление.Элементы.Найти("Шрифт").Значение;
		Линия = ОформлениеЗаголовкаТаблицы[0].Оформление.Элементы.Найти("СтильГраницы").Значение;
	КонецЕсли;
	
	// Добавляем строку нумерации колонок
	КоличествоСтрокШапки = ТабДокумент.ФиксацияСверху;
	КоличествоКолонок = ТабДокумент.ШиринаТаблицы;
	
	Если КоличествоСтрокШапки > 0 Тогда
		
		ИсходнаяОбласть = ТабДокумент.Область(КоличествоСтрокШапки, , КоличествоСтрокШапки);
		ОбластьПриемник = ТабДокумент.Область(КоличествоСтрокШапки + 1, , КоличествоСтрокШапки + 1);
		ТабДокумент.ВставитьОбласть(ИсходнаяОбласть, ОбластьПриемник, ТипСмещенияТабличногоДокумента.ПоВертикали, Ложь);
		
		Для Ном = 1 По КоличествоКолонок Цикл
			
			ТекОбласть = ТабДокумент.Область(КоличествоСтрокШапки + 1, Ном);
			ТекОбласть.Шрифт = Шрифт;
			ТекОбласть.Текст = "" + Ном;
			ТекОбласть.ЦветФона = ЦветФона;
			ТекОбласть.ЦветТекста = ЦветТекста;
			ТекОбласть.ЦветРамки = ЦветРамки;
			ТекОбласть.Обвести(Линия, Линия, Линия, Линия);
			ТекОбласть.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
			ТекОбласть.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
			
		КонецЦикла;
		
		ТабДокумент.ФиксацияСверху = КоличествоСтрокШапки + 1;
		
	КонецЕсли;
	
КонецПроцедуры

Этот способ гарантирует, что даже при ручной отрисовке рамки ячеек не «слетят», а шрифт номеров будет точно соответствовать шрифту заголовков отчета.

---

Способ 3. Декларативный метод средствами СКД без кода

Мало кто знает, но пронумеровать колонки можно непосредственно внутри схемы компоновки данных без написания кода постобработки табличного документа. Для этого используется системное поле или вычисляемое поле с функцией НомерПоПорядкуВГруппировке().

Проанализируем шаги настройки этого механизма:

  1. Перейдем на вкладку «Вычисляемые поля» нашей СКД.
  2. Добавим новое вычисляемое поле с именем НомерКолонки. В качестве выражения укажем функцию СистемныеПоля.НомерПоПорядкуВГруппировке.
  3. На вкладке «Ресурсы» добавим это поле как ресурс. Рассчитывать его нужно по группировкам колонок нашей таблицы, указав выражение Максимум(НомерКолонки).
  4. В настройках структуры отчета (вкладка «Настройки») найдем настройки нашей таблицы. В область колонок добавим вывод нашего ресурса НомерКолонки непосредственно под основными группировками колонок.

Важная тонкость: Иногда при использовании системных полей в иерархических группировках СКД выводит начальный индекс (например, 0 или пустую ячейку). Эту проблему легко решить с помощью вкладки «Условное оформление» в СКД:

Этот метод хорош тем, что выполняется полностью декларативно в рамках стандартных возможностей СКД, сохраняя работоспособность отчета на любых клиентах без модификации общего программного кода. Для решения других аналогичных задач настройки колонок исключительно штатными средствами платформы можно использовать методику вывода ресурса в СКД только в одной колонке.

---

Резюме и рекомендации

Мы рассмотрели три эффективных метода решения задачи. Подведем краткие итоги, какой метод выбрать для вашего проекта:

← На главную