Функция ОписаниеПараметровПечати() Экспорт

	Результат = Новый Структура;
	Результат.Вставить("Форма");
	Результат.Вставить("ОбъектыПечати");
	Результат.Вставить("Идентификатор");
	Результат.Вставить("МенеджерПечати");
	Результат.Вставить("Обработчик");
	Результат.Вставить("СразуНаПринтер");
	Результат.Вставить("ФорматСохранения");
	Результат.Вставить("ЗаголовокФормы");
	Результат.Вставить("ПереопределитьПользовательскиеНастройкиКоличества");
	Результат.Вставить("ДополнитьКомплектВнешнимиПечатнымиФормами");
	Результат.Вставить("ФиксированныйКомплект");
	Результат.Вставить("ДополнительныеПараметры");

	Возврат Результат;

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

#Область УстаревшиеПроцедурыИФункции

////////////////////////////////////////////////////////////////////////////////
// Работа с макетами офисных документов.

//	Секция содержит интерфейсные функции (API), используемые при создании
//	печатных форм основанных на офисных документах MS Office (шаблоны MS Word) и Open Office (шаблоны OO Writer).
//
////////////////////////////////////////////////////////////////////////////////
//	Типы используемых данных (определяется конкретными реализациями).
//	СсылкаПечатнаяФорма	- ссылка на печатную форму.
//	СсылкаМакет			- ссылка на макет.
//	Область				- ссылка на область в печатной форме или макете (структура)
//						доопределяется в интерфейсном модуле служебной информацией
//						об области.
//	ОписаниеОбласти			- описание области макета (см. ниже).
//	ДанныеЗаполнения		- либо структура, либо массив структур (для случая
//							списков и таблиц.
////////////////////////////////////////////////////////////////////////////////
//	ОписаниеОбласти - структура, описывающая подготовленные пользователем области макета
//	ключ ИмяОбласти - имя области
//	ключ ТипТипОбласти - 	ВерхнийКолонтитул.
//							НижнийКолонтитул
//							Общая
//							СтрокаТаблицы
//							Список
//

////////////////////////////////////////////////////////////////////////////////
// Функции инициализации и закрытия ссылок.

// Устарела. Следует использовать УправлениеПечатью.ИнициализироватьПечатнуюФорму.
//
// Создает соединение с выходной печатной формой.
// Необходимо вызвать перед любыми действиями над формой.
// Функция не работает в любых других браузерах кроме IE.
// Перед выполнением функции в веб-клиенте необходимо подключить расширение для работы с 1С:Предприятием.
//
// Параметры:
//  ТипДокумента            - Строка - тип печатной формы "DOC" или "ODT";
//  НастройкиСтраницыМакета - Соответствие - параметры из структуры, возвращаемой функцией ИнициализироватьМакет
//                                           (параметр устарел, его следует пропускать и использовать параметр Макет);
//  Макет                   - Структура - результат функции ИнициализироватьМакет.
//
// Возвращаемое значение:
//  Структура - новая печатная форма.
//

Функция ИнициализироватьПечатнуюФорму(Знач ТипДокумента, Знач НастройкиСтраницыМакета = Неопределено, Макет = Неопределено) Экспорт

	Если ВРег(ТипДокумента) = "DOC" Тогда
		Параметр = ?(Макет = Неопределено, НастройкиСтраницыМакета, Макет); // для обратной совместимости
		ПечатнаяФорма = УправлениеПечатьюMSWordКлиент.ИнициализироватьПечатнуюФормуMSWord(Параметр);
		ПечатнаяФорма.Вставить("Тип", "DOC");
		ПечатнаяФорма.Вставить("ПоследняяВыведеннаяОбласть", Неопределено);
		Возврат ПечатнаяФорма;
	ИначеЕсли ВРег(ТипДокумента) = "ODT" Тогда
		ПечатнаяФорма = УправлениеПечатьюOOWriterКлиент.ИнициализироватьПечатнуюФормуOOWriter(Макет);
		ПечатнаяФорма.Вставить("Тип", "ODT");
		ПечатнаяФорма.Вставить("ПоследняяВыведеннаяОбласть", Неопределено);
		Возврат ПечатнаяФорма;
	КонецЕсли;

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

// Устарела. Следует использовать УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента.
//
// Создает COM-соединение с макетом. В дальнейшем это соединение используется при получении из него областей (тегов и
// таблиц).
// Функция не работает в любых других браузерах кроме IE.
// Перед выполнением функции в веб-клиенте необходимо подключить расширение для работы с 1С:Предприятием.
//
// Параметры:
//  ДвоичныеДанныеМакета - ДвоичныеДанные - двоичные данные макета;
//  ТипМакета            - Строка - тип макета печатной формы "DOC" или "ODT";
//  ИмяМакета            - Строка - имя, которое будет использовано при создании временного файла макета.
//
// Возвращаемое значение:
//  Структура - макет.
//

Функция ИнициализироватьМакетОфисногоДокумента(Знач ДвоичныеДанныеМакета, Знач ТипМакета, Знач ИмяМакета = "") Экспорт

	Макет = Неопределено;
	ИмяВременногоФайла = "";

	#Если ВебКлиент Тогда
		Если ПустаяСтрока(ИмяМакета) Тогда
			ИмяВременногоФайла = Строка(Новый УникальныйИдентификатор) + "." + НРег(ТипМакета);
		Иначе
			ИмяВременногоФайла = ИмяМакета + "." + НРег(ТипМакета);
		КонецЕсли;
	#КонецЕсли

	Если ВРег(ТипМакета) = "DOC" Тогда
		Макет = УправлениеПечатьюMSWordКлиент.ПолучитьМакетMSWord(ДвоичныеДанныеМакета, ИмяВременногоФайла);
		Если Макет <> Неопределено Тогда
			Макет.Вставить("Тип", "DOC");
		КонецЕсли;
	ИначеЕсли ВРег(ТипМакета) = "ODT" Тогда
		Макет = УправлениеПечатьюOOWriterКлиент.ПолучитьМакетOOWriter(ДвоичныеДанныеМакета, ИмяВременногоФайла);
		Если Макет <> Неопределено Тогда
			Макет.Вставить("Тип", "ODT");
			Макет.Вставить("НастройкиСтраницыМакета", Неопределено);
		КонецЕсли;
	КонецЕсли;

	Возврат Макет;

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

// Устарела. Следует использовать УправлениеПечатью.ОчиститьСсылки.
//
// Освобождает ссылки в созданном интерфейсе связи с офисным приложением.
// Необходимо вызывать каждый раз после завершения формирования макета и выводе печатной формы пользователю.
//
// Параметры:
//  ПечатнаяФорма     - Структура - результат функций ИнициализироватьПечатнуюФорму и ИнициализироватьМакетОфисногоДокумента;
//  ЗакрытьПриложение - Булево    - Истина, если требуется ли закрыть приложение.
//                                  Соединение с макетом требуется закрывать с закрытием приложения.
//                                  ПечатнуюФорму не требуется закрывать.
//

Процедура ОчиститьСсылки(ПечатнаяФорма, Знач ЗакрытьПриложение = Истина) Экспорт

	Если ПечатнаяФорма <> Неопределено Тогда
		Если ПечатнаяФорма.Тип = "DOC" Тогда
			УправлениеПечатьюMSWordКлиент.ЗакрытьСоединение(ПечатнаяФорма, ЗакрытьПриложение);
		Иначе
			УправлениеПечатьюOOWriterКлиент.ЗакрытьСоединение(ПечатнаяФорма, ЗакрытьПриложение);
		КонецЕсли;
		ПечатнаяФорма = Неопределено;
	КонецЕсли;

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

////////////////////////////////////////////////////////////////////////////////
// Функция отображения печатной формы пользователю.

// Устарела. Более не требуется.
//
// Показывает сформированный документ пользователю.
//
// Параметры:
//  ПечатнаяФорма - Структура - результат функции ИнициализироватьПечатнуюФорму.
//

Процедура ПоказатьДокумент(Знач ПечатнаяФорма) Экспорт

	Если ПечатнаяФорма.Тип = "DOC" Тогда
		УправлениеПечатьюMSWordКлиент.ПоказатьДокументMSWord(ПечатнаяФорма);
	ИначеЕсли ПечатнаяФорма.Тип = "ODT" Тогда
		УправлениеПечатьюOOWriterКлиент.ПоказатьДокументOOWriter(ПечатнаяФорма);
	КонецЕсли;

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

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

// Устарела. Следует использовать УправлениеПечатью.ОбластьМакета.
//
// Получает область из макета печатной формы.
//
// Параметры:
//  СсылкаНаМакет   - Структура - макет печатной формы.
//  ОписаниеОбласти - Структура:
//   * ИмяОбласти - Строка -имя области;
//   * ТипТипОбласти - Строка - тип области: "ВерхнийКолонтитул", "НижнийКолонтитул", "Общая", "СтрокаТаблицы", "Список".
//
// Возвращаемое значение:
//  Структура - область макета.
//


Процедура ОбновитьКомандыСостоянияОригинала(Форма, Список) Экспорт

	СостоянияОригиналов = ИспользуемыеСостояния();

	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПодключаемыеКоманды") Тогда
		ПодменюУстановитьНастроитьСостояниеОригинала = Форма.Элементы.Найти("ПодменюУстановитьНастроитьСостояниеОригиналаОбычное");
		Если Не ПодменюУстановитьНастроитьСостояниеОригинала = Неопределено Тогда
			Форма.Элементы.Удалить(ПодменюУстановитьНастроитьСостояниеОригинала);
		КонецЕсли;

		ПодменюУстановитьНастроитьСостояниеОригинала = Форма.Элементы.Найти("ПодменюУстановитьНастроитьСостояниеОригиналаСмТакже");
		Если Не ПодменюУстановитьНастроитьСостояниеОригинала = Неопределено Тогда
			Форма.Элементы.Удалить(ПодменюУстановитьНастроитьСостояниеОригинала);
		КонецЕсли;
	КонецЕсли;

	ВывестиНаФормуКомандыСостоянияОригинала(Форма, Список, СостоянияОригиналов);

	ЗаполнитьСписокВыбораСостоянийОригинала(Форма, СостоянияОригиналов);

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

// Устанавливает условное форматирование для подключаемых элементов в списке.
//
//	Параметры:
//  Форма - ФормаКлиентскогоПриложения - форма списка документа.
//  Список - ТаблицаФормы - основной список формы.
//

Процедура УстановитьУсловноеОформлениеВФормеСписка(Форма, Список) Экспорт

	ЭлементОформления = Форма.УсловноеОформление.Элементы.Добавить();

	ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(Список.Имя+".СостояниеОригиналаПервичногоДокумента");
	ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
	ЭлементОтбора.Использование = Истина;

	ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Текст", НСтр("ru = '<Неизвестно>'"));
	ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста",  ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
	ЭлементОформления.Использование = Истина;

	ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
	ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("СостояниеОригиналаПервичногоДокумента");
	ПолеОформления.Использование = Истина;

	ЭлементОформления = Форма.УсловноеОформление.Элементы.Добавить();

	ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(Список.Имя+".СостояниеОригиналаПервичногоДокумента");
	ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
	ЭлементОтбора.Использование = Истина;

	ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ГиперссылкаЦвет);
	ЭлементОформления.Использование = Истина;

	ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
	ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("СостояниеОригиналаПервичногоДокумента");
	ПолеОформления.Использование = Истина;

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

// Добавляет в описание профиля поставляемых групп доступа роль для изменения состояния оригинала.
//
// Параметры:
//  ОписаниеПрофиля - см. УправлениеДоступом.НовоеОписаниеПрофиляГруппДоступа
//

Процедура ДополнитьПрофильРольюДляИзмененияСостоянийОригиналовДокументов(ОписаниеПрофиля) Экспорт

	ОписаниеПрофиля.Роли.Добавить("ИзменениеСостоянийОригиналовПервичныхДокументов");

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

// Добавляет в описание профиля поставляемых групп доступа роль для настройки списка состояния оригинала.
//
// Параметры:
//  ОписаниеПрофиля - см. УправлениеДоступом.НовоеОписаниеПрофиляГруппДоступа.
//

Процедура ДополнитьПрофильРольюДляНастройкиСостоянийОригиналовДокументов(ОписаниеПрофиля) Экспорт

	ОписаниеПрофиля.Роли.Добавить("ДобавлениеИзменениеСостоянийОригиналовПервичныхДокументов");

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

// Добавляет в описание профиля поставляемых групп доступа роль для чтения состояния оригинала.
//
// Параметры:
//  ОписаниеПрофиля - см. УправлениеДоступом.НовоеОписаниеПрофиляГруппДоступа.
//

Процедура ДополнитьПрофильРольюДляЧтенияСостоянийОригиналовДокументов(ОписаниеПрофиля) Экспорт

	ОписаниеПрофиля.Роли.Добавить("ЧтениеСостоянийОригиналовПервичныхДокументов");

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

// Возвращает массив всех состояний.
//
//	Возвращаемое значение:
//  Массив из СправочникСсылка.СостоянияОригиналовПервичныхДокументов - все возможные состояния оригинала, включая
//    скрытое "Оригиналы не все".
//

Функция ВсеСостояния() Экспорт

	Запрос = Новый запрос;
	Запрос.Текст ="ВЫБРАТЬ РАЗРЕШЕННЫЕ
	              |	СостоянияОригиналовПервичныхДокументов.Ссылка КАК Состояние
	              |ИЗ
	              |	Справочник.СостоянияОригиналовПервичныхДокументов КАК СостоянияОригиналовПервичныхДокументов
	              |ГДЕ
	              |	НЕ СостоянияОригиналовПервичныхДокументов.ПометкаУдаления
	              |
	              |УПОРЯДОЧИТЬ ПО
	              |	СостоянияОригиналовПервичныхДокументов.РеквизитДопУпорядочивания" ;

	Выборка = Запрос.Выполнить();

	Возврат Выборка.Выгрузить().ВыгрузитьКолонку("Состояние");

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

// Выводит подключаемые команды в форме. Вызывается без подключения подсистемы "Подключаемые команды".
//
//	Параметры:
//  Форма - ФормаКлиентскогоПриложения - форма списка документа.
//  Список - ТаблицаФормы - основной список формы.
//  СостоянияОригиналов - ТаблицаЗначений - состояния оригинала, разрешенные пользователям, и используемые при смене
//                                          состояния оригинала:
//              * Наименование 	- Строка - наименование состояния оригинала;
//              * Ссылка		- СправочникСсылка.СостоянияОригиналовПервичныхДокументов - ссылка на элемент справочника СостоянияОригиналовПервичныхДокументов.
//


Процедура ЦентрМониторингаРегламентноеЗадание() Экспорт
	ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.СборИОтправкаСтатистики);

	НеобходимаЗаписьОценкиПроизводительности = Ложь;

	ОценкаПроизводительностиСуществует = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОценкаПроизводительности");
	Если ОценкаПроизводительностиСуществует Тогда
		МодульОценкаПроизводительности = ОбщегоНазначения.ОбщийМодуль("ОценкаПроизводительности");
		ВремяНачала = МодульОценкаПроизводительности.НачатьЗамерВремени();
	КонецЕсли;

	ДатаЗапуска = ТекущаяУниверсальнаяДата();
	ПараметрыЦентраМониторинга = Новый Структура();

	ПараметрыЦентраМониторинга.Вставить("ВключитьЦентрМониторинга");
	ПараметрыЦентраМониторинга.Вставить("ЦентрОбработкиИнформацииОПрограмме");
	ПараметрыЦентраМониторинга.Вставить("РегистрироватьДампы");
	ПараметрыЦентраМониторинга.Вставить("РегистрацияДамповСледующееФормирование");
	ПараметрыЦентраМониторинга.Вставить("РегистрацияДамповПериодФормирования");

	ПараметрыЦентраМониторинга.Вставить("РегистрироватьБизнесСтатистику");
	ПараметрыЦентраМониторинга.Вставить("БизнесСтатистикаСледующееФормирование");
	ПараметрыЦентраМониторинга.Вставить("БизнесСтатистикаПериодФормирования");

	ПараметрыЦентраМониторинга.Вставить("РегистрироватьСтатистикуКонфигурации");
	ПараметрыЦентраМониторинга.Вставить("РегистрироватьНастройкуКонфигурации");
	ПараметрыЦентраМониторинга.Вставить("СтатистикаКонфигурацииСледующееФормирование");
	ПараметрыЦентраМониторинга.Вставить("СтатистикаКонфигурацииПериодФормирования");

	ПараметрыЦентраМониторинга.Вставить("ОтправкаДанныхСледующееФормирование");
	ПараметрыЦентраМониторинга.Вставить("ОтправкаДанныхПериодФормирования");
	ПараметрыЦентраМониторинга.Вставить("ДатаОповещения");
	ПараметрыЦентраМониторинга.Вставить("ПринудительнаяОтправкаМинидампов");
	ПараметрыЦентраМониторинга.Вставить("ТаймаутОтветаПользователя");

	ПараметрыЦентраМониторинга = ПолучитьПараметрыЦентраМониторинга(ПараметрыЦентраМониторинга);

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

			ПараметрыЦентраМониторинга.РегистрацияДамповСледующееФормирование =
				ТекущаяУниверсальнаяДата() + ПараметрыЦентраМониторинга.РегистрацияДамповПериодФормирования;

			НеобходимаЗаписьОценкиПроизводительности = Истина;
		КонецЕсли;

		Если ПараметрыЦентраМониторинга.РегистрироватьБизнесСтатистику И ДатаЗапуска >= ПараметрыЦентраМониторинга.БизнесСтатистикаСледующееФормирование Тогда
			Попытка
				РегистрацияОперацийСтатистики();
			Исключение
				Комментарий = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
				ЗаписьЖурналаРегистрации(НСтр("ru = 'Центр мониторинга.Регистрация операций статистики'",
					ОбщегоНазначения.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
				ЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики("ЦентрМониторинга.РегистрацияОперацийСтатистики.Ошибка", 1, Комментарий);
			КонецПопытки;

			ПараметрыЦентраМониторинга.БизнесСтатистикаСледующееФормирование =
			ТекущаяУниверсальнаяДата()
			+ ПараметрыЦентраМониторинга.БизнесСтатистикаПериодФормирования;

			НеобходимаЗаписьОценкиПроизводительности = Истина;
		КонецЕсли;

		Если (ПараметрыЦентраМониторинга.РегистрироватьСтатистикуКонфигурации ИЛИ ПараметрыЦентраМониторинга.РегистрироватьНастройкуКонфигурации) И ДатаЗапуска >= ПараметрыЦентраМониторинга.СтатистикаКонфигурацииСледующееФормирование Тогда
			Попытка
				СобратьСтатистикуКонфигурации(Новый Структура("РегистрироватьСтатистикуКонфигурации, РегистрироватьНастройкуКонфигурации", ПараметрыЦентраМониторинга.РегистрироватьСтатистикуКонфигурации, ПараметрыЦентраМониторинга.РегистрироватьНастройкуКонфигурации));
			Исключение
				Комментарий = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
				ЗаписьЖурналаРегистрации(НСтр("ru = 'Центр мониторинга.Собрать статистику конфигурации'",
					ОбщегоНазначения.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
				ЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики("ЦентрМониторинга.СобратьСтатистикуКонфигурации.Ошибка", 1, Комментарий);
			КонецПопытки;

			ПараметрыЦентраМониторинга.СтатистикаКонфигурацииСледующееФормирование =
			ТекущаяУниверсальнаяДата()
			+ ПараметрыЦентраМониторинга.СтатистикаКонфигурацииПериодФормирования;

			НеобходимаЗаписьОценкиПроизводительности = Истина;
		КонецЕсли;

		Если ДатаЗапуска >= ПараметрыЦентраМониторинга.ОтправкаДанныхСледующееФормирование Тогда
			Попытка
				СформироватьПакетДляОтправки();
			Исключение
				Комментарий = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
				ЗаписьЖурналаРегистрации(НСтр("ru = 'Центр мониторинга.Сформировать пакет для отправки'",
					ОбщегоНазначения.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
				ЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики("ЦентрМониторинга.СформироватьПакетДляОтправки.Ошибка", 1, Комментарий);
			КонецПопытки;

			Попытка
				HTTPОтвет = ОтправитьДанныеМониторинга();
				Если HTTPОтвет.КодСостояния = 200 Тогда
					// Все хорошо.
				КонецЕсли;
			Исключение
				Комментарий = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
				ЗаписьЖурналаРегистрации(НСтр("ru = 'Центр мониторинга.Отправить данные мониторинга'",
					ОбщегоНазначения.КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Комментарий);
				ЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики("ЦентрМониторинга.ОтправитьДанныеМониторинга.Ошибка",
					1, Комментарий);
			КонецПопытки;

			ПараметрыЦентраМониторинга.ОтправкаДанныхСледующееФормирование = ТекущаяУниверсальнаяДата()
				+ ПолучитьПараметрыЦентраМониторинга("ОтправкаДанныхПериодФормирования");

			ПараметрыЦентраМониторинга.Удалить("РегистрацияДамповСледующееФормирование");
			ПараметрыЦентраМониторинга.Удалить("РегистрацияДамповПериодФормирования");

			ПараметрыЦентраМониторинга.Удалить("БизнесСтатистикаСледующееФормирование");
			ПараметрыЦентраМониторинга.Удалить("БизнесСтатистикаПериодФормирования");

			ПараметрыЦентраМониторинга.Удалить("СтатистикаКонфигурацииСледующееФормирование");
			ПараметрыЦентраМониторинга.Удалить("СтатистикаКонфигурацииПериодФормирования");

			НеобходимаЗаписьОценкиПроизводительности = Истина;

			// Установим дополнительные параметры обработки ошибок.
			УстановитьДополнительнуюИнформациюОбработкиОшибок();
		КонецЕсли;

		// Что бы не было записи параметров, которые установились при обработке ответа от сервиса,
		// то удалим эти параметры.
		ПараметрыЦентраМониторинга.Удалить("РегистрироватьДампы");
		ПараметрыЦентраМониторинга.Удалить("РегистрироватьБизнесСтатистику");
		ПараметрыЦентраМониторинга.Удалить("РегистрироватьСтатистикуКонфигурации");
		ПараметрыЦентраМониторинга.Удалить("РегистрироватьНастройкуКонфигурации");
		ПараметрыЦентраМониторинга.Удалить("ОтправкаДанныхПериодФормирования");

		УстановитьПараметрыЦентраМониторинга(ПараметрыЦентраМониторинга);
	Иначе
		УдалитьРегламентноеЗадание("СборИОтправкаСтатистики");
	КонецЕсли;

	// Убедимся, что отправка не запрещена, вариант дампа указан и срок сбора не вышел.
	ПараметрыЦентраМониторинга.Вставить("ОтправлятьФайлыДампов");
	ПараметрыЦентраМониторинга.Вставить("ВариантДампа");
	ПараметрыЦентраМониторинга.Вставить("ОкончаниеСбораДампов");

	ПараметрыЦентраМониторинга = ПолучитьПараметрыЦентраМониторинга(ПараметрыЦентраМониторинга);

	НачатьСборИОтправкуОтчетовОбОшибках = Не ПараметрыЦентраМониторинга.ОтправлятьФайлыДампов = 0
											И Не ПустаяСтрока(ПараметрыЦентраМониторинга.ВариантДампа)
											И ДатаЗапуска < ПараметрыЦентраМониторинга.ОкончаниеСбораДампов;
	Если НачатьСборИОтправкуОтчетовОбОшибках Тогда

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

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

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

#КонецОбласти

#Область РаботаСБизнесСтатистикой


Процедура ЗаполнитьОбщиеРеквизиты(ОбщиеРеквизиты) Экспорт

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

		Если ОбщиеРеквизиты.Получить("ЗаголовокСистемы") <> Неопределено Тогда
			ОбщиеРеквизиты["ЗаголовокСистемы"] = ИмяЭтойИнформационнойБазы();
		КонецЕсли;
		Если ОбщиеРеквизиты.Получить("АдресБазыВИнтернете") <> Неопределено Тогда
			ОбщиеРеквизиты["АдресБазыВИнтернете"] = ОбщегоНазначения.АдресПубликацииИнформационнойБазыВИнтернете();
		КонецЕсли;
		Если ОбщиеРеквизиты.Получить("АдресБазыВЛокальнойСети") <> Неопределено Тогда
			ОбщиеРеквизиты["АдресБазыВЛокальнойСети"] = ОбщегоНазначения.АдресПубликацииИнформационнойБазыВЛокальнойСети();
		КонецЕсли;

		Если ТипЗнч(ОбщиеРеквизиты.Получить("ТекущийПользователь")) = Тип("Соответствие") Тогда
			ТекущийПользователь = Пользователи.АвторизованныйПользователь();
			ЗаполнитьРеквизитыПоПредмету(ОбщиеРеквизиты.Получить("ТекущийПользователь"), ТекущийПользователь);
			ЗаполнитьРеквизитыСвойствИКонтактнойИнформации(ОбщиеРеквизиты.Получить("ТекущийПользователь"), ТекущийПользователь);
		КонецЕсли;

	КонецЕсли;

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

Процедура ЗаполнитьРеквизитыПоСКД(Реквизиты, Предмет, ПараметрыШаблона) Экспорт

	ИмяМакета = ПараметрыШаблона.Макет;

	ПараметрыЗапроса = Новый Массив;
	МетаданныеОбъекта = Предмет.Метаданные();
	ИмяОбъекта = МетаданныеОбъекта.Имя;
	МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(МетаданныеОбъекта.ПолноеИмя());
	МакетСКД = МенеджерОбъекта.ПолучитьМакет(ИмяМакета);

	АдресСхемы = ПоместитьВоВременноеХранилище(МакетСКД);
	КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
	КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы));
	ПараметрПериод = Новый ПараметрКомпоновкиДанных("Период");

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

	КомпоновщикНастроек.ЗагрузитьНастройки(МакетСКД.НастройкиПоУмолчанию);
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных();

	Для Каждого Реквизит Из Реквизиты Цикл
		ВыбранноеПоле = КомпоновщикНастроек.Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));

		ИмяПоля = Реквизит.Ключ;
		Если СтрЗаканчиваетсяНа(ИмяПоля, "}") И СтрНайти(ИмяПоля, "{") > 0 Тогда
			ИмяПоля = Лев(ИмяПоля, СтрНайти(ИмяПоля, "{") - 1);
		КонецЕсли;

		ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
	КонецЦикла;

	МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(МакетСКД, КомпоновщикНастроек.ПолучитьНастройки(),,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

	Если МакетКомпоновкиДанных.НаборыДанных.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	ТекстЗапросаМакет = МакетКомпоновкиДанных.НаборыДанных.Данные.Запрос;

	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапросаМакет;

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

		КонецЕсли;
	КонецЦикла;

	Если НезаполненныеПараметры.Количество() > 0 Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Не удалось сформировать сообщение, т.к. отсутствуют данные заполнения параметров: %1 для %2'"),
			СтрСоединить(НезаполненныеПараметры, ","), Строка(Предмет));
	КонецЕсли;

	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	Если РезультатЗапроса.Количество() > 0 Тогда
		РезультатЗапроса = СтрокаТаблицыЗначенийВСоответствие(РезультатЗапроса[0]);
		УстановитьПараметрыИзЗапроса(Реквизиты, РезультатЗапроса);
	КонецЕсли;

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

Процедура ЗаполнитьРеквизитыПоПредмету(Реквизиты, Предмет)

	МетаданныеОбъекта = Предмет.Метаданные();
	ПараметрыОснования = ОпределитьРеквизитыДляЗапросаПоМетаданным(Реквизиты, МетаданныеОбъекта);

	СписокРеквизитов = Сред(СписокПараметров(ПараметрыОснования), 3);
	Если ЗначениеЗаполнено(СписокРеквизитов) Тогда

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

	КонецЕсли;

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

Функция СтрокаТаблицыЗначенийВСоответствие(СтрокаТаблицыЗначений)

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

	Возврат Соответствие;

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

// Подставляет в шаблон значения параметров сообщения и формирует текст сообщения.
//
// Параметры:
//  ШаблонСтроки        - Строка
//  ВставляемыеЗначения - Соответствие
//  Префикс             - Строка
//
// Возвращаемое значение:
//   Строка
//

Функция ВставитьПараметрыВСтрокуСогласноТаблицеПараметров(Знач ШаблонСтроки, ВставляемыеЗначения, Знач Префикс = "") Экспорт

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

	Возврат Результат;

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

// Обрабатывает текст HTML для помещения в форматированный документ.
//


Процедура СохранитьДанныеВместеСПодписью(ОписаниеДанных, ОбработкаРезультата = Неопределено) Экспорт

	ЭлектроннаяПодписьСлужебныйКлиент.СохранитьДанныеВместеСПодписью(ОписаниеДанных, ОбработкаРезультата);

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

// Проверяет действительность подписи и сертификата.
// Сертификат всегда проверяется на сервере, если администратор
// настроил проверку электронных подписей на сервере.
//
// Параметры:
//   Оповещение           - ОписаниеОповещения - оповещение о результате выполнения следующих типов:
//             = Булево       - Истина, если проверка выполнена успешно - если ПараметрыПроверки - Неопределено
//             = Строка       - описание ошибки проверки подписи.
//             = Неопределено - не удалось получить менеджер криптографии (когда не указан).
//             = см. ЭлектроннаяПодписьКлиентСервер.РезультатПроверкиПодписи - если
//             ПараметрыПроверки.РезультатВВидеСтруктуры - Истина.
//   ИсходныеДанные       - ДвоичныеДанные - двоичные данные, которые были подписаны.
//                          Математическая проверка выполняется на стороне клиента, даже когда
//                          администратор настроил проверку электронных подписей на сервере,
//                          если указан менеджер криптографии или его удалось получить без ошибки.
//                          Это повышает производительность, а также безопасность, когда проверяется подпись
//                          в расшифрованном файле (он не будет передан на сервер).
//                        - Строка - адрес временного хранилища, содержащего исходные двоичные данные.
//                        - Структура:
//                           * КонвертXML       - Строка - подписанный КонвертXML,
//                                                         смотри также функцию КонвертXML.
//                           * ПараметрыXMLDSig - см. ЭлектроннаяПодписьКлиент.ПараметрыXMLDSig
//                        - Структура:
//                           * ПараметрыCMS - см. ЭлектроннаяПодписьКлиент.ПараметрыCMS
//                           * Данные  - Строка - произвольная строка для подписания,
//                                     - ДвоичныеДанные - двоичные данные для подписания.
//   Подпись              - ДвоичныеДанные - двоичные данные электронной подписи.
//                        - Строка         - адрес временного хранилища, содержащего двоичные данные.
//                        - Неопределено   - если ИсходныеДанные - конверт SOAP.
//   МенеджерКриптографии - Неопределено - получить менеджер криптографии по умолчанию
//                          (менеджер первой программы в списке, как настроил администратор).
//                        - МенеджерКриптографии - использовать указанный менеджер криптографии.
//   НаДату               - Дата - проверить сертификат на указанную дату,
//                          если дату не удалось извлечь из подписи или если проверяется КонвертXML.
//                          Если параметр не заполнен, тогда проверять на текущую дату сеанса,
//                          если дату не удалось извлечь из подписи или если проверяется КонвертXML.
//   ПараметрыПроверки    - см. ПараметрыПроверкиПодписи
//                        - Неопределено - показать ошибку создания менеджера криптографии (когда не указан).
//

Процедура ПроверитьПодпись(Оповещение, ИсходныеДанные, Подпись,
	МенеджерКриптографии = Неопределено,
	НаДату = Неопределено,
	ПараметрыПроверки = Неопределено) Экспорт

	ЭлектроннаяПодписьСлужебныйКлиент.ПроверитьПодпись(
		Оповещение, ИсходныеДанные, Подпись, МенеджерКриптографии, НаДату, ПараметрыПроверки);

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

// Конструктор параметра "ПараметрыПроверки" для процедуры "ПроверитьПодпись".
//
// Возвращаемое значение:
//  Структура:
//   * ПоказатьОшибкуСозданияМенеджераКриптографии - Булево - показать ошибку
//              создания менеджера криптографии (когда не указан).
//   * РезультатВВидеСтруктуры - Булево - если Истина, результат будет в виде
//      см. ЭлектроннаяПодписьКлиентСервер.РезультатПроверкиПодписи
//


Функция НастройкиСлужебнойУчетнойЗаписиДляУсовершенствованияПодписей(ИдентификаторФормы = Неопределено) Экспорт

	НастройкиСлужебнойУчетнойЗаписи = Новый Структура("СлужебнаяУчетнаяЗаписьDSS, Ошибка, ПараметрыПодписиCAdEST");

	МодульСервисКриптографииDSS = ОбщегоНазначения.ОбщийМодуль("СервисКриптографииDSS");
	НастройкиПодключения = МодульСервисКриптографииDSS.НастройкиПодключенияСлужебнойУчетнойЗаписи();

	Если НастройкиПодключения.Свойство("Ошибка")
		И ЗначениеЗаполнено(НастройкиПодключения.Ошибка) Тогда
		НастройкиСлужебнойУчетнойЗаписи.Ошибка = НастройкиПодключения.Ошибка;
		Возврат НастройкиСлужебнойУчетнойЗаписи;
	КонецЕсли;

	МодульСервисКриптографииDSSКлиентСервер = ОбщегоНазначения.ОбщийМодуль("СервисКриптографииDSSКлиентСервер");
	Результат = МодульСервисКриптографииDSS.АутентификацияПоЛогину(НастройкиПодключения.Результат);

	Если Результат.Выполнено Тогда
		АдресаСерверовМетокВремени = МодульСервисКриптографииDSSКлиентСервер.ПолучитьСервераШтамповВремени(
			Результат.НастройкиПользователя);

		Если АдресаСерверовМетокВремени.Количество() = 0 Тогда
			НастройкиСлужебнойУчетнойЗаписи.Ошибка =
				НСтр("ru = 'В служебной учетной записи нет доступных адресов серверов меток времени'");
			Возврат НастройкиСлужебнойУчетнойЗаписи;
		КонецЕсли;

		Если ИдентификаторФормы = Неопределено Тогда
			НастройкиСлужебнойУчетнойЗаписи.СлужебнаяУчетнаяЗаписьDSS = Результат.НастройкиПользователя;
		Иначе
			НастройкиСлужебнойУчетнойЗаписи.СлужебнаяУчетнаяЗаписьDSS =
				ПоместитьВоВременноеХранилище(Результат.НастройкиПользователя, ИдентификаторФормы);
		КонецЕсли;

	Иначе
		НастройкиСлужебнойУчетнойЗаписи.Ошибка = Результат.Ошибка;
		Возврат НастройкиСлужебнойУчетнойЗаписи;
	КонецЕсли;

	НастройкиСлужебнойУчетнойЗаписи.ПараметрыПодписиCAdEST =
		МодульСервисКриптографииDSSКлиентСервер.ПолучитьСвойствоПодписиCAdES(
			"T", Истина, Ложь, "Подпись", АдресаСерверовМетокВремени[0].Адрес);

	Возврат НастройкиСлужебнойУчетнойЗаписи;

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

// Только для внутреннего использования.

Функция УсовершенствоватьНаСторонеСервера(Параметры) Экспорт

	Результат = Новый Структура;
	Результат.Вставить("Успех", Ложь);
	Результат.Вставить("ТекстОшибки", "");
	Результат.Вставить("СвойстваПодписи", ЭлектроннаяПодписьКлиентСервер.НовыеСвойстваПодписи());
	Результат.Вставить("АлгоритмПодписи");
	Результат.Вставить("ОшибкаПриСозданииМенеджераКриптографии", Ложь);
	Результат.Вставить("ОперацияНачалась", Параметры.ОперацияНачалась);

	Подпись = Параметры.ЭлементДанныхДляСервера.Подпись;
	Если ТипЗнч(Подпись) = Тип("Строка") Тогда
		Попытка
			Подпись = ПолучитьИзВременногоХранилища(Подпись);
		Исключение
			ИнформацияОбОшибке = ИнформацияОбОшибке();
			Результат.ТекстОшибки = ЭлектроннаяПодписьСлужебныйКлиентСервер.ЗаголовокОшибкиПолученияДанных("ПродлениеСрокаДействияПодписи")
			 + Символы.ПС + ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
			Возврат Результат;
		КонецПопытки;
	КонецЕсли;

	АлгоритмПодписи = ЭлектроннаяПодписьСлужебныйКлиентСервер.АлгоритмСформированнойПодписи(Подпись);
	Результат.АлгоритмПодписи = АлгоритмПодписи;

	Если Параметры.ЭтоМодельСервисаСДоступнымУсовершенствованием Тогда

		ПараметрыВыполнения = Новый Структура;
		ПараметрыВыполнения.Вставить("ТипПодписи", Параметры.ТипПодписи);
		ПараметрыВыполнения.Вставить("ПараметрыПодписиCAdEST", Параметры.ПараметрыПодписиCAdEST);
		ПараметрыВыполнения.Вставить("СлужебнаяУчетнаяЗаписьDSS", Параметры.СлужебнаяУчетнаяЗаписьDSS);
		ПараметрыВыполнения.Вставить("ИгнорироватьСрокДействияСертификата", Параметры.ИгнорироватьСрокДействияСертификата);

		РезультатЗапроса = УсовершенствоватьПодписьВСервисе(Подпись, ПараметрыВыполнения);
		ЗаполнитьЗначенияСвойств(Результат, РезультатЗапроса);

		Если Результат.Успех Тогда
			Если Параметры.ЭлементДанныхДляСервера.Свойство("ПодписанныйОбъект") Тогда

				Результат.СвойстваПодписи.ПодписанныйОбъект = Параметры.ЭлементДанныхДляСервера.ПодписанныйОбъект;
				Результат.СвойстваПодписи.ПорядковыйНомер = Параметры.ЭлементДанныхДляСервера.ПорядковыйНомер;
				ПредставлениеОшибки = ОбновитьУсовершенствованнуюПодпись(Результат.СвойстваПодписи);

				Если ЗначениеЗаполнено(ПредставлениеОшибки) Тогда
					Результат.Успех = Ложь;
					Результат.ТекстОшибки = ПредставлениеОшибки;
					Возврат Результат;
				КонецЕсли;

				Если ЗначениеЗаполнено(Результат.СвойстваПодписи.Подпись) Тогда
					ЗарегистрироватьУсовершенствованиеПодписиВЖурнале(Результат.СвойстваПодписи);
				КонецЕсли;

			КонецЕсли;
		Иначе
			Возврат Результат;
		КонецЕсли;

		ПоместитьВоВременноеХранилище(ПараметрыВыполнения.СлужебнаяУчетнаяЗаписьDSS, Параметры.СлужебнаяУчетнаяЗаписьDSSАдрес);

	Иначе

		ПараметрыСоздания = ПараметрыСозданияМенеджераКриптографии();
		ПараметрыСоздания.ОписаниеОшибки = Новый Структура;
		ПараметрыСоздания.АлгоритмПодписи = АлгоритмПодписи;

		МенеджерКриптографии = МенеджерКриптографии("ПродлениеСрокаДействияПодписи", ПараметрыСоздания);

		Если МенеджерКриптографии = Неопределено Тогда
			Результат.ТекстОшибки = ПараметрыСоздания.ОписаниеОшибки;
			Результат.ОшибкаПриСозданииМенеджераКриптографии = Истина;
			Возврат Результат;
		КонецЕсли;

		МенеджерКриптографии.АдресаСерверовМетокВремени = ЭлектроннаяПодпись.ОбщиеНастройки().АдресаСерверовМетокВремени;

		ДополнительныеПараметры = Новый Структура;
		ДополнительныеПараметры.Вставить("МенеджерКриптографии", МенеджерКриптографии);
		ДополнительныеПараметры.Вставить("ИгнорироватьСрокДействияСертификата", Параметры.ИгнорироватьСрокДействияСертификата);

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

		ЗаполнитьЗначенияСвойств(Результат, РезультатЗапроса);

	КонецЕсли;

	Если Не Результат.Успех Тогда
		Возврат Результат;
	КонецЕсли;

	Результат.ОперацияНачалась = Истина;

	Возврат Результат;

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

////////////////////////////////////////////////////////////////////////////////
// Обновление информационной базы.

////////////////////////////////////////////////////////////////////////////////
// Работа с XMLDSig

// Подписывает сообщение, подставляя в КонвертXML данные подписи.
//
// Параметры:
//  КонвертXML             - см. ЭлектроннаяПодписьКлиент.КонвертXML
//  ПараметрыXMLDSig       - см. ЭлектроннаяПодписьКлиент.ПараметрыXMLDSig
//  СертификатКриптографии - СертификатКриптографии - используемый сертификат криптографии.
//  МенеджерКриптографии   - МенеджерКриптографии   - менеджер криптографии,
//                           который соответствует закрытому ключу сертификата с установленным паролем.
//
// Возвращаемое значение:
//  Строка - подписанный КонвертXML.
//


Процедура УсовершенствоватьНаСторонеЦиклПослеОперацииНаКлиенте(ДвоичныеДанные, Контекст) Экспорт

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

	ОписаниеОшибки = "";
	Если ЭлектроннаяПодписьСлужебныйКлиентСервер.ПустыеДанныеПодписи(ДвоичныеДанные, ОписаниеОшибки) Тогда
		Ошибка = ОписаниеОшибкиПриУсовершенствовании();
		Ошибка.Текст = ОписаниеОшибки;
		УсовершенствоватьНаСторонеПослеОшибки(Ошибка, Контекст);
		Возврат;
	КонецЕсли;

	Контекст.ОперацияНачалась = Истина;
	Контекст.ЭлементДанных.Вставить("СвойстваПодписи", Новый Структура("Подпись", ДвоичныеДанные));

	Оповещение = Новый ОписаниеОповещения("ВыполнитьПослеПолученияКонтейнераУсовершенствованнойПодписи", ЭтотОбъект, Контекст,
		"УсовершенствоватьНаСторонеЦиклПослеОшибкиОперацииНаКлиенте", ЭтотОбъект);
	Контекст.МенеджерКриптографии.НачатьПолучениеКонтейнераПодписейКриптографии(Оповещение, ДвоичныеДанные);

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

// Продолжение процедуры УсовершенствоватьНаСтороне.
Асинх Процедура ВыполнитьПослеПолученияКонтейнераУсовершенствованнойПодписи(КонтейнерПодписи, Контекст) Экспорт

	ДатаСеанса = ОбщегоНазначенияКлиент.ДатаСеанса();
	ДобавкаВремени = ДатаСеанса - ОбщегоНазначенияКлиент.ДатаУниверсальная();
	ПараметрыПодписи = Ждать ПараметрыПодписиКриптографии(
			КонтейнерПодписи, ДобавкаВремени, ДатаСеанса);

	Контекст.ЭлементДанных.Вставить("ПараметрыПодписи", ПараметрыПодписи);

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

		ВыполнитьНаСторонеЦиклПослеУсовершенствования(СвойстваПодписи, Контекст);
	КонецЕсли;

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

// Продолжение процедуры УсовершенствоватьНаСтороне.

Процедура ВыполнитьНаСторонеПослеУсовершенствованияИПроверкиСертификата(Результат, Контекст) Экспорт

	ПараметрыПодписи = Контекст.ЭлементДанных.ПараметрыПодписи;

	СвойстваПодписи = Новый Структура;
	СвойстваПодписи.Вставить("Подпись",             Контекст.ЭлементДанных.СвойстваПодписи.Подпись);
	СвойстваПодписи.Вставить("ТипПодписи",          ПараметрыПодписи.ТипПодписи);
	СвойстваПодписи.Вставить("СрокДействияПоследнейМеткиВремени", ПараметрыПодписи.СрокДействияПоследнейМеткиВремени);

	Если Результат = Истина Тогда
		ВыполнитьНаСторонеЦиклПослеУсовершенствования(СвойстваПодписи, Контекст);
	Иначе
		Ошибка = ОписаниеОшибкиПриУсовершенствовании();
		Ошибка.Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru='При проверке сертификата подписи после усовершенствования: %1
			|%2'"), Результат, СвойстваСертификатаСтрокой(ПараметрыПодписи.СертификатПоследнейМеткиВремени));
		УсовершенствоватьНаСторонеПослеОшибки(Ошибка, Контекст);
	КонецЕсли;

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

// Продолжение процедуры УсовершенствоватьНаСтороне.

Процедура УсовершенствоватьНаСторонеЦиклПослеОшибкиОперацииНаКлиенте(ИнформацияОбОшибке, СтандартнаяОбработка, Контекст) Экспорт

	СтандартнаяОбработка = Ложь;

	Ошибка = ОписаниеОшибкиПриУсовершенствовании();
	Ошибка.Текст = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
	УсовершенствоватьНаСторонеПослеОшибки(Ошибка, Контекст);

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

// Продолжение процедуры УсовершенствоватьНаСтороне.

Процедура ВыполнитьНаСторонеЦиклПослеУсовершенствования(СвойстваПодписи, Контекст)

	ЭлементДанных = Контекст.ЭлементыДанных[Контекст.Индекс];

	Если Контекст.НаСторонеКлиента Тогда

		НовыеСвойстваПодписи = ЭлектроннаяПодписьКлиентСервер.НовыеСвойстваПодписи();
		ОбновитьПодпись = Ложь;

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

		ЭлементДанных.Вставить("СвойстваПодписи", НовыеСвойстваПодписи);

		Если Не ЭлементДанных.Свойство("ПодписанныйОбъект") Тогда
			УсовершенствоватьНаСторонеЦиклНачало(Контекст);
			Возврат;
		КонецЕсли;

		Если ОбновитьПодпись Тогда
			ЭлементДанных.СвойстваПодписи.ПодписанныйОбъект = ЭлементДанных.ПодписанныйОбъект;
			ЭлементДанных.СвойстваПодписи.ПорядковыйНомер = ЭлементДанных.ПорядковыйНомер;

			ПредставлениеОшибки = ЭлектроннаяПодписьСлужебныйВызовСервера.ОбновитьУсовершенствованнуюПодпись(
				ЭлементДанных.СвойстваПодписи);

			Если ЗначениеЗаполнено(ПредставлениеОшибки) Тогда
				ЭлементДанных.Удалить("СвойстваПодписи");
				Ошибка = ОписаниеОшибкиПриУсовершенствовании();
				Ошибка.Текст = ПредставлениеОшибки;
				УсовершенствоватьНаСторонеПослеОшибки(Ошибка, Контекст);
				Возврат;
			КонецЕсли;

			Если ЗначениеЗаполнено(ЭлементДанных.СвойстваПодписи.Подпись) Тогда
				ЭлектроннаяПодписьСлужебныйВызовСервера.ЗарегистрироватьУсовершенствованиеПодписиВЖурнале(
					ЭлементДанных.СвойстваПодписи);
			КонецЕсли;
		КонецЕсли;

	Иначе

		ЭлементДанных.Вставить("СвойстваПодписи", СвойстваПодписи);

	КонецЕсли;

	ОповеститьОбИзменении(ЭлементДанных.ПодписанныйОбъект);
	УсовершенствоватьНаСторонеЦиклНачало(Контекст);

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

// Продолжение процедуры УсовершенствоватьНаСтороне.

Процедура УсовершенствоватьНаСторонеПослеОшибки(Ошибка, Контекст)

	Контекст.ЕстьОшибки = Истина;

	ЭлементДанных = Контекст.ЭлементыДанных[Контекст.Индекс];
	Если Не ЭлементДанных.Свойство("Ошибка") Тогда
		ЭлементДанных.Вставить("Ошибка", "");
	КонецЕсли;

	ТекстОшибки = Ошибка.Текст;
	Если Не Контекст.ПрерыватьОбработкуМассиваПриОшибке Тогда

		Если Ошибка.ОшибкаСозданияМенеджераКриптографии Тогда
			ОшибкиСозданияМенеджераКриптографии = Контекст.ОшибкиСозданияМенеджераКриптографии;
			Если ОшибкиСозданияМенеджераКриптографии.Найти(ТекстОшибки) = Неопределено Тогда
				ОшибкиСозданияМенеджераКриптографии.Добавить(ТекстОшибки);
			КонецЕсли;
		КонецЕсли;

		ЭлементДанных.Ошибка = ЭлементДанных.Ошибка + ?(ЭлементДанных.Ошибка <> "", Символы.ПС, "")
		+ ?(Ошибка.НаКлиенте, НСтр("ru='На компьютере:'"), НСтр("ru='На сервере:'")) + " "
		+ Ошибка.Текст;
	Иначе
		ЭлементДанных.Ошибка = ЭлементДанных.Ошибка + ?(ЭлементДанных.Ошибка <> "", Символы.ПС, "")
			+ ?(Ошибка.НаКлиенте, НСтр("ru='На компьютере:'"), НСтр("ru='На сервере:'")) + " "
			+ Ошибка.Текст;
	КонецЕсли;

	Если Контекст.ПрерыватьОбработкуМассиваПриОшибке Тогда
		УсовершенствоватьНаСторонеПослеЦикла(Контекст, ТекстОшибки);
	Иначе
		УсовершенствоватьНаСторонеЦиклНачало(Контекст);
	КонецЕсли;

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

// Для процедуры УсовершенствоватьНаСтороне.


Функция ВыгрузитьДанныеВXML(ИмяФайлаОбмена = "")

	КомпонентыОбмена = КомпонентыОбмена("Отправка");

	// Открываем файл обмена.
	ОбменДаннымиXDTOСервер.ОткрытьФайлВыгрузки(КомпонентыОбмена, ИмяФайлаОбмена);

	ЕстьВыгруженныеОбъекты      = Ложь;
	ЕстьОшибкиПередКонвертацией = Ложь;

	УстановитьПривилегированныйРежим(Истина);

	Попытка
		КомпонентыОбмена.МенеджерОбмена.ПередКонвертацией(КомпонентыОбмена);
	Исключение
		ЕстьОшибкиПередКонвертацией = Истина;
		ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Событие: %1.
				|Обработчик: ПередКонвертацией.
				|
				|Ошибка выполнения обработчика.
				|%2.'"),
			КомпонентыОбмена.НаправлениеОбмена,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ОбменДаннымиXDTOСервер.ЗаписатьВПротоколВыполнения(КомпонентыОбмена, ТекстОшибки);
	КонецПопытки;

	Если ЗначениеЗаполнено(УзелОбмена)
		И Не ЕстьОшибкиПередКонвертацией Тогда

		СоставПланаОбмена = УзелОбмена.Метаданные().Состав;

		// Внутреннее соединение с основной таблицей необходимо для исключения из выгрузки битых ссылок.
		ШаблонТекстаЗапроса =
		"ВЫБРАТЬ
		|	ТаблицаИзменений.Ссылка
		|ИЗ
		|	&ПолноеИмяТаблицыМетаданныхИзменения КАК ТаблицаИзменений
		|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ПолноеИмяТаблицыМетаданных КАК ОсновнаяТаблица
		|		ПО ОсновнаяТаблица.Ссылка = ТаблицаИзменений.Ссылка
		|ГДЕ ТаблицаИзменений.Узел = &Узел";

		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("Узел", УзелОбмена);

		Для Каждого ЭлементСостава Из СоставПланаОбмена Цикл

			Если Не ОбщегоНазначения.ЭтоОбъектСсылочногоТипа(ЭлементСостава.Метаданные) Тогда

				Продолжить;

			КонецЕсли;

			ПолноеИмяОбъекта = ЭлементСостава.Метаданные.ПолноеИмя();
			ПравилоОбработки = КомпонентыОбмена.ПравилаОбработкиДанных.Найти(ЭлементСостава.Метаданные, "ОбъектВыборкиМетаданные");
			Если ПравилоОбработки = Неопределено Тогда

				Продолжить;

			КонецЕсли;

			ПолноеИмяОбъектаИзменения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку("%1.Изменения", ПолноеИмяОбъекта);
			ТекстЗапроса = СтрЗаменить(ШаблонТекстаЗапроса, "&ПолноеИмяТаблицыМетаданныхИзменения", ПолноеИмяОбъектаИзменения);
			Запрос.Текст = СтрЗаменить(ТекстЗапроса, "&ПолноеИмяТаблицыМетаданных", ПолноеИмяОбъекта);

			Выборка = Запрос.Выполнить().Выбрать();
			Пока Выборка.Следующий() Цикл
				ОбменДаннымиXDTOСервер.ВыгрузкаОбъектаВыборки(КомпонентыОбмена, Выборка.Ссылка.ПолучитьОбъект(), ПравилоОбработки);
				ЕстьВыгруженныеОбъекты = ЕстьВыгруженныеОбъекты Или Не КомпонентыОбмена.ФлагОшибки;
			КонецЦикла;
		КонецЦикла;
	КонецЕсли;

	Если СписокДополнениеКВыгрузке.Количество() > 0 Тогда

		СобытиеНачало = НСтр("ru='ВыгрузкаЗагрузкаEnterpriseData.Начало'", ОбщегоНазначения.КодОсновногоЯзыка());
		СобытиеОкончание = НСтр("ru='ВыгрузкаЗагрузкаEnterpriseData.Окончание'", ОбщегоНазначения.КодОсновногоЯзыка());

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

	Если Не ЕстьОшибкиПередКонвертацией Тогда
		Попытка
			КомпонентыОбмена.МенеджерОбмена.ПослеКонвертации(КомпонентыОбмена);
		Исключение
			ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Событие: %1.
					|Обработчик: ПослеКонвертации.
					|
					|Ошибка выполнения обработчика.
					|%2.'"),
				КомпонентыОбмена.НаправлениеОбмена,
				ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
			ОбменДаннымиXDTOСервер.ЗаписатьВПротоколВыполнения(КомпонентыОбмена, ТекстОшибки);
		КонецПопытки;
	КонецЕсли;

	УстановитьПривилегированныйРежим(Ложь);

	КомпонентыОбмена.ФайлОбмена.ЗаписатьКонецЭлемента(); // Body
	КомпонентыОбмена.ФайлОбмена.ЗаписатьКонецЭлемента(); // Message
	КомпонентыОбмена.ФайлОбмена.Закрыть();

	РезультатВыгрузки = Новый Структура;
	РезультатВыгрузки.Вставить("ЕстьВыгруженныеОбъекты",     ЕстьВыгруженныеОбъекты);
	РезультатВыгрузки.Вставить("ЕстьОшибки",                 КомпонентыОбмена.ФлагОшибки);
	РезультатВыгрузки.Вставить("ТекстОшибки",                КомпонентыОбмена.СтрокаСообщенияОбОшибке);
	РезультатВыгрузки.Вставить("ВыгруженныеОбъекты",         КомпонентыОбмена.ВыгруженныеОбъекты);
	РезультатВыгрузки.Вставить("ВыгруженныеПоСсылкеОбъекты", КомпонентыОбмена.ВыгруженныеПоСсылкеОбъекты);

	Возврат РезультатВыгрузки;

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

// Выполняет загрузку сообщения.
// Параметры:
//   СтруктураПараметров - Структура:
//    * ТекстXML - Строка - сообщение которое следует загрузить (в случае загрузки из текста).
//    * АдресНаСервере - Строка - имя временного файла с данными для загрузки (при загрузке из файла)
//   АдресРезультата - Строка - адрес для размещения результата, при запуске из фонового задания.
//

Процедура ЗагрузкаСообщения(СтруктураПараметров, АдресРезультата) Экспорт

	ЧтениеXML = Новый ЧтениеXML;

	Если СтруктураПараметров.Свойство("ЭтоФоновоеЗадание") Тогда

		ЗаполнитьЗначенияСвойств(ЭтотОбъект, СтруктураПараметров);

	КонецЕсли;

	АдресНаСервере = "";
	Если СтруктураПараметров.Свойство("АдресНаСервере", АдресНаСервере) Тогда

		ЧтениеXML.ОткрытьФайл(СтруктураПараметров.АдресНаСервере);

	Иначе

		ЧтениеXML.УстановитьСтроку(СтруктураПараметров.ТекстXML);

	КонецЕсли;

	РезультатЗагрузки = ЗагрузитьДанныеИзXML(ЧтениеXML);
	ЧтениеXML.Закрыть();

	Попытка

		Если ЗначениеЗаполнено(АдресНаСервере) Тогда

			УдалитьФайлы(АдресНаСервере);

		КонецЕсли;

	Исключение

		СобытиеЖурнала = ОбменДаннымиСервер.СобытиеЖурналаРегистрацииОбменДанными();
		ОписаниеОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());

		ЗаписьЖурналаРегистрации(СобытиеЖурнала, УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки);

	КонецПопытки;

	Если РезультатЗагрузки.ЕстьОшибки Тогда

		ВызватьИсключение РезультатЗагрузки.ТекстОшибки;

	КонецЕсли;

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

// Загружает данные из сообщения обмена.
//
// Параметры:
//  ЧтениеXML	 - ЧтениеXML - инициализированный сообщением обмена объект ЧтениеXML.
//
// Возвращаемое значение:
//   Структура:
//    * ЕстьОшибки - Булево - признак, что во время загрузки сообщения обмена возникли ошибки.
//    * ТекстОшибки - Строка - текст сообщения об ошибке.
//    * ЗагруженныеОбъекты - Массив - массив загруженных объектов.
//


Процедура ОткрытьXMLНаСервере()
	ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайлаЗагрузки); // ДвоичныеДанные
	АдресНаСервере = ПолучитьИмяВременногоФайла("xml");
	ДвоичныеДанные.Записать(АдресНаСервере);
	ТХ = Новый ТекстовыйДокумент;
	ТХ.Прочитать(АдресНаСервере);
	ДанныеДляЗагрузкиXDTO = ТХ.ПолучитьТекст();
	УдалитьФайлы(АдресНаСервере);
КонецПроцедуры

&НаСервере

Функция СохранитьНастройкиВыгрузкиНаСервере()
	ДополнитьДанныеОтбораПриНеобходимости();
	ИмяВремФайла = ПолучитьИмяВременногоФайла("xml");

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.ОткрытьФайл(ИмяВремФайла);
	ЗаписьXML.ЗаписатьОбъявлениеXML();
	ЗаписьXML.ЗаписатьНачалоЭлемента("Objects");
	Если ЗначениеЗаполнено(Объект.ПериодОтбораВсехДокументов) Тогда
		ЗаписьXML.ЗаписатьНачалоЭлемента("Period");
		ЗаписьXML.ЗаписатьАтрибут("Beg", XMLСтрока(Объект.ПериодОтбораВсехДокументов.ДатаНачала));
		ЗаписьXML.ЗаписатьАтрибут("End", XMLСтрока(Объект.ПериодОтбораВсехДокументов.ДатаОкончания));
		ЗаписьXML.ЗаписатьКонецЭлемента(); //Period
	КонецЕсли;
	Для Каждого Стр Из Объект.ДополнительнаяРегистрация Цикл
		ЗаписьXML.ЗаписатьНачалоЭлемента("Object");
		ЗаписьXML.ЗаписатьАтрибут("Type", XMLСтрока(Стр.ПолноеИмяМетаданных));
		Если Стр.ВыборПериода Тогда
			ЗаписьXML.ЗаписатьАтрибут("Sel_Period", XMLСтрока(Стр.ВыборПериода));
			Если ЗначениеЗаполнено(Стр.Период) Тогда
				ЗаписьXML.ЗаписатьАтрибут("Beg_Period", XMLСтрока(Стр.Период.ДатаНачала));
				ЗаписьXML.ЗаписатьАтрибут("End_Period", XMLСтрока(Стр.Период.ДатаОкончания));
			КонецЕсли;
		КонецЕсли;
		ЗаписьXML.ЗаписатьАтрибут("F_String", XMLСтрока(Стр.ОтборСтрокой));
		Если Стр.Отбор.Элементы.Количество() > 0 Тогда

			Для Каждого ЭлементОтбора Из Стр.Отбор.Элементы Цикл
				ЗаписьXML.ЗаписатьНачалоЭлемента("Filter");
				ЗаписьXML.ЗаписатьАтрибут("Comp", XMLСтрока(СокрЛП(ЭлементОтбора.ВидСравнения)));
				ЗаписьXML.ЗаписатьАтрибут("Present", XMLСтрока(СокрЛП(ЭлементОтбора.Представление)));

				Если ЗначениеЗаполнено(ЭлементОтбора.ЛевоеЗначение) Тогда
					ЗаписатьЗначениеОтбора(ЭлементОтбора.ЛевоеЗначение, "_L", ЗаписьXML)
				КонецЕсли;

				Если ЗначениеЗаполнено(ЭлементОтбора.ПравоеЗначение) Тогда

					Если ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("СписокЗначений") Тогда

						ЗаписатьМножественноеЗначениеОтбора(ЭлементОтбора.ПравоеЗначение, "_R", ЗаписьXML)

					Иначе

						ЗаписатьЗначениеОтбора(ЭлементОтбора.ПравоеЗначение, "_R", ЗаписьXML)

					КонецЕсли;

				КонецЕсли;

				ЗаписьXML.ЗаписатьКонецЭлемента();//Filter
			КонецЦикла;

		КонецЕсли;
		ЗаписьXML.ЗаписатьКонецЭлемента(); //Object
	КонецЦикла;
	ЗаписьXML.ЗаписатьКонецЭлемента(); //Objects
	ЗаписьXML.Закрыть();
	АдресВХранилище = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВремФайла));
	УдалитьФайлы(ИмяВремФайла);
	Возврат АдресВХранилище;
КонецФункции

&НаСервере

Процедура ЗаписатьМножественноеЗначениеОтбора(Знач ЭлементОтбора_Значение, Постфикс, ЗаписьXML)

	ЗаписьXML.ЗаписатьАтрибут("Type" + Постфикс,  Строка(ТипЗнч(ЭлементОтбора_Значение)));

	Для Каждого ЭлементСпискаЗначений Из ЭлементОтбора_Значение Цикл

		ЗаписьXML.ЗаписатьНачалоЭлемента("Array");
		ЗаписатьЗначениеОтбора(ЭлементСпискаЗначений.Значение, Постфикс, ЗаписьXML);
		ЗаписьXML.ЗаписатьКонецЭлемента();

	КонецЦикла;

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

&НаСервере

Процедура ЗаписатьЗначениеОтбора(Знач ЭлементОтбора_Значение, Постфикс, ЗаписьXML)
	ТипДанных = ТипЗнч(ЭлементОтбора_Значение);
	ОбъектМетаданных =  Метаданные.НайтиПоТипу(ТипДанных);

	Если ОбъектМетаданных <> Неопределено Тогда
		ЗаписьXML.ЗаписатьАтрибут("Type" + Постфикс,  ОбъектМетаданных.ПолноеИмя());
	Иначе
		ЗаписьXML.ЗаписатьАтрибут("Type" + Постфикс,  Строка(ТипДанных));
	КонецЕсли;
	Если XMLТип(ТипДанных) <> Неопределено Тогда
		ЗаписьXML.ЗаписатьАтрибут("Val" + Постфикс, XMLСтрока(ЭлементОтбора_Значение));
	Иначе
		ЗаписьXML.ЗаписатьАтрибут("Val" + Постфикс, XMLСтрока(Строка(ЭлементОтбора_Значение)));
	КонецЕсли;

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

&НаКлиенте

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

&НаСервере

Процедура ОбновитьПравилаВыгрузкиНаСервере()

	Элементы.РасширениеФормата.СписокВыбора.Очистить();
	Элементы.РасширениеФормата.СписокВыбора.Добавить("", НСтр("ru = '<без расширения>'"));
	Для Каждого Расширение Из РасширенияФормата.НайтиСтроки(Новый Структура("БазоваяВерсия", Объект.ВерсияФормата)) Цикл
		Элементы.РасширениеФормата.СписокВыбора.Добавить(Расширение.ПространствоИмен);
	КонецЦикла;

	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	ОбработкаОбъект.ЗаполнениеПравилВыгрузки();
	ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");
КонецПроцедуры

&НаСервере

Процедура ОбновитьПравилаЗагрузкиНаСервере()

	Элементы.РасширениеФорматаЗагрузка.СписокВыбора.Очистить();
	Элементы.РасширениеФорматаЗагрузка.СписокВыбора.Добавить("", НСтр("ru = '<без расширения>'"));
	Для Каждого Расширение Из РасширенияФормата.НайтиСтроки(Новый Структура("БазоваяВерсия", Объект.ВерсияФормата)) Цикл

		Элементы.РасширениеФорматаЗагрузка.СписокВыбора.Добавить(Расширение.ПространствоИмен);

	КонецЦикла;

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

&НаСервере

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

&НаСервере

Функция ПредставлениеОтбора(Период, Отбор)
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	Возврат ОбработкаОбъект.ПредставлениеОтбора(Период, Отбор);
КонецФункции

&НаСервере


Процедура ПередВыгрузкойДанных(Контейнер) Экспорт

	ТекущийИдентификаторНеуказанногоПользователя = ПользователиСлужебный.СоздатьНеуказанногоПользователя().УникальныйИдентификатор();

	ИмяФайла = Контейнер.СоздатьПроизвольныйФайл("xml", ТипДанныхДляВыгрузкиИдентификатораНеуказанногоПользователя());
	ЗаписатьОбъектВФайл(ТекущийИдентификаторНеуказанногоПользователя, ИмяФайла);

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

// Вызывается перед выгрузкой объекта.
// см. "ПриРегистрацииОбработчиковВыгрузкиДанных".
//
// Параметры:
//  Контейнер - ОбработкаОбъект.ВыгрузкаЗагрузкаДанныхМенеджерКонтейнера
//  МенеджерВыгрузкиОбъекта - ОбработкаОбъект.ВыгрузкаЗагрузкаДанныхМенеджерВыгрузкиДанныхИнформационнойБазы
//  Сериализатор - СериализаторXDTO
//  Объект - КонстантаМенеджерЗначения
//         - СправочникОбъект
//         - ДокументОбъект
//         - БизнесПроцессОбъект
//         - ЗадачаОбъект
//         - ПланСчетовОбъект
//         - ПланОбменаОбъект
//         - ПланВидовХарактеристикОбъект
//         - ПланВидовРасчетаОбъект
//         - РегистрСведенийНаборЗаписей
//         - РегистрНакопленияНаборЗаписей
//         - РегистрБухгалтерииНаборЗаписей
//         - РегистрРасчетаНаборЗаписей
//         - ПоследовательностьНаборЗаписей
//         - ПерерасчетНаборЗаписей
//  Артефакты - Массив
//  Отказ - Булево
//

Процедура ПередВыгрузкойОбъекта(Контейнер, МенеджерВыгрузкиОбъекта, Сериализатор, Объект, Артефакты, Отказ) Экспорт

	Если ТипЗнч(Объект) <> Тип("СправочникОбъект.Пользователи") Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Объект метаданных %1 не может быть обработан обработчиком %2.'"),
			Объект.Метаданные().ПолноеИмя(),
			"ВыгрузкаЗагрузкаДанныхСверткаСсылокНаПользователейВРазделенныхДанных.ПередВыгрузкойОбъекта");
	КонецЕсли;

	Если Объект.Ссылка.УникальныйИдентификатор() = ТекущийИдентификаторНеуказанногоПользователя Тогда

		НовыйАртефакт = ФабрикаXDTO.Создать(ТипАртефактНеуказанногоПользователя());
		Артефакты.Добавить(НовыйАртефакт);

	ИначеЕсли ПользователиСлужебныйВМоделиСервиса.ПользовательЗарегистрированКакНеразделенный(Объект.ИдентификаторПользователяИБ) Тогда

		НовыйАртефакт = ФабрикаXDTO.Создать(ТипАртефактНеразделенногоПользователя());
		НовыйАртефакт.UserName = ВнутреннееИмяНеразделенногоПользователя(Объект.ИдентификаторПользователяИБ);
		Артефакты.Добавить(НовыйАртефакт);

	КонецЕсли;

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

Процедура ПослеВыгрузкиОбъекта(Контейнер, МенеджерВыгрузкиОбъекта, Сериализатор, Объект, Артефакты) Экспорт

	Если ТипЗнч(Объект) <> Тип("СправочникОбъект.Пользователи") Тогда
		ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Объект метаданных %1 не может быть обработан обработчиком %2.'"),
			Объект.Метаданные().ПолноеИмя(),
			"ВыгрузкаЗагрузкаДанныхСверткаСсылокНаПользователейВРазделенныхДанных.ПослеВыгрузкиОбъекта");
	КонецЕсли;

	Если Объект.Ссылка.УникальныйИдентификатор() <> ТекущийИдентификаторНеуказанногоПользователя Тогда

		ЭтоСсылкаНеразделенногоПользователя = ПользователиСлужебныйВМоделиСервиса.ПользовательЗарегистрированКакНеразделенный(
			Объект.ИдентификаторПользователяИБ);

		ЕстественныйКлюч = Новый Структура("Неразделенный", ЭтоСсылкаНеразделенногоПользователя);
		МенеджерВыгрузкиОбъекта.ТребуетсяСопоставитьСсылкуПриЗагрузке(Объект.Ссылка, ЕстественныйКлюч);

	КонецЕсли;

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

#КонецОбласти

#Область ОбработчикиЗагрузкиДанных

// Вызывается перед загрузкой данных.
//
// Параметры:
//  Контейнер - ОбработкаОбъект.ВыгрузкаЗагрузкаДанныхМенеджерКонтейнера - менеджер
//    контейнера, используемый в процессе загрузки данных. Подробнее см. комментарий
//    к программному интерфейсу обработки ВыгрузкаЗагрузкаДанныхМенеджерКонтейнера.
//

Процедура ПередЗагрузкойДанных(Контейнер) Экспорт

	ТекущийИдентификаторНеуказанногоПользователя = ПользователиСлужебный.СоздатьНеуказанногоПользователя().УникальныйИдентификатор();

	ИмяФайла = Контейнер.ПолучитьПроизвольныйФайл(ТипДанныхДляВыгрузкиИдентификатораНеуказанногоПользователя());
	ИсходныйИдентификаторНеуказанногоПользователя = ПрочитатьОбъектИзФайла(ИмяФайла);

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

Процедура ПередСопоставлениемСсылок(Контейнер, ОбъектМетаданных, ТаблицаИсходныхСсылок, СтандартнаяОбработка, Отказ) Экспорт

	Если ОбъектМетаданных = Метаданные.Справочники.Пользователи Тогда

		СтандартнаяОбработка = Ложь;

	Иначе

		ВызватьИсключение НСтр("ru = 'Тип данных указан неверно'");

	КонецЕсли;

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

Функция СопоставитьСсылки(Контейнер, МенеджерСопоставленияСсылок, ТаблицаИсходныхСсылок) Экспорт

	ИмяКолонки = МенеджерСопоставленияСсылок.ИмяКолонкиИсходныхСсылок();

	Результат = Новый ТаблицаЗначений();
	Результат.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("СправочникСсылка.Пользователи"));
	Результат.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("СправочникСсылка.Пользователи"));

	СопоставлениеНеуказанногоПользователя = Результат.Добавить();
	СопоставлениеНеуказанногоПользователя[ИмяКолонки] =
		Справочники.Пользователи.ПолучитьСсылку(ИсходныйИдентификаторНеуказанногоПользователя);
	СопоставлениеНеуказанногоПользователя.Ссылка =
		Справочники.Пользователи.ПолучитьСсылку(ТекущийИдентификаторНеуказанногоПользователя);

	ОбъединитьНеразделенныхПользователей = Ложь;
	ОбъединитьРазделенныхПользователей = Ложь;

	Если ОбщегоНазначения.РазделениеВключено() Тогда

		Если Контейнер.ПараметрыЗагрузки().Свойство("СвернутьРазделенныхПользователей") Тогда
			ОбъединитьРазделенныхПользователей = Контейнер.ПараметрыЗагрузки().СвернутьРазделенныхПользователей;
		Иначе
			ОбъединитьРазделенныхПользователей = Ложь;
		КонецЕсли;

	Иначе
		ОбъединитьНеразделенныхПользователей = Истина;
		ОбъединитьРазделенныхПользователей = Ложь;
	КонецЕсли;

	Для Каждого СтрокаТаблицыИсходныхСсылок Из ТаблицаИсходныхСсылок Цикл

		Если СтрокаТаблицыИсходныхСсылок.Неразделенный Тогда

			Если ОбъединитьНеразделенныхПользователей Тогда

				СопоставлениеПользователя = Результат.Добавить();
				СопоставлениеПользователя[ИмяКолонки] = СтрокаТаблицыИсходныхСсылок[ИмяКолонки];
				СопоставлениеПользователя.Ссылка =
					Справочники.Пользователи.ПолучитьСсылку(ТекущийИдентификаторНеуказанногоПользователя);

			КонецЕсли;

		Иначе

			Если ОбъединитьРазделенныхПользователей Тогда

				СопоставлениеПользователя = Результат.Добавить();
				СопоставлениеПользователя[ИмяКолонки] = СтрокаТаблицыИсходныхСсылок[ИмяКолонки];
				СопоставлениеПользователя.Ссылка =
					Справочники.Пользователи.ПолучитьСсылку(ТекущийИдентификаторНеуказанногоПользователя);

			КонецЕсли;

		КонецЕсли;

	КонецЦикла;

	Возврат Результат;

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

// Выполняет обработчики перед загрузкой определенного типа данных.
//
// Параметры:
//  Контейнер - ОбработкаОбъект.ВыгрузкаЗагрузкаДанныхМенеджерКонтейнера - менеджер
//		контейнера, используемый в процессе выгрузи данных. Подробнее см. комментарий
//		к программному интерфейсу обработки ВыгрузкаЗагрузкаДанныхМенеджерКонтейнера.
//  ОбъектМетаданных - ОбъектМетаданных - объект метаданных.
//  Отказ - Булево - признак выполнения данной операции.
//

Процедура ПередЗагрузкойТипа(Контейнер, ОбъектМетаданных, Отказ) Экспорт

	Если ПользователиСлужебныйВМоделиСервисаПовтИсп.СписокНаборовЗаписейСоСсылкамиНаПользователей().Получить(ОбъектМетаданных) <> Неопределено Тогда

		СохраненныеСсылкиНаНеуказанногоПользователя = Новый ТаблицаЗначений();

		Для Каждого Измерение Из ОбъектМетаданных.Измерения Цикл

			СохраненныеСсылкиНаНеуказанногоПользователя.Колонки.Добавить(Измерение.Имя, Измерение.Тип);

		КонецЦикла;

	Иначе

		СохраненныеСсылкиНаНеуказанногоПользователя = Неопределено;

	КонецЕсли;

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


Функция СтроковоеПредставлениеТипа(Тип)

	Представление = "";

	Если ЭтоСсылка(Тип) Тогда

		ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
		ИмяОбъекта = СтрРазделить(ПолноеИмя, ".")[1];

		Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "СправочникСсылка";

		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ДокументСсылка";

		ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "БизнесПроцессСсылка";

		ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовХарактеристикСсылка";

		ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланСчетовСсылка";

		ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланВидовРасчетаСсылка";

		ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ЗадачаСсылка";

		ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПланОбменаСсылка";

		ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда
			Представление = "ПеречислениеСсылка";

		КонецЕсли;

		Результат = ?(Представление = "", Представление, Представление + "." + ИмяОбъекта);

	ИначеЕсли Тип = Тип("Неопределено") Тогда

		Результат = "Неопределено";

	ИначеЕсли Тип = Тип("Строка") Тогда
		Результат = "Строка";

	ИначеЕсли Тип = Тип("Число") Тогда
		Результат = "Число";

	ИначеЕсли Тип = Тип("Булево") Тогда
		Результат = "Булево";

	ИначеЕсли Тип = Тип("Дата") Тогда
		Результат = "Дата";

	Иначе

		Результат = Строка(Тип);

	КонецЕсли;

	Возврат Результат;

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

//	Преобразует таблицу значений в массив.
//	Может использоваться для передачи на клиента данных, полученных
//	на сервере в виде таблицы значений в том случае, если таблица
//	значений содержит только такие значения, которые могут
//  быть переданы на клиента.
//
//	Полученный массив содержит структуры, каждая из которых повторяет
//	структуру колонок таблицы значений.
//
//	Не рекомендуется использовать для преобразования таблиц значений
//	с большим количеством строк.
//
//	Параметры:
//    ТаблицаЗначений - ТаблицаЗначений
//
//	Возвращаемое значение:
//    Массив
//
&НаСервереБезКонтекста

Функция ТаблицаЗначенийВМассив(ТаблицаЗначений)

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

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

// Форматирует строку в соответствии с заданным шаблоном.
// Возможные значения тегов выделения:
//	 Строка  - выделяет строку жирным шрифтом.
//	 Строка
//
// Пример:
//	Минимальная версия программы 1.1. Обновите программу.
//
// Возвращаемое значение:
//  ФорматированнаяСтрока
//
&НаСервереБезКонтекста

Функция ФорматированнаяСтрока(Знач Строка)

	СтрокиСВыделением = Новый СписокЗначений;
	Пока СтрНайти(Строка, "") <> 0 Цикл
		НачалоВыделения = СтрНайти(Строка, "");
		СтрокаДоОткрывающегоТега = Лев(Строка, НачалоВыделения - 1);
		СтрокиСВыделением.Добавить(СтрокаДоОткрывающегоТега);
		СтрокаПослеОткрывающегоТега = Сред(Строка, НачалоВыделения + 3);
		КонецВыделения = СтрНайти(СтрокаПослеОткрывающегоТега, "");
		ВыделенныйФрагмент = Лев(СтрокаПослеОткрывающегоТега, КонецВыделения - 1);
		СтрокиСВыделением.Добавить(ВыделенныйФрагмент,, Истина);
		СтрокаПослеВыделения = Сред(СтрокаПослеОткрывающегоТега, КонецВыделения + 4);
		Строка = СтрокаПослеВыделения;
	КонецЦикла;
	СтрокиСВыделением.Добавить(Строка);

	СтрокиСоСсылками = Новый СписокЗначений;
	Для Каждого ЧастьСтроки Из СтрокиСВыделением Цикл

		Строка = ЧастьСтроки.Значение;

		Если ЧастьСтроки.Пометка Тогда
			СтрокиСоСсылками.Добавить(Строка,, Истина);
			Продолжить;
		КонецЕсли;

		НачалоВыделения = СтрНайти(Строка, "<a href = ");
		Пока НачалоВыделения <> 0 Цикл
			СтрокаДоОткрывающегоТега = Лев(Строка, НачалоВыделения - 1);
			СтрокиСоСсылками.Добавить(СтрокаДоОткрывающегоТега, );

			СтрокаПослеОткрывающегоТега = Сред(Строка, НачалоВыделения + 9);
			ЗакрывающийТег = СтрНайти(СтрокаПослеОткрывающегоТега, ">");

			Ссылка = СокрЛП(Лев(СтрокаПослеОткрывающегоТега, ЗакрывающийТег - 2));
			Если СтрНачинаетсяС(Ссылка, """") Тогда
				Ссылка = Сред(Ссылка, 2, СтрДлина(Ссылка) - 1);
			КонецЕсли;
			Если СтрЗаканчиваетсяНа(Ссылка, """") Тогда
				Ссылка = Сред(Ссылка, 1, СтрДлина(Ссылка) - 1);
			КонецЕсли;

			СтрокаПослеСсылки = Сред(СтрокаПослеОткрывающегоТега, ЗакрывающийТег + 1);
			КонецВыделения = СтрНайти(СтрокаПослеСсылки, "");
			ТекстСсылки = Лев(СтрокаПослеСсылки, КонецВыделения - 1);
			СтрокиСоСсылками.Добавить(ТекстСсылки, Ссылка);

			СтрокаПослеВыделения = Сред(СтрокаПослеСсылки, КонецВыделения + 4);
			Строка = СтрокаПослеВыделения;

			НачалоВыделения = СтрНайти(Строка, "<a href = ");
		КонецЦикла;
		СтрокиСоСсылками.Добавить(Строка);

	КонецЦикла;

	МассивСтроки = Новый Массив;
	Для Каждого ЧастьСтроки Из СтрокиСоСсылками Цикл

		Если ЧастьСтроки.Пометка Тогда
			//@skip-check new-font
			МассивСтроки.Добавить(Новый ФорматированнаяСтрока(ЧастьСтроки.Значение, Новый Шрифт(,,Истина))); // АПК:1345 - автономная обработка не может использовать стили
		ИначеЕсли Не ПустаяСтрока(ЧастьСтроки.Представление) Тогда
			МассивСтроки.Добавить(Новый ФорматированнаяСтрока(ЧастьСтроки.Значение,,,, ЧастьСтроки.Представление));
		Иначе
			МассивСтроки.Добавить(ЧастьСтроки.Значение);
		КонецЕсли;

	КонецЦикла;

	Возврат Новый ФорматированнаяСтрока(МассивСтроки); // АПК:1356 - можно использовать составную форматированную строку, так как массив строк формируется из переданного в функцию текста.

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

// Формирует представление числа для определенного языка и параметров числа.
//
// Параметры:
//  Шаблон          - Строка - строка, содержит перечисленные через точку с запятой 6 форм строки
//                             для каждой категории числительного:
//                             %1 обозначает позицию числа;
//  Число           - Число - число, которое будет подставлено в строку вместо параметра "%1".
//  Вид             - ВидЧисловогоЗначения - определяет вид числового значения, для которого формируется представление.
//                             Количественное (по умолчанию) или Порядковое.
//  ФорматнаяСтрока - Строка - строка параметров форматирования. См. аналогичный параметр в СтрокаСЧислом.
//
// Возвращаемое значение:
//  Строка - представление строки числа в требуемой форме.
//
// Пример:
//
//  Строка = СтроковыеФункцииКлиентСервер.СтрокаСЧисломДляЛюбогоЯзыка(
//		НСтр("ru=';остался %1 день;;осталось %1 дня;осталось %1 дней;осталось %1 дня';
//		     |en=';left %1 day;;;;left %1 days'"),
//		0.05,, "ЧДЦ=1");
//
&НаСервереБезКонтекста

Функция СтрокаСЧисломДляЛюбогоЯзыка(Шаблон, Число, Вид = Неопределено, ФорматнаяСтрока = "ЧН=0;")

	Если ПустаяСтрока(Шаблон) Тогда
		Возврат Формат(Число, ФорматнаяСтрока);
	КонецЕсли;

	Если Вид = Неопределено Тогда
		Вид = ВидЧисловогоЗначения.Количественное;
	КонецЕсли;

	Возврат СтрокаСЧислом(Шаблон, Число, Вид, ФорматнаяСтрока);

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

// Возвращает признак, является ли конфигурация базовой.
//
// Возвращаемое значение:
//   Булево   - Истина, если конфигурация - базовая.
//
&НаСервереБезКонтекста

Функция ЭтоБазоваяВерсияКонфигурации()

	Возврат СтрНайти(ВРег(Метаданные.Имя), "БАЗОВАЯ") > 0;

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

// Возвращает признак включения условного разделения.
// В случае вызова в неразделенной конфигурации возвращает Ложь.
//
&НаСервереБезКонтекста


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

	Для каждого Тип Из ОписаниеТипов.Типы() Цикл
		ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип); // ОбъектМетаданныхСправочник, ОбъектМетаданныхДокумент

		Если ОбъектМетаданных <> Неопределено Тогда
			СтруктураОбъекта = РазложитьПолноеИмяОбъекта(ОбъектМетаданных.ПолноеИмя());

			Если ТипыОбъектовПоддерживающиеВводПоСтроке[СтруктураОбъекта.ТипОбъекта] = Истина Тогда

				Для каждого Колонка Из ОбъектМетаданных.ВводПоСтроке Цикл

					Если СоответствиеКолонок.Получить(Колонка.Имя) = Неопределено Тогда
						ЗаголовокКолонки = ЗаголовокКолонки + Разделитель + Колонка.Имя;
						Разделитель = ", ";
						СоответствиеКолонок.Вставить(Колонка.Имя, Колонка.Имя);
					КонецЕсли;

				КонецЦикла;

			КонецЕсли;

			Если СтруктураОбъекта.ТипОбъекта = "Документ" Тогда
				ЗаголовокКолонки = ЗаголовокКолонки + Разделитель + "Представление";
			КонецЕсли;
		КонецЕсли;

		ЗаголовокКолонки = НСтр("ru = 'Введенные данные'");

	КонецЦикла;

	ДобавитьИнформациюПоКолонке(ИнформацияПоКолонкам, "Ссылки", ЗаголовокКолонки, Новый ОписаниеТипов("Строка"), Ложь, 1);

	Шапка = ШапкаБланкаДляЗаполненияПоИнформацииПоКолонкам(ИнформацияПоКолонкам);
	ШаблонСДанными.Очистить();
	ШаблонСДанными.Вывести(Шапка);

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

Функция ТипыОбъектовПоддерживающиеВводПоСтроке()

	СписокОбъектов = Новый Соответствие;
	СписокОбъектов.Вставить("БизнесПроцесс",          Истина);
	СписокОбъектов.Вставить("Документ",               Истина);
	СписокОбъектов.Вставить("Задача",                 Истина);
	СписокОбъектов.Вставить("ПланВидовРасчета",       Истина);
	СписокОбъектов.Вставить("ПланВидовХарактеристик", Истина);
	СписокОбъектов.Вставить("ПланОбмена",             Истина);
	СписокОбъектов.Вставить("ПланСчетов",             Истина);
	СписокОбъектов.Вставить("Справочник",             Истина);

	Возврат СписокОбъектов;

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

Процедура СопоставитьЗначениеКолонкиАвто(ТаблицаСопоставления, ИмяКолонки) Экспорт

	Типы = ТаблицаСопоставления.Колонки.ОбъектСопоставления.ТипЗначения.Типы();
	ТипыОбъектовПоддерживающиеВводПоСтроке = ТипыОбъектовПоддерживающиеВводПоСтроке();

	ЗначенияДляСопоставления = Новый ТаблицаЗначений();

	ТекстЗапроса = "";

	Для каждого Тип Из Типы Цикл
		ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип); // ОбъектМетаданныхСправочник, ОбъектМетаданныхДокумент
		Если ОбъектМетаданных <> Неопределено И ПравоДоступа("Чтение", ОбъектМетаданных) Тогда
			СтруктураОбъекта = РазложитьПолноеИмяОбъекта(ОбъектМетаданных.ПолноеИмя());

			МассивКолонок = Новый Массив;
			Если ТипыОбъектовПоддерживающиеВводПоСтроке[СтруктураОбъекта.ТипОбъекта] = Истина Тогда
				Для каждого Поле Из ОбъектМетаданных.ВводПоСтроке Цикл
					МассивКолонок.Добавить(Поле.Имя);
				КонецЦикла;
				Если СтруктураОбъекта.ТипОбъекта = "Документ" Тогда
					МассивКолонок.Добавить("Ссылка");
				КонецЕсли;
			КонецЕсли;

			ТекстЗапроса = СтрокаЗапроса(ТекстЗапроса, СтруктураОбъекта.ТипОбъекта,
				СтруктураОбъекта.НазваниеОбъекта, МассивКолонок);
		КонецЕсли;
	КонецЦикла;

	Если ПустаяСтрока(ТекстЗапроса) Тогда
		Возврат;
	КонецЕсли;

	ТекстЗапроса = "ВЫБРАТЬ
		|ЗначенияДляСопоставления.ЗначениеПоиска КАК ЗначениеПоиска,
		|ЗначенияДляСопоставления.Ключ КАК Ключ
		|ПОМЕСТИТЬ ЗначенияДляСопоставления
		|ИЗ
		|	&ЗначенияДляСопоставления КАК ЗначенияДляСопоставления"
		+ ОбщегоНазначения.РазделительПакетаЗапросов()
		+ ТекстЗапроса + "
		|ИТОГИ ПО Ключ";

	Типы.Добавить(Тип("Строка"));
	ПараметрыСтроки = Новый КвалификаторыСтроки(500);
	ДопустимыеТипы = Новый ОписаниеТипов(Типы, , ПараметрыСтроки);
	ЗначенияДляСопоставления.Колонки.Добавить("ЗначениеПоиска", ДопустимыеТипы);
	ЗначенияДляСопоставления.Колонки.Добавить("Ключ", ОбщегоНазначения.ОписаниеТипаЧисло(10));

	Для каждого Строка Из ТаблицаСопоставления Цикл
		Если НЕ ЗначениеЗаполнено(Строка[ИмяКолонки]) Тогда
			Продолжить;
		КонецЕсли;

		Значение = ДокументПоПредставлению(Строка[ИмяКолонки], Типы);
		НоваяСтрока = ЗначенияДляСопоставления.Добавить();
		НоваяСтрока.ЗначениеПоиска =?(Значение = Неопределено, СокрЛП(Строка[ИмяКолонки]), Значение);
		НоваяСтрока.Ключ = ТаблицаСопоставления.Индекс(Строка);

	КонецЦикла;

	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("ЗначенияДляСопоставления", ЗначенияДляСопоставления);

	ТаблицаРезультатов = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

	Пока ТаблицаРезультатов.Следующий() Цикл

		РезультатПоиска = ТаблицаРезультатов.Выбрать();
		СтрокаДанных = ТаблицаСопоставления.Получить(ТаблицаРезультатов.Ключ);
		Если СтрокаДанных = Неопределено Тогда
			Продолжить;
		КонецЕсли;

		НайденныеВарианты = Новый Массив;
		Пока РезультатПоиска.Следующий() Цикл
			Если РезультатПоиска.СсылкаНаОбъект <> Неопределено Тогда
				НайденныеВарианты.Добавить(РезультатПоиска.СсылкаНаОбъект);
			КонецЕсли;
		КонецЦикла;

		Если НайденныеВарианты.Количество() = 1 Тогда
			СтрокаДанных.ОбъектСопоставления = НайденныеВарианты[0];
			СтрокаДанных.РезультатСопоставленияСтроки =  ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусСопоставлен();
		ИначеЕсли НайденныеВарианты.Количество() > 1 Тогда
			СтрокаДанных.СписокНеоднозначностей.ЗагрузитьЗначения(НайденныеВарианты);
			СтрокаДанных.РезультатСопоставленияСтроки = ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусНеоднозначность();
		Иначе
			СтрокаДанных.РезультатСопоставленияСтроки = ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусНеСопоставлен();
		КонецЕсли;

	КонецЦикла;

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

// Распознает документ по представлению для режима поиска ссылок.
//

Функция ДокументПоПредставлению(Представление, Типы)

	Для каждого Тип Из Типы Цикл
		ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип);
		Если ОбъектМетаданных = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		СтруктураИмениОбъекта = РазложитьПолноеИмяОбъекта(ОбъектМетаданных.ПолноеИмя());
		Если ВРег(СтруктураИмениОбъекта.ТипОбъекта) <> ВРег("Документ") Тогда
			Продолжить;
		КонецЕсли;

		ПредставлениеЭлемента = ОбщегоНазначения.ПредставлениеОбъекта(ОбъектМетаданных);

		Если СтрНайти(Представление, ПредставлениеЭлемента) > 0 Тогда
			ПредставлениеНомерИДата = СокрЛП(Сред(Представление, СтрДлина(ПредставлениеЭлемента) + 1));
			ПозицияОкончанияНомера = СтрНайти(ПредставлениеНомерИДата, " ");
			Номер = Лев(ПредставлениеНомерИДата, ПозицияОкончанияНомера - 1);
			ПозицияОт = СтрНайти(НРег(ПредставлениеНомерИДата), НСтр("ru = 'от'"));
			ПредставлениеДата = СокрЛ(Сред(ПредставлениеНомерИДата, ПозицияОт + 2));
			ПозицияОкончаниеДаты = СтрНайти(ПредставлениеДата, " ");
			ДатаОкругленнаяДоДня = Лев(ПредставлениеДата, ПозицияОкончаниеДаты - 1) + " 00:00:00";
			НомерДокумент = Номер;
			ДатаДокумента = СтроковыеФункцииКлиентСервер.СтрокаВДату(ДатаОкругленнаяДоДня);
		КонецЕсли;

		УстановитьПривилегированныйРежим(Истина);
		Документ = Документы[ОбъектМетаданных.Имя].НайтиПоНомеру(НомерДокумент, ДатаДокумента); // ОбъектМетаданныхДокумент
		УстановитьПривилегированныйРежим(Ложь);

		Если Документ = Неопределено ИЛИ Документ = Документы[ОбъектМетаданных.Имя].ПустаяСсылка() Тогда
			Возврат Неопределено;
		КонецЕсли;

		Возврат Документ;

	КонецЦикла;

	Возврат Неопределено;

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


Функция ЗначениеЯчейки(Колонка, ЗначениеЯчейки)

	ДанныеЯчейки = "";
	Для каждого ТипДанных Из Колонка.ТипКолонки.Типы() Цикл
		ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипДанных);

		Если ОбъектМетаданных = Неопределено Тогда
			Продолжить;
		КонецЕсли;

		ОписаниеОбъекта = РазложитьПолноеИмяОбъекта(ОбъектМетаданных.ПолноеИмя());
		Если ОписаниеОбъекта.ТипОбъекта = "Справочник" Тогда
			Если Не ОбъектМетаданных.Автонумерация
			   И ОбъектМетаданных.ДлинаКода > 0 Тогда
				ДанныеЯчейки = Справочники[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоКоду(ЗначениеЯчейки, Истина);
			КонецЕсли;
			Если Не ЗначениеЗаполнено(ДанныеЯчейки)
			   И ЗначениеЗаполнено(ЗначениеЯчейки)
			   И ОбъектМетаданных.ДлинаНаименования > 0 Тогда
				//@skip-check query-in-loop - штучные запросы разнородных данных.
				ДанныеЯчейки = НайтиПоНаименованию(ЗначениеЯчейки, ОбъектМетаданных, Колонка);
			КонецЕсли;
			Если Не ЗначениеЗаполнено(ДанныеЯчейки)
			   И ОбъектМетаданных.ДлинаКода > 0 Тогда
				ДанныеЯчейки = Справочники[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоКоду(ЗначениеЯчейки, Истина);
			КонецЕсли;
		ИначеЕсли ОписаниеОбъекта.ТипОбъекта = "Перечисление" Тогда
			Для каждого ЗначениеПеречисления Из Перечисления[ОписаниеОбъекта.НазваниеОбъекта] Цикл
				Если Строка(ЗначениеПеречисления) = СокрЛП(ЗначениеЯчейки) Тогда
					ДанныеЯчейки = ЗначениеПеречисления;
				КонецЕсли;
			КонецЦикла;
		ИначеЕсли ОписаниеОбъекта.ТипОбъекта = "ПланСчетов" Тогда
			ДанныеЯчейки = ПланыСчетов[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоКоду(ЗначениеЯчейки);
			Если ДанныеЯчейки.Пустая() Тогда
				ДанныеЯчейки = ПланыСчетов[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоНаименованию(ЗначениеЯчейки, Истина);
			КонецЕсли;
		ИначеЕсли ОписаниеОбъекта.ТипОбъекта = "ПланВидовХарактеристик" Тогда
			Если Не ОбъектМетаданных.Автонумерация И ОбъектМетаданных.ДлинаКода > 0 Тогда
				ДанныеЯчейки = ПланыВидовХарактеристик[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоКоду(ЗначениеЯчейки);
			КонецЕсли;
			Если Не ЗначениеЗаполнено(ДанныеЯчейки) Тогда
				ДанныеЯчейки = ПланыВидовХарактеристик[ОписаниеОбъекта.НазваниеОбъекта].НайтиПоНаименованию(ЗначениеЯчейки, Истина);
			КонецЕсли;
		Иначе
			ДанныеЯчейки =  Строка(ЗначениеЯчейки);
		КонецЕсли;
		Если ЗначениеЗаполнено(ДанныеЯчейки) Тогда
			Прервать;
		КонецЕсли;
	КонецЦикла;

	Возврат ДанныеЯчейки;

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

Функция НайтиПоНаименованию(ЗначениеЯчейки, ОбъектМетаданных, Колонка)

	Запрос = Новый Запрос;

	Если ОбъектМетаданных.Иерархический
	   И ОбъектМетаданных.ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда

		Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ИмяСправочника.Ссылка КАК Ссылка
		|ИЗ
		|	#ИмяСправочника КАК ИмяСправочника
		|ГДЕ
		|	ИмяСправочника.Наименование = &Наименование
		|	И ИмяСправочника.ЭтоГруппа = &ЭтоГруппа
		|
		|УПОРЯДОЧИТЬ ПО
		|	ИмяСправочника.ЭтоГруппа";

		Если Колонка.Использование = "ДляГруппы" Тогда
			Запрос.УстановитьПараметр("ЭтоГруппа", Истина);
		ИначеЕсли Колонка.Использование = "ДляЭлемента" Тогда
			Запрос.УстановитьПараметр("ЭтоГруппа", Ложь);
		Иначе
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "И ИмяСправочника.ЭтоГруппа = &ЭтоГруппа", "");
		КонецЕсли;

	Иначе

		Запрос.Текст =
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ИмяСправочника.Ссылка КАК Ссылка
		|ИЗ
		|	#ИмяСправочника КАК ИмяСправочника
		|ГДЕ
		|	ИмяСправочника.Наименование = &Наименование";

	КонецЕсли;

	Запрос.Текст = СтрЗаменить(Запрос.Текст, "#ИмяСправочника", ОбъектМетаданных.ПолноеИмя());
	Запрос.УстановитьПараметр("Наименование", ЗначениеЯчейки);

	РезультатЗапроса = Запрос.Выполнить();

	Если РезультатЗапроса.Пустой() Тогда
		Возврат Неопределено;
	КонецЕсли;

	Выборка = РезультатЗапроса.Выбрать();

	Если Выборка.Следующий() Тогда
		Возврат Выборка.Ссылка;
	КонецЕсли;

	Возврат Неопределено;

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

Процедура ОпределитьПозицииКолонокВМакете(ШаблонСДанными, ИнформацияПоКолонкам)

	ОбластьЗаголовка = ОбластьЗаголовкаШаблонаТаблицы(ШаблонСДанными);

	СоответствиеКолонок = Новый Соответствие;
	Для НомерКолонки = 1 По ОбластьЗаголовка.ШиринаТаблицы Цикл
		Ячейка=ШаблонСДанными.ПолучитьОбласть(1, НомерКолонки, 1, НомерКолонки).ТекущаяОбласть;
		ИмяКолонкиВМакете = Ячейка.Текст;
		СоответствиеКолонок.Вставить(ИмяКолонкиВМакете, НомерКолонки);
	КонецЦикла;

	Для каждого Колонка Из ИнформацияПоКолонкам Цикл
		Позиция = СоответствиеКолонок.Получить(Колонка.ПредставлениеКолонки);
		Если Позиция <> Неопределено Тогда
			Колонка.Позиция = Позиция;
		Иначе
			Колонка.Позиция = -1;
		КонецЕсли;
	КонецЦикла;

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

#Область ПодготовкаКЗагрузкеДанных

Функция ОбластьЗаголовкаШаблонаТаблицы(Шаблон)

	ВысотаШапки = 1;
	Для НомерКолонки = 1 По Шаблон.ШиринаТаблицы Цикл
		Ячейка = Шаблон.ПолучитьОбласть(2, НомерКолонки, 2, НомерКолонки).ТекущаяОбласть;
		Если ЗначениеЗаполнено(Ячейка.Текст) Тогда
			ВысотаШапки = 2;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	ОбластьЗаголовокТаблицы = Шаблон.ПолучитьОбласть(1, 1, ВысотаШапки, Шаблон.ШиринаТаблицы);

	Возврат ОбластьЗаголовокТаблицы;

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

// Формирует макет табличного документа на основание реквизитов справочника для универсальной загрузки.
//


Процедура ГрупповоеИзменениеРеквизитов(Команда)

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

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

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

/////////////////////////////////////// КЛИЕНТ ///////////////////////////////////////////

// Завершение диалога закрытия формы.
&НаКлиенте

Процедура ЗакрытиеФормыЗавершение(Знач РезультатВопроса, Знач ДополнительныеПараметры) Экспорт
	Если РезультатВопроса = КодВозвратаДиалога.Да Тогда
		ПодтверждениеЗакрытияФормы = Истина;
		Закрыть();
	Иначе
		ПодтверждениеЗакрытияФормы = Ложь;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте

Процедура ПереходКСледующемуШагуЗагрузкиДанных()

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

			АдресЗагруженныхДанных = АдресВХранилищеТаблицыСопоставления();
			Закрыть(АдресЗагруженныхДанных);
		ИначеЕсли ТипЗагрузки = "ВставкаИзБуфераОбмена" Тогда
			Элементы.Назад.Заголовок = НСтр("ru = '< В начало_'");
			ЗакрытьФормуИВернутьМассивСсылок();
		Иначе
			Элементы.СтраницыПомощника.ТекущаяСтраница = Элементы.ДлительныеОперации;
			ЗаписатьЗагружаемыеДанныеКлиент();
		КонецЕсли;
	КонецЕсли;

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

// Параметры:
//  Результат - Произвольный
//  Параметр - см. ОписаниеПараметраСопоставленияНеоднозначностей
//
&НаКлиенте

Процедура ПослеСопоставленияНеоднозначностей(Результат, Параметр) Экспорт

	Если ТипЗагрузки  = "ТабличнаяЧасть" Тогда
		Если Результат <> Неопределено Тогда
			ПрефиксТабличнойЧасти = ЗагрузкаДанныхИзФайлаКлиентСервер.ПрефиксТабличнойЧасти() + "_";

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

	ПоказатьСтатистикуПоСопоставлениюЗагрузкаИзФайла();

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

&НаКлиенте

Процедура ВыполнитьСопоставление()
	КоличествоСопоставленныхПоКолонкам = 0;
	СписокКолонок = "";
	ВыполнитьСопоставлениеПоВыбранномуРеквизиту(КоличествоСопоставленныхПоКолонкам, СписокКолонок);
	ПоказатьОповещениеПользователя(НСтр("ru = 'Выполнено сопоставление'"),, НСтр("ru = 'Сопоставлено элементов:'") + " " + Строка(КоличествоСопоставленныхПоКолонкам));
	ПоказатьСтатистикуПоСопоставлениюЗагрузкаИзФайла();
КонецПроцедуры

&НаКлиенте

Функция ВсеДанныеСопоставлены()
	Отбор = Новый Структура("РезультатСопоставленияСтроки", ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусСопоставлен());
	Результат = ТаблицаСопоставленияДанных.НайтиСтроки(Отбор);
	КоличествоСопоставленных = Результат.Количество();

	Если ТаблицаСопоставленияДанных.Количество() = КоличествоСопоставленных Тогда
		Возврат Истина;
	Иначе
		Возврат Ложь;
	КонецЕсли;

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

&НаКлиенте

Функция СтатисткаСопоставления()

	Отбор                    = Новый Структура("РезультатСопоставленияСтроки", ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусСопоставлен());
	Результат                = ТаблицаСопоставленияДанных.НайтиСтроки(Отбор);
	КоличествоСопоставленных = Результат.Количество();

	Если ТипЗагрузки = "ВставкаИзБуфераОбмена" Тогда
		Отбор                   = Новый Структура("РезультатСопоставленияСтроки", ЗагрузкаДанныхИзФайлаКлиентСервер.СтатусНеСопоставлен());
		Результат               = ТаблицаСопоставленияДанных.НайтиСтроки(Отбор);
		КоличествоНеоднозначных = ТаблицаСопоставленияДанных.Количество() - КоличествоСопоставленных - Результат.Количество();
	Иначе
		Отбор                   = Новый Структура("ОписаниеОшибки", "");
		Результат               = ТаблицаСопоставленияДанных.НайтиСтроки(Отбор);
		КоличествоНеоднозначных = ТаблицаСопоставленияДанных.Количество() - Результат.Количество();
	КонецЕсли;
	КоличествоНеСопоставленных  = ТаблицаСопоставленияДанных.Количество() - КоличествоСопоставленных;

	Результат = Новый Структура;
	Результат.Вставить("Всего",            ТаблицаСопоставленияДанных.Количество());
	Результат.Вставить("Сопоставленных",   КоличествоСопоставленных);
	Результат.Вставить("Неоднозначных",    КоличествоНеоднозначных);
	Результат.Вставить("Несопоставленных", КоличествоНеСопоставленных);
	Результат.Вставить("НеНайдено",        КоличествоНеСопоставленных - КоличествоНеоднозначных);

	Возврат Результат;

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

&НаКлиенте