При интеграции систем автоматизации, переносе данных или разборе файлов обмена (текстовых документов, CSV, XML) разработчики часто сталкиваются с задачей, когда имя реквизита и его значение поступают в виде простых строк. Например, из внешнего файла мы считываем конструкцию вида: "НаименованиеРеквизита" - "Значение". В современных версиях платформы 1С:Предприятие 8 для этого достаточно использовать синтаксис квадратных скобок, однако в платформе 1С:Предприятие 7.7 этот механизм реализован иначе.
В данной статье мы подробно разберем, как динамически записывать и считывать значения реквизитов в 1С 7.7, управлять типами данных, работать с периодическими реквизитами и использовать метаданные для автоматизации рутинных операций.
Для того чтобы записать значение в реквизит, имя которого хранится в строковой переменной, в платформе 1С 7.7 существует специальный встроенный метод УстановитьАтрибут(). Он доступен у всех объектов, имеющих настраиваемый набор реквизитов (справочники, документы и т.д.).
Рассмотрим синтаксис метода:
Объект.УстановитьАтрибут(ИмяРеквизита, Значение)
Параметры метода:
Давайте разберем практический пример, в котором мы создаем новый элемент справочника и динамически заполняем его реквизиты, зная только их строковые имена:
// Создаем объект справочника "Сотрудники"
Спр = СоздатьОбъект("Справочник.Сотрудники");
// Инициируем создание нового элемента справочника
Спр.Новый();
// Задаем строковые переменные с именами реквизитов и значениями
ИмяПоля1 = "Адрес";
ЗначениеПоля1 = "г. Москва, ул. Ленина, д. 10";
ИмяПоля2 = "Телефон";
ЗначениеПоля2 = "8-800-555-35-35";
// Записываем значения в реквизиты динамическим способом
Спр.УстановитьАтрибут(ИмяПоля1, ЗначениеПоля1);
Спр.УстановитьАтрибут(ИмяПоля2, ЗначениеПоля2);
// Обязательно сохраняем изменения в базе данных
Спр.Записать();
Этот простой и эффективный способ полностью решает задачу, избавляя программиста от написания громоздких конструкций условий Если...Тогда для каждого возможного реквизита конфигурации.
В процессе разработки часто возникает и обратная задача: прочитать значение реквизита справочника, если его имя также известно только в виде строки. Для этого в паре к методу записи используется метод ПолучитьАтрибут().
Синтаксис метода:
Значение = Объект.ПолучитьАтрибут(ИмяРеквизита);
Проанализируем пример, в котором мы считываем данные из существующего элемента справочника:
Спр = СоздатьОбъект("Справочник.Сотрудники");
// Находим сотрудника по его коду в базе
Если Спр.НайтиПоКоду("00045") = 1 Тогда
ИмяРеквизита = "Адрес";
// Получаем значение реквизита динамически
ТекущийАдрес = Спр.ПолучитьАтрибут(ИмяРеквизита);
Сообщить("Адрес сотрудника: " + ТекущийАдрес);
КонецЕсли;
Если перед нами стоит задача полностью выгрузить или проанализировать все реквизиты конкретного справочника, мы можем использовать встроенный механизм работы с метаданными. Объект Метаданные позволяет программно получить структуру конфигурации.
Разберем по шагам, как получить имена всех реквизитов справочника "Сотрудники":
// Получаем объект метаданных для конкретного справочника
СпрСотр = Метаданные.Справочник("Сотрудники");
// Выясняем общее количество реквизитов данного справочника в конфигураторе
КолвоРеквизитов = СпрСотр.Реквизит();
// Запускаем цикл перебора всех доступных реквизитов по их порядковому номеру
Для Ном = 1 По КолвоРеквизитов Цикл
// Получаем объект метаданных текущего реквизита
СпрРекв = СпрСотр.Реквизит(Ном);
// Считываем его системный идентификатор (имя) и другие полезные свойства
ИмяРеквизита = СпрРекв.Идентификатор;
СинонимРеквизита = СпрРекв.Синоним;
ТипДанных = СпрРекв.Тип;
Сообщить("Реквизит: " + ИмяРеквизита + " (" + СинонимРеквизита + "), Тип: " + ТипДанных);
КонецЦикла;
Важное замечание: При переборе коллекции Метаданные.Справочник("...").Реквизит() платформа возвращает только те реквизиты, которые были созданы пользователем вручную в процессе конфигурирования. Системные свойства, такие как Код, Наименование, Родитель или Владелец, в эту коллекцию не попадают. Тем не менее, методы УстановитьАтрибут() и ПолучитьАтрибут() прекрасно работают с этими предопределенными системными реквизитами.
При использовании динамической загрузки данных из внешних источников мы не застрахованы от нештатных ситуаций. Рассмотрим наиболее частые проблемы и архитектурные решения для них.
В файле-источнике все данные обычно представлены в виде текста. Если в базе данных 1С реквизит имеет отличный от строки тип (например, Число, Дата, Ссылка на другой справочник или Перечисление), то простая попытка записать туда строку вызовет ошибку несоответствия типов.
Выясним, как правильно преобразовывать типы с использованием метаданных:
// Пример преобразования простых типов
Если ТипДанных = "Число" Тогда
ЗначениеДляЗаписи = Число(ЗначениеИзФайла);
ИначеЕсли ТипДанных = "Дата" Тогда
ЗначениеДляЗаписи = Дата(ЗначениеИзФайла);
ИначеЕсли ТипДанных = "Справочник" Тогда
// Определяем вид справочника, на который ссылается реквизит
ВидСправочника = СпрРекв.Вид;
СпрПоиск = СоздатьОбъект("Справочник." + ВидСправочника);
// Ищем элемент по наименованию
Если СпрПоиск.НайтиПоНаименованию(ЗначениеИзФайла, 0, 1) = 1 Тогда
ЗначениеДляЗаписи = СпрПоиск.ТекущийЭлемент();
Иначе
ЗначениеДляЗаписи = ПолучитьПустоеЗначение("Справочник." + ВидСправочника);
КонецЕсли;
КонецЕсли;
Для поиска и подстановки значения перечисления по его строковому идентификатору в 1С 7.7 существует изящный трюк с использованием системной функции Шаблон(). Этот метод позволяет вычислить значение текстового выражения динамически:
// СпрРекв.Вид возвращает имя перечисления в конфигураторе (например, "ЮрФизЛицо")
ИмяПеречисления = СпрРекв.Вид;
ИмяЗначения = "ФизическоеЛицо"; // прочитано из файла
// Динамически получаем объект перечисления
ЗначениеПеречисления = Шаблон("[Перечисление." + ИмяПеречисления + "." + ИмяЗначения + "]");
// Успешно записываем его в объект
Спр.УстановитьАтрибут(ИмяРеквизита, ЗначениеПеречисления);
Если реквизит справочника является периодическим (то есть хранит историю изменений в разрезе дат), стандартный вызов метода УстановитьАтрибут() запишет новое значение на текущую рабочую дату системы. Чтобы записать значение на конкретную дату из внешнего файла, необходимо использовать специальный объект Периодический:
Если СпрРекв.Периодический = 1 Тогда
ПериодическийОбъект = СоздатьОбъект("Периодический");
// Связываем объект с нужным реквизитом конкретного элемента справочника
ПериодическийОбъект.ИспользоватьОбъект(ИмяРеквизита, Спр.ТекущийЭлемент());
// Устанавливаем дату и значение
ПериодическийОбъект.ДатаЗнач = ДатаИзФайла;
ПериодическийОбъект.Значение = ЗначениеИзФайла;
// Сохраняем периодическое значение в базе данных
ПериодическийОбъект.Записать();
КонецЕсли;
Так как имена реквизитов поступают из внешнего источника, пользователь может допустить опечатку или файл может быть устаревшей версии. Чтобы избежать аварийного завершения работы программы при попытке записать несуществующий атрибут, обязательно используйте конструкцию перехвата ошибок Попытка...Исключение:
Попытка
Спр.УстановитьАтрибут(ИмяРеквизита, ЗначениеДляЗаписи);
Исключение
Сообщить("Внимание! Не удалось записать реквизит '" + ИмяРеквизита + "'. Возможно, он отсутствует в конфигурации.");
КонецПопытки;
Применение данных методов позволит вам создавать гибкие и устойчивые механизмы импорта данных любой сложности в среде 1С:Предприятие 7.7.