Разработка и Конфигурация · 10 мин
Как обойти строки табличного документа в 1С
Как обойти строки табличного документа в 1С: цикл по областям, чтение ячеек, поиск текста, работа с группировками. Примеры кода на встроенном языке.
Табличный документ в 1С — это объект типа «ТабличныйДокумент», который используется для печатных форм, отчётов и макетов. В отличие от таблицы значений, он не имеет встроенной коллекции строк, поэтому «обойти строки» здесь означает последовательно перебирать области по номерам строк или искать нужные ячейки по содержимому. Это частая задача при разборе загруженных из Excel данных, при анализе сформированного отчёта или при программной проверке печатной формы.
Основная сложность в том, что табличный документ хранит данные не построчно, а в виде прямоугольных областей ячеек. Разработчику нужно самостоятельно определить границы данных, прочитать значения через свойство «Текст» или «Параметр» области и правильно обработать объединённые ячейки, итоговые строки и группировки. Ниже разобраны рабочие приёмы с примерами кода.
Как устроен табличный документ и почему нет прямого обхода строк
Объект «ТабличныйДокумент» представляет собой сетку ячеек, адресуемых по номеру строки и номеру колонки. Фактические размеры заполненной области доступны через свойства ВысотаТаблицы (число строк) и ШиринаТаблицы (число колонок). Именно эти значения задают границы цикла обхода.
Каждая ячейка — это область, которую можно получить методом Область(НомерСтроки, НомерКолонки). У области читаются свойства Текст (отображаемая строка) и Параметр (значение параметра, если ячейка заполнена из макета с параметрами). Для данных, выведенных из макета с параметрами, свойство «Параметр» надёжнее, так как возвращает исходное значение, а не отформатированную строку.
Базовый обход строк в цикле по номерам
Самый универсальный способ — цикл от первой строки до ВысотаТаблицы. Внутри цикла читаем нужные колонки. Типовой фрагмент выглядит так:
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
ЗначениеКолонки1 = ТабДок.Область(НомерСтроки, 1).Текст;
ЗначениеКолонки2 = ТабДок.Область(НомерСтроки, 2).Текст;
Если ПустаяСтрока(ЗначениеКолонки1) Тогда
Продолжить; // пропускаем пустые строки
КонецЕсли;
// обработка значений
КонецЦикла;Обратите внимание: нумерация строк и колонок начинается с единицы, а не с нуля. Обращение к области за пределами размеров таблицы не вызовет ошибку — вернётся пустая область, поэтому проверки на пустоту обязательны, иначе в обработку попадут «фантомные» строки.
Если документ содержит шапку и подвал (заголовки колонок, итоги), начальную и конечную строки данных лучше определять не фиксированными числами, а поиском — иначе при изменении макета обход сместится и начнёт читать служебные строки как данные.
Определение границ данных через НайтиТекст
Метод НайтиТекст(СтрокаПоиска, Начало, ИскатьПоСтрокам, ...) возвращает область с первой ячейкой, содержащей искомый текст. Это удобно для поиска начала табличной части: например, найти ячейку «Номенклатура» в шапке и начать обход со следующей строки.
ОбластьШапки = ТабДок.НайтиТекст("Номенклатура");
Если ОбластьШапки = Неопределено Тогда
ВызватьИсключение "Не найдена шапка таблицы";
КонецЕсли;
ПерваяСтрокаДанных = ОбластьШапки.Низ + 1;
Для НомерСтроки = ПерваяСтрокаДанных По ТабДок.ВысотаТаблицы Цикл
// чтение данных
КонецЦикла;Аналогично находят конец данных — по тексту «Итого» или по первой полностью пустой строке. Такой подход устойчив к изменению количества строк в шапке макета.
Обход с чтением значений параметров
Когда табличный документ сформирован из макета с параметрами (типичный случай для печатных форм), ячейки хранят не только текст, но и исходные значения. Чтение через Параметр избавляет от обратного преобразования строк в числа и даты:
Ячейка = ТабДок.Область(НомерСтроки, 3);
Если Ячейка.СодержитЗначение Тогда
Значение = Ячейка.Значение; // типизированное значение
Иначе
Значение = Ячейка.Текст; // только текст
КонецЕсли;Свойство СодержитЗначение показывает, хранит ли ячейка типизированное значение. Это особенно полезно при разборе документов, загруженных из внешних источников через Прочитать() из файла Excel: там часть ячеек может содержать значения, а часть — только текст.
Обход строк в отчётах на СКД через расшифровку
Если нужно обойти строки отчёта, сформированного системой компоновки данных, прямой перебор ячеек табличного документа — худший вариант: данные там перемешаны с оформлением и итогами. Правильнее работать с коллекцией элементов расшифровки (ДанныеРасшифровки), где каждая строка отчёта представлена структурированным элементом с полями.
Альтернатива — вывести результат СКД не в табличный документ, а в таблицу значений через ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений. Тогда обход становится стандартным циклом Для Каждого Строка Из ТаблицаЗначений Цикл с доступом к колонкам по именам.
Способы обхода данных табличного документа
Универсальный, работает с любым документом, включая загруженные из Excel. Требует ручного определения границ данных и обработки пустых строк.
Устойчив к изменению шапки макета. Не подходит, если якорный текст может встречаться в данных.
Самый надёжный для отчётов: типизированные колонки и именованный доступ. Требует перестройки кода вывода результата.
Подходит для уже сформированных отчётов, где нужны значения полей строк. Сложнее в реализации и зависит от структуры настроек СКД.
Загрузка данных из Excel и типичные проблемы обхода
Частый сценарий — загрузка прайса или ведомости из Excel: файл открывают методом ТабДок.Прочитать(ИмяФайла), а затем обходят строки. Здесь подстерегает несколько ловушек: объединённые ячейки (текст хранится только в левой верхней ячейке объединения), скрытые строки, числа, прочитанные как текст, и строки итогов внутри данных.
Для объединённых областей проверяйте свойство ОбъединеннаяОбласть или читайте текст с учётом того, что у «подчинённых» ячеек он пуст. Числа, прочитанные как текст, преобразуйте через Число() с предварительной очисткой от неразрывных пробелов и разделителей разрядов, иначе получите ошибку преобразования или ноль.
Проверка результата обхода
После реализации обхода убедитесь, что обработаны именно те строки, что ожидались. Минимальный контроль — подсчёт обработанных строк и сверка с количеством строк данных в исходном документе. Полезно также выводить в журнал первую и последнюю обработанную строки с их содержимым.
Как проверить результат
Совпадает с числом строк данных в документе
Меньше или больше — смещены границы обхода
Числа имеют тип Число, даты — тип Дата
Всё прочитано как строки — данные читались через Текст
Содержит реальные данные
Содержит заголовок колонки — шапка не пропущена
Отфильтрованы проверками
Попадают в обработку и дают лишние записи
Для отладки удобно временно выводить номер строки и содержимое ключевых ячеек через Сообщить() — это быстро показывает, где обход сбивается: на шапке, на объединённых ячейках или на итогах.
Часто задаваемые вопросы
Как узнать количество строк в табличном документе?
Используйте свойство ВысотаТаблицы — оно возвращает номер последней строки, в которой есть содержимое или оформление. Аналогично ШиринаТаблицы даёт число колонок. Учтите, что пустые строки в середине документа тоже входят в этот диапазон.
Почему Область() возвращает пустой текст, хотя в ячейке есть данные?
Чаще всего ячейка входит в объединённую область, а текст хранится в её левой верхней ячейке. Вторая причина — значение выведено как параметр, и читать его нужно через свойство Параметр или Значение, а не Текст. Также проверьте, не перепутаны ли номера строки и колонки местами.
Можно ли обойти строки табличного документа конструкцией «Для Каждого»?
Нет, табличный документ не является коллекцией строк, поэтому прямой итератор недоступен. Обход выполняется числовым циклом по номерам строк от 1 до ВысотаТаблицы. Если нужен именно «Для Каждого», выведите данные в таблицу значений или прочитайте их из расшифровки СКД.
Как пропустить строки итогов и группировок при обходе?
Надёжнее всего опираться на признак в данных: например, проверять, что ключевая колонка не пуста и не содержит слов «Итого». Если документ сформирован из макета, можно помечать строки данных уникальным параметром в скрытой колонке и проверять его при обходе. Для отчётов СКД вместо фильтрации ячеек правильнее читать расшифровку.
Что быстрее: чтение ячеек по одной или через ПолучитьОбласть?
При обработке больших документов быстрее один раз получить область данных методом ПолучитьОбласть и работать с ней, чем многократно вызывать Область() у исходного документа. Однако для типовых объёмов печатных форм разница незаметна, и оптимизацию стоит делать только при реальных проблемах с производительностью.
Как обойти строки табличного документа, открытого на форме?
Точно так же: реквизит формы типа ТабличныйДокумент доступен в коде по имени, и у него есть те же свойства ВысотаТаблицы, Область и НайтиТекст. Учитывайте контекст выполнения — чтение возможно и на клиенте, и на сервере, но запись в документ на клиенте имеет ограничения в зависимости от режима.
Что важно запомнить
Строки табличного документа обходятся числовым циклом до ВысотаТаблицы с чтением ячеек через Область(). Границы данных надёжнее определять через НайтиТекст, типизированные значения читать через Параметр или Значение, а для отчётов СКД предпочтителен вывод в таблицу значений или работа с расшифровкой.