Как выполнить отбор и изменить записи регистра сведений по значению ресурса в 1С?

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

При программной работе с регистрами сведений разработчики нередко сталкиваются с ошибкой времени выполнения «Недопустимое значение параметра» при попытке вызвать метод Выбрать() с отбором по ресурсу или реквизиту. Разберем, почему возникает данная ошибка, как устроена работа платформы 1С:Предприятие с отборами и как правильно отобрать и модифицировать нужные записи.

Причина ошибки при вызове метода Выбрать()

Проанализируем исходную ситуацию. В типовых конфигурациях, например в «1С:Управление торговлей 11», регистр сведений ШтрихкодыНоменклатуры спроектирован так, что измерением является Штрихкод, а Номенклатура, Характеристика и Упаковка выступают ресурсами. Это обеспечивает уникальность штрихкода в рамках информационной базы.

Посмотрим на ошибочный фрагмент кода:


Отбор = Новый Структура("Номенклатура", НоменклатураСсылка);
Выборка = РегистрыСведений.ШтрихкодыНоменклатуры.Выбрать(Отбор);

Выясним причину сбоя: согласно синтаксис-помощнику 1С, параметр Отбор у объекта РегистрСведенийМенеджер.Выбрать() может принимать только структуру, ключами которой являются исключительно измерения регистра (а также поля Период, ПериодС, ПериодПо для периодических регистров и Регистратор для подчиненных регистратору). Передать в структуру ресурс или реквизит платформа не позволяет. Аналогичное ограничение действует и для свойства Отбор объекта РегистрСведенийНаборЗаписей.

Если нам необходимо найти и изменить записи регистра по значению ресурса, стандартный путь заключается в двух шагах: получить ключевые поля (измерения) с помощью запроса, а затем точечно или пакетно обновить записи.

Способ 1. Изменение записей через РегистрСведенийМенеджерЗаписи

Рассмотрим подробнее классический вариант, который отлично подходит для точечной модификации небольшого количества записей. Мы выбираем измерения запросом с фильтром по ресурсу в секции ГДЕ, а затем в цикле читаем и перезаписываем каждую строку через РегистрСведенийМенеджерЗаписи.

Разберем по шагам реализацию алгоритма:

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

Посмотрим на пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Штрихкоды.Штрихкод КАК Штрихкод
    |ИЗ
    |	РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
    |ГДЕ
    |	Штрихкоды.Номенклатура = &Номенклатура";

Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);
Выборка = Запрос.Выполнить().Выбрать();

НачатьТранзакцию();
Попытка
	Пока Выборка.Следующий() Цикл
		МенеджерЗаписи = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьМенеджерЗаписи();
		МенеджерЗаписи.Штрихкод = Выборка.Штрихкод;
		МенеджерЗаписи.Прочитать();
		
		Если МенеджерЗаписи.Выбран() Тогда
			// Вносим требуемые изменения в ресурсы или реквизиты
			МенеджерЗаписи.Номенклатура = НоваяНоменклатураСсылка;
			МенеджерЗаписи.Записать(Истина);
		КонецЕсли;
	КонецЦикла;
	
	ЗафиксироватьТранзакцию();
Исключение
	ОтменитьТранзакцию();
	ВызватьИсключение;
КонецПопытки;

Способ 2. Модификация через РегистрСведенийНаборЗаписей

Рассмотрим альтернативный вариант с использованием объекта РегистрСведенийНаборЗаписей. Этот способ предпочтителен при пакетной обработке и при необходимости работы с несколькими записями, объединенными общими измерениями.

Посмотрим, как организовать изменение данных через набор записей:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Штрихкоды.Штрихкод КАК Штрихкод
    |ИЗ
    |	РегистрСведений.ШтрихкодыНоменклатуры КАК Штрихкоды
    |ГДЕ
    |	Штрихкоды.Номенклатура = &Номенклатура";

Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);
Выборка = Запрос.Выполнить().Выбрать();

НачатьТранзакцию();
Попытка
	Пока Выборка.Следующий() Цикл
		НаборЗаписей = РегистрыСведений.ШтрихкодыНоменклатуры.СоздатьНаборЗаписей();
		НаборЗаписей.Отбор.Штрихкод.Установить(Выборка.Штрихкод);
		НаборЗаписей.Прочитать();
		
		Для Каждого Запись Из НаборЗаписей Цикл
			Запись.Номенклатура = НоваяНоменклатураСсылка;
		КонецЦикла;
		
		НаборЗаписей.Записать();
	КонецЦикла;
	
	ЗафиксироватьТранзакцию();
Исключение
	ОтменитьТранзакцию();
	ВызватьИсключение;
КонецПопытки;

Важные практические рекомендации

При программной модификации записей регистров важно учитывать следующие технические особенности:

  1. Явное управление транзакциями: Каждый вызов метода Записать() вне транзакции инициирует отдельную системную транзакцию СУБД. При обработке сотен строк это приводит к сильным задержкам. Использование конструкций НачатьТранзакцию() и ЗафиксироватьТранзакцию() ускоряет процесс записи в десятки раз.
  2. Контроль целостности данных: Прямая запись через РегистрСведенийМенеджерЗаписи или РегистрСведенийНаборЗаписей не выполняет типовых проверок, заложенных в экранных формах документов или справочников. При изменении номенклатуры в регистре штрихкодов необходимо гарантировать, что сопутствующие ресурсы (характеристики, упаковки) согласованы с новой номенклатурой.
← На главную