Чтение файла Excel из кода 1С: COM, табличный документ, ADO и XML

· 9 мин

Содержание

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

Загрузить данные из Excel в 1С программно можно четырьмя путями: через COM-объект Excel.Application, через встроенный ТабличныйДокумент, через ADO (драйвер OLE DB) и распаковкой XLSX как ZIP-архива с XML. Ниже у каждого способа рабочий код, ограничения и случаи, когда он проигрывает остальным.

Какой способ выбрать под вашу задачу

Сначала ответьте на три вопроса: где выполняется код (клиент, сервер, фоновое задание), стоит ли на этой машине Excel и сколько строк в файле. Дальше всё видно из таблицы.

СпособНужен Excel на машинеСерверСкорость на 100 тыс. строкГлавный риск
COM Excel.Applicationдапочти всегда нетнизкая при чтении по ячейкамзависший процесс Excel в памяти
ТабличныйДокумент.Прочитать()нетдасредняялишний расход памяти на форматирование
ADO / OLE DBнет, нужен драйверзависит от разрядностивысокаядрайвер другой разрядности, угадывание типов
XLSX как XMLнетдавысокаясами разбираем даты и общие строки
Где и как вы читаете файл?

Чтение через COM-соединение с Excel

Способ самый наглядный: 1С запускает Excel как внешнее приложение и работает с ним, как макрос. Подходит для клиентской стороны на Windows, когда Excel уже установлен.

Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Excel.Visible = Ложь;
Попытка
    Книга = Excel.Workbooks.Open(ПутьКФайлу, 0, Истина);
    Лист = Книга.Worksheets(1);
    ПоследняяСтрока = Лист.UsedRange.Rows.Count;
    Для НомерСтроки = 2 По ПоследняяСтрока Цикл
        Артикул = СокрЛП(Лист.Cells(НомерСтроки, 1).Value);
        Количество = Лист.Cells(НомерСтроки, 3).Value;
        // дальше разбор и запись в 1С
    КонецЦикла;
    Книга.Close(Ложь);
Исключение
    ТекстОшибки = ОписаниеОшибки();
КонецПопытки;
Excel.Quit();
Excel = Неопределено;

Что здесь важно:

  • 🔒 Второй параметр Open отвечает за обновление связей, третий включает режим «только чтение». Исходный файл при этом не блокируется для других.
  • 🧹 Excel.Quit() вызывайте всегда, в том числе после ошибки. Иначе в диспетчере задач останется процесс EXCEL.EXE, и через десяток запусков машина начнёт тормозить.
  • 🐌 Построчное чтение Cells(i, j).Value — это отдельный вызов внешнего объекта на каждую ячейку. На 50 тысяч строк по 10 колонок получится полмиллиона обращений.

Чтобы ускорить, читайте диапазон целиком одним вызовом и разбирайте массив уже в 1С:

Область = Лист.Range(Лист.Cells(2, 1), Лист.Cells(ПоследняяСтрока, 10));
Данные = Область.Value.Выгрузить();

Проверьте индексацию полученного массива на маленьком диапазоне 2×2, прежде чем писать цикл на весь файл. Нумерация элементов у выгруженного массива отличается от нумерации строк и колонок в Excel.

Если на компьютере несколько версий Office или Excel запущен под другим пользователем, Новый COMОбъект("Excel.Application") может упасть с ошибкой доступа или вернуть не тот экземпляр. Для серверных задач этот способ лучше не использовать вообще.

Табличный документ вместо COM

ТабличныйДокумент умеет читать файлы Excel сам, без установленного пакета. Для XLSX в актуальных релизах платформы 8.3 это штатная возможность, на сервере она работает так же, как на клиенте.

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

Для НомерСтроки = 2 По Таблица.ВысотаТаблицы Цикл
    Артикул = СокрЛП(Таблица.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
    Количество = Таблица.Область(НомерСтроки, 3, НомерСтроки, 3).Значение;
КонецЦикла;

Режим Значение возвращает то, что лежит в ячейке: число как число, дату как дату. Режим Текст вернёт строку так, как её видит пользователь, со всеми пробелами-разделителями тысяч. Для чисел и дат берите значение, для артикулов и кодов — текст, иначе код 00123 превратится в 123.

Минус способа: форматирование и объединённые ячейки тоже попадают в память. Файл на 200 тысяч строк с цветной разметкой занимает заметно больше места, чем сами данные.

Чтение через ADO и драйвер OLE DB

Excel здесь работает как база данных: лист — это таблица, шапка — имена полей. Подключаетесь через ADODB.Connection и пишете обычный SQL-запрос.

Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ПутьКФайлу
    + ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1""");

Набор = Новый COMОбъект("ADODB.Recordset");
Набор.Open("SELECT * FROM [Лист1$]", Соединение);

Пока Не Набор.EOF Цикл
    Артикул = СокрЛП(Набор.Fields("Артикул").Value);
    Набор.MoveNext();
КонецЦикла;

Набор.Close();
Соединение.Close();

Условия, без которых способ не заработает:

  1. Установлен драйвер Microsoft Access Database Engine (поставщик Microsoft.ACE.OLEDB.12.0 или новее).
  2. Разрядность драйвера совпадает с разрядностью процесса 1С. 64-разрядный клиент не увидит 32-разрядный драйвер и наоборот.
  3. Первая строка листа — действительно шапка, а не пустая строка и не заголовок отчёта.

Параметр IMEX=1 заставляет драйвер читать смешанные колонки как текст. Без него колонка, где первые строки числовые, а дальше встречается текст, вернёт пустые значения на текстовых ячейках. Именно так «теряются» артикулы вроде А-125 в колонке с цифрами.

Разбор XLSX как XML без Excel

Файл XLSX — это ZIP-архив. Внутри лежат XML-файлы, и их можно прочитать штатными объектами 1С. Способ быстрый и работает на любом сервере, но разбор придётся написать самому.

Нужные части архива:

  • xl/sharedStrings.xml — таблица общих строк. Текст ячеек хранится здесь один раз, а на листе лишь индекс.
  • xl/worksheets/sheet1.xml — данные первого листа.
  • xl/workbook.xml — список листов и их имена.

Порядок работы:

  1. Распакуйте архив через ЧтениеZipФайла во временный каталог (ПолучитьИмяВременногоФайла() даёт путь, каталог создайте сами).
  2. Прочитайте sharedStrings.xml через ЧтениеXML в массив строк.
  3. Пройдите по элементам c в sheet1.xml. У каждого есть адрес в атрибуте r (например B7), тип в атрибуте t и значение в дочернем элементе v.
  4. Если t="s", значение в v — индекс в массиве общих строк. Если t="str", это результат формулы-строки. Если t="inlineStr", текст лежит прямо в ячейке. Если t нет, это число.
Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "c" Тогда
        Адрес = Чтение.ЗначениеАтрибута("r");
        ТипЯчейки = Чтение.ЗначениеАтрибута("t");
    КонецЕсли;
КонецЦикла;

Даты в таких файлах лежат числом: количество дней от 30.12.1899. Преобразуйте так: Дата(1899, 12, 30) + Целое(Значение) * 86400. Дробная часть числа — время суток.

Пустые ячейки в XML часто просто отсутствуют, поэтому колонку определяйте по адресу из атрибута r, а не по порядковому номеру элемента в строке. Иначе после первой пропущенной ячейки данные поедут влево.

Когда COM не стартует: проверка соединения

Самая частая жалоба на COM — «Ошибка при вызове конструктора (COMObject)». Прежде чем менять код, проверьте среду.

Диагностика: выберите симптом

Ошибки данных и проверка перед записью

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

Проверяйте по очереди:

  • 🔢 Числа в виде текста. В ячейке 1 250,50 с неразрывным пробелом. Уберите пробелы (в том числе символ с кодом 160) и замените запятую на точку перед Число().
  • 📅 Даты. Одни ячейки хранят настоящую дату, другие текст «05.10.26». Обрабатывайте оба варианта и не пропускайте тихо те, что не распознались.
  • 🔗 Ссылки на справочники. Артикул из файла ищите запросом сразу по пакету, а не по одному элементу в цикле. Ненайденное складывайте в отчёт об ошибках.
  • 🚫 Пустые обязательные поля. Строку без количества или цены не загружайте и не обнуляйте молча.
  • 🔁 Дубли. Одна позиция в двух строках должна либо складываться, либо попадать в отчёт.

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

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

Как ускорить загрузку больших файлов

Скорость почти никогда не упирается в чтение файла. Основное время съедает запись в базу и поиск связанных объектов.

Что даёт реальный выигрыш:

  1. Прочитать всё в таблицу значений, потом работать с ней. Чтение и запись не должны чередоваться ячейка за ячейкой.
  2. Один запрос вместо тысячи. Передайте артикулы временной таблицей и получите соответствие «артикул → ссылка» за один проход. Поиск НайтиПоКоду() в цикле на 100 тысяч строк заметно медленнее.
  3. Записывать порциями. Например, по 1000 строк в одной транзакции: НачатьТранзакцию() и ЗафиксироватьТранзакцию() на порцию, а не на всю загрузку и не на каждую строку.
  4. Не обновлять форму на каждой строке. Индикатор прогресса показывайте раз в сотню или тысячу строк.
  5. Вынести загрузку в фоновое задание, если файл большой. Пользователь продолжит работу, а ошибку не потеряет: итог пишется в журнал.
  6. Для регистров сведений использовать набор записей. Заполнили набор целиком и записали одним вызовом, это быстрее, чем создавать запись по одной.

Ориентиры по времени очень зависят от сервера и объёма базы, поэтому измеряйте на своих данных: замерьте время чтения, проверки и записи отдельно. Часто выясняется, что чтение занимает секунды, а запись минуты.

Перед запуском загрузки
Выполнено: 0 / 6

Частые вопросы

Можно ли читать Excel в 1С без установленного Excel?
Да. ТабличныйДокумент.Прочитать(), ADO с драйвером Access Database Engine и разбор XLSX как XML не требуют самого Excel.
Почему нельзя вызвать COM-объект Excel в регламентном задании?
Excel рассчитан на работу под интерактивным пользователем. В фоновом процессе без рабочего стола он зависает на скрытых диалогах или не запускается. Для таких задач берите табличный документ или XML.
Что делать с файлами в старом формате XLS?
Табличный документ и ADO читают и их. Для ADO в строке подключения укажите Excel 8.0 вместо Excel 12.0 Xml. Разбор через XML к XLS неприменим: это не ZIP-архив.
Как узнать список листов книги?
В COM это коллекция Книга.Worksheets, у каждого листа есть свойство Name. При разборе XML имена листов лежат в xl/workbook.xml.
Чем ADO хуже других способов?
Он сам определяет тип колонки по первым строкам, поэтому смешанные данные читаются неверно. Для файлов с произвольной структурой надёжнее табличный документ.