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