Как правильно сохранить ХранилищеЗначения при передаче данных между формами в 1С?

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

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

Разбор типовых ошибок при работе с ХранилищемЗначения

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

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

Решение 1: Правильная работа с Временным хранилищем и контекстом формы

Для того чтобы данные не пропадали, мы должны привязать адрес временного хранилища к УникальномуИдентификатору формы-владельца. Рассмотрим, как должен выглядеть исправленный код в подчиненной форме (которую мы открываем для редактирования).

Сначала разберем серверную функцию упаковки данных. Обратите внимание на передачу АдресВХ:


&НаСервере
Функция ПолучитьАдресХранилища(ДокументДляСохранения, АдресВХ)
    // Создаем ХранилищеЗначения на сервере
    ХЗ = Новый ХранилищеЗначения(ДокументДляСохранения);
    
    // Помещаем в хранилище, используя адрес, связанный с формой-владельцем
    // Если АдресВХ не передан, данные могут удалиться слишком рано
    Возврат ПоместитьВоВременноеХранилище(ХЗ, АдресВХ);
КонецФункции

В форме-владельце (документе), при получении результата, нам необходимо правильно извлечь данные и поместить их в объект. Разберем процедуру обработки возврата:


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

Решение 2: Использование HTML как промежуточного формата (Рекомендуется)

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

Шаг 1. В форме редактирования преобразуем документ в HTML:


&НаКлиенте
Процедура ПодготовитьДанныеКОтправке()
    ТекстHTML = "";
    Вложения = Новый Структура;
    // Комментарий - это реквизит с типом ФорматированныйДокумент
    Комментарий.ПолучитьHTML(ТекстHTML, Вложения);
    
    СтруктураВозврата = Новый Структура;
    СтруктураВозврата.Вставить("ТекстHTML", ТекстHTML);
    СтруктураВозврата.Вставить("Вложения", Вложения); // Если есть картинки
    
    Закрыть(СтруктураВозврата);
КонецПроцедуры

Шаг 2. В форме-владельце сохраняем полученную строку:

Посмотрим на пример обработки в основной форме. Мы можем хранить HTML-текст в обычной строке неограниченной длины до момента окончательной записи документа. Это избавляет нас от проблем с "исчезающим" хранилищем на клиенте.


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

Важные замечания по реализации

Проанализируем еще несколько критических моментов, которые помогут избежать ошибок:

Таким образом, для надежного сохранения ХранилищаЗначения необходимо либо строго контролировать УникальныйИдентификатор временного хранилища, либо использовать промежуточную сериализацию в HTML/JSON, что является более современным и стабильным подходом в управляемом приложении.

← На главную