Перебор строк и колонок - это цикл в цикле, что не очень производительно.
Для решения задач типа:
- сравнить таблицы с учетом или без учета порядка строк
- поиск дублирующихся строк
удобно пользоваться методом таблицы значений Свернуть().
Идея такова:
1. Копируем обе таблицы в одну общую таблицу
2. В общую таблицу добавляем колонку "Показатель". Заполняем его следующим образом: в строках, полученных из первой таблицы ставим Показатель = 1, в строках из второй таблицы ставим Показатель = 2
3. Сворачиваем общую таблицу: ТаблицаОбщая.Свернуть(ВсеСравниваемыеКолонки, "Показатель");
4. После свертки совпавшие строки будут иметь Показатель = 3, а в несовпавших строках будет Показатель = 1, либо Показатель = 2
Таким образом, отсутстсвие строк с показателем, равным 1 или 2, является признаком равенства таблиц.
Заметим, что для данного подхода совсем необязательно, чтобы количество строк сравниваемых таблиц совпадало. Просто будет обнаружена разница и лишние строки окажутся в числе несовпавших строк.
Вот процедура, реализующая данный подход
// Ищет отличия двух таблиц
//
// Параметры:
// Таблица1 - ТаблицаЗначений или ТабличнаяЧасть - первая таблица
// Таблица2 - ТаблицаЗначений или ТабличнаяЧасть - вторая таблица
// МассивСтрокиТаблицы1 - Выходной параметр, массив строк Таблицы1 - строки Таблицы1,
// несовпадающие с соответствующими строками Таблицы2
// МассивСтрокиТаблицы2 - Выходной параметр, массив строк Таблицы2 - строки Таблицы2,
// несовпадающие с соответствующими строками Таблицы1
// СтрокаПереченьКолонок - Строка - имена колонок, по которым сравниваются строки таблиц.
// Если пустая строка, то подразумеваются все колонки Таблицы1
// СтрокаИсключемыеКолонки - Строка - колонки, которые не должны участвовать в сравнении
//
// Описание:
// Процедура сравнивает таблицы, и возвращает несовпадающие строки в двух массивах
//
// Пример:
//
// Документ1 = ...
// Документ2 = ...
// СтрокиОтличия1 = Неопределено;
// СтрокиОтличия2 = Неопределено;
// НайтиОтличияТаблиц(Документ1.Товары, Документ2.Товары, СтрокиОтличия1, СтрокиОтличия2);
// Если СтрокиОтличия1.Количество() + СтрокиОтличия2.Количество() = 0 Тогда
// Сообщить("Табличные части документов совпадают");
// КонецЕсли;
//
Процедура НайтиОтличияТаблиц(Таблица1, Таблица2, МассивСтрокиТаблицы1, МассивСтрокиТаблицы2, СтрокаПереченьКолонок = "", СтрокаИсключемыеКолонки = "")
#Область Определение_реального_перечня_колонок
// Определение реального перечня колонок с учетом необязательных параметров
// В области определяется переменная РеальныйПереченьКолонок и ничего больше
СтруктураИсключаемыеКолонки = Новый Структура(СтрокаИсключемыеКолонки);
Если ЗначениеЗаполнено(СтрокаПереченьКолонок) Тогда
Если ЗначениеЗаполнено(СтрокаИсключемыеКолонки) Тогда
// Странно, что заполнены оба необязательных параметра.
// Тем не менее, выполним это требование
РеальныйПереченьКолонок = "";
СтруктураПереченьКолонок = Новый Структура(СтрокаПереченьКолонок);
Для каждого ЭлементСтруктуры Из СтруктураПереченьКолонок Цикл
ИмяКолонки = ЭлементСтруктуры.Ключ;
Если Не СтруктураИсключаемыеКолонки.Свойство(ИмяКолонки) Тогда
РеальныйПереченьКолонок = РеальныйПереченьКолонок + ?(РеальныйПереченьКолонок = "", "", ", ") + ИмяКолонки;
КонецЕсли;
КонецЦикла;
Иначе
РеальныйПереченьКолонок = СтрокаПереченьКолонок;
КонецЕсли;
Иначе
РеальныйПереченьКолонок = "";
Если ТипЗнч(Таблица1) = Тип("ТаблицаЗначений") Тогда
Колонки = Таблица1.Колонки;
Иначе
Колонки = Таблица1.ВыгрузитьКолонки().Колонки;
КонецЕсли;
Для каждого Колонка Из Колонки Цикл
Если Не СтруктураИсключаемыеКолонки.Свойство(Колонка.Имя) Тогда
РеальныйПереченьКолонок = РеальныйПереченьКолонок + ?(РеальныйПереченьКолонок = "", "", ", ") + Колонка.Имя;
КонецЕсли;
КонецЦикла;
КонецЕсли;
#КонецОбласти
#Область Создание_общей_таблицы
// Создается объединенная общая таблица, заполненная строками обеих таблиц
// с двумя дополнительными системными колонками
// В области определяется переменная ТаблицаОбщая и ничего больше
Если ТипЗнч(Таблица1) = Тип("ТаблицаЗначений") Тогда
ТаблицаОбщая = Таблица1.Скопировать(, РеальныйПереченьКолонок);
Иначе
ТаблицаОбщая = Таблица1.Выгрузить(, РеальныйПереченьКолонок);
КонецЕсли;
ТаблицаОбщая.Колонки.Добавить("sys_ИндексСтроки");
ТаблицаОбщая.Колонки.Добавить("sys_ПоказательТаблицы");
ИндексСтроки = 0;
Для каждого СтрокаОбщейТаблицы Из ТаблицаОбщая Цикл
СтрокаОбщейТаблицы.sys_ИндексСтроки = ИндексСтроки;
СтрокаОбщейТаблицы.sys_ПоказательТаблицы = 1;
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
ИндексСтроки = 0;
Для каждого СтрокаТаблицы2 Из Таблица2 Цикл
СтрокаОбщейТаблицы = ТаблицаОбщая.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаОбщейТаблицы, СтрокаТаблицы2);
СтрокаОбщейТаблицы.sys_ИндексСтроки = ИндексСтроки;
СтрокаОбщейТаблицы.sys_ПоказательТаблицы = 2;
ИндексСтроки = ИндексСтроки + 1;
КонецЦикла;
#КонецОбласти
// Сворачивание совпадающих строк
ТаблицаОбщая.Свернуть("sys_ИндексСтроки, " + РеальныйПереченьКолонок, "sys_ПоказательТаблицы");
// Получение результатов
МассивСтрокиТаблицы1 = Новый Массив;
СтрокиСПоказателем1 = ТаблицаОбщая.НайтиСтроки(Новый Структура("sys_ПоказательТаблицы", 1));
Для каждого СтрокаОбщейТаблицы Из СтрокиСПоказателем1 Цикл
МассивСтрокиТаблицы1.Добавить(Таблица1[СтрокаОбщейТаблицы.sys_ИндексСтроки]);
КонецЦикла;
МассивСтрокиТаблицы2 = Новый Массив;
СтрокиСПоказателем2 = ТаблицаОбщая.НайтиСтроки(Новый Структура("sys_ПоказательТаблицы", 2));
Для каждого СтрокаОбщейТаблицы Из СтрокиСПоказателем2 Цикл
МассивСтрокиТаблицы2.Добавить(Таблица2[СтрокаОбщейТаблицы.sys_ИндексСтроки]);
КонецЦикла;
// Замечание. Строки ОбщейТаблицы, у которых sys_ПоказательТаблицы = 3, это совпавшие
// строки Таблицы1 и Таблицы2
КонецПроцедуры
Показать