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

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

При переходе от обычных форм к управляемым формам в платформе 1С:Предприятие 8.3 разработчики часто сталкиваются с вопросом корректного использования сложных типов данных, таких как Структура. Если в обычных формах мы могли легко использовать реквизиты объекта типа Структура, то в управляемых формах возникают особенности, связанные с клиент-серверным взаимодействием и архитектурой форм. Разберем, как эффективно передавать и хранить структуры в управляемых формах, опираясь на лучшие практики и возможности платформы.

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

1. Использование реквизита формы с произвольным типом для хранения структуры

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

  1. Объявление реквизита формы:

    Мы объявляем новый реквизит формы в конфигураторе, указывая для него тип "Произвольный". Это позволит нам присваивать ему значения типа Структура или другие сложные типы, которые поддерживают сериализацию платформой.

    
    // Пример добавления реквизита в конфигураторе:
    // Название: МояСтруктураДанных
    // Тип: Произвольный
    

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

  2. Работа со структурой в коде:

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

    
    &НаСервере
    Процедура ИнициализироватьСтруктуруНаСервере()
        МояСтруктураДанных = Новый Структура;
        МояСтруктураДанных.Вставить("Ключ1", "Значение1");
        МояСтруктураДанных.Вставить("Ключ2", 123);
        // Добавляем другие необходимые поля в структуру
    КонецПроцедуры
    
    &НаСервере
    Процедура ИспользоватьСтруктуруНаСервере()
        Если МояСтруктураДанных <> Неопределено Тогда
            Сообщить("Значение по Ключ1: " + МояСтруктураДанных.Ключ1);
            // Выполняем другие операции со структурой
        Иначе
            Сообщить("Структура МояСтруктураДанных не инициализирована.");
        КонецЕсли;
    КонецПроцедуры
    
  3. Нюансы с типами данных и прикладными объектами:

    Важно различать встроенный тип Структура, который является универсальным типом встроенного языка, и специальные типы для представления данных прикладных объектов в форме, такие как ДанныеФормыСтруктура. Тип ДанныеФормыСтруктура содержит набор свойств произвольного типа, которые, в свою очередь, могут быть другими структурами, коллекциями или структурами с коллекциями, и предназначен для работы с объектными данными в контексте формы.

    Крайне важно: не рекомендуется использовать типы Структура и СписокЗначений в данных реквизитов формы, которые являются частью других реквизитов (например, в свойствах реквизитов типа ДанныеФормыСтруктура). Также, если реквизит формы имеет тип "Произвольный", не следует устанавливать ему значения, содержащие прикладные объекты, такие как ДокументОбъект, СправочникОбъект и другие, напрямую. Для работы с прикладными объектами в форме существуют специальные типы ДанныеФормыСтруктура, ДанныеФормыКоллекция и т.д., а также специальные методы ЗначениеВРеквизитФормы() и РеквизитФормыВЗначение() для преобразования между ними. Эти методы обеспечивают корректную сериализацию и десериализацию объектных данных при обмене между клиентом и сервером.

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

    Если мы хотим, чтобы реквизит формы был всегда доступен на стороне клиента, независимо от того, отображается он в элементах формы или нет, нам нужно установить флаг "Использовать всегда" для этого реквизита в конфигураторе. Однако этот флаг нельзя установить для реквизитов с типом, который не передается автоматически с сервера на клиент, например, ХранилищеЗначения, поскольку для таких типов требуется специальная обработка передачи.

2. Использование временного хранилища для передачи структуры

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

  1. Принцип работы временного хранилища:

    Временное хранилище позволяет нам помещать одно или несколько значений на сервере, а затем получать адрес их хранения в виде строковой переменной (УникальныйИдентификатор), которая затем может быть передана на клиент. На клиенте мы храним этот адрес, а при необходимости вновь обращаемся к серверу, передавая этот адрес, чтобы получить доступ к данным. Это позволяет избежать полной сериализации и десериализации всей структуры при каждом клиент-серверном взаимодействии, что значительно оптимизирует производительность, особенно для больших объемов данных или при частых обращениях.

  2. Помещение и получение данных из хранилища:

    Для помещения данных во временное хранилище используется метод ПоместитьВоВременноеХранилище(). Он возвращает адрес, который мы сохраняем, например, в строковом реквизите формы или передаем как параметр. Для получения данных используется метод ПолучитьИзВременногоХранилища().

    
    &НаСервере
    Функция ПоместитьСтруктуруВоВременноеХранилище()
    
        МояСтруктура = Новый Структура;
        МояСтруктура.Вставить("Имя", "Иван");
        МояСтруктура.Вставить("Возраст", 30);
        МояСтруктура.Вставить("ДатаРождения", Дата(1993, 5, 15));
        // Добавляем любые другие данные в структуру
    
        // Помещаем структуру во временное хранилище.
        // Второй параметр (УникальныйИдентификатор) - это владелец хранилища.
        // Если владелец не указан (Неопределено), данные хранятся до конца вызова сервера.
        // Если указан объект формы (через ее УникальныйИдентификатор), 
        // данные хранятся пока существует форма и очищаются при ее закрытии.
        АдресХранилища = ПоместитьВоВременноеХранилище(МояСтруктура, ЭтаФорма.УникальныйИдентификатор); 
    
        Возврат АдресХранилища;
    КонецФункции
    
    &НаКлиенте
    Процедура Кнопка_ИспользоватьДанныеНаСервереНажатие()
        // Предполагаем, что у нас есть реквизит формы "АдресСтруктурыВХранилище" типа Строка,
        // в котором мы сохраняем адрес.
        Если Не ЗначениеЗаполнено(АдресСтруктурыВХранилище) Тогда
            АдресСтруктурыВХранилище = ПоместитьСтруктуруВоВременноеХранилище(); 
            Сообщить("Структура помещена во временное хранилище по адресу: " + АдресСтруктурыВХранилище);
        КонецЕсли;
    
        // Теперь мы можем вызвать серверную процедуру, передав адрес
        ИспользоватьСтруктуруИзХранилищаНаСервере(АдресСтруктурыВХранилище);
    КонецПроцедуры
    
    &НаСервере
    Процедура ИспользоватьСтруктуруИзХранилищаНаСервере(Адрес)
        Если ЗначениеЗаполнено(Адрес) Тогда
            // Получаем структуру из временного хранилища по переданному адресу
            МояСтруктура = ПолучитьИзВременногоХранилища(Адрес);
    
            Если МояСтруктура <> Неопределено Тогда
                Сообщить("Данные из хранилища: Имя - " + МояСтруктура.Имя + ", Возраст - " + МояСтруктура.Возраст + ", Дата рождения - " + МояСтруктура.ДатаРождения);
                // Выполняем дальнейшую обработку данных
            Иначе
                Сообщить("Данные по адресу '" + Адрес + "' во временном хранилище не найдены или устарели.");
            КонецЕсли;
        Иначе
            Сообщить("Адрес временного хранилища не указан.");
        КонецЕсли;
    КонецПроцедуры
    
  3. Управление сроком хранения данных:

    При помещении данных во временное хранилище мы должны указать владельца. Если владелец не указан (или указано Неопределено), помещенное значение автоматически удаляется после завершения текущего вызова сервера. Если же в качестве владельца указан объект формы (например, УникальныйИдентификатор текущей формы, который мы можем получить через ЭтаФорма.УникальныйИдентификатор), данные хранятся всё время, пока функционирует объект формы, и очищаются только при её удалении. Это позволяет эффективно управлять жизненным циклом данных, связывая их с конкретным экземпляром формы.

  4. Ограничения и важные моменты при использовании временного хранилища:

    Не все типы данных могут быть помещены во временное хранилище. Мы не можем помещать данные, типы которых не поддерживают сериализацию (например, COM-объекты, объекты файловых потоков или некоторые внутренние объекты платформы). Максимальный объем данных, помещаемых во временное хранилище за один вызов метода ПоместитьВоВременноеХранилище(), не должен превышать 4 Гб в сериализованном виде. Этого, как правило, достаточно для большинства прикладных задач, но стоит учитывать для очень больших коллекций.

    При вызове процедур или функций под директивой &НаСервере из формы со стороны клиента происходит "упаковка" всего контекста формы и отправка его на сторону сервера. Однако при внеконтекстной передаче управления (&НаСервереБезКонтекста) на сервер передаются только те данные, которые явно указаны в параметрах процедуры/функции. При этом не рекомендуется использовать объекты типов ДанныеФормыСтруктура, ДанныеФормыКоллекция и аналогичные в качестве параметров функции, передаваемых по значению, при внеконтекстных вызовах, поскольку они предназначены для работы в контексте формы и их прямое использование вне контекста может быть некорректным или неэффективным.

Общие аспекты работы с реквизитами формы в управляемых формах

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

Для преобразования данных прикладных объектов (например, СправочникОбъект) в реквизиты управляемой формы и обратно существуют специальные методы ЗначениеВРеквизитФормы() и РеквизитФормыВЗначение(). Эти методы обеспечивают корректное представление объектных данных в форме, сохраняя их структуру и поведение, характерные для управляемых форм, и являются краеугольным камнем для работы с объектами прикладного решения в форме.

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

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

← На главную