Как правильно реализовать копирование данных из ХранилищаЗначения в ФорматированныйДокумент на управляемой форме

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

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

Почему данные ХранилищаЗначения «не видны» на форме

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

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

Этап 1: Чтение и отображение данных

Для работы с форматированным текстом на форме обычно создается реквизит (например, с именем Текст) и типом ФорматированныйДокумент. Чтобы при открытии существующего документа этот реквизит заполнился данными из поля ТекстПриказа (тип ХранилищеЗначения), необходимо использовать обработчик события ПриЧтенииНаСервере. Рассмотрим этот процесс по шагам.

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


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

Обратите внимание, что мы используем метод Получить(). Без него мы имеем лишь объект-контейнер, а не сами данные.

Этап 2: Сохранение данных в базу

Когда пользователь вносит изменения в редактор на форме, они сохраняются только в реквизите Текст. Чтобы эти изменения попали в базу данных в поле ТекстПриказа, нам нужно выполнить обратную операцию перед записью объекта. Для этого идеально подходит событие ПередЗаписьюНаСервере.

Разберем пример реализации:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    // Упаковываем форматированный документ обратно в ХранилищеЗначения
    ТекущийОбъект.ТекстПриказа = Новый ХранилищеЗначения(ЭтаФорма.Текст);
КонецПроцедуры

Здесь важно помнить: мы работаем с ТекущийОбъект, так как именно он будет записан в СУБД. Присваивание напрямую в Объект.ТекстПриказа (через данные формы) не сработает должным образом.

Этап 3: Решение проблемы копирования

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

Выясним причину: событие ПриЧтенииНаСервере при копировании не вызывается, так как объект еще не был записан в базу и, технически, не «читается» из нее, а создается в памяти. В этом случае нам помогает событие формы ПриСозданииНаСервере и анализ параметров формы.

Посмотрим на правильный алгоритм обработки копирования:


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

Важные нюансы и рекомендации

При работе с ХранилищеЗначения и управляемыми формами следует учитывать еще несколько технических аспектов:

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

Подводя итог, можно сказать, что ключ к успеху кроется в понимании разделения данных на «легкие» (доступные в Объект на форме) и «тяжелые» (доступные только через ХранилищеЗначения в контексте сервера). Используя связку ПриСозданииНаСервере с параметром ЗначениеКопирования, вы обеспечите корректную работу приложения и удобство для пользователей при копировании документов.

← На главную