При разработке интерфейсов на платформе 1С:Предприятие 8.3 часто возникает классическая задача: необходимо отфильтровать или полностью обновить данные в таблице на форме в зависимости от выбранного значения в другом поле. Например, при выборе сотрудника в шапке формы мы хотим мгновенно увидеть список всех его активных заказов в табличной части. Рассмотрим, как это реализовать правильно, разберем типичные ошибки новичков и проанализируем более продвинутые способы оптимизации работы формы.
Этот метод подходит в тех случаях, когда данные в табличной части являются временными (реквизит формы типа ТаблицаЗначений), и нам нужно программно управлять процессом их получения. Разберем ситуацию, когда у нас есть поле Официант и табличная часть Заказы.
Первым делом проанализируем обработчик события изменения поля. Нам нужно передать управление на сервер, выполнить запрос к базе данных и загрузить результат в таблицу формы.
Рассмотрим пример кода в модуле формы:
&НаКлиенте
Процедура ОфициантПриИзменении(Элемент)
// Вызываем серверную процедуру для получения данных
ЗапроситьСтрокиНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗапроситьСтрокиНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Заказы.НомерСтола КАК НомерСтола,
| Заказы.Ссылка КАК Ссылка,
| Заказы.Сумма КАК Сумма,
| Заказы.СтатусЗаказ КАК СтатусЗаказ
|ИЗ
| Документ.Заказы КАК Заказы
|ГДЕ
| Заказы.Официант = &Официант";
// Устанавливаем параметр, обращаясь напрямую к реквизиту формы "Официант"
Запрос.УстановитьПараметр("Официант", Объект.Официант);
РезультатЗапроса = Запрос.Выполнить();
// Выгружаем результат запроса в таблицу значений
ТЗ = РезультатЗапроса.Выгрузить();
// Очищаем текущую таблицу на форме и загружаем новые данные
Объект.Заказы.Очистить();
Объект.Заказы.Загрузить(ТЗ);
КонецПроцедуры
Важный нюанс: Обратите внимание на установку параметра &Официант. Часто начинающие разработчики пытаются передать строковое имя, однако для корректной работы запроса и использования индексов базы данных необходимо передавать именно СправочникСсылка.Официанты. Проанализируем также использование метода Загрузить(). Он работает максимально быстро, если колонки в РезультатЗапроса полностью совпадают по именам с колонками вашей табличной части.
Если ваша задача — просто отобразить список документов или записей регистра, которые не требуют немедленного редактирования и сохранения в составе текущего объекта, лучшим решением будет использование Динамического списка. Рассмотрим, почему это эффективнее:
Для реализации этого метода создадим на форме реквизит с типом ДинамическийСписок, выберем в качестве основной таблицы Документ.Заказы и настроим произвольный запрос. В тексте запроса добавим условие: ГДЕ Заказы.Официант = &Официант.
Теперь посмотрим на программную часть. В обработчике изменения поля нам достаточно просто обновить значение параметра списка:
&НаКлиенте
Процедура ОфициантПриИзменении(Элемент)
// Устанавливаем параметр динамического списка
// СписокЗаказов — это имя реквизита формы типа ДинамическийСписок
СписокЗаказов.Параметры.УстановитьЗначениеПараметра("Официант", Объект.Официант);
КонецПроцедуры
Платформа сама инициирует перечитку данных, и нам даже не нужно вызывать методы обновления элементов интерфейса.
Выясним причину, по которой формы в 1С иногда "тормозят". При вызове обычной процедуры &НаСервере на сервер передается вся форма целиком (весь контекст). Если форма содержит сотни реквизитов, это создает лишнюю нагрузку. Проанализируем, как сделать вызов более легким с помощью &НаСервереБезКонтекста.
В этом случае мы передаем только нужную ссылку, а возвращаем массив структур или таблицу значений:
&НаКлиенте
Процедура ОфициантПриИзменении(Элемент)
// Получаем данные с сервера без передачи всей формы
ДанныеЗаказов = ПолучитьСписокЗаказовНаСервере(Объект.Официант);
// Загружаем полученные данные в таблицу
Объект.Заказы.Очистить();
Для Каждого СтрокаДанных Из ДанныеЗаказов Цикл
НоваяСтрока = Объект.Заказы.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСписокЗаказовНаСервере(ВыбранныйОфициант)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ГДЕ Официант = &Официант";
Запрос.УстановитьПараметр("Официант", ВыбранныйОфициант);
Возврат Запрос.Выполнить().Выгрузить(); // Возвращаем ТЗ
КонецФункции
Чтобы ваше решение было по-настоящему качественным, рассмотрим еще несколько важных аспектов:
1. Индексирование реквизитов. Проверьте в конфигураторе, стоит ли у реквизита Официант в документе Заказы свойство Индексировать. Без индекса при росте базы данных (свыше 100 000 заказов) выборка будет работать крайне медленно, так как системе придется просматривать каждую запись в таблице.
2. Обработка пустых значений. Проанализируем ситуацию: что должно происходить, если пользователь очистил поле Официант? В коде желательно добавить условие: если Объект.Официант.Пустая(), то либо очищать таблицу заказов, либо (если этого требует бизнес-логика) показывать заказы по всем официантам, изменив текст запроса или настройки отбора.
3. Условное оформление. Разберем способ визуального улучшения. Если в списке заказов есть критичные статусы (например, "Отменен" или "Просрочен"), не нужно раскрашивать их кодом при заполнении таблицы. Используйте свойство формы УсловноеОформление. Это работает быстрее и позволяет настроить цвета, шрифты и видимость колонок без единой строчки кода в цикле.
4. Гиперссылки. Для удобства пользователя убедитесь, что в колонке Ссылка (или Номер) установлено свойство КнопкаОчистки или настроена возможность открытия значения. Это позволит менеджеру или администратору провалиться в конкретный документ прямо из сформированного списка.
Таким образом, мы рассмотрели два основных подхода к выводу данных: гибкий ручной метод через запрос и высокопроизводительный метод через динамические списки. Выбор конкретного варианта зависит от того, планируете ли вы выполнять сложные расчеты с этими данными в памяти формы или просто отображаете их для ознакомления.