Почему ТабличныйДокумент.Прочитать() возвращает 16384 колонки при загрузке Excel в 1С и как получить реальный размер таблицы?

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

При загрузке файлов Excel (особенно формата .xlsx) в объект 1С ТабличныйДокумент с помощью метода Прочитать() разработчики часто сталкиваются с неожиданным behavior: свойства ШиринаТаблицы и ВысотаТаблицы возвращают огромные значения (например, 16 384 колонки и 9 806 строк), хотя реальных данных в файле всего 10–20 колонок.

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

Причины некорректного определения размера таблицы

Проанализируем ситуации, из-за которых ТабличныйДокумент определяет размер таблицы со значительным запасом:

  1. Форматирование пустых ячеек в Excel: Если в файле Excel для ячеек задан стиль (цвет фона, границы, шрифт или выравнивание), даже при отсутствии текста платформа 1С воспринимает эти ячейки как заполненные области табличного документа.
  2. Метаданные XLSX-архива: Записи в файле Excel содержат служебный тег dimension, определяющий максимальный рабочий диапазон листа. Сторонние генераторы файлов или сам MS Excel при сохранении могут прописывать в этот тег предельное количество колонок (до 16 384). Метод Прочитать() считывает этот диапазон целиком.
  3. Особенности работы платформ 1С: В некоторых версиях платформы присутствует штатное поведение (или ошибки импорта), когда область чтения расширяется до границы отформатированного диапазона.

Способ 1. Поиск первой пустой ячейки по строке заголовка

Если загружаемый файл имеет четкую структуру с шапкой (строкой заголовков колонок), разберем самый простой вариант определения количества колонок: выполнение цикла по строке шапки до первой незаполненной ячейки.

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


&НаСервере
Функция ПрочитатьExcelФайл(ПутьКФайлу)
    
    ТабДок = Новый ТабличныйДокумент;
    ТабДок.Прочитать(ПутьКФайлу);
    
    // Определим реальное количество колонок по строке шапки (например, строка 3)
    СтрокаШапки = 3;
    МаксКолонок = ТабДок.ШиринаТаблицы;
    РеальноеКоличествоКолонок = 0;
    
    Для НомерКолонки = 1 По МаксКолонок Цикл
        ТекстЯчейки = СокрЛП(ТабДок.ПолучитьОбласть(СтрокаШапки, НомерКолонки).ТекущаяОбласть.Текст);
        Если ПустаяСтрока(ТекстЯчейки) Тогда
            Прервать;
        КонецЕсли;
        РеальноеКоличествоКолонок = РеальноеКоличествоКолонок + 1;
    КонецЦикла;
    
    Возврат РеальноеКоличествоКолонок;
    
КонецФункции

Способ 2. Обратный обход ячеек для поиска реальных границ

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

Посмотрим на реализацию поиска последней заполненной строки и колонки:


&НаСервере
Процедура ОпределитьГраницыТаблицы(ТабДок, ПоследняяСтрока, ПоследняяКолонка)
    
    ПоследняяСтрока = 0;
    ПоследняяКолонка = 0;
    
    ВсегоСтрок = ТабДок.ВысотаТаблицы;
    ВсегоКолонок = ТабДок.ШиринаТаблицы;
    
    // Поиск последней строки с данными
    Для Стр = Наоборот ВсегоСтрок По 1 Цикл
        ФлагЗаполнена = Ложь;
        Для Кол = 1 По Мин(ВсегоКолонок, 100) Цикл // проверяем первые 100 колонок
            Текст = СокрЛП(ТабДок.Область(Стр, Кол).Текст);
            Если Не ПустаяСтрока(Текст) Тогда
                ФлагЗаполнена = Истина;
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        Если ФлагЗаполнена Тогда
            ПоследняяСтрока = Стр;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Поиск последней колонки с данными
    Для Кол = Наоборот ВсегоКолонок По 1 Цикл
        ФлагЗаполнена = Ложь;
        Для Стр = 1 По ПоследняяСтрока Цикл
            Текст = СокрЛП(ТабДок.Область(Стр, Кол).Текст);
            Если Не ПустаяСтрока(Текст) Тогда
                ФлагЗаполнена = Истина;
                Прервать;
            КонецЕсли;
        КонецЦикла;
        
        Если ФлагЗаполнена Тогда
            ПоследняяКолонка = Кол;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Способ 3. Использование ПостроителяЗапроса для автоматической обрезки

Существует эффективный прием очистки пустых областей с помощью объекта ПостроительЗапроса. Передача области табличного документа в описание источника данных позволяет отсечь пустые строки и колонки и сразу получить объект ТаблицаЗначений.

Проанализируем этот подход на примере:


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

Альтернативные способы чтения файлов Excel

Если стандартный метод ТабличныйДокумент.Прочитать() работает медленно из-за большого объема пустых отформатированных ячеек, воспользуемся альтернативными инструментами интеграции:

← На главную