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