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

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

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

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

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

Свойство Колонки возвращает объект КоллекцияКолонокТаблицыЗначений. Это не массив и не список значений, а отдельная коллекция со своими методами: Найти(), Добавить(), Вставить(), Индекс(), Количество(). Каждый элемент коллекции — объект КолонкаТаблицыЗначений с полезными свойствами: Имя, ТипЗначения, Заголовок, Ширина.

Ниже разобраны основные сценарии: простой перебор колонок, получение имён списком, поиск конкретной колонки, определение типов данных и копирование структуры без строк. Все примеры работают как на сервере, так и на клиенте в толстом и тонком клиенте, если таблица значений там доступна.

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

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

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

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

Простой перебор колонок в цикле

Базовый способ получить все колонки — цикл Для Каждого по коллекции. Внутри цикла доступны все свойства текущей колонки:

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

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

КонецЦикла;

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

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

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

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

КонецЦикла;

Оба варианта дают одинаковый результат. Цикл Для Каждого читается проще, а индексный цикл нужен, когда важна позиция колонки или требуется параллельный обход другой коллекции.

Порядок действий
  1. 1
    Убедитесь, что переменная содержит объект ТаблицаЗначений, а не результат запроса или дерево значений
  2. 2
    Обратитесь к свойству ТЗ.Колонки — это коллекция колонок
  3. 3
    Переберите коллекцию циклом «Для Каждого» и читайте Колонка.Имя, Колонка.ТипЗначения
  4. 4
    Проверьте результат через Сообщить() или отладчик, остановившись внутри цикла

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

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

ИменаКолонок = "";

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

ИменаКолонок = ИменаКолонок + ?(ИменаКолонок = "", "", ", ") + Колонка.Имя;

КонецЦикла;

Альтернатива — собрать имена в массив и соединить функцией СтрСоединить() (в старых версиях платформы её нет, там используют конкатенацию в цикле):

МассивИмен = Новый Массив;

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

МассивИмен.Добавить(Колонка.Имя);

КонецЦикла;

ИменаКолонок = СтрСоединить(МассивИмен, ", ");

Полученную строку удобно передавать в ТЗ.Свернуть(ИменаКолонок) или ТЗ.Скопировать(, ИменаКолонок). Учтите ограничение: в этих методах имена разделяются запятыми без проблем, но лишние пробелы вокруг имён допустимы — платформа их обрабатывает корректно.

bsl
ИменаКолонок = "";
Для Каждого Колонка Из ТЗ.Колонки Цикл
    ИменаКолонок = ИменаКолонок + ?(ИменаКолонок = "", "", ", ") + Колонка.Имя;
КонецЦикла;

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

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

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

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

ВызватьИсключение "В таблице нет колонки ""Сумма""";

КонецЕсли;

Метод Найти() возвращает объект колонки или Неопределено, если колонки с таким именем нет. Поиск нечувствителен к регистру: Найти("сумма") и Найти("СУММА") найдут колонку «Сумма». Это соответствует общему правилу встроенного языка — идентификаторы в 1С регистронезависимы.

Если нужен только индекс колонки (например, для метода Вставить()), используйте связку: сначала Найти(), затем ТЗ.Колонки.Индекс(Колонка). Прямого метода «ИндексПоИмени» у коллекции нет.

Как узнать тип данных колонки

Свойство ТипЗначения возвращает объект ОписаниеТипов. Чтобы узнать конкретные типы, используйте метод Типы(), который возвращает массив:

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

Типы = Колонка.ТипЗначения.Типы();

Для Каждого Тип Из Типы Цикл

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

КонецЦикла;

КонецЦикла;

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

Для проверки конкретного типа удобен метод СодержитТип(): Колонка.ТипЗначения.СодержитТип(Тип("Число")) вернёт булево. Также через КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты можно узнать длину, точность и состав даты.

Копирование структуры колонок без данных

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

ТЗПриемник = ТЗИсточник.СкопироватьКолонки();

Метод копирует имена, типы, заголовки и ширину всех колонок, но не переносит строки. Если нужна только часть колонок, передайте их имена строкой через запятую первым параметром: ТЗИсточник.СкопироватьКолонки("Номенклатура, Количество").

Ручное копирование через цикл оправдано, когда структуру нужно изменить на лету — например, сузить тип колонки или переименовать её. В этом случае перебирайте колонки источника и вызывайте ТЗПриемник.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения, Колонка.Заголовок) с нужными правками.

Сравнение вариантов

СкопироватьКолонки()

Быстрый способ продублировать структуру целиком или частично. Не подходит, если нужно изменить типы или имена колонок.

Цикл + Колонки.Добавить()

Полный контроль над структурой приемника: можно менять имена, типы, пропускать колонки. Требует больше кода.

Выгрузить() из результата запроса

Если таблица строится запросом, структура формируется автоматически по полям выборки — вручную колонки описывать не нужно.

Особенности для таблиц на форме и частые ошибки

Если таблица значений является реквизитом управляемой формы, обращение ТЗ.Колонки напрямую недоступно: реквизит формы имеет тип ДанныеФормыКоллекция, а не ТаблицаЗначений. Перед работой с колонками преобразуйте данные: ТЗ = РеквизитФормыВЗначение("ТаблицаНаФорме") — после этого работайте с колонками обычным способом. Для обратного переноса используйте ЗначениеВРеквизитФормы().

Ещё одна ловушка — попытка получить колонки у результата запроса. У объекта РезультатЗапроса тоже есть свойство Колонки, но это коллекция другого типа (КолонкиРезультатаЗапроса) с похожим, но не идентичным составом свойств. Если нужна именно таблица значений, сначала выполните ТЗ = РезультатЗапроса.Выгрузить().

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

Типичные ошибки
01
Обращение к ТЗ.Колонки у реквизита формы без РеквизитФормыВЗначение — возникает ошибка «Поле объекта не обнаружено»
02
Обращение к строке таблицы по имени колонки без проверки Найти() — падение кода, если структура таблицы изменилась
03
Поиск колонки по заголовку вместо имени — Найти() возвращает Неопределено, хотя колонка визуально существует
04
Изменение структуры таблицы при наличии индексов по удаляемым колонкам — ошибка выполнения
Контрольные точки

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

Количество колонок
Норма

ТЗ.Колонки.Количество() совпадает с ожидаемым числом

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

Колонок больше или меньше — проверьте, откуда таблица получена

Имена колонок
Норма

Каждая нужная колонка находится через Найти() и возвращает объект

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

Найти() возвращает Неопределено — имя указано неверно или колонка не создана

Типы данных
Норма

Колонка.ТипЗначения содержит ожидаемые типы

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

Массив типов пустой или содержит лишние типы — колонка добавлена без описания типов

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

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

Реквизит формы с таблицей — это не ТаблицаЗначений, а ДанныеФормыКоллекция. Сначала выполните ТЗ = РеквизитФормыВЗначение("ИмяРеквизита"), затем работайте с ТЗ.Колонки как обычно. После изменений верните данные через ЗначениеВРеквизитФормы(ТЗ, "ИмяРеквизита").

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

Готового метода «вернуть список имён» у коллекции нет. Самый короткий путь — собрать имена в массив циклом и соединить СтрСоединить(). Если таблица получена из запроса, можно обойти колонки результата запроса до выгрузки, но цикл всё равно потребуется.

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

Это разные типы коллекций. У результата запроса элементы — КолонкаРезультатаЗапроса, у таблицы значений — КолонкаТаблицыЗначений. Состав свойств похож (Имя, ТипЗначения), но методы коллекций различаются. Для единообразия удобнее сразу выгрузить результат: ТЗ = РезультатЗапроса.Выгрузить().

Как узнать, есть ли в таблице колонка с нужным именем?

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

Как скопировать только структуру таблицы без строк?

Вызовите ТЗПриемник = ТЗИсточник.СкопироватьКолонки() — будут перенесены имена, типы, заголовки и ширина всех колонок, но ни одной строки. Для частичного копирования передайте имена нужных колонок строкой через запятую.

Почему Колонка.ТипЗначения возвращает пустой список типов?

Если колонка добавлена без второго параметра в Колонки.Добавить(), она принимает значения любого типа, и массив Типы() пуст. Это не ошибка, но если нужна строгая типизация, пересоздайте колонку с явным описанием типов через ОписаниеТипов.

Итог

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

Колонки таблицы значений доступны через ТЗ.Колонки: перебор циклом даёт имена и типы, Найти() проверяет существование колонки, СкопироватьКолонки() дублирует структуру без данных. На управляемой форме сначала преобразуйте реквизит через РеквизитФормыВЗначение.