Чтение табличного документа в 1С 8.3: ячейки, области, Excel и двоичные данные

· 9 мин

Содержание

Чтобы прочитать табличный документ в 1С, создайте объект Новый ТабличныйДокумент, загрузите в него файл методом Прочитать(ИмяФайла) и берите текст ячеек через ТабДок.Область("R2C3").Текст. Для макета из конфигурации файл не нужен: ПолучитьМакет("Имя") сразу возвращает готовый табличный документ. Если файл пришёл в памяти (двоичные данные из хранилища, вложение письма, ответ HTTP-сервиса), его сначала пишут во временный файл или передают методу поток.

Какой способ выбрать? Макет подходит для своих печатных форм и шаблонов. Прочитать() — для Excel, OpenDocument и MXL от пользователя. COM-объект Excel нужен редко: когда требуются формулы, скрытые листы или работа на старой платформе без метода Прочитать().

Объектная модель: как устроен табличный документ и чтение ячеек

Табличный документ — это сетка ячеек. Строки адресуются буквой R, колонки — буквой C, нумерация с единицы. Адрес R1C1 — левый верхний угол.

Основные свойства и методы для чтения:

  • 📐 ВысотаТаблицы — номер последней заполненной строки;
  • 📏 ШиринаТаблицы — номер последней заполненной колонки;
  • 🔲 Область(...) — возвращает ячейку или прямоугольник ячеек;
  • 📝 .Текст — то, что видит пользователь, всегда строка;
  • 🔢 .Значение, .СодержитЗначение, .ТипЗначения — типизированное значение, если ячейка его хранит;
  • 🔗 .Расшифровка и .Параметр — служебные данные ячеек из печатных форм.

Метод Область принимает несколько вариантов адреса:

ВызовЧто вернёт
Область("R3C2")одну ячейку
Область("R2C1:R10C5")прямоугольник
Область(2, 1, 10, 5)тот же прямоугольник числами: верх, лево, низ, право
Область("R5")строку целиком
Область("C3")колонку целиком
Область("Шапка")именованную область

Минимальный пример чтения одной ячейки:

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("C:\Обмен\Прайс.xlsx");
Наименование = СокрЛП(ТабДок.Область("R2C1").Текст);

Текст ячейки нередко содержит хвостовые пробелы и переводы строк. Оборачивайте его в СокрЛП() сразу, а не на этапе сравнения.

Области и именованные диапазоны в табличном документе

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

Получить список всех имён можно перебором коллекции Области:

Для Каждого Обл Из ТабДок.Области Цикл
    Сообщить(Обл.Имя + ": строки " + Обл.Верх + "-" + Обл.Низ
        + ", колонки " + Обл.Лево + "-" + Обл.Право);
КонецЦикла;

У любой области есть координаты Верх, Низ, Лево, Право. По ним удобно вычислять, где начинаются данные. Например, табличная часть начинается сразу под областью «Шапка»: ПерваяСтрока = ТабДок.Области.Шапка.Низ + 1.

Чтение из макета конфигурации

Макет читается без файла. Методом ПолучитьОбласть берут фрагмент, а свойство Параметры даёт доступ к его параметрам:

Макет = ПолучитьМакет("ШаблонЗагрузки"); // в модуле объекта обработки
ОбластьШапки = Макет.ПолучитьОбласть("Шапка");
Колонок = ОбластьШапки.ШиринаТаблицы;

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

Чтение выделенной области на форме

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

Координаты выделенной области читаются так же: Верх, Низ, Лево, Право. Дальше — обычный цикл по строкам внутри этих границ. Сам цикл лучше вынести на сервер и передать туда только четыре числа и документ из реквизита формы.

Объединённые ячейки

Если ячейки объединены, текст хранится в левой верхней. Остальные ячейки диапазона возвращают пустую строку. В шапках Excel это частая ловушка: колонка «Количество» стоит над двумя подколонками, и вторая читается как пустая.

Загрузка табличного документа из файла Excel, MXL и памяти

Метод Прочитать() у табличного документа понимает форматы xlsx, xls, ods и mxl. Формат определяется по расширению, поэтому файл без расширения или с чужим расширением не загрузится.

Второй параметр управляет тем, что попадёт в ячейки:

РежимЧто получитеКогда выбирать
СпособЧтенияЗначенийТабличногоДокумента.Текствсё как строки, в виде отображениянужен текст «как на экране»
СпособЧтенияЗначенийТабличногоДокумента.Значениечисла, даты, булево — типизированнозагрузка сумм, количеств, дат
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);

Метод Прочитать() для Excel появился в платформе 8.3 не с первого релиза. Если компилятор сообщает, что метод не найден, проверьте версию платформы и режим совместимости конфигурации.

Файл лежит у пользователя, а читать нужно на сервере

Типичная ошибка: передать на сервер путь вида C:\Users\...\Загрузка.xlsx. Сервер этого диска не видит. Правильная схема — сначала поместить файл во временное хранилище , затем на сервере достать двоичные данные.

На клиенте:

&НаКлиенте
Процедура Загрузить(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
    НачатьПомещениеФайлаНаСервер(Оповещение, , , , УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(ОписаниеФайла, ДопПараметры) Экспорт
    Если ОписаниеФайла = Неопределено Или ОписаниеФайла.ПомещениеФайлаОтменено Тогда
        Возврат;
    КонецЕсли;
    ЗагрузитьНаСервере(ОписаниеФайла.Адрес, ОписаниеФайла.СсылкаНаФайл.Расширение);
КонецПроцедуры

Чтение из памяти: двоичные данные и поток

На сервере двоичные данные пишут во временный файл с правильным расширением, читают и удаляют:

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

В актуальных версиях платформы Прочитать() принимает и поток: ТабДок.Прочитать(Данные.ОткрытьПотокДляЧтения()). Тогда временный файл не нужен. Перед использованием сверьтесь с синтакс-помощником своей версии: если в описании метода нет варианта с потоком, оставайтесь на схеме с временным файлом.

Вставка из буфера обмена

Самый простой для пользователя способ — поле табличного документа на форме. Пользователь копирует диапазон в Excel и вставляет его в поле через Ctrl+V. Код читает реквизит формы так же, как документ из файла. Файлы, расширения и права на диск здесь не участвуют.

Перебор строк и фильтрация содержимого

Базовый цикл — от первой строки данных до ВысотаТаблицы. Колонки удобнее искать по заголовкам, а не по номерам: поставщик завтра добавит колонку, и номера съедут.

Поиск колонок по заголовку

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

Обращение Область(Строка, Колонка) с двумя числами возвращает одну ячейку. Это короче, чем собирать строку адреса "R" + Стр + "C" + Кол.

Поиск строки по тексту

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

Найдено = ТабДок.НайтиТекст("Итого");
ПоследняяСтрока = ?(Найдено = Неопределено, ТабДок.ВысотаТаблицы, Найдено.Верх - 1);

Так отсекают итоговую строку, которую не нужно загружать как товар.

Фильтрация при переборе

Что обычно отбрасывают:

  • 🚫 пустые строки — проверка ключевой колонки через ЗначениеЗаполнено;
  • 🚫 повторы шапки на каждой странице выгрузки;
  • 🚫 строки групп и подытогов — у них пустой артикул или нулевое количество;
  • 🚫 строки после «Итого» и подписи.

Быстрый перенос в таблицу значений

Для больших файлов цикл по ячейкам медленный. Известный приём — построитель запроса с источником данных из области:

Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(
    ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы));
Построитель.Выполнить();
ТЗ = Построитель.Результат.Выгрузить();

Первая строка области становится именами колонок. Заголовки с пробелами и знаками превращаются в допустимые имена, поэтому проверьте ТЗ.Колонки перед обращением по имени. Код выполняйте на сервере.

Ошибки и нестандартные ситуации при чтении

Большинство сбоев загрузки повторяются из проекта в проект. Ниже — симптомы и что с ними делать.

Диагностика: выберите симптом

Преобразование текста в число и дату

Если режим Значение недоступен или файл пришёл как текст, чистите строку вручную:

Функция ТекстВЧисло(Знач Текст)
    Текст = СтрЗаменить(Текст, Символы.НПП, "");
    Текст = СтрЗаменить(Текст, " ", "");
    Текст = СтрЗаменить(Текст, ",", ".");
    Попытка
        Возврат Число(Текст);
    Исключение
        Возврат 0;
    КонецПопытки;
КонецФункции

Для дат в формате ДД.ММ.ГГГГ разберите строку на части через СтрРазделить(Текст, ".") и соберите Дата(Год, Месяц, День). Пример: «15.03.2025» → Дата(2025, 3, 15).

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

Лишние строки в ВысотаТаблицы

ВысотаТаблицы учитывает не только текст, но и оформление. Если в Excel протянули рамку до 1000-й строки, цикл пройдёт тысячу строк. Защита — останавливаться после нескольких подряд пустых ключевых ячеек, например пяти.

Готовый код: загрузка прайса из Excel в таблицу значений

Полный пример на сервере. Шапка — в первой строке, нужные колонки: «Артикул», «Наименование», «Цена», «Количество».

&НаСервере
Процедура РазобратьТаблицу(ТабДок)
    Колонки = КолонкиПоЗаголовкам(ТабДок, 1);
    Обязательные = СтрРазделить("артикул,наименование,цена,количество", ",");
    Для Каждого Имя Из Обязательные Цикл
        Если Колонки.Получить(Имя) = Неопределено Тогда
            ВызватьИсключение "В файле нет колонки «" + Имя + "»";
        КонецЕсли;
    КонецЦикла;

    Товары.Очистить(); // табличная часть или реквизит формы
    ПустыхПодряд = 0;
    Для Стр = 2 По ТабДок.ВысотаТаблицы Цикл
        Артикул = СокрЛП(ТабДок.Область(Стр, Колонки["артикул"]).Текст);
        Если Не ЗначениеЗаполнено(Артикул) Тогда
            ПустыхПодряд = ПустыхПодряд + 1;
            Если ПустыхПодряд >= 5 Тогда
                Прервать;
            КонецЕсли;
            Продолжить;
        КонецЕсли;
        ПустыхПодряд = 0;
        Если НРег(Артикул) = "итого" Тогда
            Прервать;
        КонецЕсли;

        НоваяСтрока = Товары.Добавить();
        НоваяСтрока.Артикул = Артикул;
        НоваяСтрока.Наименование = СокрЛП(ТабДок.Область(Стр, Колонки["наименование"]).Текст);
        НоваяСтрока.Цена = ТекстВЧисло(ТабДок.Область(Стр, Колонки["цена"]).Текст);
        НоваяСтрока.Количество = ТекстВЧисло(ТабДок.Область(Стр, Колонки["количество"]).Текст);
    КонецЦикла;
КонецПроцедуры

Что делает код по шагам:

  1. Находит номера колонок по заголовкам первой строки.
  2. Прерывает загрузку с понятным сообщением, если обязательной колонки нет.
  3. Идёт по строкам со второй, пропуская пустые.
  4. Останавливается на пяти пустых строках подряд или на строке «Итого».
  5. Приводит цену и количество к числу.

Чтение через COM-объект Excel

Когда нужен конкретный лист по имени или значения формул, а встроенного чтения не хватает, используют Excel напрямую. Работает только в Windows и только там, где Excel установлен — у пользователя или на сервере.

Excel = Новый COMОбъект("Excel.Application");
Книга = Excel.Workbooks.Open(ИмяФайла);
Лист = Книга.Worksheets(1);
Строк = Лист.UsedRange.Rows.Count;
Для Стр = 2 По Строк Цикл
    Артикул = Лист.Cells(Стр, 1).Value;
КонецЦикла;
Книга.Close(Ложь);
Excel.Quit();

Всегда закрывайте книгу и вызывайте Quit, в том числе в ветке Исключение. Иначе процессы EXCEL.EXE копятся в памяти, и через пару десятков загрузок сервер начинает тормозить.

Частые вопросы

Можно ли прочитать второй лист книги Excel методом Прочитать?
Встроенный метод читает первый лист. Для другого листа пересохраните его отдельным файлом или используйте COM-объект Excel и обращение Worksheets("Имя").
Чем отличается Текст от Значения ячейки?
Текст — строка в том виде, как её видно на экране, с форматированием. Значение хранит число, дату или булево, если документ прочитан в режиме Значение.
Работает ли чтение Excel в веб-клиенте?
Сам разбор выполняйте на сервере. С клиента передайте только двоичные данные файла через временное хранилище — это работает и в тонком, и в веб-клиенте.
Как прочитать файл CSV в табличный документ?
CSV методом Прочитать() табличного документа не загружается. Используйте ЧтениеТекста или ТекстовыйДокумент и разбирайте строки через СтрРазделить по разделителю.
Почему загрузка 20 тысяч строк идёт несколько минут?
Каждое обращение к Область() затратно. Перенесите данные в таблицу значений через построитель запроса и работайте уже с ней.