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