//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирПривилегированный Экспорт;

#Если Клиент Тогда
	
// Структура примитивных типов (Булево, Дата, Строка, Число)
Перем ПримитивныеТипы;
Перем мИмяКолонкиНомерСтроки Экспорт;
Перем мИмяКолонкиРезультатПоиска Экспорт;
Перем мИмяКолонкиРезультатЗаписи Экспорт;
Перем мАлгоритмКонвертацииЗначенияПараметры Экспорт;
Перем мЭтоСсылочныйОбъект Экспорт;
Перем мПлатформа Экспорт;
Перем мКоличествоУспешно Экспорт;
Перем мКоличествоНеуспешно Экспорт;

////////////////////////////////////////////////////////////////////////////////
// УНИВЕРСАЛЬНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ

// Выводит сообщение об ошибке и выставляет параметр Отказ в "Истина". 
// В случае работы на клиенте или на сервере выводит в окно сообщений,
// в случае внешнего соединения вызывает исключение.
//
// Параметры:
//  ТекстСообщения - строка, текст сообщения.
//  Отказ          - булево, признак отказа (необязательный).
//
Функция ПолучитьПричинуОшибки(ТекстСообщения, Отказ = Ложь, Заголовок = "") Экспорт

	НачалоСлужебногоСообщения    = Найти(ТекстСообщения, "{");
	ОкончаниеСлужебногоСообщения = Найти(ТекстСообщения, "}:");
	Если ОкончаниеСлужебногоСообщения > 0 И НачалоСлужебногоСообщения > 0 Тогда
		ТекстСообщения = Лев(ТекстСообщения, (НачалоСлужебногоСообщения - 1)) +
		                 Сред(ТекстСообщения, (ОкончаниеСлужебногоСообщения + 2));
	КонецЕсли;
	Отказ = Истина;
	Возврат ТекстСообщения;
	
КонецФункции

// Функция интерактивно предлагает выбрать значение в зависимости от переданных параметров
// В форме, в списке выбора или выдает сообщение, что "Данная ячейка не может содержать значение"
//
// Параметры:
//  Значение - значение, которое необходимо выбрать
//  ОписаниеТипов - Описание типов выбираемого значения
//  СвязьПоТипу   - ПВХ связи значения по типу
//  ЭлементСвязиПоТипу - номер элемента связи по типу
//
// Возвращаемое значение:
//  Истина - значение выбрано, ложь - иначе.
//
Функция мВыбратьЗначение(Значение, ОписаниеТипов, СвязьПоТипу, ЭлементСвязиПоТипу, СвязьПоВладельцу, ВыборГруппы = Ложь)
	
	Если СвязьПоТипу = Неопределено Тогда
		Типы = ОписаниеТипов;
	Иначе
		ВидыСубконто = СвязьПоТипу.ВидыСубконто;
		Если ЭлементСвязиПоТипу > ВидыСубконто.Количество() Тогда
			Предупреждение("Данная ячейка не может содержать значение");
			Возврат ложь;
		КонецЕсли;
		Типы = СвязьПоТипу.ВидыСубконто[ЭлементСвязиПоТипу-1].ВидСубконто.ТипЗначения;
	КонецЕсли;
	Если Типы.Типы().Количество() = 1 Тогда
		Тип = Типы.Типы()[0];
		Менеджер = ирОбщий.ПолучитьМенеджерЛкс(Тип);
		Если Менеджер = Неопределено Тогда
			Возврат ВвестиЗначение(Значение,,Типы);
		Иначе
			//Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
			//	Если ВыборГруппы Тогда
			//		ФормаВыбора = Менеджер.ПолучитьФормуВыбораГруппы();
			//	Иначе
			//		ФормаВыбора = Менеджер.ПолучитьФормуВыбора();
			//	КонецЕсли;
			//	ФормаВыбора.ПараметрВыборПоВладельцу = СвязьПоВладельцу;
			//	ФормаВыбора.ПараметрОтборПоВладельцу = СвязьПоВладельцу;
			//Иначе
			//	ФормаВыбора = Менеджер.ПолучитьФормуВыбора();
			//КонецЕсли;
			//ФормаВыбора.НачальноеЗначениеВыбора = Значение;
			//Значение = ФормаВыбора.ОткрытьМодально();
			Отбор = Новый Структура();
			Если ЗначениеЗаполнено(СвязьПоВладельцу) Тогда
				Отбор.Вставить("Владелец", СвязьПоВладельцу);
			КонецЕсли; 
			Если ВыборГруппы Тогда
				Отбор.Вставить("ЭтоГруппа", Истина);
			КонецЕсли; 
			Значение = ирОбщий.ОткрытьФормуСпискаЛкс(Тип, Отбор, ,, Истина,, Значение, Истина);
			Возврат Значение <> Неопределено;
		КонецЕсли;
	Иначе
		ФормаВыбораЗначения = ПолучитьФорму("ФормаВыбораЗначения");
		ФормаВыбораЗначения.ЭлементыФормы.Значение.ВыборПоВладельцу = СвязьПоВладельцу;
		ФормаВыбораЗначения.ЭлементыФормы.Значение.ТипЗначения = ОписаниеТипов;
		ФормаВыбораЗначения.ЭлементыФормы.Значение.ОграничениеТипа = Типы;
		ФормаВыбораЗначения.ЭлементыФормы.Значение.ЭлементСвязиПоТипу = ЭлементСвязиПоТипу;
		ФормаВыбораЗначения.ЭлементыФормы.Значение.Значение = Значение;
		Значение = ФормаВыбораЗначения.ОткрытьМодально();
		Возврат Не Значение = Неопределено;
	КонецЕсли;
	
КонецФункции

// Функция приводит строковое представление числа к его значению
//
// Параметры:
//  Представление - Представление числа
//  ОписаниеТипов - Допустимое описание типов численного значения
//
// Возвращаемое значение:
//  Значение типа число
//
Функция мПривестиКЧислу(Представление, Знач ОписаниеТипов = Неопределено, Примечание = "")
	
	Если ОписаниеТипов = Неопределено Тогда
		ОписаниеТипов = Новый ОписаниеТипов("Число");
	КонецЕсли;
	
	НРегПредставление = НРег(Представление);
	Если НРегПредставление = "да" или НРегПредставление = "истина" или НРегПредставление = "включено" Тогда
		Возврат 1;
	ИначеЕсли НРегПредставление = "нет" или НРегПредставление = "ложь" или НРегПредставление = "выключено" Тогда
		Возврат 0;
	КонецЕсли;
	
	Результат = СтрЗаменить(Представление, " ", "");
	Попытка
		Результат = Число(Результат);
	Исключение
		Примечание = "Неправильный формат числа";
		Возврат 0;
	КонецПопытки;
	
	Результат1 = ОписаниеТипов.ПривестиЗначение(Результат);
	
	Если Не Результат1 = Результат Тогда
		Примечание = "Недопустимое числовое значение";
	КонецЕсли;
	
	Возврат Результат1;
	
КонецФункции // мПривестиКЧислу()

// Функция возвращает части представления даты
//
// Параметры:
//  Представление - Представление даты
//
// Возвращаемое значение:
//  массив частей даты
//
Функция ПолучитьЧастиПредставленияДаты(ЗНАЧ Представление)
	
	МассивЧастей = Новый Массив;
	НачалоЦифры = 0;
	Для к = 1 По СтрДлина(Представление) Цикл
		
		Символ = Сред(Представление, к ,1);
		ЭтоЦифра = Символ >= "0" и Символ <= "9";
		
		Если ЭтоЦифра Тогда
			
			Если НачалоЦифры = 0 Тогда
				НачалоЦифры = к;
			КонецЕсли;
			
		Иначе
			
			Если Не НачалоЦифры = 0 Тогда
				МассивЧастей.Добавить(Число(Сред(Представление,НачалоЦифры, к - НачалоЦифры)));
			КонецЕсли;
			
			НачалоЦифры = 0;
		КонецЕсли;
		
	КонецЦикла;
	
	Если Не НачалоЦифры = 0 Тогда
		МассивЧастей.Добавить(Число(Сред(Представление,НачалоЦифры)));
	КонецЕсли;
	
	Возврат МассивЧастей;
КонецФункции // ()

// Функция приводит строковое представление даты к его значению
//
// Параметры:
//  Представление - Представление числа
//  ОписаниеТипов - Допустимое описание типов значения типа дата
//
// Возвращаемое значение:
//  Значение типа дата
//
Функция мПривестиКДате(Представление, ТипРеквизита, Примечание = "")
	
	Результат = ТипРеквизита.ПривестиЗначение(Представление);
	Если Результат = '00010101' Тогда
		
		МассивЧастей = ПолучитьЧастиПредставленияДаты(Представление);
		Если ТипРеквизита.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Время Тогда
			
			Попытка
				
				Если МассивЧастей.Количество() = 3 Тогда
					Результат = Дата(1,1,1, МассивЧастей[0],МассивЧастей[1],МассивЧастей[2]);
				ИначеЕсли МассивЧастей.Количество() = 6 Тогда
					Результат = Дата(1,1,1, МассивЧастей[3],МассивЧастей[4],МассивЧастей[5]);
				КонецЕсли;
				
			Исключение
				Примечание = "Неправильный формат даты";
			КонецПопытки;
			
		ИначеЕсли МассивЧастей.Количество() = 3 или МассивЧастей.Количество() = 6 Тогда
			
			Если МассивЧастей[0] >= 1000 Тогда
				Временно = МассивЧастей[0];
				МассивЧастей[0] = МассивЧастей[2];
				МассивЧастей[2] = Временно;
			КонецЕсли;
			
			Если МассивЧастей[2] < 100 Тогда
				МассивЧастей[2] = МассивЧастей[2] + ?(МассивЧастей[2] < 30, 2000,1900);
			КонецЕсли;
			
			Попытка
				Если МассивЧастей.Количество() = 3 или ТипРеквизита.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда
					Результат = Дата(МассивЧастей[2],МассивЧастей[1],МассивЧастей[0]);
				Иначе
					Результат = Дата(МассивЧастей[2],МассивЧастей[1],МассивЧастей[0],МассивЧастей[3],МассивЧастей[4],МассивЧастей[5]);
				КонецЕсли;
			Исключение
				Примечание = "Неправильный формат даты";
			КонецПопытки;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция мПривестиКУникальномуИдентификатору(Представление, Примечание = "")
	
	Попытка
		Результат = Новый УникальныйИдентификатор(Представление);
	Исключение
		Примечание = "Неправильный формат уникального идентификатора";
	КонецПопытки;
	Возврат Результат;
	
КонецФункции

Функция мПривестиКОписаниюТипов(Представление, Примечание = "")
	
	Попытка
		Результат = Новый ОписаниеТипов(Представление);
	Исключение
		Примечание = "Неправильный формат описания типов";
	КонецПопытки;
	Возврат Результат;
	
КонецФункции


////////////////////////////////////////////////////////////////////////////////
// СЛУЖЕБНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ

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

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

// Функция считывает в табличный документ данные из файла в формате Excel
//
// Параметры:
//  ТабличныйДокумент  - ТабличныйДокумент, в который необходимо прочитать данные
//  ИмяФайла           - имя файла в формате Excel, из которого необходимо прочитать данные
//  НомерЛистаExcel    - номер листа книги Excel, из которого необходимо прочитать данные
//
// Возвращаемое значение:
//  Истина, если файл прочитан, Ложь - иначе
//
Функция _мПрочитатьТабличныйДокументИзExcel(ТабличныйДокумент, ИмяФайла, НомерЛистаExcel = 1) Экспорт
	
	#Если Сервер И Не Сервер Тогда
	    ТабличныйДокумент = Новый ТабличныйДокумент;
	#КонецЕсли
	xlLastCell = 11;
	
	ВыбФайл = Новый Файл(ИмяФайла);
	Если НЕ ВыбФайл.Существует() Тогда
		Сообщить("Файл не существует!");
		Возврат Ложь;
	КонецЕсли;
	
	Попытка
		Excel = Новый COMОбъект("Excel.Application");
		Excel.WorkBooks.Open(ИмяФайла);
		Состояние("Обработка файла Microsoft Excel...");
		ExcelЛист = Excel.Sheets(НомерЛистаExcel);
	Исключение
		Сообщить("Ошибка. Возможно неверно указан номер листа книги Excel.");
		Возврат ложь;
		
	КонецПопытки;
	
	ТабличныйДокумент.Очистить();
	
	ActiveCell = Excel.ActiveCell.SpecialCells(xlLastCell);
	RowCount = ActiveCell.Row;
	ColumnCount = ActiveCell.Column;
	Для Column = 1 По ColumnCount Цикл
		ТабличныйДокумент.Область("C" + Формат(Column, "ЧГ=")).ШиринаКолонки = ExcelЛист.Columns(Column).ColumnWidth;
	КонецЦикла;
	Для Row = 1 По RowCount Цикл
		
		Для Column = 1 По ColumnCount Цикл
			ТабличныйДокумент.Область("R" + Формат(Row, "ЧГ=") +"C" + Формат(Column, "ЧГ=")).Текст = ExcelЛист.Cells(Row,Column).Text;
		КонецЦикла;
		
	КонецЦикла;
	
	Excel.WorkBooks.Close();
	Excel = 0;
	
	Возврат Истина;
	
КонецФункции // ()

////////////////////////////////////////////////////////////////////////////////
//

// Функция интерактивно предлагает выбрать значение в текущей ячейке табличного документа
//
// Параметры:
//  ТабличныйДокумент  - ТабличныйДокумент, в текущей ячейке которого необходимо выбрать значение
//
// Возвращаемое значение:
//  Истина, если значение выбрано, Ложь - иначе
//
Процедура ВыбратьЗначениеВЯчейке() Экспорт
	
	ОчиститьСообщения();
	ТекущаяОбласть = ТабличныйДокумент.ТекущаяОбласть;
	Если ТекущаяОбласть.Верх <> ТекущаяОбласть.Низ Или ТекущаяОбласть.Лево <> ТекущаяОбласть.Право Тогда
		Предупреждение("Для непосредственного выбора значения необходимо выбирать только одну ячейку");
		Возврат;
	КонецЕсли;
	ТекущаяКолонка = ПолучитьКолонку(ТекущаяОбласть);
	Если ТекущаяКолонка = Неопределено  Тогда
		Предупреждение("Значение данной колонки не выбирается");
		Возврат;
	КонецЕсли;
	ТекущаяСтрока = КонтрольЗаполненияСтроки(ТабличныйДокумент, ТекущаяОбласть.Верх);
	Значение = ТекущаяОбласть.Расшифровка;
	СвязьПоТипу = Неопределено;
	Если Не ПустаяСтрока(ТекущаяКолонка.СвязьПоТипу) Тогда
		Если ТипЗНЧ(ТекущаяКолонка.СвязьПоТипу) = Тип("Строка") Тогда
			ТекущаяСтрока.Свойство(ТекущаяКолонка.СвязьПоТипу,СвязьПоТипу);
		Иначе
			СвязьПоТипу = ТекущаяКолонка.СвязьПоТипу;
		КонецЕсли;
	КонецЕсли;
	СвязьПоВладельцу = Неопределено;
	Если Не ПустаяСтрока(ТекущаяКолонка.СвязьПоВладельцу) Тогда
		Если ТипЗНЧ(ТекущаяКолонка.СвязьПоВладельцу) = Тип("Строка") Тогда
			ТекущаяСтрока.Свойство(ТекущаяКолонка.СвязьПоВладельцу,СвязьПоВладельцу);
		Иначе
			СвязьПоВладельцу = ТекущаяКолонка.СвязьПоВладельцу;
		КонецЕсли;
	КонецЕсли;
	ЭлементСвязиПоТипу = ?(ТекущаяКолонка.ЭлементСвязиПоТипу = 0,1,ТекущаяКолонка.ЭлементСвязиПоТипу);
	Если мВыбратьЗначение(Значение, ТекущаяКолонка.ОписаниеТипов,СвязьПоТипу, ЭлементСвязиПоТипу,СвязьПоВладельцу,ТекущаяКолонка.ИмяКолонкиПриемника = "Родитель") Тогда
		ТекущаяОбласть.Расшифровка = Значение;
		Если ПустаяСтрока(ТекущаяКолонка.ИскатьПо) Тогда
			ТекущаяОбласть.Текст = Строка(Значение);
		Иначе
			ТекущаяОбласть.Текст = Строка(Значение[ТекущаяКолонка.ИскатьПо]);
		КонецЕсли;
		ОчиститьСообщения();
		КонтрольЗаполненияСтроки(ТабличныйДокумент, ТекущаяОбласть.Верх);
	КонецЕсли;
	
КонецПроцедуры // ()

////////////////////////////////////////////////////////////////////////////////
//

// Функция возвращает метаданные источника данных
//
// Параметры:
//  нет
//
// Возвращаемое значение:
//  Объект метаданных
//
Функция ПолучитьМетаданныеИсточника() Экспорт
	
	Результат = ирОбщий.НайтиОбъектМетаданныхПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
	Возврат Результат;
	
КонецФункции // ()

// Функция возвращает значение структуры "Колонки" по области табличного документа,
// содержащее описание свойств колонки
//
// Параметры:
//  область - область табличного документа
//
// Возвращаемое значение:
//  значение структуры "Колонки"
//
Функция ПолучитьКолонку(Область)
	Для каждого СтрокаСопоставления Из СопоставлениеКолонокТЗ Цикл
		Если "" + Область.Лево = СтрокаСопоставления.ИмяКолонкиИсточника Тогда
			Возврат СтрокаСопоставления;
		КонецЕсли;
	КонецЦикла;
	Возврат Неопределено;
КонецФункции // ()

////////////////////////////////////////////////////////////////////////////////
//

// Процедура обновляет содержимое табличного документа, в соответствии с таблицей загружаемых реквизитов
//
// Параметры:
//  ТабличныйДокумент - ТабличныйДокумент, который необходимо обновить
//  БезВопросов       - булево, если Ложь, спрашивать об очистке табличного документа, если он не пустой, Истина - иначе
//
Процедура ОбновитьДанныеТабличногоДокумента(БезВопросов = Ложь) Экспорт
	
	#Если Сервер И Не Сервер Тогда
	    ТабличныйДокумент = Новый ТабличныйДокумент;
	#КонецЕсли
	Если ТабличныйДокумент.ВысотаТаблицы > 1 И Не БезВопросов Тогда
		Результат = Вопрос("Табличный документ содержит данные. Очистить?", РежимДиалогаВопрос.ДаНетОтмена, , КодВозвратаДиалога.Нет);
		Если  Результат = КодВозвратаДиалога.Да Тогда
			ТабличныйДокумент.Очистить();
		ИначеЕсли Результат = КодВозвратаДиалога.Отмена Тогда
			Возврат;
		Иначе
			Для к = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
				ТабличныйДокумент.Область(СтрокаЗаголовковТабличногоДокумента, К).Текст = "";
			КонецЦикла;
		КонецЕсли;
	Иначе
		ТабличныйДокумент.Очистить();
	КонецЕсли;
	Если ТабличныйДокумент.ВысотаТаблицы = 0 Тогда
		СтрокаЗаголовковТабличногоДокумента = 1;
		ПерваяСтрокаДанныхТабличногоДокумента = 2;
	КонецЕсли; 
	
	//СформироватьСтруктуруКолонок();
	СформироватьШапкуТабличногоДокумента();
	
КонецПроцедуры // ()

Процедура УстановитьИсточник() Экспорт
	
	ЭтотОбъект.мЭтоСсылочныйОбъект = Ложь;
	МетаданныеИсточника = ПолучитьМетаданныеИсточника();
	Если МетаданныеИсточника <> Неопределено Тогда
		ЭтотОбъект.ПредставлениеТаблицы = МетаданныеИсточника.Представление();
		ЭтотОбъект.мЭтоСсылочныйОбъект = ирОбщий.ЛиСсылочныйОбъектМетаданных(МетаданныеИсточника, Ложь);
	ИначеЕсли ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда 
		ОписаниеТаблицы = ирОбщий.ПолучитьОписаниеТаблицыБДИис(ПолноеИмяТаблицы);
		Если ОписаниеТаблицы = Неопределено Тогда
			Сообщить("Таблица БД " + ПолноеИмяТаблицы + " не найдена");
			ЭтотОбъект.ПолноеИмяТаблицы = "";
		КонецЕсли; 
	КонецЕсли;
	СписокСохраненныхНастроек = ирОбщий.ВосстановитьЗначениеЛкс("ирЗагрузкаТабличныхДанных." + ПолноеИмяТаблицы);
	Если Ложь
		Или ТаблицаЗначений.Колонки.Количество() < 2
		Или (Истина
			И ТаблицаЗначений.Колонки.Количество() <= 2 
			И ЗначениеЗаполнено(ПолноеИмяТаблицы))
	Тогда
		ОбновитьКолонкиТаблицыЗначений(, ЗначениеЗаполнено(ПолноеИмяТаблицы));
	КонецЕсли; 
	СопоставлениеКолонокТЗЗаполнить();
	ЗаполнитьСопоставлениеКолонокБД();
	Если ТабличныйДокумент.ВысотаТаблицы <= СтрокаЗаголовковТабличногоДокумента Тогда
		ОбновитьДанныеТабличногоДокумента(Истина);
	КонецЕсли;

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

// Процедура формирует шапку табличного документа, в соответствии с таблицей загружаемых реквизитов
//
// Параметры:
//  ТабличныйДокумент - ТабличныйДокумент, у которого необходимо сформировать шапку
//
Процедура СформироватьШапкуТабличногоДокумента() Экспорт
	
	Линия = Новый Линия(ТипЛинииЯчейкиТабличногоДокумента.Сплошная, 1);
	
	Таблица = СопоставлениеКолонокТЗ.Скопировать();
	Таблица.Сортировать("ИмяКолонкиИсточника");
	Для каждого СтрокаСопоставления Из СопоставлениеКолонокТЗ Цикл
		НомерКолонки = СтрокаСопоставления.ИмяКолонкиИсточника;
		Если Не СтрокаСопоставления.Пометка Тогда
			Продолжить;
		КонецЕсли;
		Если Не ЗначениеЗаполнено(НомерКолонки) Тогда
			Для Счетчик = 1 По СопоставлениеКолонокТЗ.Количество() Цикл
				Если СопоставлениеКолонокТЗ.Найти("" + Счетчик, "ИмяКолонкиИсточника") = Неопределено Тогда
					НомерКолонки = Счетчик;
					Прервать;
				КонецЕсли; 
			КонецЦикла;
			Если Не ЗначениеЗаполнено(НомерКолонки) Тогда
				Продолжить;
			КонецЕсли; 
			ОписаниеКолонки = Новый Структура("Имя, Заголовок, ПримерДанных", "" + НомерКолонки, СтрокаСопоставления.СинонимКолонкиПриемника, "");
			СопоставитьКолонкуТЗ(СтрокаСопоставления, ОписаниеКолонки);
		КонецЕсли; 
		
		Если СтрокаСопоставления.ШиринаКолонки = 0 Тогда
			ШиринаКолонки = 40;
			Если СтрокаСопоставления.ОписаниеТипов.Типы().Количество() = 1 Тогда
				ПервыйТип = СтрокаСопоставления.ОписаниеТипов.Типы()[0];
				Если ПервыйТип = Тип("Строка") Тогда
					Если СтрокаСопоставления.ОписаниеТипов.КвалификаторыСтроки.Длина = 0 Тогда
						ШиринаКолонки = 80;
					Иначе
						ШиринаКолонки = Мин(Макс(СтрокаСопоставления.ОписаниеТипов.КвалификаторыСтроки.Длина,10),80);
					КонецЕсли;
				ИначеЕсли ПервыйТип = Тип("Число") Тогда
					ШиринаКолонки = Макс(СтрокаСопоставления.ОписаниеТипов.КвалификаторыЧисла.Разрядность,10);
				ИначеЕсли ПервыйТип = Тип("Булево") Тогда
					ШиринаКолонки = 10;
				КонецЕсли;
			КонецЕсли;
		Иначе
			ШиринаКолонки = СтрокаСопоставления.ШиринаКолонки;
		КонецЕсли;
		Область = ТабличныйДокумент.Область(СтрокаЗаголовковТабличногоДокумента, НомерКолонки);
		БылТекст = Не ПустаяСтрока(Область.Текст);
		Область.Текст = ?(БылТекст, Область.Текст + Символы.ПС,"") + СтрокаСопоставления.СинонимКолонкиПриемника;
		Область.Расшифровка = СтрокаСопоставления.ИмяКолонкиПриемника;
		Область.ЦветФона = ЦветаСтиля.ЦветФонаФормы;
		Область.Обвести(Линия, Линия, Линия, Линия);
		ОбластьКолонки = ТабличныйДокумент.Область("C"+НомерКолонки);
		ОбластьКолонки.ШиринаКолонки = ?(БылТекст, Макс(ОбластьКолонки.ШиринаКолонки,ШиринаКолонки),ШиринаКолонки);
	КонецЦикла;
	//ОбновитьКолонкиТаблицыЗначений(, Ложь);
	
КонецПроцедуры // СформироватьШапкуТабличногоДокумента()

Процедура ОбновитьКолонкиТаблицыЗначений(ОчиститьСуществующие = Ложь, ИзБД = Истина) Экспорт 
	
	Если ОчиститьСуществующие Тогда
		ТаблицаЗначений.Очистить();
		ТаблицаЗначений.Колонки.Очистить();
	КонецЕсли; 
	ПроверитьДобавитьКолонкуИдентификатораСтроки(ТаблицаЗначений);
	Если ИзБД Тогда
		Если ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда
			Если Истина
				И СопоставлениеКолонокБД.НайтиСтроки(Новый Структура("Пометка", Истина)).Количество() = 0 
				И СопоставлениеКолонокБД.НайтиСтроки(Новый Структура("ПолеПоиска", Истина)).Количество() = 0
			Тогда
				СопоставлениеКолонокБД.ЗаполнитьЗначения(Истина, "Пометка");
			КонецЕсли; 
			ПоляТЗ = ирОбщий.ПолучитьПоляТаблицыБДЛкс(ПолноеИмяТаблицы);
			Для каждого ПолеТЗ Из ПоляТЗ Цикл
				СтрокаСопоставления = СопоставлениеКолонокБД.Найти(ПолеТЗ.Имя, "ИмяКолонкиПриемника");
				Если Ложь
					Или ТаблицаЗначений.Колонки.Найти(ПолеТЗ.Имя) <> Неопределено
					Или СтрокаСопоставления = Неопределено
					Или (Не СтрокаСопоставления.Пометка И Не СтрокаСопоставления.ПолеПоиска)
				Тогда
					Продолжить;
				КонецЕсли; 
				ТаблицаЗначений.Колонки.Добавить(ПолеТЗ.Имя, ПолеТЗ.ТипЗначения, ПолеТЗ.Заголовок);
			КонецЦикла;
		КонецЕсли; 
	Иначе
		мПлатформа = ирКэш.Получить();
		#Если Сервер И Не Сервер Тогда
		    мПлатформа = Обработки.ирПлатформа.Создать()
		#КонецЕсли
		ИндикаторКолонок = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТабличныйДокумент.ШиринаТаблицы, "Анализ документа");
		Для Счетчик = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
			ирОбщий.ОбработатьИндикаторЛкс(ИндикаторКолонок);
			СинонимКолонки = "";
			Если ЗначениеЗаполнено(СтрокаЗаголовковТабличногоДокумента) Тогда
				СинонимКолонки = ТабличныйДокумент.Область(СтрокаЗаголовковТабличногоДокумента, Счетчик).Текст;
			КонецЕсли; 
			Если Не ЗначениеЗаполнено(СинонимКолонки) Тогда
				СинонимКолонки = "Колонка " + Счетчик;
			КонецЕсли; 
			ИмяКолонки = мПлатформа.ПолучитьИдентификаторИзПредставления(СинонимКолонки);
			ШиринаКолонки = ТабличныйДокумент.Область(ПерваяСтрокаДанныхТабличногоДокумента, Счетчик).ШиринаКолонки;
			//Если ЛиВтораяСтрокаСодержитТипыЗначений Тогда
			Если Ложь Тогда
				ИменаТипов = ТабличныйДокумент.Область(2, Счетчик).Текст;
			Иначе
				ИменаТипов = Новый Массив;
				МаксДлинаСтроки = 0;
				Для НомерСтроки = ПерваяСтрокаДанныхТабличногоДокумента По ТабличныйДокумент.ВысотаТаблицы Цикл
					ОбработкаПрерыванияПользователя();
					ОбластьЯчейки = ТабличныйДокумент.Область(НомерСтроки, Счетчик);
					Расшифровка = ОбластьЯчейки.Расшифровка;
					Если Истина
						И Расшифровка <> Неопределено 
						И ТипЗнч(Расшифровка) <> Тип("ИдентификаторРасшифровкиКомпоновкиДанных")
					Тогда 
						ИменаТипов.Добавить(ТипЗнч(Расшифровка));
					КонецЕсли; 
					Если МаксДлинаСтроки < СтрДлина(ОбластьЯчейки.Текст) Тогда
						МаксДлинаСтроки = СтрДлина(ОбластьЯчейки.Текст);
					КонецЕсли; 
				КонецЦикла;
				Если ИменаТипов.Количество() = 0 Тогда
					ИменаТипов = "Строка";
				КонецЕсли; 
			КонецЕсли; 
			Если ТаблицаЗначений.Колонки.Найти(ИмяКолонки) <> Неопределено Тогда
				Продолжить;
			КонецЕсли; 
			ТаблицаЗначений.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов(ИменаТипов,,,, Новый КвалификаторыСтроки(МаксДлинаСтроки)), СинонимКолонки, ШиринаКолонки);
		КонецЦикла; 
		ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	КонецЕсли; 
	
КонецПроцедуры

Функция ПолучитьКолонкиТабличногоДокумента() Экспорт 

	КолонкиТабличногоДокумента = Новый Соответствие;
	мПлатформа = ирКэш.Получить();
	#Если Сервер И Не Сервер Тогда
	    мПлатформа = Обработки.ирПлатформа.Создать()
	#КонецЕсли
	Для Счетчик = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
		СинонимКолонки = "";
		Если ЗначениеЗаполнено(СтрокаЗаголовковТабличногоДокумента) Тогда
			СинонимКолонки = ТабличныйДокумент.Область(СтрокаЗаголовковТабличногоДокумента, Счетчик).Текст;
		КонецЕсли; 
		Если Не ЗначениеЗаполнено(СинонимКолонки) Тогда
			СинонимКолонки = "Колонка " + Счетчик;
		КонецЕсли; 
		ИмяКолонки = "" + Счетчик;
		ПримерДанных = ТабличныйДокумент.Область(ПерваяСтрокаДанныхТабличногоДокумента, Счетчик).Текст;
		КолонкиТабличногоДокумента[ИмяКолонки] = Новый Структура("Имя, Заголовок, ПримерДанных", ИмяКолонки, СинонимКолонки, ПримерДанных);
	КонецЦикла; 
	Возврат КолонкиТабличногоДокумента;
	
КонецФункции 

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

Процедура СообщитьИтогиКонвертации(Знач КоличествоОшибокКонвертации)
	
	Если КоличествоОшибокКонвертации Тогда
		Сообщить("Выявлено ячеек, содержащих ошибки/неоднозначное представление: " + КоличествоОшибокКонвертации, СтатусСообщения.Внимание);
	Иначе
		Сообщить("Не выявлено ячеек, содержащих ошибки");
	КонецЕсли;

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

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

Процедура ОбновитьКоличествоУспешноДляОтображения()
	
	ЭтотОбъект.КоличествоУспешно = мКоличествоУспешно;
	ЭтотОбъект.КоличествоНеуспешно = мКоличествоНеуспешно;

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

Функция ОбработатьСобытиеЛкс(ТаблицаСобытий, ИмяСобытия, выхОписаниеОшибки, П1 = null, П2 = null, П3 = null, П4 = null, П5 = null, П6 = null, П7 = null, П8 = null) Экспорт 
	
	Алгоритм = СобытияОбработкиОбъектов.Найти(ИмяСобытия).Алгоритм;
	Попытка
		Выполнить(Алгоритм);
	Исключение
		выхОписаниеОшибки = ПолучитьПричинуОшибки(ОписаниеОшибки());
		Возврат Ложь;
	КонецПопытки;
	Возврат Истина;
	
КонецФункции

////////////////////////////////////////////////////////////////////////////////
//

// Процедура выполняет контроль заполнения данных табличного документа
// сообщает об ошибках и устанавливает коментарии к ошибочным ячейкам
//
// Параметры:
//  ТабличныйДокумент - ТабличныйДокумент, у которого необходимо сформировать шапку
//
Процедура КонтрольЗаполнения() Экспорт
	
	КоличествоЭлементов = ТабличныйДокумент.ВысотаТаблицы - ПерваяСтрокаДанныхТабличногоДокумента + 1;
	ОчиститьСообщения();
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(КоличествоЭлементов, "Контроль заполнения");
	КоличествоОшибокКонвертации = 0;
	Для К = 0  По КоличествоЭлементов - 1 Цикл
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		КонтрольЗаполненияСтроки(ТабличныйДокумент, К + ПерваяСтрокаДанныхТабличногоДокумента,, КоличествоОшибокКонвертации);
	КонецЦикла;
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс(, Истина);
	СообщитьИтогиКонвертации(КоличествоОшибокКонвертации);
	
КонецПроцедуры // КонтрольЗаполнения()

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

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

// Функция возвращает массив возможных значений для текущей колонки по представлению
//
// Параметры:
//  Колонка - Структура, свойства, в соответствии с которыми необходимо получить возможные значения
//  Представление - Строка, по которой необходимо вернуть массив значений
//  Примечание    - массив текстов ячеек строки
//  ТекущиеДанные  - структура загруженных значений
//
// Возвращаемое значение:
//  массив возможных значений
//
Функция ПолучитьВозможныеЗначения(Колонка, Представление, Примечание, ТекущиеДанные, КэшПоиска = Неопределено)
	
	Примечание = "";
	НайденныеЗначения = Новый Массив;
	Если ПустаяСтрока(Представление) Тогда
		Возврат НайденныеЗначения;
	КонецЕсли; 
	Если КэшПоиска = Неопределено Тогда
		КэшПоиска = Новый Соответствие;
	КонецЕсли; 
	КэшПоискаКолонки = КэшПоиска[Колонка];
	Если КэшПоискаКолонки = Неопределено Тогда
		КэшПоискаКолонки = Новый Соответствие;
		КэшПоиска[Колонка] = КэшПоискаКолонки;
	КонецЕсли; 
	ОписаниеТипов = Колонка.ОписаниеТипов;
	СвязьПоТипу = Неопределено;
	Если Не ПустаяСтрока(Колонка.СвязьПоТипу)  Тогда
		Если ТипЗНЧ(Колонка.СвязьПоТипу) = Тип("Строка") Тогда
			ТекущиеДанные.Свойство(Колонка.СвязьПоТипу, СвязьПоТипу);
		Иначе
			СвязьПоТипу = Колонка.СвязьПоТипу;
		КонецЕсли;
		Если Не СвязьПоТипу = Неопределено Тогда
			ЭлементСвязиПоТипу = Колонка.ЭлементСвязиПоТипу;
			Если ЭлементСвязиПоТипу = 0 Тогда
				ЭлементСвязиПоТипу = 1;
			КонецЕсли;
			ВидыСубконто = СвязьПоТипу.ВидыСубконто;
			Если ЭлементСвязиПоТипу > ВидыСубконто.Количество() Тогда
				Возврат НайденныеЗначения;
			КонецЕсли;
			ОписаниеТипов = СвязьПоТипу.ВидыСубконто[ЭлементСвязиПоТипу-1].ВидСубконто.ТипЗначения;
		КонецЕсли;
	КонецЕсли;
	Для каждого ТипРеквизита Из ОписаниеТипов.Типы() Цикл
		Если Ложь
			Или ТипРеквизита = Тип("Неопределено")
			Или ТипРеквизита = Тип("Null")
		Тогда
			НайденныеЗначения.Добавить(Новый (ТипРеквизита));
		ИначеЕсли Ложь
			Или ТипРеквизита = ПримитивныеТипы.Число 
			Или ТипРеквизита = ПримитивныеТипы.Булево 
		Тогда
			НайденныеЗначения.Добавить(мПривестиКЧислу(Представление, Колонка.ОписаниеТипов, Примечание));
		ИначеЕсли Ложь
			Или ТипРеквизита = ПримитивныеТипы.Строка 
			или ТипРеквизита = ПримитивныеТипы.Дата 
		Тогда
			НайденныеЗначения.Добавить(мПривестиКДате(Представление, Колонка.ОписаниеТипов, Примечание));
		ИначеЕсли ТипРеквизита = Тип("УникальныйИдентификатор") Тогда
			НайденныеЗначения.Добавить(мПривестиКУникальномуИдентификатору(Представление, Примечание));
		ИначеЕсли ТипРеквизита = Тип("ОписаниеТипов") Тогда
			НайденныеЗначения.Добавить(мПривестиКОписаниюТипов(Представление, Примечание));
		Иначе
			МетаданныеТипа = Метаданные.НайтиПоТипу(ТипРеквизита);
			Если Перечисления.ТипВсеСсылки().СодержитТип(ТипРеквизита) Тогда
				//Это Перечисление
				Для каждого ЗначениеПеречисления Из ирОбщий.ПолучитьМенеджерЛкс(ТипРеквизита) Цикл
					Если Колонка.ИскатьПо = "Имя" Тогда
						КлючЗначенияПеречисления = XMLСтрока(ЗначениеПеречисления);
					Иначе
						КлючЗначенияПеречисления = Строка(ЗначениеПеречисления);
					КонецЕсли; 
					Если ирОбщий.СтрокиРавныЛкс(КлючЗначенияПеречисления, Представление) Тогда
						НайденныеЗначения.Добавить(ЗначениеПеречисления);
					КонецЕсли;
				КонецЦикла;
			ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипРеквизита) Тогда
				//Это документ
				//ИскатьПо = Колонка.ИскатьПо;
				//Если ИскатьПо = "Идентификатор" Тогда
					СписокДокументов = ирОбщий.ПреобразоватьПредставлениеВСсылкуЛкс(МетаданныеТипа, Представление, КэшПоискаКолонки);
					Если СписокДокументов <> Неопределено Тогда
						Для Каждого ЭлементСписка Из СписокДокументов Цикл
							НайденныеЗначения.Добавить(ЭлементСписка.Значение);
						КонецЦикла;
					КонецЕсли; 
				//Иначе
				//	Если ИскатьПо = "Номер" Тогда
				//		//НайденноеЗначение = Менеджер.НайтиПоКоду(Представление);
				//	ИначеЕсли ИскатьПо = "Дата" Тогда
				//		//НайденноеЗначение = Менеджер.Найти
				//	Иначе
				//		ДлиннаСинонима = СтрДлина(""+МетаданныеТипа);
				//		Если Лев(Представление, ДлиннаСинонима) = ""+МетаданныеТипа Тогда
				//			НомерИДата = СокрЛП(Сред(Представление, ДлиннаСинонима+1));
				//			ПозицияОт = Найти(НомерИДата, " от ");
				//			Если Не ПозицияОт = 0 Тогда
				//				НомерДок = Лев(НомерИДата, ПозицияОт-1);
				//				Попытка
				//					ДатаДок  = Дата(Сред(НомерИДата, ПозицияОт+4));
				//				Исключение
				//					ДатаДок = Неопределено;
				//				КонецПопытки;
				//				Если Не ДатаДок = Неопределено Тогда
				//					Менеджер = ирОбщий.ПолучитьМенеджерЛкс(ТипРеквизита);
				//					НайденноеЗначение = Менеджер.НайтиПоНомеру(НомерДок, ДатаДок);
				//					Если Не НайденноеЗначение.Пустая() Тогда
				//						НайденныеЗначения.Добавить(НайденноеЗначение);
				//					КонецЕсли;
				//				КонецЕсли;
				//			КонецЕсли;
				//		КонецЕсли;
				//	КонецЕсли;
				//КонецЕсли; 
			ИначеЕсли МетаданныеТипа <> Неопределено Тогда
				ИскатьПо = Колонка.ИскатьПо;
				Если ИскатьПо = "Идентификатор" Тогда
					НайденныеЗначения.Добавить(ирОбщий.ПреобразоватьПредставлениеВСсылкуЛкс(МетаданныеТипа, Представление));
				Иначе
					ПоляТаблицыБД = ирКэш.ПолучитьПоляТаблицыБДЛкс(МетаданныеТипа.ПолноеИмя());
					НайденныеЗначения = КэшПоискаКолонки[Представление];
					Если НайденныеЗначения = Неопределено Тогда
						НайденныеЗначения = Новый Массив;
						ЭтоСправочник = Справочники.ТипВсеСсылки().СодержитТип(ТипРеквизита);
						Если ПустаяСтрока(ИскатьПо) Или ПоляТаблицыБД.Найти(ИскатьПо) = Неопределено Тогда
							СтрокаОсновногоПредставления = Строка(МетаданныеТипа.ОсновноеПредставление);
							Если СтрокаОсновногоПредставления = "ВВидеКода" Тогда
								ИскатьПо = "Код";
							ИначеЕсли СтрокаОсновногоПредставления = "ВВидеНаименования" Тогда
								ИскатьПо = "Наименование";
							ИначеЕсли СтрокаОсновногоПредставления = "ВВидеНомера" Тогда
								ИскатьПо = "Номер";
							КонецЕсли;
						КонецЕсли;
						Запрос = Новый Запрос;
						Запрос.Текст =
						"ВЫБРАТЬ
						|	_Таблица.Ссылка
						|ИЗ
						|	" + МетаданныеТипа.ПолноеИмя() + " КАК _Таблица
						|ГДЕ";
						Запрос.Текст = Запрос.Текст + "
						|	_Таблица." + ИскатьПо + " = &Представление";
						Запрос.УстановитьПараметр("Представление",Представление);
						Если Истина
							И ЭтоСправочник 
							И Не ПустаяСтрока(Колонка.СвязьПоВладельцу) 
							И Колонка.СвязьПоВладельцу <> "<Создаваемый объект>"
							И МетаданныеТипа.Владельцы.Количество() > 0 
						Тогда
							СвязьПоВладельцу = Неопределено;
							Если ТипЗНЧ(Колонка.СвязьПоВладельцу) = Тип("Строка") Тогда
								ТекущиеДанные.Свойство(Колонка.СвязьПоВладельцу,СвязьПоВладельцу);
							Иначе
								СвязьПоВладельцу = Колонка.СвязьПоВладельцу;
							КонецЕсли;
							Если Не СвязьПоВладельцу = Неопределено Тогда
								Запрос.Текст = Запрос.Текст + "
								|	И _Таблица.Владелец = &СвязьПоВладельцу";
								Запрос.УстановитьПараметр("СвязьПоВладельцу",СвязьПоВладельцу);
							КонецЕсли;
						КонецЕсли;
						Выборка =  Запрос.Выполнить().Выбрать();
						Пока Выборка.Следующий() Цикл
							НайденныеЗначения.Добавить(Выборка.Ссылка);
						КонецЦикла;
						КэшПоискаКолонки[Представление] = НайденныеЗначения;
					КонецЕсли; 
				КонецЕсли; 
			Иначе
				Примечание = "Для типа значения """ + ТипРеквизита + """ не описан способ поиска";
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	Возврат НайденныеЗначения;
КонецФункции // ()

////////////////////////////////////////////////////////////////////////////////
//

// Функция возвращает текущие настройки загружаемых реквизитов в формате Табличного документа
//
// Возвращаемое значение:
//  табличный документ
//
Функция ПолучитьНастройку() Экспорт
	
	ДокументРезультат = Новый Структура;
	ДокументРезультат.Вставить("ДобавлятьСтрокиБД", ДобавлятьСтрокиБД);
	ДокументРезультат.Вставить("СобытияОбработкиОбъектов", СобытияОбработкиОбъектов.Скопировать(, "ИмяСобытия, Алгоритм"));
	ДокументРезультат.Вставить("ОбновлятьСтрокиБД", ОбновлятьСтрокиБД);
	ДокументРезультат.Вставить("ПерваяСтрокаДанныхТабличногоДокумента", ПерваяСтрокаДанныхТабличногоДокумента);
	ДокументРезультат.Вставить("СтрокаЗаголовковТабличногоДокумента", СтрокаЗаголовковТабличногоДокумента);
	ДокументРезультат.Вставить("СопоставлениеКолонокТЗ", СопоставлениеКолонокТЗ.Скопировать());
	ДокументРезультат.Вставить("СопоставлениеКолонокБД", СопоставлениеКолонокБД.Скопировать());
	ДокументРезультат.Вставить("ТаблицаЗначений", ТаблицаЗначений.СкопироватьКолонки());
	ДокументРезультат.Вставить("ШапкаТабличногоДокумента", ТабличныйДокумент.ПолучитьОбласть(СтрокаЗаголовковТабличногоДокумента, 1, СтрокаЗаголовковТабличногоДокумента, ТабличныйДокумент.ШиринаТаблицы));
	Возврат ДокументРезультат;
	
КонецФункции // ()

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

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

////////////////////////////////////////////////////////////////////////////////
//

// Функция возвращает список, элементами которого выступают возможные имена представления загружаемого реквизита
//
// Параметры:
//  ЗагружаемыйРеквизит - Строка таблицы значений загружаемого реквизита
//
// Возвращаемое значение:
//  список значений; значение списка - строка имя представления
//
Функция ПолучитьСписокИменПредставлений(ЗагружаемыйРеквизит) Экспорт
	
	СписокВыбора = Новый СписокЗначений;
	Если ЗагружаемыйРеквизит.ОписаниеТипов.Типы().Количество() = 1 Тогда
		Тип = ЗагружаемыйРеквизит.ОписаниеТипов.Типы()[0];
		МетаданныеТипа = Метаданные.НайтиПоТипу(Тип);
		Если МетаданныеТипа <> Неопределено Тогда
			ПолноеИмяМД = МетаданныеТипа.ПолноеИмя();
			КорневойТип = ирОбщий.ПолучитьПервыйФрагментЛкс(ПолноеИмяМД);
		КонецЕсли; 
		ЭтоСправочник = Справочники.ТипВсеСсылки().СодержитТип(Тип);
		ЭтоСчет = ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип);
		ЭтоВидХарактеристик = ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип);
		Если ЭтоСправочник ИЛИ ЭтоСчет Или ЭтоВидХарактеристик Тогда
			ЕстьКод = МетаданныеТипа.ДлинаКода > 0;
			ЕстьИмя = МетаданныеТипа.ДлинаНаименования > 0;
			ВидОсновногоПредставление = ?(ЭтоСправочник, Метаданные.СвойстваОбъектов.ОсновноеПредставлениеСправочника,
				?(ЭтоСчет,Метаданные.СвойстваОбъектов.ОсновноеПредставлениеСчета,Метаданные.СвойстваОбъектов.ОсновноеПредставлениеВидаХарактеристики));
			Если МетаданныеТипа.ОсновноеПредставление = ВидОсновногоПредставление.ВВидеКода Тогда
				Если ЕстьКод Тогда
					СписокВыбора.Добавить("Код", "Код");
				КонецЕсли;
				Если ЕстьИмя Тогда
					СписокВыбора.Добавить("Наименование", "Наименование");
				КонецЕсли;
			Иначе
				Если ЕстьИмя Тогда
					СписокВыбора.Добавить("Наименование", "Наименование");
				КонецЕсли;
				Если ЕстьКод Тогда
					СписокВыбора.Добавить("Код", "Код");
				КонецЕсли;
			КонецЕсли;
			Для каждого Реквизит Из МетаданныеТипа.Реквизиты Цикл
				Если Не Реквизит.Индексирование = Метаданные.СвойстваОбъектов.Индексирование.НеИндексировать
					И Реквизит.Тип.Типы().Количество() = 1 и Реквизит.Тип.Типы()[0] = Тип ("Строка")
				Тогда
					СписокВыбора.Добавить(Реквизит.Имя, Реквизит.Представление());
				КонецЕсли;
			КонецЦикла;
		КонецЕсли; 
		Если ирОбщий.ЛиКорневойТипПеречисленияЛкс(КорневойТип) Тогда 
			СписокВыбора.Добавить("Синоним");
			СписокВыбора.Добавить("Имя");
		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда 
			СписокВыбора.Добавить("Авто", "<Авто>");
		ИначеЕсли МетаданныеТипа <> Неопределено Тогда 
			СписокВыбора.Добавить("Идентификатор", "<Идентификатор>");
		КонецЕсли;
	КонецЕсли;
	Возврат СписокВыбора;
	
КонецФункции // ()

Функция ПолучитьСписокСвязейПоВладельцу(ЗагружаемыйРеквизит) Экспорт
	
	ЕстьТипСамогоОбъекта = Ложь;
	Если мЭтоСсылочныйОбъект Тогда
		ОписаниеТиповСправочника = Тип(СтрЗаменить(ПолноеИмяТаблицы, ".", "Ссылка."));
	КонецЕсли; 
	СписокВыбора = Новый СписокЗначений;
	ТипыВладельцев = Новый Соответствие;
	Для каждого ТипКолонки Из ЗагружаемыйРеквизит.ОписаниеТипов.Типы() Цикл
		Если Справочники.ТипВсеСсылки().СодержитТип(ТипКолонки) Тогда
			Для каждого Владелец Из Метаданные.НайтиПоТипу(ТипКолонки).Владельцы Цикл
				ТипВладельца   = Тип(СтрЗаменить(Владелец.ПолноеИмя(), ".", "Ссылка."));
				Если ТипыВладельцев[ТипВладельца] = Неопределено Тогда
					Если ТипВладельца = ОписаниеТиповСправочника Тогда
						ЕстьТипСамогоОбъекта = Истина;
					КонецЕсли;
					ТипыВладельцев.Вставить(ТипВладельца, Владелец.ПолноеИмя());
					Для каждого КолонкаСвязиПоВладельцу Из СопоставлениеКолонокТЗ Цикл
						Если КолонкаСвязиПоВладельцу.ОписаниеТипов.Типы()[0] = ТипВладельца Тогда
							// Возможно надо будет по всем типам проходить
							СписокВыбора.Добавить(КолонкаСвязиПоВладельцу.ИмяКолонкиПриемника,КолонкаСвязиПоВладельцу.ИмяКолонкиПриемника);
						КонецЕсли;
					КонецЦикла;
				КонецЕсли;
			КонецЦикла;
		КонецЕсли;
	КонецЦикла;
	Если Не ТипыВладельцев.Количество() = 0 Тогда
		СписокВыбора.Добавить(Неопределено, "<пустое значение>");
	КонецЕсли;
	Для каждого КлючИЗначение Из ТипыВладельцев Цикл
		СписокВыбора.Добавить(СтрЗаменить(КлючИЗначение.Значение, ".", "Ссылка."), "<"+КлючИЗначение.Значение+">");
	КонецЦикла;
	Если ЕстьТипСамогоОбъекта Тогда
		СписокВыбора.Вставить(0, "<Создаваемый объект>", "<Создаваемый объект>");
	КонецЕсли;
	Возврат СписокВыбора;
	
КонецФункции // ()

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

////////////////////////////////////////////////////////////////////////////////
//

Процедура ЗаполнитьСопоставлениеКолонокБД() Экспорт 
	
	КопияСопоставления = СопоставлениеКолонокБД.Скопировать();
	СопоставлениеКолонокБД.Очистить();
	Если Не ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда
		Возврат;
	КонецЕсли; 
	МетаданныеИсточника = ПолучитьМетаданныеИсточника();
	ПоляТаблицы = ирОбщий.ПолучитьПоляТаблицыБДЛкс(ПолноеИмяТаблицы);
	СтруктураКлючаОбъекта = ирОбщий.ПолучитьСтруктуруКлючаТаблицыБДЛкс(ПолноеИмяТаблицы, Ложь);
	МассивВозможныхПолейПоиска = Новый Массив;
	МассивВозможныхПолейПоиска.Добавить("Код");
	МассивВозможныхПолейПоиска.Добавить("Наименование");
	МассивВозможныхПолейПоиска.Добавить("Период");
	МассивВозможныхПолейПоиска.Добавить("Регистратор");
	МассивВозможныхПолейПоиска.Добавить("НомерСтроки");
	МассивВозможныхПолейПоиска.Добавить("Ссылка");
	МассивВозможныхПолейПоиска.Добавить("Номер");
	МассивВозможныхПолейПоиска.Добавить("Владелец");
	МассивВозможныхПолейПоиска.Добавить("Дата");
	МассивВозможныхПолейПоиска.Добавить("Родитель");
	МассивВозможныхПолейПоиска.Добавить("ЭтоГруппа");
	ТипТаблицыБД = ирОбщий.ПолучитьТипТаблицыБДЛкс(ПолноеИмяТаблицы);
	Если ирОбщий.ЛиКорневойТипРегистраБДЛкс(ТипТаблицыБД) Тогда
		Для каждого МетаИзмерение Из МетаданныеИсточника.Измерения Цикл
			МассивВозможныхПолейПоиска.Добавить(МетаИзмерение.Имя);
		КонецЦикла;
	КонецЕсли; 
	Для Каждого ПолеТаблицы Из ПоляТаблицы Цикл
		//Если Ложь
		//	Или ПолеТаблицы.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений"))
		//	Или ПолеТаблицы.ТипЗначения.СодержитТип(Тип("ХранилищеЗначения"))
		//	Или (Истина
		//		И ПолеТаблицы.Метаданные = Неопределено
		//		И (Ложь
		//			Или ПолеТаблицы.Имя = "ВерсияДанных"
		//			Или ПолеТаблицы.Имя = "Предопределенный"))
		//Тогда
		//	Продолжить;
		//КонецЕсли; 
		ЗагружаемыйРеквизит = СопоставлениеКолонокБД.Добавить();
		ЗагружаемыйРеквизит.ИмяКолонкиПриемника = ПолеТаблицы.Имя;
		ЗагружаемыйРеквизит.СинонимКолонкиПриемника = ПолеТаблицы.Заголовок;
		ЗагружаемыйРеквизит.ОписаниеТиповПриемника = ПолеТаблицы.ТипЗначения;
		ЗагружаемыйРеквизит.ДоступноИзменение = Истина
			И Не (Истина
				И ирОбщий.ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицыБД)
				И (Ложь
					Или ПолеТаблицы.Имя = "Ссылка"
					Или ПолеТаблицы.Имя = "НомерСтроки"))
			И (Ложь
				Или Не мЭтоСсылочныйОбъект 
				Или Не ирОбщий.НедоступноИзменениеПоляСсылочногоОбъектаЛкс(ПолеТаблицы.Имя));
		Если ирОбщий.ЛиМетаданныеОбъектаСГруппамиЛкс(МетаданныеИсточника) Тогда 
			Если Истина
				И ПолеТаблицы.Метаданные <> Неопределено 
				И (Ложь
					Или ирКэш.НомерРежимаСовместимостиЛкс() < 802014 
					Или Метаданные.ОбщиеРеквизиты.Найти(ПолеТаблицы.Метаданные.Имя) = Неопределено) 
			Тогда 
				ЗагружаемыйРеквизит.Принадлежность = ПолеТаблицы.Метаданные.Использование;
			Иначе
				ЗагружаемыйРеквизит.Принадлежность = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента;
			КонецЕсли; 
		КонецЕсли; 
		Если СтруктураКлючаОбъекта.Свойство(ПолеТаблицы.Имя) Тогда
			ЗагружаемыйРеквизит.МожетБытьПолемПоиска = Истина;
			ЗагружаемыйРеквизит.Ключевое = Истина;
			ЗагружаемыйРеквизит.ПолеПоиска = Не мЭтоСсылочныйОбъект;
		ИначеЕсли ПолеТаблицы.Метаданные = Неопределено Тогда 
			ЗагружаемыйРеквизит.МожетБытьПолемПоиска = МассивВозможныхПолейПоиска.Найти(ПолеТаблицы.Имя) <> Неопределено;
		Иначе
			Попытка
				Индексирован = ПолеТаблицы.Метаданные.Индексирование <> Метаданные.СвойстваОбъектов.Индексирование.НеИндексировать;
			Исключение
				Индексирован = Ложь;
			КонецПопытки; 
			ЗагружаемыйРеквизит.МожетБытьПолемПоиска = Индексирован;
		КонецЕсли; 
		ЗагружаемыйРеквизит.Значение = ЗагружаемыйРеквизит.ОписаниеТиповПриемника.ПривестиЗначение(Неопределено);
		СтараяСтрока = КопияСопоставления.Найти(ЗагружаемыйРеквизит.ИмяКолонкиПриемника, "ИмяКолонкиПриемника");
		Если СтараяСтрока <> Неопределено Тогда
			ЗаполнитьЗначенияСвойств(ЗагружаемыйРеквизит, СтараяСтрока, "ИзИсточника, ПолеПоиска, Пометка, Значение"); 
			Если ЗагружаемыйРеквизит.ИзИсточника Тогда
				СопоставитьКолонкуБД(ЗагружаемыйРеквизит, ТаблицаЗначений.Колонки.Найти(СтараяСтрока.ИмяКолонкиИсточника));
			КонецЕсли; 
		КонецЕсли; 
		Если СтруктураКлючаОбъекта.Свойство(ПолеТаблицы.Имя) Тогда
			ЗагружаемыйРеквизит.Пометка = Не мЭтоСсылочныйОбъект;
			//ЗагружаемыйРеквизит.ПолеПоиска = Не мЭтоСсылочныйОбъект;
		КонецЕсли; 
	КонецЦикла;
	СопоставлениеКолонокБД.Сортировать("СинонимКолонкиПриемника");
	СопоставлениеКолонокБДЗаполнитьПоИменамСинонимам();
	ВыявитьНеуникальныеКлючи();
	
КонецПроцедуры // ()

Функция ВыявитьНеуникальныеКлючи(выхСтрокаКлючаИсточника = "") Экспорт 
	
	выхСтрокаКлючаИсточника = "";
	Для Каждого СтрокаСопоставления Из СопоставлениеКолонокБД.НайтиСтроки(Новый Структура("ПолеПоиска", Истина)) Цикл
		Если выхСтрокаКлючаИсточника <> "" Тогда
			выхСтрокаКлючаИсточника = выхСтрокаКлючаИсточника + ",";
		КонецЕсли; 
		выхСтрокаКлючаИсточника = выхСтрокаКлючаИсточника + СтрокаСопоставления.ИмяКолонкиИсточника;
	КонецЦикла; 
	НеуникальныеКлючи = ирОбщий.ПолучитьНеуникальныеКлючиТаблицыЛкс(ТаблицаЗначений, выхСтрокаКлючаИсточника);
	ЭтотОбъект.КоличествоНеуникально = НеуникальныеКлючи.Количество();
	Возврат НеуникальныеКлючи;

КонецФункции

Процедура СопоставлениеКолонокБДЗаполнитьПоИменамСинонимам() Экспорт
	
	Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
		Если Колонка.Имя = мИмяКолонкиНомерСтроки Тогда
			Продолжить;
		КонецЕсли; 
		СтруктураОтбора = Новый Структура("СинонимКолонкиИсточника", "");
		СтрокиСопоставления = СопоставлениеКолонокБД.НайтиСтроки(СтруктураОтбора);
		СтрокаИмен = "";
		Для Каждого СтрокаСопоставления Из СтрокиСопоставления Цикл
			Если Не ирОбщий.ОписаниеТипов1ВходитВОписаниеТипов2Лкс(Колонка.ТипЗначения, СтрокаСопоставления.ОписаниеТиповПриемника) Тогда
				Продолжить;
			КонецЕсли; 
			Если Ложь
				Или ирОбщий.СтрокиРавныЛкс(СтрокаСопоставления.ИмяКолонкиПриемника, Колонка.Имя) 
				Или ирОбщий.СтрокиРавныЛкс(СтрокаСопоставления.СинонимКолонкиПриемника, Колонка.Заголовок)
			Тогда
				СопоставитьКолонкуБД(СтрокаСопоставления, Колонка);
				СтрокаИмен = СтрокаИмен + ", " + СтрокаСопоставления.ИмяКолонкиПриемника;
			КонецЕсли; 
		КонецЦикла;
		Если СтрокиСопоставления.Количество() > 0 Тогда
			СтрокаКолонки = КолонкиТЗ.Найти(Колонка.Имя, "ИмяКолонки");
			Если СтрокаКолонки <> Неопределено Тогда
				СтрокаКолонки.КолонкиПриемника = СтрокаКолонки.КолонкиПриемника + СтрокаИмен;
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	
КонецПроцедуры

Процедура ОбновитьКолонкиТаблицыБД(ОчиститьСуществующие = Истина, ДобавитьКолонкуРезультатаЗаписи = Истина) Экспорт 
	
	Если ОчиститьСуществующие Тогда
		ТаблицаБД.Очистить();
		ТаблицаБД.Колонки.Очистить();
	КонецЕсли; 
	ПроверитьДобавитьКолонкуИдентификатораСтроки(ТаблицаБД);
	Если ТаблицаБД.Колонки.Найти(мИмяКолонкиРезультатПоиска) = Неопределено Тогда
		ТаблицаБД.Колонки.Добавить(мИмяКолонкиРезультатПоиска, Новый ОписаниеТипов("Строка"), "<Результат поиска>");
	КонецЕсли;
	Если ДобавитьКолонкуРезультатаЗаписи Тогда
		Если ТаблицаБД.Колонки.Найти(мИмяКолонкиРезультатЗаписи) = Неопределено Тогда
			ТаблицаБД.Колонки.Добавить(мИмяКолонкиРезультатЗаписи, Новый ОписаниеТипов("Строка"), "<Результат записи>");
		КонецЕсли;
	КонецЕсли; 
	СтруктураКлючаОбъекта = ирОбщий.ПолучитьСтруктуруКлючаТаблицыБДЛкс(ПолноеИмяТаблицы, Ложь);
	ПоляБД = ирОбщий.ПолучитьПоляТаблицыБДЛкс(ПолноеИмяТаблицы);
	Для каждого КлючИЗначение Из СтруктураКлючаОбъекта Цикл
		ПолеБД = ПоляБД.Найти(КлючИЗначение.Ключ, "Имя");
		ТаблицаБД.Колонки.Добавить(ПолеБД.Имя, ПолеБД.ТипЗначения, ПолеБД.Заголовок + " (ключ)");
	КонецЦикла;
	КопияСопоставления = СопоставлениеКолонокБД.Скопировать();
	КопияСопоставления.Сортировать("ПолеПоиска Убыв, Пометка Убыв");
	Для каждого СтрокаСопоставленияБД Из КопияСопоставления Цикл
		Если Ложь
			Или СтруктураКлючаОбъекта.Свойство(СтрокаСопоставленияБД.ИмяКолонкиПриемника) // Колонка уже добавлена выше
			Или (Истина
				И Не СтрокаСопоставленияБД.ПолеПоиска
				И Не СтрокаСопоставленияБД.Пометка)
		Тогда
			Продолжить;
		КонецЕсли; 
		ПолеБД = ПоляБД.Найти(СтрокаСопоставленияБД.ИмяКолонкиПриемника, "Имя");
		ЗаголовокКолонки = ПолеБД.Заголовок;
		Если СтрокаСопоставленияБД.ПолеПоиска Тогда
			ЗаголовокКолонки = ЗаголовокКолонки + " (поиск)";
		ИначеЕсли Не СтрокаСопоставленияБД.Пометка Тогда
			ЗаголовокКолонки = ЗаголовокКолонки + " (новая)";
		КонецЕсли; 
		ТаблицаБД.Колонки.Добавить(ПолеБД.Имя, ПолеБД.ТипЗначения, ЗаголовокКолонки);
	КонецЦикла;
	
КонецПроцедуры

Процедура ПроверитьДобавитьКолонкуИдентификатораСтроки(Таблица) Экспорт 
	
	Если Таблица.Колонки.Найти(мИмяКолонкиНомерСтроки) = Неопределено Тогда
		Таблица.Колонки.Вставить(0, мИмяКолонкиНомерСтроки, Новый ОписаниеТипов("Число"), "<№>");
	КонецЕсли;

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

Процедура СопоставлениеКолонокТЗЗаполнить() Экспорт
	
	ОбновитьСопоставлениеКолонокТЗ(Истина);
	КолонкиТабличногоДокумента = ПолучитьКолонкиТабличногоДокумента();
	Для Каждого КлючИЗначение Из КолонкиТабличногоДокумента Цикл
		Колонка = КлючИЗначение.Значение;
		СтруктураОтбора = Новый Структура("СинонимКолонкиИсточника", "");
		СтрокиСопоставления = СопоставлениеКолонокТЗ.НайтиСтроки(СтруктураОтбора);
		КолонкаСопоставлена = Ложь;
		Для Каждого СтрокаСопоставления Из СтрокиСопоставления Цикл
			Если ирОбщий.СтрокиРавныЛкс(СтрокаСопоставления.СинонимКолонкиПриемника, Колонка.Заголовок) Тогда
				СопоставитьКолонкуТЗ(СтрокаСопоставления, Колонка);
				КолонкаСопоставлена = Истина;
				Прервать;
			КонецЕсли; 
		КонецЦикла;
		Если КолонкаСопоставлена Тогда
			СтрокаКолонки = НесопоставленныеКолонкиТД.Найти(Колонка.Имя, "ИмяКолонки");
			Если СтрокаКолонки <> Неопределено Тогда
				НесопоставленныеКолонкиТД.Удалить(СтрокаКолонки);
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	
КонецПроцедуры

Процедура СопоставитьКолонкуБД(Знач СтрокаСопоставления, Знач Колонка = Неопределено) Экспорт 
	
	Если Колонка <> Неопределено Тогда
		//СтрокаСопоставления.Пометка = Истина;
		СтрокаСопоставления.ИзИсточника = Истина;
		СтрокаСопоставления.ИмяКолонкиИсточника = Колонка.Имя;
		СтрокаСопоставления.СинонимКолонкиИсточника = Колонка.Заголовок;
		СтрокаСопоставления.ОписаниеТиповИсточника = Колонка.ТипЗначения;
	Иначе
		СтрокаСопоставления.ИзИсточника = Ложь;
		СтрокаСопоставления.ИмяКолонкиИсточника = "";
		СтрокаСопоставления.СинонимКолонкиИсточника = "";
		СтрокаСопоставления.ОписаниеТиповИсточника = Неопределено;
	КонецЕсли; 

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

Процедура СопоставитьКолонкуТЗ(Знач СтрокаСопоставления, Знач Колонка = Неопределено, УстановитьДопСвойства = Истина) Экспорт 
	
	Если Колонка <> Неопределено Тогда
		Если УстановитьДопСвойства Тогда
			СтрокаСопоставления.Пометка = Истина;
			СтрокаСопоставления.РежимКонвертации = "Искать";
		КонецЕсли; 
		СтрокаСопоставления.ИмяКолонкиИсточника = Колонка.Имя;
		СтрокаСопоставления.СинонимКолонкиИсточника = Колонка.Заголовок;
		СтрокаСопоставления.ПримерДанных = Колонка.ПримерДанных;
	Иначе
		СтрокаСопоставления.РежимКонвертации = "Устанавливать";
		СтрокаСопоставления.ИмяКолонкиИсточника = "";
		СтрокаСопоставления.СинонимКолонкиИсточника = "";
		СтрокаСопоставления.ПримерДанных = Неопределено;
	КонецЕсли; 

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

Процедура ОчиститьСопоставлениеКолонокБД() Экспорт

	Для Каждого СтрокаКолонкиБД Из СопоставлениеКолонокБД Цикл
		СопоставитьКолонкуБД(СтрокаКолонкиБД);
	КонецЦикла;
	ОбновитьСопоставлениеКолонокБД();

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

Процедура ОчиститьСопоставлениеКолонокТЗ() Экспорт

	Для Каждого СтрокаКолонкиТЗ Из СопоставлениеКолонокТЗ Цикл
		СопоставитьКолонкуТЗ(СтрокаКолонкиТЗ);
	КонецЦикла;
	ОбновитьСопоставлениеКолонокТЗ();

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

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

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

Процедура ОбновитьСопоставлениеКолонокТЗ(УстановитьПометкуДляСопоставленных = Ложь) Экспорт 
	
	КопияСопоставления = СопоставлениеКолонокТЗ.Скопировать();
	СопоставлениеКолонокТЗ.Очистить();
	КолонкиТабличногоДокумента = ПолучитьКолонкиТабличногоДокумента();
	Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
		Если Ложь
			Или Колонка.ТипЗначения.СодержитТип(Тип("ХранилищеЗначения"))
			Или Колонка.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений"))
			Или ирОбщий.СтрокиРавныЛкс(Колонка.Имя, мИмяКолонкиНомерСтроки)
		Тогда
			Продолжить;
		КонецЕсли; 
		ЗагружаемыйРеквизит = СопоставлениеКолонокТЗ.Добавить();
		ЗагружаемыйРеквизит.ИмяКолонкиПриемника = Колонка.Имя;
		ЗагружаемыйРеквизит.Пометка = Истина;
		ЗагружаемыйРеквизит.СинонимКолонкиПриемника = Колонка.Заголовок;
		ЗагружаемыйРеквизит.ДоступноеОписаниеТипов = Колонка.ТипЗначения;
		ЗагружаемыйРеквизит.ОписаниеТипов = Колонка.ТипЗначения;
		СписокВыбора = ПолучитьСписокИменПредставлений(ЗагружаемыйРеквизит);
		ЗагружаемыйРеквизит.ИскатьПо = ?(СписокВыбора.Количество() = 0, "",СписокВыбора[0].Значение);
		СписокВыбора = ПолучитьСписокСвязейПоВладельцу(ЗагружаемыйРеквизит);
		ЗагружаемыйРеквизит.СвязьПоВладельцу = ?(СписокВыбора.Количество() = 0, "", СписокВыбора[0].Значение);
		СписокВыбора = ПолучитьСписокСвязейПоТипу(ЗагружаемыйРеквизит);
		Если СписокВыбора.Количество() = 0 Тогда
			ЗагружаемыйРеквизит.СвязьПоТипу = "";
			ЗагружаемыйРеквизит.ЭлементСвязиПоТипу = 0;
		Иначе
			ЗагружаемыйРеквизит.СвязьПоТипу = СписокВыбора[0].Значение;
			Если Найти(ЗагружаемыйРеквизит.ИмяКолонкиПриемника, "3") <> 0 Тогда
				ЗагружаемыйРеквизит.ЭлементСвязиПоТипу = 3;
			ИначеЕсли Найти(ЗагружаемыйРеквизит.ИмяКолонкиПриемника, "2") <> 0 Тогда
				ЗагружаемыйРеквизит.ЭлементСвязиПоТипу = 2;
			Иначе
				ЗагружаемыйРеквизит.ЭлементСвязиПоТипу = 1;
			КонецЕсли;
		КонецЕсли;
		ЗагружаемыйРеквизит.ЗначениеПоУмолчанию = ЗагружаемыйРеквизит.ОписаниеТипов.ПривестиЗначение(Неопределено);
		ЗагружаемыйРеквизит.РежимКонвертации = "Искать";
		
		СтараяСтрока = КопияСопоставления.Найти(ЗагружаемыйРеквизит.ИмяКолонкиПриемника, "ИмяКолонкиПриемника");
		Если СтараяСтрока <> Неопределено Тогда
			ЗаполнитьЗначенияСвойств(ЗагружаемыйРеквизит, СтараяСтрока,, "СинонимКолонкиПриемника, ОписаниеТипов, ДоступноеОписаниеТипов"); 
			ПересечениеТипов = ирОбщий.ПересечениеОписанийТиповЛкс(СтараяСтрока.ОписаниеТипов, ЗагружаемыйРеквизит.ОписаниеТипов);
				#Если Сервер И Не Сервер Тогда
				    ПересечениеТипов = Новый ОписаниеТипов;
				#КонецЕсли
			Если ПересечениеТипов.Типы().Количество() > 0 Тогда
				ЗагружаемыйРеквизит.ОписаниеТипов = ПересечениеТипов;
			КонецЕсли; 
			Если ЗагружаемыйРеквизит.РежимКонвертации = "Искать" Тогда
				СопоставитьКолонкуТЗ(ЗагружаемыйРеквизит, КолонкиТабличногоДокумента[СтараяСтрока.ИмяКолонкиИсточника], УстановитьПометкуДляСопоставленных);
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	СопоставлениеКолонокТЗ.Сортировать("СинонимКолонкиПриемника");
	
	КолонкиТабличногоДокумента = ПолучитьКолонкиТабличногоДокумента();
	Для Каждого СтрокаКолонкиТЗ Из СопоставлениеКолонокТЗ Цикл
		Если Не СтрокаКолонкиТЗ.РежимКонвертации = "Искать" Тогда
			Продолжить;
		КонецЕсли; 
		Если ЗначениеЗаполнено(СтрокаКолонкиТЗ.ИмяКолонкиИсточника) Тогда 
			Колонка = КолонкиТабличногоДокумента[СтрокаКолонкиТЗ.ИмяКолонкиИсточника];
			СопоставитьКолонкуТЗ(СтрокаКолонкиТЗ, Колонка, УстановитьПометкуДляСопоставленных);
		КонецЕсли; 
	КонецЦикла;
	НесопоставленныеКолонкиТД.Очистить();
	Для Каждого КлючИЗначение Из КолонкиТабличногоДокумента Цикл
		Колонка = КлючИЗначение.Значение;
		Если СопоставлениеКолонокТЗ.Найти(Колонка.Имя, "ИмяКолонкиИсточника") = Неопределено Тогда
			СтрокаКолонки = НесопоставленныеКолонкиТД.Добавить();
			СтрокаКолонки.ИмяКолонки = Колонка.Имя;
			СтрокаКолонки.СинонимКолонки = Колонка.Заголовок;
			СтрокаКолонки.ПримерДанных = Колонка.ПримерДанных; 
		КонецЕсли; 
	КонецЦикла;
	НесопоставленныеКолонкиТД.Сортировать("СинонимКолонки");

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

// Процедура выполняет инициализацию служебных переменных и констант модуля
//
Процедура Инициализация() Экспорт
	
	ПримитивныеТипы = Новый Структура ("Число, Строка, Дата, Булево",
		Тип("Число"), Тип("Строка"), Тип("Дата"), Тип("Булево"));
	Если ПерваяСтрокаДанныхТабличногоДокумента < 2 Тогда
		ПерваяСтрокаДанныхТабличногоДокумента = 2;
	КонецЕсли;
	Если СтрокаЗаголовковТабличногоДокумента < 1 Тогда
		СтрокаЗаголовковТабличногоДокумента = 1;
	КонецЕсли;

КонецПроцедуры // ()

//ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла);
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
//ирПортативный #Если Клиент Тогда
//ирПортативный 	Контейнер = Новый Структура();
//ирПортативный 	Оповестить("ирПолучитьБазовуюФорму", Контейнер);
//ирПортативный 	Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
//ирПортативный 		ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля);
//ирПортативный 		ирПортативный.Открыть();
//ирПортативный 	КонецЕсли; 
//ирПортативный #Иначе
//ирПортативный 	ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
//ирПортативный #КонецЕсли
//ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий");
//ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш");
//ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер");
//ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный");

мИмяКолонкиНомерСтроки = "_НомерСтроки9261284"; 
мИмяКолонкиРезультатПоиска = "_РезультатПоиска9261284"; 
мИмяКолонкиРезультатЗаписи = "_РезультатЗаписи9261284"; 
мПлатформа = ирКэш.Получить();
мЭтоСсылочныйОбъект = Ложь;
СтрокаЗаголовковТабличногоДокумента = 1;
ПерваяСтрокаДанныхТабличногоДокумента = 2;
ВыводитьОшибкиКонвертацииСразу = Истина;
ВыводитьОшибкаЗагрузкиСразу = Истина;
#КонецЕсли
