В сети интернет достаточно материалов с описанием справочника функций по работе с метаданными 1С: Предприятие 7.7. Например, здесь. А, также, статей с описанием формата таблиц данных и правилам построения прямых запросов к ним. Например, здесь и здесь. Зачем же нужна эта статья?
Дело в том, что есть целый класс задач по работе с данными 1С: Предприятие 7.7, которые методы, перечисленные в данных [и других подобных] статьях не решают. В качестве примера, можно рассмотреть ситуацию, когда известно некоторое значение информационной базы и требуется определить, каким образом оно хранится в таблицах dbf-файлов, если мы имеем файловый формат информационной базы. Или, обратная к ней задача, когда есть символьное значение некоторого поля dbf-таблицы и нам требуется определить соответствующее ему значение информационной базы.
С подобными задачами, в той или иной постановке, сталкивается каждый, кто начинает, например, применять механизм «прямых запросов» в работе с данными информационной базы. При этом, стандартного набора функций и процедур 1С: Предприятие 7.7 недостаточно для решения этих задач и он, как будто, не подразумевает такой вариант использования механизмов платформы. В справочной литературе на эту тему, практически, ничего нет, а примеров само-документированного кода, в сети интернет, не так уж много.
Заполнить этот пробел и призвана эта статья. В которой, со ссылкой на рабочий пример конфигурации, с реализованным 1С++ классом «Метаданные», будет представлен пример решения вышеуказанных задач.
Начнем с первой, из этих задач, а именно, поиска представления значения информационной базы в таблицах dbf-файлов. Для решения этой задачи, вполне достаточно механизмов самой платформы, правда, некоторой частью, недокументированных.
В ходе решения этой задачи, мы будем пользоваться стандартной функцией платформы, «ЗначениеВСтрокуВнутр(<Значение>)» [см. справку по языку 1С: Предприятие 7.7]. Откуда, в частности, можно узнать, что эта функция возвращает символьную строку, содержащую некоторое внутреннее представление заданного значения информационной базы. Однако, в справке нет никакой информации о том, каким образом сформирована эта строка, например, для значения ссылочного типа.
На самом деле, все очень просто. Символьная строка представляет собой результат выполнения функции «ВСтрокуСРазделителями()» списка значений, первое, четвертое и седьмое значение, которого, представляют, в совокупности, полный путь к строке записи и определяют, соответственно, префикс имени файла [«SC» — для справочников или «DH» — для документов], номер файла и порядковый номер строки, задающий первичный ключ в таблице данных.
На этом, можно было бы считать нашу задачу решенной, если бы не один очень важный момент. Значения идентификаторов в таблицах информационной базы задаются в формате Base36 -строки. При этом, в ходе трансформации, 13-ти символьная строка идентификатора объекта в числовом формате, преобразуется в 9-ти символьную строку. Причем, последние 3 символа строки, представляющие код узла распределенной информационной базы, переносятся в результирующую строку без изменений. Для трансформации идентификатора во внутреннее представление используется недокументированная функция «_IdToStr(<Значение>)» платформы 1С: Предприятие 7.7.
// получение внутреннего представления значения информационной базы
Ид = глмМетаданные.Ссылка2Ид(ЗначениеИБ);
// определение номера в имени dbf-файла
КодТаблицы = глмМетаданные.Ид2КодТаблицыИБ(Ид);
// определение типа значения
Тип = глмМетаданные.Ид2Тип(глмМетаданные.ИдКаталога(Ид));
Если Тип = "Справочник" Тогда
// имя dbf-файла таблицы
ИмяФайла = "SC" + КодТаблицы + ".dbf";
// первичный ключ (PK) таблицы
ИмяПоля = "ID";
// искомое значение ключа строки
ЗначениеПоля = глмМетаданные.Ид2СтрокаИБ(Ид);
ИначеЕсли Тип = "Документ" Тогда
// имя dbf-файла таблицы
ИмяФайла = "DH" + КодТаблицы + ".dbf";
// первичный ключ (PK) таблицы
ИмяПоля = "IDDOC";
// искомое значение ключа строки
ЗначениеПоля = глмМетаданные.Ид2СтрокаИБ(Ид);
КонецЕсли;
Решение обратной задачи, для случая, когда значение является значением первичного ключа одной из таблиц информационной базы, можно получить, основываясь на тех же принципах, применяя для этих целей композицию функций «_StrToId(<Значение>)» и «ЗначениеИзСтрокиВнутр(<Значение>)» — обратных к указанным выше.
// получение внутреннего представления значения информационной базы
Ид = глмМетаданные.КодИБ2Ид(КодТаблицы, ЗначениеПоля);
// получение значения информационной базы
ЗначениеИБ = глмМетаданные.Ид2Ссылка(Ид);
Для случая, когда определяемое значение символьного типа, в заданной таблице, является реквизитом, стандартных методов платформа 1С: Предприятие 7.7 не предоставляет и мы будем вынуждены обратиться к методам внешних компонент. Таким, например, как функция «ИДОбъекта(<Метаданные>)» объекта «MetaDataWork» компоненты «1С++».
// получение номера поля (идентификатора реквизита)
КодПоля = Сред(ИмяПоля, 3);
// получение данных соответствующего реквизита объекта метаданных
сзРеквизит = глмМетаданные.КодИб2Реквизит(_IdToStr(КодПоля));
// получение набора свойств реквизита
тзСвойстваРеквизита = глмМетаданные.ВыбратьСвойстваРеквизита(сзРеквизит.Получить("Реквизит"),
сзРеквизит.Получить("Объект"));
// получение внутреннего представления значения информационной базы
Ид = глмМетаданные.КодИБ2Ид(тзСвойстваРеквизита.ПолучитьЗначение(5, 2)
+ "." + тзСвойстваРеквизита.ПолучитьЗначение(6, 2), ЗначениеПоля);
// получение значения информационной базы
ЗначениеИБ = глмМетаданные.Ид2Ссылка(Ид);
И, раз уже зашла речь об использовании стандартных средств платформы 1С: Предприятие 7.7 для работы с метаданными конфигурации, хочется отметить определенный дискомфорт, который приходится испытывать программисту, в процессе работы, связанный, прежде всего, с отсутствием универсальности в синтаксических конструкциях методов, выполняющих одинаковые функции для разных объектов метаданных. При этом, такие простые задачи, как выборка и анализ свойств стандартных реквизитов объектов метаданных решаются «нагромождением» программного кода в несколько строк, причем, для каждого типа метаданных, отдельно. Поэтому, желание написать некоторую программную оболочку для стандартных процедур работы с метаданными 1С: Предприятие 7.7, вполне естественно. Ниже, представлены примеры, как в 1С++ классе «Метаданные» решаются подобные задачи.
Объекты = глмМетаданные.ВыбратьОбъекты(глмМетаданные.ПолучитьПустойИд());
Объекты.ВыбратьСтроки();
Пока Объекты.ПолучитьСтроку() = 1 Цикл
Если глмМетаданные.ЭтоКаталог(Объекты.Ид) = 0 Тогда
сзМетаданные.ДобавитьЗначение(Объекты.Ид,
глмМетаданные.Ид2Тип(Объекты.Ид));
КонецЕсли;
КонецЦикла;
тзРеквизиты = глмМетаданные.ВыбратьРеквизиты(Ид, "", "", "");
Свойства = глмМетаданные.ВыбратьСвойстваРеквизита(тзРеквизиты, Ид);
Свойства.ВыбратьСтроки();
Пока Свойства.ПолучитьСтроку() = 1 Цикл
Сообщить("""" + Свойства.Имя + """ -> """ + Свойства.Значение + """");
КонецЦикла;
//*******************************************
Процедура ПечатьСведенийТаблицыСправочника(Ид)
Перем КодПоля;
КодТаблицы = глмМетаданные.Ид2КодТаблицыИБ(Ид);
Сообщить("//*******************************************");
Сообщить("Таблица данных ""SC" + КодТаблицы + """");
Сообщить("Поля:");
Реквизиты = глмМетаданные.ВыбратьРеквизиты(Ид,
"", "РеквизитСтандартный", "");
Реквизиты.ВыбратьСтроки();
Пока Реквизиты.ПолучитьСтроку() = 1 Цикл
Поз = глмМетаданные.мСтандартныеРеквизитыСправочников
.НайтиЗначение(Реквизиты.Ид);
глмМетаданные.мСтандартныеРеквизитыСправочников
.ПолучитьЗначение(Поз, КодПоля);
Сообщить("""" + Реквизиты.Ид + """ -> """ + КодПоля + """");
КонецЦикла;
Реквизиты = глмМетаданные.ВыбратьРеквизиты(Ид,
"", "Реквизит", "");
Реквизиты.ВыбратьСтроки();
Пока Реквизиты.ПолучитьСтроку() = 1 Цикл
КодПоля = "SP" + глмМетаданные
.Реквизит2КодПоляИБ(Реквизиты, Ид);
Сообщить("""" + Реквизиты.Ид + """ -> """ + КодПоля + """");
КонецЦикла;
КонецПроцедуры