В практике программиста 1С (которому часто требуется шаблон простой обработки загрузки из excel) часто встречается ситуация: при попытке программно прочитать файл Excel формата .xls с помощью стандартного метода ТабличныйДокумент.Прочитать(), система возвращает пустой документ, хотя качественный импорт данных ожидается по умолчанию. При этом внешне файл выглядит абсолютно корректно, данные в нем присутствуют, а отладка показывает, что 1С видит колонки, но не видит строк (или видит только одну пустую строку). Рассмотрим подробнее, почему это происходит и какие существуют пути решения данной проблемы.
Прежде чем переходить к причинам ошибок, проанализируем, как работает сам механизм. Часто разработчики ошибочно полагают, что метод Прочитать() загружает только первый лист книги Excel. На самом деле платформа считывает все листы файла, но объединяет их в один общий табличный документ. Чтобы получить доступ к данным конкретных листов, необходимо работать с коллекцией Области. Каждый лист Excel превращается в именованную область в 1С.
Рассмотрим пример того, как можно проверить наличие данных на разных листах:
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ПутьФайла);
// Пройдемся по всем именованным областям, которые соответствуют листам Excel
Для Каждого Область Из ТабДок.Области Цикл
Сообщить("Найден лист (область): " + Область.Имя);
КонецЦикла;
Если после выполнения этого кода коллекция областей пуста или содержит только одну пустую область, значит, проблема глубже — в самом файле или правах доступа к нему.
Одной из наиболее распространенных причин "пустого чтения" является защищенный режим редактирования. Если файл был скачан из интернета, получен по электронной почте или создан в сторонней системе (например, выгрузка из клиент-банка), операционная система Windows помечает его как потенциально опасный. При открытии такого файла в Excel сверху появляется желтая полоса с надписью "Защищенный просмотр".
Для встроенного парсера 1С такой файл выглядит заблокированным. Платформа инициализирует чтение, определяет структуру (количество колонок), но не получает доступа к самим ячейкам с данными. Чтобы проверить эту версию, попробуйте открыть файл вручную в 1С через меню Файл — Открыть. Если в окне просмотра вы видите пустую таблицу — дело именно в защите.
Как решить проблему защиты программно:
Zone.Identifier. Можно попробовать скопировать файл во временную папку перед чтением с помощью команды КопироватьФайл(), что иногда помогает сбросить атрибуты безопасности.
// Пример использования COM-объекта для "разблокировки" файла
ExcelПриложение = Новый COMОбъект("Excel.Application");
ExcelПриложение.DisplayAlerts = Ложь; // Отключаем уведомления
Книга = ExcelПриложение.Workbooks.Open(ПутьФайла);
// Сохраняем во временный файл в формате XLSX (или заново в XLS)
ВременныйПуть = ПолучитьИмяВременногоФайла("xlsx");
Книга.SaveAs(ВременныйПуть, 51); // 51 - код формата XLSX
Книга.Close();
ExcelПриложение.Quit();
// Теперь читаем уже "чистый" файл
ТабДок.Прочитать(ВременныйПуть);
Проанализируем ситуацию, когда расширение файла .xls не соответствует его реальному внутреннему содержимому. Иногда системы формируют файл в формате XLSX (XML) или даже HTML/CSV (в таких случаях полезен конвертор файлов из CSV в XLS), но сохраняют его с расширением .xls. Метод Прочитать() ожидает строго двоичный формат BIFF8 (стандарт Excel 97-2003). Если формат нарушен, 1С не сможет корректно проитерировать строки.
В этом случае рекомендуется использовать чтение через Поток с явным указанием типа файла. Посмотрим на пример кода, который позволяет более гибко работать с типами данных:
&НаСервере
Процедура ПрочитатьЧерезПоток(АдресФайла)
ДД = ПолучитьИзВременногоХранилища(АдресФайла);
Поток = ДД.ОткрытьПотокДляЧтения();
// Пытаемся прочитать как XLSX, если обычный XLS не сработал
Попытка
ТабДок.Прочитать(Поток, СпособЧтенияТабличногоДокумента.Значения, ТипФайлаТабличногоДокумента.XLSX);
Исключение
// Обработка ошибки, если формат другой
КонецПопытки;
Поток.Закрыть();
КонецПроцедуры
Если стандартный метод ТабличныйДокумент.Прочитать() продолжает выдавать пустой результат, а использование COM-объектов невозможно (например, на сервере не установлен Microsoft Office), можно прибегнуть к технологии ADO (ActiveX Data Objects). Этот метод обращается к файлу Excel как к базе данных SQL.
Преимущество ADO заключается в том, что он более толерантен к "битым" структурам файлов и защищенным режимам, так как использует системные драйверы Microsoft Access Engine.
Соединение = Новый COMОбъект("ADODB.Connection");
СтрокаСоединения = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ПутьФайла + ";Extended Properties=""Excel 12.0;HDR=YES"";";
Попытка
Соединение.Open(СтрокаСоединения);
Запись = Новый COMОбъект("ADODB.Recordset");
Запись.Open("SELECT * FROM [Лист1$]", Соединение);
Пока НЕ Запись.EOF Цикл
// Обработка данных из ячеек
Значение = Запись.Fields.Item(0).Value;
Запись.MoveNext();
КонецЦикла;
Запись.Close();
Соединение.Close();
Исключение
Сообщить("Ошибка подключения к Excel через ADO: " + ОписаниеОшибки());
КонецПопытки;
Если ваше приложение 1С работает на сервере под управлением Linux, использование COM-объектов Excel.Application невозможно в принципе. Метод Прочитать() для старых форматов .xls на Linux может работать нестабильно. В таких условиях лучшим решением будет предварительная конвертация файлов в формат .xlsx или .ods на стороне клиента или использование сторонних библиотек парсинга (например, на Python или Java), если это предусмотрено архитектурой решения.
Проанализировав ситуацию с некорректным чтением Excel-файлов, мы можем составить следующий алгоритм действий:
ТабДок.Области)..xlsx, так как он основан на XML и читается платформой 1С гораздо стабильнее.Прочитать() не справляется, используйте чтение через COM или ADO.Соблюдение этих правил позволит вам избежать проблем при автоматизации загрузки данных и сделает ваш код более отказоустойчивым при работе с внешними источниками данных.