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

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

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

Метод 1. Простой обход коллекции (Цикл с флагами)

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

Проанализируем пример кода, который позволяет за один проход определить статус:


КолвоСтрок = Объект.МТЦ.Количество();
КолвоЗаполненных = 0;

Для Каждого Стр Из Объект.МТЦ Цикл
    Если ЗначениеЗаполнено(Стр.Выбор) Тогда
        КолвоЗаполненных = КолвоЗаполненных + 1;
    КонецЕсли;
КонецЦикла;

Если КолвоЗаполненных = 0 Тогда
    Объект.СтатусЗаявки = Перечисления.Статусы.НеЗаполнено;
ИначеЕсли КолвоЗаполненных = КолвоСтрок Тогда
    Объект.СтатусЗаявки = Перечисления.Статусы.ВРаботе;
Иначе
    Объект.СтатусЗаявки = Перечисления.Статусы.ЧастичноВРаботе;
КонецЕсли;

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

Метод 2. Использование поиска пустых значений

Чтобы ускорить процесс, мы можем не перебирать все строки, а попробовать найти «пустое» значение. В 1С для этого используется метод Найти. Выясним, как это работает: если метод возвращает Неопределено, значит, пустых строк нет.

Рассмотрим пример реализации:


// Определим, что считается пустым значением для типа реквизита "Выбор"
ПустоеЗначение = ПредопределенноеЗначение("Справочник.Пользователи.ПустаяСсылка"); 

СтрокаСПустым = Объект.МТЦ.Найти(ПустоеЗначение, "Выбор");
СтрокаСЗаполненным = ""; // Здесь логика сложнее, так как Найти ищет конкретное значение

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

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

Метод 3. Выгрузка в таблицу значений и сворачивание

Один из интересных подходов — это временная выгрузка колонки в объект ТаблицаЗначений с последующим удалением дублей. Проанализируем этот алгоритм: после сворачивания в таблице останутся только уникальные значения. Если в итоге осталась одна строка и она заполнена — значит, заполнено всё. Если строк больше одной — заполнение частичное.

Посмотрим на программную реализацию этого метода:


ТЗ = Объект.МТЦ.Выгрузить( , "Выбор");
ТЗ.Свернуть("Выбор");

Если ТЗ.Количество() > 1 Тогда
    // В таблице есть и пустые, и заполненные значения
    Объект.СтатусЗаявки = Перечисления.Статусы.ЧастичноВРаботе;
ИначеЕсли ТЗ.Количество() = 1 Тогда
    Если ЗначениеЗаполнено(ТЗ[0].Выбор) Тогда
        Объект.СтатусЗаявки = Перечисления.Статусы.ВРаботе;
    Иначе
        Объект.СтатусЗаявки = Перечисления.Статусы.НетОтветственных;
    КонецЕсли;
КонецЕсли;

Плюс данного метода: лаконичность кода. Минус: метод Выгрузить копирует данные в память, что при больших объемах ТЧ не очень оптимально.

Метод 4. Оптимизация через запрос (Профессиональный подход)

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

Разберем, как составить такой запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СУММА(ВЫБОР
    |			КОГДА МТЦ.Выбор <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)
    |				ТОГДА 1
    |			ИНАЧЕ 0
    |		КОНЕЦ) КАК КолвоЗаполненных,
    |	КОЛИЧЕСТВО(МТЦ.НомерСтроки) КАК ВсегоСтрок
    |ИЗ
    |	Документ.Заявка.МТЦ КАК МТЦ
    |ГДЕ
    |	МТЦ.Ссылка = &Ссылка";

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

Если Выборка.Следующий() Тогда
    Если Выборка.КолвоЗаполненных = 0 Тогда
        Объект.СтатусЗаявки = Перечисления.Статусы.НетОтветственных;
    ИначеЕсли Выборка.КолвоЗаполненных = Выборка.ВсегоСтрок Тогда
        Объект.СтатусЗаявки = Перечисления.Статусы.ВРаботе;
    Иначе
        Объект.СтатусЗаявки = Перечисления.Статусы.ЧастичноВРаботе;
    КонецЕсли;
КонецЕсли;

Этот способ является наиболее производительным, так как платформа 1С оптимизирует выполнение запросов на уровне SQL-сервера.

Метод 5. Использование агрегатной функции Итог

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

Например, если реквизит Выбор — это Булево (галочка), то код будет выглядеть так:


ВсегоСтрок = Объект.МТЦ.Количество();
СуммаИстин = Объект.МТЦ.Итог("Выбор"); // Истина считается как 1

Если СуммаИстин = 0 Тогда
    Объект.СтатусЗаявки = "Не заполнено";
ИначеЕсли СуммаИстин = ВсегоСтрок Тогда
    Объект.СтатусЗаявки = "Заполнено";
Иначе
    Объект.СтатусЗаявки = "Частично";
КонецЕсли;

Рекомендации по выбору решения

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

  1. Если проверка происходит в интерактивном режиме (при изменении строки пользователем) — лучше использовать Метод 2 (Поиск) или простой цикл с прерыванием, так как данных в этот момент немного, и важна скорость отклика интерфейса.
  2. Если проверка выполняется при проведении документа — крайне желательно использовать Метод 4 (Запрос). Это обеспечит стабильную работу даже при очень большом количестве строк в документе.
  3. Для простых логических проверок — используйте метод Итог, если тип данных позволяет это сделать.

Важный нюанс: при проверке заполненности всегда учитывайте тип данных реквизита. Помните, что для строки «пусто» — это "", для ссылки — ПустаяСсылка, для числа — 0, а для даты — 01.01.0001. Использование функции ЗначениеЗаполнено() позволяет абстрагироваться от этих различий и писать более универсальный код.

← На главную