Записать данные в сообщение 2 страница

В

отличие от XML-сериализации, механизмы записи/чтения документов XML позволяют работать с данными формата XML на «базовом» уровне, без привязки к объектам 1С:Предприятия. В частности они позволяют открывать файлы XML для чтения, читать данные из файлов, создавать новые файлы XML и записывать в них данные.


 


398



Использование основных объектов конфигурации


Обмен данными


 


Универсальный механизм обмена данными

Постановка задачи

И

так, наше OOO «На все руки мастер» открыло свой филиал в городе Урюпинск и установило в нем такую ясе конфигурацию для учета работы филиала. В результате возникла необходимость наладить обмен данными между этими двумя базами таким образом, чтобы каждая из баз отражала полную информацию о материалах и услугах, в то время как бухгалтерский учет и расчет зарплаты велся бы в каждоЙ базе отдельно.

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

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

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

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


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

Для хранения префикса номеров мы используем объект конфигурации, с которым до сих пор еще не работали - это объект Константа.

Создание константы ПрефиксНомеров

О

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

Теперь приступим к созданию константы, в которой мы будем хранить значение префикса номеров. Откроем конфигуратор и создадим новый объект конфигурации Константа с именем «ПрефиксНумерации». Определим тип значения константы - Строка, с фиксированной длиной 2 символа.

Доработка объектов конфигурации, участвующих в обмене

П

ервое, что нам следует сделать - внести изменения в модули всех объектов, участвующих в обмене (в нашем случае это будут документы, справочники и планы видов характеристик). Эти изменения будут заключаться в том, что теперь при формировании номера документа и кода справочника или плана видов характеристик будет использоваться значение константы «ПрефиксНумерации» для обеспечения уникальности номеров и кодов в каждой из наших баз.

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


 


400



Использование основных объектов конфигурации

Функцию мы разместим в общем модуле «ОбменДанными», выглядеть она будет следующим образом:

Функция ПопучитьПрефиксНомера() Экспорт ВозвратКонсташы.ПрефиксНумерации.Получить();

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

Как вы видите, эта функция просто возвращает значение константы «ПрефиксНумерации».

Теперь доработаем справочник «Клиенты». В модуль объекта
добавим следующий обработчик события

«ПриУстановкеНовогоКода»:

Процедура ПриУстановкеНовогоКодаССтандартнаяОбработка, Префикс)

Префикс = ПолучитьПрефиксНомера();
КонецПроцедуры__________________________________________

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

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

Теперь займемся доработкой документов. В модуль документа
«ПриходнаяНакладная» добавим обработчик события

«ПриУстановкеНовогоНомера»:


Обмен данными

Такие же обработчики нужно будет добавить во все документы, участвующие в обмене. После этого для всех них нужно изменить тип номера на Строкаи увеличить длину номера до 7 символов.

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

Создание плана обмена Филиалы

Т

еперь займемся созданием «центра» любого алгоритма обмена данными, вокруг которого группируются прочие механизмы -плана обмена. Откроем конфигуратор и создадим новый объект конфигурации ПланОбменас именем «Филиалы». На закладке «Данные» создадим реквизит плана обмена «Главный», имеющий тип Булево.

Этот реквизит понадобится нам для того, чтобы разрешать коллизии при обмене данными. Под коллизией понимается ситуация, когда один и тот же объект обмена данными был изменен одновременно в двух узлах. В этом случае мы будем анализировать значение реквизита «Главный» и принимать изменения только в том случае, если они сделаны в главном узле. В случае коллизии, изменения, произведенные не в главном узле, мы будем отвергать.

Теперь перейдем на закладку «Прочее» и определим состав объектов обмена данными (кнопка «Состав»).

Установим отбор по подсистеме «УчетУслугИМатериалов» и включим в обмен все объекты, относящиеся к этой подсистеме. Проверьте, что константа «ПрефиксНумерации» не участвует в обмене, поскольку ее значение должно быть уникальным для каждой базы, участвующей в обмене.


ПроцедураПриУстановкеНовогоНомераССтандартнаяОбработка,

Префикс)

Префикс = ПолучитьПрефиксНомера();
КонецПроцедуры______




Использование основных объектов конфигурации


Обмен данными


 


                           
   
 
 
 
   
     
 
     
       
 
 
 
   

Состав данных обмена должен выглядеть следующим образом:

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

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

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

Перем РегистрацияВНовыйУзел;

Затем создадим обработчик события формы «ПередЗаписью»:

Процедура ПередЗаписью(Отказ)

РегистрацияВНовыйУзел = ЭтоНовый();
КонецПроцедуры


Этот обработчик и будет устанавливать значение нашей служебной переменной в Истина,в случае записи нового узла плана обмена. После этого создадим обработчик события формы «ПриЗаписи»:

Процедура ПриЗаписи(Отказ) Если РегистрацияВНовыйУзел Тогда // Регистрация изменений всех данных для узла

ПланыОбмена.ЗарегистрироватьИзменения(Ссылка)-КонецЕсли;

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

Событие формы «ПриЗаписи» возникает после записи объекта ПланОбменаОбъект.Филиалы,но до окончания транзакции. Именно в этот момент мы обращаемся к механизму регистрации изменений, вызывая метод менеджера планов обмена -ЗарегистрироватьИзменения(). Вданном случае будут созданы записи регистрации изменений, предназначенные для пересылки в созданный нами узел, для всех объектов обмена, указанных в составе данного плана обмена.

В заключение, создадим обработчик события формы «ПередОткрытием» для того, чтобы запретить установку реквизита «Главный» для предопределенного узла, соответствующего данной информационной базе:

!роцедура ПередОткрытием(Отказ, СтандартнаяОбработка) Если Ссылка = ПланыОбмена.Филиалы.ЭтотУзел() Тогда

ЭлементыФормы.Главный.Достуггаость = Ложь; КонецЕсли;

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

В этой процедуре мы используем метод менеджера плана обмена ЭтотУзел(), который возвращает ссылку на узел плана обмена, соответствующий данной информационной базе.

На этом создание плана обмена завершено, и мы можем перейти непосредственно к созданию процедур обмена данными.


 


404



Использование основных объектов конфигурации

Создание процедур обмена данными

Д

ля инициализации обмена данными мы используем объек конфигурации Обработка. Этот объект раньше не встреча7С нам, поэтому следует сказать о нем несколько слов. С точки зрения структуры и организации работы обработка ничем не отличается от отчета. Разница состоит лишь в том, что обработка обычно используется для того, чтобы выполнить какие-либо действия над информационной базой, а отчет - чтобы получить некоторое визуальное представление данных.

Создание обработки ОбменДанными

О

ткроем конфигуратор и создадим новый объект конфигурации Обработка с именем «ОбменДанными». Перейдем на закладку «Прочее» и откроем модуль объекта. Создадим в нем процедуру «ОбменСФилиалами»:

Процедура ОбменСФилналами() Экспорт

ВыборкаУзлов = ПланыОбмена.Филиалы.Выбрать();

Пока ВыборкаУзлов.Следующий() Цикл

// Произвести обменданными со всеми узлами,

// кроме текущего (ЭтотУзел)

Если ВыборкаУзлов.Ссылка оПланыОбмена

.Филиалы

.ЭтотУзел() Тогда УзелОбъект = ВыборкаУзлов.ПолучитьОбъект();

// Получить сообщение

УзелОбъект.ПрочитатьСообщениеСИзменениями();

// Сформировать сообщение

УзелОбъект.ЗаписатьСообщениеСИзменениямиО;

КонецЕсли; КонецДикла; КонепПроцедуры

Алгоритм работы этой процедуры заключается в следующем: i цикле мы перебираем узлы, которые содержатся в плане обмена «Филиалы», и для всех узлов, кроме себя самого, производим сначала чтение сообщений, поступивших из других узлов обмена (процеДУРУ


Обмен данными

«ПрочитатьСообщенияСИзменениями» мы создадим позднее), а затем формируем для них сообщения, предназначенные для передачи и содержащие измененные данные для этого узла (процедура «ЗаписатьСообщениеСИзменениями» также будет создана нами позднее).

Теперь создадим основную форму обработки и в обработчик события нажатия кнопки «Выполнить» - «КнопкаВыполнитьНажатие» вставим вызов процедуры ОбменСФилиалами():

ПроцедураКнопкаВыполнитьНажатие(Элемент)

ОбменСФилиалами(); КонедПроцедуры

Создание процедуры записи данных

С

ами процедуры записи и чтения данных обмена мы разместим в модуле объекта План обмена «ОбменСФилиалами». Сначала создадим процедуру, которая используется нами при обмене данными - «ЗаписатьСообщениеСИзменениями». Порядок создания этой процедуры будет следующим: сначала мы сформируем имя файла, который будет содержать данные для обмена:

Процедура ЗаписатьСообщениеСИзменениями() Экспорт

Сообщить("----- Выгрузка в узел" + Строка(ЭтотОбъект) + "--------- ");

Каталог = КаталогВременныхФайлов();

// Сформировать имя временного файла

ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\","", "\") +

"Message" + СокрЛЩПланыОбмена.Филиалы.ЭтотУзел().Код) + "_" + СокрЛП(Ссылка.Код) + ".xml";

Сообщить("----- Конец выгрузки----------");

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

Для упрощения примера, мы будем обмениваться сообщениями через каталог временных файлов. Имена сообщений стандартизованы и имеют вид «Ме8$а§еКодУзлаОтправителя_КодУзлаПолучателя.хт1».

После этого обратимся к механизмам записи/чтения XML документов и создадим новый объект ЗаписьХМЦ с помощью которого откроем новый XML файл для записи, запишем в него


 


406



Использование основных объектов конфигурации

объявление XML, и в конце процедуры завершим запись закроем файл:

Процедура ЗаписатьСообщениеСИзменениями() Экспорт
Сообщить("----- Выгрузка в узел " + Строка(ЭтотОбъект) + "-------- ");

Каталог = КаталогВременныхФайлов(); // Сформировать имя временного файла ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\","", "\") +

"Message" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + *_"

СокрЛП(Ссылка.Код) + ".xrnl;

// Создать объект записи XML //*** запись XML документов ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.ОткрытьФайл(ИмяФайла);ЗаписьXML.ЗаписатьОбъявлениеXML();

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

Сообщить("----- Конец выгрузки---------- ");

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

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


Обмен данными

ЗаписьСообщения.ЗакончитьЗапись();

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

Сообщить("----- Конец выгрузки---------- ");

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

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

При формировании выборки мы передаем вторым параметром номер сообщения, которым эти данные будут переданы:

Процедура ЗаписатьСообщениеСИзменениями() Экспорт

Сообщить("----- Выгрузка в узел " + Строка(ЭтотОбъект) + "----------");

Каталог = КаталогВременныхФайлов(); // Сформировать имя временного файла ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\","", "\") +

"Message" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + "_" + СокрЛП(Ссылка.Код) + ".xml";

// Создать объект записи XML //*** запись XML документов ЗаписьXML = Новый ЗаписьXML; ЗaписьXML.OткpытьФaйл(ИмяФaйлa);

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


 


Процедура ЗаписатьСообщениеСИзменениями() Экспорт
Сообщить("----- Выгрузка в узел " + Строка(ЭтотОбъект) + "-------- ");

Каталог = КаталогВременныхФайлов(); // Сформировать имя временного файла ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\","", "\") +

"Message" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + "_* СокрЛП(Ссьшка.Код) + ".xml*;

// Создать объект записи XML //*** запись XML документов ЗаписьXML = Новый ЗаписьХМЦ ЗaпиcьXML.OткpьrтьФaйл(ИмяФaйлa);

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

//*** инфраструктура сообщений

ЗаписьСообщения= ПланыОбмена.СоздатьЗаписьСообщенияО;

ЗаписьСообщения.НачатьЗапись(ЗаписьХМЬ, Ссылка);

Сообщить(" Номер сообщения; " + ЗаписьСообщения.НомерСообшения),^


//*** инфраструктура сообщений

ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Ссылка);

Сообщить(" Номер сообщения:" + ЗаписьСообщения.НомерСообщения);

// Получить выборку измененных данных//*** механизм регистрации изменений ВыборкаИзменений= ПланыОбмена

.ВыбратьИзмененияЗаписьСообщения.Получатель,

ЗаписьСообщения.НомерСообщеиия);

ЗаписьСообщения.ЗакончитьЗапись();

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

Сообщить("----- Конец выгрузки---------- ");

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


 




Использование основных объектов конфигурации


Обмен данными


 


Теперь осталось только перебрать выборку записей в цикле сериализовать их в открытый XML файл:

Процедура ЗаписатьСообщениеСИзменениями() Экспорт

Сообщить("----- Выгрузка в узел " + Строка(ЭтотОбъект) + "--------- ");

Каталог = КаталогВременныхФайлов(); // Сформировать имя временного файла ИмяФайла = Каталог +?(Прав(Каталог, 1)= "\'\"", "\") +

"Message" + СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + "_" + СокрЛП(Ссылка.Код) + ".xml";

// Создать объект записи XML //*** запись XML документов ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.ОткрытьФайл(ИмяФайла); ЗаписьXML.ЗаписатьОбъявлениеXML();

//*** инфраструктура сообщений

ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

ЗаписьСообщения.НачатьЗапись(ЗаписьXML,Ссылка);

Сообщить(" Номер сообщения:" + ЗаписьСообщения.НомерСообщения);

// Получить выборку измененных данных //*** механизм регистрации изменений ВыборкаИзменений = ПланыОбмена

.ВыбратьИзменения(ЗаписьСообщения.Получатель,

ЗаписьСообщения.НомерСообщения);

Пока ВыборкаИзмеиений.Следующий() Цикл