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