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