В работе часто приходится сжимать выгруженные данные в zip архив, отправлять по почте, и потом автоматически разархивировать полученный zip файл:
Код 1C v 8.х // Распаковывает файл архива ZIP в указанный каталог; Извлекает все файлы архива
//
// Параметры:
// ПолноеИмяФайлаАрхива - Строка - имя файла архива, который необходимо распаковать
// ПутьРаспаковкиФайлов - Строка - путь по которому необходимо распаковать файлы
// ПарольАрхива - Строка - пароль для распаковки архива. По умолчанию пустая строка
//
// Возвращаемое значение:
// Результат - Булево - Истина, если успешно, Ложь, если нет.
//
Функция РаспаковатьZipФайл(Знач ПолноеИмяФайлаАрхива, Знач ПутьРаспаковкиФайлов, Знач ПарольАрхива = "") Экспорт
// возвращаемое значение функции
Результат = Истина;
Попытка
Архиватор = Новый ЧтениеZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);
Исключение
Архиватор = Неопределено;
СообщитьОбОшибке(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
Попытка
Архиватор.ИзвлечьВсе(ПутьРаспаковкиФайлов, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при распаковке файлов архива: %1 в каталог: %2'");
СтрокаСообщения = ПодставитьПараметрыВСтроку(СтрокаСообщения, ПолноеИмяФайлаАрхива, ПутьРаспаковкиФайлов);
Сообщить(СтрокаСообщения);
Результат = Ложь;
КонецПопытки;
Архиватор.Закрыть();
Архиватор = Неопределено;
Возврат Результат;
КонецФункции
// Запаковывает указанный каталог в файл архива ZIP
//
// Параметры:
// ПолноеИмяФайлаАрхива - Строка - имя файла архива, в который необходимо запаковать
// МаскаУпаковкиФайлов - Строка - имя файла, помещаемого в архив, или маска.
// Недопустимо использование в именах файлов и папок букв национальных алфавитов, которые при
// преобразовании из символов UNICODE в узкие символы могут быть преобразованы с потерей информации.
// Рекомендуется использовать в именах файлов и папок символы латинского алфавита.
// ПарольАрхива - Строка - пароль для архива. По умолчанию пустая строка
//
// Возвращаемое значение:
// Результат - Булево - Истина, если успешно, Ложь, если нет.
//
Функция ЗапаковатьВZipФайл(Знач ПолноеИмяФайлаАрхива, Знач МаскаУпаковкиФайлов, Знач ПарольАрхива = "") Экспорт
// возвращаемое значение функции
Результат = Истина;
Попытка
Архиватор = Новый ЗаписьZipФайла(ПолноеИмяФайлаАрхива, ПарольАрхива);
Исключение
Архиватор = Неопределено;
СообщитьОбОшибке(КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Ложь;
КонецПопытки;
Попытка
Архиватор.Добавить(МаскаУпаковкиФайлов, РежимСохраненияПутейZIP.НеСохранятьПути);
Архиватор.Записать();
Исключение
СтрокаСообщения = НСтр("ru = 'Ошибка при запаковке файлов архива: %1 из каталог: %2'");
СтрокаСообщения = ПодставитьПараметрыВСтроку(СтрокаСообщения, ПолноеИмяФайлаАрхива, МаскаУпаковкиФайлов);
Сообщить(СтрокаСообщения);
Результат = Ложь;
КонецПопытки;
Архиватор = Неопределено;
Возврат Результат;
КонецФункции
В примере используется строковая функция ПодставитьПараметрыВСтроку ():
Код 1C v 8.х // Подставляет параметры в строку. Максимально возможное число параметров - 9.
// Параметры в строке задаются как %<номер параметра>. Нумерация параметров начинается с единицы.
//
// Параметры:
// СтрокаПодстановки – Строка – шаблон строки с параметрами (вхождениями вида "%ИмяПараметра");
// Параметр<n> - Строка - подставляемый параметр.
//
// Возвращаемое значение:
// Строка – текстовая строка с подставленными параметрами.
//
// Пример:
// ПодставитьПараметрыВСтроку(НСтр("ru='%1 пошел в %2'"), "Вася", "Зоопарк") = "Вася пошел в Зоопарк".
//
Функция ПодставитьПараметрыВСтроку(Знач СтрокаПодстановки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено,
Знач Параметр7 = Неопределено, Знач Параметр8 = Неопределено, Знач Параметр9 = Неопределено) Экспорт
Если СтрокаПодстановки = Неопределено ИЛИ СтрДлина(СтрокаПодстановки) = 0 Тогда
Возврат "";
КонецЕсли;
Результат = "";
НачПозиция = 1;
Позиция = 1;
Пока Позиция <= СтрДлина(СтрокаПодстановки) Цикл
СимволСтроки = Сред(СтрокаПодстановки, Позиция, 1);
Если СимволСтроки <> "%" Тогда
Позиция = Позиция + 1;
Продолжить;
КонецЕсли;
Результат = Результат + Сред(СтрокаПодстановки, НачПозиция, Позиция - НачПозиция);
Позиция = Позиция + 1;
СимволСтроки = Сред(СтрокаПодстановки, Позиция, 1);
Если СимволСтроки = "%" Тогда
Позиция = Позиция + 1;
НачПозиция = Позиция;
Результат = Результат + "%";
Продолжить;
КонецЕсли;
Попытка
НомерПараметра = Число(СимволСтроки);
Исключение
ВызватьИсключение НСтр("ru='Входная строка СтрокаПодстановки имеет неверный формат: %'" + СимволСтроки);
КонецПопытки;
Если СимволСтроки = "1" Тогда
ЗначениеПараметра = Параметр1;
ИначеЕсли СимволСтроки = "2" Тогда
ЗначениеПараметра = Параметр2;
ИначеЕсли СимволСтроки = "3" Тогда
ЗначениеПараметра = Параметр3;
ИначеЕсли СимволСтроки = "4" Тогда
ЗначениеПараметра = Параметр4;
ИначеЕсли СимволСтроки = "5" Тогда
ЗначениеПараметра = Параметр5;
ИначеЕсли СимволСтроки = "6" Тогда
ЗначениеПараметра = Параметр6;
ИначеЕсли СимволСтроки = "7" Тогда
ЗначениеПараметра = Параметр7;
ИначеЕсли СимволСтроки = "8" Тогда
ЗначениеПараметра = Параметр8;
ИначеЕсли СимволСтроки = "9" Тогда
ЗначениеПараметра = Параметр9;
Иначе
ВызватьИсключение НСтр("ru='Входная строка СтрокаПодстановки имеет неверный формат: %'" + ЗначениеПараметра);
КонецЕсли;
Если ЗначениеПараметра = Неопределено Тогда
ЗначениеПараметра = "";
Иначе
ЗначениеПараметра = Строка(ЗначениеПараметра);
КонецЕсли;
Результат = Результат + ЗначениеПараметра;
Позиция = Позиция + 1;
НачПозиция = Позиция;
КонецЦикла;
Если (НачПозиция <= СтрДлина(СтрокаПодстановки)) Тогда
Результат = Результат + Сред(СтрокаПодстановки, НачПозиция, СтрДлина(СтрокаПодстановки) - НачПозиция + 1);
КонецЕсли;
Возврат Результат;
КонецФункции
При написании небольших автоматизированных тестов часто надо обойти всю конфигурацию и проверить, например, для всех форм какое-нибудь свойство. Это всё легко делается через свойство глобального контекста "Метаданные", но чтоб дорбаться до обхода реквизитов надо написать кучу вложенных циклов. При этом код становится слабочитаемым и слабомодифицируемым.
Ниже приведен небольшой модуль, который решает задачу легко и удобно. Создана специальная функция РазвернутьСтрокуОбходаМетаданных, которая может по строке типа "Метаданные.Справочники.*.Реквизиты.*" построить массив строк с перечислением всех реквизитов всех справочников. При помощи этой и нескольких других функций в экспортных функциях модуля реализованы вполне прикладные задачи - получение всех реквизитов, всех макетов, всех форм конфигурации и построение таблицы всех составных типов.
Код 1C v 8.х // Автор: Alexander Speshilov
// Рекрсивная функция, которая разворачивает строку вида "Метаданные.Справочники.*[Имя].Реквизиты.*.Тип"
// в массив строк, заменяя "*" или другой символ, задаваемый параметрами обходом всех элементов
// коллекции. Допускает выполнение функций встроенного языка (не стоит отдавать ввод параметров
// пользователям). При этом выражение, используемое для получения по умолчанию может быть задано в
// квадратных скобках или параметром функции.
//
// Параметры
// СтрокаОбхода - Строка - Разворачиваемая строка
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Массив строк
//
Функция РазвернутьСтрокуОбходаМетаданных(СтрокаОбхода, ЗаменяемоеЗначение = "*", ПредставлениеПоУмолчанию = "")
Рез = Новый Массив;
ЧастиСтрокиОбхода = РазобратьСтрокуОбхода(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Если ЧастиСтрокиОбхода = Неопределено тогда
Рез.Добавить(СтрокаОбхода); //фактически это ограничение рекурсии.
Иначе
ОбъектКоллекции = Вычислить(ЧастиСтрокиОбхода.СтрокаКоллекции);
РазвернутаяКоллекция = РазвернутьКоллекциюВПредставления(ОбъектКоллекции, ЧастиСтрокиОбхода.СтрокаПредставление);
Для каждого ЭлементРазвернутойКоллекции Из РазвернутаяКоллекция Цикл
// рекурсивный вызов
ТекущаяСтрокаОбхода = ЧастиСтрокиОбхода.СтрокаНачало + ЭлементРазвернутойКоллекции + ЧастиСтрокиОбхода.СтрокаКонец;
МассивЭлемента = РазвернутьСтрокуОбходаМетаданных(ТекущаяСтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Для каждого ПримитивныйЭлементОбхода Из МассивЭлемента Цикл
Рез.Добавить(ПримитивныйЭлементОбхода);
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат Рез;
КонецФункции // РазвернутьСтрокуОбходаМетаданных()
// Разбирает строку обхода на удобные для работы поля
//
// Параметры
// СтрокаОбхода - Строка - Разворачиваемая строка
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Структура с полями ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец
// или Неопределено (если строка не содержит ЗаменяемоеЗначение)
//
Функция РазобратьСтрокуОбхода(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию)
Если ПустаяСтрока(ЗаменяемоеЗначение) Тогда
ВызватьИсключение "Некорректное выражение заменяемого значения";
КонецЕсли;
ПозицияЗамены = Найти(СтрокаОбхода, ЗаменяемоеЗначение);
// Если не найдена строка - возвращаем неопределено, как индикатор
Если ПозицияЗамены = 0 Тогда
Возврат Неопределено;
КонецЕсли;
СтрокаНачало = Лев(СтрокаОбхода,ПозицияЗамены - 1);
//Получение строки для выражения-коллекции
СтрокаКоллекции = СтрокаНачало;
Если Прав(СтрокаКоллекции, 1) = "." Тогда
СтрокаКоллекции = Лев(СтрокаКоллекции,СтрДлина(СтрокаКоллекции) - 1);
КонецЕсли;
ПозицияОкончанияЗамены = ПозицияЗамены + СтрДлина(ЗаменяемоеЗначение);
ОстатокВыражения = Сред(СтрокаОбхода, ПозицияОкончанияЗамены);
//Обработка явного задания представления
ОткрывающаяСкобка = "[";
ЗакрывающаяСкобка = "]";
Если Найти(ОстатокВыражения, ОткрывающаяСкобка) = 1 Тогда
ОстатокВыражения = Сред(ОстатокВыражения, СтрДлина(ОткрывающаяСкобка) + 1);
ПозицияЗакрывающейСкобки = Найти(ОстатокВыражения, ЗакрывающаяСкобка);
Если ПозицияЗакрывающейСкобки = 0 Тогда
ВызватьИсключение "Синтаксическая ошибка разбора выражения";
КонецЕсли;
СтрокаПредставление = Лев(ОстатокВыражения, ПозицияЗакрывающейСкобки - 1);
ОстатокВыражения = Сред(ОстатокВыражения, ПозицияЗакрывающейСкобки + СтрДлина(ЗакрывающаяСкобка));
Иначе
СтрокаПредставление = ПредставлениеПоУмолчанию;
КонецЕсли;
СтрокаКонец = ОстатокВыражения;
Рез = Новый Структура("ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец",
ПозицияЗамены, СтрокаНачало, СтрокаКоллекции, СтрокаПредставление, СтрокаКонец);
Возврат Рез;
КонецФункции // РазобратьСтрокуОбхода()
// Разворачивает объект коллекции в массив представления элементов
//
// Параметры
// Коллекция - Произвольный - Коллекция, которую можно обойти через "Для каждого"
// ПредставлениеЭлемента - Строка - необяз., свойство элементов коллекции, которое
// используется для получения представления.
//
// Возвращаемое значение:
// Массив - Массив представлений коллекции
//
Функция РазвернутьКоллекциюВПредставления(Коллекция, Знач ПредставлениеЭлемента = "")
//Проверка и подгонка параметров
Если не ПустаяСтрока(ПредставлениеЭлемента) Тогда
Если Найти(ПредставлениеЭлемента, ";")>0 Тогда
ВызватьИсключение "Некорректное выражение представления";
КонецЕсли;
ПредставлениеЭлемента = "." + ПредставлениеЭлемента;
КонецЕсли;
Рез = Новый Массив;
Для каждого ЭлементКоллекции Из Коллекция Цикл
ТекПредставление = Строка(Вычислить("ЭлементКоллекции" + ПредставлениеЭлемента));
Рез.Добавить(ТекПредставление);
КонецЦикла;
Возврат Рез;
КонецФункции // РазвернутьКоллекцию()
// Разворачивает массив строк через РазвернутьСтрокуОбходаМетаданных
//
// Параметры
// МассивСтрокОбхода - Массив - Массив разворачиваемых строк
// ЗаменяемоеЗначение - Строка - заменяемое значение
// ПредставлениеПоУмолчанию - Строка - выражение для получения представления
//
// Возвращаемое значение:
// Массив строк
//
Функция РазвернутьМассивСтрокОбходаМетаданных(МассивСтрокОбхода, ЗаменяемоеЗначение = "*", ПредставлениеПоУмолчанию = "Имя")
Рез = Новый Массив;
Для каждого СтрокаОбхода Из МассивСтрокОбхода Цикл
ДополнениеРезультата = РазвернутьСтрокуОбходаМетаданных(СтрокаОбхода, ЗаменяемоеЗначение, ПредставлениеПоУмолчанию);
Для каждого ТекСтрока Из ДополнениеРезультата Цикл
Рез.Добавить(ТекСтрока);
КонецЦикла;
КонецЦикла;
Возврат Рез;
КонецФункции // РазвернутьМассивСтрокОбходаМетаданных()
// Преобразует строку в массив одиночных строк по разделителю Символы.ПС
//
// Параметры
// ПреобразуемаяСтрока - строка для преобразования
// ИгнорироватьПустые - Булево - Пропускать пустые строки
// СокращатьПробелы - Использовать СокрЛП
//
// Возвращаемое значение:
// Массив строк
//
Функция ПолучитьМассивСтрокМногострочнойСтроки(ПреобразуемаяСтрока, ИгнорироватьПустые = Истина, СокращатьПробелы = Истина)
Рез = Новый Массив;
ЧислоСтрок = СтрЧислоСтрок(ПреобразуемаяСтрока);
Для Сч = 1 По ЧислоСтрок Цикл
ТекСтрока = СтрПолучитьСтроку(ПреобразуемаяСтрока, Сч);
Если ИгнорироватьПустые и ПустаяСтрока(ТекСтрока) Тогда
Продолжить;
КонецЕсли;
Если СокращатьПробелы Тогда
ТекСтрока = СокрЛП(ТекСтрока);
КонецЕсли;
Рез.Добавить(ТекСтрока);
КонецЦикла;
Возврат Рез;
КонецФункции // ПолучитьМассивСтрокМногострочнойСтроки()
// Возвращает все реквизиты конфигурации, которые сохраняются в ИБ
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеХранимыеРеквизитыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.Константы.*
|Метаданные.ПланыОбмена.*.Реквизиты.*
|Метаданные.ПланыОбмена.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Справочники.*.Реквизиты.*
|Метаданные.Справочники.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Документы.*.Реквизиты.*
|Метаданные.Документы.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Последовательности.*.Измерения.*
|Метаданные.ПланыВидовХарактеристик.*.Реквизиты.*
|Метаданные.ПланыВидовХарактеристик.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.ПланыСчетов.*.Реквизиты.*
|Метаданные.ПланыСчетов.*.ПризнакиУчета.*
|Метаданные.ПланыСчетов.*.ПризнакиУчетаСубконто.*
|Метаданные.ПланыСчетов.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.ПланыВидовРасчета.*.Реквизиты.*
|Метаданные.ПланыВидовРасчета.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.РегистрыСведений.*.Измерения.*
|Метаданные.РегистрыСведений.*.Ресурсы.*
|Метаданные.РегистрыСведений.*.Реквизиты.*
|Метаданные.РегистрыНакопления.*.Измерения.*
|Метаданные.РегистрыНакопления.*.Ресурсы.*
|Метаданные.РегистрыНакопления.*.Реквизиты.*
|Метаданные.РегистрыБухгалтерии.*.Измерения.*
|Метаданные.РегистрыБухгалтерии.*.Ресурсы.*
|Метаданные.РегистрыБухгалтерии.*.Реквизиты.*
|Метаданные.РегистрыРасчета.*.Измерения.*
|Метаданные.РегистрыРасчета.*.Ресурсы.*
|Метаданные.РегистрыРасчета.*.Реквизиты.*
|Метаданные.БизнесПроцессы.*.Реквизиты.*
|Метаданные.БизнесПроцессы.*.ТабличныеЧасти.*.Реквизиты.*
|Метаданные.Задачи.*.Реквизиты.*
|Метаданные.Задачи.*.РеквизитыАдресации.*
|Метаданные.Задачи.*.ТабличныеЧасти.*.Реквизиты.*
|";
ВсеХранимыеРеквизитыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеХранимыеРеквизитыКонфигурации;
КонецФункции // ПолучитьВсеХранимыеРеквизитыКонфигурации()
// Возвращает все реквизиты конфигурации составного типа, которые сохраняются в ИБ
//
// Параметры - Нет
//
// Возвращаемое значение:
// ТаблицаЗначений
//
Функция ПолучитьВсеХранимыеРеквизитыКонфигурацииСоставногоТипа() Экспорт
ВсеХранимыеРеквизитыКонфигурации = ПолучитьВсеХранимыеРеквизитыКонфигурации();
Рез = Новый ТаблицаЗначений;
Рез.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
Рез.Колонки.Добавить("Тип", Новый ОписаниеТипов("ОписаниеТипов"));
Рез.Колонки.Добавить("КоличествоПростыхТипов", Новый ОписаниеТипов("Число"));
Для каждого ТекРеквизит Из ВсеХранимыеРеквизитыКонфигурации Цикл
Реквизит = Вычислить(ТекРеквизит);
Тип = Реквизит.Тип;
КоличествоПростыхТипов = Тип.Типы().Количество();
Если КоличествоПростыхТипов<>1 Тогда
ТекСтрока = Рез.Добавить();
ТекСтрока.Имя = ТекРеквизит;
ТекСтрока.Тип = Тип;
ТекСтрока.КоличествоПростыхТипов = КоличествоПростыхТипов;
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции // ПолучитьВсеХранимыеРеквизитыКонфигурации()
// Возвращает все формы конфигурации
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеФормыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.ПланыОбмена.*.Формы.*
|Метаданные.КритерииОтбора.*.Формы.*
|Метаданные.ОбщиеФормы.*
|Метаданные.Справочники.*.Формы.*
|Метаданные.Документы.*.Формы.*
|Метаданные.ЖурналыДокументов.*.Формы.*
|Метаданные.Перечисления.*.Формы.*
|Метаданные.Отчеты.*.Формы.*
|Метаданные.Обработки.*.Формы.*
|Метаданные.ПланыВидовХарактеристик.*.Формы.*
|Метаданные.ПланыСчетов.*.Формы.*
|Метаданные.ПланыВидовРасчета.*.Формы.*
|Метаданные.РегистрыСведений.*.Формы.*
|Метаданные.РегистрыНакопления.*.Формы.*
|Метаданные.РегистрыБухгалтерии.*.Формы.*
|Метаданные.РегистрыРасчета.*.Формы.*
|Метаданные.БизнесПроцессы.*.Формы.*
|Метаданные.Задачи.*.Формы.*
|";
ВсеФормыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеФормыКонфигурации;
КонецФункции // ПолучитьВсеФормыКонфигурации()
// Возвращает все макеты конфигурации
//
// Параметры - Нет
//
// Возвращаемое значение:
// Массив объектов метаданных
//
Функция ПолучитьВсеМакетыКонфигурации() Экспорт
СтрокаВсехРеквизитов =
"
|Метаданные.ПланыОбмена.*.Макеты.*
|Метаданные.ОбщиеМакеты.*
|Метаданные.Справочники.*.Макеты.*
|Метаданные.Документы.*.Макеты.*
|Метаданные.ЖурналыДокументов.*.Макеты.*
|Метаданные.Перечисления.*.Макеты.*
|Метаданные.Отчеты.*.Макеты.*
|Метаданные.Обработки.*.Макеты.*
|Метаданные.ПланыВидовХарактеристик.*.Макеты.*
|Метаданные.ПланыСчетов.*.Макеты.*
|Метаданные.ПланыВидовРасчета.*.Макеты.*
|Метаданные.РегистрыСведений.*.Макеты.*
|Метаданные.РегистрыНакопления.*.Макеты.*
|Метаданные.РегистрыБухгалтерии.*.Макеты.*
|Метаданные.РегистрыРасчета.*.Макеты.*
|Метаданные.БизнесПроцессы.*.Макеты.*
|Метаданные.Задачи.*.Макеты.*
|";
ВсеМакетыКонфигурации = РазвернутьМассивСтрокОбходаМетаданных(ПолучитьМассивСтрокМногострочнойСтроки(СтрокаВсехРеквизитов));
Возврат ВсеМакетыКонфигурации;
КонецФункции // ПолучитьВсеМакетыКонфигурации()
Для того чтобы существовала возможность обмена какими-либо данными с кем-либо, необходимо некоторым образом идентифицировать тех, с кем мы будем обмениваться, и для каждого из них описать перечень обмена
Обе эти задачи позволяет решать прикладной объект конфигурации
План обмена .
При помощи планов обмена мы получаем информацию о том, какие элементы данных были изменены и в какой узел обмена их необходимо передать. Это возможно благодаря тому, что планы обмена содержат механизм регистрации изменений. Информация об измененных данных переносится с помощью сообщений, инфраструктура которых также поддерживается планами обмена.
Подобно тому, как элементами данных справочника являются элементы справочника, элементами данных плана обмена являются узлы плана обмена. Каждый узел идентифицирует участника обмена по данному плану обмена. Кроме этого в каждом плане обмена всегда существует один предопределенный узел, идентифицирующий данную информационную базу.
В состав данных, которыми может производиться обмен, входят элементы информационных структур базы данных, которые описываются следующими объектами встроенного языка:
Константа.МенеджерЗначения.<имя>;
СправочникОбъект.<имя>;
ДокументОбъект.<имя>;
ПоследовательностьНаборЗаписей.<имя>;
ПланВидовХарактеристикОбъект.<имя>;
ПланСчетовОбъект.<имя>;
ПланВидовРасчетаОбъект.<имя>;
РегистрСведенийНаборЗаписей.<имя>;
РегистрНакопленияНаборЗаписей.<имя>;
РегистрБухгалтерииНаборЗаписей.<имя>;
РегистрРасчетаНаборЗаписей.<имя>;
ПерерасчетНаборЗаписей.<имя>;
БизнесПроцессОбъект.<имя>;
ЗадачаОбъект.<имя>;
УдалениеОбъекта.
При описании состава данных плана обмена разработчик имеет возможность указать для каждого типа объектов признак Авторегистрация. Он определяет, каким образом план обмена будет отслеживать изменения этих данных.
Создание плана обмена Филиалы
Состав данных обмена должен выглядеть следующим образом:
Теперь с помощью конструктора создадим основную форму узла, чтобы описать в ней некоторые действия, которые должны выполняться при создании нового узла обмена.
Суть этих действий будет заключаться в том, что при создании нового узла обмена мы должны будем сформировать для него все необходимые записи регистрации изменений для всех объектов конфигурации, входящих в данный план обмена. Это будет своего рода начальная синхронизация узла обмена всеми данными обмена.
Прежде всего, опишем в модуле формы узла служебную переменную, которая будет хранить признак того, является ли записываемый узел новым или нет.
Перем РегистрацияВНовыйУзел;
Затем создадим обработчик события формы ПередЗаписью.
Код 1C v 8.х Процедура ПередЗаписью(Отказ)
РегистрацияВНовыйУзел = ЭтоНовый();
КонецПроцедуры
Этот обработчик и будет устанавливать значение нашей служебной переменной в Истина в случае записи нового узла плана обмена.
После этого создадим обработчик события формы ПриЗаписи.
Код 1C v 8.х Процедура ПриЗаписи(Отказ)
Если РегистрацияВНовыйУзел Тогда
// Регистрация изменений всех данных для узла
ПланыОбмена.ЗарегистрироватьИзменения(Ссылка);
КонецЕсли;
КонецПроцедуры
Создание обработки Обмен данными
Откроем конфигуратор и создадим новый объект конфигурации Обработка с именем ОбменДанными. Перейдем на закладку Прочее и откроем модуль объекта.
Создадим в нем процедуру ОбменСФилиалами.
Код 1C v 8.х Процедура ОбменСФилиалами() Экспорт
ВыборкаУзлов = ПланыОбмена.Филиалы.Выбрать();
Пока ВыборкаУзлов.Следующий() Цикл
// Произвести обмен данными со всеми узлами, кроме текущего (ЭтотУзел)
Если ВыборкаУзлов.Ссылка <> ПланыОбмена.Филиалы.ЭтотУзел() Тогда
УзелОбъект = ВыборкаУзлов.ПолучитьОбъект();
// Получить сообщение
УзелОбъект.ПрочитатьСообщениеСИзменениями();
// Сформировать сообщение
УзелОбъект.ЗаписатьСообщениеСИзменениями();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Теперь создадим основную форму обработки и в обработчик события нажатия кнопки Выполнить – КнопкаВыполнитьНажатие вставим вызов процедуры ОбменСФилиалами().
Код 1C v 8.х Процедура КнопкаВыполнитьНажатие(Элемент)
ОбменСФилиалами();
КонецПроцедуры
Создание процедуры записи данных
Сами процедуры записи и чтения данных обмена мы разместим в модуле объекта План обмена Филиалы. Сначала создадим процедуру, которая используется нами при обмене данными, – ЗаписатьСообщениеСИзменениями.
Код 1C v 8.х Процедура ЗаписатьСообщениеСИзменениями() Экспорт
Сообщить("-------- Выгрузка в узел " + Строка(ЭтотОбъект) + " ---------");
Каталог = КаталогВременныхФайлов();
// Сформировать имя временного файла
ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\","", "\") + "Message"
+ СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + "_" +
СокрЛП(Ссылка.Код) + ".xml";
// Создать объект записи XML
// *** Запись XML-документов
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайла);
ЗаписьXML.ЗаписатьОбъявлениеXML();
// *** Инфраструктура сообщений
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Ссылка);
Сообщить("Номер сообщения: " + ЗаписьСообщения.НомерСообщения);
// Получить выборку измененных данных
// *** Механизм регистрации изменений
ВыборкаИзменений =ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель,
ЗаписьСообщения.НомерСообщения);
Пока ВыборкаИзменений.Следующий() Цикл
// Записать данные в сообщение
// *** XML-сериализация
ЗаписатьXML(ЗаписьXML, ВыборкаИзменений.Получить());
КонецЦикла;
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();
Сообщить("-------- Конец выгрузки------------");
КонецПроцедуры
На этом создание процедуры записи данных обмена закончено.
Создание процедуры чтения данных
Код 1C v 8.х Процедура ПрочитатьСообщениеСИзменениями() Экспорт
Каталог = КаталогВременныхФайлов();
// Сформировать имя файла
ИмяФайла = Каталог +?(Прав(Каталог, 1) = "\", "", "\") + "Message"
+ СокрЛП(Ссылка.Код) + "_" +
СокрЛП(ПланыОбмена.Филиалы.ЭтотУзел().Код) + ".xml";
Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Тогда
Возврат;
КонецЕсли;
// *** Чтение документов XML
// Попытаться открыть файл
ЧтениеXML = Новый ЧтениеXML;
Попытка
ЧтениеXML.ОткрытьФайл(ИмяФайла);
Исключение
Сообщить("Невозможно открыть файл обмена данными.");
Возврат;
КонецПопытки;
Сообщить("-------- Загрузка из " + Строка(ЭтотОбъект) + "------------");
Сообщить(" - Считывается файл " + ИмяФайла);
// Загрузить из найденного файла
// *** Инфраструктура сообщений
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
// Читать заголовок сообщения обмена данными - файла XML
ЧтениеСообщения.НачатьЧтение(ЧтениеXML);
// Сообщение предназначено не для этого узла
Если ЧтениеСообщения.Отправитель <> Ссылка Тогда
ВызватьИсключение "Неверный узел";
КонецЕсли;
// Удаляем регистрацию изменений
// для узла отправителя сообщения
// *** Служба регистрации изменений
ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель,ЧтениеСообщения.НомерПринятого);
// Читаем данные из сообщения
// *** XML-сериализация
Пока ВозможностьЧтенияXML(ЧтениеXML) Цикл
// Читаем очередное значение
Данные = ПрочитатьXML(ЧтениеXML);
// Записать полученные данные
Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
Данные.ОбменДанными.Загрузка = Истина;
Данные.Записать();
КонецЦикла;
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
УдалитьФайлы(ИмяФайла);
Сообщить("-------- Конец загрузки------------");
КонецПроцедуры