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

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

Как проверить наличие колонки в табличной части 1С

Способы проверить наличие колонки в табличной части 1С: через метаданные, Найти(), конструктор запроса. Примеры кода, типичные ошибки и ответы на вопросы.

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

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

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

Почему проверка обязательна перед обращением к колонке

Встроенный язык 1С не прощает обращения к несуществующим реквизитам. Строка вида СтрокаТЧ.Комментарий, где реквизита «Комментарий» нет в табличной части, вызовет исключение «Поле объекта не обнаружено (Комментарий)». В клиентском коде пользователь увидит окно ошибки, в регламентном задании — запись в журнале регистрации и прерванное выполнение.

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

Проверка занимает доли миллисекунды, а отладка падения в рабочей базе — часы. Поэтому в любом универсальном коде правило простое: сначала проверил, потом обратился.

Проверка через метаданные табличной части объекта

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

Пример проверки реквизита «СуммаНДС» в табличной части «Товары» документа:

Функция ЕстьКолонкаВТЧ(Объект, ИмяТабличнойЧасти, ИмяРеквизита)

МетаданныеОбъекта = Объект.Метаданные();

Если МетаданныеОбъекта.ТабличныеЧасти.Найти(ИмяТабличнойЧасти) = Неопределено Тогда

Возврат Ложь;

КонецЕсли;

Возврат МетаданныеОбъекта.ТабличныеЧасти[ИмяТабличнойЧасти]

.Реквизиты.Найти(ИмяРеквизита) <> Неопределено;

КонецФункции

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

Метод через метаданные работает на сервере и на клиенте (в управляемых формах — с учётом контекста), не требует обращения к данным и не зависит от того, заполнен объект или пуст. Это самый надёжный способ для объектов конфигурации.

Проверка колонки в таблице значений

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

У таблицы значений есть коллекция Колонки, у которой метод Найти() ищет колонку по имени:

ТЗ = ДокументОбъект.Товары.Выгрузить();

Если ТЗ.Колонки.Найти("Цена") = Неопределено Тогда

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

Иначе

// работаем с колонкой

Итог = ТЗ.Итог("Цена");

КонецЕсли;

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

Функция ЕстьКолонка(ТЗ, ИмяКолонки)

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

Если ВРег(Колонка.Имя) = ВРег(ИмяКолонки) Тогда

Возврат Истина;

КонецЕсли;

КонецЦикла;

Возврат Ложь;

КонецФункции

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

bsl
Если ТЗ.Колонки.Найти(ИмяКолонки) = Неопределено Тогда Возврат Ложь; КонецЕсли;

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

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

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

Проверка через свойства структуры

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

Если СтруктураСтроки.Свойство("Скидка") Тогда

// поле есть, можно читать значение

КонецЕсли;

Метод Свойство() возвращает Истина, даже если значение поля — Неопределено. Это важно: проверяется именно наличие ключа, а не заполненность значения.

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

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

Работаете с объектом конфигурации (документ, справочник)Проверяйте через Метаданные().ТабличныеЧасти[].Реквизиты.Найти()
Есть таблица значений после Выгрузить() или запросаИспользуйте ТЗ.Колонки.Найти(ИмяКолонки)
Данные в структуре или соответствииПроверяйте через метод Свойство()
Код должен работать в разных версиях конфигурацииПроверка через метаданные обязательна перед любым обращением

Проверка через Попытка/Исключение — когда оправдана

Третий подход — не проверять, а перехватывать ошибку обращения:

Попытка

Значение = СтрокаТЧ.ДополнительныйРеквизит;

Исключение

Значение = Неопределено;

КонецПопытки;

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

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

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

Как убедиться, что проверка написана правильно

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

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

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

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

Объект с существующей колонкой
Норма

Проверка вернула Истина, значение прочитано

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

Вернулось Ложь — проверьте имя реквизита на опечатки

Объект без нужной колонки
Норма

Проверка вернула Ложь, код пошёл по альтернативной ветке

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

Возникло исключение — проверка не срабатывает

Объект без табличной части
Норма

Функция вернула Ложь на первом уровне проверки

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

Ошибка обращения к табличной части — пропущен первый уровень

Производительность и оптимизация

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

Для многократных вызовов с разными объектами результаты проверки можно кэшировать в соответствии, где ключ — имя объекта метаданных плюс имя реквизита, а значение — булево. Это уместно в длительных обменах и пакетных обработках.

КэшКолонок = Новый Соответствие;

КлючКэша = ИмяДокумента + "." + ИмяТЧ + "." + ИмяРеквизита;

Результат = КэшКолонок[КлючКэша];

Если Результат = Неопределено Тогда

Результат = ЕстьКолонкаВТЧ(Объект, ИмяТЧ, ИмяРеквизита);

КэшКолонок.Вставить(КлючКэша, Результат);

КонецЕсли;

Итог

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

Для объектов конфигурации проверяйте реквизит через метаданные, для таблиц значений — через Колонки.Найти(), для структур — через Свойство(). Всегда сначала проверяйте существование самой табличной части. Попытку/Исключение оставьте для экзотических случаев. В циклах проверку выносите за пределы перебора строк.

Часто задаваемые вопросы

Можно ли проверить наличие колонки без выгрузки табличной части в таблицу значений?

Да. Для объекта конфигурации достаточно обратиться к метаданным: Объект.Метаданные().ТабличныеЧасти[ИмяТЧ].Реквизиты.Найти(ИмяРеквизита). Выгрузка в таблицу значений не нужна и лишь тратит память.

Почему Колонки.Найти() возвращает Неопределено, хотя колонка видна на форме?

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

Регистр букв в имени колонки имеет значение?

Нет. Имена реквизитов и колонок во встроенном языке 1С регистронезависимы: «Цена», «ЦЕНА» и «цена» — одно и то же имя. Но опечатки в буквах (пропущенная или лишняя) критичны.

Как проверить наличие колонки в результате запроса, не выгружая его?

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

Что делать, если нужно проверить сразу несколько колонок?

Напишите функцию, принимающую массив имён, и в цикле проверяйте каждое через Колонки.Найти() или метаданные, возвращая массив отсутствующих. Это удобно для валидации структуры перед загрузкой данных из файлов.

Работает ли проверка через метаданные в расширении конфигурации?

Да, метаданные в расширении включают и реквизиты, добавленные самим расширением. Но помните: если расширение отключат, обращение к добавленным им реквизитам из основного кода вызовет ошибку — поэтому проверка наличия особенно важна именно в связке с расширениями.