Как организовать запись реквизитов справочника в регистр сведений при сохранении объекта

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С часто возникает задача логирования или ведения истории изменений конкретных объектов. Рассмотрим ситуацию, когда при записи элемента справочника Кластеры необходимо автоматически заносить текущие значения его реквизитов в периодический регистр сведений ИзмененияОбъектов. Это позволяет отслеживать, кто, когда и какие параметры изменял в системе.

Анализ структуры данных

Прежде чем переходить к кодированию, разберем структуру объектов, с которыми мы работаем. Согласно условию задачи, у нас есть справочник Кластеры со следующими ключевыми полями:

Данные должны попадать в периодический регистр сведений ИзмененияОбъектов. Периодичность регистра важна, так как она позволяет автоматически фиксировать момент изменения (поле Период). В регистре созданы измерения и реквизиты: Наименование, Пользователь, Строка1 (для хранения имени кластера), Число1 (для порта) и Спр1 (для ссылки на версию платформы).

Реализация записи в форме справочника

Разберем самый распространенный способ решения для начинающих разработчиков — написание кода непосредственно в модуле формы справочника. Мы будем использовать обработчик события ПриЗаписи. Важно помнить, что в управляемых формах этот обработчик выполняется на сервере, что позволяет нам напрямую работать с базой данных.

Проанализируем программный код, который создает запись в регистре:


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

КонецПроцедуры

Рассмотрим важный нюанс: использование метода Записать(Ложь). По умолчанию метод Записать() набора записей удаляет все существующие записи, подходящие под установленный отбор, и записывает новые. Если отбор не установлен, использование метода без параметра или с параметром Истина может очистить весь регистр! Поэтому для добавления записи в историю мы используем Ложь.

Оптимизация кода с помощью ЗаполнитьЗначенияСвойств

Если названия реквизитов в справочнике и названия полей в регистре совпадают, мы можем значительно упростить наш код. Вместо ручного присваивания каждой переменной, воспользуемся мощным инструментом платформы — методом ЗаполнитьЗначенияСвойств. Выясним, как это сокращает трудозатраты.


// Вместо множества строк:
// ЗаписьРегистра.Строка1 = Объект.Строка1;
// ЗаписьРегистра.Число1 = Объект.Число1;

// Используем одну команду:
ЗаполнитьЗначенияСвойств(НоваяЗапись, ТекущийОбъект);

Этот метод проанализирует оба объекта, найдет поля с одинаковыми именами и типами, и автоматически перенесет данные. Это не только делает код чище, но и снижает риск возникновения ошибок при опечатках в именах переменных.

Создание интерфейса для просмотра истории

Чтобы пользователь мог просматривать накопленные данные, в регистре сведений ИзмененияОбъектов необходимо создать форму списка. Выполним следующие шаги в конфигураторе:

  1. Найдем в дереве метаданных наш регистр сведений.
  2. Перейдем на закладку Формы.
  3. Нажмем на кнопку "Добавить" (иконка с плюсом).
  4. В мастере создания выберем тип "Форма списка регистра сведений".
  5. Нажмем "Готово", чтобы платформа автоматически сгенерировала стандартный интерфейс.

Помните, что если форма списка не создана явно, 1С генерирует её автоматически в режиме "Предприятие". Однако создание собственной формы позволяет настроить фильтры, группировки и условное оформление (например, выделять цветом изменения важных портов или критических версий платформы).

Профессиональный подход: Подписки на события

Разберем ситуацию: что будет, если программист решит изменить данные справочника Кластеры программно, не открывая форму? В этом случае код, написанный в форме, не сработает, и запись в историю не попадет. Чтобы избежать такой потери данных, профессионалы используют Подписки на события.

Проанализируем алгоритм создания подписки:

Код в общем модуле будет выглядеть практически так же, как и в модуле формы, но он будет гарантированно срабатывать при любом изменении объекта в системе — будь то ручной ввод, загрузка из Excel или обмен данными с другой базой.

Использование современных форматов (JSON)

Если состав реквизитов справочника Кластеры часто меняется, создавать под каждый новый реквизит отдельную колонку в регистре неудобно. В сообщении форума упоминается отличная идея — сериализация. Мы можем собрать все значимые поля объекта в структуру, преобразовать её в JSON-строку и записать в одно текстовое поле регистра.

Посмотрим на пример реализации такого подхода:


ЗаписьРегистра = РегистрыСведений.ИзмененияОбъектов.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Период = ТекущаяДата();
ЗаписьРегистра.Наименование = ЭтотОбъект.Наименование;

// Собираем данные в структуру
ДанныеДляЗаписи = Новый Структура;
ДанныеДляЗаписи.Вставить("Порт", ЭтотОбъект.Порт);
ДанныеДляЗаписи.Вставить("Логин", ЭтотОбъект.Логин);
ДанныеДляЗаписи.Вставить("Версия", Строка(ЭтотОбъект.ВерсияПлатформы));

// Преобразуем в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляЗаписи);
СтрокаИстории = ЗаписьJSON.Закрыть();

ЗаписьРегистра.СтрокаДанных = СтрокаИстории;
ЗаписьРегистра.Записать();

Такой метод позволяет хранить неограниченное количество параметров, не расширяя структуру регистра сведений, что делает систему более гибкой и производительной при больших объемах данных.

← На главную