Как объединить таблицы значений с одинаковыми именами колонок, но разными заголовками в 1С?

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

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

Ограничения платформы при работе с колонками таблицы значений

Прежде чем приступать к объединению, проанализируем ограничения платформы 1С:

  1. Требования к свойству Имя: Системный идентификатор колонки обязан соответствовать правилам именования переменных 1С: начинаться с буквы или подчеркивания и не содержать пробелов, дефисов, знаков % и прочих спецсимволов. В то же время свойство Заголовок может содержать произвольную строку.
  2. Метод ЗаполнитьЗначенияСвойств: Копирует данные только по совпадению свойства Имя. Сопоставлять ячейки по пользовательским заголовкам штатный метод не умеет.
  3. Использование запросов: Если объединять таблицы через конструкцию ОБЪЕДИНИТЬ ВСЕ в запросе, у всех колонок должно быть строго задано ОписаниеТипов, а псевдонимы полей также не могут содержать пробелы и знаки процента.

Способ 1. Создание результирующей таблицы с маппингом колонок через Соответствие

Рассмотрим основной и наиболее универсальный подход: создание новой таблицы значений, динамическое формирование валидных системных имен колонок и перенос строк циклом.

Разберем алгоритм по шагам:

  1. Создаем новую результирующую таблицу значений.
  2. Используем объект Соответствие, где ключом будет уникальный заголовок колонки, а значением — сгенерированное системное имя в новой таблице.
  3. Обходим коллекции колонок первой и второй таблиц. Если заголовок встречается впервые, генерируем для него безопасное имя (например, Колонка_1, Колонка_2) и добавляем колонку в результирующую таблицу с сохранением типов и исходного заголовка.
  4. Заполняем результирующую таблицу строками из обеих таблиц, обращаясь к соответствию имен.

Посмотрим на пример программной реализации:


// Создаем результирующую таблицу и структуру соответствия
ТЗ_Результат = Новый ТаблицаЗначений;
КартаКолонок = Новый Соответствие; // Ключ: Заголовок, Значение: ИмяКолонкиВРезультате
СчетчикКолонок = 0;

МассивИсходныхТЗ = Новый Массив;
МассивИсходныхТЗ.Добавить(ТаблицаЗначений1);
МассивИсходныхТЗ.Добавить(ТаблицаЗначений2);

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

// Шаг 2. Построчно переносим данные в результирующую таблицу
Для Каждого ТЗ_Источник Из МассивИсходныхТЗ Цикл
    Для Каждого СтрИсточник Из ТЗ_Источник Цикл
        НоваяСтрока = ТЗ_Результат.Добавить();
        
        Для Каждого КолонкаИсточника Из ТЗ_Источник.Колонки Цикл
            ТекстЗаголовка = КолонкаИсточника.Заголовок;
            Если ПустаяСтрока(ТекстЗаголовка) Тогда
                ТекстЗаголовка = КолонкаИсточника.Имя;
            КонецЕсли;
            
            ИмяКолонкиПриемника = КартаКолонок[ТекстЗаголовка];
            НоваяСтрока[ИмяКолонкиПриемника] = СтрИсточник[КолонкаИсточника.Имя];
        КонецЦикла;
    КонецЦикла;
КонецЦикла;

Способ 2. Префиксация системных имен исходных таблиц

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

В платформе 1С свойство Имя объекта КолонкаТаблицыЗначений доступно не только для чтения, но и для записи. Это позволяет переименовать конфликтующие колонки прямо в исходных таблицах, добавив к ним уникальный префикс, при этом свойство Заголовок останется неизменным.

Разберем по шагам реализацию этого способа:

  1. Переименовываем колонки в первой таблице, добавляя префикс Т1_.
  2. Переименовываем колонки во второй таблице, добавляя префикс Т2_.
  3. Добавляем в первую таблицу недостающие колонки из второй таблицы.
  4. Дописываем строки из второй таблицы в первую.

Посмотрим на пример кода:


// Переименовываем колонки первой таблицы
Для Каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
    Колонка.Имя = "Т1_" + Колонка.Имя;
КонецЦикла;

// Переименовываем колонки второй таблицы
Для Каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
    Колонка.Имя = "Т2_" + Колонка.Имя;
КонецЦикла;

// Добавляем структуру колонок из второй таблицы в первую
Для Каждого Колонка Из ТаблицаЗначений2.Колонки Цикл
    ТаблицаЗначений1.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения, Колонка.Заголовок);
КонецЦикла;

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

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

← На главную