Как записать соответствие в данные формы коллекции и обеспечить доступность данных между процедурами

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

При разработке на платформе 1С:Предприятие 8.3 (Управляемые формы) начинающие программисты часто сталкиваются с ситуацией, когда данные, полученные в одной серверной процедуре, «исчезают» или становятся недоступными в другой. Кроме того, возникают сложности при попытке загрузить специфические коллекции, такие как Соответствие, напрямую в элементы формы. Рассмотрим подробнее, почему так происходит и как правильно организовать передачу данных.

Проблема 1: Область видимости переменных на сервере

Разберем ситуацию, описанную автором: в процедуре ЗаполнитьНаСервере создается переменная РезЗапрос (тип Соответствие). В следующей процедуре РаспределитьНаСервере при попытке обхода этой переменной возникает ошибка «Переменная не определена».

Выясним причину: В управляемом приложении каждый вызов серверной процедуры с клиента — это фактически новый сеанс работы контекста сервера (если не используются определенные механизмы сохранения состояния). Переменная, объявленная внутри процедуры, является локальной. Как только выполнение кода доходит до КонецПроцедуры, все локальные переменные уничтожаются.

Чтобы данные были доступны в разных процедурах сервера, у нас есть три пути:

  1. Реквизиты формы: Если мы запишем данные в реквизит, созданный в редакторе формы, они будут сохраняться между вызовами (так называемый «контекст формы»).
  2. Временное хранилище: Мы можем поместить объект во временное хранилище, передать адрес на клиент, а затем снова вернуть его на сервер.
  3. Передача параметров: Если одна процедура вызывает другую, мы можем передать данные как параметры.

Проблема 2: Несоответствие типов при использовании метода Загрузить

Попытка выполнить код ОбщееКоличествоМест.Загрузить(РезЗапрос) приводит к ошибке «Несоответствие типов». Проанализируем ситуацию: объект ДанныеФормыКоллекции (которым является таблица на форме) имеет метод Загрузить(), но согласно синтакс-помощнику, этот метод принимает исключительно объект типа ТаблицаЗначений.

Соответствие — это набор пар «Ключ» и «Значение». Оно не имеет структуры колонок, поэтому платформа не «знает», в какую колонку таблицы формы поместить ключ, а в какую — значение. Прямая загрузка здесь невозможна.

Решение 1: Прямая выгрузка из результата запроса в таблицу формы

Если ваша задача — просто отобразить результат запроса в таблице на форме, использование Соответствия как промежуточного звена избыточно. Рассмотрим самый эффективный способ:


&НаСервере
Процедура ЗаполнитьНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ВидДеятельности,
        |   КоличествоМест
        |ИЗ
        |   Справочник.Номенклатура"; // Пример текста запроса
    
    РезультатЗапроса = Запрос.Выполнить();
    
    // Выгружаем результат в таблицу значений
    ТаблицаРезультата = РезультатЗапроса.Выгрузить();
    
    // Загружаем данные напрямую в реквизит формы (тип ДанныеФормыКоллекции)
    // Имена колонок в запросе должны совпадать с именами колонок таблицы на форме
    ОбщееКоличествоМест.Загрузить(ТаблицаРезультата);
КонецПроцедуры

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

Решение 2: Ручной перенос данных из Соответствия в таблицу формы

Бывают случаи, когда логика программы требует предварительной обработки данных именно в объекте Соответствие. В этом случае мы должны вручную обойти коллекцию и заполнить строки таблицы. Разберем по шагам, как это сделать:


&НаСервере
Процедура ПеренестиИзСоответствияВТаблицу(РезЗапрос)
    // РезЗапрос - это наше Соответствие
    
    // 1. Очищаем таблицу формы, если это необходимо
    ОбщееКоличествоМест.Очистить();
    
    // 2. Обходим соответствие циклом
    Для Каждого Элемент Из РезЗапрос Цикл
        // 3. Добавляем новую строку в ДанныеФормыКоллекции
        НоваяСтрока = ОбщееКоличествоМест.Добавить();
        
        // 4. Заполняем колонки, обращаясь к свойствам Ключ и Значение
        НоваяСтрока.КоличествоМест = Элемент.Ключ;
        НоваяСтрока.ВидДеятельности = Элемент.Значение;
    КонецЦикла;
КонецПроцедуры

Решение 3: Использование временного хранилища для передачи Соответствия

Если вы не хотите выводить данные на форму (в таблицу), а хотите просто сохранить Соответствие для следующего серверного вызова, используйте ПоместитьВоВременноеХранилище. Посмотрим на пример реализации:


&НаСервере
Процедура ЗаполнитьНаСервере()
    РезЗапрос = Новый Соответствие();
    // ... заполнение соответствия ...
    
    // Помещаем во временное хранилище. 
    // УникальныйИдентификатор формы привязывает данные к жизни этой формы.
    АдресХранилища = ПоместитьВоВременноеХранилище(РезЗапрос, ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры

&НаСервере
Процедура РаспределитьНаСервере()
    // Извлекаем данные по адресу
    РезЗапрос = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    Если РезЗапрос <> Неопределено Тогда
        Для Каждого Строка Из РезЗапрос Цикл
            // Теперь ошибка "Переменная не определена" не возникнет
            // Логика обработки...
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Рекомендации и итоги

Проанализировав ситуацию, мы можем дать несколько советов для оптимизации работы:

Таким образом, для решения задачи автора наиболее правильным будет либо отказаться от Соответствия в пользу выгрузки запроса в ТЗ, либо реализовать ручное заполнение строк таблицы формы через цикл Для Каждого.

← На главную