Всем Привет!
Данная публикация в основном рассчитана на новичков, но надеюсь что и бывалые найдут что то полезное.
Собственно задача можно сказать несложная, но готовых вариантов я не увидел на просторах интернета.
Задача такова, сравнить 2 таблицы значений (Табличные части) и выдать результат, о том что в них изменилось, применительно к реальной задаче будет звучать так, показать пользователю что изменилось в документе. Допустим пусть это будут 2 разные версии объектов записанные в ИБ, конечно многие могут сказать (или подумать) может быть научить пользователя пользоваться обработкой История изменений объектов. Всё конечно хорошо в теории, но История изменения объектов (допустим УПП 1.3.38.3) обладает рядом недостатков, а именно:
- При версии объекта больше 999 при работе вызывает ошибку, оно и понятно разработчики не позаботились о корректном переводе (Строка – Число и обратно), но да бог с ними, не об этом речь.
- Обработка сравнивает табличные части по индексам, т.е. если строка будет перемещена с 1-й на 3-ю позицию, обработка покажет изменения, а они были? Тоже думаю что нет.
Накидал небольшой кусочек кода, как выкрутится из такой ситуации.
- Дано:
Таблица значений эталон, с ней будем сравнивать.
Таблица значений, которую будем сравнивать.
Колонки «ВесСтроки, Идентификатор,БылВыбран» были добавлены для успешного анализа.
2. Думаю описывать заполнение таблиц нет смысла, они должны у нас уже быть по задаче, отмечу только что для успешной обработки нам понадобится дополнительная структура «СтруктураВеса».
Дело в том что, при таком подходе мы сможем более гибко настроить алгоритм для соответствия строк.
Возьмём пример из таблиц Выше
Строка Номер 2 в обоих таблицах содержит всего 1 изменение , а если их будет 2 и более ?
Ответ прост, при таком подходе мы можем легко настроить алгоритм так, что при совпадении только по номенклатуре строки сопоставятся или нет, а если изменят только номенклатуру и остальные значения в строке будут нетронутыми сопоставлять ли такие строки или нет? Именно за этим мы и делаем табличку с весом значимости колонки.
3. Так же нам понадобится таблица куда мы будем записывать результат работы алгоритма, рисунок уже после отработки алгоритма.
Как видим имея такую табличку, соединяя через неё сравниваемые таблицы мы всегда можем показать пользователям, что было изменено, добавлено, удалено, осталось без изменений и это всё без привязки к конкретной строке, анализируются все строки.
Собственно весь код ниже, так же выкладываю обработку с примером.
Функция ПровестиАнализ(ТЗИсточник,ТЗПриемник,ТЗАнализ,МассивКолонок,СтруктураВеса)
Для Каждого Строка из ТЗИсточник Цикл
МаксимальныйПорог = СтруктураВеса.Количество() + 1;
МинимальныйПорог = 3;
ТЗПриемник.ЗаполнитьЗначения(0,"ВесСтроки");
Для Каждого СтрокаПоиска из ТЗПриемник Цикл
Если СтрокаПоиска.БылВыбран Тогда
Продолжить;
КонецЕсли;
ВесСтроки = 0;
Для каждого Колонка Из МассивКолонок Цикл
ЗначениеИсточник = Строка[Колонка];
ЗначениеПриемник = СтрокаПоиска[Колонка];
Если СтруктураВеса.Свойство(Колонка) Тогда
Вес = СтруктураВеса[Колонка];
Иначе
Продолжить;
КонецЕсли;
Если ЗначениеИсточник = ЗначениеПриемник Тогда
ВесСтроки = ВесСтроки + Вес;
КонецЕсли;
КонецЦикла;
СтрокаПоиска.ВесСтроки = ВесСтроки;
КонецЦикла;
ТЗПриемник.Сортировать("ВесСтроки Убыв, БылВыбран Убыв");
Для Каждого СтрокаПоиска из ТЗПриемник Цикл
Если СтрокаПоиска.БылВыбран Тогда
Продолжить;
КонецЕсли;
Если СтрокаПоиска.ВесСтроки = МаксимальныйПорог Тогда
СтрокаПоиска.БылВыбран = Истина;
НоваяСтрока = ТЗАнализ.Добавить();
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
НоваяСтрока.ИдентификаторПриемник = Строка.Идентификатор;
НоваяСтрока.Состояние = "Совпадение";
Прервать;
ИначеЕсли СтрокаПоиска.ВесСтроки >= МинимальныйПорог Тогда
СтрокаПоиска.БылВыбран = Истина;
НоваяСтрока = ТЗАнализ.Добавить();
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
НоваяСтрока.ИдентификаторПриемник = Строка.Идентификатор;
НоваяСтрока.Состояние = "Изменен";
Прервать;
ИначеЕсли СтрокаПоиска.ВесСтроки < МинимальныйПорог Тогда
НоваяСтрока = ТЗАнализ.Добавить();
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
НоваяСтрока.Состояние = "Удален";
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Отбор = Новый Структура;
Отбор.Вставить("БылВыбран", Ложь);
НайденныеСтроки = ТЗПриемник.НайтиСтроки(Отбор);
Для Каждого НайденнаяСтрока из НайденныеСтроки Цикл
СтрокаПоиска.БылВыбран = Истина;
НоваяСтрока = ТЗАнализ.Добавить();
НоваяСтрока.ИдентификаторПриемник = НайденнаяСтрока.Идентификатор;
НоваяСтрока.Состояние = "Добавлен";
КонецЦикла;
Возврат ТЗАнализ;
КонецФункции // ПровестиАнализ(ТЗИсточник,ТЗПриемник,ТЗАнализ)
Надеюсь статья была полезной.