Полезные процедуры по работе с СКД и табличными документами
05.09.16 14:41

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

1. Объединение, скрытие, замена

Пусть требуется получить отчет следующего вида


Этот отчет имеет несколько особенностей:
- Объединенные ячейки в шапке
 - Количество и состав колонок в группе “Бонусы” - динамические. Выводятся только, если заполнено хотя бы для одного сотрудника в отчете. Если, например, никто из попавших в отчет сотрудников не получил надбавку за сверхурочные, то этой колонки в отчете быть не должно. Проектов в группе “за проекты” может быть неограниченное количество.
- Дополнительные требования к порядку полей: колонка “Оклад” должна выводиться первой, “Всего по сотруднику” - последней

В консоли можно получить следующий результат


Далее приведены универсальные процедуры, с помощью которых можно:
1. Объединить ячейки “Бонусы” и “За проекты” в шапке отчета с помощью процедуры ОбъединтьЯчейкиВТабличномДокументе()
2. Скрыть заголовок ресурса “Сумма” с помощью процедуры СкрытьСтрокиВТабличномДокументе()


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

	СтандартнаяОбработка = Ложь;

	ВывестиСКДВТабличныйДокумент(СхемаКомпоновкиДанных, ДокументРезультат, КомпоновщикНастроек);

	Маркер = "Бонусы";
	ОбъединтьЯчейкиВТабличномДокументе(ДокументРезультат, Маркер);

	Маркер = "За проекты";
	ОбъединтьЯчейкиВТабличномДокументе(ДокументРезультат, Маркер);

	Маркер = "Сумма";
	СкрытьСтрокиВТабличномДокументе(ДокументРезультат, Маркер);

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

Процедура ОбъединтьЯчейкиВТабличномДокументе(ТабличныйДокумент, МаркерОбъединения) Экспорт
	// Находит ячейки, содержащие в тексте МаркерОбъединения
	// Объединяет ячейки, располагающиеся рядом, содержащие одинаковый текст и маркер объединения 
	
	ОбъединяемыеЯчейки = НайтиОбластиТабличногоДокументаПоВхождениюПодстроки(ТабличныйДокумент, МаркерОбъединения);
	ОбъединяемыеЯчейки.Колонки.Добавить("Диапазон");
	ОбъединяемыеЯчейки.Сортировать("Верх,Лево");
	
	Для Каждого Строка из ОбъединяемыеЯчейки Цикл
		Отбор = Новый Структура("Текст,Верх,Лево", Строка.Текст, Строка.Верх-1, Строка.Лево);
		НайденныеСтроки = ОбъединяемыеЯчейки.НайтиСтроки(Отбор);
		Если НайденныеСтроки.Количество() Тогда
			Строка.Диапазон = НайденныеСтроки[0].Диапазон;
			Строка.Диапазон.Низ = Макс(Строка.Диапазон.Низ, Строка.Верх);
			Продолжить;
		КонецЕсли;
		
		Отбор = Новый Структура("Текст,Верх,Лево", Строка.Текст, Строка.Верх, Строка.Лево-1);
		НайденныеСтроки = ОбъединяемыеЯчейки.НайтиСтроки(Отбор);
		Если НайденныеСтроки.Количество() Тогда
			Строка.Диапазон = НайденныеСтроки[0].Диапазон;
			Строка.Диапазон.Право = Макс(Строка.Диапазон.Право, Строка.Лево);
			Продолжить;
		КонецЕсли;
		
		Строка.Диапазон = Новый Структура("Текст,Верх,Лево,Низ,Право", Строка.Текст, Строка.Верх, Строка.Лево, Строка.Верх, Строка.Лево);
	КонецЦикла;
	
	ОбъединяемыеЯчейки.Свернуть("Диапазон");
	Для Каждого Строка Из ОбъединяемыеЯчейки Цикл
		Диапазон = Строка.Диапазон;
		Область = ТабличныйДокумент.Область(Диапазон.Верх, Диапазон.Лево, Диапазон.Низ, Диапазон.Право);
		Область.Объединить();
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗаменитьТекстВТабличномДокументе(ТабличныйДокумент, ПодстрокаПоиска, ПодстрокаЗамены) Экспорт
	
	НайденныеОбласти = НайтиОбластиТабличногоДокументаПоВхождениюПодстроки(ТабличныйДокумент, ПодстрокаПоиска);
	Для каждого Строка из НайденныеОбласти Цикл
		Строка.Область.Текст = СтрЗаменить(Строка.Область.Текст, ПодстрокаПоиска, ПодстрокаЗамены);
	КонецЦикла;
	
КонецПроцедуры

Процедура СкрытьСтрокиВТабличномДокументе(ТабличныйДокумент, МаркерУдаления) Экспорт
	
	НайденныеОбласти = НайтиОбластиТабличногоДокументаПоВхождениюПодстроки(ТабличныйДокумент, МаркерУдаления);
	НайденныеОбласти.Свернуть("Верх");
	
	Для каждого Строка из НайденныеОбласти Цикл
		Область = ТабличныйДокумент.Область(Строка.Верх, , Строка.Верх, );
		Область.Видимость = Ложь;
	КонецЦикла;
	
КонецПроцедуры

Функция НайтиОбластиТабличногоДокументаПоВхождениюПодстроки(ТабличныйДокумент, ПодстрокаПоиска) Экспорт
	
	НайденныеОбласти = Новый ТаблицаЗначений;
	НайденныеОбласти.Колонки.Добавить("Область");
	НайденныеОбласти.Колонки.Добавить("Текст");
	НайденныеОбласти.Колонки.Добавить("Верх");
	НайденныеОбласти.Колонки.Добавить("Лево");
	
	НайденнаяОбласть = ТабличныйДокумент.НайтиТекст(ПодстрокаПоиска);
	
	Пока НЕ НайденнаяОбласть = Неопределено Цикл
		
		НоваяСтрока = НайденныеОбласти.Добавить();
		ЗаполнитьЗначенияСвойств(НоваяСтрока, НайденнаяОбласть);
		НоваяСтрока.Область = НайденнаяОбласть;
		
		НайденнаяОбласть = ТабличныйДокумент.НайтиТекст(ПодстрокаПоиска, НайденнаяОбласть);
		
	КонецЦикла;
	
	Возврат НайденныеОбласти;
	
КонецФункции

2. Процедуры по выводу табличного документа

Эти процедуры можно найти в различных интерпретациях на множестве сайтов. Здесь выкладываю те, которые использую я


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

Функция ПолучитьТаблицуЗначенийИзСКД(МакетСКД, КомпоновщикНастроек) Экспорт
	
	Результат = Новый ТаблицаЗначений;
	
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();  
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	
	МакетКомпоновки = КомпоновщикМакета.Выполнить(МакетСКД, Настройки,,,
				Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
	
	ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
	
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
	ПроцессорВывода.УстановитьОбъект(Результат);
	
	ПроцессорВывода.Вывести(ПроцессорКомпоновки);
	
	Возврат Результат;
	
КонецФункции

3. Вывод рядом двух независимых таблиц

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


Функция ПрисоединитьТабличныйДокументКТабличномуДокументу(ТабличныйДокументОсновной, ТабличныйДокументПрисоединяемый)
	// идея взята с форума: http://forum.infostart.ru/forum86/topic157420/message1610993/#message1610993
	ТабличныйДокументОбъединенный = Новый ТабличныйДокумент;
	
	Область = ТабличныйДокументОсновной.ПолучитьОбласть(1,1, ТабличныйДокументОсновной.ВысотаТаблицы, ТабличныйДокументОсновной.ШиринаТаблицы);
	
	ТабличныйДокументОбъединенный.Вывести(Область);
	ТабличныйДокументОбъединенный.Присоединить(ТабличныйДокументПрисоединяемый);
	
	Возврат ТабличныйДокументОбъединенный;
КонецФункции

4. Установка собственного формата для табличного документа

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


Процедура ЗадатьФорматСтрокВТабличномДокументе(пТабличныйДокумент)
	// задает индивидуальный формат строк для табличного документа, сохраняя ширину колонок при выводе его в другой табличный документ
	
	пТабличныйДокумент.Область(1,,пТабличныйДокумент.ВысотаТаблицы).СоздатьФорматСтрок();
	
КонецПроцедуры

К статье прилагается внешняй отчет со сводным примером (запускается в любой конфигурации 8.2/8.3 на обычных или управляемых формах)

Read Full Article