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

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

Как перебрать колонки таблицы значений в 1С 8

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

Таблица значений в 1С 8 — универсальная структура для промежуточного хранения и обработки данных: в неё выгружаются результаты запросов, табличные части документов, данные из файлов. Работа с такой таблицей почти всегда сводится к двум операциям: перебору строк и перебору колонок. Если со строками вопросов обычно не возникает, то обход колонок вызывает затруднения, потому что колонки — это отдельная коллекция со своими свойствами и методами.

Коллекция колонок доступна через свойство Колонки объекта «ТаблицаЗначений». Каждый элемент этой коллекции — объект «КолонкаТаблицыЗначений» с полями Имя, ТипЗначения, Заголовок, Ширина и другими. Перебирая коллекцию, можно динамически определить структуру таблицы, построить универсальную выгрузку или обработать ячейки без жёсткой привязки к именам колонок.

Как устроена коллекция колонок таблицы значений

Коллекция ТЗ.Колонки — это объект «КоллекцияКолонокТаблицыЗначений». Она поддерживает обход в цикле, обращение по индексу и по имени, а также методы добавления, удаления и поиска. Порядок колонок в коллекции соответствует порядку их добавления в таблицу, и именно в этом порядке они будут перебираться.

Каждый элемент коллекции описывает одну колонку. На практике чаще всего используются три свойства: Имя — строковый идентификатор, по которому обращаются к значениям; ТипЗначения — описание типов, допустимых в ячейках; Заголовок — текст, отображаемый пользователю в табличном поле. Если заголовок не задан явно, он совпадает с именем.

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

Базовый перебор колонок в цикле

Самый простой сценарий — вывести имена всех колонок таблицы. Для этого достаточно цикла «Для Каждого»:

Для Каждого Колонка Из ТЗ.Колонки Цикл

Сообщить(Колонка.Имя + " — " + Колонка.ТипЗначения);

КонецЦикла;

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

Если нужен порядковый номер колонки, используют индексный обход через метод Количество():

Для Индекс = 0 По ТЗ.Колонки.Количество() - 1 Цикл

Колонка = ТЗ.Колонки[Индекс];

Сообщить("Колонка №" + Индекс + ": " + Колонка.Имя);

КонецЦикла;

Выбор между «Для Каждого» и индексным циклом зависит от задачи. «Для Каждого» короче и читается легче; индексный цикл нужен, когда требуется номер колонки, пропуск элементов с шагом или обход в обратном порядке.

Перебор ячеек: вложенные циклы по строкам и колонкам

Чтобы обойти все ячейки таблицы, циклы вкладывают: внешний перебирает строки, внутренний — колонки. Значение ячейки получают через оператор квадратных скобок по имени колонки:

Для Каждого Строка Из ТЗ Цикл

Для Каждого Колонка Из ТЗ.Колонки Цикл

Значение = Строка[Колонка.Имя];

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

КонецЦикла;

КонецЦикла;

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

КоличествоКолонок = ТЗ.Колонки.Количество();

Для Каждого Строка Из ТЗ Цикл

Для Индекс = 0 По КоличествоКолонок - 1 Цикл

Значение = Строка[Индекс];

КонецЦикла;

КонецЦикла;

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

bsl
Для Каждого Строка Из ТЗ Цикл
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        Сообщить(Колонка.Имя + " = " + Строка[Колонка.Имя]);
    КонецЦикла;
КонецЦикла;

Обращение к колонке по имени и проверка её существования

Когда нужна конкретная колонка, а не полный перебор, используют метод Найти(). Он возвращает объект колонки или Неопределено, если колонки с таким именем нет:

КолонкаСумма = ТЗ.Колонки.Найти("Сумма");

Если КолонкаСумма <> Неопределено Тогда

Итог = ТЗ.Итог("Сумма");

Иначе

Сообщить("Колонка ""Сумма"" отсутствует в таблице");

КонецЕсли;

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

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

Типичные ошибки
01
Обращение Строка.ИмяКолонки без проверки существования колонки — при изменении структуры источника код падает с ошибкой; используйте Колонки.Найти()
02
Цикл «Для Индекс = 1 По Количество()» — индексация начинается с нуля, поэтому первая колонка пропускается, а последняя вызывает ошибку выхода за границы
03
Изменение коллекции колонок (добавление, удаление) внутри цикла её перебора — порядок обхода нарушается, элементы пропускаются
04
Путаница между перебором колонок и перебором строк: ТЗ.Колонки — это структура, а сами данные лежат в строках таблицы

Практические сценарии использования перебора колонок

Универсальная выгрузка в табличный документ

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

Приведение типов и очистка данных

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

Сравнение структур двух таблиц

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

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

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

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

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

Ещё одно ограничение: таблица значений недоступна для прямой передачи между клиентом и сервером в управляемых формах. На клиенте её аналогом служит «ДанныеФормыКоллекция», у которой коллекция колонок как самостоятельный объект отсутствует — структуру там определяют по реквизитам формы.

Сравнение способов обхода

Для Каждого Колонка Из ТЗ.Колонки

Универсальный читаемый вариант; подходит для большинства задач анализа структуры и обработки ячеек

Индексный цикл по ТЗ.Колонки

Нужен, когда важен номер колонки или обход в произвольном порядке; требует аккуратности с нулевой базой индексов

Прямое обращение Строка.ИмяКолонки

Самый быстрый и наглядный способ, но только при заранее известной и гарантированной структуре таблицы

Запрос к таблице значений

Оптимален для агрегации и фильтрации больших объёмов; избыточен для простого перебора ячеек

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

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

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

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

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

Число обработанных ячеек
Норма

Равно произведению ТЗ.Количество() на ТЗ.Колонки.Количество()

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

Меньше ожидаемого — пропущены колонки или строки, проверьте границы циклов

Первая колонка в выводе
Норма

Присутствует в результате обработки

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

Отсутствует — вероятно, цикл начат с индекса 1 вместо 0

Поведение на пустой таблице
Норма

Циклы завершаются сразу, ошибок нет

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

Ошибка обращения к элементу — нет проверки на пустую коллекцию

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

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

Обратитесь к коллекции по индексу: ИмяПервой = ТЗ.Колонки[0].Имя. Перед этим убедитесь, что колонки есть: ТЗ.Колонки.Количество() > 0, иначе обращение к нулевому элементу вызовет ошибку.

Можно ли перебрать колонки без цикла?

Для отдельных задач — да. Метод ТЗ.Колонки.Найти("Имя") возвращает конкретную колонку, а ТЗ.Итог("Имя") считает сумму без явного перебора. Но получить список всех имён или обработать каждую ячейку без цикла невозможно.

Как перебрать колонки и изменить значения ячеек?

Используйте вложенные циклы и присваивайте значение через квадратные скобки: Строка[Колонка.Имя] = НовоеЗначение. Запись через точку (Строка.ИмяКолонки = ...) тоже работает, но только когда имя колонки известно на момент написания кода.

Почему возникает ошибка «Поле объекта не обнаружено» при обращении к колонке?

Колонки с указанным именем нет в таблице. Причины: опечатка в имени, изменение структуры источника данных, обращение к таблице до добавления колонок. Перед обращением проверяйте наличие через ТЗ.Колонки.Найти("Имя").

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

У табличной части нет коллекции «Колонки» в явном виде. Структуру получают через метаданные: Метаданные.Документы.РеализацияТоваров.ТабличныеЧасти.Товары.Реквизиты — эту коллекцию можно перебрать аналогично. Альтернатива — выгрузить табличную часть в таблицу значений методом Выгрузить() и работать с ней.

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

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

Итог

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

Колонки таблицы значений перебираются через коллекцию ТЗ.Колонки циклом «Для Каждого» или по индексу с нуля. Значение ячейки читается как Строка[Колонка.Имя] или Строка[Индекс]. Перед обращением к колонке по имени проверяйте её существование методом Найти(), а для больших таблиц предпочитайте встроенные методы и обращение по индексу.