Как загрузить данные из Excel в массив или таблицу значений в 1С 8.3

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

Загрузка данных из внешних файлов Microsoft Excel — одна из самых частых задач, с которыми сталкивается разработчик 1С. Несмотря на кажущуюся простоту, здесь существует множество подводных камней: от проблем с контекстом выполнения (Клиент/Сервер) до производительности и зависимости от установленного ПО. В этой статье мы подробно разберем два основных метода реализации этой задачи, проанализируем ошибки начинающих разработчиков и изучим профессиональный подход к парсингу файлов.

Метод 1. Использование COM-объекта (Microsoft Office)

Этот метод основан на обращении к установленному на компьютере приложению Microsoft Excel через механизм COM. Рассмотрим ситуацию, когда нам нужно выбрать файл на клиенте, передать путь на сервер и прочитать данные из колонок.

Разберем типичную ошибку начинающих: попытку вызвать серверную процедуру без правильной связки с интерфейсом. Чтобы отладчик «заходил» в серверную процедуру, и она вообще выполнялась, необходимо организовать вызов из клиентского обработчика. Проанализируем правильную структуру кода:


&НаКлиенте
Процедура ПолеДляВыбораФайлаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите excel-файл";
    Диалог.Фильтр = "Таблицы (*.xls,*.xlsx)|*.xls;*.xlsx;";
    
    Если Диалог.Выбрать() Тогда
        Объект.ПутьКФайлу = Диалог.ПолноеИмяФайла;
    КонецЕсли;
КонецПроцедуры

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

Теперь рассмотрим саму серверную логику. Часто возникает вопрос: как загрузить не одну колонку, а сразу несколько (например, «Артикул», «Наименование» и «Цена»)? Для этого лучше всего использовать массив структур. Структура позволяет обращаться к данным по именам, что делает код читаемым.


&НаСервере
Процедура ЗагрузитьДанныеНаСервере(ПутьКФайлу)
    Если ПустаяСтрока(ПутьКФайлу) Тогда
        Возврат;
    КонецЕсли;

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

    Лист = Книга.Sheets(1);
    
    // Определяем последнюю заполненную строку
    xlCellTypeLastCell = 11;
    ПоследняяСтрока = Лист.Cells.SpecialCells(xlCellTypeLastCell).Row;
    
    МассивРезультатов = Новый Массив;
    
    Для НомСтроки = 2 По ПоследняяСтрока Цикл
        // Создаем структуру для хранения данных одной строки
        ДанныеСтроки = Новый Структура;
        ДанныеСтроки.Вставить("Артикул", Лист.Cells(НомСтроки, 1).Value);
        ДанныеСтроки.Вставить("Наименование", Лист.Cells(НомСтроки, 2).Value);
        ДанныеСтроки.Вставить("Цена", Лист.Cells(НомСтроки, 3).Value);
        
        МассивРезультатов.Добавить(ДанныеСтроки);
    КонецЦикла;

    // ОБЯЗАТЕЛЬНО закрываем Excel, чтобы процессы не зависали в памяти
    Книга.Close(Ложь);
    ExcelПриложение.Quit();
    ExcelПриложение = Неопределено;
    
    Сообщить("Загружено строк: " + МассивРезультатов.Количество());
КонецПроцедуры

Метод 2. Штатное чтение через Табличный Документ (Рекомендуемый)

Использование COM-объектов считается устаревшим и ненадежным подходом. Если на сервере не установлен Microsoft Excel или сервер работает под управлением Linux, ваш код не сработает. Рассмотрим более универсальный и современный способ — использование метода Прочитать() объекта ТабличныйДокумент.

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

  1. Независимость: Не требуется установленный Microsoft Office.
  2. Скорость: Чтение в память 1С происходит быстрее, чем обращение к каждой ячейке через COM.
  3. Кроссплатформенность: Работает на любом сервере.

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


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

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

Важные технические нюансы и оптимизация

При работе с большими объемами данных важно учитывать архитектурные особенности платформы 1С. Рассмотрим подробнее, на что стоит обратить внимание:

1. Очистка памяти при использовании COM. Процессы EXCEL.EXE часто остаются в «висячем» состоянии в диспетчере задач сервера. Это происходит, если 1С не смогла корректно закрыть объект из-за ошибки или если остались «неявные» ссылки. Чтобы этого избежать, всегда используйте блок Попытка...Исключение и в блоке завершения обнуляйте переменные, присваивая им Неопределено.

2. Определение границ данных. Метод SpecialCells(11) может возвращать неверную последнюю строку, если в файле было форматирование ниже самих данных. Профессионалы рекомендуют использовать свойство UsedRange или проверять заполненность ключевых полей (например, артикула) в цикле Пока.

3. Типы данных. При чтении через ТабличныйДокумент числа могут прочитаться как строки, если в Excel стоял текстовый формат. Используйте функцию Число() с предварительной очисткой строки от неразрывных пробелов (символ с кодом 160), которые Excel часто добавляет как разделители разрядов.

4. Фоновое выполнение. Если файл содержит десятки тысяч строк, процедура может длиться долго, что приведет к зависанию интерфейса пользователя или обрыву соединения по таймауту. В таких случаях разберем возможность запуска загрузки через ФоновыеЗадания.Выполнить(). Это позволит пользователю продолжать работу, пока сервер обрабатывает файл в фоновом режиме.

5. Режим отладки на сервере. Если ваш отладчик «проскакивает» серверные процедуры, убедитесь, что сервер 1С запущен с ключом -debug. В противном случае точки остановки будут работать только в клиентском коде.

Подводя итог, можно сказать: для простых разовых задач на локальном компьютере подойдет метод COM. Однако для надежных корпоративных решений всегда выбирайте чтение через ТабличныйДокумент или прямую распаковку XLSX как XML, так как это гарантирует стабильность работы системы вне зависимости от внешнего окружения.

← На главную