Как загрузить данные из кросс-таблицы Excel в 1С и отобразить их на управляемой форме?

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

При автоматизации складского учета или заказов часто возникает ситуация, когда внешний файл Excel имеет «горизонтальную» структуру: в строках указаны товары, а в колонках — магазины или контрагенты, и на пересечении стоит количество. Такая структура удобна для человека, но неудобна для загрузки в типовые документы 1С, где контрагент обычно является реквизитом шапки, а товары — строками табличной части. В этой статье мы разберем, как правильно организовать чтение таких данных, нормализовать их и вывести на управляемую форму 1С 8.3.

Проблема: Кросс-таблица и интерфейс управляемых форм

Рассмотрим исходную задачу: файл содержит около 100 товаров и 50 магазинов. Если пытаться загрузить данные «как есть», создав табличную часть с 50 колонками, мы столкнемся с жестким ограничением метаданных — колонки в табличных частях объектов (документов, справочников) нельзя создавать «на лету» в режиме 1С:Предприятие. Более того, работа с ТаблицейЗначений на управляемых формах существенно отличается от старых «обычных» форм (v8.2), где использовался элемент Табличное поле с методом СоздатьКолонки().

Способ 1. Загрузка данных через COM-объект

Проанализируем классический способ чтения Excel с использованием COM-соединения. Этот метод позволяет напрямую обращаться к ячейкам листа и выгружать их в массивы 1С. Рассмотрим пример кода для получения данных в ТаблицуЗначений:


// Создаем подключение к Excel
Попытка
    Excel = Новый COMОбъект("Excel.Application");
    Книга = Excel.Workbooks.Open(ПутьКФайлу);
    ТекЛист = Книга.Worksheets(1);
Исключение
    Сообщить("Ошибка при открытии Excel: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

КолСтрок = ТекЛист.UsedRange.Rows.Count;
КолСтолбцов = ТекЛист.UsedRange.Columns.Count;

// Получаем данные одним массивом для ускорения
СомОбластьДанных = ТекЛист.Range(ТекЛист.Cells(1,1), ТекЛист.Cells(КолСтрок, КолСтолбцов));
Данные = СомОбластьДанных.Value.Выгрузить();

// Формируем ТаблицуЗначений
ТЗ = Новый ТаблицаЗначений;
Для Сч = 0 По КолСтолбцов - 1 Цикл
    ТЗ.Колонки.Добавить("Колонка" + Сч);
КонецЦикла;

Для Сч = 1 По КолСтрок Цикл
    ТЗ.Добавить();
КонецЦикла;

Для Сч = 0 По КолСтолбцов - 1 Цикл
    ТЗ.ЗагрузитьКолонку(Данные[Сч], "Колонка" + Сч);
КонецЦикла;

Excel.Quit();

Важный нюанс: метод Value.Выгрузить() работает значительно быстрее, чем перебор каждой ячейки в цикле Cells(x, y).Value. Однако помните, что COM-объект требует установленного Microsoft Excel на компьютере, где выполняется код (обычно на клиенте), и может работать медленно при больших объемах данных.

Способ 2. Нормализация данных (Рекомендуемый подход)

Вместо того чтобы мучиться с отображением 50 колонок магазинов на форме, проанализируем ситуацию с точки зрения архитектуры 1С. Для создания документов нам нужна «плоская» структура. Выясним причину, почему это лучше: плоскую таблицу проще сортировать, группировать и искать в ней расхождения.

Рассмотрим алгоритм трансформации:

  1. Читаем Excel во временную ТаблицуЗначений.
  2. Создаем целевую ТаблицуЗначений с тремя колонками: Магазин, Товар, Количество.
  3. В цикле обходим временную таблицу: внешний цикл по строкам (товары), внутренний — по колонкам (начиная с колонки магазина).
  4. Если в ячейке на пересечении стоит количество > 0, добавляем строку в целевую ТЗ.

Посмотрим на пример трансформации:


ТЗ_Результат = Новый ТаблицаЗначений;
ТЗ_Результат.Колонки.Добавить("Магазин");
ТЗ_Результат.Колонки.Добавить("Товар");
ТЗ_Результат.Колонки.Добавить("Количество");

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

Теперь у вас есть готовый набор данных для создания 50 документов (по одному на каждый уникальный магазин) простым перебором с группировкой.

Как вывести динамическую таблицу на Управляемую форму?

Если бизнес-задача все же требует показать пользователю таблицу именно в том виде, в котором она была в Excel (с магазинами в колонках), нам придется программно изменять состав реквизитов формы. В управляемом интерфейсе 1С 8.3 для этого используется метод ИзменитьРеквизиты().

Разберем по шагам процесс вывода динамической ТаблицыЗначений:

  1. Удаление старых колонок: Перед созданием новых нужно программно удалить элементы формы и реквизиты, созданные при предыдущей загрузке.
  2. Создание реквизитов: Формируем массив объектов РеквизитФормы.
  3. Добавление на форму: Используем ЭтаФорма.ИзменитьРеквизиты(МассивДобавляемыхРеквизитов).
  4. Создание элементов интерфейса: Для каждого нового реквизита создаем элемент формы типа ПолеФормы.

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


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

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

Альтернатива: Чтение через Табличный Документ

Рассмотрим более современный и быстрый способ чтения Excel без использования COM. Платформа 1С позволяет загрузить файл напрямую в ТабличныйДокумент. Это работает стабильнее на стороне сервера.


ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);

// Далее работаем с ТабДок как с матрицей
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;

Для НомСтроки = 2 По ВсегоСтрок Цикл
    ТоварНаименование = ТабДок.Область(НомСтроки, 1).Текст;
    // ... логика обработки
КонецЦикла;

Резюме и рекомендации

Проанализировав ситуацию, можно сделать следующие выводы:

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

← На главную