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