Заполнение справочника с изображениями элементами по умолчанию





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

Добрый день, коллеги.

В процессе работы понадобилось мне создать справочник изображений и заполнить его начальными значениями (значениями по умолчанию). Т.е. суть задачи стоит в том, чтобы создать и загрузить небольшую кучку изображений.

На начальном этапе мы имеем список данных изображений вида:

Outdoor;Улица
1.Trail Head;Начало тропы
2.Bike Trail;Велосипедная дорожка
3.Skiing Area;Лыжная зона
4.Swimming Area;Зона купания
5.Ski Resort;Лыжный курорт
6.Ice Skating;Каток
7.Golf Course;Поле для гольфа
8.Ball Park;Футбольне поле
9.Scenic Area;Живописная местность
10.Picnic Area;Место для пикников
11.Park;Парк
12.Forest;Лес
13.Summit;Вершина
14.Campground;Кэмпинг
15.Lodge;Охотничий домик
16.RV Park;Кемпинг
17.Shower;Душевая
18.Drinking Water;Питевая вода
19.Geocache;Тайник
20.Multi-Cache;Несколько тайников
21.Letterbox Cache;Тайник почтовый щик
22.Puzzle Cache;Тайник-загадка
23.Geocache Found;Тайник найден
24.Truck;Грузовик
25.ATV;Вездеход
26.Cemetery;Кладбище
27.Ghost Town;Город без жителей
28.TracBack Point;Точка обратного отсчета

Hunting;Преследование
1.Hunting Area;Охотничьи угодья
2.Blind;Вслепую
3.Tree Stand;Древесное насаждения
4.Cover;Укрытие
5.Food Source;Источник пищи
6.Water Source;Источник воды
.....

Тут у нас есть группы изображений и потом пронумерованные изображения, которые входят в саму группу. Наименования у нас на двух языках: русский и английский.

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

Создавать предопределенные элементы в справочнике, загружать картинки, копирую по 100 раз наименования — не наш путь.

Было принято решение: делаем макет предопределенных значений и из него грузим все элементы с группами.

Таким образом решение задачи было разбито на 2 части:

1) Формирование макета XML с данными, в том числе картинками в виде двоичных данных.

2) написание механизма загрузки предопределенных значений из макета.

Для работы с XML и создания пакета данных было решено использовать пакеты XDTO. Для нашего случая был разработан следующий пакет:

<xs:schema xmlns:tns="http://www.MapsImage.Kim" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.MapsImage.Kim" attributeFormDefault="unqualified" elementFormDefault="qualified">
<xs:element name="Images" type="tns:ImagesType"/>
<xs:complexType name="ImageGroupType">
<xs:sequence>
<xs:element name="Image" type="tns:ImageType" maxOccurs="unbounded"/>
<xs:element name="NameEnglish" type="xs:string"/>
<xs:element name="NameRussian" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ImageType">
<xs:sequence>
<xs:element name="NameEnglish" type="xs:string"/>
<xs:element name="NameRussian" type="xs:string"/>
<xs:element name="binImage" type="xs:base64Binary" nillable="true"/>
<xs:element name="fileNameImage" type="xs:string" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ImagesType">
<xs:sequence>
<xs:element name="ImageGroup" type="tns:ImageGroupType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

Для формирования нашего XML разработал простую обработку:

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

Рассмотрим самые интересные моменты. В первую очередь мы разбираем файл .txt на составляющие и сохраняем прочитанные значения в массив структур. По факту мы повторяем дерево, которое будет грузится в объект XDTO и потом выгружаться в XML. Пришлось делать так, потому что наш добавленный пакет XDTO не доступен на клиенте и доступен только на сервере. В итоге начальная функция разбора входящих данных выглядит так:

&НаКлиенте
Процедура СоздатьXML(Команда)
Если ФайлTXT = "" ИЛИ ПапкаИзображений = "" Тогда
Возврат;
КонецЕсли;
Файл = Новый ЧтениеТекста(ФайлTXT,КодировкаТекста.UTF8);
ТекстФайла = Файл.Прочитать();
Файл.Закрыть();

МассивПодстрок = СтрРазделить(ТекстФайла,Символы.ПС,Ложь);

СтрокаЦифр = "0123456789";
МассивГрупп = Новый Массив;
СтруктураГруппы = НЕОПРЕДЕЛЕНО;

Для Каждого СтрМассива ИЗ МассивПодстрок Цикл
ПервыйСимвол = Лев(СтрМассива,1);
Если Найти(СтрокаЦифр,ПервыйСимвол) = 0 Тогда
//Это группа
СтруктураГруппы = ПолучитьСтруктуруДанных(Истина);
РазобратьСтрокуНаИмена(СтрМассива,СтруктураГруппы,Истина);

МассивГрупп.Добавить(СтруктураГруппы);
Иначе
//Это элемент
СтруктураИзображения = ПолучитьСтруктуруДанных();
РазобратьСтрокуНаИмена(СтрМассива,СтруктураИзображения);

СтруктураГруппы["Image"].Добавить(СтруктураИзображения);

//  Картинка = ПолучитьИмяФайлаИзображения(МассивФайлов,СтруктураИзображения["fileNameImage"]);
КонецЕсли;
КонецЦикла;

СтрукутраПараметров = Новый Структура;
СтрукутраПараметров.Вставить("МассивГрупп",МассивГрупп);

ОписаниеОповещения = Новый ОписаниеОповещения("ЗавершениеПоискФайлов",ЭтотОбъект,СтрукутраПараметров);

НачатьПоискФайлов(ОписаниеОповещения,ПапкаИзображений,"*",Истина);

КонецПроцедуры

Функция "ПолучитьСтруктуруДанных" возвращают структуру нужного, а "РазобратьСтрокуНаИмена" работает со строкой, преобразуя ее и заполняя данные структуры. Они просты в реализации и не представляют большого интереса.

На этом этапе мы получили массив структур групп изображений и самих изображений. Теперь нам надо подтянуть к каждому изображению конкретно само изображение (в виде двоичных данных) и имена файлов. У меня данная база работает наплатформе версии 8.3.10.2580 и по умолчанию отключено использование модальных окон. Воспользуемся асинхронной функцией поиска файлов "НачатьПоискФайлов".

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

&НаКлиенте
Процедура ЗавершениеПоискФайлов (Результат, ДополнительныеПараметры) ЭКСПОРТ
Если Результат = НЕОПРЕДЕЛЕНО Тогда
Возврат;
КонецЕсли;
МассивГрупп = ДополнительныеПараметры.МассивГрупп;
Для Каждого СтрГруппы ИЗ МассивГрупп Цикл
Для Каждого СтрИзображения ИЗ СтрГруппы["Image"] Цикл
Картинка = ПолучитьИмяФайлаИзображения(Результат,СтрИзображения["fileNameImage"]);
Если Картинка = НЕОПРЕДЕЛЕНО Тогда
Продолжить;
КонецЕсли;

СтрИзображения["binImage"] = Новый ДвоичныеДанные(Картинка.ПолноеИмя);
СтрИзображения["fileNameImage"] = СтрИзображения["fileNameImage"] + Картинка.Расширение;
КонецЦикла;
КонецЦикла;

ТекстXML = ПолучитьОбъектXDTOПоПространствуИмен(МассивГрупп);
КонецПроцедуры

Получив всю нужную информацию мы, наконец, можем приступить в формированию файла XML. Это можно сделать, например, следующим образом:

&НаСервереБезКонтекста
Функция ПолучитьОбъектXDTOПоПространствуИмен (МассивГрупп)
ПространствоИмен = "http://www.MapsImage.Kim";
КорневоеСвойство = "Images";
ОбъектИзображений = ФабрикаXDTO.Создать(ФабрикаXDTO.Пакеты.Получить(ПространствоИмен).КорневыеСвойства.Получить(КорневоеСвойство).Тип);

Для Каждого СтрМассива ИЗ МассивГрупп Цикл
ГруппаИзображений = ОбъектИзображений.ImageGroup.Добавить(ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен,"ImageGroupType")));
ЗаполнитьЗначенияСвойств(ГруппаИзображений,СтрМассива,"NameEnglish,NameRussian");
Для Каждого СтрМассиваИзображения ИЗ СтрМассива["Image"] Цикл
Если СтрМассиваИзображения.binImage = НЕОПРЕДЕЛЕНО Тогда
Сообщить ("Нет изображения!! + " + СтрМассиваИзображения["NameEnglish"]);
КонецЕсли;
Изображение = ГруппаИзображений.Image.Добавить(ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(ПространствоИмен,"ImageType")));
ЗаполнитьЗначенияСвойств(Изображение,СтрМассиваИзображения,"NameEnglish,NameRussian,fileNameImage");
Если СтрМассиваИзображения.binImage <> НЕОПРЕДЕЛЕНО Тогда
Изображение["binImage"] = Base64Строка(СтрМассиваИзображения.binImage);
КонецЕсли;
КонецЦикла;
КонецЦикла;

ИмяВременногоФайла = ПолучитьИмяВременногоФайла(".gpx");

ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяВременногоФайла,"UTF-8");

ЗаписьXML.ЗаписатьОбъявлениеXML();

ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектИзображений, КорневоеСвойство,ПространствоИмен,,НазначениеТипаXML.Явное);

ЗаписьXML.Закрыть();

Файл = Новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
ДанныеXML = Файл.Прочитать();

Возврат ДанныеXML;

КонецФункции

По факту мы обходим ранее сформированную структуру и переносим ее в XDTO пакет.

На выходе (в форме обработки) получим текст вида:

<?xml version="1.0" encoding="UTF-8"?>
<Images xmlns="http://www.MapsImage.Kim" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ImagesType">
<ImageGroup>
<Image>
<NameEnglish>Trail Head</NameEnglish>
<NameRussian>Начало тропы</NameRussian>
<binImage>iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAAFNElEQVR42q2Ve0xT
VxzH77n3tvTBbWtb+rAtSHlUYTBAqHMmytBNYerM3hvJ1KETH5s4l/iIcZs6o5vT
GLOIBKawuanzkbiJM1s0M06GTBxCZGB59mGhpbTYQh/33rNz2w5dsj89f9z8cs65
n/u939/v/A6AEGJPYgAEamlpqVy/zelJBNGBZnEcjwWxQdM0y7IEQaAY7UdxLAAM
UKnGa776zGw2c6CCovm0pMZgMIjEOEviPAgwErE4ECQwNsza+i0YHZSp9GKhlImO
GC7gZxz9g6HRir7uWxxIbVyWkf99fq4QicBJGJOFAsRiWXinqWnpginGFOpmy+jA
0FS1QREJcVpoThbW0uoaaK9w2S5yIK1xaWbBqSyTiFshMRLHAA8LB+H4OIuEhMea
T31dglZ8Y+zbq/9KnZHPRDgKUoRwHZ3uvraVQ7af4qC0p09mZFJoNwEg4IFwkPUO
W7Rquq8HuWP/5UIpWnrgpFe8fzc5vQBGYARAPCrpbqfH1vFuHKRJXWLM/TbNKOXM
BxhfBFv/uFs2N7R7h7lqy+9T9ZLyl7O6LZ4r14dvd8r1yRr0azGPcIzt7B513Fv1
CKTPakgzSCEJUWoikUhvx/WTNbNmTE/s6Q2nGfnoA7X1XZ8fsc2ZPz80hqwGGEvH
cmfp9dq7Kobtl6JmT1usz2wwGChkMo9H9tzvnmceO7i3cMTLKmT4ZBG8sfL2BPaU
gE9GUNKYSAzU3+91Wt6LgzSGJVrTca2awkmW5Avampv37JCXv57ZP8BMSyEmQWcv
2D/cacufWQQBEh3BaG5y0OZx9a39V5F+sSq9VqOKFiRPaO1rN2ePmDIUFStyVUng
8fI9dKSr4YyVJ8iQyZWoStGM3erz2CpdjkYOpNK9qEg9ppTLIAFR9tHTZb1vSvec
qX+OR0a1/GgXJxClL2hQHKGxdZvu3GihVCoVqsyhIZ/Xse4RSK6vlsglSBBXRATP
4x5O0fSeaygWiTlFxWWNg9aEvBy4f09xhpE8Vmfddzig1qmRUy7XwzHnBveDy3EQ
pT1KURQgmChLYLf3zMrznK2fhxMcqP60de+XExAQBNt59GBR05/B2m8YiUSC/PZ6
vf7hD0acP3OgpKllwqQjiYmJseOKngM9zT8cz1+0UDfpTmHxNW8gXaOwHfg08+R5
z6Vf+SIBH/2a3+sf91bFQUptaYLisCCBq2xSQDrt1tl57sZzzyM57ff8OVncB747
71y+qqOslNq9PWvj1q5+m5YE0XMbCITHqjxDVziQQrMoQXoYJ8RY1Fq3tX3/Pv3G
NTkoznvmzCfb5ix7SefxQYXsxDuVubu25BSW3BKJ0wAdpCEIhf1MYHMcJFcv5FGH
WCAmSdLtceZNd/zWuBjZXF3bvWX73/Pmii6eXfDQj0mo2g1V2ZurzKmma6oUE2BC
qMQhO86Of/QIBIRfAJw7/QGvZc/H6s0b86PJunqzVaaTdvd1vYmyrk6uW16euWbV
s1m5N6bokwFkOP1w4j8gXHQAYgJUY0zQUn80+5VXjY2XrRXr7ROsMjh6LehbjV6Z
Oft0+Vum7OnJZa91yZSa/wMpFmLSQzjGRwmO+B0pyYOFecqm27TDqeMJqbCvbcNa
nUBEVle3lZRopVN0J07hQqEQgdB+CCcw3ybPSBSUU1Bic+8EpIpLP2TYMGpoYUBQ
OEgAOM3dDrQXdQUaI5mQHSdVJC8JAxG0mUHb6WG9cld769V486+o3GqzkZNVwzX2
x5p/7KZBM5PB5JJeT9dV7ysqKgJP6jr6B+fh0+/Kt4cZAAAAAElFTkSuQmCC</binImage>
<fileNameImage>TrailHead.png</fileNameImage>
</Image>
<Image>
<NameEnglish>Bike Trail</NameEnglish>
<NameRussian>Велосипедная дорожка</NameRussian>
<binImage>iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAIAAABvFaqvAAACAklEQVR42q2UMUtc
QRDH//O880wgnyCtVnYRLEISxBQBQQsJBGxCLAQNCrk010UsUlj4EQJJITY2Ymfl
VTYJWJmQFAEhnyBwp+c5zszue2/29BQOH8Pe8t7u7/4z898lZsZ9PBRARDQwIhLk
Ryi8CK4BFQvlymdQF7jQ4A7orBzRBrV1DPPsj7Ii6HIZVI0gHgJ9dvm+Jw+K+1vl
PPvpQasKCqIoA9ZLENdJJZyVEnTeinNVlIA+RBANm66GU/SRij0eV4iikxSEEaOM
....

На этом процесс генерации XML файла с данными завершен и мы переходить ко второй части задачи — загрузке данных в справочник.

Справочник будет иметь следующий вид:

Как мы видим, в справочник я добавил 2 макета.

Описание данных — это макет и с итоговой XML для загрузки.

Описание пакета — это XDS схема пакет XDTO. Мы будем загружать XML так же через пакет XDTO.

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

&НаСервереБезКонтекста
Процедура ЗагрузитьЗначенияПоУмолчаниюНаСервере()

//Получим описание пакета
ИмяФайла = ПолучитьИмяФайлаМакета("ОписаниеПакета");

//Получим свою фабрику XDTO
Фабрика = ПолучитьСвоюФабрикуXDTO(ИмяФайла);

//Получим из макета данные XML и сохраним в файл
ИмяФайлаДанных = ПолучитьИмяФайлаМакета("ОписаниеДанных");

//Прочитаем данные из фабрики
ОбъектИзображений = ПолучитьОбъектXDTOДанных(Фабрика,ИмяФайлаДанных);

//Загрузим данные в справочник
ЗагрузкаСпискаИзображений (ОбъектИзображений);
КонецПроцедуры

Загрузку изображений так же можно разбить на несколько этапов:

1) Получение своей фабрики XDTO

2) Получение объекта XDTO из XML

3) Разбор объекта XDTO

Для получения данных воспользуемся универсальной функцией, которая сохраняет данные из макета в файл и возвращает полный путь к этому файлу:

&НаСервереБезКонтекста
Функция ПолучитьИмяФайлаМакета (ИмяМакета)
ИмяФайла = ПолучитьИмяВременногоФайла(".xml");

МакетОписанияПакета = Справочники.ИзображенияMapSource.ПолучитьМакет(ИмяМакета);
ТекстОписанияПакета = МакетОписанияПакета.ПолучитьТекст();

ТекстовыйФайл = Новый ТекстовыйДокумент;
ТекстовыйФайл.ДобавитьСтроку(ТекстОписанияПакета);
ТекстовыйФайл.Записать(ИмяФайла,КодировкаТекста.UTF8);

Возврат ИмяФайла
КонецФункции

Для получения своей фабрики воспользуемся следующим кодом (спасибо большое за понимание принципов работы с XDTO Андрею Овсянкину и его циклу статей про XDTO)

&НаСервереБезКонтекста
Функция ПолучитьСвоюФабрикуXDTO(ИмяФайлаОписанияПакета)
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайлаОписанияПакета);

ПостроительDOM = Новый ПостроительDOM;
Документ = ПостроительDOM.Прочитать(Чтение);
ПостроительСхем = Новый ПостроительСхемXML;

Схема = ПостроительСхем.СоздатьСхемуXML(Документ.ЭлементДокумента);

НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить(Схема);
Фабрика = Новый ФабрикаXDTO(НаборСхем);

Возврат Фабрика;
КонецФункции

С помощью нашей фабрики мы и прочитывали объект XDTO и уже исходя из объекта формируем элементы справочника.

Для получения объекта XDTO с помощью нашей созданной фабрики используется функция:

&НаСервереБезКонтекста
Функция ПолучитьОбъектXDTOДанных(Фабрика,ИмяФайлаДанных)
ЧтениеXMLДанных = Новый ЧтениеXML;
ЧтениеXMLДанных.ОткрытьФайл(ИмяФайлаДанных);

ОбъектModel = Фабрика.ПрочитатьXML(ЧтениеXMLДанных);

Возврат ОбъектModel;
КонецФункции

Создаем элементы, на основании объекта XDTO в следующем коде:

&НаСервереБезКонтекста
Процедура ЗагрузкаСпискаИзображений (ОбъектИзображений)
ШаблонПоиска = "Custom";
Для Каждого СтрГруппы ИЗ ОбъектИзображений.ImageGroup Цикл
ГруппаИзображения = Справочники.ИзображенияMapSource.СоздатьГруппу();
ГруппаИзображения.Наименование = СтрГруппы["NameRussian"];
ГруппаИзображения.НаименованиеАнглийское = СтрГруппы["NameEnglish"];
ГруппаИзображения.ЗначениеПоУмолчанию = Истина;
ГруппаИзображения.Записать();

СсылкаНаГруппу = ГруппаИзображения.Ссылка;

Для Каждого СтрИзображения ИЗ СтрГруппы.Image Цикл
Изображение = Справочники.ИзображенияMapSource.СоздатьЭлемент();
Изображение.Наименование = СтрИзображения["NameRussian"];
Изображение.НаименованиеАнглийское = СтрИзображения["NameEnglish"];
Изображение.ЗначениеПоУмолчанию = Истина;
Изображение.ИмяФайла = СтрИзображения["fileNameImage"];
Если Найти(Изображение.ИмяФайла,ШаблонПоиска) Тогда
Изображение.ИмяФайла = ПолучитьНовоеИмяФайла(СтрИзображения["fileNameImage"],ШаблонПоиска);
КонецЕсли;
ДвоичныеДанныеИзображения = СтрИзображения["binImage"];
Изображение.ДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанныеИзображения,Новый СжатиеДанных(9));
Изображение.Родитель = СсылкаНаГруппу;
Изображение.Записать();
КонецЦикла;


КонецЦикла;
КонецПроцедуры

В итоге мы получаем то, что нам и требовалось:

Прикрепил архив с конфигурацией, с описанными объектами, изображениями и текстовым файлом, а так же отдельно изображения — вдруг кому-нибудь понадобятся

Leave a Comment

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