Как из внешней обработки изменить данные, отображаемые в реквизите формы справочника?

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

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

Почему нельзя массово менять реквизиты формы

Проанализируем базовую концепцию управляемого интерфейса 1С:Предприятие 8.3:

  1. Область жизни реквизита формы: Реквизит формы создается исключительно в контексте конкретного экземпляра открытой формы на клиенте и сервере формы. Он существует только в оперативной памяти, пока форма открыта пользователем, и уничтожается при ее закрытии.
  2. Отсутствие серверного контекста форм: Серверные процедуры и фоновые задания, выполняющие пакетную обработку, в принципе не имеют доступа к интерфейсным объектам.
  3. Ограничения производительности: Попытка программно открыть или получить форму через ПолучитьФорму или ОткрытьФорму для 7 000 элементов в цикле неизбежно приведет к утечкам оперативной памяти, зависанию клиентского сеанса и аварийному завершению работы программы.

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

Шаг 1. Анализируем происхождение данных на форме

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

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

Шаг 2. Выбираем способ обновления данных

Рассмотрим типовые сценарии и способы их программной реализации во внешней обработке.

Сценарий 1: Данные хранятся в регистре сведений «Дополнительные сведения»

Если поле является дополнительным сведением (механизм БСП), оно хранится в независимом регистре сведений ДополнительныеСведения. Для его изменения не требуется перезаписывать сам элемент справочника. Разберем пример пакетной записи через менеджер записи:


Для Каждого СсылкаЭлемента Из МассивСсылок Цикл
    МенеджерЗаписи = РегистрыСведений.ДополнительныеСведения.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Объект = СсылкаЭлемента;
    МенеджерЗаписи.Свойство = НужноеСвойство; // ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения
    МенеджерЗаписи.Значение = НовоеЗначение;
    МенеджерЗаписи.Записать(Истина);
КонецЦикла;

Сценарий 2: Данные хранятся в табличной части «ДополнительныеРеквизиты»

Если реквизит выведен через механизм дополнительных реквизитов БСП, физически он расположен в табличной части объекта ДополнительныеРеквизиты. Посмотрим, как программно найти или добавить строку в табличную часть объекта справочника:


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

Сценарий 3: Данные привязаны к независимому или периодическому регистру сведений

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


НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(СсылкаНоменклатура);
НаборЗаписей.Отбор.ВидЦены.Установить(НужныйВидЦены);

НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = ТекущаяДатаСеанса();
НоваяЗапись.Номенклатура = СсылкаНоменклатура;
НоваяЗапись.ВидЦены = НужныйВидЦены;
НоваяЗапись.Цена = НоваяЦена;

НаборЗаписей.Записать();

Сценарий 4: Реквизит формы передает параметры в модуль объекта

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


Для Каждого СсылкаЭлемента Из МассивСсылок Цикл
    ОбъектСправочника = СсылкаЭлемента.ПолучитьОбъект();
    ОбъектСправочника.ДополнительныеСвойства.Вставить("ИмяСлужебногоПараметра", ЗначениеПараметра);
    ОбъектСправочника.Записать();
КонецЦикла;

Альтернативное решение: типовая обработка «Групповое изменение реквизитов»

Если конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), для массовой корректировки 7 000 элементов не обязательно писать внешнюю обработку с нуля. Типовая обработка ГрупповоеИзменениеРеквизитов позволяет:

  1. Напрямую менять типовые реквизиты и табличные части объектов.
  2. Корректировать дополнительные реквизиты и сведения без открытия форм элементов.
  3. Выполнять произвольный алгоритм на встроенном языке 1С на сервере для каждого выбранного элемента выборки.
← На главную