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