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