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

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

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

Выясним причину: почему стандартные настройки не работают

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

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

Способ 1: Использование ХранилищаОбщихНастроек

Если данные в колонке должны сохраняться индивидуально для пользователя, наиболее подходящим инструментом является ХранилищеОбщихНастроек. Рассмотрим, как реализовать сохранение и загрузку данных всей таблицы.

Для начала разберем процедуру сохранения данных. Мы будем вызывать её в событии формы ПриЗакрытии или при изменении критически важных данных (например, даты).


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

Теперь рассмотрим, как восстановить эти данные при открытии формы в событии ПриСозданииНаСервере:


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

Важный нюанс: Если вы хотите, чтобы данные были общими для всех пользователей, в методе Записать хранилища настроек в параметре "Пользователь" нужно передать пустое значение или системную строку, доступную всем.

Способ 2: Использование вспомогательного регистра сведений (Глобальный подход)

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

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

Алгоритм работы будет следующим:

  1. В событии ПриИзменении ячейки таблицы вызывайте серверную процедуру для записи значения в регистр.
  2. В событии ПриЧтенииНаСервере (или ПриСозданииНаСервере) делайте запрос к регистру и заполняйте колонку в таблице формы.

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

Способ 3: Кэширование при обновлении данных (Обработка серверных вызовов)

Часто данные пропадают не при закрытии формы, а при штатных действиях, таких как смена даты или склада. В типовых конфигурациях (УТ 11, ERP) такие действия вызывают полную перезагрузку объекта. Чтобы этого избежать, мы применим технику кэширования.

Разберем по шагам:

  1. Перед вызовом серверной процедуры, которая обновляет данные, выгружаем нашу колонку в соответствие (ключ — идентификатор строки, значение — данные).
  2. После выполнения серверного кода (например, после ЗначениеВРеквизитФормы) проходим циклом по таблице и восстанавливаем значения из соответствия.

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


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

Рекомендации по программному добавлению реквизитов

Если вы добавляете колонку через ИзменитьРеквизиты, помните, что такие реквизиты существуют только пока открыта форма. Чтобы платформа подхватила их в механизм настроек, рассмотрите возможность использования специальных обработчиков:

Подведем итог: Для временного сохранения в рамках одного пользователя используйте ХранилищеОбщихНастроек. Для обеспечения доступности данных всем пользователям и надежного хранения — используйте Регистр сведений. Всегда контролируйте моменты перезаполнения таблицы из объекта конфигурации, чтобы вовремя восстанавливать данные в динамических колонках.

← На главную