Как исправить ошибку «Значение поля не соответствует установленному отбору» при изменении записи регистра сведений?

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

При работе с независимыми регистрами сведений в 1С программисты часто сталкиваются с неприятной ситуацией: при попытке изменить ресурсы существующей записи через СоздатьМенеджерЗаписи() система выдает критическую ошибку: «Запись не верна! Значение поля не соответствует установленному отбору». Особенно часто это происходит в типовых конфигурациях (ЗУП 3.1, ERP 2.5, КА), где на регистры «навешано» множество подписок на события. Разберем подробно, почему это происходит и как правильно изменить данные, чтобы избежать конфликтов с бизнес-логикой платформы.

Анализируем причину ошибки

Рассмотрим ситуацию, описанную в теме. Программист пытается изменить даты в регистре ТрудоваяДеятельностьФизическихЛиц. В этом регистре есть два ключевых измерения: ФизическоеЛицо и НомерПоПорядку. Код выглядит логично: создается менеджер записи, устанавливаются измерения, данные прочитываются, меняются ресурсы и вызывается метод Записать(). Однако платформа блокирует действие.

Выясним причину. Когда мы используем МенеджерЗаписи, платформа 1С автоматически устанавливает отбор по всем измерениям, которые были указаны перед вызовом метода Прочитать(). В момент вызова Записать() система проверяет, соответствуют ли значения измерений в объекте установленному в начале пути отбору. Если в процессе записи (например, внутри подписки на событие или в модуле набора записей) какое-либо измерение программно меняется, возникает конфликт.

В случае с регистром трудовой деятельности часто срабатывает типовая подписка (например, ПроверитьЗаписиДанныхФизическихЛиц), которая пересчитывает НомерПоПорядку. Если система видит, что нумерация нарушена, она может принудительно изменить 2 на 1. Менеджер записи, который «ожидает» только номер 2, видит подмену и выбрасывает ошибку соответствия отбору.

Решение №1: Использование Набора Записей (Рекомендуемое)

Наиболее надежный и правильный способ решения проблемы — отказ от МенеджераЗаписи в пользу НабораЗаписей. Это позволяет нам установить отбор только по тем измерениям, которые мы НЕ планируем менять (например, только по физическому лицу), и работать со всеми строками этого объекта сразу.

Разберем по шагам, как реализовать этот алгоритм:

  1. Создадим объект НаборЗаписей.
  2. Установим отбор по основному измерению (ФизическоеЛицо).
  3. Прочитаем данные из базы.
  4. Найдем в наборе конкретную строку, которую нужно модифицировать.
  5. Произведем изменения и запишем набор целиком.

Посмотрим на пример кода, который решает проблему:


// Создаем набор записей
НаборТрудовойДеятельности = РегистрыСведений.ТрудоваяДеятельностьФизическихЛиц.СоздатьНаборЗаписей();

// Устанавливаем отбор только по физлицу, чтобы не ограничивать конкретный номер по порядку
НаборТрудовойДеятельности.Отбор.ФизическоеЛицо.Установить(СтрокаДанных.ФизическоеЛицо);
НаборТрудовойДеятельности.Прочитать();

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

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

Решение №2: Отключение бизнес-логики через ОбменДанными.Загрузка

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

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

Пример реализации:


ткЗапись = РегистрыСведений.ТрудоваяДеятельностьФизическихЛиц.СоздатьМенеджерЗаписи();
ткЗапись.ФизическоеЛицо = Строка.ФизическоеЛицо;
ткЗапись.НомерПоПорядку = Строка.НомерПоПорядку;
ткЗапись.Прочитать();

// Меняем данные
ВрДата = ткЗапись.ДатаНачала;
ткЗапись.ДатаНачала = ткЗапись.ДатаОкончания;
ткЗапись.ДатаОкончания = ВрДата;

// Отключаем проверки бизнес-логики
ткЗапись.ОбменДанными.Загрузка = Истина;
ткЗапись.Записать();

Важное предостережение: использование ОбменДанными.Загрузка = Истина — это «тяжелая артиллерия». Этот метод может привести к нарушению целостности данных, например, если подписка должна была создать важные связанные записи в других регистрах, а вы это действие заблокировали. Используйте этот метод только тогда, когда точно понимаете последствия.

Дополнительные возможности: ДополнительныеСвойства

В современных конфигурациях на базе БСП часто предусмотрены более тонкие механизмы управления записью. Вместо полного отключения проверок через Загрузка = Истина, можно передать в объект определенный параметр, который поймет конкретная подписка на событие.

Например, в модулях Зарплаты и Кадров часто встречается проверка функции ЗарплатаКадры.ОтключитьБизнесЛогикуПриЗаписи(Источник). Чтобы пройти эту проверку, иногда достаточно добавить свойство в менеджер или набор записей:


ткЗапись.ДополнительныеСвойства.Вставить("ПроверятьБизнесЛогикуПриЗаписи", Ложь);
// Или наоборот, в зависимости от логики конкретной функции в вашей версии конфигурации

Почему Набор Записей лучше Менеджера Записи?

Подведем итог, почему для изменения записей в регистрах со сложной логикой (как в HR-блоке) стоит выбирать именно наборы:

Таким образом, столкнувшись с ошибкой отбора при записи, первым делом проанализируйте, не меняются ли измерения записи в подписках на события. Если это так — смело переходите на использование РегистрСведенийНаборЗаписей с широким отбором.

← На главную