Почему не срабатывает «Проверка заполнения» при записи в регистр и как настроить контроль данных?

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

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

Природа свойства «Проверка заполнения»

Первое и самое важное, что нам необходимо усвоить: свойство «Проверка заполнения» в объектах метаданных является декларативным интерфейсным свойством. Рассмотрим подробнее, что это значит. Платформа 1С проектировалась так, чтобы минимизировать написание однотипного кода в формах. Чтобы разработчику не приходилось в каждой форме документа или справочника писать условие Если ЗначениеЗаполнено(Реквизит) = Ложь Тогда..., была введена автоматизация на уровне метаданных.

Это свойство служит инструкцией для Управляемой формы. Когда пользователь нажимает кнопку «Записать» или «Провести» в интерфейсе, платформа автоматически запускает механизм ПроверитьЗаполнение(). Если свойство установлено в «Выдавать ошибку», поле подчеркивается красным пунктиром, и выполнение прерывается. Однако при выполнении программного кода типа:


Движение = Движения.МойРегистр.Добавить();
ЗаполнитьЗначенияСвойств(Движение, Выборка);
Движения.МойРегистр.Записать();

Платформа полагает, что разработчик действует осознанно и сам контролирует корректность передаваемых данных. В этом случае автоматическая проверка не запускается. Это сделано для обеспечения производительности и гибкости: в коде могут быть ситуации, когда объект нужно записать во временном «черновом» состоянии.

Решение №1: Использование метода ПроверитьЗаполнение()

Если нам необходимо, чтобы программная запись подчинялась тем же правилам, что и интерактивная, мы должны явно вызвать проверку в коде. Разберем, как это реализовать. Перед вызовом метода Записать() следует вызвать метод ПроверитьЗаполнение(). Этот метод возвращает Истина, если все реквизиты, помеченные в метаданных, заполнены, и Ложь в противном случае.

Посмотрим на пример правильной организации записи:


Если Движения.МойРегистр.ПроверитьЗаполнение() Тогда
    Движения.МойРегистр.Записать();
Иначе
    // Обработка ошибки, если данные некорректны
    ВызватьИсключение "Ошибка заполнения обязательных полей в регистре!";
КонецЕсли;

При вызове этого метода платформа также инициирует событие ОбработкаПроверкиЗаполнения в модуле набора записей регистра. Это дает возможность реализовать сложную логику проверки, зависящую от условий.

Решение №2: Свойство «Запрет незаполненных значений»

Выясним разницу между «Проверкой заполнения» и «Запретом незаполненных значений». Эти свойства часто путают, но они работают на разных уровнях системы. Если «Проверка заполнения» — это уровень интерфейса, то «Запрет незаполненных значений» — это уровень СУБД (движка базы данных).

Рассмотрим характеристики этого свойства:

  1. Бескомпромиссность: Оно работает всегда. Неважно, записываете ли вы объект из формы, программно через Движения или даже через внешнее соединение — база данных просто не примет запись с «пустой» ссылкой или нулевым значением.
  2. Исключения: Если условие нарушено, система генерирует системное исключение (Run-time error), которое прерывает транзакцию.
  3. Ограничения: Для составных типов данных это свойство работает специфично — оно запрещает только значение Неопределено, но может пропустить пустую ссылку одного из допустимых типов.

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

Особенности проверки в регистрах, подчиненных регистратору

В случае с регистрами сведений или накопления, которые записываются документом, есть важный нюанс. Платформа 1С автоматически проверяет заполнение реквизитов самого документа при его записи из формы. Однако она не «спускается» автоматически внутрь табличных частей или наборов записей движений для проверки их свойств метаданных.

Выделим шаги для надежной проверки движений в документе:

Пример кода в модуле документа:


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

Влияние режима «ОбменДанными.Загрузка»

Стоит отдельно упомянуть свойство ОбменДанными.Загрузка. Даже если вы используете метод ПроверитьЗаполнение() или написали свою проверку в событии ПередЗаписью, общепринятой практикой в 1С является обход этих проверок, если Загрузка = Истина. Это необходимо для беспрепятственного переноса данных между базами.

Однако помните: «Запрет незаполненных значений» (тот самый, что на уровне СУБД) сработает даже при Загрузка = Истина. Это еще один аргумент в пользу того, чтобы использовать это свойство только для самых критичных полей, без которых существование записи физически невозможно или бессмысленно.

Резюме и рекомендации

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

  1. Используйте «Проверку заполнения» в метаданных для визуальной подсказки пользователю в формах.
  2. Для программного контроля (в обработках или при проведении документов) всегда вызывайте метод Объект.ПроверитьЗаполнение().
  3. Если поле является фундаментальным (например, «Организация» в финансовом регистре), устанавливайте «Запрет незаполненных значений».
  4. Если логика проверки сложная (зависит от даты, вида операции или других реквизитов), реализуйте её в обработчике ОбработкаПроверкиЗаполнения в модуле объекта/регистра. Это позволит сосредоточить логику контроля в одном месте, и она будет вызываться как автоматически формой, так и вашим программным вызовом ПроверитьЗаполнение().

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

← На главную