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