Как проверить заполненность реквизита табличной части документа в 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке и доработке документов часто возникает необходимость проконтролировать корректность ввода данных пользователем. Рассмотрим практическую задачу: в документе ОтчетПроизводстваЗаСмену конфигурации «Управление производственным предприятием» (УПП 1.3) требуется проверить, заполнен ли реквизит табличной части ЗаказРезерв.

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

Способ 1. Использование встроенной функции ЗначениеЗаполнено()

Самым простым и универсальным способом проверки конкретного значения является использование глобальной контекстной функции ЗначениеЗаполнено(). Она появилась еще в платформе 8.1 и остается базовым инструментом разработчика.

Проанализируем важный нюанс: реквизиты резервирования или заказов в производственных документах почти всегда имеют составной тип данных (например, ссылки на документы ЗаказПокупателя и ЗаказНаПроизводство). Функция ЗначениеЗаполнено() идеально подходит для таких полей, поскольку она автоматически возвращает Ложь, если в переменной находится:

  1. Пустая ссылка любого из допустимых ссылочных типов.
  2. Значение Неопределено или Null.
  3. Пустая строка, число ноль или дата 0001-01-01.

Именно из-за составного типа данных стандартный метод поиска строк ТабличнаяЧасть.НайтиСтроки() в этой ситуации неприменим: пустая ссылка одного документа не будет эквивалентна пустой ссылке другого типа или значению Неопределено.

Посмотрим на пример базового обхода табличной части в цикле:


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

Способ 2. Платформенное свойство «Проверка заполнения» в метаданных

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

Однако выясним причину, почему в типовых конфигурациях вроде УПП 1.3 этот механизм подходит далеко не всегда. Платформенное свойство метаданных требует безусловного заполнения реквизита во всех строках документа без исключения. В реальном производственном учете выпуск продукции может оформляться как под конкретный заказ, так и на склад (без резерва) в рамках одного документа. Если включить жесткую проверку в метаданных, документ перестанет проводиться для бескомпромиссных складских выпусков.

Способ 3. Валидация в событии ОбработкаПроверкиЗаполнения

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

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

  1. Исключаем реквизит из автоматической системной проверки, удалив его имя из массива ПроверяемыеРеквизиты.
  2. В цикле проверяем условия для каждой строки.
  3. При обнаружении незаполненного поля формируем объект СообщениеПользователю, указывая путь к конкретной ячейке табличной части. Это позволит пользователю перейти к проблемной строке простым кликом по тексту ошибки.

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


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

    // Выполняем выборочный контроль строк
    Для Индекс = 0 По Продукция.Количество() - 1 Цикл
        Стр = Продукция[Индекс];
        
        // Например, проверяем только если продукция требует резервирования
        Если Стр.ТребуетРезерва И Не ЗначениеЗаполнено(Стр.ЗаказРезерв) Тогда
            Отказ = Истина;
            
            Сообщение = Новый СообщениеПользователю;
            Сообщение.Текст = "Не заполнен заказ резерва в строке " + (Индекс + 1);
            Сообщение.Поле = "Продукция[" + Индекс + "].ЗаказРезерв";
            Сообщение.УстановитьДанные(ЭтотОбъект);
            Сообщение.Сообщить();
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

Способ 4. Проверка больших табличных частей через запрос

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

Запрос мгновенно возвращает номера строк, где реквизит не указан, без перебора объектов памяти:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТЧ.НомерСтроки КАК НомерСтроки
    |ИЗ
    |    Документ.ОтчетПроизводстваЗаСмену.Продукция КАК ТЧ
    |ГДЕ
    |    ТЧ.Ссылка = &Ссылка
    |    И (ТЧ.ЗаказРезерв ЕСТЬ NULL 
    |        ИЛИ ТЧ.ЗаказРезерв = ЗНАЧЕНИЕ(Документ.ЗаказПокупателя.ПустаяСсылка)
    |        ИЛИ ТЧ.ЗаказРезерв = ЗНАЧЕНИЕ(Документ.ЗаказНаПроизводство.ПустаяСсылка))";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Результат = Запрос.Выполнить();

Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Обрабатываем найденные ошибки
    КонецЦикла;
КонецЕсли;

Где размещать код проверки: форма или модуль объекта

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

  1. Модуль формы: проверки в событиях ПередЗаписью или ПриИзменении формы срабатывают только при интерактивном вводе данных пользователем. При программной записи документа эти обработчики игнорируются.
  2. Модуль объекта: размещение проверок в процедурах ОбработкаПроверкиЗаполнения, ПередЗаписью или ОбработкаПроведения модуля объекта гарантирует целостность учетных данных независимо от того, каким способом был создан документ.
← На главную