Нередко разработчики и администраторы 1С сталкиваются с ситуацией, когда на одном и том же рабочем месте при работе в одной базе один пользователь успешно формирует печатную форму, а у другого процедура падает с критической ошибкой «Ошибка получения информации о принтере» на строке с вызовом метода ТабДокумент.ПроверитьВывод(). Разберем механизм работы этого метода, выясним причины сбоя и рассмотрим способы его устранения как в пользовательском режиме, так и на уровне программного кода.
Метод ПроверитьВывод() объекта ТабличныйДокумент предназначен для того, чтобы определить, поместится ли переданный массив областей (или отдельная область) на текущую страницу табличного документа без переноса на следующий лист. Чтобы выполнить такой расчет, платформе 1С недостаточно внутренних данных макета — ей необходимо знать точные физические параметры области печати:
Для получения этих характеристик платформа обращается к графической подсистеме операционной системы и драйверу принтера, назначенного для данного табличного документа. Если у табличного документа задано свойство КлючПараметровПечати, платформа автоматически сохраняет индивидуальные настройки печати (включая имя принтера, поля и ориентацию страницы) в системное хранилище настроек конкретного пользователя. Когда сохраненный принтер переименовывается, удаляется из системы, отключается в RDP-сессии или драйвер перестает отвечать, метод ПроверитьВывод() не может опросить устройство и генерирует исключение.
Если пользователь ранее распечатал документ на принтер, который в текущий момент недоступен (например, сетевой принтер был отключен или в терминальной сессии изменился номер перенаправленного порта), платформа продолжает пытаться опрашивать старое имя принтера из кэша настроек пользователя.
Для исправления ситуации очистим сохраненные параметры печати. Разберем несколько способов реализации этой задачи.
Способ А. Программная очистка через менеджер системных настроек:
Мы можем использовать объект ХранилищеСистемныхНастроек или менеджеры хранилищ для удаления сохраненных параметров конкретной формы или отчета у проблемного пользователя:
// Удаление настроек печати для конкретного ключа и пользователя
КлючОбъекта = "Общее/ПараметрыПечатиТабличныхДокументов"; // Либо конкретный КлючПараметровПечати
ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, ИмяНастройки, ИмяПользователя);
Способ Б. Использование специализированных обработок:
Для массового анализа и удаления битых настроек удобно применить внешние административные обработки (например, «Редактор хранилищ настроек» из комплекта инструментов разработчика или специализированные утилиты очистки хранилища). В обработке достаточно выбрать имя пользователя, найти ветку настроек печати табличных документов и удалить сохраненные записи.
Способ В. Штатный интерфейс БСП:
В конфигурациях, использующих Библиотеку Стандартных Подсистем, очистку можно выполнить без программирования. Разберем последовательность действий:
При подключении через удаленный рабочий стол с перенаправлением локальных принтеров Windows присваивает принтерам динамические имена вида «HP LaserJet (перенаправлено 2)». При следующем входе номер сессии меняется, а сохраненная в 1С настройка продолжает указывать на принтер из предыдущей сессии. В результате метод ПроверитьВывод() падает.
Чтобы избежать этой проблемы на уровне операционной системы, назначим принтером по умолчанию на сервере терминалов виртуальное устройство, имя которого не меняется от сеанса к сеансу (например, Microsoft Print to PDF или Microsoft XPS Document Writer).
Чтобы защитить алгоритм формирования печатных форм от подобных сбоев на уровне программного кода, проанализируем три приема:
1. Безопасный вызов с обработкой исключений:
Поскольку доступность драйвера принтера зависит от окружения клиентской машины, вызов ПроверитьВывод() всегда следует помещать в защитный блок. Если драйвер недоступен, печатная форма все равно будет сформирована, пусть и без динамического разбиения строк:
Попытка
Если Не ТабДокумент.ПроверитьВывод(МассивВыводимыхОбластей) Тогда
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
Исключение
// При сбое подсистемы печати продолжаем вывод без деления страниц
КонецПопытки;
ТабДокумент.Вывести(МассивВыводимыхОбластей);
2. Сброс имени принтера перед проверкой:
Если перед вызовом проверки принудительно очистить свойство ИмяПринтера, платформа не станет искать старое сохраненное устройство, а использует текущий системный принтер по умолчанию:
ТабДокумент.ИмяПринтера = "";
Если Не ТабДокумент.ПроверитьВывод(МассивВыводимыхОбластей) Тогда
ТабДокумент.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
3. Корректное использование ключа параметров печати:
Если для печатной формы не требуется сохранять индивидуальные пользовательские поля и ориентацию, рекомендуется не заполнять свойство ТабДокумент.КлючПараметровПечати либо очищать его перед расчетом разбивки страниц. Это предотвратит чтение некорректных данных из пользовательского хранилища.