Как правильно реализовать условную проверку заполнения реквизитов в табличной части 1С и избежать типичных ошибок в булевой логике

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

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

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

Разберем по шагам: приоритеты логических операторов И и ИЛИ

Проанализируем ситуацию, с которой столкнулся автор темы. Изначально задача формулировалась следующим образом: если в строке табличной части заполнены поля Номенклатура и Количество, то необходимо проверить, заполнено ли поле Качество (или в реальной задаче — Дисциплина). Если оно не заполнено, система должна вывести предупреждение.

В состоянии сильной усталости разработчик попытался написать следующее условие:


Если НЕ ЗначениеЗаполнено(Строка.Номенклатура) И НЕ ЗначениеЗаполнено(Строка.Количество) ИЛИ ЗначениеЗаполнено(Строка.Качество) Тогда
    Сообщить("Качество не в действии");
КонецЕсли;

Выясним причину, почему данная конструкция работает некорректно и приводит к непредсказуемым результатам. Всё дело в приоритете логических операторов в языке программирования 1С. Оператор И имеет более высокий приоритет, чем оператор ИЛИ. В результате платформа вычисляет написанное условие следующим образом:

  1. Сначала вычисляется левая часть с оператором И: (НЕ ЗначениеЗаполнено(Номенклатура) И НЕ ЗначениеЗаполнено(Количество)).
  2. Затем полученный результат объединяется по условию ИЛИ с правой частью: ... ИЛИ ЗначениеЗаполнено(Качество).

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

Чтобы исправить эту логическую ошибку в рамках одного простого условия, необходимо четко расставить приоритеты с помощью скобок или переписать логику «от противного». Посмотрим на пример правильного простого условия:


Если ЗначениеЗаполнено(Строка.Номенклатура) И ЗначениеЗаполнено(Строка.Количество) И НЕ ЗначениеЗаполнено(Строка.Качество) Тогда
    Сообщить("Поле ""Качество"" не заполнено!");
КонецЕсли;

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

Технические особенности проверки заполнения для типа Булево

Рассмотрим подробнее важный нюанс, упомянутый участниками обсуждения. Что произойдет, если реквизит Качество имеет тип Булево? Здесь разработчиков часто подстерегает скрытая ловушка.

Дело в том, что системная функция ЗначениеЗаполнено() работает с типом Булево специфическим образом:

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

Профессиональное решение: использование события ОбработкаПроверкиЗаполнения

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

Современный и профессиональный стандарт разработки на платформе 1С:Предприятие 8.3 подразумевает использование специализированного обработчика **ОбработкаПроверкиЗаполнения** в модуле объекта (документа или справочника). Этот механизм позволяет красиво подсвечивать незаполненные поля красным цветом и автоматически фокусировать на них внимание пользователя при попытке записи или проведения.

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


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

Разберем по шагам, что делает этот код:

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

Визуальное оформление на форме: свойство АвтоОтметкаНезаполненного

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

АвтоОтметкаНезаполненного — это свойство элемента управления (поля ввода) на форме. Когда оно включено (равно Истина), платформа автоматически подчеркивает поле на форме красным пунктиром, сигнализируя пользователю о необходимости ввода данных. Однако важно помнить следующее:

Таким образом, сочетание грамотной серверной валидации в событии ОбработкаПроверкиЗаполнения и своевременное визуальное оформление интерфейса позволяет создавать надежные, отказоустойчивые и удобные для пользователей программные продукты на базе 1С:Предприятие.

← На главную