Все описанные выше действия по обмену данными в распределенной информационной базе можно выполнить также программно. Покажем это на примере специальной обработки, с помощью которой для выбранного узла будут реализовываться те же самые действия, которые ранее мы выполняли интерактивно.
Итак, в конфигураторе центральной базы добавим обработку ОбменСМагазинами и откроем ее основную форму.
Добавим в форму реквизит Магазин типа ПланОбменаСсылка.Магазины, в котором будет содержаться ссылка на выбранный узел обмена. А также добавим в форму команды: ЗаписатьИзменения, ПрочитатьИзменения и СоздатьНачальныйОбраз. Перетащим эти команды и реквизит в окно элементов формы.
У всех трех кнопок, соответствующих командам, снимем флажок у свойства Доступность. Это делается для того, чтобы действия по созданию начального образа, записи и чтению изменений обмена становились возможны только в случае выбора в поле Магазин непредопределенного узла, который не совпадает с узлом текущей информационной базы.
Для того чтобы обеспечить такое поведение кнопок, поместим в модуле формы функцию ПолучитьДоступностьПоУзлу(), в которую передается ссылка на выбранный узел (листинг 3.33).
Листинг 3.33. Функция «ПолучитьДоступностьПоУзлу»
&НаСервереБезКонтекста
Функция ПолучитьДоступностьПоУзлу(Узел)
ДоступностьКнопок = Ложь;
// Определить наличие установленного непредопределенного узла.
Если Узел <> ПланыОбмена.Магазины.ПустаяСсылка()
И Узел <> ПланыОбмена.Магазины.ЭтотУзел()
И Узел.ПолучитьОбъект() <> Неопределено Тогда
ДоступностьКнопок = Истина;
КонецЕсли;
Возврат ДоступностьКнопок;
КонецФункции
Эта функция будет возвращать Истина, в случае если ссылка, содержащаяся в параметре Узел, не пустая и не равна ссылке на предопределенный узел, соответствующий текущей информационной базе. Для получения ссылки на текущий узел используется метод менеджера узла плана обмена ЭтотУзел(). В противном случае функция вернет Ложь.
После этого создадим обработчик события ПриИзменении для поля формы Магазин, в котором доступность кнопок будет зависеть от значения, возвращенного описанной ранее функцией (листинг 3.34).
Листинг 3.34. Обработчик события «ПриИзменении» поля «Магазин»
&НаКлиенте
Процедура МагазинПриИзменении(Элемент)
ДоступностьКнопок = ПолучитьДоступностьПоУзлу(Магазин);
// Установить доступность кнопок в зависимости от установленного узла обмена.
Элементы.СоздатьНачальныйОбраз.Доступность = ДоступностьКнопок;
Элементы.ЗаписатьИзменения.Доступность = ДоступностьКнопок;
Элементы.ПрочитатьИзменения.Доступность = ДоступностьКнопок;
КонецПроцедуры
Теперь создадим обработчик команды СоздатьНачальныйОбраз и заполним следующим образом (листинг 3.35).
Листинг 3.35. Обработчик команды «СоздатьНачальныйОбраз»
&НаКлиенте
Процедура СоздатьНачальныйОбраз(Команда)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
Диалог.Заголовок = "Выбор каталога для создания начального образа";
Диалог.Показать(Новый ОписаниеОповещения("ПослеВыбораКаталога", ЭтотОбъект));
КонецПроцедуры
В этом обработчике мы вызываем диалог выбора каталога, в который будет помещен начальный образ информационной базы, и показываем его пользователю с помощью немодального метода Показать(). В этот метод мы передаем описание оповещения, указывающее на экспортную процедуру ПослеВыбораКаталога(), которая будет вызвана после того, как пользователь выберет каталог (листинг 3.36).
Листинг 3.36. Процедура «ПослеВыбораКаталога»
&НаКлиенте
Процедура ПослеВыбораКаталога(ВыбранныеФайлы, Параметры) Экспорт
Если ВыбранныеФайлы = Неопределено Тогда
Возврат;
КонецЕсли;
Каталог = ВыбранныеФайлы[0];
СоздатьНачальныйОбразНаСервере(Магазин, Каталог);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Создание начального образа узла завершено.";
Сообщение.Сообщить();
КонецПроцедуры
В этом обработчике оповещения, в случае если каталог выбран, мы получаем путь к каталогу как первый элемент массива, содержащийся в параметре ВыбранныеФайлы, и вызываем процедуру СоздатьНачальныйОбразНаСервере(), в которую передаем этот каталог и выбранный узел обмена, содержащийся в реквизите Магазин (листинг 3.37).
Листинг 3.37. Процедура «СоздатьНачальныйОбразНаСервере»
&НаСервереБезКонтекста
Процедура СоздатьНачальныйОбразНаСервере(Узел, КаталогСоединения)
ПланыОбмена.СоздатьНачальныйОбраз(Узел, "File =""" + КаталогСоединения + """");
КонецПроцедуры
В этой процедуре вызывается метод СоздатьНачальныйОбраз() объекта ПланыОбменаМенджер, с помощью которого и создается начальный образ для подчиненного узла распределенной информационной базы. В первом параметре мы передаем в этот метод ссылку на узел, для которого мы хотим создать начальный образ, а во втором – строку соединения с создаваемой информационной базой.
Теперь создадим обработчик команды ЗаписатьИзменения и заполним следующим образом (листинг 3.38).
Листинг 3.38. Обработчик команды «ЗаписатьИзменения»
&НаКлиенте
Процедура ЗаписатьИзменения(Команда)
ЗаписатьИзмененияНаСервере(Магазин);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Запись изменений завершена.";
Сообщение.Сообщить();
КонецПроцедуры
В этом обработчике мы вызываем процедуру ЗаписатьИзмененияНаСервере(). В эту процедуру мы передаем выбранный узел обмена, содержащийся в реквизите Магазин (листинг 3.39), и выводим сообщение пользователю об успешной записи изменений, зарегистрированных для этого узла.
Листинг 3.39. Процедура «ЗаписатьИзмененияНаСервере»
&НаСервереБезКонтекста
Процедура ЗаписатьИзмененияНаСервере(Узел)
// Сформировать полное имя файла обмена.
Каталог = Константы.КаталогОбмена.Получить();
ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\","", "\") + "Message_" + СокрЛП(ПланыОбмена.Магазины.ЭтотУзел().Код) + "_" +
СокрЛП(Узел.Код) + ".xml";
// Создать и проинициализировать объект ЗаписьXML.
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайла);
// Создать объект ЗаписьСообщенияОбмена и начать запись сообщения.
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Узел);
// Записать содержимое тела сообщения обмена данными распределенной ИБ.
ПланыОбмена.ЗаписатьИзменения(ЗаписьСообщения);
// Закончить запись сообщения и запись XML.
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();
КонецПроцедуры
В этой процедуре сначала мы формируем имя файла, в который будет записано сообщение обмена.
Для упрощения примера мы будем обмениваться сообщениями через заранее известный каталог обмена, путь к которому хранится в константе Каталог обмена. Значение этой константы (например, e:\Exchange) наряду с префиксом номеров можно задать в форме настроек информационной базы (см. рис. 3.15).
Имена файлов сообщений стандартизованы и имеют вид Message_<КодУзлаОтправителя>_<КодУзлаПолучателя>.xml. В качестве узла-отправителя сообщения обмена здесь выступает предопределенный узел информационной базы, полученный с помощью метода ЭтотУзел(), а в качестве узла-получателя – узел, ссылка на который содержится в параметре Узел.
Для доступа к файлу обмена мы создаем объект ЗаписьXML. Затем с помощью метода СоздатьЗаписьСообщения() объекта ПланыОбменаМенджер создаем объект ЗаписьСообщенияОбмена, с помощью которого будет выполняться запись сообщений обмена данными. При вызове метода этого объекта НачатьЗапись() во втором параметре мы указываем, для какого узла будет производиться выгрузка изменений.
После этого мы вызываем метод ЗаписатьИзменения() объекта ПланыОбменаМенджер, который и записывает изменения, предназначенные для передачи в выбранный узел, в сообщение обмена с ранее сформированным именем.
В заключение мы заканчиваем запись сообщения обмена и закрываем файл.
Теперь создадим обработчик команды ПрочитатьИзменения и заполним следующим образом (листинг 3.40).
Листинг 3.40. Обработчик команды «ПрочитатьИзменения»
&НаКлиенте
Процедура ПрочитатьИзменения(Команда)
ПрочитатьИзмененияНаСервере(Магазин);
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Чтение изменений завершено.";
Сообщение.Сообщить();
КонецПроцедуры
В этом обработчике мы вызываем процедуру ПрочитатьИзмененияНаСервере(). В эту процедуру мы передаем выбранный узел обмена, содержащийся в реквизите Магазин (листинг 3.41), и выводим сообщение пользователю об успешном получении изменений, от этого узла.
Листинг 3.41. Процедура «ПрочитатьИзмененияНаСервере»
&НаСервереБезКонтекста
Процедура ПрочитатьИзмененияНаСервере(Узел)
// Сформировать полное имя файла обмена.
Каталог = Константы.КаталогОбмена.Получить();
ИмяФайла = Каталог + ?(Прав(Каталог, 1) = "\","", "\") + "Message_" + СокрЛП(Узел.Код) + "_" +
СокрЛП(ПланыОбмена.Магазины.ЭтотУзел().Код) + ".xml";
// Создать и проинициализировать объект ЧтениеXML.
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайла);
// Создать объект ЧтениеСообщенияОбмена и начать чтение сообщения.
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
// Прочитать содержимое тела сообщения.
ПланыОбмена.ПрочитатьИзменения(ЧтениеСообщения);
// Закончить чтение сообщения и чтение XML.
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
КонецПроцедуры
В этой процедуре мы формируем имя файла, из которого будет прочитано сообщение обмена. Это делается по аналогии с процедурой ЗаписатьИзмененияНаСервере(), приведенной в листинге 3.39. Только здесь узел-отправитель и узел-получатель сообщения меняются местами.
Для доступа к файлу обмена мы создаем объект ЧтениеXML. Затем с помощью метода СоздатьЧтениеСообщения() объекта ПланыОбменаМенджер создаем объект ЧтениеСообщенияОбмена, с помощью которого выполняется чтение сообщений обмена данными.
После этого мы вызываем метод ПрочитатьИзменения() объекта ПланыОбменаМенджер, в котором и происходит чтение изменений, полученных от выбранного узла, из сообщения обмена с ранее сформированным именем.
В заключение мы заканчиваем чтение сообщения обмена и закрываем файл.
Проверим, как это работает. Запустим «1С:Предприятие» и в форме настроек информационной базы зададим путь к каталогу обмена (e:\Exchange), который будет храниться в константе Каталог обмена (см. рис. 3.15).
Затем откроем список узлов плана обмена Магазины. Добавим в этот список еще одну запись с кодом Розн и наименованием Розничный. В поле Склад выберем значение Розничный склад. Затем откроем обработку Обмен с магазинами, в поле Магазин выберем узел обмена Розничный и нажмем кнопку Создать начальный образ (рис. 3.22).
Рис. 3.22. Программное создание начального образа для узла «Розничный»
Таким образом, мы программно создадим подчиненный узел обмена путем создания начального образа из нашей центральной базы.
Откроем базу подчиненного узла Розничный. Там мы увидим все данные, перенесенные из центральной базы при создании начального образа. При программном обмене также будет поддерживаться стратегия распространения данных по подчиненным узлам, описанная ранее в разделе «». В результате в базу розничного узла помимо «общих» данных (не привязанных к складу) попадут только те данные, склад которых совпадает со складом узла обмена. Поскольку такое поведение реализовано в модуле плана обмена Магазины, то оно «работает» независимо от способа обмена данными.
Теперь установим значение константы Префикс номеров как «РЗ» и зададим путь к каталогу обмена (e:\Exchange). Добавим новую номенклатуру. Ее код будет начинаться с префикса «РЗ». После этого откроем обработку Обмен с магазинами, в поле Магазин выберем узел, которому будут передаваться данные (Центральный офис), и нажмем кнопку Записать изменения (рис. 3.23).
Рис. 3.23. Запись изменений в подчиненном узле для центральной базы
Чтобы получить эти изменения, в центральной базе откроем обработку Обмен с магазинами, в поле Магазин выберем узел, из которого данные были выгружены (Розничный), и нажмем кнопку Прочитать изменения. В результате новая номенклатура, добавленная в подчиненном узле, появится в центральной базе.
При этом при записи изменений для центральной базы в каталоге обмена появится файл сообщения обмена с именем Message_Розн_ЦентрОфис.xml. Из этого файла изменения от розничного узла будут прочитаны в центральную базу. Выбор файла сообщения пользователем не понадобится, поскольку имена файлов стандартизованы, а каталог обмена хранится в константе информационной базы.