При разработке в среде «1С:Предприятие» работа с регистрами сведений через объект НаборЗаписей является стандартной операцией. Однако начинающие разработчики часто сталкиваются с ошибкой «Запись не соответствует отбору». Давайте подробно разберем, почему возникает эта ситуация, как работает механизм отборов и как правильно изменять данные в периодических независимых регистрах.
Рассмотрим ситуацию, представленную в коде автора. Попытка удалить старые записи и записать новые по списку идентификаторов (GUID) приводит к фатальной ошибке. Проанализируем ключевые строки кода:
МассивГУИДов = Объект.Товары.Выгрузить(,"ГУИД");
НаборСтатусНоменклатуры = РегистрыСведений.СтатусНоменклатуры.СоздатьНаборЗаписей();
НаборСтатусНоменклатуры.Отбор.ГУИД.Установить(МассивГУИДов);
НаборСтатусНоменклатуры.Записать();
В этом фрагменте скрыто сразу несколько критических ошибок, которые блокируют работу алгоритма:
Выгрузить(,"ГУИД") для табличной части возвращает объект типа ТаблицаЗначений, а не массив. При попытке установить таблицу значений в качестве значения отбора для измерения типа УникальныйИдентификатор, система не сможет корректно сопоставить данные.Отбор в наборе записей поддерживает исключительно вид сравнения «Равно». Вы не можете передать туда список значений или массив, чтобы система обработала «все записи из списка» за один проход.НаборЗаписей гласит: любая запись, добавляемая в набор, должна иметь значения измерений, в точности соответствующие установленным фильтрам (отборам). Если вы установили отбор ГУИД = Значение_А, то при попытке добавить в этот же набор запись с ГУИД = Значение_Б, платформа выдаст ошибку несоответствия.Давайте выясним причину, по которой платформа накладывает такие строгие ограничения. НаборЗаписей — это не просто коллекция строк, это проекция (выборка) данных из таблицы базы данных, ограниченная конкретными значениями измерений. Когда мы вызываем метод Записать(Истина), система выполняет две операции в рамках одной транзакции:
Если бы система позволяла устанавливать отбор «В списке», операция Записать(Истина) приводила бы к непредсказуемым результатам: очистке огромных пластов данных при записи всего нескольких строк. Поэтому 1С требует четко определять границы «порции» данных, с которой мы работаем.
Если нам необходимо обновить записи по списку различных ГУИДов, мы должны обрабатывать каждый ГУИД в отдельном наборе записей. Рассмотрим, как это реализовать правильно:
// Получаем массив уникальных идентификаторов корректно
МассивГУИДов = Объект.Товары.ВыгрузитьКолонку("ГУИД");
Для Каждого ТекущийГУИД Из МассивГУИДов Цикл
Набор = РегистрыСведений.СтатусНоменклатуры.СоздатьНаборЗаписей();
// Устанавливаем отбор строго по одному конкретному значению
Набор.Отбор.ГУИД.Установить(ТекущийГУИД);
// Если нужно просто удалить старые записи и добавить новые:
// Набор.Записать(); // Очистит записи по этому ГУИДу
// Добавляем новую запись
НоваяЗапись = Набор.Добавить();
НоваяЗапись.ГУИД = ТекущийГУИД;
НоваяЗапись.ДокументПредприятия = Объект.Ссылка;
НоваяЗапись.СтатусНоменклатуры = СтатусНоменклатуры;
НоваяЗапись.Период = Объект.ДатаСоздания;
// Записываем набор с замещением (Истина по умолчанию)
// Это удалит старые записи по данному ГУИДу и создаст новую
Набор.Записать();
КонецЦикла;
Для независимых регистров сведений, когда требуется изменить или создать ровно одну запись за раз, удобно использовать РегистрСведенийМенеджерЗаписи. Этот объект работает медленнее набора при массовых операциях, но его код более лаконичен.
Проанализируем пример использования менеджера записи:
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
МенеджерЗаписи = РегистрыСведений.СтатусНоменклатуры.СоздатьМенеджерЗаписи();
// Заполняем ключевые поля (измерения и период для периодических регистров)
МенеджерЗаписи.ГУИД = СтрокаТЧ.ГУИД;
МенеджерЗаписи.Период = Объект.ДатаСоздания;
// Читаем существующую запись, если она есть
МенеджерЗаписи.Прочитать();
// Заполняем ресурсы и реквизиты
МенеджерЗаписи.ДокументПредприятия = Объект.Ссылка;
МенеджерЗаписи.СтатусНоменклатуры = СтатусНоменклатуры;
// Записываем (перезаписывает существующую или создает новую)
МенеджерЗаписи.Записать();
КонецЦикла;
При работе с типом УникальныйИдентификатор в измерениях следует учитывать специфику платформы 1С:
ГУИД табличной части действительно хранятся объекты типа УникальныйИдентификатор. Если там хранятся строки (например, "550e8400-e29b-41d4-a716-446655440000"), то при установке отбора необходимо преобразовать строку: Новый УникальныйИдентификатор(СтрокаГУИД).ГУИД, вы замещаете (удаляете) все исторические записи по этому идентификатору за все даты. Если ваша задача — изменить запись только на конкретную дату, в отбор набора записей необходимо также включить Период.Выполнение записи в цикле (как в «Способе №1») может быть медленным, если строк в таблице очень много (тысячи). В таких случаях рекомендуется:
НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Это значительно ускорит работу с СУБД.Организация), обязательно включайте их в отбор. Чем точнее отбор, тем быстрее СУБД находит и блокирует нужный диапазон данных.Таким образом, основная ошибка заключалась в попытке использовать НаборЗаписей как универсальный контейнер для разных групп данных. Помните: один набор — одно значение для каждого измерения в отборе.