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