
1S_8.2_Praktikum
.pdf
//Получить выборку измененных данных
//*** Механизм регистрации изменений ВыборкаИзменений =
ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель ,ЗаписьСообщения.НомерСообщения);
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть(); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец выгрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Теперь осталось только перебрать выборку записей в цикле и сериализовать их в открытый XML-файл.
//Получить выборку измененных данных
//*** Механизм регистрации изменений ВыборкаИзменений =
ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель ,ЗаписьСообщения.НомерСообщения);
Пока ВыборкаИзменений.Следующий() Цикл
// Записать данные в сообщение *** XML-сериализация ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());
КонецЦикла;
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть(); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец выгрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
На этом создание процедуры записи данных обмена закончено. Полностью она выглядит так:
Процедура ЗаписатьСообщениеСИзменениями() Экспорт
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "-------- Выгрузка в узел " + Строка(ЭтотОбъект) + " ---------
---";
Сообщение.Сообщить(); Каталог = КаталогВременныхФайлов();
// Сформировать имя временного файла
ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\","", "\") + "Message" + СокрЛП(ПланыОбмена.
Филиалы.ЭтотУзел().Код) + "_" + СокрЛП(Ссылка.Код) + ".xml";
411

//Создать объект записи XML
//*** ЗаписьXML-документов ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.ОткрытьФайл(ИмяФайла); ЗаписьXML.ЗаписатьОбъявлениеXML();
//*** Инфраструктура сообщений
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения(); ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Ссылка); Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = " Номер сообщения: " + ЗаписьСообщения.НомерСообщения; Сообщение.Сообщить();
//Получить выборку измененных данных
//*** Механизм регистрации изменений ВыборкаИзменений =
ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель ,ЗаписьСообщения.НомерСообщения);
Пока ВыборкаИзменений.Следующий() Цикл
// Записать данные в сообщение *** XML-сериализация ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());
КонецЦикла;
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть(); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец выгрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Процедура чтения данных
Порядок создания процедуры чтения данных будет таким же, как и ранее. Если вы не хотите детально разбираться в коде, пролистайте до конца раздела, там будет процедура полностью.
Сначала сформируем имя файла, содержащего данные обмена.
Процедура ПрочитатьСообщениеСИзменениями() Экспорт
Каталог = КаталогВременныхФайлов();
// Сформировать имя файла ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\", "", "\") +
"Message" + СокрЛП(Ссылка.Код) + "_" +
СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + ".xml"; Файл = Новый Файл(ИмяФайла); Если Не Файл.Существует() Тогда
Возврат; КонецЕсли;
412

УдалитьФайлы(ИмяФайла); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец загрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Мы формируем имя файла, которое надеемся найти в этом каталоге, а затем, создав новый объект Файл с таким именем проверяем, существует ли он. Если такого файла нет, мы завершаем работу процедуры. Если же он найден, нужно будет удалить его после того, как все данные, содержащиеся в нем, будут обработаны.
Теперь добавим в процедуру команды чтения найденного файла с данными обмена.
Процедура ПрочитатьСообщениеСИзменениями() Экспорт
Каталог = КаталогВременныхФайлов();
// Сформировать имя файла ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\", "", "\") +
"Message" + СокрЛП(Ссылка.Код) + "_" +
СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + ".xml"; Файл = Новый Файл(ИмяФайла); Если Не Файл.Существует() Тогда
Возврат; КонецЕсли;
//*** Чтение документов XML
//Попытаться открыть файл ЧтениеXML = Новый ЧтениеXML; Попытка
ЧтениеXML.ОткрытьФайл(ИмяФайла); Исключение
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Невозможно открыть файл обмена данными."; Сообщение.Сообщить();
Возврат; КонецПопытки;
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "-------- Загрузка из " + Строка(ЭтотОбъект) + " ------
------";
Сообщение.Сообщить(); Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = " – Считывается файл " + ИмяФайла; Сообщение.Сообщить();
ЧтениеXML.Закрыть();
УдалитьФайлы(ИмяФайла); Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "-------- Конец загрузки ------------"; Сообщение.Сообщить();
413

КонецПроцедуры
Именно в этот момент мы обращаемся к механизмам записи/чтения документов XML, которые работают с ними на базовом уровне.
Для этого мы создаем новый объект ЧтениеXML, с помощью которого открываем найденный файл для чтения. В случае успеха мы выводим сообщение о начале загрузки данных из файла. В конце процедуры мы также прекращаем чтение XML-данных из файла методом Закрыть().
Полученные таким образом данные должны являться некоторым сообщением обмена данными. Для того чтобы предоставить их в терминах сообщений, мы добавим в процедуру следующий код:
//*** Чтение документов XML
//Попытаться открыть файл ЧтениеXML = Новый ЧтениеXML; Попытка
ЧтениеXML.ОткрытьФайл(ИмяФайла); Исключение
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "Невозможно открыть файл обмена данными.";
Сообщение.Сообщить(); Возврат;
КонецПопытки; Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "-------- Загрузка из " + Строка(ЭтотОбъект) + " ------------"; Сообщение.Сообщить(); Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = " – Считывается файл " + ИмяФайла; Сообщение.Сообщить();
//Загрузить из найденного файла
//*** Инфраструктура сообщений
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
// Читать заголовок сообщения обмена данными – файла XML ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть(); |
|
|
УдалитьФайлы(ИмяФайла); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец загрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Здесь мы обращаемся к механизмам инфраструктуры сообщений планов обмена и создаем объект ЧтениеСообщенияОбмена. Используя метод
414

этого объекта НачатьЧтение(), мы считываем заголовок XMLсообщения, в котором содержится в том числе информация об отправителе сообщения. После того, как всѐ сообщение будет нами обработано, мы заканчиваем чтение.
Теперь, когда мы представили данные обмена в виде сообщения и получили его заголовок, можно произвести одну проверку перед тем, как начать собственно обрабатывать данные.
//Загрузить из найденного файла
//*** Инфраструктура сообщений
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
//Читать заголовок сообщения обмена данными – файла XML ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
//Сообщение предназначено не для этого узла
Если ЧтениеСообщения.Отправитель <> Ссылка Тогда ВызватьИсключение "Неверный узел";
КонецЕсли;
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть(); |
|
|
УдалитьФайлы(ИмяФайла); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец загрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Мы проверяем, является ли отправитель сообщения тем узлом, для которого мы в данном вызове этой процедуры производим обмен данными.
Если все в порядке, то перед тем как начать чтение данных, следует удалить все записи регистрации изменений, которые были сделаны для этого узла и соответствовали номерам сообщений как номер принятого. Это делается затем, чтобы исключить дублирование данных, которые уже были ранее посланы этому узлу и им обработаны.
// Сообщение предназначено не для этого узла Если ЧтениеСообщения.Отправитель <> Ссылка Тогда ВызватьИсключение
"Неверный узел"; КонецЕсли;
//Удаляем регистрацию изменений для узла отправителя сообщения.
//*** Служба регистрации изменений
ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправ итель,ЧтениеСообщения.НомерПринятого);
415

ЧтениеСообщения.ЗакончитьЧтение();
Здесь мы обращаемся к службе регистрации изменений и используем метод УдалитьРегистрациюИзменений() для выполнения описанных действий.
Теперь можем приступить к непосредственно чтению самих данных, содержащихся в сообщении.
// Сообщение предназначено не для этого узла Если ЧтениеСообщения.Отправитель <> Ссылка Тогда ВызватьИсключение
"Неверный узел"; КонецЕсли;
// Удаляем регистрацию изменений для узла отправителя сообщения. // *** Служба регистрации изменений
ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель,Чт ениеСообщения.НомерПринятого);
// Читаем данные из сообщения *** XML-сериализация Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
КонецЦикла;
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
Чтение данных выполняется в цикле, причем мы снова обращаемся к механизмам XML-сериализации и методом глобального контекста ВозможностьЧтенияXML() получаем очередной тип данных XML из объекта ЧтениеXML и определяем, имеется ли соответствующий тип 1С:Предприятия. В случае успеха выполнение цикла продолжается.
Первое, что нам нужно сделать – представить данные XML в виде некоторого значения, имеющего тип 1С:Предприятия. Для этого мы используем метод глобального контекста ПрочитатьXML().
// Читаем данные из сообщения *** XML-сериализация Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
//Читаем очередное значение
Данные = ПрочитатьXML(ЧтениеXML);
КонецЦикла;
Врезультате выполнения этого метода переменная Данные будет содержать объект 1С:Предприятия, соответствующий данным XML.
Теперь следует разрешить возможную коллизию.
416

// Читаем данные из сообщения *** XML-сериализация Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
// Читаем очередное значение
Данные = ПрочитатьXML(ЧтениеXML);
// Не переносим изменение, полученное в главный из неглавного, если есть регистрация изменения
Если Не ЧтениеСообщения.Отправитель.Главный И
ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправит ель, Данные) Тогда
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = " – Изменения отклонены"; Сообщение.Сообщить();
Продолжить; КонецЕсли;
КонецЦикла;
Возможная коллизия решается следующим образом: мы проверяем, является ли узел-отправитель главным узлом и есть ли записи об изменении этого объекта для данного узла в нашей БД. Если объект изменялся в нашей базе и отправитель не является главным узлом, мы отклоняем запись полученного объекта. Во всех остальных случаях мы принимаем изменения полученного объекта.
Теперь единственное, что нам осталось сделать – записать полученные данные.
// Не переносим изменение, полученное в главный из неглавного, если есть регистрация изменения
Если Не ЧтениеСообщения.Отправитель.Главный И
ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправитель, Данные) Тогда
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = " – Изменения отклонены"; Сообщение.Сообщить();
Продолжить; КонецЕсли;
// Записать полученные данные Данные.ОбменДанными.Отправитель =
ЧтениеСообщения.Отправитель; Данные.ОбменДанными.Загрузка = Истина; Данные.Записать();
КонецЦикла;
Перед записью полученного объекта мы устанавливаем у него в параметрах обмена данными узел отправителя для того, чтобы система
417

при записи этого объекта в нашей базе данных не формировала записи регистрации изменений этого объекта для того узла, от которого мы его только что получили.
Кроме этого, в параметрах обмена мы устанавливаем свойство Загрузка, информирующее систему о том, что запись объекта будет происходить в режиме обновления данных, полученных в результате обмена. Такое указание позволяет системе упростить процедуру записи объекта, отказавшись от ряда стандартных проверок и исключив изменения связанных данных, которые выполняются при обычной записи.
На этом создание процедуры получения и обработки данных обмена закончено. Полностью процедура будет выглядеть так:
Процедура ПрочитатьСообщениеСИзменениями() Экспорт
Каталог = КаталогВременныхФайлов();
// Сформировать имя файла ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\", "", "\") +
"Message" + СокрЛП(Ссылка.Код) + "_" +
СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + ".xml"; Файл = Новый Файл(ИмяФайла); Если Не Файл.Существует() Тогда
Возврат; КонецЕсли;
//*** Чтение документов XML
//Попытаться открыть файл ЧтениеXML = Новый ЧтениеXML; Попытка
ЧтениеXML.ОткрытьФайл(ИмяФайла); Исключение
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "Невозможно открыть файл обмена данными."; Сообщение.Сообщить();
Возврат; КонецПопытки;
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "-------- Загрузка из " + Строка(ЭтотОбъект) + " ------------"; Сообщение.Сообщить(); Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = " – Считывается файл " + ИмяФайла; Сообщение.Сообщить();
//Загрузить из найденного файла
//*** Инфраструктура сообщений
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
//Читать заголовок сообщения обмена данными – файла XML ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
//Сообщение предназначено не для этого узла
418

Если ЧтениеСообщения.Отправитель <> Ссылка Тогда ВызватьИсключение "Неверный узел";
КонецЕсли; // Удаляем регистрацию изменений для узла отправителя сообщения.
// *** Служба регистрации изменений ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель,Чт
ениеСообщения.НомерПринятого);
// Читаем данные из сообщения *** XML-сериализация Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
// Читаем очередное значение
Данные = ПрочитатьXML(ЧтениеXML);
// Не переносим изменение, полученное в главный из неглавного, если есть регистрация изменения
Если Не ЧтениеСообщения.Отправитель.Главный И
ПланыОбмена.ИзменениеЗарегистрировано(ЧтениеСообщения.Отправитель, Данные) Тогда
Сообщение = Новый СообщениеПользователю; Сообщение.Текст = " – Изменения отклонены"; Сообщение.Сообщить();
Продолжить; КонецЕсли;
// Записать полученные данные Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель; Данные.ОбменДанными.Загрузка = Истина; Данные.Записать();
КонецЦикла;
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть(); |
|
|
УдалитьФайлы(ИмяФайла); |
|
|
Сообщение = Новый СообщениеПользователю; |
|
|
Сообщение.Текст = "-------- |
Конец загрузки ------------ |
"; |
Сообщение.Сообщить(); |
|
|
КонецПроцедуры
Проверка работы обмена данными
Чтобы иметь возможность редактировать константу ПрефиксНумерации, раскроем ветвь Общие, выделим ветвь Общие формы и с помощью конструктора форм создадим форму констант с именем ОбщиеНастройки.
419

Откроем окно свойств Дополнительно для этой формы (контекстное меню – Дополнительно) и укажем принадлежность этой формы к подсистеме Предприятие.
420