Картинка и иконка в карточке справочника 1С: реквизит, форма и загрузка
Содержание
Чтобы в карточке справочника появилась картинка, нужны три вещи: реквизит, который хранит изображение, поле на форме, которое его показывает, и команда, которая загружает файл. Под «иконкой» в 1С понимают два разных случая, и подход у них разный.
Первый случай: пользователь сам прикладывает фото товара, логотип контрагента или скан. Это данные, они лежат в базе, и для них нужен реквизит типа ХранилищеЗначения. Второй случай: картинка в интерфейсе, то есть значок команды, пункта меню или кнопки. Это не данные, а объект конфигурации, и добавляется он в Конфигураторе.
Дальше разбираем оба случая. Основное внимание уделено первому, потому что именно его чаще всего ищут. Работа идёт в Конфигураторе, в режиме разработчика, на платформе 8.3 с управляемыми формами.
Два вида «иконок»: данные и элементы оформления
Сначала определите, что вам нужно. От этого зависит весь остальной путь.
| Что нужно | Где хранится | Как добавить |
|---|---|---|
| Фото товара, логотип организации, подпись сотрудника | В базе, в записи элемента справочника | Реквизит ХранилищеЗначения + поле картинки + загрузка |
| Значок команды или кнопки на форме | В конфигурации, ветка «Общие» → «Картинки» | Общая картинка, затем свойство «Картинка» у команды |
| Картинка у самого справочника в дереве конфигурации и в меню | В конфигурации | Свойство «Картинка» в палитре свойств объекта |
Если картинку нужно менять без Конфигуратора, обычным пользователем, это всегда реквизит. Общие картинки правит только разработчик.
Для типовых конфигураций (Бухгалтерия, ЗУП, Управление торговлей) добавлять реквизит в справочник напрямую в основной конфигурации не стоит: при обновлении возникнет конфликт. Делайте это в расширении конфигурации. Для самописной конфигурации ограничений нет.
Подготовка реквизита для хранения изображений
Откройте Конфигуратор, найдите нужный справочник в ветке «Справочники» и откройте его объект. На закладке «Данные» добавьте реквизит.
- Нажмите «Добавить» на закладке «Реквизиты».
- Задайте имя, например
Картинка. Синоним: «Изображение» или «Фото». - В поле «Тип» выберите
ХранилищеЗначения. - Сохраните объект.
Почему именно ХранилищеЗначения, а не, скажем, строка с путём к файлу. Путь на локальный диск у каждого пользователя свой, и на другом компьютере картинка не откроется. Хранилище значения держит двоичные данные прямо в базе, поэтому картинка доступна всем, кто работает с базой, и попадает в резервную копию вместе с данными.
Есть и обратная сторона. Каждый файл увеличивает размер базы. Фото на 3 МБ в тысяче карточек дают около 3 ГБ. Поэтому до загрузки договоритесь о требованиях: например, не более 300 КБ на изображение и формат JPEG или PNG.
⚠️ Не добавляйте реквизит с картинкой в справочники, в которых миллионы элементов, не прикинув размер базы. Для больших каталогов картинки обычно хранят отдельно, в присоединённых файлах или на файловом сервере.
Для небольших изображений, которые одинаковы для всех (например, значок вида номенклатуры), удобнее другой вариант: общий макет или общая картинка в конфигурации. Тогда в базе не растёт ни один байт.
Настройка отображения картинки в форме элемента
Теперь вынесите изображение на форму. Откройте форму элемента справочника в Конфигураторе.
- На закладке «Реквизиты» формы добавьте реквизит формы типа «Строка» с именем
КартинкаАдрес. Он понадобится для адреса во временном хранилище. - На закладке «Элементы» добавьте элемент типа «Поле картинки».
- В свойстве «Путь к данным» укажите
КартинкаАдрес. - Подберите размер: свойства «Ширина» и «Высота», а также «Растягивать» и «Пропорционально», чтобы фото не искажалось.
- Если пользователь не должен править картинку вручную, включите «Только просмотр». Загружать будем кнопкой.
Поле картинки умеет показывать данные из временного хранилища: туда помещают двоичные данные, а в реквизит записывают адрес. Поэтому и нужен промежуточный реквизит формы. Само значение, которое хранится в базе, остаётся в ХранилищеЗначения.
Чтобы картинка появлялась при открытии существующей карточки, добавьте код. В модуле формы это обработчик ПриСозданииНаСервере, а для случая, когда запись перечитали, ПриЧтенииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьКартинку();
КонецПроцедуры
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ОбновитьКартинку();
КонецПроцедуры
&НаСервере
Процедура ОбновитьКартинку()
ДвоичныеДанные = Объект.Картинка.Получить();
Если ДвоичныеДанные = Неопределено Тогда
КартинкаАдрес = "";
Иначе
КартинкаАдрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
Пока в реквизит ничего не записано, метод Получить() вернёт Неопределено. Эту ветку код обрабатывает отдельно, иначе на пустой карточке будет ошибка.
Загрузка изображений в режиме предприятия
Загрузку делаем кнопкой на форме. Пользователь нажимает её, выбирает файл на своём компьютере, и картинка сразу появляется в поле.
Добавьте команду формы ЗагрузитьКартинку, поместите кнопку в командную панель и напишите обработчики:
&НаКлиенте
Процедура ЗагрузитьКартинку(Команда)
Оповещение = Новый ОписаниеОповещения("ЗагрузитьКартинкуЗавершение", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьКартинкуЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Не Результат Тогда
Возврат;
КонецЕсли;
КартинкаАдрес = Адрес;
СохранитьКартинкуВОбъект(Адрес);
КонецПроцедуры
&НаСервере
Процедура СохранитьКартинкуВОбъект(Адрес)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
Объект.Картинка = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
КонецПроцедуры
Что происходит по шагам. НачатьПомещениеФайла открывает диалог выбора файла и отправляет его на сервер. В обработчике завершения приходит адрес во временном хранилище. Его мы сразу присваиваем в КартинкаАдрес, и поле картинки показывает новое изображение. Затем на сервере двоичные данные кладутся в реквизит объекта с упаковкой.
Запись в базу произойдёт, когда пользователь нажмёт «Записать» или «Записать и закрыть». До этого картинка есть только в форме. Если хотите, чтобы она записывалась сразу, добавьте в ЗагрузитьКартинкуЗавершение вызов Записать(), но тогда у нового элемента без обязательных полей запись не пройдёт.
Для работы через веб-клиент диалог выбора файла может потребовать расширение для работы с файлами или разрешение браузера. Если кнопка «ничего не делает», проверьте это в первую очередь.
Какие форматы подходят. Поле картинки показывает то, что понимает платформа: PNG, JPEG, GIF, BMP. Для значков с прозрачным фоном берите PNG. Растровые форматы вроде TIFF лучше заранее конвертировать.
Полезный приём: перед записью проверьте размер файла и откажите, если он больше лимита. На сервере у двоичных данных есть метод Размер():
Если ДвоичныеДанные.Размер() > 300 * 1024 Тогда
ВызватьИсключение "Файл больше 300 КБ. Уменьшите изображение.";
КонецЕсли;
Программная загрузка иконок из каталога
Когда картинок много, вручную по одной не загрузишь. Типичная задача: в каталоге на диске лежат файлы, имя каждого совпадает с артикулом или кодом элемента. Их нужно разом приложить к карточкам.
Рассмотрим схему для серверной обработки: каталог доступен серверу 1С, имена файлов вида Код.png.
&НаСервере
Процедура ЗагрузитьИзКаталога(Каталог)
Файлы = НайтиФайлы(Каталог, "*.png");
Для Каждого Файл Из Файлы Цикл
Код = Файл.ИмяБезРасширения;
Ссылка = Справочники.Номенклатура.НайтиПоКоду(Код);
Если Ссылка.Пустая() Тогда
Продолжить;
КонецЕсли;
Данные = Новый ДвоичныеДанные(Файл.ПолноеИмя);
Объект = Ссылка.ПолучитьОбъект();
Объект.Картинка = Новый ХранилищеЗначения(Данные, Новый СжатиеДанных(9));
Объект.Записать();
КонецЦикла;
КонецПроцедуры
Справочник в примере условный, подставьте свой. Три замечания по существу:
- Каталог должен быть виден серверу, а не вашему компьютеру. Для клиент-серверной базы это сетевой путь или папка на самом сервере.
- Запись элемента через
Записать()запустит обработчики, которые есть у справочника, и может создать записи в журнале регистрации. На большом объёме разбивайте загрузку на пакеты. - Если в справочнике включена проверка при записи, часть элементов не сохранится. Ловите исключение в
Попытка … Исключениеи копите список ненайденных кодов для отчёта.
Перед массовой загрузкой сделайте копию базы . Ошибка в коде на тысячах элементов откатывается только восстановлением.
Отображение картинок в табличных частях и списках
В форме элемента всё просто, в списке сложнее. Колонку динамического списка с реквизитом ХранилищеЗначения картинкой напрямую не отобразить: платформа не умеет превращать такое значение в изображение на лету.
Рабочих путей три:
- Значок вместо фото. Для списка часто хватает маленькой картинки-признака: «есть фото», «нет фото». Добавьте в список колонку с полем картинки и привяжите её к реквизиту типа «Картинка из библиотеки» или к числовому индексу картинки, а значение вычисляйте в запросе динамического списка, например отдельным полем-признаком.
- Условное оформление. Для колонки можно задать условное оформление, которое по условию подставляет нужную общую картинку. Так в списке показываются значки статусов, групп, типов.
- Хранение в присоединённых файлах. Если вам нужны настоящие миниатюры в списках, картинки кладут отдельным справочником файлов, а в списке выводят значок. Фото открывается по двойному щелчку или в карточке.
В табличной части документа та же логика: реквизит ХранилищеЗначения в строке работает, но показывать огромные изображения в каждой строке не стоит. Получится медленная форма. Держите в строке ссылку на элемент справочника, а картинку смотрите в его карточке.
Если нужен значок команды или кнопки, а не данные, процедура другая:
- В дереве конфигурации откройте ветку «Общие» → «Картинки».
- Добавьте общую картинку и загрузите файл PNG или SVG.
- В свойстве «Картинка» нужной команды или кнопки выберите её.
Для кнопок берите небольшие изображения порядка 16 или 32 пикселей по стороне. Для высокого разрешения экрана платформа умеет работать с набором вариантов одной картинки, но для начала хватит одного.
Синхронизация изображений при обмене данными
Если базы обмениваются данными, картинка в ХранилищеЗначения ведёт себя как обычный реквизит: передаётся вместе с элементом, если реквизит попал в состав обмена. На практике возникают три вопроса.
Размер сообщений. Каждая картинка увеличивает файл обмена. При первой выгрузке всего справочника с тысячами фото сообщение вырастет в разы, обмен по медленному каналу может идти долго. Выгружайте крупный первый пакет в нерабочее время.
Типовые правила обмена. В готовых правилах конвертации (например, обмен Бухгалтерия — Управление торговлей) ваш собственный реквизит не передаётся. Его нужно добавить в правила: в конвертации появляется правило свойства для этого реквизита. Это работа разработчика, отдельного флажка в интерфейсе нет.
Разные конфигурации. Если в приёмнике такого реквизита нет, при загрузке он будет проигнорирован или даст ошибку. Сначала создайте реквизит в обеих базах, потом включайте его в обмен.
Для обмена по формату EnterpriseData дополнительно придётся расширять формат: стандартная схема картинок для вашего реквизита не предусмотрена.
Частые проблемы и способы их решения
В этом разделе собраны симптомы, которые встречаются реже, чем кажется, но выбивают из колеи.
КартинкаАдрес, а не на сам реквизит Картинка. Убедитесь, что ОбновитьКартинку() вызывается при открытии существующей карточки.СохранитьКартинкуВОбъект значение действительно попадает в Объект.Картинка.Ещё два наблюдения. Картинка, загруженная из файла с нестандартным кодеком, может не показаться. Откройте её в любом редакторе и пересохраните как PNG. И второе: вставка картинки из буфера обмена в 1С не работает так же, как в Word, нужен отдельный код через НачатьПомещениеФайла с работой через буфер, поэтому новичкам проще сохранить файл и загрузить его.
Частые вопросы
Можно ли добавить картинку без программирования?
Какого размера делать иконку для кнопки?
Подойдёт ли SVG?
ХранилищеЗначения берите PNG или JPEG.Почему нельзя просто хранить путь к файлу?
Как удалить загруженную картинку?
Объект.Картинка = Новый ХранилищеЗначения(Неопределено); и сбрасывает КартинкаАдрес. Затем запишите элемент.