Как программно изменить значения в табличной части бизнес-процесса по ссылке

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

При разработке в среде 1С:Предприятие часто возникает задача массового изменения данных в объектах, которые уже записаны в базе данных. Одной из таких задач является программная установка признаков (флагов или "галочек") в табличных частях бизнес-процессов. В этой статье мы подробно разберем, как, имея только ссылку на бизнес-процесс, добраться до его внутренней таблицы, изменить в ней данные и корректно сохранить результат.

Постановка задачи и анализ ситуации

Представим сценарий: у нас есть выборка данных, в которой одна из колонок содержит ссылку на объект БизнесПроцесс. Нам необходимо зайти в каждую такую ссылку, найти табличную часть (например, под названием Оплата) и во всех строках этой таблицы установить значение реквизита Оплачено в состояние Истина. Важно понимать, что ссылка (СправочникСсылка, ДокументСсылка или БизнесПроцессСсылка) — это лишь идентификатор объекта в базе данных. Она доступна только для чтения. Для того чтобы внести изменения, нам необходимо получить сам объект в оперативную память.

Шаг 1: Получение объекта бизнес-процесса

Для начала работы с данными бизнес-процесса мы должны вызвать метод ПолучитьОбъект(). Этот метод создает в памяти копию данных, которую можно редактировать. Рассмотрим, как это выглядит в коде:


// Предположим, Выборка - это результат запроса или обхода коллекции
ЗаявкаОбъект = Выборка.Ссылка.ПолучитьОбъект();

Если ЗаявкаОбъект = Неопределено Тогда
    // Обработка ситуации, если объект был удален
    Возврат;
КонецЕсли;

Использование метода ПолучитьОбъект() является обязательным условием для любого изменения данных. Попытка изменить реквизит непосредственно через ссылку приведет к ошибке компиляции или выполнения, так как ссылка не имеет свойств для записи.

Шаг 2: Обход табличной части и изменение данных

После того как мы получили объект, мы получаем доступ ко всем его коллекциям, включая табличные части. Табличная часть представляет собой коллекцию строк, которую можно перебрать с помощью цикла Для Каждого. Проанализируем пример кода, который перебирает строки таблицы Оплата и устанавливает признак оплаты:


// Обходим все строки табличной части "Оплата"
Для Каждого СтрокаТЧ Из ЗаявкаОбъект.Оплата Цикл
    // Устанавливаем признак оплаты
    СтрокаТЧ.Оплачено = Истина; 
КонецЦикла;

В этом цикле мы обращаемся к каждой строке СтрокаТЧ и меняем значение её реквизита Оплачено. Обратите внимание, что на данном этапе изменения внесены только в объект, находящийся в оперативной памяти сервера. В базе данных информация пока остается прежней.

Шаг 3: Сохранение изменений в базе данных

Для фиксации изменений необходимо вызвать метод Записать(). Это критически важный шаг, без которого все предыдущие действия будут потеряны после завершения работы процедуры. Разберем полный цикл обработки одного объекта:


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

Оптимизация работы и важные нюансы

Просто вызвать метод записи иногда бывает недостаточно в сложных системах. Рассмотрим дополнительные аспекты, которые сделают ваш код профессиональным и надежным.

1. Использование транзакций и блокировок

Если вы обрабатываете большое количество бизнес-процессов в цикле, вызов Записать() для каждого объекта по отдельности может существенно замедлить работу. Рекомендуется использовать транзакции. Кроме того, чтобы избежать ошибки "Объект изменен или удален другим пользователем", полезно использовать объектную блокировку.


НачатьТранзакцию();
Попытка
    ЗаявкаОбъект = СсылкаНаБП.ПолучитьОбъект();
    ЗаявкаОбъект.Заблокировать(); // Блокируем объект от изменений другими пользователями
    
    // ... логика изменения ТЧ ...
    
    ЗаявкаОбъект.Записать();
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка при обработке: " + ОписаниеОшибки());
КонецПопытки;

2. Поиск конкретных строк в табличной части

Если табличная часть Оплата содержит сотни строк, а изменить нужно только те, что относятся к определенному периоду или условию, эффективнее использовать метод НайтиСтроки() вместо полного перебора. Рассмотрим пример:


ПараметрыОтбора = Новый Структура("Статус", "КОплате");
СтрокиДляИзменения = ЗаявкаОбъект.Оплата.НайтиСтроки(ПараметрыОтбора);

Для Каждого ТекущаяСтрока Из СтрокиДляИзменения Цикл
    ТекущаяСтрока.Оплачено = Истина;
КонецЦикла;

3. Обновление интерфейса у пользователя

Если этот код выполняется в то время, когда у пользователя открыта форма этого бизнес-процесса, он не увидит изменений мгновенно, так как форма отображает старые данные из кэша. Чтобы система принудительно обновила открытые формы, после метода Записать() следует вызвать ОповеститьОбИзменении(Ссылка).

4. Влияние на логику бизнес-процесса

Бизнес-процессы в 1С не просто хранят данные, они управляют логикой (точками маршрута). Если реквизит Оплачено является условием для перехода на следующий этап, простая перезапись объекта может не сдвинуть процесс дальше по карте маршрута. В таких случаях может потребоваться программно вызвать проверку условий или выполнить связанные задачи (Задачи) бизнес-процесса.

Итоги

Для успешного решения задачи мы выполнили следующие действия:

  1. Выяснили, что работа со ссылкой требует получения объекта через ПолучитьОбъект().
  2. Проанализировали структуру табличной части и научились обходить её строки.
  3. Обеспечили сохранение данных методом Записать().
  4. Рассмотрели продвинутые техники: транзакции, блокировки и оптимизацию поиска строк.

Эти принципы применимы не только к бизнес-процессам, но и к документам, справочникам и другим объектам метаданных 1С.

← На главную