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

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

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

Анализ проблемы: почему исчезают данные?

Проанализируем ситуацию: когда мы выполняем процедуру обновления таблицы значений, система чаще всего либо заново инициализирует объект ТаблицаЗначений, либо очищает текущую таблицу и заполняет её новыми данными из запроса. Если колонка была добавлена программно и не заполнена в источнике данных (например, в результате выполнения запроса к базе), то при обновлении она либо исчезнет из структуры, либо её значения во всех строках сбросятся в состояние по умолчанию (для Булево — это Ложь).

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

Способ 1. Клонирование таблицы перед обновлением

Самый быстрый способ, предложенный в обсуждении, — это создание временной копии таблицы. Посмотрим на пример реализации этого метода. Перед тем как запустить алгоритм обновления, мы создаем полную или частичную копию нашей ТЗ в памяти сервера.


// 1. Создаем копию текущей таблицы
тзКопия = ХорошоСкомпонованнаяТз.Скопировать();

// 2. Выполняем процедуру обновления основной таблицы
ВыполнитьОбновлениеТаблицы(ХорошоСкомпонованнаяТз);

// 3. Пытаемся восстановить значения (при условии сохранения порядка строк)
Для Индекс = 0 По ХорошоСкомпонованнаяТз.Количество() - 1 Цикл
    Если Индекс < тзКопия.Количество() Тогда
        ХорошоСкомпонованнаяТз[Индекс].РеквизитБулево = тзКопия[Индекс].РеквизитБулево;
    КонецЕсли;
КонецЦикла;

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

Способ 2. Использование объекта «Соответствие» (Map)

Проанализируем более профессиональный подход. Чтобы точно восстановить значение Булево для каждой конкретной строки, нам нужен уникальный ключ. В качестве ключа может выступать ссылка на объект (если это справочник или документ) или какой-то внутренний идентификатор (например, УникальныйИдентификаторСтроки).

Разберем по шагам алгоритм с использованием объекта Соответствие:

  1. Создаем объект Соответствие, где ключом будет идентификатор строки, а значением — наш флаг.
  2. Проходим циклом по текущей ТЗ и заполняем соответствие.
  3. Обновляем ТЗ.
  4. Проходим по новой ТЗ и восстанавливаем значения по ключу.

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

// Обновляем таблицу (структуру и данные)
ОбновитьДанныеТаблицы(); 

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

Способ 3. Работа с данными управляемой формы

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

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

Рассмотрим пример использования временного хранилища для сохранения всей ТЗ:


// На сервере сохраняем ТЗ перед обновлением
АдресХранилища = ПоместитьВоВременноеХранилище(МояТаблицаЗначений, ЭтаФорма.УникальныйИдентификатор);

// После обновления (например, в другом методе) извлекаем данные
СтараяТЗ = ПолучитьИзВременногоХранилища(АдресХранилища);
Если ТипЗнч(СтараяТЗ) = Тип("ТаблицаЗначений") Тогда
    // Здесь выполняем сопоставление данных, как в Способе 2
КонецЕсли;

Способ 4. Сохранение структуры при полной переинициализации

Иногда процедура обновления полностью пересоздает колонки таблицы. В этом случае мы должны убедиться, что после «очистки» структуры наш программный реквизит добавлен заново. Посмотрим, как это реализовать:


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

Важно: если таблица связана с интерфейсом формы, просто добавить колонку в объект ТаблицаЗначений на сервере недостаточно — она не появится на форме автоматически. Вам потребуется вызвать ИзменитьРеквизиты для добавления реквизита формы и затем программно создать элемент формы (поле ввода или флажок).

Рекомендации по выбору метода

Подводя итог нашему анализу, дадим несколько практических советов:

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

← На главную