К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как перебрать табличный документ в 1С

Как перебрать табличный документ 1С в цикле: чтение ячеек, обход областей, работа с ТекущаяОбласть, примеры кода на встроенном языке и типичные ошибки разработчиков.

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

Основной способ перебора — цикл по номерам строк и колонок с обращением к методу Область() и чтением свойства Текст или Значение (через расшифровку для параметров). Границы документа определяют свойства ВысотаТаблицы и ШиринаТаблицы. Ниже разобраны все рабочие сценарии: от простого двойного цикла до обхода именованных областей и загрузки данных в таблицу значений.

Чем табличный документ отличается от таблицы значений

Табличный документ (объект ТабличныйДокумент) — это аналог листа электронной таблицы: у него есть строки, колонки, объединённые ячейки, форматирование и параметры. Обратиться к данным «по имени колонки», как в таблице значений, нельзя — только по координатам или по имени области. Это главное отличие, из-за которого начинающие разработчики путаются.

Таблица значений хранит типизированные данные и предназначена для вычислений, а табличный документ — для отображения и печати. Поэтому типовой приём выглядит так: перебрать табличный документ, построчно скопировать данные в таблицу значений и дальше работать уже с ней — искать, сортировать, сворачивать.

Базовый перебор всех ячеек в цикле

Универсальный вариант — вложенный цикл «Для». Внешний цикл идёт по строкам, внутренний — по колонкам. Общее число строк возвращает свойство ВысотаТаблицы, число колонок — ШиринаТаблицы. Если документ пустой, оба свойства равны нулю, и тело цикла просто не выполнится — отдельная проверка не обязательна, но полезна для понятного сообщения пользователю.

Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл

Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл

ТекстЯчейки = ТабДок.Область(НомерСтроки, НомерКолонки).Текст;

Если Не ПустаяСтрока(ТекстЯчейки) Тогда

// обработка значения

КонецЕсли;

КонецЦикла;

КонецЦикла;

Метод Область() с двумя числовыми параметрами возвращает одну ячейку. Свойство Текст всегда возвращает строку — то, что видно на экране. Если в ячейке записана дата или число, вы получите их отформатированное представление, и для обратного преобразования придётся учитывать формат. Это частая причина ошибок при загрузке данных.

Как получить типизированные значения, а не текст

Когда табличный документ сформирован программно через макет с параметрами, исходные значения доступны через расшифровку. У ячейки-параметра свойство Расшифровка хранит переданное значение с исходным типом. Это надёжнее, чем парсить текст.

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

Функция СтрокаВЧисло(Стр)

Попытка

Возврат Число(СтрЗаменить(СтрЗаменить(Стр, " ", ""), Символ(160), ""));

Исключение

Возврат Неопределено;

КонецПопытки;

КонецФункции

Типичные ошибки
01
Парсинг чисел без удаления неразрывных пробелов (Символ(160)) — Число() выбрасывает исключение на отформатированных строках.
02
Обращение к Область() с нулевым или отрицательным индексом — нумерация строк и колонок начинается с 1.
03
Чтение только свойства Текст, когда в ячейке доступна типизированная расшифровка — теряется исходный тип данных.

Перебор именованных областей макета

Если документ построен по макету, удобнее работать не с «голыми» координатами, а с именованными областями. Имена областей макета сохраняются в результирующем документе, и их можно получить методом Область("ИмяОбласти"). У области есть свойства Верх, Низ, Лево, Право — координаты границ, по которым легко организовать цикл только внутри нужного блока.

ОбластьДанные = ТабДок.Область("СтрокаДанных");

Для НомерСтроки = ОбластьДанные.Верх По ОбластьДанные.Низ Цикл

Наименование = ТабДок.Область(НомерСтроки, 2).Текст;

КонецЦикла;

При многократном выводе одной и той же области макета (типовая ситуация для строк табличной части) в документе окажется много областей с одинаковым именем. Метод Область("Имя") вернёт первую найденную. Чтобы перебрать все, используют метод НайтиТекст() или отслеживают координаты вывода самостоятельно: запоминают ВысотаТаблицы до и после каждого Вывести().

При выводе строк макета в цикле сохраняйте границы каждой строки: Верх = ТабДок.ВысотаТаблицы + 1 перед Вывести(), Низ = ТабДок.ВысотаТаблицы после. Так получите точную карту документа без поиска по именам областей.
ПЗ
Практическое замечание

Загрузка табличного документа в таблицу значений

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

Порядок действий
  1. 1
    Прочитайте файл в табличный документ: ТабДок.Прочитать(ИмяФайла).
  2. 2
    Проверьте, что ВысотаТаблицы больше 1 — есть данные помимо шапки.
  3. 3
    Создайте таблицу значений и добавьте колонки по ячейкам первой строки.
  4. 4
    Переберите строки со второй по последнюю, заполняя новые строки таблицы.
  5. 5
    Пропускайте полностью пустые строки, чтобы не тащить мусор в дальнейшую обработку.
  6. 6
    Проверьте результат: количество строк и выборочные значения в нескольких колонках.

Имена колонок из шапки нужно нормализовать: убрать пробелы и недопустимые символы, потому что имя колонки таблицы значений должно быть допустимым идентификатором. Проще всего формировать служебные имена вида «Колонка1», «Колонка2», а соответствие с человекочитаемыми заголовками хранить отдельно.

ТЗ = Новый ТаблицаЗначений;

Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл

ТЗ.Колонки.Добавить("Колонка" + Кол);

КонецЦикла;

Для Стр = 2 По ТабДок.ВысотаТаблицы Цикл

НоваяСтрока = ТЗ.Добавить();

Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл

НоваяСтрока[Кол - 1] = СокрЛП(ТабДок.Область(Стр, Кол).Текст);

КонецЦикла;

КонецЦикла;

Производительность и ограничения

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

Дополнительные ограничения: объединённые ячейки возвращают текст только в левой верхней ячейке объединения, остальные будут пустыми — это нужно учитывать при разборе макетов с шапками. Скрытые строки и колонки при переборе по координатам читаются так же, как видимые, что иногда даёт неожиданные данные. Табличный документ целиком доступен только на сервере или в толстом клиенте; в тонком клиенте работа с ним ограничена.

Контрольные точки

Как проверить результат

Количество строк в итоговой таблице значений
Норма

Совпадает с числом непустых строк данных в документе

Тревожный признак

Строк больше или меньше — значит, съехала граница цикла или не отфильтрованы пустые строки

Значения числовых колонок
Норма

Числа распознаны как числа, итоги сходятся с источником

Тревожный признак

Числа остались строками или обрезаны — проблема с форматом и пробелами

Данные из объединённых ячеек
Норма

Значения взяты из левой верхней ячейки объединения

Тревожный признак

Пустые значения там, где в документе текст виден

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

Как узнать, пустой ли табличный документ?

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

Можно ли перебрать табличный документ через «Для Каждого»?

Нет, табличный документ не является коллекцией — прямой итератор для него недоступен. Перебор выполняется только по координатам через цикл «Для» либо через поиск методом НайтиТекст().

Как найти ячейку с нужным значением без полного перебора?

Используйте метод НайтиТекст(СтрокаПоиска, ОбластьПоиска, ИскатьПоСтрокам, ЦелаяЯчейка) — он возвращает область первой найденной ячейки. Повторный вызов с указанием области после найденной позиции позволяет найти следующие вхождения.

Почему Область(Строка, Колонка) возвращает пустой текст, хотя в документе значение есть?

Чаще всего ячейка входит в объединённую область, а текст хранится в её левой верхней ячейке. Также проверьте, не смещены ли координаты: нумерация начинается с единицы, а шапка и итоговые строки сдвигают расположение данных.

Как перебрать табличный документ на управляемой форме?

Реквизит формы типа ТабличныйДокумент доступен в серверных процедурах. В клиентском контексте чтение ячеек ограничено, поэтому перебор выносят в серверную процедуру «&НаСервере» и передают туда данные или имя реквизита.

Что быстрее: перебор табличного документа или чтение Excel напрямую?

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

Итог

Что важно запомнить

Табличный документ перебирают вложенным циклом по строкам и колонкам в пределах ВысотаТаблицы и ШиринаТаблицы, читая ячейки через Область(). Свойство Текст возвращает строку — для чисел и дат нужно преобразование. Для дальнейшей обработки данные удобно переносить в таблицу значений, а на больших документах заранее оценивать производительность.