Анализ журнала регистрации для автонастройки списка выгружаемых объектов в обработке ВыгрузкаЗагрузкаДанныхXML82.epf

Сказ о том, как с помощью слегка модифицированной обработки ВыгрузкаЗагрузкаДанныхXML82.epf решить задачу "Выгрузить из базы-источника все объекты, которые заданный пользователь изменил в указанный период".
Данная публикация может быть интересна тем, кто хочет узнать: а) как программно анализировать журнал регистрации и б) как программно настраивать список выгружаемых объектов в обработке ВыгрузкаЗагрузкаДанныхXML82.epf.

История такая. Есть две базы — одна рабочая, другая тестовая копия. Так получилось (не будем обсуждать почему), что некий пользователь проделал большой объём работы в тестовой базе — он изменил в старых периодах около тысячи существующих документов и создал несколько новых. Работал он день и ночь на протяжении нескольких дней, не спал и не ел (по крайней мере примерно так мне описала ситуацию главный бухгалтер). В общем, в итоге возникла необходимость перенести эти изменённые документы из тестовой базы обратно в рабочую. Переносить ручками было нереально (большой объём, точных сведений что и где менялось нет), поэтому нужно было как-то заавтоматизировать процесс переноса.

Чтобы выполнить эту задачу, нужно было ответить на два вопроса — что переносить и чем переносить? Над вторым вопросом долго думать не пришлось, так как есть палочка-выручалочка под названием ВыгрузкаЗагрузкаДанныхXML82.epf. Теперь нужно было ответить на первый вопрос — что? Предоставить список изменённых документов пользователь, разумеется, не смог. Поэтому единственный способ узнать что же нужно переносить — это проанализировать журнал регистрации (нужно выгрузить все объекты, которые этот пользователь изменил/создал в указанный период времени).

По итогам в обработку ВыгрузкаЗагрузкаДанныхXML82.epf версии 2.1.8 была добавлена ещё одна кнопка с незамысловатым названием Кнопка1 и нарисован такой обработчик её нажатия:

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

Дата1 = Дата(2025, 08, 01); // Отбор записей ЖР по периоду: дата начала периода (или Неопределено)
Дата2 = Дата(2025, 08, 31); // Отбор записей ЖР по периоду: дата окончания периода (или Неопределено)
Пользователь = "Иванов И.И."; // Отбор записей ЖР по пользователю: имя пользователя (или Неопределено)

// {{ Получаем таблицу значений с записями ЖР
ТЗ = Новый ТаблицаЗначений;
Фильтр = Новый Структура;
Если ЗначениеЗаполнено(Дата1) Тогда
Фильтр.Вставить("ДатаНачала", НачалоДня(Дата1));
КонецЕсли;
Если ЗначениеЗаполнено(Дата2) Тогда
Фильтр.Вставить("ДатаОкончания", КонецДня(Дата2));
КонецЕсли;
Если ЗначениеЗаполнено(Пользователь) Тогда
Фильтр.Вставить("Пользователь", Пользователь);
КонецЕсли;
МассивСобытий = Новый Массив;
МассивСобытий.Добавить("_$Data$_.New");
МассивСобытий.Добавить("_$Data$_.Post");
МассивСобытий.Добавить("_$Data$_.Unpost");
МассивСобытий.Добавить("_$Data$_.Update");
Фильтр.Вставить("Событие", МассивСобытий);
МассивМетаданных = Новый Массив;
Для Каждого МетаДок Из Метаданные.Документы Цикл
МассивМетаданных.Добавить(МетаДок);
КонецЦикла;
Фильтр.Вставить("Метаданные", МассивМетаданных);
ВыгрузитьЖурналРегистрации(ТЗ, Фильтр, "Дата, Пользователь, Событие, Метаданные, Данные, ПредставлениеДанных");
// Получаем таблицу значений с записями ЖР }}

// Для целей отладки можно посмотреть содержимое таблицы с записями ЖР:
//Если ТЗ.ВыбратьСтроку() = Неопределено Тогда
// Возврат;
//КонецЕсли;

ТЗ.Свернуть("Метаданные, Данные"); // удаляем дубли

// {{ Формируем соответствие, у которого в качестве ключей - тип метаданных,
// а в качестве значений - массивы ссылок на объекты
// (возможно, лучше было бы использовать ДеревоЗначений, но уже лень переделывать)
ВремСоотв = Новый Соответствие;
Для Каждого СтрокаТЗ Из ТЗ Цикл
МассивДанных = ВремСоотв[СтрокаТЗ.Метаданные];
Если МассивДанных = Неопределено Тогда
МассивДанных = Новый Массив;
КонецЕсли;
МассивДанных.Добавить(СтрокаТЗ.Данные);
ВремСоотв[СтрокаТЗ.Метаданные] = МассивДанных;
КонецЦикла;
// Формируем соответствие, у которого в качестве ключей - тип метаданных,
// а в качестве значений - массивы ссылок на объекты }}

КолвоОшибок = 0;

// {{ Настраиваем какие типы объектов выгружать и какие при этом отборы использовать
Для Каждого КлючИЗначение Из ВремСоотв Цикл
ТекИмяМетаданных = КлючИЗначение.Ключ;
ТекМассивСсылок = КлючИЗначение.Значение;

ТекОбъектМД = Метаданные.НайтиПоПолномуИмени(ТекИмяМетаданных);

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

Сообщить("Настройка отборов завершена! Ошибок: " + КолвоОшибок);

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

На выходе получили требуемый XML, который и загрузили в рабочую базу.

P.S. Кстати говоря, в модификации самой обработки ВыгрузкаЗагрузкаДанныхXML82.epf особой нужды, скорее всего, нет. Полагаю, что можно нарисовать отдельную обработку-обёртку, которая получит из ЖР необходимые данные, создаст объект штатной обработки ВыгрузкаЗагрузкаДанныхXML82.epf и программно настроит у неё список выгружаемых объектов. Но это уже совсем другая история…

2 Comments

  1. bforce

    Мне понравилась сама идея чтения журнала регистрации для отлова изменившихся объектов. Ранее она мне в голову не приходила. Спасибо!

    Reply
  2. echo77

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

    Reply

Leave a Comment

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