Почему не срабатывает проверка заполнения в 1С и как это исправить

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

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

Разбор причины: почему «красные поля» не останавливают запись

Для начала проанализируем, как работает платформа. Красное подчеркивание — это лишь визуальная индикация (интерфейсный уровень). Автоматическая блокировка записи при пустых реквизитах срабатывает только при использовании стандартных команд формы (например, системной кнопки «Записать и закрыть»). Если же мы создаем свою команду и описываем ее алгоритм в коде, мы берем на себя ответственность за инициацию проверки.

Рассмотрим стандартную ошибку в коде, когда проверка игнорируется:


&НаКлиенте
Процедура СтартПрограммно(Команда)
    // Просто вызываем запись, платформа не проверяет заполнение по умолчанию
    Записать(); 
    СтартПрограммноНаСервере();
КонецПроцедуры

В данном примере метод Записать() просто отправляет данные в базу. Чтобы платформа выполнила проверку, ей нужно дать команду. Выясним, как это сделать правильно.

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

Самый корректный и «чистый» способ — вызвать метод ПроверитьЗаполнение() непосредственно в обработчике команды на клиенте. Этот метод возвращает Истина, если все обязательные поля заполнены, и Ложь, если есть ошибки. При этом платформа сама выведет пользователю сообщения обо всех незаполненных реквизитах.

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


&НаКлиенте
Процедура СтартИЗакрытьПрограммно(Команда)
    // Проверяем заполнение перед выполнением каких-либо действий
    Если ЭтаФорма.ПроверитьЗаполнение() Тогда
        // Если проверка пройдена, записываем объект и запускаем процесс
        Записать();
        СтартПрограммноНаСервере();
        Закрыть();
    КонецЕсли;
КонецПроцедуры

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

Решение 2: Проверка в модуле объекта (ПередЗаписью)

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

Посмотрим на пример кода в модуле объекта:


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

    // Вызываем стандартную проверку
    Если Не ЭтотОбъект.ПроверитьЗаполнение() Тогда
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Если вы устанавливаете Отказ = Истина в модуле объекта, пользователь может получить системную ошибку «Не удалось записать объект», которая выглядит менее дружелюбно, чем стандартное сообщение о незаполненном поле.

Почему проверка может не работать даже при вызове методов

Разберем ситуации, когда мы вызвали нужные функции, но проверка все равно «пролетает» мимо:

  1. Режим загрузки данных: Если в коде установлено Объект.ОбменДанными.Загрузка = Истина, платформа отключает все проверки, включая ОбработкаПроверкиЗаполнения. Это часто бывает при программном создании бизнес-процессов из других модулей.
  2. Особенности метода Старт(): Для бизнес-процессов метод Старт() инициирует запись. Если вы вызываете его на сервере через Объект.Ссылка.ПолучитьОбъект().Старт(), проверка может не сработать, так как объект получен напрямую из базы, минуя контекст формы.
  3. Массив ПроверяемыеРеквизиты: В модуле объекта существует предопределенная процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты). Проверьте, не удаляет ли кто-то программно ваши реквизиты из массива ПроверяемыеРеквизиты.
  4. Свойство формы: У самой управляемой формы есть свойство «Автоматическая проверка заполнения». Если там стоит значение «Не проверять», то даже стандартные механизмы могут давать сбой.

Разница между проверкой на Клиенте и на Сервере

Рассмотрим подробнее, где именно выполняется метод ПроверитьЗаполнение(), так как от этого зависит результат:

1. На Клиенте (в модуле формы): Метод проверяет и реквизиты самого объекта, и реквизиты формы, которые не связаны с объектом, но имеют пометку «Проверка заполнения».

2. На Сервере (в модуле объекта): Метод ЭтотОбъект.ПроверитьЗаполнение() «видит» только те данные, которые принадлежат самому объекту (поля таблиц БД). Если у вас на форме есть дополнительные элементы, влияющие на логику, проверка в модуле объекта их проигнорирует.

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

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

  1. Всегда устанавливайте Выдавать ошибку в свойствах реквизита в дереве метаданных.
  2. В пользовательских командах формы всегда первым делом вызывайте Если ПроверитьЗаполнение() Тогда....
  3. Если логика проверки сложная (зависит от условий), описывайте ее в ОбработкаПроверкиЗаполнения в модуле объекта, добавляя или удаляя поля из массива ПроверяемыеРеквизиты.

Пример динамического управления проверкой в модуле объекта:


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

Таким образом, мы обеспечиваем гибкость и гарантируем, что бизнес-процесс не будет запущен с некорректными данными, а пользователь получит понятное и своевременное уведомление об ошибке.

← На главную