Работа с файлами (картинками) в интерфейсе Такси
(бесплатная статья по Программированию в 1С)

О чем эта статья

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

Применимость

В статье рассматривается платформа «1С:Предприятие» редакции 8.3. Представленная информация актуальна для текущих релизов платформы.

Работа с файлами (картинками) в интерфейсе Такси

Рассмотрим алгоритм работы с файлами и картинками в новом интерфейсе 1С:Предприятие 8.3 “Такси”.

Во-первых, почему я решил написать эту статью: Новая концепция 1С – отказ от модальных окон, следовательно все методы и объекты, которые порождали открытие модальных окон в новом интерфейсе работать не смогут, точнее смогут, только если в свойствах конфигурации разрешить модальные окна.
Режим использования модальности в интерфейсе Такси

Для увеличения нажмите на изображение.

Однако, если разрешить модальные окна, то мы столкнемся с проблемами при работе в web-клиенте.

Во-вторых, о работе с картинками в управляемых формах часто спрашивают.

Итак, задача: в справочнике “Товары” необходимо сохранять и отображать в форме фотографию товара.
Исходная конфигурация не содержит ничего, кроме самого справочника с товарами, выкладывать ее не буду, просто создайте пустую конфигурацию в 8.3.

Для хранения самого графического файла, в справочнике создадим реквизит “ДанныеКартинки”, с типом “Хранилище значений”.
Отображение фотографий товаров в 1С

Для увеличения нажмите на изображение.

Если планируете выгружать картинку (файл) из информационной базы обратно в файловую систему, то добавьте еще реквизит, который будет хранить исходное имя файла и его тип.

Далее, займемся формой. Как видно на картинке, реквизит с типом хранилище значений в форме недоступен.

Форма элемента - ХранилищеЗначения

Для увеличения нажмите на изображение.

Как будем отображать картинку в форме? Нет, не декорацией с типом “картинка”. А в виде реквизита формы с типом “строка”. Да, да! Это очевидно, и странно, что мало кто об этом догадывается сам.

Все дело в том, что если на форму вынести реквизит с типом “строка”, который будет содержать навигационную ссылку на графические данные или адрес временного хранилища которое содержит такие данные, то форма сможет отобразить сами графические данные.
Добавим реквизит формы с именем “СсылкаНаКартинку”, тип “строка”, длина не ограничена. И поместим его в реквизиты формы.
Ссылка на картинку в реквизитах формы 1С

Для увеличения нажмите на изображение.

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

Для увеличения нажмите на изображение.

Интерфейсная часть готова. Займемся кодингом. Создадим команду формы “ВыбратьФайлКартинки”, в виде кнопки расположим ее на форме.
1С Выбрать файл картинки

Для увеличения нажмите на изображение.

В модуле опишем обработчик события “Действие” для созданной команды формы:
Процедура ВыбратьФайлКартинки

Для увеличения нажмите на изображение.

Пару комментариев к вышеописанному коду:

Если бы мы не обращали внимание на режим модальности приложения, то могли вполне использовать метод “ПоместитьФайл”, однако цель статьи показать работу с файлами именно в таком режиме.
Метод НачатьПомещениеФайла помещает выбранный файл во временное хранилище (если выбор файла был произведен) и вызывает процедуру “ОбработатьВыборФайла” в этом же модуле.

Обращаю внимание на выделенный “УникальныйИдентификатор”, этим свойством мы связали временное хранилище с текущей формой. В противном случае файл в хранилище помещен будет, но само хранилище при серверном вызовет будет уничтожено, а нам оно еще понадобится, для записи файла в реквизит справочника.

Опишем процедуру “ОбработатьВыборФайла”:
ОбработатьВыборФайла

Для увеличения нажмите на изображение.

Если пользователь не отказался от выбора файла, то в реквизит формы “СсылкаНаКартинку” помещаем адрес во временном хранилище, куда были помещены данные картинки.

Вуаля!
Добавление фотографий в 1С

Так, осталось теперь при записи элемента справочника записать данные из временного хранилища в реквизит элемента справочника. Описываем событие ПередЗаписьюНаСервере:
Процедура ПередЗаписьюНаСервере

Для увеличения нажмите на изображение.

Проверяем в реквизите формы у нас что? Если адрес временного хранилища, пишем данные в реквизит элемента справочника, обращаясь к “ТекущийОбъект”, “ТекущийОбъект” – это сконвертированные данные формы, которые пишутся в базу в этот момент времени.

Осталось описать открытие формы, для отображения картинки уже сохраненной в реквизите элемента справочника.
Процедура ПриСозданииНаСервере

Для увеличения нажмите на изображение.

Вот и все. Готовую базу можно взять тут.

Павел Чистов

PDF-версия статьи для участников группы ВКонтакте

Мы ведем группу ВКонтакте – http://vk.com/kursypo1c.

Если Вы еще не вступили в группу – сделайте это сейчас и в блоке ниже (на этой странице) появятся ссылка на скачивание материалов.

Статья в PDF-формате

Статья в PDF-формате

Вы можете скачать эту статью в формате PDF по следующей ссылке: Курсы-по-1С.рф – Новое в редакции 8.3 – Работа с файлами (картинками) в интерфейсе Такси.pdf

Если Вы уже участник группы – нужно просто повторно авторизоваться в ВКонтакте, чтобы скрипт Вас узнал. В случае проблем решение стандартное: очистить кеш браузера или подписаться через другой браузер.

49 комментариев для “Работа с файлами (картинками) в интерфейсе Такси
(бесплатная статья по Программированию в 1С)

  1. Дмитрий сказал:

    Подскажите, а как провернуть такую же операцию, но с регистром сведений?

    • Василий Ханевич сказал:

      Добрый день!
      В регистре сведений можно создать измерение Объект (тип – СправочникСсылка.Товары) и ресурс типа ХранилищеЗначения. В нем и будут храниться двоичные данные картинки.
      При выборе файла картинки можно записывать элемент справочника Товары и добавлять запись в регистр сведений.

      • Дмитрий сказал:

        Спасибо! И ещё вопрос.
        Как я могу загрузить целую папку изображений в РС? Чтоб не по одной штуке, а сразу все. Возможно ли это?

        • Василий Ханевич сказал:

          Для записи в регистр сведений можно использовать разные объекты встроенного языка. РегистрСведенийМенеджерЗаписи – для одиночной записи, РегистрСведенийНаборЗаписей – для сохранения группы записей. Для набора записей можно использовать отборы по значениям измерений (и по периоду, если регистр сведений периодический).

          • Дмитрий сказал:

            Василий, подскажите ещё.Как мне во внешней обработке отобразить на форме картинки, пути на которые у меня находятся в регистре сведений?

            • Василий Ханевич сказал:

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

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

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

              &НаСервереБезКонтекста
              Функция ПолучитьПутьКФайлуКартинки()
                 
                  Результат = "";

                  Запрос = Новый Запрос;
                  Запрос.Текст =
                      "ВЫБРАТЬ ПЕРВЫЕ 1
                      |   Рег.ПутьКФайлуКартинки КАК ПутьКФайлуКартинки
                      |ИЗ
                      |   РегистрСведений.КартинкиНоменклатуры КАК Рег";
                 
                  Выборка = Запрос.Выполнить().Выбрать();
                 
                  Если Выборка.Следующий() Тогда
                      Результат = Выборка.ПутьКФайлуКартинки;
                  КонецЕсли;
                 
                  Возврат Результат;

              КонецФункции
              • Дмитрий сказал:

                В таком случае он открывает только последний файл.А как его останавливать на каждом файле и просматривать по-одному?

                • Дмитрий сказал:

                  При этом изменять булевское значение в отдельной колонке “Качество”РС, в зависимости от нажатой кнопки “Одобрить” или “Забраковать”.

                  • Дмитрий сказал:

                    У меня в РС есть реквизит “Качество” булевый. На форме я отображаю картинку и есть 2 кнопки “Одобрить” и “Забраковать”. Я во внешней обработке пускаю цикл, который пробегает все фотографии из РС. Как мне останавливать его на на каждой фотографии и совершать этот выбор по качеству?Спасибо!

                    • Василий Ханевич сказал:

                      Можно на форме создать таблицу значений (или список значений). Заполнить таблицу значений всеми путями к картинкам, которые требуется обработать. По нажатию на кнопку Следующая картинка переходить к следующей строке таблицы значений, отображать на форме очередную картинку. При нажатии на кнопку Одобрить производить запись в регистр сведений. Поскольку мы знаем, с какой картинкой в данный момент работаем, можем корректно определить, какую именно запись в регистре требуется изменять.

                • Василий Ханевич сказал:

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

                  • Дмитрий сказал:

                    Можете приложить вариант кода?Не до конца понимаю как это реализовать.

                    • Василий Ханевич сказал:

                      Нет, готовое решение подготовить не смогу, только ответить на Ваши вопросы по теме.
                      Поэтому разделите задачу на подзадачи, распишите себе по пунктам, что и в какой последовательности будете делать.
                      1. Создать таблицу значений на форме, заполнить её всеми путями к картинкам, которые нужно показать.
                      2. Добавить команды Предыдущая картинка и Следующая картинка. Создать вспомогательный реквизит формы, где будете хранить текущую выводимую строку таблицы значений (чтобы далее было понятно, что именно записывать в базу). При нажатии на кнопки переходим к предыдущей или следующей строке таблицы.
                      3. Добавить команду формы Одобрить. При нажатии на кнопку производить запись в базу.
                      Примерно такая последовательность шагов.

  2. AlexeyNV сказал:

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

    не работает, поскажите что не так плз

    • Василий Ханевич сказал:

      Добрый день!
      Для очистки хранилища значения можно использовать код:

      ТекущийОбъект.ДанныеКартинки = Неопределено;
  3. Артур сказал:

    А почему картинка не сохраняется после записи и закрытия элемента??

    • Василий Ханевич сказал:

      Добрый день!
      Сейчас проверил – файл сохраняется. Проверьте, что в Вашем программном коде реализован обработчик события формы ПередЗаписьюНаСервере.
      Также можно скачать выгрузку базы, сравнить со своим кодом.

  4. Макс сказал:

    Подскажите как быть. Если нужно чтобы сохранялся в базе просто путь к файлу на диске, а не весь файл(картинка). Чтобы база 1с не росла.

    • Василий Ханевич сказал:

      Добрый день!
      В таком случае можно в справочнике создать строковый реквизит ИмяФайлаКартинки. И при открытии формы помещать во временное хранилище двоичные данные картинки с диска:

      АдресКартинки = ПоместитьВоВременноеХранилище(Новый Картинка(Объект.ИмяФайлаКартинки));

      Для загрузки файла с диска можно использовать следующий код:

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

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

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

      При открытии формы можно также воспользоваться методом глобального контекста НачатьПомещениеФайла, который поместит файл с диска во временное хранилище для отображения на форме:

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

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

    Подскажите, ка быть с pdf файлами. Тип “поле картинка” не подходит. Как и html. Pdf очень востребован для отображения, например, договора с контрагентами.

    • Василий Ханевич сказал:

      Добрый день!
      Отобразить PDF-документ на форме не получится.
      Можно сохранить PDF-документ в файл на диске, затем открыть его приложением, которое установлено в системе как приложение по умолчанию для PDF-файлов:

      ЗапуститьПриложение(ИмяВременногоФайла);
    • Василий Ханевич сказал:

      Добрый день!
      Например, при помощи внедрения в HTML картинки, закодированной в base64:

      <img src="data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7" width="16" height="14" alt="внедренная картинка"/>

      Т.е. происходит внедрение картинки при помощи data:URI, что позволяет вставить код картинок прямо в HTML-страницу без обращений к внешним файлам.

  6. Бестужев Сергей сказал:

    А как быть если картинка (ХранилищеДанных) это ресурс регистра сведений, а его измерение это ссылка на объект которому принадлежит эта картинка? Например так в Бухгалтерия 3.0 Регистр ХранимыеФайлыВерсий, а “владельцем” картинки является элемент справочника ВерсииФайлов?

    • Сергей Калинкин сказал:

      Добрый день!

      Если картинка хранится в регистре сведений, тогда код необходимо модернизировать следующим образом:

      &НаСервере
      Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
         
          ЗначениеКлюча = Новый Структура;
          ЗначениеКлюча.Вставить("ИмяИзмерения", Ссылка);
          КлючЗаписи = РегистрыСведений.ИмяРегистраСведений.СоздатьКлючЗаписи(ЗначениеКлюча);
         
          СсылкаНаКартинку = ПолучитьНавигационнуюСсылку(КлючЗаписи, "ИмяРесурса");       
         
      КонецПроцедуры

      &НаСервере
      Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
         
          Если ЭтоАдресВременногоХранилища(СсылкаНаКартинку) Тогда
             
              ДвоичныеДанные = ПолучитьИзВременногоХранилища(СсылкаНаКартинку);
             
              ЗаписьРегистра = РегистрыСведений.ИмяРегистраСведений.СоздатьМенеджерЗаписи();
              ЗаписьРегистра.ИмяИзмерения = Ссылка;
              ЗаписьРегистра.ИмяРесурса = Новый ХранилищеЗначения(ДвоичныеДанные);
              ЗаписьРегистра.Записать();
             
          КонецЕсли;
         
      КонецПроцедуры
  7. alexandr.kharchuk сказал:

    Хорошая статья. Но у меня один вопрос. Я также добавил кнопку “Открыть картинку” при нажатии которой открывается картинка, но в отдельной форме. Вопрос: подскажите способ, как проверить была ли помещена картинка в хранилище, если нет то скрыть кнопку “Открыть картинку”. Заранее спасибо

    • GROOVY сказал:

      Так в статье же есть проверка на временное хранилище Если ЭтоАдресВременногоХранилища() Тогда Элементы.Кнопка.Видимость = Ложь

  8. Олег сказал:

    Павел, подскажите, а данный способ будет работать для документов, а не справочников?
    Спасибо!

  9. Денис сказал:

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

    • GROOVY сказал:

      Не указали идентификатор формы при помещении файла в ВХ. ВХ было уничтодено при клиент-серверном вызове.

        • Василий Ханевич сказал:

          В методе НачатьПомещениеФайла:

          НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
          • поля сказал:

            Все прописано, но не работает, в режиме предприятия картинка загружается и записывается, но при открытии этого объекта картинки нет

            • Василий Ханевич сказал:

              Проверьте в таком случае, что процедура ПриСозданииНаСервере отрабатывает (можно в отладке проверить, происходит ли в ней остановка на точке). Возможно, в модуле сама процедура есть, но она не назначена в свойствах формы как обработчик события.
              Также к статье приложен файл с выгрузкой базы. На ней работает корректно? Сравните со своими доработками. Можно использовать Сравнить, объединить с конфигурацией из файла.

  10. silv сказал:

    Павел спасибо Вам за статью, у меня выдает ошибку “Переменная не определена (ЭтотОбъект)” подскажите пожалуйста где моя ошибка.

  11. Igorok сказал:

    Павел, подскажите, как узнать (чтобы не ошибиться) список необходимых параметров для процедуры примера “ОбработатьВыборФайла” ?

    • GROOVY сказал:

      В синтаксис-помощнике подробно указаны параметры процедур которые необходимо описать в обработчике оповещения. Ищите метод НачатьПомещениеФайла.

  12. Ivan сказал:

    Классная стать! Подскажите как сохранить эту картинку обратно в файловую систему?

  13. Павел сказал:

    Спасибо за статью, Подскажите как вывести произвольную картинку в форме списка?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Мы используем файлы cookies, чтобы сделать сайт удобнее.
Продолжая просмотр сайта, Вы соглашаетесь с их использованием.
Подробнее