Как создать копию ТабличногоДокумента в 1С на клиенте?

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

При разработке интерактивных форм в 1С часто возникает задача сохранения промежуточных состояний табличного документа — например, для реализации механизма отмены действий (комбинация клавиш Ctrl+Z), создания снимков отчета или временного буфера данных. При попытке сделать это исключительно на стороне тонкого клиента разработчики сталкиваются с непредвиденным поведением платформы.

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

Почему не работает простое присваивание и передача по значению

Проанализируем распространенную ошибку, когда разработчик пытается передать табличный документ в функцию с модификатором Знач или присвоить его новой переменной:


&НаКлиенте
Функция ПолучитьКопиюТД(Знач ИсходныйТД)
    Возврат ИсходныйТД;
КонецФункции

&НаКлиенте
Процедура ПроверитьКопию()
    Копия = ПолучитьКопиюТД(ТабличныйДокументНаФорме);
    Копия.Область(1, 1).Текст = "Измененный текст";
КонецПроцедуры

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

Ограничения тонкого и веб-клиента

Рассмотрим, почему невозможно легко склонировать весь документ без обращения к серверу. На стороне тонкого и веб-клиента для объекта ТабличныйДокумент действует ряд строгих ограничений:

  1. Отключены основные методы компоновки и сборки: Вывести(), Присоединить(), ВставитьОбласть(), Заполнить() и ПолучитьОбласть().
  2. Недоступен метод чтения из внешнего файла или потока Прочитать().
  3. На клиенте доступна только прямая работа с ячейками через метод Область().

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

Способ 1. Клонирование документа через вызов сервера без контекста

Если требуется получить полный независимый дубликат табличного документа со всем оформлением, необходимо использовать серверный контекст. Чтобы минимизировать накладные расходы и избежать передачи всех данных формы, используем директиву &НаСервереБезКонтекста.

Посмотрим на пример правильной реализации функции копирования:


&НаСервереБезКонтекста
Функция СкопироватьТабличныйДокумент(ИсходныйТД) Экспорт
    НовыйТД = Новый ТабличныйДокумент;
    НовыйТД.Вывести(ИсходныйТД);
    Возврат НовыйТД;
КонецФункции

&НаКлиенте
Процедура СохранитьСостояние()
    // Создаем независимый снимок документа
    КопияДокумента = СкопироватьТабличныйДокумент(Элементы.ПолеТабличногоДокумента);
    МассивИсторииСостояний.Добавить(КопияДокумента);
КонецПроцедуры

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

Способ 2. Оптимизация истории изменений через временное хранилище

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


&НаСервереБезКонтекста
Функция ПоместитьСнимокТДВХранилище(ТабличныйДокумент, УникальныйИдентификатор)
    НовыйТД = Новый ТабличныйДокумент;
    НовыйТД.Вывести(ТабличныйДокумент);
    Возврат ПоместитьВоВременноеХранилище(НовыйТД, УникальныйИдентификатор);
КонецФункции

&НаКлиенте
Процедура ЗафиксироватьВерсию()
    АдресСнимка = ПоместитьСнимокТДВХранилище(ТабличныйДокумент, УникальныйИдентификатор);
    ИсторияАдресов.Добавить(АдресСнимка);
КонецПроцедуры

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

Способ 3. Реализация механизма Undo (Ctrl+Z) без полного копирования

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

Вместо полного снимка документа реализуем сохранение дельты изменений непосредственно на клиенте:

  1. При начале редактирования ячейки запоминаем ее координаты (например, через свойства области) и исходное значение.
  2. При подтверждении ввода формируем структуру с параметрами: имя или координаты области, старое значение, старый текст.
  3. Помещаем эту структуру в клиентский стек истории изменений.
  4. При нажатии Ctrl+Z извлекаем последнее изменение из стека и программно восстанавливаем свойства только этой конкретной ячейки через метод Область().

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

← На главную