Как передать массив значений в параметры управляемой формы 1С?

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

При разработке на платформе 1С часто возникает задача открыть одну форму из другой и передать в нее определенные параметры для инициализации. Если с передачей одиночных значений (чисел, строк, ссылок или значений перечислений) обычно проблем не возникает, то при попытке передать массив можно столкнуться с ошибкой "Массив не может использоваться в данных формы". Разберем, почему эта ошибка возникает и как ее правильно обойти.

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

В чем заключается корень проблемы?

Основная причина ошибки "Массив не может использоваться в данных формы" кроется в архитектуре управляемых форм 1С. Реквизиты формы, которые мы создаем в конфигураторе, являются частью "данных формы". Эти данные должны быть сериализуемы, то есть платформа должна уметь преобразовывать их в формат для передачи между клиентом и сервером и обратно. Тип данных Массив не поддерживается в качестве типа для реквизита данных формы.

Когда мы в процедуре ПриСозданииНаСервере пытаемся выполнить присваивание:


// Этот код вызовет ошибку, если ВидБюджета - реквизит формы, 
// а в параметрах пришел массив.
ВидБюджета = Параметры.ВидБюджета;

Платформа пытается записать массив в реквизит формы ВидБюджета и справедливо сообщает, что так делать нельзя. Главный вывод: массивы можно передавать в параметрах, но нельзя сохранять их напрямую в реквизитах данных формы.

Решение: передача массива без объявления параметра в форме

Самый простой и эффективный способ — передавать данные в структуру параметров, но не создавать для них одноименный параметр в дереве объектов формы. Параметры, переданные при открытии, все равно будут доступны в обработчике ПриСозданииНаСервере.

Рассмотрим по шагам, как это реализовать.

  1. Подготовка данных на клиенте. В коде, откуда мы вызываем форму, формируем структуру с параметрами. В качестве значения мы можем поместить как одно значение, так и массив.

    Пример передачи одного значения:

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

    Пример передачи массива значений:

    
    &НаКлиенте
    Процедура ЗагрузитьИзExcel_ОС_НМА(Команда)
        ПараметрыФормы = Новый Структура;
        
        СписокВидов = Новый Массив;
        СписокВидов.Добавить(ПредопределенноеЗначение("Перечисление.киб_ВидыТРУ.НМА"));
        СписокВидов.Добавить(ПредопределенноеЗначение("Перечисление.киб_ВидыТРУ.ОС"));
        
        ПараметрыФормы.Вставить("ВидБюджета", СписокВидов);
        
        ОткрытьФорму("Обработка.ЗагрузчикДокументов.Форма.Форма", ПараметрыФормы);
    КонецПроцедуры
    
  2. Обработка параметров на сервере. В открываемой форме (в нашем случае это обработка ЗагрузчикДокументов) в процедуре ПриСозданииНаСервере мы получаем доступ к переданным данным через объект Параметры.

    Важно: убедитесь, что в самой форме (в конфигураторе, на вкладке "Параметры") у вас нет параметра с именем "ВидБюджета". Если он там есть, удалите его.

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

Ключевая идея этого подхода — не пытаться "сохранить" массив в данных формы, а использовать его сразу после получения для настройки формы или для выполнения какой-либо логики.

Альтернативный способ: использование временного хранилища

Для передачи больших или сложных объемов данных между формами существует более надежный механизм — временное хранилище. Этот метод гарантирует, что данные не будут "потеряны" или некорректно переданы.

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

Таким образом, для решения задачи передачи массива в параметры формы следует запомнить простое правило: получайте массив в `ПриСозданииНаСервере` и сразу же его обрабатывайте, не пытаясь присвоить его реквизиту данных формы. Это позволит избежать ошибок и реализовать необходимую логику инициализации формы.

← На главную