Как правильно добавлять строки в табличную часть 1С и настраивать фильтры в запросах

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

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

Ошибка №1: Неправильное использование метода Добавить() в цикле

Рассмотрим классическую ситуацию: нам нужно заполнить табличную часть списком сотрудников. Часто код выглядит следующим образом:


Стр = ЭтотОбъект.ТабличнаяЧасть1.Добавить();    
Запрос = Новый Запрос("ВЫБРАТЬ Пользователи.Ответственный ИЗ Справочник.Пользователи КАК Пользователи");
    
Рез = Запрос.Выполнить().Выбрать();
Пока Рез.Следующий() Цикл
    Стр.Сотрудник = Рез.Ответственный;
КонецЦикла;

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

Верное решение: Вызов метода Добавить() должен происходить внутри цикла обхода выборки. Таким образом, на каждой итерации (для каждой записи из базы данных) в табличной части будет создаваться новая строка.


Рез = Запрос.Выполнить().Выбрать();
Пока Рез.Следующий() Цикл
    // Создаем новую строку ТЧ для каждого результата запроса
    НоваяСтрока = ЭтотОбъект.ТабличнаяЧасть1.Добавить();  
    НоваяСтрока.Сотрудник = Рез.Ответственный;
КонецЦикла;

Ошибка №2: Особенности оператора ПОДОБНО и использование масок поиска

Часто требуется отобрать данные не по точному совпадению, а по вхождению подстроки в наименование. В языке запросов 1С для этого используется оператор ПОДОБНО. Однако просто написать Наименование ПОДОБНО &Параметр недостаточно, если в самом параметре не указаны специальные символы — маски.

Разберем, почему условие Пользователи.Наименование ПОДОБНО "Производство" может не вернуть результат. Без спецсимволов этот оператор работает практически как обычное равенство. Чтобы поиск работал как «содержит», необходимо использовать символ процента %.

Основные правила использования спецсимволов в ПОДОБНО:

  1. % (Процент) — заменяет любое количество произвольных символов.
  2. _ (Подчеркивание) — заменяет один произвольный символ.
  3. [...] (В квадратных скобках) — любой одиночный символ из указанного набора.

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Пользователи.Ссылка
    |ИЗ
    |   Справочник.Пользователи КАК Пользователи
    |ГДЕ
    |   Пользователи.Наименование ПОДОБНО &Производство
    |   И НЕ Пользователи.Наименование ПОДОБНО &Ростов";

// Указываем маски поиска прямо в значениях параметров
Запрос.УстановитьПараметр("Производство", "%Производство%");
Запрос.УстановитьПараметр("Ростов", "%Ростов%");

Работа с типами данных: Сравнение ссылок и чисел

В процессе обсуждения часто возникают ошибки, связанные с типами данных. Например, попытка сравнить ссылку на справочник с числом: ГДЕ Пользователи.Ответственный > 0. В системе 1С ссылка — это уникальный идентификатор (GUID), а не число. Такое сравнение в запросе является некорректным.

Если нам нужно проверить, заполнено ли поле ссылки, следует использовать проверку на пустую ссылку. Выясним, как это сделать правильно:

  1. Использование конструкции ЗНАЧЕНИЕ(...) внутри текста запроса.
  2. Передача пустой ссылки через параметр (менее предпочтительно, но допустимо).

Пример правильной проверки на заполненность ссылки в запросе:

ГДЕ Пользователи.Ответственный <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)

Оптимизация: Метод Загрузить() против Добавить()

Если ваш запрос возвращает сотни или тысячи строк, использование метода Добавить() в цикле может существенно замедлить работу интерфейса, так как каждое добавление строки вызывает пересчет и обновление элементов формы. Рассмотрим более производительный способ — выгрузку результата запроса в таблицу значений с последующей загрузкой в ТЧ.

Проанализируем пошагово этот алгоритм:

  1. Выполняем запрос и получаем результат.
  2. Выгружаем результат в ТаблицаЗначений.
  3. Используем метод табличной части Загрузить().

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

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

Обработка «битых» ссылок и NULL

При обращении через точку (например, Пользователи.Ответственный.Наименование) в запросе, 1С выполняет неявное ЛЕВОЕ СОЕДИНЕНИЕ. Если поле Ответственный не заполнено, результатом будет NULL. Это может привести к тому, что строка вообще не попадет в выборку при определенных условиях ГДЕ.

Для надежности рекомендуем использовать функцию ЕСТЬNULL(). Рассмотрим пример:


ВЫБРАТЬ
    ЕСТЬNULL(Пользователи.Ответственный.Наименование, "Имя не задано") КАК ФизЛицо
ИЗ
    Справочник.Пользователи КАК Пользователи

Итоговый алгоритм решения задачи

Давайте соберем воедино все рекомендации и составим идеальный блок кода для заполнения ТЧ с учетом фильтров и проверки параметров:


Процедура ЗаполнитьТабличнуюЧасть()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Пользователи.Ответственный КАК Сотрудник,
        |   Пользователи.ОтветственныйНапарник КАК Напарник
        |ИЗ
        |   Справочник.Пользователи КАК Пользователи
        |ГДЕ
        |   Пользователи.Наименование ПОДОБНО &МаскаПроизводство
        |   И НЕ Пользователи.Наименование ПОДОБНО &МаскаРостов
        |   И Пользователи.Ответственный <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)";
    
    // Правильно готовим параметры с процентами
    Запрос.УстановитьПараметр("МаскаПроизводство", "%Производство%");
    Запрос.УстановитьПараметр("МаскаРостов", "%Ростов%");
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    // Перед заполнением можно очистить ТЧ, если это требуется по логике
    // ЭтотОбъект.ТабличнаяЧасть1.Очистить();
    
    Пока Выборка.Следующий() Цикл
        // Добавляем сотрудника
        НоваяСтрока = ЭтотОбъект.ТабличнаяЧасть1.Добавить();
        НоваяСтрока.Сотрудник = Выборка.Сотрудник;
        
        // Добавляем напарника, если он есть (бизнес-логика)
        Если ЗначениеЗаполнено(Выборка.Напарник) Тогда
            СтрокаНапарника = ЭтотОбъект.ТабличнаяЧасть1.Добавить();
            СтрокаНапарника.Сотрудник = Выборка.Напарник;
        КонецЕсли;
    КонецЦикла;

КонецПроцедуры

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

← На главную