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