Сравнение таблиц значений (табличных частей)

06.12.13

Разработка - Математика и алгоритмы

Задача такова, сравнить 2 таблицы значений (Табличные части) и выдать результат, о том что в них изменилось, применительно к реальной задаче будет звучать так, показать пользователю что изменилось в документе.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Бесплатно
ПримерСравниванияТЗПоСтрокамСИспользованиемУдельногоВеса.epf
.epf 7,05Kb
48
48 Скачать бесплатно

Всем Привет!

Данная публикация в основном рассчитана на новичков, но надеюсь что и бывалые найдут что то полезное.

Собственно задача можно сказать несложная, но готовых вариантов я не увидел на просторах интернета.

Задача такова, сравнить 2 таблицы значений (Табличные части) и выдать результат, о том что в них изменилось, применительно к реальной задаче будет звучать так, показать пользователю что изменилось в документе. Допустим пусть это будут 2 разные версии объектов записанные в ИБ, конечно многие могут сказать (или подумать) может быть научить пользователя пользоваться обработкой История изменений объектов. Всё конечно хорошо в теории, но История изменения объектов (допустим УПП 1.3.38.3) обладает рядом недостатков, а именно:

  1. При версии объекта больше 999 при работе вызывает ошибку, оно и понятно разработчики не позаботились о корректном переводе (Строка – Число и обратно), но да бог с ними, не об этом речь.
  2. Обработка сравнивает табличные части по индексам, т.е. если строка будет перемещена с 1-й на 3-ю позицию, обработка покажет изменения, а они были? Тоже думаю что нет.

Накидал небольшой кусочек кода, как выкрутится из такой ситуации.

  1. Дано:

Таблица значений эталон, с ней будем сравнивать.

 

 

Таблица значений, которую  будем сравнивать.

 

Колонки «ВесСтроки, Идентификатор,БылВыбран» были добавлены для успешного анализа.

 2. Думаю описывать заполнение таблиц нет смысла, они должны у нас уже быть по задаче, отмечу только что для успешной обработки нам понадобится дополнительная структура «СтруктураВеса».

Дело в том что, при таком подходе мы сможем более  гибко настроить алгоритм для соответствия строк.

 

Возьмём пример из таблиц Выше

Строка Номер 2 в обоих таблицах содержит всего 1 изменение , а если их будет 2 и более ?

Ответ прост, при таком подходе мы можем легко настроить алгоритм так, что при совпадении только по номенклатуре  строки сопоставятся или нет, а если изменят только номенклатуру и остальные значения в строке будут нетронутыми сопоставлять ли такие строки или нет? Именно за этим мы и делаем табличку с весом значимости колонки.

 3. Так же нам понадобится таблица куда мы будем записывать результат работы алгоритма, рисунок уже после отработки алгоритма.

 

Как видим имея такую табличку, соединяя через неё сравниваемые таблицы мы всегда можем показать пользователям, что было изменено, добавлено, удалено, осталось без изменений и это всё без привязки к конкретной строке, анализируются все строки.

 

Собственно весь код ниже, так же выкладываю обработку с примером.


Функция ПровестиАнализ(ТЗИсточник,ТЗПриемник,ТЗАнализ,МассивКолонок,СтруктураВеса)

    Для Каждого Строка из ТЗИсточник Цикл
       
МаксимальныйПорог   = СтруктураВеса.Количество() + 1;
       
МинимальныйПорог    = 3;
       
ТЗПриемник.ЗаполнитьЗначения(0,"ВесСтроки");
        Для Каждого
СтрокаПоиска из ТЗПриемник Цикл
            Если
СтрокаПоиска.БылВыбран Тогда
                Продолжить;
            КонецЕсли;
           
ВесСтроки = 0;
            Для каждого
Колонка Из МассивКолонок Цикл
               
ЗначениеИсточник = Строка[Колонка];
               
ЗначениеПриемник = СтрокаПоиска[Колонка];
                Если
СтруктураВеса.Свойство(Колонка) Тогда
                    
Вес = СтруктураВеса[Колонка];
                Иначе
                     Продолжить;
                КонецЕсли;
                Если
ЗначениеИсточник = ЗначениеПриемник Тогда
                   
ВесСтроки = ВесСтроки + Вес;
                КонецЕсли;
            КонецЦикла;
           
СтрокаПоиска.ВесСтроки = ВесСтроки;
        КонецЦикла;

       
ТЗПриемник.Сортировать("ВесСтроки Убыв, БылВыбран Убыв");

        Для Каждого
СтрокаПоиска из ТЗПриемник Цикл
            Если
СтрокаПоиска.БылВыбран Тогда
                Продолжить;
            КонецЕсли;

            Если СтрокаПоиска.ВесСтроки = МаксимальныйПорог Тогда
                СтрокаПоиска.БылВыбран = Истина;
               
НоваяСтрока = ТЗАнализ.Добавить();
               
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
               
НоваяСтрока.ИдентификаторПриемник = Строка.Идентификатор;
               
НоваяСтрока.Состояние = "Совпадение";
                Прервать;
            ИначеЕсли
СтрокаПоиска.ВесСтроки >= МинимальныйПорог Тогда
               
СтрокаПоиска.БылВыбран = Истина;
               
НоваяСтрока = ТЗАнализ.Добавить();
               
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
               
НоваяСтрока.ИдентификаторПриемник = Строка.Идентификатор;
               
НоваяСтрока.Состояние = "Изменен";
                Прервать;
            ИначеЕсли
СтрокаПоиска.ВесСтроки < МинимальныйПорог Тогда
               
НоваяСтрока = ТЗАнализ.Добавить();
               
НоваяСтрока.ИдентификаторИсточник = СтрокаПоиска.Идентификатор;
               
НоваяСтрока.Состояние = "Удален";
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;

   
Отбор = Новый Структура;
   
Отбор.Вставить("БылВыбран", Ложь);
   
НайденныеСтроки = ТЗПриемник.НайтиСтроки(Отбор);

    Для Каждого
НайденнаяСтрока из НайденныеСтроки Цикл
       
СтрокаПоиска.БылВыбран = Истина;
       
НоваяСтрока = ТЗАнализ.Добавить();
       
НоваяСтрока.ИдентификаторПриемник = НайденнаяСтрока.Идентификатор;
       
НоваяСтрока.Состояние = "Добавлен";
    КонецЦикла;

    Возврат
ТЗАнализ;

КонецФункции
// ПровестиАнализ(ТЗИсточник,ТЗПриемник,ТЗАнализ)
 

Надеюсь статья была полезной.

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    20129    dimanich70    81    

144

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14734    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3581    56    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18478    171    sapervodichka    112    

135

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    8371    quazare    8    

111

СКД Универсальные функции Программист Стажер Платформа 1С v8.3 Система компоновки данных Конфигурации 1cv8 Бесплатно (free)

Столкнулся с тем, что мне приходится писать гору отчетов. Во многих приходится использовать повторяющиеся приемы. Решил написать шпаргалку, которая, надеюсь пригодится не только мне. В этой статье: Объединение ячеек в отчете только на определенном уровне иерархии, Постобработка итогов в табличном документе, Скрытие колонок в зависимости от количества месяцев в периоде.

28.05.2022    10437    milkers    11    

98

Универсальные функции БСП (Библиотека стандартных подсистем) Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данной статье я рассматриваю несколько полезных "классических" функций и процедур для работы с данными, которые уже встроены в БСП и готовы к использованию.

25.04.2022    19171    quazare    11    

139
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. kwazi 659 07.12.13 12:56 Сейчас в теме
в бсп есть подсистема версионирование и есть отчет по сравнению версий там уже все есть
2. echo77 1906 07.12.13 19:28 Сейчас в теме
(1) Автор пишет о существовании нескольких багов этого отчета.
Я бы взял этот отчет за основу и допилил
3. Xatori111 18 07.12.13 22:11 Сейчас в теме
(2)Это всего лишь пример как можно сравнить таблицы, а отчёт допилить не проблема, вопрос надо ли?
Дмитрий74Чел; +1 Ответить
4. Yashazz 4790 08.12.13 12:07 Сейчас в теме
1. Таких сравнивалок для таблиц значений уже было вагон, и я не понимаю, почему авторы почти всех их делают НЕ через запрос.
2. Если делать не для себя, а для пользователя, то я бы предложил игры с самим интерфейсом документа (например, изменить фон нужных полей и ячеек табчастей другим цветом, для изменившихся/добавленных итд, вопрос только про удалённые).
5. Поручик 4692 09.12.13 07:58 Сейчас в теме
(4) Сделай через запрос, оценим поделие.
Evil Beaver; +1 Ответить
6. Yashazz 4790 09.12.13 23:23 Сейчас в теме
(5) Изволите желать через СКД, да с наборами, аль бо по-простому, в обычном запросе? )))
7. Поручик 4692 09.12.13 23:55 Сейчас в теме
(6) Сделайте весь список, пожалуйста. Я бы не отказался посмотреть на СКД с наборами
8. soap 67 11.12.13 15:14 Сейчас в теме
Для обычного запроса как то так простейший пример

ТЗ1=Новый ТаблицаЗначений ;
ТЗ2=Новый ТаблицаЗначений;
ТЗ1.Колонки.Добавить("П1");
ТЗ1.Колонки.Добавить("П2");
ТЗ1.Колонки.Добавить("П3");
ТЗ2.Колонки.Добавить("П1");
ТЗ2.Колонки.Добавить("П2");
ТЗ2.Колонки.Добавить("П3");

Запрос.Текст =
"ВЫБРАТЬ
| ЕСТЬNULL(ТЗ1.П1,ТЗ2.П1) КАК П1,
| ЕСТЬNULL(ТЗ1.П1,1) КАК Удалено,
| ЕСТЬNULL(ТЗ2.П1,2) КАК Добавлено,
| ТЗ1.П2 КАК П2_Начальное ,
| ТЗ2.П2 КАК П2_Текущее ,
| ТЗ1.П3 КАК П3_Начальное ,
| ТЗ2.П3 КАК П3_Текущее,
| ВЫБОР
| Когда ТЗ1.П2<>ТЗ2.П2
| Тогда 3
| ИНАЧЕ 4
| КОНЕЦ КАК ИзмененоП2,
| ВЫБОР
| Когда ТЗ1.П3<>ТЗ2.П3
| Тогда 3
| ИНАЧЕ 4
| КОНЕЦ КАК ИзмененоП3
| ИЗ
| ТЗ1 КАК ТЗ1
| ПОЛНОЕ СОЕДИНЕНИЕ ТЗ2 КАК ТЗ2
| ПО ТЗ2.П1=ТЗ2.П1";
9. amyd 94 12.12.13 10:03 Сейчас в теме
тоже самое, но на основе запросов, все же перебирать табличные части, пускай и в цикле, "мовитон", особенно если ТЗ за 5000 записей.
сначала хотел вывести "контр публикацию" с ссылкой на эту, но уж очень хорошо расписана, поэтому просто дополню в комментарии своей процедурой сравнения на основе запросов
функция ТабличныеЧастиРазныеУлучшенная(ТаблицаДо,ТаблицаПосле,ТаблицаРасхождений=неопределено) экспорт
	//ТаблицаДо=док.Товары.Выгрузить();
	//	ТаблицаПосле=док.Товары.Выгрузить();
	ТекстЗапроса="Выбрать ";	
	
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		ТекстЗапроса = ТекстЗапроса +"
		| ТТДо."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса=Лев(ТекстЗапроса,стрдлина(ТекстЗапроса)-1);
	ТекстЗапроса = ТекстЗапроса+"
	|поместить ТаблоДо 
	|из 
	|	&ТабДо как ТТДо
	|;	
	|Выбрать";
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		
		ТекстЗапроса = ТекстЗапроса +"
		| ТТПосле."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса=Лев(ТекстЗапроса,стрдлина(ТекстЗапроса)-1);	
	ТекстЗапроса = ТекстЗапроса+"
	|поместить ТаблоПосле 
	|из 
	|	&ТабПосле как ТТПосле
	|;
	|выбрать" ;
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		
		ТекстЗапроса = ТекстЗапроса +"
		| Сборочный."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса = ТекстЗапроса+"
	| ЕстьNULL(сумма(Сборочный.Контроль),0) как Контроль
	|из 
	|	(
	|выбрать " ;
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		
		ТекстЗапроса = ТекстЗапроса +"
		| ТаблоДо."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса = ТекстЗапроса+"
	|   -1 как Контроль
	| из  ТаблоДо как ТаблоДо
	|	 
	|Объединить все
	|
	| Выбрать ";
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		
		ТекстЗапроса = ТекстЗапроса +"
		| ТаблоПосле."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса = ТекстЗапроса+"
	|   1
	| из  ТаблоПосле как ТаблоПосле
	| ) как Сборочный
	| сгруппировать по";
	для каждого эл из ТаблицаДо.Колонки цикл
		если эл.Имя="КлючСтроки" тогда
			продолжить;
		конецесли;
		
		ТекстЗапроса = ТекстЗапроса +"
		| Сборочный."+эл.Имя+",";
	конеццикла;
	ТекстЗапроса=Лев(ТекстЗапроса,стрдлина(ТекстЗапроса)-1);	
	
	запр = новый Запрос(ТекстЗапроса);
	
	Запр.УстановитьПараметр("ТабДо",ТаблицаДо);
	Запр.УстановитьПараметр("ТабПосле",ТаблицаПосле);
	
	ВЫЗаДН = запр.Выполнить().Выгрузить();
	ТаблицаРасхождений=ВЫЗаДН.Скопировать();
	если ВЫЗаДН.найти(1,"контроль")<> неопределено или ВЫЗаДН.найти(-1,"контроль")<>неопределено тогда
		возврат истина;
	иначе
		возврат ложь;
	конецесли;
	
	
конецфункции	
Показать
Оставьте свое сообщение