Почему ТабличныйДокумент.Прочитать() не загружает XLS файлы и как это исправить?

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

При переходе с использования устаревших технологий (например, COM-соединения с Excel или ADO) на нативные средства платформы 1С:Предприятие, программисты часто сталкиваются с неожиданными ошибками. Одна из самых распространенных — "Формат файла не поддерживается" при вызове метода Прочитать() объекта ТабличныйДокумент. Ситуация выглядит парадоксально: файл корректно открывается в Microsoft Excel или LibreOffice, но 1С отказывается с ним работать.

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем нюансы работы платформы 8.3.11 и выше, а также выясним, как правильно организовать чтение файлов на стороне сервера. Для быстрого построения алгоритма можно использовать шаблон обработки загрузки из Excel.

Анализ стандартного подхода и поиск ошибки

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


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

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

Проблема «Ложного» расширения (HTML/XML под видом XLS)

Если код выше работает исправно, но на определенных файлах все равно возникает ошибка формата, нам следует проанализировать структуру самого файла. Многие сторонние системы (банковские сервисы, CRM, веб-отчеты) используют "трюк": они генерируют обычную HTML-таблицу или XML-структуру (SpreadsheetML), но сохраняют файл с расширением .xls.

Разберем, почему это критично:

Рекомендация: откройте проблемный файл в обычном текстовом редакторе (Блокнот, Notepad++). Если вы видите теги <html> или <?xml ...>, значит, это не настоящий Excel-файл. В таком случае в методе Прочитать() нужно явно указывать ТипФайлаТабличногоДокумента.HTML.

Явное указание типа файла

Иногда автоматическое определение формата платформой дает сбой. Мы рекомендуем явно указывать тип файла в качестве третьего параметра метода Прочитать(). Это помогает платформе выбрать правильный алгоритм парсинга данных.


// Явное указание формата XLS (Excel 97-2003)
ТабличныйДокумент.Прочитать(ИмяВременногоФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение, ТипФайлаТабличногоДокумента.XLS);

Если вы работаете с более современными файлами, используйте ТипФайлаТабличногоДокумента.XLSX. Это исключит лишние проверки платформы и ускорит процесс открытия. Для предварительной трансформации исходных документов подойдёт конвертер файлов из XLS в XLSX.

Особенности платформы 8.3.11 и разрядность сервера

Проанализируем технический контекст версии 8.3.11. В этом релизе и последующем 8.3.12 в нативных библиотеках чтения файлов Excel были зафиксированы ошибки, связанные с обработкой сложных объектов внутри книги (макросы, диаграммы, сложные сводные таблицы). Если ТабличныйДокумент встречает элемент, который он не может отрисовать, он может выдать общую ошибку формата.

Также стоит учитывать разрядность сервера 1С:

  1. На 64-битных серверах работа с бинарными форматами BIFF8 иногда может приводить к специфическим ошибкам доступа к памяти, если файл поврежден или имеет нестандартную структуру индексов строк.
  2. На Linux-серверах стабильность чтения старого формата .xls исторически ниже, чем в Windows-среде, из-за особенностей используемых библиотек трансляции.

Методы решения проблемы "неуспешной записи"

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

Проанализируем пример "безопасного" чтения:


ДанныеФайла.Записать(ИмяВременногоФайла);

// Проверим, существует ли файл физически перед чтением
ФайлНаДиске = Новый Файл(ИмяВременногоФайла);
СчетчикПопыток = 0;

Пока Не ФайлНаДиске.Существует() И СчетчикПопыток < 10 Цикл
    // Небольшая пауза, если файл еще не создался ОС
    СчетчикПопыток = СчетчикПопыток + 1;
    #Если Сервер Тогда
        // На сервере можно использовать ожидание через заблокированные процессы, 
        // но проще дождаться появления файла в цикле
    #КонецЕсли
КонецЦикла;

Если ФайлНаДиске.Существует() Тогда
    ТабличныйДокумент.Прочитать(ИмяВременногоФайла);
Иначе
    ВызватьИсключение "Не удалось зафиксировать файл на диске сервера";
КонецЕсли;

Защищенный просмотр и блокировки NTFS

Выясним еще одну причину, которая часто ускользает от внимания программистов. Файлы, полученные из внешних источников (почта, интернет), могут помечаться операционной системой как небезопасные. В свойствах файла в NTFS появляется атрибут "Заблокировано" (Zone.Identifier). Хотя 1С работает от имени системного пользователя, на некоторых конфигурациях прав доступа это может блокировать чтение потоков данных файла. Если вы столкнулись с системной ошибкой при чтении, попробуйте предварительно "разблокировать" файл или копировать его данные в новый поток.

Лимиты и ограничения формата

Не забывайте, что формат .xls (BIFF8) имеет жесткие ограничения:

Если файл был сформирован программно и эти лимиты были нарушены (например, записано 70 000 строк в формате XLS), Microsoft Excel может попытаться "починить" такой файл при открытии, а ТабличныйДокумент.Прочитать() просто выдаст ошибку формата, так как структура индексов внутри файла будет нарушена.

Итоги

Для стабильной работы загрузки данных через ТабличныйДокумент придерживайтесь следующих правил:

  1. Убедитесь, что файл действительно является бинарным Excel, а не переименованным HTML.
  2. Явно указывайте ТипФайлаТабличногоДокумента в методе Прочитать().
  3. Проверяйте физическое наличие файла на диске после вызова Записать().
  4. Если возможно, используйте современный формат .xlsx, так как работа с ним в 1С реализована более стабильно и прозрачно.
← На главную