Как реализовать вывод графика платежей по месяцам в виде шахматки из регистра сведений?

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

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

Архитектурные ошибки при использовании табличной части справочника

Рассмотрим типичную ошибку: создание в справочнике табличной части с жестким набором колонок Месяц1, Месяц2, ..., Месяц12 и программное заполнение строк при проведении документов оплаты.

Проанализируем ключевые риски и ограничения такого подхода:

  1. Жесткая структура метаданных. В режиме «1С:Предприятие» невозможно динамически изменять реквизиты табличной части объекта метаданных. Если договор заключается более чем на год или график платежей смещается на следующий календарный период, жестко заданные колонки перестанут удовлетворять требованиям.
  2. Транзакционные блокировки. Если документ оплаты при проведении пытается записать данные в табличную часть договора, возникнут взаимоблокировки при параллельной работе пользователей. Справочник предназначен для условно-постоянной информации, а не для оперативных движений.
  3. Падение производительности. Платформа 1С при считывании ссылки на справочник загружает в оперативную память все его табличные части. Раздувание табличной части справочника приведет к замедлению работы интерфейса и выборок данных.
  4. Ошибки в запросах при обращении через точку. В исходном коде запроса условие вида УчетОплаты.Договор.Ссылка = &ДСсылка порождает неявное левое соединение (LEFT JOIN) с таблицей справочника договоров. Для корректной оптимизации запроса следует обращаться напрямую к ссылочному измерению: УчетОплаты.Договор = &ДСсылка.

Вариант 1. Обращение к колонкам по имени и генерация строк

Если табличная часть с предопределенным числом месяцев уже существует и требуется заполнить ее строками со смещением, разберем программный способ адресации полей без громоздких конструкций Если ... Тогда.

Вместо перебора условий используем индексацию через квадратные скобки по строковому имени колонки и встроенную функцию ДобавитьМесяц:


&НаСервере
Процедура ЗаполнитьГрафикНаСервере()

	Объект.ГрафикПлатежей.Очистить();
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	УчетОплаты.ДатаОплаты КАК ДатаОплаты,
		|	УчетОплаты.МесяцОплаты КАК МесяцОплаты
		|ИЗ
		|	РегистрСведений.УчетОплаты КАК УчетОплаты
		|ГДЕ
		|	УчетОплаты.Договор = &ДСсылка";
		
	Запрос.УстановитьПараметр("ДСсылка", Объект.Ссылка);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Пока Выборка.Следующий() Цикл
		// Если оплата покрывает несколько месяцев, создаем соответствующие строки
		Для Смещение = 1 По Выборка.МесяцОплаты Цикл
			НоваяСтрока = Объект.ГрафикПлатежей.Добавить();
			НоваяСтрока.ДатаОплаты = ДобавитьМесяц(Выборка.ДатаОплаты, Смещение - 1);
			
			// Формируем имя колонки динамически и присваиваем значение
			ИмяКолонки = "Месяц" + Формат(Смещение, "ЧГ=");
			НоваяСтрока[ИмяКолонки] = Выборка.МесяцОплаты;
		КонецЦикла;
	КонецЦикла;

КонецПроцедуры

Вариант 2. Динамическое создание колонок на форме (Таблица значений)

Наиболее грамотный способ с точки зрения платформы — не хранить данные в метаданных справочника, а динамически формировать таблицу в памяти формы при ее открытии. Для этого используется реквизит формы с типом ТаблицаЗначений, метод ИзменитьРеквизиты() и добавление элементов управления.

Посмотрим на пример создания колонок на клиенте и сервере:


&НаСервере
Процедура СформироватьДинамическуюТаблицуНаСервере(КоличествоМесяцев)

	// Создаем массив добавляемых реквизитов формы
	ДобавляемыеРеквизиты = Новый Массив;
	
	Для НомерКолонки = 1 По КоличествоМесяцев Цикл
		ИмяКолонки = "Месяц_" + Формат(НомерКолонки, "ЧГ=");
		ТипРеквизита = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2));
		
		Реквизит = Новый РеквизитФормы(ИмяКолонки, ТипРеквизита, "ТаблицаОплатНаФорме", "Месяц " + НомерКолонки);
		ДобавляемыеРеквизиты.Добавить(Реквизит);
	КонецЦикла;
	
	ИзменитьРеквизиты(ДобавляемыеРеквизиты);
	
	// Создаем элементы интерфейса
	Для Каждого Реквизит Из ДобавляемыеРеквизиты Цикл
		ЭлементКолонка = Элементы.Добавить(Реквизит.Имя, Тип("ПолеФормы"), Элементы.ТаблицаОплатНаФорме);
		ЭлементКолонка.Вид = ВидПоляФормы.ПолеВвода;
		ЭлементКолонка.ПутьКДанным = "ТаблицаОплатНаФорме." + Реквизит.Имя;
	КонецЦикла;

КонецПроцедуры

Вариант 3. Использование отчета на СКД или Поля табличного документа

Когда шахматка требуется только для аналитики и просмотра, оптимальным решением является вывод отчета на базе Системы компоновки данных (СКД) прямо на форму элемента справочника или использование элемента управления Поле табличного документа.

Разберем преимущества этого способа:

  1. Настоящая кросс-таблица. В схеме компоновки данных можно задать группировку строк по датам или договорам, а группировку колонок — по периодам (месяцам). Платформа автоматически сформирует горизонтальные секции без необходимости писать программный код для добавления колонок.
  2. Отсутствие блокировок. Отчет считывает данные напрямую из регистра сведений УчетОплаты в момент открытия или по требованию пользователя, не затрагивая данные самого договора.
  3. Гибкость настройки. Пользователь может самостоятельно изменять состав полей, включать отборы и менять оформление таблицы.

Таким образом, для реализации матричных структур следует разделять хранение данных (регистры сведений) и их визуальное представление (динамические таблицы формы или отчеты СКД), избегая принудительного расширения табличных частей объектов нормативно-справочной информации.

← На главную