RDT1C/DataProcessors/ирСравнениеТаблиц/Ext/ObjectModule.bsl
Администратор 9a70e9dec5 .
2021-05-03 23:50:12 +03:00

1390 lines
105 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирПривилегированный Экспорт;
Перем ПризнакРавно Экспорт; // признаки сравнения
Перем ПризнакНеРавно Экспорт;
Перем ПризнакТолько1 Экспорт;
Перем ПризнакТолько2 Экспорт;
Перем ВыводитьРазницу Экспорт; // флаг, выводить ли разницу числовых сравниваемых колонок
Перем ВсегоРазличий Экспорт; // количество найденных различий при сравнении файлов
Перем ЗагрузкаТабличныхДанных1 Экспорт;
Перем ЗагрузкаТабличныхДанных2 Экспорт;
Перем КонсольЗапросов1 Экспорт;
Перем КонсольЗапросов2 Экспорт;
Перем мИмяГруппыКлючевыхКолонок Экспорт;
Перем мИмяГруппыСравниваемыхКолонок Экспорт;
Перем мИмяГруппыНесравниваемыхКолонок Экспорт;
Перем мИмяГруппыРазностныхКолонок Экспорт;
Перем мИмяКолонкиРезультатаСравнения Экспорт;
Перем мИмяКолонкиНомераСтрокиРезультата Экспорт;
Перем СравниваемыеКолонкиРезультата Экспорт;
Перем СтруктураКолонокРезультата Экспорт;
Перем мИменаВозвращаемыхСвойств Экспорт;
Функция ОбновитьДанныеТаблицы(Знач НомерСтороны, Интерактивно = Ложь, СброситьНастройки = Ложь) Экспорт
Если ЭтотОбъект["ТипИсточника" + НомерСтороны] = "ТаблицаЗначений" Тогда
ИмяФайла = ЭтотОбъект["ИмяФайла" + НомерСтороны];
Если ЗначениеЗаполнено(ИмяФайла) Тогда
Файл = Новый Файл(ИмяФайла);
Таблица = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(Файл.ПолноеИмя, Истина);
ЭтотОбъект["Таблица" + НомерСтороны] = Таблица;
КонецЕсли;
ИначеЕсли ЭтотОбъект["ТипИсточника" + НомерСтороны] = "ТабличныйДокумент" Тогда
ИмяФайла = ЭтотОбъект["ИмяФайла" + НомерСтороны];
ЗагрузкаТабличныхДанных = ЗагрузчикТабличныхДанных(НомерСтороны);
#Если Сервер И Не Сервер Тогда
ЗагрузкаТабличныхДанных = Обработки.ирЗагрузкаТабличныхДанных.Создать();
#КонецЕсли
ФормаЗагрузки = ЗагрузкаТабличныхДанных.ПолучитьФорму(); // Чтобы создались колонки в реквизитах объекта
Если ЗначениеЗаполнено(ИмяФайла) Тогда
Файл = Новый Файл(ИмяФайла);
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.Прочитать(Файл.ПолноеИмя);
ЗагрузкаТабличныхДанных.ТабличныйДокумент = ТабличныйДокумент;
КонецЕсли;
ЗагрузкаТабличныхДанных.ТаблицаЗначений = ЭтотОбъект["Таблица" + НомерСтороны];
НастройкаЗагрузки = Неопределено;
Если Не СброситьНастройки Тогда
НастройкаЗагрузки = ЭтотОбъект["НастройкаЗагрузки" + НомерСтороны];
КонецЕсли;
Если НастройкаЗагрузки <> Неопределено Тогда
ЗагрузкаТабличныхДанных.мЗагрузитьНастройку(НастройкаЗагрузки, Не ЗначениеЗаполнено(ИмяФайла));
Иначе
Интерактивно = Истина;
КонецЕсли;
ЗагрузкаТабличныхДанных.ОбновитьКолонкиТаблицыЗначений(НастройкаЗагрузки = Неопределено, Ложь);
ЗагрузкаТабличныхДанных.ОбновитьСопоставлениеКолонокТЗ();
ЗагрузкаТабличныхДанных.СопоставлениеКолонокТЗЗаполнить();
Если Интерактивно Тогда
ФормаЗагрузки.СинхронизироватьРеквизитыОбъекта(Ложь);
ФормаЗагрузки.РежимРедактора = Истина;
ФормаЗагрузки.ПараметрТабличныйДокумент = ТабличныйДокумент;
РезультатФормы = ФормаЗагрузки.ОткрытьМодально();
Если РезультатФормы = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
ЗагрузкаТабличныхДанных.СохранятьДанныеТД = Не ЗначениеЗаполнено(ИмяФайла);
ЗагрузкаТабличныхДанных.СохранятьДанныеТЗ = Ложь;
ЭтотОбъект["НастройкаЗагрузки" + НомерСтороны] = ЗагрузкаТабличныхДанных.мПолучитьНастройку();
КонецЕсли;
ЗагрузкаТабличныхДанных.ЗагрузитьВТаблицуЗначенийИзТабличногоДокумента();
Таблица = ЗагрузкаТабличныхДанных.ТаблицаЗначений;
ЭтотОбъект["Таблица" + НомерСтороны] = Таблица;
ИначеЕсли ЭтотОбъект["ТипИсточника" + НомерСтороны] = "Запрос" Тогда
КонсольЗапросов = КонсольЗапросов(НомерСтороны);
Если Ложь
Или КонсольЗапросов.ДеревоЗапросов.Строки.Количество() = 0
Или Интерактивно
Тогда
КонсольЗапросов.мФормаБудетОткрыватьсяПовторно = Истина;
КонсольЗапросов.мКоллекцияДляЗаполнения = Новый ТаблицаЗначений;
КонсольЗапросов.ОткрытьМодально();
КонецЕсли;
КонсольЗапросов.ВыполнитьЗапрос();
Таблица = КонсольЗапросов.ЭлементыФормы.РезультатКоллекция.Значение;
ЭтотОбъект["Таблица" + НомерСтороны] = Таблица;
КонецЕсли;
ОбновитьСопоставлениеКолонок();
ЗаполнитьСопоставлениеКолонок();
Таблица = ЭтотОбъект["Таблица" + НомерСтороны];
Если Таблица.Количество() = 0 Тогда
ирОбщий.СообщитьЛкс("Таблица " + НомерСтороны + " не содержит данных");
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
Функция ЗагрузчикТабличныхДанных(Знач НомерСтороны) Экспорт
ЗагрузкаТабличныхДанных = ЭтотОбъект["ЗагрузкаТабличныхДанных" + НомерСтороны];
Если ЗагрузкаТабличныхДанных = Неопределено Тогда
ЗагрузкаТабличныхДанных = ирОбщий.СоздатьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирЗагрузкаТабличныхДанных");
ЭтотОбъект["ЗагрузкаТабличныхДанных" + НомерСтороны] = ЗагрузкаТабличныхДанных;
КонецЕсли;
Возврат ЗагрузкаТабличныхДанных;
КонецФункции
Функция КонсольЗапросов(Знач НомерСтороны = 1) Экспорт
КонсольЗапросов = ЭтотОбъект["КонсольЗапросов" + НомерСтороны];
Если КонсольЗапросов = Неопределено Тогда
КонсольЗапросов = ирОбщий.СоздатьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов").ПолучитьФорму();
ЭтотОбъект["КонсольЗапросов" + НомерСтороны] = КонсольЗапросов;
КонецЕсли;
Возврат КонсольЗапросов;
КонецФункции
Процедура ОбновитьСопоставлениеКолонок() Экспорт
КопияСопоставления1 = КолонкиТаблица1.Выгрузить();
КопияСопоставления2 = КолонкиТаблица2.Выгрузить();
КолонкиТаблица2.Очистить();
Для Каждого Колонка Из Таблица2.Колонки Цикл
СопоставлениеКолонки = КолонкиТаблица2.Добавить();
СопоставлениеКолонки.Выводить = Истина;
СопоставлениеКолонки.ИмяКолонки = Колонка.Имя;
СтараяСтрока = КопияСопоставления2.Найти(СопоставлениеКолонки.ИмяКолонки, "ИмяКолонки");
Если СтараяСтрока <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СопоставлениеКолонки, СтараяСтрока, "Выводить");
КонецЕсли;
СопоставлениеКолонки.СинонимКолонки = Колонка.Заголовок;
СопоставлениеКолонки.ОписаниеТипов = Колонка.ТипЗначения;
КонецЦикла;
КолонкиТаблица1.Очистить();
Для Каждого Колонка Из Таблица1.Колонки Цикл
СопоставлениеКолонки = КолонкиТаблица1.Добавить();
СопоставлениеКолонки.Выводить = Истина;
СопоставлениеКолонки.ИмяКолонки = Колонка.Имя;
СтараяСтрока = КопияСопоставления1.Найти(СопоставлениеКолонки.ИмяКолонки, "ИмяКолонки");
Если СтараяСтрока <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СопоставлениеКолонки, СтараяСтрока);
Колонка2 = Неопределено;
Если ЗначениеЗаполнено(СопоставлениеКолонки.ИмяКолонки2) Тогда
Колонка2 = Таблица2.Колонки.Найти(СопоставлениеКолонки.ИмяКолонки2);
КонецЕсли;
СопоставитьКолонку(СопоставлениеКолонки, Колонка2);
КонецЕсли;
СопоставлениеКолонки.СинонимКолонки = Колонка.Заголовок;
СопоставлениеКолонки.ОписаниеТипов = Колонка.ТипЗначения;
СопоставлениеКолонки.Числовая = Колонка.ТипЗначения.СодержитТип(Тип("Число"));
КонецЦикла;
ЭтотОбъект.КоличествоСтрок1 = Таблица1.Количество();
ЭтотОбъект.КоличествоСтрок2 = Таблица2.Количество();
ВыявитьНеуникальныеКлючи("1");
ВыявитьНеуникальныеКлючи("2");
КонецПроцедуры
Процедура ЗаполнитьСопоставлениеКолонок(ПоИменам = Ложь) Экспорт
Для Каждого Колонка Из Таблица2.Колонки Цикл
Если Истина
И ЗагрузкаТабличныхДанных2 <> Неопределено
И ирОбщий.СтрокиРавныЛкс(Колонка.Имя, ЗагрузкаТабличныхДанных2.мИмяКолонкиНомерСтроки)
Тогда
Продолжить;
КонецЕсли;
ПодобратьСопоставлениеКолонкиПоРавенствуСвойства("ИмяКолонки", Колонка);
ПодобратьСопоставлениеКолонкиПоРавенствуСвойства("СинонимКолонки", Колонка);
КонецЦикла;
КонецПроцедуры
Процедура ПодобратьСопоставлениеКолонкиПоРавенствуСвойства(Знач ИмяПоляРавенства, Знач Колонка)
СтруктураОтбора = Новый Структура("ИмяКолонки2", "");
СтрокиСопоставления = КолонкиТаблица1.НайтиСтроки(СтруктураОтбора);
СтрокаИмен = "";
Для Каждого СтрокаСопоставления Из СтрокиСопоставления Цикл
Если Не ирОбщий.ОписанияТиповПересекаютсяЛкс(Колонка.ТипЗначения, Таблица1.Колонки[СтрокаСопоставления.ИмяКолонки].ТипЗначения) Тогда
Продолжить;
КонецЕсли;
Если ирОбщий.СтрокиРавныЛкс(СтрокаСопоставления[ИмяПоляРавенства], Колонка.Имя) Тогда
СопоставитьКолонку(СтрокаСопоставления, Колонка);
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ПодобратьКлючевыеИСравниваемыеКолонки() Экспорт
СтрокаКлюча1 = "";
СтрокаКлюча2 = "";
Если Таблица1.Количество() > 1 И Таблица2.Количество() > 1 Тогда
Уникальность1Достигнута = Ложь;
Уникальность2Достигнута = Ложь;
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КолонкиТаблица1.Количество(), "Подбор ключа таблиц");
КолонкиТаблица1.Сортировать("Числовая");
Для Каждого СтрокаСопоставления Из КолонкиТаблица1 Цикл
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
Если СтрокаСопоставления.ИмяКолонки2 = "" Тогда
Продолжить;
КонецЕсли;
ДобавитьКолонкуВСтрокуКлюча(СтрокаСопоставления.ИмяКолонки, СтрокаКлюча1);
ДобавитьКолонкуВСтрокуКлюча(СтрокаСопоставления.ИмяКолонки2, СтрокаКлюча2);
СтрокаСопоставления.Ключевая = Истина;
СтрокаСопоставления.Выводить = Истина;
Если Не ПроверитьУникальностьКлючаТаблицы(Таблица1, СтрокаКлюча1) Тогда
Продолжить;
Иначе
Уникальность1Достигнута = Истина;
КонецЕсли;
Если Не ПроверитьУникальностьКлючаТаблицы(Таблица2, СтрокаКлюча2) Тогда
Продолжить;
Иначе
Уникальность2Достигнута = Истина;
КонецЕсли;
Прервать;
КонецЦикла;
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
Иначе
Уникальность1Достигнута = Истина;
Уникальность2Достигнута = Истина;
КонецЕсли;
Если Истина
И Не Уникальность1Достигнута
И Таблица1.Количество() > 0
И ЗначениеЗаполнено(СтрокаКлюча1)
Тогда
ирОбщий.СообщитьЛкс("В таблице 1 имеются неуникальные строки по сопоставленным колонкам (" + СтрокаКлюча1 + ")");
КонецЕсли;
Если Истина
И Не Уникальность2Достигнута
И Таблица2.Количество() > 0
И ЗначениеЗаполнено(СтрокаКлюча2)
Тогда
ирОбщий.СообщитьЛкс("В таблице 2 имеются неуникальные строки по сопоставленным колонкам (" + СтрокаКлюча2 + ")");
КонецЕсли;
Для Каждого СтрокаСопоставления Из КолонкиТаблица1 Цикл
Если СтрокаСопоставления.ИмяКолонки2 = "" Тогда
Продолжить;
КонецЕсли;
СтрокаСопоставления.Сравнивать = Не СтрокаСопоставления.Ключевая;
КонецЦикла;
ВыявитьНеуникальныеКлючи("1");
ВыявитьНеуникальныеКлючи("2");
КонецПроцедуры
Функция ПроверитьУникальностьКлючаТаблицы(Таблица, СтрокаКлюча)
КопияТаблицы = Таблица.Скопировать(, СтрокаКлюча);
КопияТаблицы.Свернуть(СтрокаКлюча);
ТолькоУникальные = КопияТаблицы.Количество() = Таблица.Количество();
Возврат ТолькоУникальные;
КонецФункции
Функция ВыявитьНеуникальныеКлючи(НомерСтороны, выхСтрокаКлючаИсточника = "") Экспорт
выхСтрокаКлючаИсточника = "";
Для Каждого СтрокаСопоставления Из КолонкиТаблица1.НайтиСтроки(Новый Структура("Ключевая", Истина)) Цикл
Если НомерСтороны = "1" Тогда
ИмяПоля = СтрокаСопоставления.ИмяКолонки;
Иначе
ИмяПоля = СтрокаСопоставления.ИмяКолонки2;
КонецЕсли;
Если выхСтрокаКлючаИсточника <> "" Тогда
выхСтрокаКлючаИсточника = выхСтрокаКлючаИсточника + ",";
КонецЕсли;
выхСтрокаКлючаИсточника = выхСтрокаКлючаИсточника + ИмяПоля;
КонецЦикла;
НеуникальныеКлючи = ирОбщий.НеуникальныеКлючиТаблицыЛкс(ЭтотОбъект["Таблица" + НомерСтороны], выхСтрокаКлючаИсточника);
ЭтотОбъект["КоличествоНеуникальныхКлючей" + НомерСтороны] = НеуникальныеКлючи.Количество();
Возврат НеуникальныеКлючи;
КонецФункции
Процедура ДобавитьКолонкуВСтрокуКлюча(Знач ИмяДобавляемойКолонки, СтрокаКлюча)
Если СтрокаКлюча <> "" Тогда
СтрокаКлюча = СтрокаКлюча + ",";
КонецЕсли;
СтрокаКлюча = СтрокаКлюча + ИмяДобавляемойКолонки;
КонецПроцедуры
Процедура СопоставитьКолонку(Знач СтрокаСопоставления, Знач Колонка = Неопределено) Экспорт
Если Колонка <> Неопределено Тогда
Для Каждого СтрокаСтарая Из КолонкиТаблица1.НайтиСтроки(Новый Структура("ИмяКолонки2", Колонка.Имя)) Цикл
Если СтрокаСтарая = СтрокаСопоставления Тогда
Продолжить;
КонецЕсли;
// Если у подходящей колонки таблицы 2 уже есть сопоставление, то делаем ничего
Возврат;
КонецЦикла;
СтрокаКолонки2 = КолонкиТаблица2.Найти(Колонка.Имя, "ИмяКолонки");
Если СтрокаКолонки2 <> Неопределено Тогда
СтрокаКолонки2.ИмяКолонки1 = СтрокаСопоставления.ИмяКолонки;
СтрокаКолонки2.СинонимКолонки1 = СтрокаСопоставления.СинонимКолонки;
КонецЕсли;
СтрокаСопоставления.ИмяКолонки2 = Колонка.Имя;
СтрокаСопоставления.СинонимКолонки2 = Колонка.Заголовок;
СтрокаСопоставления.ОписаниеТипов2 = Колонка.ТипЗначения;
Иначе
СтрокаКолонки2 = КолонкиТаблица2.Найти(СтрокаСопоставления.ИмяКолонки2, "ИмяКолонки");
Если СтрокаКолонки2 <> Неопределено Тогда
СтрокаКолонки2.ИмяКолонки1 = "";
СтрокаКолонки2.СинонимКолонки1 = "";
КонецЕсли;
СтрокаСопоставления.ИмяКолонки2 = "";
СтрокаСопоставления.СинонимКолонки2 = "";
СтрокаСопоставления.ОписаниеТипов2 = Неопределено;
СтрокаСопоставления.Ключевая = Ложь;
СтрокаСопоставления.Сравнивать = Ложь;
КонецЕсли;
КонецПроцедуры
Функция Сравнить2СтрокиПоКолонкам(Знач КолонкиСопоставления, Знач Строка1, Знач Строка2, Знач ТабличныеЧасти1, Знач ТабличныеЧасти2, Знач РазличныеКолонки)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
#Если Сервер И Не Сервер Тогда
Для Каждого СтрокаСопоставления Из КолонкиСопоставления Цикл
// п34ы46754674 Логика скопирована из СравнитьЗначенияЯчеек()
ЗначенияЯчеекРавны = Истина;
Если НеУчитыватьРегистр Тогда
// сравнение без учета регистра имеет смысл только для строк
ЛевоеЗначение = Строка1[СтрокаСопоставления.ИмяКолонки];
ПравоеЗначение = Строка2[СтрокаСопоставления.ИмяКолонки2];
Если ТипЗнч(ЛевоеЗначение) = Тип("Строка") И ТипЗнч(ПравоеЗначение) = Тип("Строка") Тогда
Если ВРег(ЛевоеЗначение) <> ВРег(ПравоеЗначение) Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
Иначе
Если ЛевоеЗначение <> ПравоеЗначение Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
КонецЕсли;
Иначе
Если Строка1[СтрокаСопоставления.ИмяКолонки] <> Строка2[СтрокаСопоставления.ИмяКолонки2] Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
КонецЕсли;
Если Не ЗначенияЯчеекРавны Тогда
РазличныеКолонки.Добавить(СтрокаСопоставления.ИмяКолонки);
КонецЕсли;
КонецЦикла;
#КонецЕсли
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого СтрокаСопоставления Из КолонкиСопоставления Цикл     ЗначенияЯчеекРавны = Истина;   Если НеУчитыватьРегистр Тогда     ЛевоеЗначение = Строка1[СтрокаСопоставления.ИмяКолонки];   ПравоеЗначение = Строка2[СтрокаСопоставления.ИмяКолонки2];   Если ТипЗнч(ЛевоеЗначение) = Тип("Строка") И ТипЗнч(ПравоеЗначение) = Тип("Строка") Тогда   Если ВРег(ЛевоеЗначение) <> ВРег(ПравоеЗначение) Тогда   ЗначенияЯчеекРавны = Ложь;   КонецЕсли;   Иначе   Если ЛевоеЗначение <> ПравоеЗначение Тогда   ЗначенияЯчеекРавны = Ложь;   КонецЕсли;   КонецЕсли;   Иначе   Если Строка1[СтрокаСопоставления.ИмяКолонки] <> Строка2[СтрокаСопоставления.ИмяКолонки2] Тогда   ЗначенияЯчеекРавны = Ложь;   КонецЕсли;   КонецЕсли;   Если Не ЗначенияЯчеекРавны Тогда   РазличныеКолонки.Добавить(СтрокаСопоставления.ИмяКолонки);   КонецЕсли;   КонецЦикла;  
Для Каждого КлючИЗначение Из ТабличныеЧасти1 Цикл
ЗначенияЯчеекРавны = Истина;
Если Не ирОбщий.СериализацииРавныЛкс(КлючИЗначение.Значение, ТабличныеЧасти2[КлючИЗначение.Ключ]) Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
Если Не ЗначенияЯчеекРавны Тогда
РазличныеКолонки.Добавить(КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
//РазличныеКолонки = Новый СписокЗначений;
//Для Каждого Колонка Из Строка1.Владелец().Колонки Цикл
// Если Строка1[Колонка.Имя] <> Строка2[Колонка.Имя] Тогда
// РазличныеКолонки.Добавить(Колонка.Имя);
// КонецЕсли;
//КонецЦикла;
//Для Каждого КлючИЗначение Из ТабличныеЧасти1 Цикл
// Если Не ирОбщий.СериализацииРавныЛкс(КлючИЗначение.Значение, ТабличныеЧасти2[КлючИЗначение.Ключ]) Тогда
// РазличныеКолонки.Добавить("#" + КлючИЗначение.Ключ);
// КонецЕсли;
//КонецЦикла;
//РазличныеКолонки.СортироватьПоЗначению();
//Для Каждого РазличнаяКолонка Из РазличныеКолонки Цикл
// Если ТекстРазличий <> "" Тогда
// ТекстРазличий = ТекстРазличий + ",";
// КонецЕсли;
// ТекстРазличий = ТекстРазличий + РазличнаяКолонка.Значение;
//КонецЦикла;
Возврат РазличныеКолонки.Количество() = 0;
КонецФункции
Функция СравнитьЗначенияЯчеек(Знач ЛевоеЗначение, Знач ПравоеЗначение) Экспорт
// п34ы46754674
ЗначенияЯчеекРавны = Истина;
// регистронезависимое сравнение
Если НеУчитыватьРегистр Тогда
// сравнение без учета регистра имеет смысл только для строк
Если ТипЗнч(ЛевоеЗначение) = Тип("Строка") И ТипЗнч(ПравоеЗначение) = Тип("Строка") Тогда
Если ВРег(ЛевоеЗначение) <> ВРег(ПравоеЗначение) Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
Иначе
Если ЛевоеЗначение <> ПравоеЗначение Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
КонецЕсли;
Иначе
// регистрозависимое сравнение
Если ЛевоеЗначение <> ПравоеЗначение Тогда
ЗначенияЯчеекРавны = Ложь;
КонецЕсли;
КонецЕсли;
Возврат ЗначенияЯчеекРавны;
КонецФункции
// Результат - Истина, если таблицы равны
Функция СравнитьТаблицы(Параметры) Экспорт
#Если Сервер И Не Сервер Тогда
Параметры = Новый Структура
#КонецЕсли
РежимСравненияСВыгрузкой = Параметры.РежимСравненияСВыгрузкой;
Если Истина
И РежимСравненияСВыгрузкой
И Параметры.Свойство("ДанныеФайлов")
Тогда
ЭтотОбъект.КаталогВыгрузки = ПолучитьИмяВременногоФайла();
СоздатьКаталог(КаталогВыгрузки);
Разделитель = ирОбщий.РазделительФайловойСистемыЛкс();
Для Каждого КлючИЗначение Из Параметры.ДанныеФайлов Цикл
КлючИЗначение.Значение.Записать(КаталогВыгрузки + Разделитель + КлючИЗначение.Ключ);
КонецЦикла;
КонецЕсли;
КлючевыеКолонки = КолонкиТаблица1.Выгрузить(Новый Структура("Ключевая", Истина));
ВыводимыеКолонки1 = КолонкиТаблица1.Выгрузить(Новый Структура("Ключевая, Выводить", Ложь, Истина)).ВыгрузитьКолонку("ИмяКолонки");
ВыводимыеКолонки2 = Новый Массив;
Для Каждого СтрокаКолонки Из КолонкиТаблица2.НайтиСтроки(Новый Структура("Выводить", Истина)) Цикл
Если КлючевыеКолонки.Найти(СтрокаКолонки.ИмяКолонки, "ИмяКолонки2") = Неопределено Тогда
ВыводимыеКолонки2.Добавить(СтрокаКолонки.ИмяКолонки);
КонецЕсли;
КонецЦикла;
КолонкиРазницыЧисел = КолонкиТаблица1.НайтиСтроки(Новый Структура("Сравнивать, Числовая", Истина, Истина));
СтрокаПорядка1 = ирОбщий.СтрСоединитьЛкс(КлючевыеКолонки.ВыгрузитьКолонку("ИмяКолонки"));
СтрокаПорядка2 = ирОбщий.СтрСоединитьЛкс(КлючевыеКолонки.ВыгрузитьКолонку("ИмяКолонки2"));
ТабличныеЧасти = Новый Структура;
ТабличныеЧастиЭталона = Новый Структура;
ТабличныеЧастиСтроки = Новый Структура;
ТабличныеЧастиСтрокиЭталона = Новый Структура;
Если РежимСравненияСВыгрузкой Тогда
СчитанаПоследняяПорция = Ложь;
СчитанаПоследняяПорцияЭталона = Ложь;
МетаданныеВыгрузкиЛ = ПрочитатьМетаданныеВыгрузки();
СтруктураТаблицы = Новый Структура;
Запрос = ПодготовитьЗапросСравненияВыгрузки(СтруктураТаблицы);
КоличествоПорцийЭталона = МетаданныеВыгрузкиЛ.КоличествоПорций;
ОсталосьПорцийЭталона = КоличествоПорцийЭталона;
РезультатЗапроса = ВыполнитьЗапросСИндикатором(Запрос);
Если СтруктураТаблицы.ТабличныеЧасти.Количество() > 0 Тогда
РазмерПорции = 1000;
Иначе
РазмерПорции = 100000;
КонецЕсли;
//РазмерПорции = 10; // Для отладки
НомерПорции = 0;
Выборка = РезультатЗапроса.Выбрать();
ТабличныеЧасти = СкопироватьТабличныеЧасти(СтруктураТаблицы.ТабличныеЧасти);
КолонкиВложенныхТаблиц = Неопределено;
ВременныйКаталог = ПолучитьИмяВременногоФайла();
ПорцияОсновнойТаблицы = СоздатьТаблицуПорции(РезультатЗапроса);
#Если _ Тогда
ПорцияОсновнойТаблицы = Новый ТаблицаЗначений;
ТабличныеЧасти = Новый Структура;
#КонецЕсли
ПорцияОсновнойТаблицыЭталона = Новый ТаблицаЗначений;
КоличествоСтрок = Выборка.Количество();
КоличествоСтрокЭталона = МетаданныеВыгрузкиЛ.КоличествоСтрок;
Иначе
СчитанаПоследняяПорция = Истина;
СчитанаПоследняяПорцияЭталона = Истина;
ПорцияОсновнойТаблицыЭталона = Таблица1;
Если ЗначениеЗаполнено(СтрокаПорядка1) Тогда
ПорцияОсновнойТаблицыЭталона.Сортировать(СтрокаПорядка1, Новый СравнениеЗначений);
КонецЕсли;
ПорцияОсновнойТаблицы = Таблица2;
Если ЗначениеЗаполнено(СтрокаПорядка2) Тогда
ПорцияОсновнойТаблицы.Сортировать(СтрокаПорядка2, Новый СравнениеЗначений);
КонецЕсли;
КоличествоСтрок = ПорцияОсновнойТаблицы.Количество();
КоличествоСтрокЭталона = ПорцияОсновнойТаблицыЭталона.Количество();
КонецЕсли;
ЕстьТЧ = ТабличныеЧасти.Количество() > 0;
СоздатьКолонкиРезультата();
КолонкиСопоставления = КолонкиТаблица1.НайтиСтроки(Новый Структура("Сравнивать, Ключевая", Истина, Ложь));
ВсегоРазличий = 0;
ИндексСтроки = 0;
ИндексСтрокиЭталона = 0;
ВзятьСледующуюСтроку = Истина;
ВзятьСледующуюСтрокуЭталона = Истина;
СчитанаПоследняяПорция = Истина;
СчетчикИзменных = 0;
СчетчикДобавленных = 0;
СчетчикУдаленных = 0;
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КоличествоСтрок + КоличествоСтрокЭталона, "Сравнение");
Пока Истина Цикл
Если Ложь
Или ИндексСтроки % 100 = 0
Или ИндексСтрокиЭталона % 100 = 0
Тогда
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
КонецЕсли;
Если ВзятьСледующуюСтроку Тогда
Если Не РежимСравненияСВыгрузкой Или ЕстьТЧ Тогда
Если ИндексСтроки >= ПорцияОсновнойТаблицы.Количество() Тогда
Если Не СчитанаПоследняяПорция Тогда
ПорцияОсновнойТаблицы.Очистить();
Для Каждого КлючИЗначение Из ТабличныеЧасти Цикл
КлючИЗначение.Значение.Очистить();
КонецЦикла;
СчитанаПоследняяПорция = СчитатьПорциюВыборкиВТаблицу(Выборка, ПорцияОсновнойТаблицы, РазмерПорции, ТабличныеЧасти);
ПодготовитьПорциюТабличныхЧастейКСравнению(ТабличныеЧасти);
ИндексСтроки = 0;
КонецЕсли;
КонецЕсли;
Если ИндексСтроки < ПорцияОсновнойТаблицы.Количество() Тогда
ТекущаяСтрока = ПорцияОсновнойТаблицы[ИндексСтроки];
Иначе
ТекущаяСтрока = Неопределено;
КонецЕсли;
Иначе
Если Выборка.Следующий() Тогда
ТекущаяСтрока = Выборка;
Иначе
ТекущаяСтрока = Неопределено;
КонецЕсли;
КонецЕсли;
ВзятьСледующуюСтроку = Ложь;
ИндексСтроки = ИндексСтроки + 1;
КонецЕсли;
Если ВзятьСледующуюСтрокуЭталона Тогда
Если ИндексСтрокиЭталона >= ПорцияОсновнойТаблицыЭталона.Количество() Тогда
Если Не СчитанаПоследняяПорцияЭталона Тогда
НомерПорции = НомерПорции + 1;
ИмяФайлаПорции = ИмяФайлаПорции(КаталогСравнения, НомерПорции);
Архив = Новый ЧтениеZipФайла(ИмяФайлаПорции);
ИмяФайлаДанныхXML = ВременныйКаталог + "\" + Архив.Элементы.Получить(0).Имя;
Архив.ИзвлечьВсе(ВременныйКаталог);
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаДанныхXML);
ЧтениеXML.Прочитать();
ЧтениеXML.Прочитать();
ирОбщий.СостояниеЛкс("Десериализация порции");
СтруктураДанных = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
ирОбщий.СостояниеЛкс("");
ПорцияОсновнойТаблицыЭталона = СтруктураДанных.ОсновнаяТаблица;
ТабличныеЧастиЭталона = СтруктураДанных.ТабличныеЧасти;
ЧтениеXML.Закрыть();
ЧтениеXML.Закрыть();
УдалитьФайлы(ВременныйКаталог);
ПодготовитьПорциюТабличныхЧастейКСравнению(ТабличныеЧастиЭталона);
#Если _ Тогда
ПорцияОсновнойТаблицыЭталона = Новый ТаблицаЗначений;
#КонецЕсли
ИндексСтрокиЭталона = 0;
ОсталосьПорцийЭталона = ОсталосьПорцийЭталона - 1;
СчитанаПоследняяПорцияЭталона = ОсталосьПорцийЭталона = 0;
КонецЕсли;
КонецЕсли;
Если ИндексСтрокиЭталона < ПорцияОсновнойТаблицыЭталона.Количество() Тогда
ТекущаяСтрокаЭталона = ПорцияОсновнойТаблицыЭталона[ИндексСтрокиЭталона];
Иначе
ТекущаяСтрокаЭталона = Неопределено;
КонецЕсли;
ВзятьСледующуюСтрокуЭталона = Ложь;
ИндексСтрокиЭталона = ИндексСтрокиЭталона + 1;
КонецЕсли;
Если Истина
И СчитанаПоследняяПорция
И ТекущаяСтрока = Неопределено
И СчитанаПоследняяПорцияЭталона
И ТекущаяСтрокаЭталона = Неопределено
Тогда
Прервать;
КонецЕсли;
СтрокаРезультата = Неопределено;
РезультатСравненияКлючейСтрок = СравнитьКлючиСтрокТаблиц(ТекущаяСтрокаЭталона, ТекущаяСтрока, КлючевыеКолонки);
Индикатор.Счетчик = Индикатор.Счетчик + 1;
Если РезультатСравненияКлючейСтрок = ВидСравнения.Равно Тогда
Если ЕстьТЧ Тогда
ТабличныеЧастиСтроки = Новый Структура;
Для Каждого КлючИЗначение Из ТабличныеЧасти Цикл
ТабличныеЧастиСтроки.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение.Скопировать(Новый Структура("Ссылка", ТекущаяСтрока.Ссылка)));
КонецЦикла;
ТабличныеЧастиСтрокиЭталона = Новый Структура;
Для Каждого КлючИЗначение Из ТабличныеЧастиЭталона Цикл
ТабличныеЧастиСтрокиЭталона.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение.Скопировать(Новый Структура("Ссылка", ТекущаяСтрокаЭталона.Ссылка)));
КонецЦикла;
КонецЕсли;
РазличныеКолонки = Новый Массив;
Если Сравнить2СтрокиПоКолонкам(КолонкиСопоставления, ТекущаяСтрокаЭталона, ТекущаяСтрока, ТабличныеЧастиСтрокиЭталона, ТабличныеЧастиСтроки, РазличныеКолонки) Тогда
Признак = ПризнакРавно;
Иначе
Признак = ПризнакНеРавно;
СчетчикИзменных = СчетчикИзменных + 1;
КонецЕсли;
Если Признак <> ПризнакРавно Или Не НеВыводитьОдинаковыеСтроки Тогда
ВывестиСтрокуРезультата(СтрокаРезультата, ТекущаяСтрокаЭталона, "1", ВыводимыеКолонки1);
ВывестиСтрокуРезультата(СтрокаРезультата, ТекущаяСтрока, "2", ВыводимыеКолонки2, КлючевыеКолонки);
Если ВыводитьРазницуЧисловыхКолонокСравнения Тогда
ВывестиРазницуЧисел(СтрокаРезультата, Признак, КолонкиРазницыЧисел);
КонецЕсли;
Для Каждого РазличнаяКолонка Из РазличныеКолонки Цикл
СтрокаРезультата[РазличнаяКолонка + "Различно"] = Истина;
КонецЦикла;
КонецЕсли;
ВзятьСледующуюСтроку = Истина;
ВзятьСледующуюСтрокуЭталона = Истина;
Индикатор.Счетчик = Индикатор.Счетчик + 1;
ИначеЕсли РезультатСравненияКлючейСтрок = ВидСравнения.Меньше Тогда
СчетчикДобавленных = СчетчикДобавленных + 1;
ВзятьСледующуюСтрокуЭталона = Истина;
Признак = ПризнакТолько1;
ВывестиСтрокуРезультата(СтрокаРезультата, ТекущаяСтрокаЭталона, "1", ВыводимыеКолонки1, КлючевыеКолонки);
ИначеЕсли РезультатСравненияКлючейСтрок = ВидСравнения.Больше Тогда
СчетчикУдаленных = СчетчикУдаленных + 1;
ВзятьСледующуюСтроку = Истина;
Признак = ПризнакТолько2;
ВывестиСтрокуРезультата(СтрокаРезультата, ТекущаяСтрока, "2", ВыводимыеКолонки2, КлючевыеКолонки);
КонецЕсли;
Если СтрокаРезультата <> Неопределено Тогда
СтрокаРезультата[мИмяКолонкиРезультатаСравнения] = Признак;
Если Признак <> ПризнакРавно Тогда
ВсегоРазличий = ВсегоРазличий + 1;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
Если Истина
И РежимСравненияСВыгрузкой
И Параметры.Свойство("ДанныеФайлов")
Тогда
УдалитьФайлы(КаталогВыгрузки);
КонецЕсли;
Результат = Новый Структура(мИменаВозвращаемыхСвойств);
ЗаполнитьЗначенияСвойств(Результат, ЭтотОбъект, мИменаВозвращаемыхСвойств);
Результат.Вставить("ЛиТаблицыРавны", ВсегоРазличий = 0);
Возврат Результат;
КонецФункции
Процедура СоздатьКолонкиРезультата(ТабличноеПолеРезультата = Неопределено) Экспорт
ЭтотОбъект.СравниваемыеКолонкиРезультата = Новый Массив;
ЭтотОбъект.СтруктураКолонокРезультата = Новый Структура;
ЭтотОбъект.РезультатСравнения = Новый ТаблицаЗначений;
РезультатСравнения.Колонки.Добавить(мИмяКолонкиРезультатаСравнения, Новый ОписаниеТипов("Число"), "Результат сравнения");
РезультатСравнения.Колонки.Добавить(мИмяКолонкиНомераСтрокиРезультата, Новый ОписаниеТипов("Число"));
КолонкиГруппы = КолонкиТаблица1.НайтиСтроки(Новый Структура("Ключевая", Истина));
ДобавитьКолонкиТаблицыГруппыРезультата(КолонкиГруппы, "1");
Если ТабличноеПолеРезультата <> Неопределено Тогда
ТабличноеПолеРезультата.Колонки.Очистить();
КолонкаТабличногоПоля = ТабличноеПолеРезультата.Колонки.Добавить(мИмяКолонкиРезультатаСравнения);
КолонкаТабличногоПоля.Данные = мИмяКолонкиРезультатаСравнения;
КолонкаТабличногоПоля.ТекстШапки = "Результат сравнения";
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыКлючевыхКолонок, "Ключевые колонки", , "1", "1", ТабличноеПолеРезультата);
КонецЕсли;
СоздатьКолонкиСтороныРезультата("1", ТабличноеПолеРезультата);
СоздатьКолонкиСтороныРезультата("2", ТабличноеПолеРезультата);
СоздатьКолонкиРазличий(Новый Структура("Сравнивать", Истина), "Различно", ТабличноеПолеРезультата);
Если ВыводитьРазницуЧисловыхКолонокСравнения Тогда
СоздатьКолонкиРазличий(Новый Структура("Числовая, Сравнивать", Истина, Истина), "Разность", ТабличноеПолеРезультата);
КонецЕсли;
Если ТабличноеПолеРезультата <> Неопределено Тогда
//ЭтотОбъект.РезультатСравненияОтобранное = РезультатСравнения;
ирОбщий.НастроитьДобавленныеКолонкиТабличногоПоляЛкс(ТабличноеПолеРезультата, РезультатСравнения.Колонки,,, Истина);
КонецЕсли;
КонецПроцедуры
Процедура СоздатьКолонкиРазличий(Знач ОтборКолонок, Знач СуффиксКолонки, Знач ТабличноеПолеРезультата)
КолонкиГруппы = КолонкиТаблица1.НайтиСтроки(ОтборКолонок);
Для Каждого КолонкаГруппы Из КолонкиГруппы Цикл
КолонкаИсходнойТаблицы = Таблица1.Колонки[КолонкаГруппы.ИмяКолонки];
ДобавитьКолонкуТаблицыРезультата(КолонкаГруппы.ИмяКолонки, КолонкаГруппы.ИмяКолонки, КолонкаИсходнойТаблицы, СуффиксКолонки);
КонецЦикла;
Если ТабличноеПолеРезультата <> Неопределено Тогда
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыРазностныхКолонок, "Различие колонок", , СуффиксКолонки, "1", ТабличноеПолеРезультата);
КонецЕсли;
КонецПроцедуры
Функция СравнитьКлючиСтрокТаблиц(Строка1, Строка2, КлючевыеКолонки)
Если Истина
И Строка1 = Неопределено
И Строка2 = Неопределено
Тогда
Возврат Неопределено;
ИначеЕсли Истина
И Строка1 = Неопределено
И Строка2 <> Неопределено
Тогда
Возврат ВидСравнения.Больше;
ИначеЕсли Истина
И Строка2 = Неопределено
И Строка1 <> Неопределено
Тогда
Возврат ВидСравнения.Меньше;
КонецЕсли;
СравнениеЗначений = Новый СравнениеЗначений();
//Если КлючевыеКолонки.Количество() > 0 Тогда
Результат = ВидСравнения.Равно;
//Иначе
// Результат = ВидСравнения.Больше;
//КонецЕсли;
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
#Если Сервер И Не Сервер Тогда
Для Каждого СтрокаСравнения Из КлючевыеКолонки Цикл
РезультатЯчейки = СравнениеЗначений.Сравнить(Строка1[СтрокаСравнения.ИмяКолонки], Строка2[СтрокаСравнения.ИмяКолонки2]);
Если РезультатЯчейки = 0 Тогда
//
ИначеЕсли РезультатЯчейки > 0 Тогда
Возврат ВидСравнения.Больше;
Иначе // РезультатЯчейки < 0 Тогда
Возврат ВидСравнения.Меньше;
КонецЕсли;
КонецЦикла;
#КонецЕсли
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого СтрокаСравнения Из КлючевыеКолонки Цикл   РезультатЯчейки = СравнениеЗначений.Сравнить(Строка1[СтрокаСравнения.ИмяКолонки], Строка2[СтрокаСравнения.ИмяКолонки2]);   Если РезультатЯчейки = 0 Тогда     ИначеЕсли РезультатЯчейки > 0 Тогда   Возврат ВидСравнения.Больше;   Иначе   Возврат ВидСравнения.Меньше;   КонецЕсли;   КонецЦикла;  
Возврат Результат;
КонецФункции
Процедура СоздатьКолонкиСтороныРезультата(Знач НомерСтороны, Знач ТабличноеПолеРезультата = Неопределено)
// Используем имена сопоставленных колонок от первой стороны
СопоставленныеНеключевые = КолонкиТаблица1.Выгрузить(Новый Структура("Ключевая, Выводить", Ложь, Истина));
// Отбросим несопоставленные, т.к. их отдельно выводим
Отбрасываемые = СопоставленныеНеключевые.НайтиСтроки(Новый Структура("ИмяКолонки2", ""));
Для Каждого Отбрасываемая Из Отбрасываемые Цикл
СопоставленныеНеключевые.Удалить(Отбрасываемая);
КонецЦикла;
Если НомерСтороны = "1" Тогда
ИмяКолонкиСопоставления = "ИмяКолонки";
Иначе
ИмяКолонкиСопоставления = "ИмяКолонки2";
КонецЕсли;
ДобавитьКолонкиТаблицыГруппыРезультата(СопоставленныеНеключевые, НомерСтороны, ИмяКолонкиСопоставления);
КолонкиГруппы = СопоставленныеНеключевые.НайтиСтроки(Новый Структура("Ключевая, Сравнивать", Ложь, Истина));
Если ТабличноеПолеРезультата <> Неопределено Тогда
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыСравниваемыхКолонок, "Сравниваемые колонки", НомерСтороны, НомерСтороны, НомерСтороны,
ТабличноеПолеРезультата, ИмяКолонкиСопоставления);
КонецЕсли;
Если НомерСтороны = "1" Тогда
Для Каждого КолонкаГруппы Из КолонкиГруппы Цикл
СравниваемыеКолонкиРезультата.Добавить(КолонкаГруппы.ИмяКолонки);
КонецЦикла;
КонецЕсли;
КолонкиГруппы = СопоставленныеНеключевые.НайтиСтроки(Новый Структура("Выводить, Ключевая, Сравнивать", Истина, Ложь, Ложь));
Если ТабличноеПолеРезультата <> Неопределено Тогда
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыНесравниваемыхКолонок, "Несравниваемые колонки", НомерСтороны, НомерСтороны, НомерСтороны,
ТабличноеПолеРезультата, ИмяКолонкиСопоставления);
КонецЕсли;
// Используем имена несопоставленных колонок от своей стороны
Если НомерСтороны = "1" Тогда
КолонкиГруппы = КолонкиТаблица1.НайтиСтроки(Новый Структура("Выводить, ИмяКолонки2", Истина, ""));
ДобавитьКолонкиТаблицыГруппыРезультата(КолонкиГруппы, НомерСтороны);
Если ТабличноеПолеРезультата <> Неопределено Тогда
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыНесравниваемыхКолонок, "Несопоставленные колонки", НомерСтороны, НомерСтороны, НомерСтороны,
ТабличноеПолеРезультата,, Ложь);
КонецЕсли;
КонецЕсли;
Если НомерСтороны = "2" Тогда
КолонкиГруппы = КолонкиТаблица2.НайтиСтроки(Новый Структура("Выводить, ИмяКолонки1", Истина, ""));
ДобавитьКолонкиТаблицыГруппыРезультата(КолонкиГруппы, НомерСтороны);
Если ТабличноеПолеРезультата <> Неопределено Тогда
ДобавитьКолонкиТабличногоПоляГруппыРезультата(КолонкиГруппы, мИмяГруппыНесравниваемыхКолонок, "Несопоставленные колонки", НомерСтороны, НомерСтороны, НомерСтороны,
ТабличноеПолеРезультата,, Ложь);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ДобавитьКолонкиТаблицыГруппыРезультата(Знач КолонкиГруппы, Знач НомерСтороны, ИмяКолонкиСопоставления = "ИмяКолонки")
Массив = Новый Массив;
Для Каждого КолонкаГруппы Из КолонкиГруппы Цикл
ИмяКолонки = КолонкаГруппы[ИмяКолонкиСопоставления];
КолонкаИсходнойТаблицы = ЭтотОбъект["Таблица" + НомерСтороны].Колонки[ИмяКолонки];
ИмяКолонкиРезультата = ДобавитьКолонкуТаблицыРезультата(ИмяКолонки, КолонкаГруппы.ИмяКолонки, КолонкаИсходнойТаблицы, НомерСтороны);
Массив.Добавить(ИмяКолонкиРезультата);
КонецЦикла;
Результат = ирОбщий.СтрСоединитьЛкс(Массив);
Возврат Результат;
КонецФункции
Функция ДобавитьКолонкуТаблицыРезультата(Знач ИмяКолонкиТаблицыРезультата, Знач ИмяИсходнойКолонки, Знач КолонкаИсходнойТаблицы, Суффикс)
ИмяКолонкиРезультата = ИмяКолонкиТаблицыРезультата + Суффикс;
Если Суффикс = "Различно" Тогда
ОписаниеТиповКолонки = Новый ОписаниеТипов("Булево");
Иначе
КвалификаторыЧисла = КолонкаИсходнойТаблицы.ТипЗначения.КвалификаторыЧисла;
#Если Сервер И Не Сервер Тогда
КвалификаторыЧисла = Новый КвалификаторыЧисла;
#КонецЕсли
ОписаниеТиповКолонки = Новый ОписаниеТипов(КолонкаИсходнойТаблицы.ТипЗначения,,,
Новый КвалификаторыЧисла(КвалификаторыЧисла.Разрядность, КвалификаторыЧисла.РазрядностьДробнойЧасти, ДопустимыйЗнак.Любой));
КонецЕсли;
РезультатСравнения.Колонки.Добавить(ИмяКолонкиРезультата, ОписаниеТиповКолонки, КолонкаИсходнойТаблицы.Заголовок + " " + Суффикс, КолонкаИсходнойТаблицы.Ширина);
СтруктураКолонокРезультата.Вставить(ИмяКолонкиРезультата, ИмяИсходнойКолонки);
Возврат ИмяКолонкиРезультата;
КонецФункции
Процедура ДобавитьКолонкиТабличногоПоляГруппыРезультата(Знач КолонкиГруппы, Знач ИмяГруппы, Знач ЗаголовокГруппы, Знач НомерСтороныГруппы = "", СуффиксКолонки = "",
Знач НомерСтороныКолонки = "", Знач ТабличноеПолеРезультата, ИмяКолонкиСопоставления = "ИмяКолонки", Сопоставленные = Истина)
#Если Клиент Тогда
Если КолонкиГруппы.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ЭтоПерваяКолонка = Ложь;
Если Не РасполагатьСравниваемыеЯчейкиВертикально Тогда
ИмяКолонкиГруппы = ИмяГруппы + НомерСтороныГруппы;
КолонкаТабличногоПоля = ТабличноеПолеРезультата.Колонки.Найти(ИмяКолонкиГруппы);
Если КолонкаТабличногоПоля = Неопределено Тогда
КолонкаТабличногоПоля = ТабличноеПолеРезультата.Колонки.Добавить(ИмяКолонкиГруппы);
Если ЗначениеЗаполнено(НомерСтороныГруппы) Тогда
ЗаголовокГруппы = ЗаголовокГруппы + " " + НомерСтороныГруппы;
КонецЕсли;
КолонкаТабличногоПоля.ТекстШапки = ЗаголовокГруппы;
ЭтоПерваяКолонка = Истина;
КонецЕсли;
КонецЕсли;
СуффиксКолонкиВнутр = СуффиксКолонки;
Для Каждого КолонкаГруппы Из КолонкиГруппы Цикл
ИмяКолонкиТаблицыРезультата = КолонкаГруппы[ИмяКолонкиСопоставления] + СуффиксКолонкиВнутр;
КолонкаТабличногоПоля = ТабличноеПолеРезультата.Колонки.Добавить(ИмяКолонкиТаблицыРезультата);
КолонкаТабличногоПоля.Данные = ИмяКолонкиТаблицыРезультата;
КолонкаТабличногоПоля.ТекстШапки = ЭтотОбъект["КолонкиТаблица" + НомерСтороныКолонки].Найти(КолонкаГруппы[ИмяКолонкиСопоставления], "ИмяКолонки").СинонимКолонки;
КолонкаТабличногоПоля.ПодсказкаВШапке = КолонкаТабличногоПоля.ТекстШапки + " " + СуффиксКолонки;
Если РасполагатьСравниваемыеЯчейкиВертикально Тогда
Если Ложь
Или Не Сопоставленные
Или СуффиксКолонки = "1"
Тогда
КолонкаТабличногоПоля.Положение = ПоложениеКолонки.НоваяКолонка;
КолонкаТабличногоПоля.ТекстШапки = КолонкаТабличногоПоля.ТекстШапки + " " + СуффиксКолонки;
КолонкаТабличногоПоля.ПодсказкаВШапке = ""; // Совпадает с заголовком
ИначеЕсли Ложь
Или СуффиксКолонки = "2"
Или СуффиксКолонки = "Различно"
Или СуффиксКолонки = "Разность"
Тогда
Если СуффиксКолонки = "Различно" Тогда
ИмяПривязкиПоложения = "ИмяКолонки2";
Иначе
ИмяПривязкиПоложения = "ИмяКолонки";
КонецЕсли;
Если СуффиксКолонки = "2" Тогда
СуффиксПарнойКолонки = "1";
ИначеЕсли СуффиксКолонки = "Разность" Тогда
СуффиксПарнойКолонки = "Различно";
Иначе
СуффиксПарнойКолонки = "2";
КонецЕсли;
КолонкаТабличногоПоля.ТекстШапки = СуффиксКолонки;
УстановитьПоложениеКолонкиТП(КолонкаГруппы, КолонкаТабличногоПоля, СуффиксКолонки, СуффиксПарнойКолонки, ТабличноеПолеРезультата, ИмяПривязкиПоложения);
КонецЕсли;
Иначе
Если СуффиксКолонки = "Разность" Тогда
КолонкаТабличногоПоля.ТекстШапки = "<" + СуффиксКолонки + ">";
УстановитьПоложениеКолонкиТП(КолонкаГруппы, КолонкаТабличногоПоля, СуффиксКолонки, "Различно", ТабличноеПолеРезультата);
КонецЕсли;
Если ЭтоПерваяКолонка Тогда
КолонкаТабличногоПоля.Положение = ПоложениеКолонки.НаСледующейСтроке;
ЭтоПерваяКолонка = Ложь;
Иначе
КолонкаТабличногоПоля.Положение = ПоложениеКолонки.ВТойЖеКолонке;
КонецЕсли;
КонецЕсли;
КонецЦикла;
#КонецЕсли
КонецПроцедуры
#Если Клиент Тогда
Процедура УстановитьПоложениеКолонкиТП(Знач КолонкаГруппы, КолонкаТабличногоПоля, Знач СуффиксКолонки, Знач СуффиксПарнойКолонки, Знач ТабличноеПолеРезультата, Знач ИмяПривязкиПоложения = "ИмяКолонки")
ПарнаяКолонка = ТабличноеПолеРезультата.Колонки.Найти(КолонкаГруппы[ИмяПривязкиПоложения] + СуффиксПарнойКолонки);
Если ПарнаяКолонка <> Неопределено Тогда
ИндексПарнойКолонки = ТабличноеПолеРезультата.Колонки.Индекс(КолонкаТабличногоПоля);
ТабличноеПолеРезультата.Колонки.Сдвинуть(КолонкаТабличногоПоля, ТабличноеПолеРезультата.Колонки.Индекс(ПарнаяКолонка) - ИндексПарнойКолонки + 1);
Если СуффиксКолонки = "Разность" Тогда
КолонкаТабличногоПоля.Положение = ПоложениеКолонки.ВТойЖеКолонке;
Иначе
КолонкаТабличногоПоля.Положение = ПоложениеКолонки.НаСледующейСтроке;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
#КонецЕсли
Процедура ВывестиСтрокуРезультата(выхСтрокаРезультата, Знач СтрокаТаблицы, Знач НомерСтороны, Знач ВыводимыеКолонки, Знач КлючевыеКолонки = Неопределено)
#Если Сервер И Не Сервер Тогда
СтрокаТаблицы = Новый ТаблицаЗначений;
СтрокаТаблицы = СтрокаТаблицы.Добавить();
#КонецЕсли
Если выхСтрокаРезультата = Неопределено Тогда
выхСтрокаРезультата = РезультатСравнения.Добавить();
выхСтрокаРезультата[мИмяКолонкиНомераСтрокиРезультата] = РезультатСравнения.Количество();
КонецЕсли;
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
#Если Сервер И Не Сервер Тогда
Если КлючевыеКолонки <> Неопределено Тогда
Если НомерСтороны = "1" Тогда
Для Каждого КлючеваяКолонка Из КлючевыеКолонки Цикл
выхСтрокаРезультата[КлючеваяКолонка.ИмяКолонки + "1"] = СтрокаТаблицы[КлючеваяКолонка.ИмяКолонки];
КонецЦикла;
Иначе
Для Каждого КлючеваяКолонка Из КлючевыеКолонки Цикл
выхСтрокаРезультата[КлючеваяКолонка.ИмяКолонки + "1"] = СтрокаТаблицы[КлючеваяКолонка.ИмяКолонки2];
КонецЦикла;
КонецЕсли;
КонецЕсли;
Для Каждого ИмяКолонки Из ВыводимыеКолонки Цикл
выхСтрокаРезультата[ИмяКолонки + НомерСтороны] = СтрокаТаблицы[ИмяКолонки];
КонецЦикла;
#КонецЕсли
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если КлючевыеКолонки <> Неопределено Тогда   Если НомерСтороны = "1" Тогда   Для Каждого КлючеваяКолонка Из КлючевыеКолонки Цикл   выхСтрокаРезультата[КлючеваяКолонка.ИмяКолонки + "1"] = СтрокаТаблицы[КлючеваяКолонка.ИмяКолонки];   КонецЦикла;   Иначе   Для Каждого КлючеваяКолонка Из КлючевыеКолонки Цикл   выхСтрокаРезультата[КлючеваяКолонка.ИмяКолонки + "1"] = СтрокаТаблицы[КлючеваяКолонка.ИмяКолонки2];   КонецЦикла;   КонецЕсли;   КонецЕсли;   Для Каждого ИмяКолонки Из ВыводимыеКолонки Цикл   выхСтрокаРезультата[ИмяКолонки + НомерСтороны] = СтрокаТаблицы[ИмяКолонки];   КонецЦикла;  
КонецПроцедуры
Процедура ЗаписатьСоотвествиеПространствИмен(Знач ЗаписьXML) Экспорт
#Если Сервер И Не Сервер Тогда
ЗаписьXML = Новый ЗаписьXML;
#КонецЕсли
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xs", "http://www.w3.org/2001/XMLSchema");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xi", "http://www.w3.org/2001/XMLSchema-instance");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("v8", "http://v8.1c.ru/data");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("cc", "http://v8.1c.ru/8.1/data/enterprise/current-config");
КонецПроцедуры
// Если в описании типов есть более одного ссылочного типа, то они заменяются на ЛюбаяСсылка
Функция КомпактноеОписаниеТиповДляСериализации(ОписаниеТипов) Экспорт
Результат = ОписаниеТипов;
Типы = Результат.Типы();
Если Типы.Количество() > 1 Тогда
ПримитивныеТипы = Новый Массив;
Для Каждого Тип Из Типы Цикл
Если Найти(XMLТип(Тип).ИмяТипа, "Ref.") > 0 Тогда
Продолжить;
КонецЕсли;
ПримитивныеТипы.Добавить(Тип);
КонецЦикла;
ВычитаемыеТипы = Новый Массив;
//Если УдалятьТипNull Тогда // Удаление типа Null из описания типов колонки уменьшает объем ее xml данных, если в ней остается только один тип. Не рекомендуется включать для данных, полученных из регистра бухгалтерии.
// ВычитаемыеТипы.Добавить(Тип("Null"));
//КонецЕсли;
Если Типы.Количество() > ПримитивныеТипы.Количество() + 1 Тогда
БазовоеОписаниеТипов = ирОбщий.ОписаниеТиповВсеСсылкиЛкс(Ложь);
Иначе
БазовоеОписаниеТипов = Результат;
КонецЕсли;
Результат = Новый ОписаниеТипов(БазовоеОписаниеТипов, ПримитивныеТипы, ВычитаемыеТипы, Результат.КвалификаторыЧисла, Результат.КвалификаторыСтроки,
Результат.КвалификаторыДаты);
КонецЕсли;
Возврат Результат;
КонецФункции
// Результат - Булево - Считана последняя порция
Функция СчитатьПорциюВыборкиВТаблицу(Выборка, ТаблицаПриемник, Знач РазмерПорции = 9999, ОбщиеВложенныеТаблицы = Неопределено) Экспорт
#Если _ Тогда
Пустышка = Новый Запрос;
Выборка = Пустышка.Выполнить();
ТаблицаПриемник = Новый ТаблицаЗначений;
#КонецЕсли
КолонкиВложенныхТаблиц = Новый Массив();
Для Каждого Колонка Из Выборка.Владелец().Колонки Цикл
Если Колонка.ТипЗначения.СодержитТип(Тип("РезультатЗапроса")) Тогда
КолонкиВложенныхТаблиц.Добавить(Колонка.Имя);
КонецЕсли;
КонецЦикла;
ЕстьКолонкиВложенныхТаблиц = КолонкиВложенныхТаблиц.Количество() > 0;
РазмерПорцииОсталось = РазмерПорции;
РедкостьИндикатора = 100;
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(РазмерПорции / РедкостьИндикатора, "Чтение порции");
Результат = Истина;
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТаблицаПриемник.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
Если ЕстьКолонкиВложенныхТаблиц Тогда
Для Каждого ИмяКолонкиВложеннойТаблицы Из КолонкиВложенныхТаблиц Цикл
Если ОбщиеВложенныеТаблицы = Неопределено Тогда
НоваяСтрока[ИмяКолонкиВложеннойТаблицы] = Выборка[ИмяКолонкиВложеннойТаблицы].Выгрузить();
Иначе
ТабличнаяЧастьИсточник = Выборка[ИмяКолонкиВложеннойТаблицы].Выгрузить();
ТабличнаяЧастьПриемник = ОбщиеВложенныеТаблицы[ИмяКолонкиВложеннойТаблицы];
Если ТабличнаяЧастьПриемник = Неопределено Или ТабличнаяЧастьПриемник.Колонки.Количество() = 0 Тогда
ТабличнаяЧастьПриемник = ТабличнаяЧастьИсточник;
Иначе
ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ТабличнаяЧастьИсточник, ТабличнаяЧастьПриемник, Новый Структура("Ссылка", Выборка.Ссылка));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
РазмерПорцииОсталось = РазмерПорцииОсталось - 1;
Если РазмерПорцииОсталось <= 0 Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
Если РазмерПорцииОсталось % РедкостьИндикатора = 0 Тогда
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
КонецЕсли;
КонецЦикла;
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
Возврат Результат;
КонецФункции
Функция ВыгрузитьДанныеДляСравнения(Параметры = Неопределено) Экспорт
#Если Не Клиент Тогда
ЭтотОбъект.КаталогВыгрузки = ПолучитьИмяВременногоФайла();
СоздатьКаталог(КаталогВыгрузки);
#КонецЕсли
УдалитьФайлы(КаталогВыгрузки, МаркерИмениФайлаПорции() + "*.*");
СтруктураТаблицы = Новый Структура;
ЗапросДетальный = ПодготовитьЗапросСравненияВыгрузки(СтруктураТаблицы);
РезультатЗапроса = ВыполнитьЗапросСИндикатором(ЗапросДетальный);
ТабличныеЧасти = СтруктураТаблицы.ТабличныеЧасти;
ПорцияОсновнойТаблицы = СоздатьТаблицуПорции(РезультатЗапроса);
Если ТабличныеЧасти.Количество() > 0 Тогда
РазмерПорции = 1000;
Иначе
РазмерПорции = 100000;
КонецЕсли;
//РазмерПорции = 10; // Для отладки
Выборка = РезультатЗапроса.Выбрать();
КоличествоСтрок = Выборка.Количество();
КоличествоПорций = Цел(КоличествоСтрок / РазмерПорции) + 1;
ИмяФайлаМетаданных = ИмяФайлаМетаданныхСравнения();
МетаданныеВыгрузки = Новый Структура;
МетаданныеВыгрузки.Вставить("КолонкиТаблица1", КолонкиТаблица1.Выгрузить());
МетаданныеВыгрузки.Вставить("Таблица1", Таблица1.СкопироватьКолонки());
МетаданныеВыгрузки.Вставить("ЗапросВыгрузки", ЗапросВыгрузки);
МетаданныеВыгрузки.Вставить("КоличествоСтрок", КоличествоСтрок);
МетаданныеВыгрузки.Вставить("РазмерПорции", РазмерПорции);
МетаданныеВыгрузки.Вставить("КоличествоПорций", КоличествоПорций);
ирОбщий.СохранитьЗначениеВФайлЛкс(МетаданныеВыгрузки, ИмяФайлаМетаданных);
СчитанаПоследняяПорция = Ложь;
НомерПорции = 1;
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КоличествоПорций, "Выгруза порций");
Пока Не СчитанаПоследняяПорция Цикл
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
ЗаписьXML = Новый ЗаписьXML;
ИмяФайлаДанныхXML = ПолучитьИмяВременногоФайла("xml");
ЗаписьXML.ОткрытьФайл(ИмяФайлаДанныхXML);
Попытка
ЗаписьXML.ЗаписатьНачалоЭлемента("Порция");
ЗаписатьСоотвествиеПространствИмен(ЗаписьXML);
СчитанаПоследняяПорция = СчитатьПорциюВыборкиВТаблицу(Выборка, ПорцияОсновнойТаблицы, РазмерПорции, ТабличныеЧасти);
Для Каждого КлючИЗначение Из ТабличныеЧасти Цикл
//ТабличныеЧасти[КлючИЗначение.Ключ] = мСервисныйПроцессор.ПолучитьТаблицуСМинимальнымиТипамиКолонокИис(КлючИЗначение.Значение);
ТабличныеЧасти[КлючИЗначение.Ключ] = КлючИЗначение.Значение;
КонецЦикла;
СтруктураДляЗаписи = Новый Структура;
СтруктураДляЗаписи.Вставить("ОсновнаяТаблица", ПорцияОсновнойТаблицы);
СтруктураДляЗаписи.Вставить("ТабличныеЧасти", ТабличныеЧасти);
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СтруктураДляЗаписи);
ПорцияОсновнойТаблицы.Очистить();
Для Каждого КлючИЗначение Из ТабличныеЧасти Цикл
КлючИЗначение.Значение.Очистить();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
Исключение
ЗаписьXML.Закрыть();
УдалитьФайлы(ИмяФайлаДанныхXML);
ВызватьИсключение;
КонецПопытки;
ЗаписьXML.Закрыть();
ИмяФайлаПорции = ИмяФайлаПорции(КаталогВыгрузки, НомерПорции);
Архив = Новый ЗаписьZipФайла(ИмяФайлаПорции);
Архив.Добавить(ИмяФайлаДанныхXML);
Архив.Записать();
УдалитьФайлы(ИмяФайлаДанныхXML);
НомерПорции = НомерПорции + 1;
КонецЦикла;
ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
Результат = Новый Структура();
#Если Не Клиент Тогда
Файлы = НайтиФайлы(КаталогВыгрузки, "*");
ДанныеФайлов = Новый Соответствие;
Для Каждого Файл Из Файлы Цикл
#Если Сервер И Не Сервер Тогда
Файл = Новый Файл;
#КонецЕсли
ДанныеФайлов[Файл.Имя] = Новый ДвоичныеДанные(Файл.ПолноеИмя);
КонецЦикла;
Результат.Вставить("ДанныеФайлов", ДанныеФайлов);
УдалитьФайлы(КаталогВыгрузки, МаркерИмениФайлаПорции() + "*.*");
#КонецЕсли
Возврат Результат;
КонецФункции
Функция ИмяФайлаМетаданныхСравнения()
ИмяФайлаМетаданных = КаталогВыгрузки + "\" + "МетаданныеСравнения.xml";
Возврат ИмяФайлаМетаданных;
КонецФункции
Функция ВыполнитьЗапросСИндикатором(Знач ЗапросДетальный)
ирОбщий.СостояниеЛкс("Выполнение запроса");
РезультатЗапроса = ЗапросДетальный.Выполнить();
ирОбщий.СостояниеЛкс("");
Возврат РезультатЗапроса;
КонецФункции
Функция СоздатьТаблицуПорции(Знач РезультатЗапроса, Знач ЭтоСсылочныйТип = Ложь)
ПорцияОсновнойТаблицы = Новый ТаблицаЗначений();
Для Каждого Колонка Из РезультатЗапроса.Колонки Цикл
Если Ложь
Или (Истина
И ЭтоСсылочныйТип
И Колонка.Имя = "ВерсияДанных")
Или Колонка.ТипЗначения.СодержитТип(Тип("РезультатЗапроса")) // Этот тип всегда один в описании типов колонки результата
Или Колонка.ТипЗначения.СодержитТип(Тип("МоментВремени")) // Этот тип всегда один в описании типов колонки результата
//Или ИсключаемыеПоля.Найти(Колонка.Имя) <> Неопределено
Тогда
Продолжить;
КонецЕсли;
ОписаниеТипов = Колонка.ТипЗначения;
ОписаниеТипов = КомпактноеОписаниеТиповДляСериализации(ОписаниеТипов);
ПорцияОсновнойТаблицы.Колонки.Добавить(Колонка.Имя, ОписаниеТипов);
КонецЦикла;
Возврат ПорцияОсновнойТаблицы;
КонецФункции
Функция ИмяФайлаПорции(Знач БазовыйКаталог, Знач НомерПорции)
ИмяФайлаПорции = КаталогВыгрузки + "\" + МаркерИмениФайлаПорции() + XMLСтрока(НомерПорции) + ".zip";
Возврат ИмяФайлаПорции;
КонецФункции
Функция МаркерИмениФайлаПорции() Экспорт
Возврат "ПорцияСравнения";
КонецФункции
Функция ПодготовитьЗапросСравненияВыгрузки(выхСтруктураТаблицы = Неопределено)
СтруктураКлюча = Новый СписокЗначений;
Для Каждого СтрокаПоля Из КолонкиТаблица1.НайтиСтроки(Новый Структура("Ключевая", Истина)) Цикл
СтруктураКлюча.Добавить(, СтрокаПоля.ИмяКолонки);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = ЗапросВыгрузки.ТекстЗапроса;
Для Каждого СтрокаПараметра Из ЗапросВыгрузки.Параметры Цикл
Запрос.Параметры.Вставить(СтрокаПараметра.ИмяПараметра, СтрокаПараметра.Значение);
КонецЦикла;
Построитель = Новый ПостроительЗапроса;
Построитель.Текст = Запрос.Текст;
Построитель.ЗаполнитьНастройки();
Построитель.Порядок.Очистить();
Для Каждого СтрокаПоля Из КолонкиТаблица1.НайтиСтроки(Новый Структура("Ключевая", Истина)) Цикл
Построитель.Порядок.Добавить(СтрокаПоля.ИмяКолонки);
КонецЦикла;
ЗапросДетальныйСПорядком = Построитель.ПолучитьЗапрос();
Запрос.Текст = ЗапросДетальныйСПорядком.Текст;
ТабличныеЧасти = Новый Структура;
ШаблонОсновнойТаблицы = КолонкиРезультатаЗапроса(Запрос.Текст, Ложь, Истина);
Для Каждого КолонкаШаблона Из ШаблонОсновнойТаблицы.Колонки Цикл
Если КолонкаШаблона.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Если Не ТабличныеЧасти.Свойство(КолонкаШаблона.Имя) Тогда
// Предопределенная табличная часть
ТабличныеЧасти.Вставить(КолонкаШаблона.Имя, Новый ТаблицаЗначений);
КонецЕсли;
КонецЕсли;
КонецЦикла;
выхСтруктураТаблицы = Новый Структура;
выхСтруктураТаблицы.Вставить("ОсновнаяТаблица", ШаблонОсновнойТаблицы);
выхСтруктураТаблицы.Вставить("ТабличныеЧасти", ТабличныеЧасти);
выхСтруктураТаблицы.Вставить("Ключ", СтруктураКлюча);
Возврат Запрос;
КонецФункции
Функция КолонкиРезультатаЗапроса(ТекстЗапроса, ВключаяЗаголовоки = Истина, КомпактноеОписаниеТипов = Ложь, ИсключаемыеПоля = Неопределено) Экспорт
ПостроительЗапроса = Новый ПостроительЗапроса;
Попытка
ПостроительЗапроса.Текст = ТекстЗапроса;
Исключение
ирОбщий.СообщитьЛкс("Ошибка при вычислении колонок результата запроса: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
ПостроительЗапроса.ЗаполнитьНастройки();
Результат = Новый ТаблицаЗначений;
Для Каждого ОписаниеПоля Из ПостроительЗапроса.ДоступныеПоля Цикл
Если Истина
И ИсключаемыеПоля <> Неопределено
И ИсключаемыеПоля.Найти(ОписаниеПоля.Имя) <> Неопределено
Тогда
Продолжить;
КонецЕсли;
НоваяКолонка = Результат.Колонки.Добавить(ОписаниеПоля.Имя, ОписаниеПоля.ТипЗначения);
Если ВключаяЗаголовоки Тогда
НоваяКолонка.Заголовок = ОписаниеПоля.Представление;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолучитьШаблоныВложенныхТаблиц(ОбъектМД)
#Если _ Тогда
ОбъектМД = Метаданные.Справочники.СервисыИис;
#КонецЕсли
ШаблоныВложенныхТаблиц = Новый Структура;
Для Каждого МетаТЧ Из ОбъектМД.ТабличныеЧасти Цикл
ШаблонТаблицы = НОвый ТаблицаЗначений;
Для Каждого МетаРеквизит Из МетаТЧ.Реквизиты Цикл
ОписаниеТипов = МетаРеквизит.Тип;
ОписаниеТипов = КомпактноеОписаниеТиповДляСериализации(ОписаниеТипов);
ШаблонТаблицы.Колонки.Добавить(МетаРеквизит.Имя, ОписаниеТипов);
КонецЦикла;
ШаблонТаблицы.Колонки.Добавить("Ссылка", Новый ОписаниеТипов(СтрЗаменить(ОбъектМД.ПолноеИмя(), ".", "Ссылка.")));
ШаблоныВложенныхТаблиц.Вставить(МетаТЧ.Имя, ШаблонТаблицы);
КонецЦикла;
Возврат ШаблоныВложенныхТаблиц;
КонецФункции
Процедура ПодготовитьПорциюТабличныхЧастейКСравнению(Знач ТабличныеЧасти)
Для Каждого КлючИЗначение Из ТабличныеЧасти Цикл
Если КлючИЗначение.Значение.Колонки.Количество() = 0 Тогда
КлючИЗначение.Значение.Колонки.Добавить("Ссылка");
КонецЕсли;
Если КлючИЗначение.Значение.Индексы.Количество() = 0 Тогда
КлючИЗначение.Значение.Индексы.Добавить("Ссылка");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция СкопироватьТабличныеЧасти(Структура)
#Если _ Тогда
Структура = Новый Структура
#КонецЕсли
Результат = Новый Структура;
Для Каждого КлючИЗначение Из Структура Цикл
Результат.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Значение.Скопировать());
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПрочитатьМетаданныеВыгрузки() Экспорт
ИмяФайлаМетаданных = ИмяФайлаМетаданныхСравнения();
ФайлМетаданных = Новый Файл(ИмяФайлаМетаданных);
Если Не ФайлМетаданных.Существует() Тогда
Возврат Неопределено;
КонецЕсли;
Результат = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ИмяФайлаМетаданных);
Возврат Результат;
КонецФункции
// вывод разницы
Процедура ВывестиРазницуЧисел(Знач СтрокаРезультата, Знач РезультатСравненияСтрок, Знач КолонкиРазницы);
#Если Сервер И Не Сервер Тогда
СтрокаРезультата = Новый ТаблицаЗначений;
СтрокаРезультата = СтрокаТаблицы.Добавить();
Строка2 = СтрокаТаблицы.Добавить();
#КонецЕсли
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
#Если Сервер И Не Сервер Тогда
Для Каждого ВыводимаяКолонка Из КолонкиРазницы Цикл
Если РезультатСравненияСтрок = ПризнакТолько2 Тогда
ЗначениеЯчейки1 = 0;
Иначе
ЗначениеЯчейки1 = СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки + "1"];
КонецЕсли;
Если РезультатСравненияСтрок = ПризнакТолько1 Тогда
ЗначениеЯчейки2 = 0;
Иначе
ЗначениеЯчейки2 = СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки2 + "2"];
КонецЕсли;
Если Истина
И ТипЗнч(ЗначениеЯчейки1) = Тип("Число")
И ТипЗнч(ЗначениеЯчейки2) = Тип("Число")
Тогда
СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки + "Разность"] = ЗначениеЯчейки2 - ЗначениеЯчейки1;
КонецЕсли;
КонецЦикла;
#КонецЕсли
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого ВыводимаяКолонка Из КолонкиРазницы Цикл   Если РезультатСравненияСтрок = ПризнакТолько2 Тогда   ЗначениеЯчейки1 = 0;   Иначе   ЗначениеЯчейки1 = СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки + "1"];   КонецЕсли;   Если РезультатСравненияСтрок = ПризнакТолько1 Тогда   ЗначениеЯчейки2 = 0;   Иначе   ЗначениеЯчейки2 = СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки2 + "2"];   КонецЕсли;   Если Истина   И ТипЗнч(ЗначениеЯчейки1) = Тип("Число")   И ТипЗнч(ЗначениеЯчейки2) = Тип("Число")   Тогда   СтрокаРезультата[ВыводимаяКолонка.ИмяКолонки + "Разность"] = ЗначениеЯчейки2 - ЗначениеЯчейки1;   КонецЕсли;   КонецЦикла;  
КонецПроцедуры
// цвета по-умолчанию
Процедура УстановитьСтандартныеЦвета() Экспорт
ОтличаютсяЦветФона = ирОбщий.ЦветФонаОшибкиЛкс();
ОтличаютсяЦветТекста = Новый Цвет;
ТолькоВТаблице1ЦветФона = WebЦвета.СветлоЖелтый;
ТолькоВТаблице1ЦветТекста = Новый Цвет;
ТолькоВТаблице2ЦветФона = WebЦвета.Лазурный;
ТолькоВТаблице2ЦветТекста = Новый Цвет;
КонецПроцедуры
//ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла);
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
//ирПортативный #Если Клиент Тогда
//ирПортативный Контейнер = Новый Структура();
//ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер);
//ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
//ирПортативный ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля);
//ирПортативный ирПортативный.Открыть();
//ирПортативный КонецЕсли;
//ирПортативный #Иначе
//ирПортативный ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
//ирПортативный #КонецЕсли
//ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий");
//ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш");
//ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер");
//ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный");
УстановитьСтандартныеЦвета();
мИменаВозвращаемыхСвойств = "ВсегоРазличий, СтруктураКолонокРезультата, СравниваемыеКолонкиРезультата, РезультатСравнения";
ПризнакРавно = 1;
ПризнакНеРавно = 2;
ПризнакТолько1 = 3;
ПризнакТолько2 = 4;
НеВыводитьОдинаковыеСтроки = Истина;
//НеУчитыватьРегистр = Истина;
РасполагатьСравниваемыеЯчейкиВертикально = Истина;
ВыводитьРазницуЧисловыхКолонокСравнения = Истина;
ЗапросВыгрузки = Новый Структура;
ЗапросВыгрузки.Вставить("Параметры", Новый Структура);
ЗапросВыгрузки.Вставить("ТекстЗапроса", "ВЫБРАТЬ 1");
мИмяГруппыКлючевыхКолонок = "_ГруппаКлючевых" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
мИмяГруппыСравниваемыхКолонок = "_ГруппаСравниваемых" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
мИмяГруппыНесравниваемыхКолонок = "_ГруппаНесравниваемых" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
мИмяГруппыРазностныхКолонок = "_ГруппаРазностных" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
мИмяКолонкиРезультатаСравнения = "РезультатСравнения" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
мИмяКолонкиНомераСтрокиРезультата = ирОбщий.ИмяКолонкиВнутреннегоИДСтрокиЛкс();