Как программно изменить и записать реквизиты элементов справочника в 1С

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

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

Нужно ли открывать форму элемента для записи реквизитов?

Для изменения реквизитов объекта открывать форму не требуется. Форма в 1С — это лишь графический интерфейс для интерактивного взаимодействия пользователя с данными. Программная работа с базой данных строится через обращение к самим объектам прикладного решения.

Открытие экранных форм в цикле создает лишнюю нагрузку на графическую подсистему и клиентское приложение, а также существенно замедляет выполнение обработки. Поэтому для массового заполнения реквизитов всегда используется непосредственная работа с объектной моделью справочника.

Базовый способ: получение объекта и запись

Рассмотрим стандартный шаблон кода для обновления реквизитов по списку ссылок. Сначала получаем ссылку на элемент, затем вызываем метод ПолучитьОбъект(), меняем значение нужного реквизита и вызываем метод Записать().


Для Каждого Сотрудник Из СписокСотрудников Цикл
    СправочникОбъект = Сотрудник.ПолучитьОбъект();
    Если СправочникОбъект <> Неопределено Тогда
        СправочникОбъект.ТвойРеквизит = ЗначениеРеквизита;
        СправочникОбъект.Записать();
    КонецЕсли;
КонецЦикла;

Разберем по шагам, что происходит в этом фрагменте:

  1. Мы выполняем обход коллекции ссылок в цикле.
  2. С помощью метода ПолучитьОбъект() из объектной ссылки получаем экземпляр типа СправочникОбъект, доступный для редактирования.
  3. Присваиваем новое значение реквизиту объекта.
  4. Вызываем метод Записать(), который сохраняет изменения в информационной базе и вызывает обработчики событий модуля объекта (ПередЗаписью, ПриЗаписи).

Почему простая запись может не сработать?

Если после выполнения кода значение в базе не изменилось или возникла ошибка, проанализируем возможные причины:

  1. Реквизит физически хранится в другом месте. В таких конфигурациях, как ЗУП 2.5 или УПП 1.3, в форме справочника СотрудникиОрганизаций отображаются данные из связанного справочника ФизическиеЛица или периодических регистров сведений. Если реквизит был добавлен не в сам справочник сотрудников, а в физическое лицо, записывать необходимо объект физического лица:
    
    ФизЛицоОбъект = СсылкаНаСотрудника.Физлицо.ПолучитьОбъект();
    ФизЛицоОбъект.ИмяРеквизита = ЗначениеРеквизита;
    ФизЛицоОбъект.Записать();
    
  2. Срабатывают типовые проверки в модуле объекта. При вызове Записать() выполняются встроенные проверки конфигурации. Если они блокируют сохранение данных или перезаписывают реквизит по умолчанию, используем флаг отключения проверок при загрузке:
    
    СправочникОбъект = СсылкаНаСотрудника.ПолучитьОбъект();
    СправочникОбъект.ОбменДанными.Загрузка = Истина;
    СправочникОбъект.ИмяРеквизита = ЗначениеРеквизита;
    СправочникОбъект.Записать();
    
    Установка свойства ОбменДанными.Загрузка = Истина позволяет обойти проверки модуля объекта и подписок на события.
  3. Логика заполнения зашита в модуль формы. Если алгоритм расчета и связывания реквизитов находится исключительно в коде формы (например, в обработчиках ПередЗаписьюВФорме), то прямая запись объекта эти обработчики не вызывает. В таком случае правильным решением является перенос алгоритма в модуль обработки или объекта.

Программная запись через форму (в крайних случаях)

Если логика заполнения жестко завязана на контекст формы обычного приложения и ее невозможно перенести в обработку, можно программно открыть форму, заполнить реквизиты и инициировать сохранение:


Форма = СсылкаНаСотрудника.ПолучитьФорму();
Форма.Открыть();
Форма.ИмяРеквизитаФормы = ЗначениеРеквизита;
Форма.ЗаписатьВФорме();
Форма.Закрыть();

Помните, что такой подход является исключительной мерой и должен применяться только тогда, когда прямая запись объекта через ПолучитьОбъект() по архитектурным причинам не применима.

← На главную