Метаданные 1С

Метаданные 1С – это список справочников, документов, их реквизитов и прочего, составляющего конфигурацию. Список метаданных 1С правится программистов в конфигураторе в окне конфигурации.

Из программы на языке 1С доступен список метаданных 1С и их свойства.

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

Рассмотрим, как работать с метаданными 1С конфигурации из языка 1С.

 

Метаданные 1С конфигурации

Глобальная переменная Метаданные дает доступ к метаданным 1С всей конфигурации (т.е. к «корню» конфигурации). Далее через точку можно обращаться к «коллекциям» — документы, справочники и т.п., чтобы выйти на конкретный справочник или документ, у которых соответственно есть «коллекции» реквизиты, табличные части и т.п. – все, как в конфигураторе, в дереве конфигурации.

Пример – создадим список всех документов конфигурации для того, чтобы пользователь мог выбрать нужный документ из списка:
спДокументовКонфигурации = Новый СписокЗначений(); //сюда будем сохранять список

//Метаданные - глобальная переменная, которая дает доступ ко всем метаданным 1С конфигурации
//Метаданные.Документы - коллекция документов конфигурации
Для каждого Документ из Метаданные.Документы Цикл
     //Документ - это метаданные 1С документа (каждого, так как мы обходим их в цикле)
     //.Имя - наименование документа так, как оно задано в конфигурации
     //.Синоним - "человеческое" наименование документа, которое отображается пользователю
     //список значений может хранить значение (имя документа) и "представление для пользователя" (как раз - синоним документа)
     спДокументовКонфигурации.Добавить( Документ.Имя, Документ.Синоним );
КонецЦикла;

//даем возможность пользователю выбрать из списка нужный документ
элДокумент = спДокументовКонфигурации.ВыбратьЭлемент();

//если пользователь нажал "Отмена", то результатом выбора будет значение НЕОПРЕДЕЛЕНО, иначе результатом будет - выбранный элемент
Если элДокумент <> Неопределено Тогда
     //в .Значение списка значений мы записывали имя документа "как в конфигурации"
     //создадим новый документ с таким именем, напомним - к документам можно обращаться Документы.ИмяДокумента или Документы[ИмяДокумента]
     обДокумент = Документы[элДокумент.Значение].СоздатьДокумент();
     //ДокументОбъект.ПолучитьФорму() - возвращает форму с указанным именем, а если имя не указано - то форму "по-умолчанию"
     обДокумент.ПолучитьФорму().Открыть();
КонецЕсли;

Пример – для общего журнала документов (отображающего все виды документов) создадим запрос, который вернет список всех документов:
[VIP_CONTENT]

ТекстЗапроса = "";
Для каждого Документ из Метаданные.Документы Цикл
     //несколько запросов объединяются друг с другом строкой "ОБЪЕДИНИТЬ ВСЕ"
     //если это не первая итерация цикла, то нужно добавить объединение запросов
     Если не ПустаяСтрока(ТекстЗапроса) Тогда
          ТекстЗапроса = ТекстЗапроса + "
          |
          | ОБЪЕДИНИТЬ ВСЕ
          | ";
     КонецЕсли;

     //добавляем имя документа
     //вид документа - добавляем строкой, выведем пользователю синоним метаданных 1С
     //момент времени - используем для сортировки документов (подробнее см. "Момент времени")
     //ссылка - для обращения потом к документу
     //ограничим по периоду, так как если много документов - получение списка может занять слишком много ресурсов
     //обратите внимание - если в конфигурации много видов документов, то запрос работать не будет - так как существует ограничение на кол-во таблиц в одном запросе
     //в этом случае нужно прописать разбиение запроса на пакеты по N документов и объединение результатов серии запросов в одной таблице
     ТекстЗапроса = ТекстЗапроса + "
     |ВЫБРАТЬ
     | """ + Документ.Синоним + """ КАК ВидДокумента,
     | Дата,
     | Номер,
     | МоментВремени,
     | Ссылка
     |ИЗ
     | Документ." + Документ.Имя + "
     |ГДЕ
     | Дата между &НачалоПериода И &ОкончаниеПериода";
КонецЦикла;

//добавим сортировку
ТекстЗапроса = ТекстЗапроса + "
|УПОРЯДОЧИТЬ ПО
| МоментВремени";

Запрос = Новый Запрос(ТекстЗапроса);

//параметры запроса - период - текущий месяц
Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ОкончаниеПериода", КонецМесяца(ТекущаяДата()));

//в нашем примере просто покажем результат пользователю
//аккуратно - если в базе много документов, то показ результатов займет много времени
Запрос.Выполнить().Выгрузить().ВыбратьСтроку();

[/VIP_CONTENT]

 

Метаданные 1С объекта

Большинство объектов 1С, сохраняемых в базе данных (справочники, документы и т.д.) представлены ссылками и объектами (подробнее см. «Ссылки и объекты»).

У ссылок и объектов есть метод .Метаданные(), который позволяет выйти на метаданные 1С этого объекта.

Пример – проверка на наличие реквизитов с типом «Справочник.Организация» в документе и обнуление значения этих реквизитов:
//ДокументОбъект - документ, полученный на изменение или создание
//аналогичным образом можно работать со ссылками, например: ДокументСсылка = Документ.ИмяДокумента.ПустаяСсылка().Метаданные()
ДокументОбъект = Документы.ПоступлениеТоваров.СоздатьДокумент();

//цикл по реквизитам
Для каждого Реквизит из ДокументОбъект.Метаданные().Реквизиты Цикл
     //у каждого реквизита может быть как один, так и несколько типов, подробнее см. "ОписаниеТипов"
     мТипов = Реквизит.Тип.Типы();
     //проверяем по каждому типу - тот ли это нужный нам?
     Для каждого Тип из мТипов Цикл
          Если Тип = Тип("СправочникСсылка.Организации") Тогда
               //обнуляем реквизит с этим именем в документе
               //для "обнуления" можно приравнивать его к Неопределено,
               //по факту значение будет установлено не Неопределено, а "пустое значение" типа реквизита
               //Неопределено только если у реквизита несколько типов
               ДокументОбъект[Реквизит.Имя] = Неопределено;
          КонецЕсли;
     КонецЦикла;
КонецЦикла;

//цикл по табличным частям
Для каждого ТабЧасть из ДокументОбъект.Метаданные().ТабличныеЧасти Цикл
     //в табличной части тоже реквизиты (колонки таб.части)
     Для каждого Реквизит из ТабЧасть.Реквизиты Цикл
          //здесь аналогично
          мТипов = Реквизит.Тип.Типы();
          Для каждого Тип из мТипов Цикл
               Если Тип = Тип("СправочникСсылка.Организации") Тогда
                    //так как это таб.часть, то мы должны пройтись по всем строкам этой тач. части
                    Для каждого Строка из ДокументОбъект[ТабЧасть.Имя] Цикл
                         Строка[Реквизит.Имя] = Неопределено;
                    КонецЦикла;
               КонецЕсли;
          КонецЦикла;
     КонецЦикла;
КонецЦикла;