Как преобразовать тип ДанныеФормыСтруктура в форму на сервере и передать реквизиты формы

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

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

В этой статье мы подробно разберем, почему возникает такая проблема, можно ли действительно выполнить преобразование типов на сервере и какими методами можно «обмануть» систему для корректной работы кода.

Анализ проблемы: почему Форма и ДанныеФормыСтруктура — это не одно и то же

Прежде всего, проанализируем ситуацию с точки зрения архитектуры платформы. Тип УправляемаяФорма является контекстным объектом. Он существует в полном объеме только на стороне клиента. Когда мы вызываем серверную процедуру и передаем туда форму, платформа передает на сервер не визуальный объект, а лишь его данные и состояние.

Основная сложность заключается в следующем:

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

Рассмотрим пример из практики. В конфигурации 1С:Комплексная автоматизация 2.4 в модуле УстановкаЦенКлиентСервер есть функция ВыбранныеСтрокиТаблицыВидовЦен(Форма). Она ожидает форму, потому что внутри обращается к реквизиту Форма.ВыбранныеЦены. Этот реквизит является реквизитом формы, а не частью документа «Установка цен номенклатуры».

Решение №1: Использование «утиной типизации» через Структуру

Самый эффективный и простой способ решить проблему без глобального переписывания типового кода — это использование структуры-контейнера. В языке 1С при обращении к свойствам объекта через точку на сервере платформа не всегда жестко проверяет тип самого объекта, если у него есть свойство с нужным именем.

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

Пример кода на клиенте перед вызовом серверной функции:


// Получаем форму программно
ФормаНовогоДокумента = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.Форма.ФормаДокумента");

// Вместо передачи ФормаНовогоДокумента.Объект, создаем "суррогат"
ПараметрИмитацияФормы = Новый Структура;

// Добавляем в структуру те реквизиты, которые функция будет искать у формы
// В нашем случае это таблица или массив 'ВыбранныеЦены'
ПараметрИмитацияФормы.Вставить("ВыбранныеЦены", ФормаНовогоДокумента.ВыбранныеЦены);

// Теперь передаем эту структуру в общий модуль
// Функция ВыбранныеСтрокиТаблицыВидовЦен внутри сделает Для Каждого Стр Из Форма.ВыбранныеЦены
// И для нее структура со свойством "ВыбранныеЦены" будет неотличима от формы
Результат = УстановкаЦенКлиентСервер.ВыбранныеСтрокиТаблицыВидовЦен(ПараметрИмитацияФормы);

Важный нюанс: Этот метод работает только в том случае, если вызываемая функция обращается к свойствам формы через точку (Форма.ИмяРеквизита) и не использует специфические методы формы вроде Элементы.Найти() или ЭтотОбъект.Открыть().

Решение №2: Программное заполнение реквизитов формы

Если вы создаете форму программно через ПолучитьФорму(), важно помнить, что на сервере в момент вызова ПриСозданииНаСервере форма еще может не содержать всех необходимых данных, если они заполняются интерактивно.

Если вам нужно, чтобы ДанныеФормыСтруктура (ваш Объект) содержал данные, которые обычно живут в форме, рассмотрите возможность временного расширения структуры данных. Однако, как было замечено в обсуждении, у ДанныеФормыСтруктура нет методов Вставить() или Добавить(), так как ее состав жестко определен составом реквизитов объекта в метаданных.

В такой ситуации проанализируем альтернативный путь: использование метода КопироватьДанныеФормы. Этот метод позволяет перенести данные из одного источника в другой, если их структуры совпадают. Но для решения проблемы «отсутствующего реквизита формы» это подходит редко.

Решение №3: Рефакторинг вызываемой функции (лучшая практика)

Если у вас есть возможность изменять общий модуль, наиболее правильным с точки зрения архитектуры решением будет изменение сигнатуры функции. Функция не должна требовать всю форму, если ей нужна только одна таблица.

Рассмотрим, как переписать типовую функцию для универсальности:


// Было:
Функция ВыбранныеСтрокиТаблицыВидовЦен(Форма) Экспорт
    // ...
    Для Каждого ТекСтрока Из Форма.ВыбранныеЦены Цикл
    // ...
КонецФункции

// Стало (универсальный вариант):
Функция ВыбранныеСтрокиТаблицыВидовЦен(КоллекцияВидовЦен) Экспорт
    ВидыЦен = Новый Массив;
    Для Каждого ТекСтрока Из КоллекцияВидовЦен Цикл
        Если ТекСтрока.Выбрана Тогда
            ВидыЦен.Добавить(ТекСтрока);
        КонецЕсли;
    КонецЦикла;
    Возврат ВидыЦен;
КонецФункции

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

Резюме и рекомендации

Подведем итог нашему разбору. Прямое преобразование ДанныеФормыСтруктура в Форму на сервере невозможно и концептуально неверно. Если вы столкнулись с ошибкой при передаче данных в общий модуль, выполните следующие действия:

Понимание разницы между данными формы и самой формой позволяет писать более надежный код и избегать трудноотлаживаемых ошибок при миграции логики между клиентом и сервером. Для автоматического выявления некорректных вызовов процедур и функций общих модулей подойдёт инструмент для статического анализа конфигураций на наличие ошибок в коде.

← На главную