Нередко в прикладных решениях 1С графические файлы хранятся в реквизитах справочников или регистров с типом ХранилищеЗначений. Типовая задача, с которой сталкиваются разработчики при проектировании интерфейса, — предоставить пользователю возможность просмотреть изображение не только в миниатюре внутри формы, но и в полноразмерном окне с помощью стандартного средства просмотра операционной системы.
Разберем, почему нельзя просто передать объект изображения во внешнюю утилиту, выясним технические нюансы работы операционной системы и реализуем правильный алгоритм выгрузки и открытия файла.
Проанализируем архитектурные ограничения взаимодействия 1С и операционной системы. Когда мы считываем данные из базы, они помещаются в оперативную память текущего сеанса как объект типа Картинка или ДвоичныеДанные. Команда вызова внешней программы ЗапуститьПриложение ожидает строку с исполняемой командой или полным путем к файлу в файловой системе.
Стандартный механизм файловых ассоциаций Windows и подавляющее большинство сторонних графических просмотрщиков требуют физический путь к файлу на диске. Они не поддерживают получение бинарного потока из чужого процесса через аргументы командной строки. Соответственно, единственный способ передать изображение внешнему просмотрщику — предварительно сохранить его на жесткий диск.
Рассмотрим подробнее шаги, которые необходимо выполнить для решения поставленной задачи:
Получить() у реквизита с типом ХранилищеЗначений.ЗапуститьПриложение.Посмотрим на пример кода обработки события таблицы или формы. Чтобы временные файлы не конфликтовали между собой, используем функцию ПолучитьИмяВременногоФайла(), передавая ей требуемое расширение, либо формируем путь через КаталогВременныхФайлов().
Разберем практический пример:
// Получаем ссылку на текущую строку
ТекСсылка = ЭлементыФормы.тпНаряды.ТекущиеДанные.Ссылка;
// Извлекаем объект из ХранилищаЗначений
ДанныеКартинки = ТекСсылка.Изображение.Получить();
Если ДанныеКартинки = Неопределено Тогда
Предупреждение("Изображение не найдено в хранилище!");
Возврат;
КонецЕсли;
// Определяем расширение файла
Расширение = "jpg";
Если ТипЗнч(ДанныеКартинки) = Тип("Картинка") Тогда
Формат = ДанныеКартинки.Формат();
Если Формат = ФорматКартинки.PNG Тогда
Расширение = "png";
ИначеЕсли Формат = ФорматКартинки.BMP Тогда
Расширение = "bmp";
ИначеЕсли Формат = ФорматКартинки.GIF Тогда
Расширение = "gif";
ИначеЕсли Формат = ФорматКартинки.TIFF Тогда
Расширение = "tif";
КонецЕсли;
КонецЕсли;
// Формируем уникальный путь во временной директории
ПутьКФайлу = ПолучитьИмяВременногоФайла(Расширение);
// Записываем данные на диск
Если ТипЗнч(ДанныеКартинки) = Тип("Картинка") Тогда
ДанныеКартинки.Записать(ПутьКФайлу);
ИначеЕсли ТипЗнч(ДанныеКартинки) = Тип("ДвоичныеДанные") Тогда
ДанныеКартинки.Записать(ПутьКФайлу);
КонецЕсли;
// Открываем файл во внешнем просмотрщике по умолчанию
ЗапуститьПриложение(ПутьКФайлу);
Проанализируем вопросы стабильности и очистки дискового пространства:
ПолучитьИмяВременногоФайла(), операционная система Windows не сможет определить, какой программой открывать файл, и предложит пользователю диалог выбора приложения. Определение расширения через свойство Картинка.Формат() гарантирует корректный выбор ассоциированной программы.УдалитьФайлы(ПутьКФайлу) сразу после команды ЗапуститьПриложение(ПутьКФайлу), внешний просмотрщик может не успеть прочитать файл с диска и выдаст ошибку. Если же передать параметр ожидания завершения, интерфейс 1С окажется заблокированным до момента, пока пользователь не закроет окно внешней программы. Поэтому временные файлы рекомендуется оставлять в системном каталоге КаталогВременныхФайлов(), позволяя операционной системе очищать их самостоятельно, либо производить очистку созданной подпапки при завершении работы программы.Если задача заключается исключительно в том, чтобы предоставить пользователю возможность рассмотреть изображение в полном масштабе, не обязательно обращаться к внешним приложениям:
ПолеКартинки. В этом случае данные извлекаются методом ХранилищеЗначений.Получить() и напрямую назначаются свойству поля формы без сохранения на физический диск: ЭлементыФормы.ПолеКартинки.Картинка = Хранилище.Получить().Рисунки табличного документа и вызвать метод ТабличныйДокумент.Показать(). Это дает встроенные возможности масштабирования и печати штатными средствами платформы.