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

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

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

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

Типичные ошибки при написании проверок

Разберем ситуации, с которыми часто сталкиваются начинающие программисты 1С при попытке проверить реквизиты табличной части:

  1. Передача имени реквизита в виде строки в функцию ЗначениеЗаполнено(). Если написать ЗначениеЗаполнено("ВремяНачала"), то функция проверит заполнение текстовой строки "ВремяНачала", а не самого реквизита. Так как строка не пустая, функция всегда будет возвращать Истина.
  2. Сравнение небулевого реквизита с истиной. Выражение ТекСтрока.ВремяНачала = Истина вернет Ложь, если реквизит имеет тип Дата, СправочникСсылка или любой другой, отличный от Булево.
  3. Использование общих процедур платформы без учета строк. Стандартные типовые функции проверки проверяют реквизиты сразу для всех строк табличной части без учета условий конкретной строки. Для динамической проверки требуется обход строк в цикле.

Решение проблемы: проверка в цикле

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

Рассмотрим пример кода, который помещается в модуль объекта в событие ПередЗаписью или специальную процедуру проверки перед проведением:


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

Разберем подробнее, как работает этот код:

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

Современный подход с выведением сообщений пользователю

Если разработка ведется на управляемых формах или с использованием библиотеки стандартных подсистем (БСП), вместо обычной процедуры Сообщить() рекомендуется использовать объект СообщениеПользователю. Это позволит не просто вывести текст ошибки, но и подсветить конкретную ячейку в табличной части.

Посмотрим на пример реализации в событии ОбработкаПроверкиЗаполнения модуля объекта:


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

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

← На главную