При разработке на платформе 1С:Предприятие 8 часто возникает задача валидации данных в таблице значений (ТЗ). Типичная ситуация: имеется таблица с множеством колонок, и перед выполнением какой-либо операции (например, созданием элементов справочника) необходимо убедиться, что все критически важные поля заполнены. Писать громоздкие конструкции Если ЗначениеЗаполнено(Колонка1) И ЗначениеЗаполнено(Колонка2)... неудобно, особенно если состав колонок может меняться.
В этой статье мы разберем несколько эффективных методов, которые позволяют автоматизировать проверку заполненности ТЗ, минимизировать ручной код и использовать встроенные возможности платформы.
Если ваша таблица значений является реквизитом формы, мы можем задействовать штатный механизм платформы, который обычно используется для проверки реквизитов объекта. Это самый «правильный» путь с точки зрения пользовательского интерфейса, так как платформа сама подсветит пустые ячейки красным цветом.
Разберем по шагам, как это настроить:
// Вызов стандартной проверки формы
Если ЭтотОбъект.ПроверитьЗаполнение() Тогда
// Если проверка пройдена, выполняем логику
СоздатьЭлементыНаОснованииТЗ();
КонецЕсли;
Этот метод избавляет нас от написания циклов. Платформа самостоятельно обойдет строки и колонки, проверит их типы и выдаст пользователю понятное сообщение со списком ошибок.
Если нам нужно программно определить наличие незаполненных ячеек в конкретной колонке без вывода сообщений пользователю, мы можем использовать метод НайтиСтроки(). Рассмотрим ситуацию, когда колонка имеет определенный тип (например, ссылку на справочник).
Проанализируем пример кода:
// Формируем структуру отбора для поиска пустой ссылки
Отбор = Новый Структура;
Отбор.Вставить("Контрагент", Справочники.Контрагенты.ПустаяСсылка());
// Ищем все строки, где контрагент не заполнен
МассивПустыхСтрок = ТаблицаЗначений.НайтиСтроки(Отбор);
Если МассивПустыхСтрок.Количество() > 0 Тогда
Сообщить("Обнаружено незаполненных строк: " + МассивПустыхСтрок.Количество());
КонецЕсли;
Важный нюанс: метод НайтиСтроки() работает очень быстро, но требует точного указания «пустого» значения для конкретного типа данных. Если колонка составного типа, этот метод может быть менее эффективен.
Один из самых мощных способов — передать таблицу значений в запрос. Это позволяет проверить сразу несколько условий заполненности для всех строк без использования циклов Для Каждого.
Выясним, как реализовать такую проверку:
// Создаем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЗ.НомерСтроки КАК НомерСтроки
|ИЗ
| &ВТ_ТЗ КАК ТЗ
|ГДЕ
| (ТЗ.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
| ИЛИ ТЗ.Сумма = 0
| ИЛИ ТЗ.Комментарий = """")";
Запрос.УстановитьПараметр("ВТ_ТЗ", ТаблицаЗначений);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка ошибок
КонецЦикла;
КонецЕсли;
Этот метод особенно полезен, если в таблице тысячи строк. Запрос на стороне сервера отработает значительно быстрее, чем перебор ячеек во встроенном языке.
Если мы все же вынуждены использовать перебор, но хотим сделать код универсальным (чтобы не перечислять имена колонок вручную), проанализируем ситуацию с использованием коллекции Колонки. Это позволит написать одну функцию для таблиц любого состава.
Функция СтрокаЗаполненаПолностью(ТекущаяСтрока, Таблица)
Для Каждого Колонка Из Таблица.Колонки Цикл
ИмяКолонки = Колонка.Имя;
Если Не ЗначениеЗаполнено(ТекущаяСтрока[ИмяКолонки]) Тогда
Возврат Ложь; // Нашли незаполненное поле
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Такой подход позволяет один раз реализовать проверку и применять её к любой таблице. Мы просто передаем строку и саму таблицу в функцию.
Рассмотрим еще один интересный вариант: автоматизация контроля в момент ввода данных. Мы можем добавить в таблицу скрытую колонку ЗначенияВсеЗаполнены с типом Булево.
При изменении данных в любой из ключевых колонок, мы вызываем одну и ту же процедуру, которая обновляет этот признак:
&НаКлиенте
Процедура ТаблицаПриИзмененииКолонки(Элемент)
ТекущаяСтрока = Элементы.Таблица.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
// Автоматический расчет признака заполненности
ТекущаяСтрока.ЗначенияВсеЗаполнены = ЗначениеЗаполнено(ТекущаяСтрока.Колонка1)
И ЗначениеЗаполнено(ТекущаяСтрока.Колонка2);
КонецЕсли;
КонецПроцедуры
Теперь, когда нам нужно обработать таблицу, мы просто проверяем одну колонку-флаг, не тратя время на повторные вычисления.
Если нам не важно, в какой именно строке ошибка, а нужно лишь понять, есть ли пустые значения в принципе, мы можем воспользоваться методом Свернуть().
Разберем этот алгоритм:
ВыгрузитьКолонку().КопияТЗ.Свернуть("ИмяКолонки").0, "", ПустаяСсылка), значит, в исходных данных были пропуски.Этот способ крайне эффективен для быстрой предварительной валидации больших массивов данных перед их загрузкой в базу.
Проанализируем ситуацию, когда колонка может содержать и строку, и ссылку (составной тип). В этом случае стандартная проверка на ПустуюСсылку в запросе может не сработать для строковых значений.
Для корректной проверки в запросах рекомендуется использовать конструкцию ВЫРАЗИТЬ или проверять на NULL, если данные поступают из внешних источников. В коде же 1С функция ЗначениеЗаполнено() является универсальной и корректно обрабатывает пустые значения всех типов, включая неопределенные значения и пустые ссылки составных типов.
Подводя итог, выбор метода зависит от контекста: для интерфейсных форм идеально подходит ПроверитьЗаполнение(), для серверной обработки больших таблиц — Запросы, а для универсальных алгоритмов — обход коллекции Колонки.