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