Почему при чтении файла Excel в табличный документ не доступны значения ячеек и как это исправить?

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

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

Попытка принудительно установить для ячейки флаг СодержитЗначение = Истина нередко приводит к следующей ошибке: «Поле объекта недоступно для записи». Разберем по шагам, почему платформа ведет себя именно так и как правильно прочитать типизированные данные из Excel без использования медленного и платформозависимого COM-соединения.

Выясним причину возникновения ошибок

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

  1. Недоступность свойства для чтения. В объекте ОбластьЯчеекТабличногоДокумента обращение к свойству Значение программно разрешено только тогда, когда булево свойство СодержитЗначение для данной ячейки установлено в Истина. По умолчанию метод ТабличныйДокумент.Прочитать() вызывается со значением второго параметра СпособЧтенияЗначенийТабличногоДокумента.Текст. При таком режиме платформа считывает все данные исключительно как строки для отображения, а признак СодержитЗначение для всех ячеек принимает значение Ложь.
  2. Недоступность свойства для записи. Ошибка при попытке вручную присвоить СодержитЗначение = Истина возникает, если табличный документ заблокирован от редактирования. Это происходит, когда у документа установлены свойства ТолькоПросмотр = Истина или Защита = Истина (например, если загружаемый лист Excel имел внутреннюю защиту или свойства были выставлены в элементе формы).
  3. Бесполезность ручной установки флага. Даже если снять защиту документа программно и установить СодержитЗначение = Истина постфактум, получить исходные типизированные данные уже не удастся: при текстовом чтении платформа не сохраняет в памяти типизированное значение из файла, поэтому ячейка станет пустой.

Основное решение: явное указание способа чтения значений

Рассмотрим самое простое и правильное решение, предусмотренное разработчиками платформы. При вызове метода Прочитать() необходимо явно передать второй параметр, указав системное перечисление СпособЧтенияЗначенийТабличногоДокумента.Значение.

Посмотрим на пример кода:


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

// Теперь свойство Значение доступно для чтения и возвращает исходный тип данных:
Ячейка = ТабДок.Область("R2C3");
Если Ячейка.СодержитЗначение Тогда
    ЗначениеЯчейки = Ячейка.Значение;
    ТипДанных = ТипЗнч(ЗначениеЯчейки); // Дата, Число, Строка или Булево
КонецЕсли;

После передачи этого системного перечисления платформа при чтении файла автоматически выставляет СодержитЗначение = Истина для всех заполненных ячеек и сохраняет исходные числа и даты как полноценные типы платформы 1С:Предприятие.

Быстрая загрузка данных через ПостроительЗапроса без обхода ячеек

Построчный обход сотен и тысяч ячеек через метод Область() в цикле работает достаточно медленно. Однако после того, как документ прочитан с признаком СпособЧтенияЗначенийТабличногоДокумента.Значение, мы можем мгновенно преобразовать всю таблицу в привычную ТаблицуЗначений с сохранением типов колонок с помощью объекта ПостроительЗапроса.

Разберем реализацию этого быстрого метода:


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

Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабДок.Область());
Построитель.Выполнить();

// Получаем готовую ТаблицуЗначений с типизированными колонками
ТаблицаДанных = Построитель.Результат.Выгрузить();

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

Ограничения и нюансы метода ТабличныйДокумент.Прочитать()

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

  1. Чтение только первого листа книги. Метод Прочитать() всегда загружает исключительно первый лист файла. Выбрать нужный лист по имени или порядковому номеру штатными средствами табличного документа невозможно.
  2. Кэшированные значения формул. Если в таблице содержатся формулы, платформа 1С считывает предрассчитанный результат из кэша файла. Если файл Excel был сформирован сторонними скриптами или библиотеками без пересчета и сохранения итогов формул, соответствующие ячейки в 1С окажутся пустыми.
  3. Система исчисления дат (1900 против 1904). В Excel поддерживаются две системы отсчета дат. Если документ сохранен в системе дат 1904 (характерно для файлов, созданных в Excel для macOS), даты при чтении через 1С могут сдвигаться на 4 года (на 1462 дня) назад. В таком случае потребуется программная корректировка полученных дат.
  4. Защита паролем и старые форматы. Платформа не умеет читать защищенные паролем на открытие книги, а также файлы устаревшего формата Excel 95 и более ранних версий (при попытке чтения будет сгенерировано исключение о неподдерживаемом формате).

Альтернативный вариант: чтение структуры XLSX через XML

Если необходимо обойти ограничение первого листа или требуется обрабатывать файлы нестандартной структуры, можно использовать прямое чтение формата .xlsx без внешних зависимостей. Поскольку современный файл Excel представляет собой упакованный ZIP-архив, его можно разобрать штатными средствами платформы с помощью объектов ЧтениеZipФайла и ЧтениеXML.

Рассмотрим общую схему такого подхода:

  1. Файл распаковывается во временный каталог через ЧтениеZipФайла.
  2. Из файла xl/sharedStrings.xml считывается общая таблица строк.
  3. Из каталога xl/worksheets/ читается XML-файл нужного листа (например, sheet1.xml, sheet2.xml), что позволяет обращаться к абсолютно любому листу книги.
  4. Числовые значения и даты (представленные количеством дней с 1900 года) преобразуются непосредственно при разборе узлов ячеек.

Тем не менее, для большинства типовых задач импорта указания СпособЧтенияЗначенийТабличногоДокумента.Значение в методе Прочитать() оказывается полностью достаточно для корректного и быстрого получения данных.

← На главную