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