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