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

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

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

Способ 1. Использование реквизита «ХранилищеНастроек» справочника внешних обработок

Если ваша задача реализуется в рамках внешней обработки, добавленной в справочник ДополнительныеОтчетыИОбработки, то самым логичным решением будет использование штатного реквизита этого справочника. В типовых конфигурациях (БП 3.0, УТ 11, ЗУП 3.1) у этого справочника есть реквизит ХранилищеНастроек с типом ХранилищеЗначения. Мы можем программно записывать туда любые сериализуемые данные.

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

Пример записи данных в ХранилищеНастроек:


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

Пример чтения данных при открытии формы:


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

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

Способ 2. Системные хранилища настроек (платформенный механизм)

Проанализируем другой вариант, который не требует привязки к конкретному реквизиту объекта. Платформа 1С предоставляет системные таблицы для хранения произвольных настроек: ХранилищеОбщихНастроек, ХранилищеСистемныхНастроек и др. Эти таблицы не видны в дереве метаданных, но они физически присутствуют в базе данных.

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

Разберем, как сохранить ТаблицуЗначений через ХранилищеОбщихНастроек:

  1. Определяем уникальный ключ объекта (например, "ДанныеМоейПечатнойФормы").
  2. Определяем ключ настроек (например, ссылку на документ, к которому привязана ТЗ, или имя пользователя).
  3. Используем метод Сохранить().

Пример программного кода:


// Сохранение данных
КлючОбъекта = "ВнешняяОбработка_ПечатьТТН";
КлючНастроек = "СохраненнаяТаблица_001";
ОписаниеНастроек = "Промежуточные данные таблицы значений";

ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, КлючНастроек, МояТаблицаЗначений, ОписаниеНастроек);

// Загрузка данных
ЗагруженнаяТЗ = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек);
Если ЗагруженнаяТЗ = Неопределено Тогда
    // Обработка ситуации, когда данных еще нет
КонецЕсли;

Важный нюанс: при использовании системных хранилищ платформа берет на себя заботу о сериализации. Однако помните, что ТаблицаЗначений является серверным объектом. Если вам нужно передать эти данные на клиент, лучше предварительно преобразовать ТЗ в Массив структур.

Способ 3. Использование служебных регистров БСП

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

Проанализируем преимущества этого подхода:

Способ 4. Механизм дополнительных сведений

Если ваши данные (таблица значений) логически связаны с конкретным документом (например, «Реализация товаров и услуг»), можно воспользоваться механизмом дополнительных сведений. В пользовательском режиме создается новое «Дополнительное сведение» с типом «Строка» (неограниченной длины).

Для сохранения таблицы значений в текстовое поле мы можем использовать сериализацию в JSON или XML:


// Сериализация ТЗ в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МояТЗ_В_Виде_Массива);
СтрокаДляХранения = ЗаписьJSON.Закрыть();

// Далее записываем эту строку в регистр сведений ДополнительныеСведения
// по стандартным правилам БСП

Важные рекомендации по работе с Таблицей Значений

При работе с ХранилищемЗначения и сложными объектами типа ТаблицаЗначений, следует придерживаться нескольких правил, чтобы избежать ошибок и падения производительности:

1. Сериализуемость данных.

Убедитесь, что все данные внутри вашей таблицы значений могут быть сериализованы. Если в колонках ТЗ содержатся специфические объекты (например, COM-объекты), запись в ХранилищеЗначения вызовет ошибку. Рекомендуется хранить в таблице только примитивные типы (числа, строки, даты, булево) и ссылки на объекты базы данных.

2. Объем данных.

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

3. Клиент-серверное взаимодействие.

Помните, что извлечь объект из ХранилищаЗначения можно только на сервере. Рассмотрим типичную последовательность действий:

  1. На клиенте пользователь нажимает кнопку «Загрузить».
  2. Вызывается серверная процедура.
  3. На сервере данные извлекаются из хранилища.
  4. Данные помещаются в реквизит формы (который отображается как таблица на экране) с помощью метода ЗначениеВРеквизитФормы().

Выясним причину, по которой иногда ХранилищеЗначения.Получить() возвращает Неопределено. Это происходит, если данные были записаны некорректно или если ключ поиска в системном хранилище не совпадает (например, из-за разного регистра символов или наличия невидимых пробелов в строке ключа).

Заключение

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

← На главную