В процессе разработки в 1С часто возникает задача объединения данных из нескольких таблиц значений в одну сводную таблицу. Трудности начинаются тогда, когда системные имена колонок в исходных таблицах совпадают (например, Колонка1, Колонка2), но смысловые заголовки колонок различаются (например, «Количество» и «Процент %»), при этом заголовки содержат пробелы или специальные знаки. Разберем особенности платформы 1С и пошаговые способы решения этой задачи.
Прежде чем приступать к объединению, проанализируем ограничения платформы 1С:
Имя: Системный идентификатор колонки обязан соответствовать правилам именования переменных 1С: начинаться с буквы или подчеркивания и не содержать пробелов, дефисов, знаков % и прочих спецсимволов. В то же время свойство Заголовок может содержать произвольную строку.ЗаполнитьЗначенияСвойств: Копирует данные только по совпадению свойства Имя. Сопоставлять ячейки по пользовательским заголовкам штатный метод не умеет.ОБЪЕДИНИТЬ ВСЕ в запросе, у всех колонок должно быть строго задано ОписаниеТипов, а псевдонимы полей также не могут содержать пробелы и знаки процента.Рассмотрим основной и наиболее универсальный подход: создание новой таблицы значений, динамическое формирование валидных системных имен колонок и перенос строк циклом.
Разберем алгоритм по шагам:
Соответствие, где ключом будет уникальный заголовок колонки, а значением — сгенерированное системное имя в новой таблице.Колонка_1, Колонка_2) и добавляем колонку в результирующую таблицу с сохранением типов и исходного заголовка.Посмотрим на пример программной реализации:
// Создаем результирующую таблицу и структуру соответствия
ТЗ_Результат = Новый ТаблицаЗначений;
КартаКолонок = Новый Соответствие; // Ключ: Заголовок, Значение: ИмяКолонкиВРезультате
СчетчикКолонок = 0;
МассивИсходныхТЗ = Новый Массив;
МассивИсходныхТЗ.Добавить(ТаблицаЗначений1);
МассивИсходныхТЗ.Добавить(ТаблицаЗначений2);
// Шаг 1. Формируем структуру колонок результирующей таблицы
Для Каждого ТЗ_Источник Из МассивИсходныхТЗ Цикл
Для Каждого КолонкаИсточника Из ТЗ_Источник.Колонки Цикл
// Если заголовок не задан, используем имя
ТекстЗаголовка = КолонкаИсточника.Заголовок;
Если ПустаяСтрока(ТекстЗаголовка) Тогда
ТекстЗаголовка = КолонкаИсточника.Имя;
КонецЕсли;
// Проверяем, добавляли ли мы уже колонку с таким заголовком
Если КартаКолонок[ТекстЗаголовка] = Неопределено Тогда
СчетчикКолонок = СчетчикКолонок + 1;
ИмяНовойКолонки = "Колонка_" + Формат(СчетчикКолонок, "ЧГ=0");
ТЗ_Результат.Колонки.Добавить(
ИмяНовойКолонки,
КолонкаИсточника.ТипЗначения,
ТекстЗаголовка
);
КартаКолонок.Вставить(ТекстЗаголовка, ИмяНовойКолонки);
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Шаг 2. Построчно переносим данные в результирующую таблицу
Для Каждого ТЗ_Источник Из МассивИсходныхТЗ Цикл
Для Каждого СтрИсточник Из ТЗ_Источник Цикл
НоваяСтрока = ТЗ_Результат.Добавить();
Для Каждого КолонкаИсточника Из ТЗ_Источник.Колонки Цикл
ТекстЗаголовка = КолонкаИсточника.Заголовок;
Если ПустаяСтрока(ТекстЗаголовка) Тогда
ТекстЗаголовка = КолонкаИсточника.Имя;
КонецЕсли;
ИмяКолонкиПриемника = КартаКолонок[ТекстЗаголовка];
НоваяСтрока[ИмяКолонкиПриемника] = СтрИсточник[КолонкаИсточника.Имя];
КонецЦикла;
КонецЦикла;
КонецЦикла;
Рассмотрим альтернативный вариант, когда заголовки в таблицах гарантированно уникальны для каждого источника и требуется объединить таблицы без создания сложных карт соответствия.
В платформе 1С свойство Имя объекта КолонкаТаблицыЗначений доступно не только для чтения, но и для записи. Это позволяет переименовать конфликтующие колонки прямо в исходных таблицах, добавив к ним уникальный префикс, при этом свойство Заголовок останется неизменным.
Разберем по шагам реализацию этого способа:
Т1_.Т2_.Посмотрим на пример кода:
// Переименовываем колонки первой таблицы
Для Каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
Колонка.Имя = "Т1_" + Колонка.Имя;
КонецЦикла;
// Переименовываем колонки второй таблицы
Для Каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
Колонка.Имя = "Т2_" + Колонка.Имя;
КонецЦикла;
// Добавляем структуру колонок из второй таблицы в первую
Для Каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
ТаблицаЗначений1.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения, Колонка.Заголовок);
КонецЦикла;
// Переносим строки из второй таблицы в первую
Для Каждого Стр2 Из ТаблицаЗначений2 Цикл
НоваяСтрока = ТаблицаЗначений1.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Стр2);
КонецЦикла;
Важный момент: Первый способ является более универсальным, так как он автоматически объединяет в одну колонку поля с одинаковыми заголовками из разных таблиц и исключает возникновение ошибок из-за некорректных символов в системных идентификаторах.