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

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

Как обойти ячейки табличного документа в 1С

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

Табличный документ в 1С (объект ТабличныйДокумент) используется для печатных форм, отчётов и загрузки данных из файлов Excel. Частая задача разработчика — программно пройтись по всем ячейкам: найти нужное значение, выгрузить содержимое в таблицу значений или проверить заполнение. Для этого применяются вложенные циклы по строкам и колонкам с обращением к области R1C1-адресации.

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

Базовый обход всех ячеек двойным циклом

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

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

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

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

ТекстЯчейки = ОбластьЯчейки.Текст;

// обработка текста ячейки

КонецЦикла;

КонецЦикла;

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

Если документ содержит тысячи строк, полный обход может занять заметное время, потому что каждый вызов Область() — это обращение к объекту. Для больших таблиц имеет смысл ограничить диапазон известными границами данных, например начинать со строки после шапки.

Чтение значений: Текст, Параметр и Значение

У области ячейки есть три разных свойства с содержимым, и их путание — типичная ошибка. Текст — это отображаемая строка, то, что пользователь видит на экране. Параметр — имя параметра, если ячейка является параметром макета (используется при заполнении по шаблону). Значение — типизированное значение, если ячейка содержит не строку, а, например, число или дату.

Для табличных документов, загруженных из Excel или сформированных выводом областей макета, чаще всего заполнено именно свойство Текст. Если нужно получить число из текста, применяйте функции преобразования с обработкой ошибок, потому что в ячейке могут быть пробелы, разделители разрядов или нечисловые символы.

Поиск ячеек по значению без полного обхода

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

НайденнаяОбласть = ТабДок.НайтиТекст("Артикул", , Истина, Истина);

Если НайденнаяОбласть <> Неопределено Тогда

СтрокаЗаголовка = НайденнаяОбласть.Верх;

КолонкаАртикула = НайденнаяОбласть.Лево;

КонецЕсли;

Такой приём незаменим при разборе печатных форм и файлов с «плавающей» структурой: сначала ищется ячейка заголовка колонки, затем от её позиции читаются данные вниз по строкам. Это устойчивее, чем жёсткая привязка к номерам колонок, которые меняются при редактировании макета.

Порядок действий при разборе таблицы с заголовком
  1. 1
    Найдите ячейку заголовка через НайтиТекст() и запомните её строку и колонку
  2. 2
    Определите последнюю строку данных через ВысотаТаблицы
  3. 3
    Пройдите циклом от строки под заголовком до конца, читая ТабДок.Область(Строка, Колонка).Текст
  4. 4
    Пропускайте пустые строки, проверяя ПустаяСтрока(Текст)
  5. 5
    Проверьте результат: количество прочитанных строк должно совпадать с ожидаемым числом записей

Обход областей и объединённых ячеек

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

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

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

Если ОбластьЯчейки.Лево <> НомерКолонки

Или ОбластьЯчейки.Верх <> НомерСтроки Тогда

Продолжить; // уже обработана как часть объединённой области

КонецЕсли;

Типичные ошибки
01
Начало цикла с нуля вместо единицы — первая строка и колонка пропускаются, а лишняя итерация читает пустоту
02
Чтение только свойства Текст там, где данные лежат в Значение, — результат пустой, хотя ячейка визуально заполнена
03
Игнорирование объединённых ячеек — одно значение попадает в результат несколько раз
04
Жёсткая привязка к номерам колонок вместо поиска заголовков — код ломается при любом изменении макета

Выгрузка содержимого в таблицу значений

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

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

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

ИмяКолонки = "Колонка" + Колонка;

ТЗ.Колонки.Добавить(ИмяКолонки);

КонецЦикла;

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

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

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

НоваяСтрока[Колонка - 1] =

ТабДок.Область(Строка, Колонка).Текст;

КонецЦикла;

КонецЦикла;

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

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

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

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

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

Маршрут решения

Как выбрать способ обхода

Нужно найти одно конкретное значение или заголовокИспользуйте НайтиТекст() вместо полного цикла
Нужно выгрузить весь документ в таблицу значенийДвойной цикл по строкам и колонкам с чтением Область().Текст
Документ содержит объединённые ячейкиДобавьте проверку границ области, чтобы не читать дубли
Структура колонок может менятьсяСначала найдите заголовки по тексту, затем читайте данные по найденным позициям

Как проверить корректность обхода

После написания кода обязательно проверьте результат на контрольном примере. Самая простая проверка — сравнить количество обработанных строк с ожидаемым и вывести несколько значений через Сообщить() или в журнал регистрации. Для таблиц значений удобно временно вывести результат в табличное поле формы.

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

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

Количество строк результата
Норма

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

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

Больше или меньше — сбиты границы цикла или лишние пустые строки

Значения первой и последней строки
Норма

Соответствуют видимым данным документа

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

Сдвиг на строку — ошибка в начальном номере строки

Повторяющиеся значения
Норма

Каждое значение встречается ожидаемое число раз

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

Дубли из объединённых ячеек — нет проверки границ области

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

Как определить, что ячейка пустая?

Проверьте текст ячейки функцией ПустаяСтрока(ТабДок.Область(Строка, Колонка).Текст). Она корректно обрабатывает и пустую строку, и строку из одних пробелов. Если данные хранятся в свойстве Значение, дополнительно проверяйте его на Неопределено.

Можно ли обойти только видимую часть документа?

Нет, программный обход работает со всем документом в памяти и не зависит от того, что видно на экране. Понятие «видимая область» относится к интерфейсу, а не к объекту ТабличныйДокумент. Ограничивать обход нужно явно заданными диапазонами строк и колонок.

Как обойти ячейки только одной колонки?

Используйте один цикл по строкам с фиксированным номером колонки: ТабДок.Область(НомерСтроки, НужнаяКолонка).Текст. Это заметно быстрее полного обхода, когда нужен один столбец данных.

Почему НайтиТекст не находит значение, которое видно в документе?

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

Работает ли обход ячеек на тонком клиенте и в веб-клиенте?

Объект ТабличныйДокумент и метод Область доступны на толстом и тонком клиенте, но с ограничениями по передаче между клиентом и сервером. Для массовой обработки надёжнее формировать и обходить документ в серверной процедуре, а на клиент возвращать уже готовый результат.

Итог

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

Обход ячеек строится на вложенных циклах от 1 до ВысотаТаблицы и ШиринаТаблицы с чтением Область(Строка, Колонка).Текст. Для поиска используйте НайтиТекст(), для объединённых ячеек проверяйте границы области, а границы циклов и типы данных обязательно проверяйте на контрольном примере.