При интеграции 1С с внешними веб-сервисами и сторонними приложениями одной из частых задач является чтение выгруженных файлов Excel. Популярный способ программного чтения без необходимости устанавливать Microsoft Excel на сервере — использование COM-объекта ADODB.Connection с провайдером Microsoft.ACE.OLEDB.12.0.
Однако при попытке открыть такой файл разработчики нередко сталкиваются с ошибкой: «Произошла исключительная ситуация (Microsoft Access Database Engine): Внешняя таблица не имеет предполагаемый формат» (или в англоязычной версии: «External table is not in the expected format»). При этом если открыть проблемный файл вручную в Microsoft Excel и просто пересохранить его, он начинает без ошибок считываться и через ADO, и штатными средствами платформы 1С. Рассмотрим причины такого поведения и разберем способы решения задачи.
Посмотрим на типовой пример кода, вызывающий исключение:
еБаза = Новый COMОбъект("ADODB.Connection");
СтрокаПодключения = "
|Provider=Microsoft.ACE.OLEDB.12.0;
|Data Source=C:\Users\cd\AppData\Local\Temp\v8_7537_12b.xlsx;
|Extended Properties=""Excel 12.0 XML;IMEX=1;HDR=Yes;"";
";
еБаза.Open(СтрокаПодключения);
Драйвер Microsoft.ACE.OLEDB.12.0 предъявляет очень строгие требования к структуре OpenXML-контейнера. Microsoft Excel при ручном открытии файла автоматически корректирует мелкие недочеты структуры прямо в оперативной памяти, а вот системный OLEDB-провайдер при любом несоответствии спецификации сразу прерывает работу с ошибкой. Проанализируем основные причины сбоя:
xl/worksheets/sheet*.xml) сторонние библиотеки часто забывают сформировать узел <dimension ref="A1:N..." />. Без явного указания размерности OLEDB-драйвер не может определить границы таблицы._rels/.rels, xl/_rels/workbook.xml.rels или типов содержимого в [Content_Types].xml.inlineStr вместо использования общей таблицы строк xl/sharedStrings.xml.Если генерацией файлов занимается сторонняя сторона (например, веб-сервис на базе библиотек OpenXML), порекомендуем им выполнить следующие доработки:
<dimension> с реальными координатами заполненных строк и колонок.workbook.xml и связанных файлах связей (.rels).Иногда драйвер дает сбой из-за особенностей синтаксиса параметра Extended Properties. Попробуем скорректировать строку подключения, убрав суффикс XML и проверив экранирование параметров:
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ИмяФайла + ";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1;"";";
Если изменить логику работы внешней системы невозможно, рассмотрим альтернативные варианты загрузки данных в 1С без установки офисных пакетов на сервер.
Начиная с платформы 8.3, объект ТабличныйДокумент умеет читать файлы .xlsx напрямую:
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла);
// Далее выполняем обход ячеек ТабДок.ПолучитьОбласть(...)
Исключение
Сообщить("Не удалось прочитать файл стандартным методом: " + ОписаниеОшибки());
КонецПопытки;
Однако если файл сильно поврежден или сформирован с грубыми нарушениями стандарта, данный метод также может вернуть ошибку выполнения файловой операции. В этом случае перейдем к прямому чтению структуры.
Файл формата .xlsx представляет собой стандартный ZIP-архив с XML-документами внутри. Платформа 1С содержит все необходимые объекты для его разбора без внешних драйверов:
.xlsx во временный каталог с помощью объекта ЧтениеZipФайла.ЧтениеXML считываем файл xl/sharedStrings.xml и сохраняем строки в массив или соответствие.xl/worksheets/sheet1.xml, извлекая строки (теги <row>) и ячейки (теги <c>).Этот метод работает максимально быстро, полностью кроссплатформенен (работает как под Windows, так и под Linux) и абсолютно не зависит от строгости драйверов OLEDB.
В ряде ситуаций драйвер ODBC оказывается более устойчивым к нестандартной структуре файла, чем OLEDB. Подключение через ADODB в этом случае выглядит следующим образом:
Соединение = Новый COMОбъект("ADODB.Connection");
СтрокаПодключения = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" + ИмяФайла + ";ReadOnly=1;";
Соединение.Open(СтрокаПодключения);
Если требуется регулярная обработка больших объемов нестандартных файлов, можно применить внешние библиотеки (.NET-компоненты на базе ExcelDataReader или ClosedXML) либо вызвать легковесную консольную утилиту через метод ЗапуститьПриложение() для предварительной конвертации файла в формат .csv.