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