Чтение табличного документа в 1С 8.3: ячейки, области, Excel и двоичные данные
Содержание
Чтобы прочитать табличный документ в 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;
Если НРег(Артикул) = "итого" Тогда
Прервать;
КонецЕсли;
НоваяСтрока = Товары.Добавить();
НоваяСтрока.Артикул = Артикул;
НоваяСтрока.Наименование = СокрЛП(ТабДок.Область(Стр, Колонки["наименование"]).Текст);
НоваяСтрока.Цена = ТекстВЧисло(ТабДок.Область(Стр, Колонки["цена"]).Текст);
НоваяСтрока.Количество = ТекстВЧисло(ТабДок.Область(Стр, Колонки["количество"]).Текст);
КонецЦикла;
КонецПроцедуры
Что делает код по шагам:
- Находит номера колонок по заголовкам первой строки.
- Прерывает загрузку с понятным сообщением, если обязательной колонки нет.
- Идёт по строкам со второй, пропуская пустые.
- Останавливается на пяти пустых строках подряд или на строке «Итого».
- Приводит цену и количество к числу.
Чтение через 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 методом Прочитать?
Worksheets("Имя").Чем отличается Текст от Значения ячейки?
Текст — строка в том виде, как её видно на экране, с форматированием. Значение хранит число, дату или булево, если документ прочитан в режиме Значение.Работает ли чтение Excel в веб-клиенте?
Как прочитать файл CSV в табличный документ?
Прочитать() табличного документа не загружается. Используйте ЧтениеТекста или ТекстовыйДокумент и разбирайте строки через СтрРазделить по разделителю.Почему загрузка 20 тысяч строк идёт несколько минут?
Область() затратно. Перенесите данные в таблицу значений через построитель запроса и работайте уже с ней.