При разработке и доработке конфигураций на платформе 1С:Предприятие 8 часто возникает задача привязки внешних файлов к документам или справочникам. Особенно это актуально для баз данных с интенсивным документооборотом (например, "1С:Управление производственным предприятием"), где хранение тяжелых графических файлов непосредственно в базе данных может привести к лавинообразному росту размера СУБД и снижению общей производительности системы. В таких случаях оптимальным решением является хранение файлов в отдельном сетевом каталоге, а в самой базе 1С — хранение только текстового пути к этому файлу.
В этой статье мы подробно разберем, как реализовать подобный функционал для обычных форм. Мы пройдем весь путь: от создания реквизита в конфигураторе до написания обработчиков интерактивного выбора и открытия файлов через внешнее приложение Windows, а также затронем критически важные аспекты работы в многопользовательской клиент-серверной среде.
Для начала проанализируем, какой тип данных необходим для хранения пути к файлу. Путь к файлу — это текстовая строка. Рассмотрим подробнее особенности настройки этого реквизита в конфигураторе:
ПутьКФото.Пользователю должно быть удобно работать с новым полем. Ввод пути вручную с клавиатуры или обычное копирование из проводника крайне непрактичны. Нам необходимо настроить интерфейс так, чтобы пользователь мог нажать на кнопку выбора (три точки), выбрать нужный файл в диалоговом окне Windows, а система сама записала полный путь в созданный реквизит.
Выясним по шагам, как настроить элемент формы:
ПутьКФото на форму, чтобы создалось поле ввода.Истина. Это действие добавит к полю ввода привычную кнопку с тремя точками.Истина. Это добавит кнопку с изображением лупы.Теперь напишем обработчик события нажатия на кнопку выбора (три точки). Нам потребуется использовать стандартный объект платформы ДиалогВыбораФайла.
Создадим событие НачалоВыбора для нашего поля ввода на форме. Ниже приведен детальный пример программного кода, который решает эту задачу:
Процедура ПутьКФотоНачалоВыбора(Элемент, СтандартнаяОбработка)
// Отменяем стандартное поведение платформы, чтобы запустить свой алгоритм
СтандартнаяОбработка = Ложь;
// Инициализируем диалог выбора в режиме открытия одного файла
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл фотографии";
// Настраиваем фильтр файлов, чтобы скрыть лишние форматы
Диалог.Фильтр = "Изображения (*.jpg;*.png;*.bmp)|*.jpg;*.png;*.bmp|Все файлы (*.*)|*.*";
Диалог.МножественныйВыбор = Ложь;
// Отображаем диалог пользователю
Если Диалог.Выбрать() Тогда
// Записываем полученный путь обратно в реквизит нашего документа
ЭтотОбъект.ПутьКФото = Диалог.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
В этом коде мы использовали метод Выбрать(), который останавливает исполнение потока и ожидает выбора пользователя. Если пользователь выбрал файл и нажал "Открыть", метод возвращает истину, и мы извлекаем полный путь через свойство ПолноеИмяФайла.
Теперь разберем, как сделать так, чтобы при нажатии на кнопку открытия (лупу) файл автоматически открывался в стандартной программе просмотра изображений операционной системы пользователя.
Для этого мы привяжемся к событию Открытие нашего поля ввода. Платформа 1С предоставляет системную функцию ЗапуститьПриложение(). Она позволяет открыть любой зарегистрированный в операционной системе документ через ассоциированное с ним приложение по умолчанию.
Рассмотрим пример кода обработчика события открытия:
Процедура ПутьКФотоОткрытие(Элемент, СтандартнаяОбработка)
// Отменяем стандартное поведение системы
СтандартнаяОбработка = Ложь;
// Проверим, заполнено ли поле пути
Если Не ЗначениеЗаполнено(ЭтотОбъект.ПутьКФото) Тогда
Предупреждение("Путь к фотографии не указан!");
Возврат;
КонецЕсли;
// Выполним проверку физического существования файла на диске
ПроверяемыйФайл = Новый Файл(ЭтотОбъект.ПутьКФото);
Если ПроверяемыйФайл.Существует() Тогда
// Запускаем внешнее приложение, ассоциированное с расширением файла
Попытка
ЗапуститьПриложение(ЭтотОбъект.ПутьКФото);
Исключение
Сообщить("Не удалось открыть файл: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Иначе
Предупреждение("Файл по указанному пути не найден или доступ к нему ограничен!");
КонецЕсли;
КонецПроцедуры
Этот код проверяет наличие файла с помощью объекта Файл и метода Существует(). Это предохраняет программу от системных ошибок в ситуациях, когда файл был удален, перемещен или переименован во внешнем каталоге.
Проанализируем крайне важную архитектурную проблему, возникающую в клиент-серверных базах данных. Если пользователи запускают систему с разных физических компьютеров, то хранение локальных путей вида C:\MyPhotos\photo.jpg приведет к ошибкам доступа у всех коллег, кроме автора записи.
Существует два основных способа решения этой проблемы:
\\ИмяСервера\ОбщаяПапка\фото.jpg. У всех пользователей 1С должны быть настроены права доступа (чтение/запись) к этой сетевой папке на уровне операционной системы Windows.Разберем, как модифицировать процедуру выбора файла для автоматического копирования в сетевой каталог:
Процедура ПутьКФотоНачалоВыбораСКопированием(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для загрузки в хранилище";
Диалог.Фильтр = "Изображения (*.jpg;*.png)|*.jpg;*.png";
Если Диалог.Выбрать() Тогда
ЛокальныйПуть = Диалог.ПолноеИмяФайла;
ВыбранныйФайл = Новый Файл(ЛокальныйПуть);
// Определяем сетевой каталог для хранения фото документов
СетевойКаталог = "\\FileServer\SharedPhotos\Documents\";
// Формируем имя файла-приемника во избежание конфликтов имен (например, добавляя код или номер документа)
ИмяФайлаПриемника = ЭтотОбъект.Номер + "_" + ВыбранныйФайл.Имя;
РезультирующийСетевойПуть = СетевойКаталог + ИмяФайлаПриемника;
Попытка
// Убедимся, что целевая папка существует
СоздатьКаталог(СетевойКаталог);
// Копируем файл средствами платформы 1С
КопироватьФайл(ЛокальныйПуть, РезультирующийСетевойПуть);
// Записываем сетевой путь в документ
ЭтотОбъект.ПутьКФото = РезультирующийСетевойПуть;
Сообщить("Файл успешно скопирован в сетевое хранилище.");
Исключение
Сообщить("Ошибка при копировании файла в сетевую папку: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
КонецПроцедуры
При использовании этого подхода мы полностью избавляем пользователя от необходимости вручную копировать файлы на сервер и следить за именованием папок. Система все делает автоматически, обеспечивая надежность хранения.
Давайте сделаем интерфейс еще более удобным. Намного приятнее, когда пользователь видит фотографию сразу при открытии документа прямо в окне 1С, без необходимости запускать сторонние программы просмотра.
В обычных формах для этого используется элемент управления ПолеКартинки. Разберем по шагам, как это реализовать:
ДекорацияФото.Пропорционально. Это позволит масштабировать любые фотографии под физический размер созданной рамки без искажения пропорций изображения.
Процедура ОбновитьКартинкуНаФорме()
// Проверяем, указан ли путь в документе
Если ЗначениеЗаполнено(ЭтотОбъект.ПутьКФото) Тогда
ПроверяемыйФайл = Новый Файл(ЭтотОбъект.ПутьКФото);
Если ПроверяемыйФайл.Существует() Тогда
// Загружаем графические данные и помещаем их в поле на форме
ЭлементыФормы.ДекорацияФото.Картинка = Новый Картинка(ЭтотОбъект.ПутьКФото);
Иначе
// Если файл физически отсутствует, очищаем поле картинки
ЭлементыФормы.ДекорацияФото.Картинка = Новый Картинка;
КонецЕсли;
Иначе
// Очищаем картинку, если реквизит пустой
ЭлементыФормы.ДекорацияФото.Картинка = Новый Картинка;
КонецЕсли;
КонецПроцедуры
Осталось настроить вызов этой процедуры в ключевых точках жизненного цикла формы:
ПриОткрытии — чтобы при открытии уже сохраненного документа картинка загружалась автоматически.ПриИзменении поля ввода пути — чтобы изображение мгновенно менялось сразу после того, как пользователь выбрал новый файл.Интегрируя этот функционал вместе с автоматическим копированием в сетевой каталог, мы получаем профессиональное, надежное и масштабируемое решение для работы с внешними графическими файлами в любой конфигурации 1С на обычных формах.