Картинка и иконка в карточке справочника 1С: реквизит, форма и загрузка

· 9 мин

Содержание

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

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

Дальше разбираем оба случая. Основное внимание уделено первому, потому что именно его чаще всего ищут. Работа идёт в Конфигураторе, в режиме разработчика, на платформе 8.3 с управляемыми формами.

Два вида «иконок»: данные и элементы оформления

Сначала определите, что вам нужно. От этого зависит весь остальной путь.

Что нужноГде хранитсяКак добавить
Фото товара, логотип организации, подпись сотрудникаВ базе, в записи элемента справочникаРеквизит ХранилищеЗначения + поле картинки + загрузка
Значок команды или кнопки на формеВ конфигурации, ветка «Общие» → «Картинки»Общая картинка, затем свойство «Картинка» у команды
Картинка у самого справочника в дереве конфигурации и в менюВ конфигурацииСвойство «Картинка» в палитре свойств объекта

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

Для типовых конфигураций (Бухгалтерия, ЗУП, Управление торговлей) добавлять реквизит в справочник напрямую в основной конфигурации не стоит: при обновлении возникнет конфликт. Делайте это в расширении конфигурации. Для самописной конфигурации ограничений нет.

Подготовка реквизита для хранения изображений

Откройте Конфигуратор, найдите нужный справочник в ветке «Справочники» и откройте его объект. На закладке «Данные» добавьте реквизит.

  1. Нажмите «Добавить» на закладке «Реквизиты».
  2. Задайте имя, например Картинка. Синоним: «Изображение» или «Фото».
  3. В поле «Тип» выберите ХранилищеЗначения.
  4. Сохраните объект.

Почему именно ХранилищеЗначения, а не, скажем, строка с путём к файлу. Путь на локальный диск у каждого пользователя свой, и на другом компьютере картинка не откроется. Хранилище значения держит двоичные данные прямо в базе, поэтому картинка доступна всем, кто работает с базой, и попадает в резервную копию вместе с данными.

Есть и обратная сторона. Каждый файл увеличивает размер базы. Фото на 3 МБ в тысяче карточек дают около 3 ГБ. Поэтому до загрузки договоритесь о требованиях: например, не более 300 КБ на изображение и формат JPEG или PNG.

⚠️ Не добавляйте реквизит с картинкой в справочники, в которых миллионы элементов, не прикинув размер базы. Для больших каталогов картинки обычно хранят отдельно, в присоединённых файлах или на файловом сервере.

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

Настройка отображения картинки в форме элемента

Теперь вынесите изображение на форму. Откройте форму элемента справочника в Конфигураторе.

  1. На закладке «Реквизиты» формы добавьте реквизит формы типа «Строка» с именем КартинкаАдрес. Он понадобится для адреса во временном хранилище.
  2. На закладке «Элементы» добавьте элемент типа «Поле картинки».
  3. В свойстве «Путь к данным» укажите КартинкаАдрес.
  4. Подберите размер: свойства «Ширина» и «Высота», а также «Растягивать» и «Пропорционально», чтобы фото не искажалось.
  5. Если пользователь не должен править картинку вручную, включите «Только просмотр». Загружать будем кнопкой.

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

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ОбновитьКартинку();
КонецПроцедуры

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    ОбновитьКартинку();
КонецПроцедуры

&НаСервере
Процедура ОбновитьКартинку()
    ДвоичныеДанные = Объект.Картинка.Получить();
    Если ДвоичныеДанные = Неопределено Тогда
        КартинкаАдрес = "";
    Иначе
        КартинкаАдрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
    КонецЕсли;
КонецПроцедуры

Пока в реквизит ничего не записано, метод Получить() вернёт Неопределено. Эту ветку код обрабатывает отдельно, иначе на пустой карточке будет ошибка.

Загрузка изображений в режиме предприятия

Загрузку делаем кнопкой на форме. Пользователь нажимает её, выбирает файл на своём компьютере, и картинка сразу появляется в поле.

Добавьте команду формы ЗагрузитьКартинку, поместите кнопку в командную панель и напишите обработчики:

&НаКлиенте
Процедура ЗагрузитьКартинку(Команда)
    Оповещение = Новый ОписаниеОповещения("ЗагрузитьКартинкуЗавершение", ЭтотОбъект);
    НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьКартинкуЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Не Результат Тогда
        Возврат;
    КонецЕсли;
    КартинкаАдрес = Адрес;
    СохранитьКартинкуВОбъект(Адрес);
КонецПроцедуры

&НаСервере
Процедура СохранитьКартинкуВОбъект(Адрес)
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
    Объект.Картинка = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
КонецПроцедуры

Что происходит по шагам. НачатьПомещениеФайла открывает диалог выбора файла и отправляет его на сервер. В обработчике завершения приходит адрес во временном хранилище. Его мы сразу присваиваем в КартинкаАдрес, и поле картинки показывает новое изображение. Затем на сервере двоичные данные кладутся в реквизит объекта с упаковкой.

Запись в базу произойдёт, когда пользователь нажмёт «Записать» или «Записать и закрыть». До этого картинка есть только в форме. Если хотите, чтобы она записывалась сразу, добавьте в ЗагрузитьКартинкуЗавершение вызов Записать(), но тогда у нового элемента без обязательных полей запись не пройдёт.

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

Какие форматы подходят. Поле картинки показывает то, что понимает платформа: PNG, JPEG, GIF, BMP. Для значков с прозрачным фоном берите PNG. Растровые форматы вроде TIFF лучше заранее конвертировать.

Полезный приём: перед записью проверьте размер файла и откажите, если он больше лимита. На сервере у двоичных данных есть метод Размер():

Если ДвоичныеДанные.Размер() > 300 * 1024 Тогда
    ВызватьИсключение "Файл больше 300 КБ. Уменьшите изображение.";
КонецЕсли;

Программная загрузка иконок из каталога

Когда картинок много, вручную по одной не загрузишь. Типичная задача: в каталоге на диске лежат файлы, имя каждого совпадает с артикулом или кодом элемента. Их нужно разом приложить к карточкам.

Рассмотрим схему для серверной обработки: каталог доступен серверу 1С, имена файлов вида Код.png.

&НаСервере
Процедура ЗагрузитьИзКаталога(Каталог)
    Файлы = НайтиФайлы(Каталог, "*.png");
    Для Каждого Файл Из Файлы Цикл
        Код = Файл.ИмяБезРасширения;
        Ссылка = Справочники.Номенклатура.НайтиПоКоду(Код);
        Если Ссылка.Пустая() Тогда
            Продолжить;
        КонецЕсли;
        Данные = Новый ДвоичныеДанные(Файл.ПолноеИмя);
        Объект = Ссылка.ПолучитьОбъект();
        Объект.Картинка = Новый ХранилищеЗначения(Данные, Новый СжатиеДанных(9));
        Объект.Записать();
    КонецЦикла;
КонецПроцедуры

Справочник в примере условный, подставьте свой. Три замечания по существу:

  • Каталог должен быть виден серверу, а не вашему компьютеру. Для клиент-серверной базы это сетевой путь или папка на самом сервере.
  • Запись элемента через Записать() запустит обработчики, которые есть у справочника, и может создать записи в журнале регистрации. На большом объёме разбивайте загрузку на пакеты.
  • Если в справочнике включена проверка при записи, часть элементов не сохранится. Ловите исключение в Попытка … Исключение и копите список ненайденных кодов для отчёта.

Перед массовой загрузкой сделайте копию базы . Ошибка в коде на тысячах элементов откатывается только восстановлением.

Отображение картинок в табличных частях и списках

В форме элемента всё просто, в списке сложнее. Колонку динамического списка с реквизитом ХранилищеЗначения картинкой напрямую не отобразить: платформа не умеет превращать такое значение в изображение на лету.

Рабочих путей три:

  1. Значок вместо фото. Для списка часто хватает маленькой картинки-признака: «есть фото», «нет фото». Добавьте в список колонку с полем картинки и привяжите её к реквизиту типа «Картинка из библиотеки» или к числовому индексу картинки, а значение вычисляйте в запросе динамического списка, например отдельным полем-признаком.
  2. Условное оформление. Для колонки можно задать условное оформление, которое по условию подставляет нужную общую картинку. Так в списке показываются значки статусов, групп, типов.
  3. Хранение в присоединённых файлах. Если вам нужны настоящие миниатюры в списках, картинки кладут отдельным справочником файлов, а в списке выводят значок. Фото открывается по двойному щелчку или в карточке.

В табличной части документа та же логика: реквизит ХранилищеЗначения в строке работает, но показывать огромные изображения в каждой строке не стоит. Получится медленная форма. Держите в строке ссылку на элемент справочника, а картинку смотрите в его карточке.

Если нужен значок команды или кнопки, а не данные, процедура другая:

  1. В дереве конфигурации откройте ветку «Общие» → «Картинки».
  2. Добавьте общую картинку и загрузите файл PNG или SVG.
  3. В свойстве «Картинка» нужной команды или кнопки выберите её.

Для кнопок берите небольшие изображения порядка 16 или 32 пикселей по стороне. Для высокого разрешения экрана платформа умеет работать с набором вариантов одной картинки, но для начала хватит одного.

Синхронизация изображений при обмене данными

Если базы обмениваются данными, картинка в ХранилищеЗначения ведёт себя как обычный реквизит: передаётся вместе с элементом, если реквизит попал в состав обмена. На практике возникают три вопроса.

Размер сообщений. Каждая картинка увеличивает файл обмена. При первой выгрузке всего справочника с тысячами фото сообщение вырастет в разы, обмен по медленному каналу может идти долго. Выгружайте крупный первый пакет в нерабочее время.

Типовые правила обмена. В готовых правилах конвертации (например, обмен Бухгалтерия — Управление торговлей) ваш собственный реквизит не передаётся. Его нужно добавить в правила: в конвертации появляется правило свойства для этого реквизита. Это работа разработчика, отдельного флажка в интерфейсе нет.

Разные конфигурации. Если в приёмнике такого реквизита нет, при загрузке он будет проигнорирован или даст ошибку. Сначала создайте реквизит в обеих базах, потом включайте его в обмен.

Для обмена по формату EnterpriseData дополнительно придётся расширять формат: стандартная схема картинок для вашего реквизита не предусмотрена.

Частые проблемы и способы их решения

В этом разделе собраны симптомы, которые встречаются реже, чем кажется, но выбивают из колеи.

Диагностика: выберите симптом

Ещё два наблюдения. Картинка, загруженная из файла с нестандартным кодеком, может не показаться. Откройте её в любом редакторе и пересохраните как PNG. И второе: вставка картинки из буфера обмена в 1С не работает так же, как в Word, нужен отдельный код через НачатьПомещениеФайла с работой через буфер, поэтому новичкам проще сохранить файл и загрузить его.

Частые вопросы

Можно ли добавить картинку без программирования?
Для значков команд и общих картинок достаточно Конфигуратора и свойств объектов. Для пользовательских фото нужен хотя бы небольшой код загрузки, как в примере выше.
Какого размера делать иконку для кнопки?
Обычно хватает 16 или 32 пикселей по стороне в формате PNG. Для фото в карточке ориентир по весу: не больше 300 КБ.
Подойдёт ли SVG?
Для общих картинок в конфигурации платформа принимает векторные изображения, они хорошо масштабируются. Для фото в ХранилищеЗначения берите PNG или JPEG.
Почему нельзя просто хранить путь к файлу?
Путь к файлу на вашем диске недоступен остальным пользователям и серверу. Данные в базе доступны всем и входят в резервную копию.
Как удалить загруженную картинку?
Добавьте команду, которая присваивает реквизиту пустое значение: Объект.Картинка = Новый ХранилищеЗначения(Неопределено); и сбрасывает КартинкаАдрес. Затем запишите элемент.