Как обойти свойства Обязательное заполнение и Запрет незаполненных значений в измерениях регистра

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

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

Различие между проверкой заполнения и запретом незаполненных значений

Прежде всего, проанализируем разницу между двумя ключевыми свойствами метаданных, которые часто путают. От этого зависит выбор метода решения задачи.

  1. Проверка заполнения (Fill Check). Это свойство логического уровня. Оно определяет, будет ли платформа выдавать предупреждение пользователю при интерактивном вводе данных в форме. Эта проверка легко обходится программным способом (методом Записать()) или установкой свойства ОбменДанными.Загрузка = Истина.
  2. Запрет незаполненных значений (Don't Allow Unfilled Values). Это ограничение физического уровня базы данных. На уровне СУБД для соответствующего поля таблицы часто устанавливается признак NOT NULL. Если это свойство включено, платформа 1С на уровне ядра проверяет наличие данных в момент фиксации транзакции записи. Именно здесь возникает ошибка: "Запись не верна! Значение поля не может быть пустым!".

Рассмотрим ситуацию: если в метаданных стоит Запрет незаполненных значений, то даже режим ОбменДанными.Загрузка = Истина может не спасти, так как платформа не может записать в таблицу БД запись, нарушающую ее структурную целостность.

Способ 1. Полная очистка набора записей регистратора

Если ваша задача — просто избавиться от "битых" остатков, которые висят на пустом измерении, и вы не планируете восстанавливать в них данные, самым простым и безопасным методом будет полная очистка движений конкретного документа-регистратора.

Выясним причину, почему это работает: при записи пустого набора записей платформа не проверяет значения измерений, так как самих строк данных в наборе нет. Мы просто удаляем все записи этого документа из таблицы регистра.

Рассмотрим пример кода для очистки движений:


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

Способ 2. Заполнение "техническим" значением (заглушкой)

В случае, если вам необходимо не просто удалить записи, а корректно "закрыть" остатки (списать их), вам придется создать движение с тем же набором измерений, который был изначально. Но так как пустое измерение записать нельзя, проанализируем вариант с использованием технического элемента.

Посмотрим на алгоритм действий:

  1. Создайте в справочнике, на который ссылается измерение (например, ОбъектыРасчетов), специальный служебный элемент с наименованием "Удалить (не используется)" или "Технический добор".
  2. Программно считайте текущие "неправильные" движения документа.
  3. В наборе записей замените пустую ссылку в измерении на вашу новую техническую ссылку.
  4. Запишите набор.
  5. Создайте новый документ (например, КорректировкаРегистров), где спишите остаток уже по этому техническому элементу.

Пример кода для программной замены значения в измерениях:


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

Способ 3. Использование флага ОбменДанными.Загрузка (нюансы)

В некоторых версиях платформы и при определенных настройках метаданных (если свойство "Запрет" не привело к жесткому NOT NULL в базе), программная запись с флагом ОбменДанными.Загрузка = Истина может сработать. Это происходит потому, что данный флаг отключает проверку Fill Check и выполнение кода в событиях ПередЗаписью и ПриЗаписи, где часто располагаются дополнительные проверки, написанные разработчиками конфигурации.

Попробуем выполнить запись в этом режиме:


Набор = РегистрыНакопления.ВашРегистр.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
// ... заполнение набора ...
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать(); 

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

Почему нельзя просто "исправить" через Тестирование и исправление?

Многие полагают, что штатный механизм Тестирование и исправление с галочкой "Очищать ссылки" или "Проставлять значения по умолчанию" решит проблему. Однако, проанализируем ситуацию: если в базе уже есть записи с NULL или пустыми ссылками, а вы включили Запрет незаполненных значений, ТиИ может попытаться исправить записи, но столкнется с тем же самым платформенным ограничением при записи. В некоторых случаях ТиИ может поместить записи в "Объект не найден", что тоже потребует последующей ручной или программной обработки.

Резюме

При возникновении ошибки "Значение поля не может быть пустым" в регистрах:

Такой подход позволяет корректно обслуживать базу данных, сохраняя целостность учета и не прибегая к внесению изменений в типовую конфигурацию.

← На главную