Почему метод ПроверитьВывод выдает ошибку получения информации о принтере у отдельных пользователей?

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

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

Как работает метод ПроверитьВывод и почему возникает ошибка

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

  1. Размер страницы и поля листа (в миллиметрах).
  2. Разрешение печати (DPI).
  3. Границы непечатных областей, определяемые драйвером конкретного принтера.

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

Причина 1. Неактуальные данные в Хранилище системных настроек

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

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

Способ А. Программная очистка через менеджер системных настроек:

Мы можем использовать объект ХранилищеСистемныхНастроек или менеджеры хранилищ для удаления сохраненных параметров конкретной формы или отчета у проблемного пользователя:


// Удаление настроек печати для конкретного ключа и пользователя
КлючОбъекта = "Общее/ПараметрыПечатиТабличныхДокументов"; // Либо конкретный КлючПараметровПечати
ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, ИмяНастройки, ИмяПользователя);

Способ Б. Использование специализированных обработок:

Для массового анализа и удаления битых настроек удобно применить внешние административные обработки (например, «Редактор хранилищ настроек» из комплекта инструментов разработчика или специализированные утилиты очистки хранилища). В обработке достаточно выбрать имя пользователя, найти ветку настроек печати табличных документов и удалить сохраненные записи.

Способ В. Штатный интерфейс БСП:

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

  1. Перейдем в раздел Администрирование → Настройки пользователей и прав → Пользователи.
  2. Выберем проблемную учетную запись и нажмем кнопку Настройки.
  3. Перейдем на вкладку Прочие настройки.
  4. Найдем строку Настройки печати табличных документов и нажмем Очистить.

Причина 2. Особенности терминального доступа (RDP / RemoteApp)

При подключении через удаленный рабочий стол с перенаправлением локальных принтеров Windows присваивает принтерам динамические имена вида «HP LaserJet (перенаправлено 2)». При следующем входе номер сессии меняется, а сохраненная в 1С настройка продолжает указывать на принтер из предыдущей сессии. В результате метод ПроверитьВывод() падает.

Чтобы избежать этой проблемы на уровне операционной системы, назначим принтером по умолчанию на сервере терминалов виртуальное устройство, имя которого не меняется от сеанса к сеансу (например, Microsoft Print to PDF или Microsoft XPS Document Writer).

Рекомендации для разработчиков по доработке кода

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

1. Безопасный вызов с обработкой исключений:

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


Попытка
    Если Не ТабДокумент.ПроверитьВывод(МассивВыводимыхОбластей) Тогда
        ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
    КонецЕсли;
Исключение
    // При сбое подсистемы печати продолжаем вывод без деления страниц
КонецПопытки;
ТабДокумент.Вывести(МассивВыводимыхОбластей);

2. Сброс имени принтера перед проверкой:

Если перед вызовом проверки принудительно очистить свойство ИмяПринтера, платформа не станет искать старое сохраненное устройство, а использует текущий системный принтер по умолчанию:


ТабДокумент.ИмяПринтера = "";
Если Не ТабДокумент.ПроверитьВывод(МассивВыводимыхОбластей) Тогда
    ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;

3. Корректное использование ключа параметров печати:

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

← На главную