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