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