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