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

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

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

Анализ проблемы: почему временное хранилище не всегда эффективно

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

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

Способ 1. Использование переменных клиентского модуля

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

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


&НаКлиенте
Перем КэшТабДока; // Переменная будет жить, пока открыта форма

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

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

Способ 2. Кэширование через Соответствие (Map) или Таблицу Значений

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

Рассмотрим по шагам, как это реализовать:

  1. Создаем переменную-контейнер на клиенте.
  2. Перед формированием проверяем наличие ключа (например, артикула или штрихкода) в соответствии.
  3. Если ключ найден — берем готовый объект. Если нет — формируем и добавляем в соответствие.

&НаКлиенте
Перем КэшМакетныхДанных;

&НаКлиенте
Процедура ВыполнитьПечать()
    
    Если КэшМакетныхДанных = Неопределено Тогда
        КэшМакетныхДанных = Новый Соответствие;
    КонецЕсли;
    
    ТекДанные = Элементы.Товары.ТекущиеДанные;
    КлючПоиска = ТекДанные.Номенклатура;
    
    ТабДок = КэшМакетныхДанных.Получить(КлючПоиска);
    
    Если ТабДок = Неопределено Тогда
        ТабДок = СформироватьНаСервере(КлючПоиска);
        КэшМакетныхДанных.Вставить(КлючПоиска, ТабДок);
    КонецЕсли;
    
    ТабДок.Показать("Печать ценника: " + ТекДанные.Номенклатура);
    
КонецПроцедуры

Способ 3. Реквизиты формы с типом ТабличныйДокумент

В управляемых формах можно создать реквизит формы с типом ТабличныйДокумент. Преимущество в том, что он автоматически сохраняет свое состояние между серверными вызовами в рамках жизни формы. Однако помните, что каждый такой реквизит увеличивает объем данных, передаваемых между клиентом и сервером при «контекстных» вызовах.

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

Решение проблемы с ошибкой «Недопустимая операция»

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

Чтобы избежать этой проблемы, при извлечении документа из кэша рекомендуется использовать метод Скопировать(). Это создаст «чистый» дубликат объекта в памяти:


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

Общие рекомендации по оптимизации макетов

Чтобы хранение на клиенте было еще эффективнее, проанализируем сам ТабличныйДокумент. Часто его «тяжесть» обусловлена не количеством строк, а метаданными:

Использование клиентского кэша в виде Соответствия или простых переменных — это самый действенный метод ускорения массовой печати. Помните о времени жизни этих данных: кэш в модуле формы очистится при закрытии формы, а кэш в глобальном клиентском модуле будет доступен до закрытия всей программы.

← На главную