При автоматизации документооборота и складского учета часто возникает задача пакетной печати внешних файлов, привязанных к документам или справочникам (например, сертификатов качества, паспортов или справок к сериям номенклатуры). Нередко такие файлы хранятся в формате TIFF и содержат несколько страниц. Попытка вывести подобный файл в табличный документ классическим способом через объект Картинка приводит к тому, что на печать отправляется исключительно первая страница документа.
Выясним причину такого поведения платформы, проанализируем возможные пути решения и подробно разберем, как реализовать вывод всех страниц многостраничных файлов как встроенными возможностями 1С, так и с привлечением внешних средств.
При стандартной загрузке графического файла через конструктор Новый Картинка(ПутьКФайлу) платформа считывает метаданные и декодирует только начальный кадр (первую страницу). При помещении этого объекта в табличный документ отображается именно первый кадр. Долгое время в платформе отсутствовали встроенные инструменты разделения многокадровых изображений на отдельные составляющие, поэтому разработчики использовали запуск внешних программ просмотра или системных библиотек.
Рассмотрим два надежных способа реализации задачи: современный штатный механизм платформы 1С и альтернативный вариант с запуском внешней специализированной утилиты.
Начиная с версии платформы 8.3.15, в 1С появилась полноценная поддержка работы с многостраничными графическими файлами. Для этого используются методы объекта Картинка и специальный объект ОбрабатываемаяКартинка.
Разберем алгоритм решения по шагам:
Картинка.КоличествоКадров() определяем, является ли изображение многостраничным.ОбрабатываемаяКартинка и вызываем метод ПолучитьКартинки(), который возвращает массив, где каждый элемент — отдельная страница.ТабличныйДокумент.ВывестиГоризонтальныйРазделительСтраниц().Посмотрим на практический пример реализации такой процедуры:
Процедура ПечатьСертификатовШтатнымиСредствами(Кнопка)
Путь = "D:\Сканы TIFF\";
ТипФайла = ".tif";
ТабДок = Новый ТабличныйДокумент;
ТабДок.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_СЕРТИФИКАТОВ";
Макет = ПолучитьМакет("МакетКартинки");
ОбластьКартинка = Макет.ПолучитьОбласть("ОбластьКартинка");
ПервыйЛист = Истина;
Для Каждого Стр Из Товары Цикл
Если НЕ ЗначениеЗаполнено(Стр.СерияНоменклатуры) Тогда
Продолжить;
КонецЕсли;
ПолныйПуть = Путь + СокрЛП(Стр.СерияНоменклатуры.Код) + ТипФайла;
Попытка
ИсходнаяКартинка = Новый Картинка(ПолныйПуть);
// Проверяем количество страниц в файле
КоличествоСтраниц = ИсходнаяКартинка.КоличествоКадров();
Если КоличествоСтраниц > 1 Тогда
// Разбираем многостраничный TIFF на массив кадров
ОбработкаИзображения = Новый ОбрабатываемаяКартинка(ИсходнаяКартинка);
МассивКадров = ОбработкаИзображения.ПолучитьКартинки();
Иначе
МассивКадров = Новый Массив;
МассивКадров.Добавить(ИсходнаяКартинка);
КонецЕсли;
Для Каждого Страница Из МассивКадров Цикл
Если НЕ ПервыйЛист Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
ОбластьКартинка.Рисунки.D1.Картинка = Страница;
ТабДок.Вывести(ОбластьКартинка);
ПервыйЛист = Ложь;
КонецЦикла;
Исключение
Сообщить("Строка № " + Стр.НомерСтроки + ": не найден или поврежден файл для серии " + Стр.СерияНоменклатуры.Код);
КонецПопытки;
КонецЦикла;
// Задаем параметры печати и выводим документ
ТабДок.КоличествоЭкземпляров = 1;
ТабДок.Показать();
КонецПроцедуры
Этот способ предпочтителен, так как он не требует установки стороннего программного обеспечения на рабочие места пользователей, корректно работает на тонком и веб-клиенте, а также позволяет централизованно управлять параметрами печати (числом копий, ориентацией и масштабом) непосредственно из 1С.
Если используется платформа 1С ниже версии 8.3.15 или в конфигурации включен режим совместимости, штатно разобрать файл на кадры не удастся. В такой ситуации печать многостраничных TIFF можно переложить на внешнюю утилиту командной строки, например популярный просмотрщик IrfanView.
Проанализируем типовые ошибки, которые часто возникают при запуске внешних программ:
.tif/print вместо .tif /print), программа воспримет ключ как часть имени файла и выдаст ошибку./print отправляет документ на принтер по умолчанию со всеми страницами файла, однако ключа командной строки для указания количества копий не имеет. Если требуется напечатать документ в нескольких экземплярах, запуск приложения оборачивают во внутренний цикл 1С либо настраивают свойства самого системного принтера.Посмотрим, как правильно сформировать строку вызова и запустить печать:
Процедура ПечатьЧерезIrfanView(Кнопка)
ПутьКаталога = "D:\Сканы TIFF\";
ТипФайла = ".tif";
ПутьКИсполняемомуФайлу = "C:\Program Files\IrfanView\i_view64.exe";
// Проверяем наличие исполняемого файла
ФайлПрограммы = Новый Файл(ПутьКИсполняемомуФайлу);
Если НЕ ФайлПрограммы.Существует() Тогда
ВызватьИсключение "Не найдена программа для печати по пути: " + ПутьКИсполняемомуФайлу;
КонецЕсли;
КоличествоКопий = 1;
Для Каждого Стр Из Товары Цикл
Если НЕ ЗначениеЗаполнено(Стр.СерияНоменклатуры) Тогда
Продолжить;
КонецЕсли;
ИмяФайла = СокрЛП(Стр.СерияНоменклатуры.Код) + ТипФайла;
ПолныйПутьКФайлу = ПутьКаталога + ИмяФайла;
ФайлСправки = Новый Файл(ПолныйПутьКФайлу);
Если НЕ ФайлСправки.Существует() Тогда
Сообщить("Строка № " + Стр.НомерСтроки + ": не обнаружен файл для серии " + Стр.СерияНоменклатуры.Код);
Продолжить;
КонецЕсли;
// Формируем командную строку с экранированием путей кавычками и обязательными пробелами перед ключами
СтрокаКоманды = """" + ПутьКИсполняемомуФайлу + """ """ + ПолныйПутьКФайлу + """ /print";
Попытка
// Запускаем печать необходимое количество раз
Для СчетчикКопий = 1 По КоличествоКопий Цикл
ЗапуститьПриложение(СтрокаКоманды, , Истина);
КонецЦикла;
Исключение
Сообщить("Ошибка печати файла: " + ПолныйПутьКФайлу + " (" + ОписаниеОшибки() + ")");
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если обновление платформы недоступно, а установка сторонних утилит на клиентские компьютеры запрещена политиками безопасности, разберем еще один способ — использование встроенной в Windows библиотеки Windows Image Acquisition (WIA).
Этот компонент доступен во всех современных версиях Windows без дополнительной установки. Механизм позволяет получить количество кадров файла через свойство FrameCount, поочередно активировать страницы свойством ActiveFrame и сохранять их как отдельные временные изображения, которые затем штатно выводятся в табличный документ 1С.
Рассмотрим пример функции, разбирающей многостраничный файл во временные файлы:
Функция РазбитьTiffЧерезWIA(ПутьКФайлу)
МассивПутей = Новый Массив;
Попытка
WiaОбъект = Новый COMОбъект("WIA.ImageFile");
WiaОбъект.LoadFile(ПутьКФайлу);
Исключение
Сообщить("Не удалось загрузить файл через WIA: " + ОписаниеОшибки());
Возврат МассивПутей;
КонецПопытки;
КоличествоСтраниц = WiaОбъект.FrameCount;
Для НомерКадра = 1 По КоличествоСтраниц Цикл
WiaОбъект.ActiveFrame = НомерКадра;
// Получаем временный файл для сохранения текущего кадра
ВременныйФайл = ПолучитьИмяВременногоФайла(".png");
ОбработкаWIA = Новый COMОбъект("WIA.ImageProcess");
ОбработкаWIA.Filters.Add(ОбработкаWIA.FilterInfos("Convert").FilterID);
ОбработкаWIA.Filters(1).Properties("FormatID").Value = "{B96B3CAF-0728-11D3-9D7B-0000F81EF32E}"; // Формат PNG
НовоеИзображение = ОбработкаWIA.Apply(WiaОбъект);
НовоеИзображение.SaveFile(ВременныйФайл);
МассивПутей.Добавить(ВременныйФайл);
КонецЦикла;
Возврат МассивПутей;
КонецФункции
Полученные временные файлы можно передать в цикл формирования табличного документа аналогично первому способу, после чего удалить временные файлы с диска с помощью процедуры УдалитьФайлы().