epf_QueryConsole/src/ИнструментыРазработчикаКонс.../Ext/ObjectModule.bsl

1994 lines
124 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область СлужебныеПроцедурыИФункции
///////////////////////////////////////////////////////////////////////////
// ФУНКЦИИ РАБОТЫ С ВРЕМЕННЫМ ХРАНИЛИЩЕМ
// Помещает во внутреннее хранилище Запросы, Параметры, Имя файла.
//
// Параметры:
// Объект - передаваемый объект обработки.
// ИдентификаторТекущегоЗапроса - GUID текущего запроса.
// ИдентификаторТекущегоПараметра - GUID текущего параметра.
//
Функция ПоместитьЗапросыВоВременноеХранилище(Объект, ИдентификаторТекущегоЗапроса, ИдентификаторТекущегоПараметра) Экспорт
ПараметрыПередачи = Новый Структура;
ПараметрыПередачи.Вставить("Запросы", Объект.Запросы.Выгрузить());
ПараметрыПередачи.Вставить("Параметры", Объект.Параметры.Выгрузить());
ПараметрыПередачи.Вставить("ИмяФайла", Объект.ИмяФайла);
ПараметрыПередачи.Вставить("ИдентификаторТекущегоЗапроса", ИдентификаторТекущегоЗапроса);
ПараметрыПередачи.Вставить("ИдентификаторТекущегоПараметра", ИдентификаторТекущегоПараметра);
АдресХранилища = ПоместитьВоВременноеХранилище(ПараметрыПередачи);
Возврат АдресХранилища;
КонецФункции
// Помещает во внутренне хранилище настройки обработки.
//
// Параметры:
// Объект - передаваемый Объект обработки.
//
Функция ПоместитьНастройкиВоВременноеХранилище(Объект) Экспорт
ПараметрыПередачи = Новый Структура;
ПараметрыПередачи.Вставить("ИспользоватьАвтосохранение", Объект.ИспользоватьАвтосохранение);
ПараметрыПередачи.Вставить("ПериодАвтосохранения", Объект.ПериодАвтосохранения);
ПараметрыПередачи.Вставить("ВыводитьВРезультатахЗапросаЗначенияСсылок", Объект.ВыводитьВРезультатахЗапросаЗначенияСсылок);
ПараметрыПередачи.Вставить("ЧередованиеЦветовВРезультатеЗапроса", Объект.ЧередованиеЦветовВРезультатеЗапроса);
ПараметрыПередачи.Вставить("ТипОбхода", Объект.ТипОбхода);
АдресХранилища = ПоместитьВоВременноеХранилище(ПараметрыПередачи);
Возврат АдресХранилища;
КонецФункции
///////////////////////////////////////////////////////////////////////////
// ФУНКЦИИ РАБОТЫ С XML-ФАЙЛАМИ
// Записывает Запросы(текст и параметры запроса) в файл XML.
//
// Параметры:
// ИмяФайла - имя файла XML.
// Объект - передаваемый объект обработки.
//
Функция ЗаписатьЗапросыВФайлXML(знач Объект) Экспорт
ФайлXML = Новый ЗаписьXML;
ИмяФайла = ПолучитьИмяВременногоФайла("q1c");
ФайлXML.ОткрытьФайл(ИмяФайла);
ФайлXML.ЗаписатьОбъявлениеXML();
ФайлXML.ЗаписатьНачалоЭлемента("querylist");
// Цикл запросов.
Для каждого ТекЗапрос Из Объект.Запросы Цикл
ФайлXML.ЗаписатьНачалоЭлемента("query");
ФайлXML.ЗаписатьАтрибут("name", ТекЗапрос.Имя);
ФайлXML.ЗаписатьНачалоЭлемента("text");
ТекстЗапроса = ТекЗапрос.Текст;
Для Счетчик = 1 По СтрЧислоСтрок(ТекстЗапроса) Цикл
ПереносСтр = Символы.ВК + Символы.ПС;
ТекСтрока = СтрПолучитьСтроку(ТекстЗапроса, Счетчик);
ФайлXML.ЗаписатьТекст(ТекСтрока);
ФайлXML.ЗаписатьБезОбработки(ПереносСтр);
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
ИдентификаторЗапроса = ТекЗапрос.Идентификатор;
// Запись параметров в XML-файл.
Если Объект.Параметры.Количество() > 0 Тогда
ФайлXML.ЗаписатьНачалоЭлемента("parameters");
Для каждого ТекПараметр Из Объект.Параметры Цикл
Если ТекПараметр.ИдентификаторЗапроса = ИдентификаторЗапроса Тогда
ИмяПараметра = ТекПараметр.Имя;
ТипПараметра = ТекПараметр.Тип;
Значение = ТекПараметр.Значение;
Если ПустаяСтрока(Значение) Тогда
ЗначениеПараметра = "";
Иначе
ЗначениеПараметра = ЗначениеИзСтрокиВнутр(ТекПараметр.Значение);
КонецЕсли;
ФайлXML.ЗаписатьНачалоЭлемента("parameter");
ФайлXML.ЗаписатьАтрибут("name", ИмяПараметра);
Если ТипПараметра = "СписокЗначений" Тогда
ФайлXML.ЗаписатьАтрибут("type", ТипПараметра);
ЗаписатьСписокЗначенийВXML(ФайлXML, ЗначениеПараметра);
ИначеЕсли ТипПараметра = "ТаблицаЗначений" Тогда
ФайлXML.ЗаписатьАтрибут("type", ТипПараметра);
Колонки = ЗначениеПараметра.Колонки.Количество();
Строки = ЗначениеПараметра.Количество();
ФайлXML.ЗаписатьАтрибут("colcount", XMLСтрока(Колонки));
ФайлXML.ЗаписатьАтрибут("rowcount", XMLСтрока(Строки));
ЗаписатьТаблицуЗначенийВXML(ФайлXML, ЗначениеПараметра);
ИначеЕсли ТипПараметра = "МоментВремени" Тогда
ФайлXML.ЗаписатьАтрибут("type", ТипПараметра);
ЗаписатьМоментВремениВXML(ФайлXML, ЗначениеПараметра);
ИначеЕсли ТипПараметра = "Граница" Тогда
ФайлXML.ЗаписатьАтрибут("type", ТипПараметра);
ЗаписатьГраницуВXML(ФайлXML, ЗначениеПараметра);
Иначе
ИмяТипа = ИмяТипаИзЗначения(ЗначениеПараметра);
ФайлXML.ЗаписатьАтрибут("type", ИмяТипа);
ФайлXML.ЗаписатьАтрибут("value", XMLСтрока(ЗначениеПараметра));
КонецЕсли;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЕсли;
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЕсли;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
ФайлXML.Закрыть();
ВозвращаемоеЗначение = Новый ДвоичныеДанные(ИмяФайла);
УдалитьФайлы(ИмяФайла);
Возврат ВозвращаемоеЗначение;
КонецФункции
// Записывает строки списка значений в Файл XML.
//
// Параметры:
// ФайлXML - записьXML.
// Значение - список значений.
//
Процедура ЗаписатьСписокЗначенийВXML(ФайлXML, Значение)
Если ТипЗнч(Значение) <> Тип("СписокЗначений") Тогда
Возврат;
КонецЕсли;
Для каждого СтрСписка Из Значение Цикл
ЗначениеЭлементаСписка = СтрСписка.Значение;
// Определение имени типа.
ИмяТипа = ИмяТипаИзЗначения(ЗначениеЭлементаСписка);
ФайлXML.ЗаписатьНачалоЭлемента("item");
ФайлXML.ЗаписатьАтрибут("type", ИмяТипа);
ФайлXML.ЗаписатьАтрибут("value", XMLСтрока(ЗначениеЭлементаСписка));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
КонецПроцедуры
// Записывает ячейки таблицы значений в Файл XML.
//
// Параметры:
// ФайлXML - записьXML.
// Значение - таблица значений.
//
Процедура ЗаписатьТаблицуЗначенийВXML(ФайлXML, Значение)
Если ТипЗнч(Значение) <> Тип("ТаблицаЗначений") Тогда
Возврат;
КонецЕсли;
КолКолонок = Значение.Колонки.Количество();
КолСтрок = Значение.Количество();
Для СтрокаИндекс = 0 По КолСтрок - 1 Цикл
Для КолонкаИндекс = 0 По КолКолонок - 1 Цикл
ЗначениеЭлементаСписка = Значение.Получить(СтрокаИндекс).Получить(КолонкаИндекс);
ИмяКолонки = Значение.Колонки.Получить(КолонкаИндекс).Имя;
// Определение имени типа.
ИмяТипа = ИмяТипаИзЗначения(ЗначениеЭлементаСписка);
Если ИмяТипа = "Строка" Тогда
Длина = Значение.Колонки.Получить(КолонкаИндекс).ТипЗначения.КвалификаторыСтроки.Длина;
Иначе
Длина = 0;
КонецЕсли;
ФайлXML.ЗаписатьНачалоЭлемента("item");
ФайлXML.ЗаписатьАтрибут("nameCol", ИмяКолонки);
ФайлXML.ЗаписатьАтрибут("row", XMLСтрока(СтрокаИндекс));
ФайлXML.ЗаписатьАтрибут("col", XMLСтрока(КолонкаИндекс));
ФайлXML.ЗаписатьАтрибут("type", ИмяТипа);
ФайлXML.ЗаписатьАтрибут("length", XMLСтрока(Длина));
ФайлXML.ЗаписатьАтрибут("value", XMLСтрока(ЗначениеЭлементаСписка));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
КонецЦикла;
КонецПроцедуры
// Записывает момент времени в Файл XML.
//
// Параметры:
// ФайлXML - записьXML.
// Значение - момент времени.
//
Процедура ЗаписатьМоментВремениВXML(ФайлXML, Значение)
Если ТипЗнч(Значение) <> Тип("МоментВремени") Тогда
Возврат;
КонецЕсли;
// Определение имени типа.
ИмяТипа = ИмяТипаИзЗначения(Значение.Ссылка);
ФайлXML.ЗаписатьНачалоЭлемента("item");
Если Значение.Ссылка <> Неопределено Тогда
ФайлXML.ЗаписатьАтрибут("type", ИмяТипа);
ФайлXML.ЗаписатьАтрибут("valueRef", XMLСтрока(Значение.Ссылка));
КонецЕсли;
ФайлXML.ЗаписатьАтрибут("valueDate", XMLСтрока(Значение.Дата));
ФайлXML.ЗаписатьКонецЭлемента();
КонецПроцедуры
// Записывает границу.
//
Процедура ЗаписатьГраницуВXML(ФайлXML, Граница)
Если ТипЗнч(Граница) <> Тип("Граница") Тогда
Возврат;
КонецЕсли;
ФайлXML.ЗаписатьНачалоЭлемента("divide");
// Определение имени типа.
ИмяТипа = ИмяТипаИзЗначения(Граница.Значение);
ТипЗначенияГраницы = ТипЗнч(Граница.Значение);
// Запись в строку вида границы.
ИмяВидаГраницы = Строка(Граница.ВидГраницы);
ФайлXML.ЗаписатьАтрибут("type", ИмяТипа);
ФайлXML.ЗаписатьАтрибут("valueDiv", ИмяВидаГраницы);
Если ТипЗначенияГраницы <> Тип("МоментВремени") Тогда
ФайлXML.ЗаписатьАтрибут("value", XMLСтрока(Граница.Значение));
Иначе
ЗаписатьМоментВремениВXML(ФайлXML, Граница.Значение);
КонецЕсли;
ФайлXML.ЗаписатьКонецЭлемента();
КонецПроцедуры
// Читает Запросы(текст и параметры) из XML-файла.
//
Функция ПрочитатьЗапросыИзФайлаXML(ДвоичныеДанные) Экспорт
Объект = ЭтотОбъект;
ИмяФайла = ПолучитьИмяВременногоФайла("q1c");
ДвоичныеДанные.Записать(ИмяФайла);
ФайлXML = Новый ЧтениеXML;
ФайлXML.ОткрытьФайл(ИмяФайла);
ФайлXML.Прочитать();
// Чтение всех запросов.
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ФайлXML.Имя = "querylist" Тогда
Пока ФайлXML.Прочитать() Цикл
// Чтение запроса.
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ФайлXML.Имя = "query" Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "name" Тогда
// Добавление запроса в таблицу.
текЭлементЗапроса = Запросы.Добавить();
текЭлементЗапроса.Идентификатор = Новый УникальныйИдентификатор;
текЭлементЗапроса.Имя = ФайлXML.Значение;
КонецЕсли;
КонецЦикла;
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ФайлXML.Имя = "text" Тогда
ФайлXML.Прочитать();
текЭлементЗапроса.Текст = ФайлXML.Значение;
// Чтение параметров.
КонецЕсли;
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ФайлXML.Имя = "parameters" Тогда
Пока ФайлXML.Прочитать() Цикл
// Чтение отдельного параметра.
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ФайлXML.Имя = "parameter" Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
// Чтение имени атрибута.
Если ФайлXML.Имя = "name" Тогда
текПараметрЗапроса = Параметры.Добавить();
текПараметрЗапроса.Идентификатор = Новый УникальныйИдентификатор;
текПараметрЗапроса.Имя = ФайлXML.Значение;
текПараметрЗапроса.ИдентификаторЗапроса = текЭлементЗапроса.Идентификатор;
КонецЕсли;
// Чтение типа параметра.
Если ФайлXML.Имя = "type" Тогда
ТипЭлемента = Тип(ФайлXML.Значение);
текПараметрЗапроса.Тип = Строка(ФайлXML.Значение);
КонецЕсли;
// Чтение значения параметра.
Если ФайлXML.Имя = "value" Тогда
Значение = XMLЗначение(ТипЭлемента, ФайлXML.Значение);
текПараметрЗапроса.Значение = ЗначениеВСтрокуВнутр(Значение);
КонецЕсли;
// Чтение количества колонок Таблицы Значений.
Если ФайлXML.Имя = "colcount" Тогда
КоличествоКолонок = Число(ФайлXML.Значение);
КонецЕсли;
// Чтение количества строк Таблицы Значений.
Если ФайлXML.Имя = "rowcount" Тогда
КоличествоСтрок = Число(ФайлXML.Значение);
КонецЕсли;
КонецЦикла;
// Чтение отдельных типов.
// Для отдельных типов предусмотрено индивидуальное чтение параметров.
// Под отдельными типами понимаются: Список значений, Таблица значений,
// Момент Времени, Граница.
//
// Список отдельных типов может увеличиваться.
Если текПараметрЗапроса.Тип = "СписокЗначений" Тогда
ПрочитатьСписокЗначенийИзXML(ФайлXML, текПараметрЗапроса);
КонецЕсли;
Если текПараметрЗапроса.Тип = "ТаблицаЗначений" Тогда
Если КоличествоКолонок > 0 Тогда
ПрочитатьТаблицуЗначенийИзXML(ФайлXML, текПараметрЗапроса, КоличествоСтрок, КоличествоКолонок);
КонецЕсли;
КонецЕсли;
Если текПараметрЗапроса.Тип = "МоментВремени" Тогда
ПрочитатьМоментВремениИзXML(ФайлXML, текПараметрЗапроса);
КонецЕсли;
Если текПараметрЗапроса.Тип = "Граница" Тогда
ПрочитатьГраницуИзXML(ФайлXML, текПараметрЗапроса);
КонецЕсли;
КонецЕсли;
Если ПроверкаКонцаТэгов(ФайлXML) Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ПроверкаКонцаТэгов(ФайлXML) Тогда
Прервать;
КонецЕсли;
КонецЦикла; // Обход по тэгам "query".
КонецЕсли; // Если "query".
КонецЦикла; // Обход по запросам.
КонецЕсли; // Если "querylist".
ФайлXML.Закрыть();
Возврат ЭтотОбъект;
КонецФункции
// Читает Список значений.
//
// Параметры:
// ФайлXML - Чтение XML.
// ПараметрЗапроса - текущий параметр.
//
Процедура ПрочитатьСписокЗначенийИзXML(ФайлXML, ПараметрЗапроса)
СписокЗН = Новый СписокЗначений;
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.Имя = "item" И ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "type" Тогда
ТипЭлемента = Тип(ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "value" Тогда
// Чтение значения.
Значение = XMLЗначение(ТипЭлемента, ФайлXML.Значение);
ЗначениеЭлементаСписка = Значение;
КонецЕсли;
КонецЦикла;
СписокЗН.Добавить(ЗначениеЭлементаСписка);
ИначеЕсли ФайлXML.Имя <> "item" Тогда
Прервать;
КонецЕсли;
КонецЦикла;
ПараметрЗапроса.Значение = ЗначениеВСтрокуВнутр(СписокЗН);
КонецПроцедуры
// Читает Таблицу значений.
//
// Параметры:
// ФайлXML - Чтение XML.
// ПараметрЗапроса - текущий параметр.
// КоличествоСтрок - количество строк.
// КоличествоКолонок - количество колонок.
//
Процедура ПрочитатьТаблицуЗначенийИзXML(ФайлXML, ПараметрЗапроса, КоличествоСтрок, КоличествоКолонок)
ТаблицаЗначений = Новый ТаблицаЗначений;
МассивКолонок = Новый Массив;
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.Имя = "item" И ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "col" Тогда
ИндексКолонки = Число(ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "row" Тогда
ИндексСтроки = Число(ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "type" Тогда
ТипЭлемента = Тип(ФайлXML.Значение);
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЭлемента);
КонецЕсли;
Если ФайлXML.Имя = "nameCol" Тогда
ИмяКолонки = ФайлXML.Значение;
КонецЕсли;
Если ФайлXML.Имя = "length" Тогда
Длина = ФайлXML.Значение;
КонецЕсли;
Если ФайлXML.Имя = "value" Тогда
Значение = XMLЗначение(ТипЭлемента, ФайлXML.Значение);
ЗначениеЯчейки = Значение;
КонецЕсли;
КонецЦикла;
ПараметрыСтроки = Новый КвалификаторыСтроки(Длина);
//ag(
Если ИндексСтроки = неопределено Тогда
//добавим пустую ТЗ
ОписаниеТипов = Новый ОписаниеТипов();
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, МассивТипов);
СтруктураКолонки = Новый Структура;
СтруктураКолонки.Вставить("Имя", ИмяКолонки);
СтруктураКолонки.Вставить("ОписаниеТипов", ОписаниеТипов);
СтруктураКолонки.Вставить("СписокЗначенийЯчеекКолонки", Новый СписокЗначений);
МассивКолонок.Вставить(ИндексКолонки,СтруктураКолонки);
Иначе
//ag)
Если МассивКолонок.Количество() - 1 < ИндексКолонки Тогда
ОписаниеТипов = Новый ОписаниеТипов();
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, МассивТипов,,, ПараметрыСтроки);
СписокЗначенийЯчеекКолонки = Новый СписокЗначений;
СписокЗначенийЯчеекКолонки.Вставить(ИндексСтроки,ЗначениеЯчейки);
СтруктураКолонки = Новый Структура;
СтруктураКолонки.Вставить("Имя", ИмяКолонки);
СтруктураКолонки.Вставить("ОписаниеТипов", ОписаниеТипов);
СтруктураКолонки.Вставить("СписокЗначенийЯчеекКолонки", СписокЗначенийЯчеекКолонки);
МассивКолонок.Вставить(ИндексКолонки, СтруктураКолонки);
Иначе
Имя = МассивКолонок.Получить(ИндексКолонки).Имя;
ОписаниеТипов = МассивКолонок.Получить(ИндексКолонки).ОписаниеТипов;
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, МассивТипов,,, ПараметрыСтроки);
СписокЗначенийЯчеекКолонки = МассивКолонок.Получить(ИндексКолонки).СписокЗначенийЯчеекКолонки;
СписокЗначенийЯчеекКолонки.Вставить(ИндексСтроки,ЗначениеЯчейки);
МассивКолонок.Удалить(ИндексКолонки);
СтруктураКолонки = Новый Структура;
СтруктураКолонки.Вставить("Имя", ИмяКолонки);
СтруктураКолонки.Вставить("ОписаниеТипов", ОписаниеТипов);
СтруктураКолонки.Вставить("СписокЗначенийЯчеекКолонки", СписокЗначенийЯчеекКолонки);
МассивКолонок.Вставить(ИндексКолонки, СтруктураКолонки);
КонецЕсли;
КонецЕсли;
ИначеЕсли ФайлXML.Имя <> "item" Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КолКолонок = МассивКолонок.Количество();
Для ИндексКолонок = 0 По КолКолонок - 1 Цикл
ИмяКолонки = МассивКолонок.Получить(ИндексКолонок).Имя;
ТипКолонки = МассивКолонок.Получить(ИндексКолонок).ОписаниеТипов;
ТаблицаЗначений.Колонки.Вставить(ИндексКолонок, ИмяКолонки, ТипКолонки, ИмяКолонки);
СписокЗначений = МассивКолонок.Получить(ИндексКолонок).СписокЗначенийЯчеекКолонки;
КолСтрок = СписокЗначений.Количество();
Для ИндексСтрок = 0 По КолСтрок - 1 Цикл
ЗначениеЯчейки = СписокЗначений.Получить(ИндексСтрок).Значение;
Если ИндексСтрок <= ТаблицаЗначений.Количество() - 1 Тогда
ТаблицаЗначений.Получить(ИндексСтрок).Установить(ИндексКолонок, ЗначениеЯчейки);
Иначе
ТаблицаЗначений.Вставить(ИндексСтрок).Установить(ИндексКолонок, ЗначениеЯчейки);
КонецЕсли;
КонецЦикла;
КонецЦикла;
ПараметрЗапроса.Значение = ЗначениеВСтрокуВнутр(ТаблицаЗначений);
КонецПроцедуры
// Читает Момент времени.
//
// Параметры:
// ФайлXML - Чтение XML.
// ПараметрЗапроса - текущий параметр.
//
Процедура ПрочитатьМоментВремениИзXML(ФайлXML, ПараметрЗапроса)
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.Имя = "item" И ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "type" Тогда
ТипЭлемента = Тип(ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "valueRef" Тогда
ЗначениеСсылки = XMLЗначение(ТипЭлемента, ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "valueDate" Тогда
ЗначениеДаты = XMLЗначение(Тип("Дата"), ФайлXML.Значение);
КонецЕсли;
КонецЦикла;
МВ = Новый МоментВремени(ЗначениеДаты, ЗначениеСсылки);
ИначеЕсли ФайлXML.Имя <> "item" Тогда
Прервать;
КонецЕсли;
КонецЦикла;
ПараметрЗапроса.Значение = ЗначениеВСтрокуВнутр(МВ);
КонецПроцедуры
// Читает Границу.
//
// Параметры:
// ФайлXML - Чтение XML.
// ПараметрЗапроса - текущий параметр.
//
Процедура ПрочитатьГраницуИзXML(ФайлXML, ПараметрЗапроса)
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.Имя = "divide" И ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = "type" Тогда
ТипЭлемента = Тип(ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "value" Тогда
Значение = XMLЗначение(ТипЭлемента, ФайлXML.Значение);
КонецЕсли;
Если ФайлXML.Имя = "valueDiv" Тогда
Вид = XMLЗначение(Тип("Строка"), ФайлXML.Значение);
Вид = ОпределениеВидаГраницы(Вид);
КонецЕсли;
КонецЦикла;
Если ТипЭлемента = Тип("МоментВремени") Тогда
ПрочитатьМоментВремениИзXML(ФайлXML, ПараметрЗапроса);
Значение = ЗначениеИзСтрокиВнутр(ПараметрЗапроса.Значение);
КонецЕсли;
Граница = Новый Граница(Значение, Вид);
ИначеЕсли ФайлXML.Имя <> "divide" Тогда
Прервать;
КонецЕсли;
КонецЦикла;
ПараметрЗапроса.Значение = ЗначениеВСтрокуВнутр(Граница);
КонецПроцедуры
// Определяет условие конца тэга "query" или "parameters".
//
// Параметры:
// ФайлXML - чтениеXML.
//
Функция ПроверкаКонцаТэгов(ФайлXML)
Если (ФайлXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ФайлXML.Имя = "query")
Или (ФайлXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ФайлXML.Имя = "parameters") Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
///////////////////////////////////////////////////////////////////////////
// ФУНКЦИИ РАБОТЫ С ЗАПРОСОМ
// Считывает параметры из текста запроса.
//
// Параметры:
// ТекстЗапроса - текст запроса.
// ИдентификаторЗапроса - уникальный идентификатор запроса.
//
Функция СчитатьПараметрыЗапроса(ТекстЗапроса, ИдентификаторЗапроса) Экспорт
МассивСтруктуры = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
// Заполняем параметрами таблицу параметров.
ПарЗап = Запрос.НайтиПараметры();
Для каждого СтрПараметры Из ПарЗап Цикл
РезультатСтруктура = ДобавлениеНовогоПараметра(СтрПараметры, ИдентификаторЗапроса);
МассивСтруктуры.Добавить(РезультатСтруктура);
КонецЦикла;
Возврат МассивСтруктуры;
КонецФункции
// Добавляет новый параметр в структуру параметров.
//
// Параметры:
// ТекущийПрочитанныйПараметр - текущий параметр, прочитанный из текста запроса.
// ИдентификаторЗапроса - GUID запроса.
//
// Возвращает: структуру параметров.
//
Функция ДобавлениеНовогоПараметра(ТекущийПрочитанныйПараметр, ИдентификаторЗапроса)
ЭлементПараметр = Новый Структура("ИдентификаторЗапроса, Имя, Тип, Значение",
ИдентификаторЗапроса, ТекущийПрочитанныйПараметр.Имя
);
// Смотрим на первый тип из списка, если есть.
ДоступныеТипы = ТекущийПрочитанныйПараметр.ТипЗначения.Типы();
Если ДоступныеТипы.Количество()=0 Тогда
// Считаем строкой
ЭлементПараметр.Тип = "Строка";
ЭлементПараметр.Значение = ЗначениеВСтрокуВнутр("");
Возврат ЭлементПараметр;
КонецЕсли;
// Формируем описание типа из первого доступного типа.
Массив = Новый Массив;
Массив.Добавить( ДоступныеТипы.Получить(0) );
НовоеОписаниеТипов = Новый ОписаниеТипов(Массив);
Значение = НовоеОписаниеТипов.ПривестиЗначение(Неопределено);
СписокДобавленныхТипов = Новый СписокЗначений;
СформироватьСписокТипов(СписокДобавленныхТипов);
Флаг = Ложь;
СтроковоеПредставлениеТипа = Строка(ТипЗнч(Значение));
Для каждого ЭлементСписка Из СписокДобавленныхТипов Цикл
Если ЭлементСписка.Представление = СтроковоеПредставлениеТипа Тогда
Флаг = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
ЭлементПараметр.Тип = ?(Флаг, СтроковоеПредставлениеТипа, XMLТип(ТипЗнч(Значение)).ИмяТипа);
ЭлементПараметр.Значение = ЗначениеВСтрокуВнутр(Значение);
Возврат ЭлементПараметр;
КонецФункции
// Загружает параметры в запрос.
// Если строковое представление значения - пустая строка, тогда значение параметра является Неопределено.
//
// Параметры:
// Запрос - передаваемый запрос.
// ПараметрыЗапроса - передаваемые параметры для запроса.
//
Процедура ЗагрузкаПараметровВЗапрос(Запрос, ПараметрыЗапроса)
Для каждого ЭлементПараметр Из ПараметрыЗапроса Цикл
СтрокаЗначение = ЭлементПараметр.Значение;
Если ПустаяСтрока(СтрокаЗначение) Тогда
Значение = Неопределено;
Иначе
Значение = ЗначениеИзСтрокиВнутр(СтрокаЗначение);
КонецЕсли;
Запрос.УстановитьПараметр(ЭлементПараметр.Имя, Значение);
КонецЦикла;
КонецПроцедуры
// Выполняется запрос
//
// Параметры:
// ТекстЗапроса - текст запроса.
// ПараметрыЗапроса - массив параметров запроса.
// ТДРезультатаЗапроса - табличный документ результата запроса.
// ПараметрыВыводаЗапроса - Структура - Параметры вывода запроса.
// * ВыводитьВременныеТаблицы - выводить временные таблицы или нет.
// * ВыводитьИдентификатор - выводить GUID для ссылок или нет.
// * ПорядокОбхода - порядок обхода результата запроса.
// * ИспользованиеЧередования - использовать чередование или нет в результирующем табличном документе.
// ОтчетПоВыполнениюЗапроса - Структура - Статистика о выполнение запроса.
// * ВремяВыполнения - время выполнения запроса.
// * КоличествоСтрок - Количество строк в результате запроса.
// * ТекстСообщения - текст сообщения об ошибке.
// Метка запроса - Строка - Метка запроса для поиска его в технологическом журнале.
//
Функция ВыполнитьЗапрос(ТекстЗапроса, ПараметрыЗапроса, ТДРезультатаЗапроса, ПараметрыВыводаЗапроса, ОтчетПоВыполнениюЗапроса, МеткаЗапроса) Экспорт
Если ЗначениеЗаполнено(МеткаЗапроса) Тогда
ЗаписатьМеткуЗапроса(ТекстЗапроса, МеткаЗапроса, "begin");
КонецЕсли;
Если ЗначениеЗаполнено(МеткаЗапроса) Тогда
ЗаписатьМеткуЗапроса(ТекстЗапроса, МеткаЗапроса, "end");
КонецЕсли;
// Массив текстов запросов.
МассивТекстов = ПостроитьМассивТекстовЗапросов(ТекстЗапроса);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса ,"\;", ";"); // Экранирование точки с запятой.
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();
// Загрузка параметров.
ЗагрузкаПараметровВЗапрос(Запрос, ПараметрыЗапроса);
// Проверка на правильность запросов.
Попытка
Начало = ТекущаяУниверсальнаяДатаВМиллисекундах();
МассивЗапросов = Запрос.ВыполнитьПакет();
Конец = ТекущаяУниверсальнаяДатаВМиллисекундах() ;
ОтчетПоВыполнениюЗапроса.ВремяВыполнения = (Конец - Начало) / 1000;
Исключение
ТекстСообщения = ОписаниеОшибки();
Возврат Неопределено;
КонецПопытки;
МассивДанныхПоЗапросу = Новый Структура;
МассивДанныхПоЗапросу.Вставить("Запрос", Запрос);
МассивДанныхПоЗапросу.Вставить("МассивТекстов", МассивТекстов);
МассивДанныхПоЗапросу.Вставить("МассивЗапросов", МассивЗапросов);
МассивДанныхПоЗапросу.Вставить("МеткаЗапроса", МеткаЗапроса);
Успешно = ВывестиРезультатЗапросов(ТДРезультатаЗапроса, МассивДанныхПоЗапросу, ПараметрыЗапроса, ПараметрыВыводаЗапроса, ОтчетПоВыполнениюЗапроса);
Если Не Успешно Тогда
Если ВозможноОшибкаИзЗаТочкиСЗапятой(ТекстЗапроса) Тогда
ОтчетПоВыполнениюЗапроса.ТекстСообщения = НСтр("ru = 'Результат запроса не был выведен. Возможно не экранирована точка с запятой. Для экранирования точки с запятой используется обратный слеш -""\;""(см. справку)'");
Иначе
ОтчетПоВыполнениюЗапроса.ТекстСообщения = НСтр("ru = 'Запрос не был выполнен, т.к. текст запроса некорректный'");
КонецЕсли;
КонецЕсли;
Возврат МассивЗапросов;
КонецФункции
Процедура ЗаписатьМеткуЗапроса(ТекстЗапроса, Метка, Статус)
Если Статус = "begin" Тогда
ТекстЗапроса = "ВЫБРАТЬ ""Marker_" + Метка+ "_"+ Статус + """ КАК МЕТКА ПОМЕСТИТЬ Marker_begin " + Символы.ПС + ";" + Символы.ПС + ТекстЗапроса + Символы.ПС + ";" + Символы.ПС;
Иначе
ТекстЗапроса = Символы.ПС + ТекстЗапроса + "ВЫБРАТЬ ""Marker_" + Метка+ "_"+ Статус + """ Как МЕТКА ПОМЕСТИТЬ Marker_end " + Символы.ПС + ";" + Символы.ПС;
КонецЕсли;
КонецПроцедуры
// Возвращает массив текстов запросов.
//
// Параметры:
// ТекстЗапроса - Текст передаваемого запроса.
//
Функция ПостроитьМассивТекстовЗапросов(знач ТекстЗапроса)
МассивТекстов = Новый Массив;
Пока Не ПустаяСтрока(ТекстЗапроса) Цикл
ТочкаСЗапятой = ";";
ПозицияТочкиСЗапятой = Найти(ТекстЗапроса, ТочкаСЗапятой);
Если Сред(ТекстЗапроса, ПозицияТочкиСЗапятой - 1, 1) = "\" Тогда
ПозицияТочкиСЗапятой = 0;
КонецЕсли;
Если ПозицияТочкиСЗапятой = 0 Тогда
ТекстОчередногоЗапроса = ТекстЗапроса;
ПозицияТочкиСЗапятой = СтрДлина(ТекстЗапроса);
Иначе
ТекстОчередногоЗапроса = Лев(ТекстЗапроса, ПозицияТочкиСЗапятой - 1);
КонецЕсли;
Если Не ПустаяСтрока(ТекстОчередногоЗапроса) Тогда
МассивТекстов.Добавить(СокрЛП(ТекстОчередногоЗапроса));
КонецЕсли;
ТекстЗапроса = Сред(ТекстЗапроса, ПозицияТочкиСЗапятой + 1);
КонецЦикла;
Возврат МассивТекстов;
КонецФункции
// Возвращает есть ли в запросе иерархия.
//
// Параметры:
// ТекстЗапроса - текст запроса.
//
Функция НаличиеИерархииВЗапросе(ТекстЗапроса)
Итоги = "ИТОГИ";
Позиция = Найти(ВРег(ТекстЗапроса), Итоги);
Возврат ?(Позиция = 0, Ложь, Истина);
КонецФункции
// Возвращает имя временной таблицы.
//
// Параметры:
// ТекстЗапроса - текст запроса.
// Буфер - переменная хранения строки вида 'ПОМЕСТИТЬ %ИмяВременнойТаблицы%'.
// Позиция - позиция после слова 'ПОМЕСТИТЬ' в тексте запроса.
//
Функция ПолучитьИмяВременнойТаблицы(ТекстЗапроса, Буфер, Позиция)
ИмяТаблицы = "";
ДлиннаТекста = СтрДлина(ТекстЗапроса);
// Добавление пустых символов к буферу.
Для Индекс = Позиция По ДлиннаТекста Цикл
Символ = Сред(ТекстЗапроса, Индекс, 1);
Если ПустаяСтрока(Символ) Тогда
Буфер = Буфер + Символ;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
// Добавление имени временной таблицы.
Для ИндексВременнойТаблицы = Индекс По ДлиннаТекста Цикл
Символ = Сред(ТекстЗапроса, ИндексВременнойТаблицы, 1);
Если Не ПустаяСтрока(Символ) Тогда
Буфер = Буфер + Символ;
ИмяТаблицы = ИмяТаблицы + Символ;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ИмяТаблицы;
КонецФункции
// Возвращает имя запроса из текста запроса.
//
// Параметры:
// ТекстЗапроса - текст запроса.
//
Функция ПолучитьИмяЗапроса(знач ТекстЗапроса)
РезультатЗначение = НСтр("ru = 'Запрос:'") + " ";
ДлинаТекста = СтрДлина(ТекстЗапроса);
ФлагПредлогаИЗ = Истина;
Пока ФлагПредлогаИЗ Цикл
СловоИЗ = "ИЗ";
ДлинаИЗ = СтрДлина(СловоИЗ);
ПозицияИЗ = Найти(ВРег(ТекстЗапроса), СловоИЗ);
Если ПозицияИЗ = 0 Тогда
Возврат РезультатЗначение;
КонецЕсли;
СимволДоИЗ = Сред(ТекстЗапроса, ПозицияИЗ - 1, 1);
СимволПослеИЗ = Сред(ТекстЗапроса, ПозицияИЗ + ДлинаИЗ, 1);
Если ПустаяСтрока(СимволДоИЗ) И ПустаяСтрока(СимволПослеИЗ) Тогда
ФлагПредлогаИЗ = Ложь;
Иначе
ТекстЗапроса = Сред(ТекстЗапроса, ПозицияИЗ + ДлинаИЗ);
КонецЕсли;
КонецЦикла;
НачальнаяПозиция = ПозицияИЗ + ДлинаИЗ;
Для Индекс = НачальнаяПозиция По ДлинаТекста Цикл
Символ = Сред(ТекстЗапроса, Индекс, 1);
Если Не ПустаяСтрока(Символ) Тогда
Прервать;
КонецЕсли;
КонецЦикла;
// Формирование имени таблицы.
Для ИндексЗапроса = Индекс По ДлинаТекста Цикл
Символ = Сред(ТекстЗапроса, ИндексЗапроса, 1);
Если Не ПустаяСтрока(Символ) Тогда
РезультатЗначение = РезультатЗначение + Символ;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Возврат РезультатЗначение;
КонецФункции
///////////////////////////////////////////////////////////////////////////
// ФУНКЦИИ РАБОТЫ С РЕЗУЛЬТАТОМ ЗАПРОСА
Функция ВозможноОшибкаИзЗаТочкиСЗапятой(ТекстЗапроса)
Позиция = 1;
Пока Позиция >0 Цикл
Позиция = Найти(ТекстЗапроса, ";");
Если Позиция > 0 Тогда
ТекстДляПоиска = Лев(ТекстЗапроса, Позиция);
Если Найти(ТекстДляПоиска, """") >0 Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
ТекстЗапроса = Сред(ТекстЗапроса, Позиция + 1);
КонецЦикла;
Возврат Ложь;
КонецФункции
// Вывод результата всех запросов с временными таблицами.
//
// Если временная таблица, то выполняется запрос из массива текстов и формируется результат.
// Если не временная таблица, то результат берется из МассиваРезультатов.
//
// Параметры:
// ТДРезультатаЗапроса - табличный документ результата запроса.
// МассивДанныхПоЗапросу - Структура - Содержит данные по запроса.
// * Запрос - Запрос - передаваемый запрос.
// * МассивТекстов - Массив - массив текстов запросов.
// * МассивЗапросов - Массив - массив результатов запросов.
// ПараметрыЗапроса - массив параметров запросов.
// ПараметрыВыводаЗапроса - Структура - Параметры вывода запроса.
// * ВыводитьВременныеТаблицы - выводить временные таблицы или нет.
// * ВыводитьИдентификатор - выводить GUID для ссылок или нет.
// * ПорядокОбхода - порядок обхода результата запроса.
// * ИспользованиеЧередования - использовать чередование или нет в результирующем табличном документе.
// ОтчетПоВыполнениюЗапроса - Структура - Статистика о выполнение запроса.
// * ВремяВыполнения - время выполнения запроса.
// * КоличествоСтрок - Количество строк в результате запроса.
// * ТекстСообщения - текст сообщения об ошибке.
//
Функция ВывестиРезультатЗапросов(ТДРезультатаЗапроса, МассивДанныхПоЗапросу, ПараметрыЗапроса, ПараметрыВыводаЗапроса, ОтчетПоВыполнениюЗапроса)
МассивТекстов = МассивДанныхПоЗапросу.МассивТекстов;
МассивЗапросов = МассивДанныхПоЗапросу.МассивЗапросов;
МеткаЗапроса = МассивДанныхПоЗапросу.МеткаЗапроса;
КоличествоТекстовЗапросов = МассивТекстов.Количество();
КоличествоРезультатовЗапросов = МассивЗапросов.Количество();
Если КоличествоРезультатовЗапросов <> КоличествоТекстовЗапросов Тогда
Возврат Ложь;
КонецЕсли;
// Накапливаемый запрос необходим для вывода временных таблиц, в том числе и удаляемых.
НакапливаемыйЗапрос = Новый Запрос;
ЗагрузкаПараметровВЗапрос(НакапливаемыйЗапрос, ПараметрыЗапроса);
Для Индекс = 0 По КоличествоТекстовЗапросов - 1 Цикл
ТекстЗапросаМассива = МассивТекстов.Получить(Индекс);
Если ЗначениеЗаполнено(МеткаЗапроса) И Найти(ТекстЗапросаМассива, МеткаЗапроса) > 0 Тогда
КоличествоРезультатовЗапросов = КоличествоРезультатовЗапросов - 1;
Продолжить;
КонецЕсли;
КоличествоСтрокОдногоЗапроса = 0;
МассивШириныКолонок = Новый Массив;
Свертка = ОпределитьСвертку(Индекс, КоличествоРезультатовЗапросов);
Поместить = "ПОМЕСТИТЬ";
ДлинаПоместить = СтрДлина(Поместить);
ПозицияПоместить = Найти(ВРег(ТекстЗапросаМассива), Поместить);
Если Индекс = 0 Тогда
СимволРазделенияЗапросов = "";
Иначе
СимволРазделенияЗапросов = ";";
КонецЕсли;
НакапливаемыйЗапрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
НакопленныйТекст = НакапливаемыйЗапрос.Текст + СимволРазделенияЗапросов + МассивТекстов.Получить(Индекс);
НакапливаемыйЗапрос.Текст = НакопленныйТекст;
// Если временная таблица и выводить временные таблицы.
Если ПозицияПоместить <> 0 И ПараметрыВыводаЗапроса.ВыводитьВременныеТаблицы Тогда
БуферПоместить = Сред(ТекстЗапросаМассива, ПозицияПоместить, ДлинаПоместить);
ПозицияПослеПоместить = ПозицияПоместить + ДлинаПоместить;
ИмяТаблицы = ПолучитьИмяВременнойТаблицы(ТекстЗапросаМассива, БуферПоместить, ПозицияПослеПоместить);
// Выполнение запроса.
ИмяЗапроса = "";
Результат = ВыполнитьЗапросСВременнойТаблицей(НакапливаемыйЗапрос, ИмяТаблицы, ИмяЗапроса);
Если Результат <> Неопределено Тогда
ТД = ВывестиРезультатОдногоЗапроса(ИмяЗапроса, Результат, Свертка, ПараметрыВыводаЗапроса, Ложь, КоличествоСтрокОдногоЗапроса, МассивШириныКолонок);
ТДРезультатаЗапроса.Вывести(ТД);
КонецЕсли;
ИначеЕсли ПозицияПоместить = 0 Тогда // Если таблица не временная, то используется готовый результат.
Результат = МассивЗапросов.Получить(Индекс);
ИмяЗапроса = ПолучитьИмяЗапроса(ТекстЗапросаМассива);
Иерархия = НаличиеИерархииВЗапросе(ТекстЗапросаМассива);
ТД = ВывестиРезультатОдногоЗапроса(ИмяЗапроса, Результат, Свертка, ПараметрыВыводаЗапроса, Иерархия, КоличествоСтрокОдногоЗапроса, МассивШириныКолонок);
ТДРезультатаЗапроса.Вывести(ТД);
КонецЕсли;
ОтчетПоВыполнениюЗапроса.КоличествоСтрок = ОтчетПоВыполнениюЗапроса.КоличествоСтрок + КоличествоСтрокОдногоЗапроса;
КонецЦикла;
Возврат Истина;
КонецФункции
// Вывод результат запроса в табличный документ.
//
// Параметры:
// ИмяЗапроса - Строка - имя запроса.
// РезультатЗапроса - результат запроса.
// Открыта - свернуть результат одного запроса в выводимом табличном документе.
// ПараметрыВыводаЗапроса - Структура - Параметры вывода запроса.
// * ВыводитьВременныеТаблицы - выводить временные таблицы или нет.
// * ВыводитьИдентификатор - выводить GUID для ссылок или нет.
// * ПорядокОбхода - порядок обхода результата запроса.
// * ИспользованиеЧередования - использовать чередование или нет в результирующем табличном документе.
// Иерархия - наличие итогов в запросе.
// КоличествоСтрок - Число - Количество строк в результате данного запроса.
// МассивШириныКолонок - массив максимальной ширины каждой колонки.
//
Функция ВывестиРезультатОдногоЗапроса(ИмяЗапроса, РезультатЗапроса, Открыта, ПараметрыВыводаЗапроса, Иерархия, КоличествоСтрок, МассивШириныКолонок)
РезультатЗапроса = ВыгрузкаРезультата(РезультатЗапроса, ПараметрыВыводаЗапроса.ПорядокОбхода, Иерархия);
ВыходнойМакет = Новый ТабличныйДокумент;
МакетОдногоЗапроса = Новый ТабличныйДокумент;
Если РезультатЗапроса = Неопределено Тогда
Возврат ВыходнойМакет;
КонецЕсли;
МакетОдногоЗапроса.Очистить();
ВыходнойМакет.Очистить();
УровеньВерхний = 1;
УровеньЗаголовкаИДеталей = 2;
// Вывод в табличный документ.
ЗаголовкиКолонок = ВывестиЗаголовкиКолонок(РезультатЗапроса, МассивШириныКолонок);
ПараметрыВыводаЗапроса.Вставить("МассивШириныКолонок", МассивШириныКолонок);
ПараметрыВыводаЗапроса.Вставить("КоличествоСтрок", КоличествоСтрок);
Детали = ВывестиДетали(РезультатЗапроса, ПараметрыВыводаЗапроса);
КоличествоСтрок = ПараметрыВыводаЗапроса.КоличествоСтрок;
Заголовок = ВывестиЗаголовокЗапроса(ИмяЗапроса, КоличествоСтрок);
МакетОдногоЗапроса.НачатьАвтогруппировкуСтрок();
МакетОдногоЗапроса.Вывести(Заголовок, УровеньВерхний);
МакетОдногоЗапроса.Вывести(ЗаголовкиКолонок, УровеньЗаголовкаИДеталей,, Открыта);
МакетОдногоЗапроса.Вывести(Детали, УровеньЗаголовкаИДеталей,, Открыта);
МакетОдногоЗапроса.ЗакончитьАвтогруппировкуСтрок();
УстановкаАвтоШирины(ВыходнойМакет, МассивШириныКолонок);
ВыходнойМакет.Вывести(МакетОдногоЗапроса).СоздатьФорматСтрок();
Возврат ВыходнойМакет;
КонецФункции
// Возвращает ТаблицуЗначений или ДеревоЗначений результата.
//
// Параметры:
// РезультатЗапроса - результат запроса.
// Иерархия - есть ли иерархия в запросе.
//
Функция ВыгрузкаРезультата(РезультатЗапроса, ПорядокОбхода, Иерархия)
Если РезультатЗапроса = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если ВРег(ПорядокОбхода) = "АВТО" Тогда
Если Иерархия Тогда
ВыгруженноеЗначение = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Иначе
ВыгруженноеЗначение = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой);
КонецЕсли;
Иначе
ВыгруженноеЗначение = РезультатЗапроса.Выгрузить(ОбходРезультатаЗапроса.Прямой);
КонецЕсли;
Возврат ВыгруженноеЗначение;
КонецФункции
Функция ВывестиЗаголовокЗапроса(ИмяЗапроса,КоличествоСтрок)
Заголовок = Новый ТабличныйДокумент;
МакетВывода = ПолучитьМакет("РезультатВыполненияЗапроса");
ОбластьЗаголовок = МакетВывода.ПолучитьОбласть("ЗапросИмя");
ОбластьЗаголовок.Параметры.ИмяЗапроса = ИмяЗапроса;
ОбластьЗаголовок.Параметры.КоличествоСтрок = КоличествоСтрок;
Заголовок.Вывести(ОбластьЗаголовок);
Возврат Заголовок;
КонецФункции
Функция ВывестиЗаголовкиКолонок(Результат, МассивШириныКолонок)
МакетВывода = ПолучитьМакет("РезультатВыполненияЗапроса");
ВерхнийЗаголовокКолонок = Новый ТабличныйДокумент;
ЗаголовокКолонок = Новый ТабличныйДокумент;
ОбластьЗаголовкиКолонок = МакетВывода.ПолучитьОбласть("ОбластьЯчейки");
Область = ОбластьЗаголовкиКолонок.Область();
Область.Шрифт = Новый Шрифт(,, Ложь);
Область.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;
Область.ЦветФона = Новый Цвет(204, 192, 133);
Индекс = 0;
// Вывод заголовка таблицы.
Для каждого Стр Из Результат.Колонки Цикл
УстановкаМаксимальнойШириныВМассив(Индекс, Стр.Имя, МассивШириныКолонок);
ОбластьЗаголовкиКолонок.Параметры.Значение = Стр.Имя;
Об = ЗаголовокКолонок.Присоединить(ОбластьЗаголовкиКолонок);
Об.ШиринаКолонки = МассивШириныКолонок.Получить(Индекс);
Индекс = Индекс + 1;
КонецЦикла;
ВерхнийЗаголовокКолонок.Вывести(ЗаголовокКолонок);
Возврат ВерхнийЗаголовокКолонок;
КонецФункции
Функция ВывестиДетали(Результат, ПараметрыВыводаЗапроса)
Детали = Новый ТабличныйДокумент;
Уровень = 1;
Детали.НачатьАвтогруппировкуСтрок();
Если ТипЗнч(Результат) = Тип("ДеревоЗначений") Тогда
ИндексСтроки = 1;
КоличествоКолонок = Результат.Колонки.Количество();
ВывестиДеталиСИерархией(Детали, Результат, ПараметрыВыводаЗапроса, Уровень, КоличествоКолонок, ИндексСтроки);
КонецЕсли;
Если ТипЗнч(Результат) = Тип("ТаблицаЗначений") Тогда
КоличествоКолонок = Результат.Колонки.Количество();
ВывестиДеталиБезИерархии(Детали, Результат, ПараметрыВыводаЗапроса, Уровень, КоличествоКолонок);
КонецЕсли;
Детали.ЗакончитьАвтогруппировкуСтрок();
Возврат Детали;
КонецФункции
Функция ВывестиДеталиБезИерархии(ОбщиеДетали, Результат, ПараметрыВыводаЗапроса, Уровень, КоличествоКолонок)
МакетВывода = ПолучитьМакет("РезультатВыполненияЗапроса");
ПараметрыВыводаЗапроса.КоличествоСтрок = Результат.Количество();
ИндексСтроки = 1;
Для каждого Строка Из Результат Цикл
Детали = Новый ТабличныйДокумент;
ОбластьДетали = МакетВывода.ПолучитьОбласть("ОбластьЯчейки");
Область = ОбластьДетали.ТекущаяОбласть;
Область.Шрифт = Новый Шрифт(,, Ложь);
Область.ЦветФона = ОпределитьЦветФонаПоИндексу(ИндексСтроки, ПараметрыВыводаЗапроса.ИспользованиеЧередования);
Для Индекс = 0 По КоличествоКолонок - 1 Цикл
Значение = Строка.Получить(Индекс);
Если ТипЗнч(Значение) = Тип("ТаблицаЗначений") Тогда
Значение = ПреобразоватьТаблицуЗначенийВСтроке(Значение);
КонецЕсли;
ЗначениеДляПараметра = Значение;
Если ЭтоСсылка(ТипЗнч(Значение)) И ПараметрыВыводаЗапроса.ВыводитьИдентификатор Тогда
Попытка
ЗначениеДляПараметра = Значение.УникальныйИдентификатор();
Исключение
ЗначениеДляПараметра = Значение;
КонецПопытки;
КонецЕсли;
ОбластьДетали.Параметры.Значение = ЗначениеДляПараметра;
ОбластьДетали.Параметры.Расшифровка = Значение;
УстановкаМаксимальнойШириныВМассив(Индекс, ЗначениеДляПараметра, ПараметрыВыводаЗапроса.МассивШириныКолонок);
Детали.Присоединить(ОбластьДетали);
КонецЦикла;
ИндексСтроки = ИндексСтроки + 1;
ОбщиеДетали.Вывести(Детали, Уровень);
КонецЦикла;
КонецФункции
Функция ВывестиДеталиСИерархией(ОбщиеДетали, Результат, ПараметрыВыводаЗапроса , Уровень, КоличествоКолонок, ИндексСтроки)
МакетВывода = ПолучитьМакет("РезультатВыполненияЗапроса");
Открыта = Истина;
Подчиненные = Результат.Строки;
ПараметрыВыводаЗапроса.КоличествоСтрок = ПараметрыВыводаЗапроса.КоличествоСтрок + Подчиненные.Количество();
Для Каждого Подчиненный Из Подчиненные Цикл
Детали = Новый ТабличныйДокумент;
ОбластьДетали = МакетВывода.ПолучитьОбласть("ОбластьЯчейки");
Область = ОбластьДетали.ТекущаяОбласть;
Область.Шрифт = Новый Шрифт(,, Ложь);
Область.ЦветФона = ОпределитьЦветФонаПоИндексу(ИндексСтроки, ПараметрыВыводаЗапроса.ИспользованиеЧередования);
Для Индекс = 0 По КоличествоКолонок - 1 Цикл
Значение = Подчиненный.Получить(Индекс);
Если ТипЗнч(Значение) = Тип("ТаблицаЗначений") Тогда
Значение = ПреобразоватьТаблицуЗначенийВСтроке(Значение);
КонецЕсли;
ЗначениеДляПараметра = Значение;
// Определение количество отступа по уровню.
Пробел = ОпределениеОтступаПоУровню(Уровень, Индекс, Открыта);
Если ЭтоСсылка(ТипЗнч(Значение)) И ПараметрыВыводаЗапроса.ВыводитьИдентификатор Тогда
Попытка
ЗначениеДляПараметра = Значение.УникальныйИдентификатор();
Исключение
ЗначениеДляПараметра = Значение;
КонецПопытки;
КонецЕсли;
ЗначениеДляПараметра = "" + Пробел + ЗначениеДляПараметра;
ОбластьДетали.Параметры.Значение = ЗначениеДляПараметра;
ОбластьДетали.Параметры.Расшифровка = Значение;
УстановкаМаксимальнойШириныВМассив(Индекс, ЗначениеДляПараметра, ПараметрыВыводаЗапроса.МассивШириныКолонок);
Детали.Присоединить(ОбластьДетали);
КонецЦикла;
ОбщиеДетали.Вывести(Детали, Уровень,, Открыта);
ИндексСтроки = ИндексСтроки + 1;
ВывестиДеталиСИерархией(ОбщиеДетали, Подчиненный, ПараметрыВыводаЗапроса, Уровень + 1, КоличествоКолонок, ИндексСтроки);
КонецЦикла;
КонецФункции
// Определяет сворачивать или нет результат одного запроса.
//
// Параметры:
// ПозицияТекущегоЗапроса - порядок запроса в пакете.
// КоличествоВсехЗапросов - количество всех запросов в пакете.
//
Функция ОпределитьСвертку(знач ПозицияТекущегоЗапроса, КоличествоВсехЗапросов)
ПозицияТекущегоЗапроса = ПозицияТекущегоЗапроса + 1;
Если КоличествоВсехЗапросов = 1 Тогда
РезультатЗначение = Истина;
Иначе
Если ПозицияТекущегоЗапроса = КоличествоВсехЗапросов Тогда
РезультатЗначение = Истина;
Иначе
РезультатЗначение = Ложь;
КонецЕсли;
КонецЕсли;
Возврат РезультатЗначение;
КонецФункции
// Выводит строку с автошириной колонок.
//
// Параметры:
// РезультатЗапроса - табличный документ с результатом запроса.
// МассивМаксШирины - массив ширины колонок для отдельного запроса.
//
Процедура УстановкаАвтоШирины(РезультатЗапроса, МассивМаксШирины)
ВерхняяГраница = МассивМаксШирины.ВГраница();
Если ВерхняяГраница = -1 Тогда
Возврат;
КонецЕсли;
Для Индекс = 0 По ВерхняяГраница Цикл
ВременныйТабличныйДокумент = Новый ТабличныйДокумент;
Стр = ВременныйТабличныйДокумент.ПолучитьОбласть(1, Индекс + 1, 1, Индекс + 1);
РезультатЗапроса.Присоединить(Стр).ШиринаКолонки = МассивМаксШирины.Получить(Индекс);
КонецЦикла;
КонецПроцедуры
///////////////////////////////////////////////////////////////////////////
// ПРОЧИЕ ПРОЦЕДУРЫ И ФУНКЦИИ
// Формирует список возможных типов конфигурации.
//
// Параметры:
// СписокДобавленныхТипов - список типов, добавленных "вручную".
//
Функция СформироватьСписокТипов(СписокДобавленныхТипов = Неопределено) Экспорт
МассивТипов = ДоступныеТипыДанных.Типы();
НеПримитивныеТипы = Новый СписокЗначений;
НеПримитивныеТипы.ЗагрузитьЗначения(МассивТипов);
НеПримитивныеТипы.СортироватьПоЗначению(НаправлениеСортировки.Возр);
СписокТипов = Новый СписокЗначений;
СписокТипов.Добавить("Строка", НСтр("ru = 'Строка'"));
СписокТипов.Добавить("Число", НСтр("ru = 'Число'"));
СписокТипов.Добавить("Дата", НСтр("ru = 'Дата'"));
СписокТипов.Добавить("Булево", НСтр("ru = 'Булево'"));
СписокТипов.Добавить("Граница", НСтр("ru = 'Граница'"));
СписокТипов.Добавить("МоментВремени", НСтр("ru = 'Момент времени'"));
СписокТипов.Добавить("СписокЗначений", НСтр("ru = 'Список значений'"));
СписокТипов.Добавить("ТаблицаЗначений", НСтр("ru = 'Таблица значений'"));
СписокДобавленныхТипов = Новый СписокЗначений;
СписокДобавленныхТипов = СписокТипов.Скопировать();
Для каждого Стр Из НеПримитивныеТипы Цикл
ЗначениеТипа = XMLТип(Стр.Значение).ИмяТипа;
ПредставлениеТипа = Строка(Стр.Значение);
СписокТипов.Добавить(ЗначениеТипа, ПредставлениеТипа);
КонецЦикла;
Возврат СписокТипов;
КонецФункции
// Определяет отступ по уровню.
//
// Параметры:
// Уровень - переданный уровень в дереве.
// НомерКолонки - номер колонки, отступ устанавливается только для первой колонки.
// Открыта - открыта группа или нет.
//
Функция ОпределениеОтступаПоУровню(Уровень, НомерКолонки, Открыта)
Пробел = "";
Если НомерКолонки = 0 Тогда
Если Уровень > 1 Тогда
Для Индекс = 1 По Уровень Цикл
Пробел = Пробел + Символы.Таб;
КонецЦикла;
Открыта = Ложь;
Иначе
Открыта = Истина;
КонецЕсли;
КонецЕсли;
Возврат Пробел;
КонецФункции
// Возвращает строковое представление типа по значению.
//
// Параметры:
// Значение - передаваемое значение.
//
Функция ИмяТипаИзЗначения(Значение) Экспорт
Если ТипЗнч(Значение) = Тип("Строка") Тогда
ИмяТипа = "Строка";
ИначеЕсли ТипЗнч(Значение) = Тип("Число") Тогда
ИмяТипа = "Число";
ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
ИмяТипа = "Булево";
ИначеЕсли ТипЗнч(Значение) = Тип("Дата") Тогда
ИмяТипа = "Дата";
ИначеЕсли ТипЗнч(Значение) = Тип("МоментВремени") Тогда
ИмяТипа = "МоментВремени";
ИначеЕсли ТипЗнч(Значение) = Тип("Неопределено") Тогда
ИмяТипа = "Строка";
Иначе
ИмяТипа = xmlТип(ТипЗнч(Значение)).ИмяТипа;
КонецЕсли;
Возврат ИмяТипа;
КонецФункции
// Возвращает вид границы из ее строкового представления.
//
// Параметры:
// Вид - строковое представление вида границы.
//
Функция ОпределениеВидаГраницы(Вид) Экспорт
Если ВРег(Вид) = "ИСКЛЮЧАЯ" Тогда
Результат = ВидГраницы.Исключая;
Иначе
Результат = ВидГраницы.Включая;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает представление значения.
//
// Параметры:
// Значение - передаваемое значение.
//
Функция ФормированиеПредставленияЗначения(Значение) Экспорт
Результат = "";
Если ТипЗнч(Значение) = Тип("ТаблицаЗначений") Тогда
ИтоговаяСтрока = "Таблица: строк = %КоличествоСтрок%, колонок = %КоличествоКолонок%";
ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока, "%КоличествоСтрок%", Строка(Значение.Количество()));
ИтоговаяСтрока = СтрЗаменить(ИтоговаяСтрока, "%КоличествоКолонок%", Строка(Значение.Колонки.Количество()));
Результат = ИтоговаяСтрока;
ИначеЕсли ТипЗнч(Значение) = Тип("МоментВремени") Тогда
Результат = Строка(Значение.Дата) + "; " + Строка(Значение.Ссылка);
ИначеЕсли ТипЗнч(Значение) = Тип("Граница") Тогда
Результат = Строка(Значение.Значение) + "; " + Строка(Значение.ВидГраницы);
КонецЕсли;
Возврат Результат;
КонецФункции
// Фильтрует список типов для данного контекста.
//
// Параметры:
// СписокТипов - список значений передаваемых типов.
// Контекст - передаваемый контекст в виде строки.
//
Процедура ФильтрацияСпискаТипов(СписокТипов, Контекст) Экспорт
Если нРег(Контекст) = "граница" Тогда
Элемент = СписокТипов.НайтиПоЗначению("СписокЗначений");
СписокТипов.Удалить(Элемент);
Элемент = СписокТипов.НайтиПоЗначению("ТаблицаЗначений");
СписокТипов.Удалить(Элемент);
Элемент = СписокТипов.НайтиПоЗначению("Граница");
СписокТипов.Удалить(Элемент);
КонецЕсли;
Элемент = СписокТипов.НайтиПоЗначению("TypeDescription"); // Тип "Описание типов" удаляется всегда.
СписокТипов.Удалить(Элемент);
КонецПроцедуры
// Устанавливает максимальную ширину ячейки для каждой колонки.
//
Процедура УстановкаМаксимальнойШириныВМассив(Индекс, знач Элем, МассивШириныКолонок)
МаксимальнаяШиринаЯчейки = 100;
Элем = СокрП(Элем);
Элем = СтрДлина(Элем);
Если Индекс > МассивШириныКолонок.ВГраница() Тогда
Если Элем < МаксимальнаяШиринаЯчейки Тогда
МассивШириныКолонок.Вставить(Индекс, Элем + 1);
Иначе
МассивШириныКолонок.Вставить(Индекс, МаксимальнаяШиринаЯчейки);
КонецЕсли;
Иначе
Макс = МассивШириныКолонок.Получить(Индекс);
Если Элем > Макс Тогда
Если Элем < МаксимальнаяШиринаЯчейки Тогда
МассивШириныКолонок.Установить(Индекс, Элем + 1);
Иначе
МассивШириныКолонок.Установить(Индекс, МаксимальнаяШиринаЯчейки);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Проверяет является ли тип ссылкой.
//
// Параметры:
// Тип - передаваемый тип.
//
Функция ЭтоСсылка(Тип) Экспорт
Возврат Справочники.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ Документы.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ Перечисления.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(Тип)
ИЛИ Задачи.ТипВсеСсылки().СодержитТип(Тип)
ИЛИ ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип);
КонецФункции
// Возвращает результат выполнения временной таблицы по имени.
//
// Параметры:
// Запрос - передаваемый запрос.
// ИмяВременнойТаблицы - имя временной таблицы.
// ИмяЗапроса - имя запроса, изменяемое в теле процедуры.
//
Функция ВыполнитьЗапросСВременнойТаблицей(знач ЗапросДляВыполнения, ИмяВременнойТаблицы, ИмяЗапроса)
ЗапросДляВыполнения.Текст = ЗапросДляВыполнения.Текст + " ; " + "ВЫБРАТЬ * ИЗ " + ИмяВременнойТаблицы;
Попытка
Результат = ЗапросДляВыполнения.Выполнить();
ИмяЗапроса = НСтр("ru = 'Временная таблица:'") + " " + ИмяВременнойТаблицы;
Исключение
Результат = Неопределено;
КонецПопытки;
Возврат Результат;
КонецФункции
// Возвращает цвет фона табличного документа по индексу строки и по использованию.
//
// Параметры:
// Индекс - передаваемый индекс строки.
// Использование - использовать или нет чередование.
//
Функция ОпределитьЦветФонаПоИндексу(Индекс, Использование)
ЦветЧередования = Новый Цвет(245, 242, 221);
Если Не Использование Тогда
Возврат WebЦвета.Белый;
КонецЕсли;
Остаток = Индекс % 2;
Если Остаток = 0 Тогда
Цвет = ЦветЧередования;
Иначе
Цвет = WebЦвета.Белый;
КонецЕсли;
Возврат Цвет;
КонецФункции
Функция ПреобразоватьТаблицуЗначенийВСтроке(ТаблицаЗначений)
ПредставлениеТаблицыЗначений = "";
Для каждого СтрокаТаблицыЗначений Из ТаблицаЗначений Цикл
Разделитель = "";
Для каждого ЯчейкаТаблицыЗначений Из СтрокаТаблицыЗначений Цикл
ПредставлениеТаблицыЗначений = ПредставлениеТаблицыЗначений + Разделитель + Строка(ЯчейкаТаблицыЗначений);
Разделитель = ";";
КонецЦикла;
ПредставлениеТаблицыЗначений = ПредставлениеТаблицыЗначений + Символы.ПС;
КонецЦикла;
Значение = ПредставлениеТаблицыЗначений;
Возврат ПредставлениеТаблицыЗначений
КонецФункции
#КонецОбласти
#Область РаботаСТехнологическимЖурналом
Функция ФайлКонфигурацииСуществует(ПутьКФайлуКонфигурации)
ФайлКонфигурации = Новый Файл(ПутьКФайлуКонфигурации + ПолучитьРазделительПути() + "logcfg.xml");
Если ФайлКонфигурации.Существует() Тогда
ФайлТекстаКонфигурации = Новый ЧтениеТекста(ФайлКонфигурации.ПолноеИмя);
СтрокаТекстКонфигурации = ФайлТекстаКонфигурации.ПрочитатьСтроку();
Пока СтрокаТекстКонфигурации <> Неопределено Цикл
Если Найти(СтрокаТекстКонфигурации, "ConsoleQueries") > 0 Тогда
Возврат Ложь;
КонецЕсли;
СтрокаТекстКонфигурации = ФайлТекстаКонфигурации.ПрочитатьСтроку();
КонецЦикла;
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Включает технологический журнал.
//
Процедура ВключениеТехнологическогоЖурнала(ПараметрыТехнологическогоЖурнала, РезультатВключения) Экспорт
КаталогКонфигурацииПриложения = ПутьККонфигурационномуФайлу();
Если КаталогКонфигурацииПриложения <> Неопределено Тогда
Если ФайлКонфигурацииСуществует(КаталогКонфигурацииПриложения) Тогда
ПереместитьФайл(КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.xml", КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.off");
КонецЕсли;
КаталогВременныхФайлов = КаталогВременныхФайлов();
СоздатьКаталог(КаталогВременныхФайлов + "1c_logs");
КаталогСЛогФайлами = КаталогВременныхФайлов + "1c_logs";
ЛогФайлыДляУдаления = НайтиФайлы(КаталогСЛогФайлами, "*.log", Истина);
Для каждого Файл Из ЛогФайлыДляУдаления Цикл
Попытка
УдалитьФайлы(Файл.ПолноеИмя);
Исключение
// Удаление файла log вызвало ошибку (нет прав, файл уже не существует).
КонецПопытки;
КонецЦикла;
ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь.Наименование;
МассивСобытие = Новый Массив;
МассивСобытие.Добавить("db2");
МассивСобытие.Добавить("dbmssql");
МассивСобытие.Добавить("dbpostgrs");
МассивСобытие.Добавить("dboracle");
МассивСобытие.Добавить("SDBL");
МассивСобытие.Добавить("DBV8DBEng");
МассивСобытие.Добавить("QERR");
МассивСобытие.Добавить("EXCP");
МассивСобытие.Добавить("EXCPCNTX");
Текст = "<?xml version=""1.0"" encoding=""UTF-8""?>" + Символы.ПС+ "<!-- ConsoleQueries -->" + Символы.ПС+ "<config xmlns=""http://v8.1c.ru/v8/tech-log"">" +
Символы.ПС + "<dump create=""false"" type=""0"" prntscrn=""false""/>" + Символы.ПС + "<log history=""1"" location=""" + КаталогСЛогФайлами + """>" + Символы.ПС;
Для каждого событие Из МассивСобытие Цикл
Текст = Текст + "<event>" + Символы.ПС+ " <eq property=""name"" value=""" + событие + """/>" + Символы.ПС + "</event>" + Символы.ПС;
КонецЦикла;
Текст = Текст + "<property name=""all""/>" + Символы.ПС+ " <property name=""sql""/>" + Символы.ПС + " <property name=""plansqltext""/>" + Символы.ПС+ "</log>" + Символы.ПС+ "<plansql/>" + Символы.ПС + "</config>";
ПолныйПутьКонфигурационногоФайла = КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.xml";
Попытка
Файл = Новый ЗаписьТекста(ПолныйПутьКонфигурационногоФайла);
Файл.ЗаписатьСтроку(Текст);
Файл.Закрыть();
Исключение
РезультатВключения.Результат = Ложь;
РезультатВключения.Причина = НСтр("ru = 'Ошибка создания конфигурационного файла в каталоге'") + " " + КаталогКонфигурацииПриложения + Символы.ПС + НСтр("ru = 'Проверьте права доступа.'");
КонецПопытки;
ИдентификаторПроцессаОС = ИдентификаторПроцессаОС();
ПараметрыТехнологическогоЖурнала.КаталогСЛогФайлами = КаталогСЛогФайлами;
ПараметрыТехнологическогоЖурнала.ИдентификаторПроцессаОС = Формат(ИдентификаторПроцессаОС, "ЧРД=; ЧРГ=; ЧГ=0");
КонецЕсли;
КонецПроцедуры
Функция ПутьККонфигурационномуФайлу()
СистемнаяИнформация = Новый СистемнаяИнформация();
Если НЕ ((СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86) Или (СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64)) Тогда
Возврат Неопределено;
КонецЕсли;
КаталогаОбщихКонфигурационныхФайлов = КаталогПрограммы() + "conf";
ФайлУказатель = Новый Файл(КаталогаОбщихКонфигурационныхФайлов + ПолучитьРазделительПутиСервера() + "conf.cfg");
Если ФайлУказатель.Существует() Тогда
ФайлКонфигурации = Новый ЧтениеТекста(ФайлУказатель.ПолноеИмя);
Строка = ФайлКонфигурации.ПрочитатьСтроку();
Пока Строка <> Неопределено Цикл
Позиция = Найти(Строка, "ConfLocation=");
Если Позиция > 0 Тогда
КаталогКонфигурацииПриложения = СокрЛП(Сред(Строка, Позиция + 13));
Прервать;
КонецЕсли;
Строка = ФайлКонфигурации.ПрочитатьСтроку();
КонецЦикла;
КонецЕсли;
Возврат КаталогКонфигурацииПриложения;
КонецФункции
// Выключает технологический журнал.
//
Процедура ВыключениеТехнологическогоЖурнала() Экспорт
КаталогКонфигурацииПриложения = ПутьККонфигурационномуФайлу();
Если КаталогКонфигурацииПриложения <> Неопределено Тогда
УдалитьФайлы(КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.xml");
КонецЕсли;
СтарыйФайлКонфигурации = Новый Файл(КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.off");
Если СтарыйФайлКонфигурации.Существует() Тогда
ПереместитьФайл(КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.off", КаталогКонфигурацииПриложения + ПолучитьРазделительПути() + "logcfg.xml");
КонецЕсли;
КонецПроцедуры
// Находит в файле технологического журнала запрос и план выполнения запроса.
//
Процедура ПрочитатьТехнологическийЖурнал(ПутьКФайлу, ИДМетки, ПрочитанныеДанные) Экспорт
МассивСтрок = Новый Массив;
ДобавлятьВМассив = Ложь;
ВременныйФайл = ПолучитьИмяВременногоФайла(".log");
КопироватьФайл(ПутьКФайлу, ВременныйФайл);
Файл = Новый ЧтениеТекста();
Файл.Открыть(ВременныйФайл);
Строка = Файл.ПрочитатьСтроку();
ВременнаяСтрока = "";
Пока Строка <> Неопределено Цикл
Если ДобавлятьВМассив Тогда
Если ДобавлятьВМассив И Найти(Строка, ИДМетки + "_end") = 0 Тогда
Если Сред(Строка, 3, 1) = ":" И Сред(Строка, 6, 1) = "." Тогда
Если ЗначениеЗаполнено(ВременнаяСтрока)
И Найти(ВременнаяСтрока, "Sql=") > 0
И Найти(ВременнаяСтрока, "planSQLText=") > 0
И Найти(ВременнаяСтрока, "Marker_" + ИДМетки) = 0 Тогда
МассивСтрок.Добавить(ВременнаяСтрока);
КонецЕсли;
ВременнаяСтрока = Строка;
Иначе
ВременнаяСтрока = ВременнаяСтрока + Символы.ПС + Строка;
КонецЕсли;
Иначе
Прервать;
КонецЕсли;
КонецЕсли;
Если Найти(Строка, ИДМетки + "_begin") > 0 Тогда
ДобавлятьВМассив = Истина;
КонецЕсли;
Строка = Файл.ПрочитатьСтроку();
КонецЦикла;
СКЛТекстИзТехЖурнала = "";
ПланВыполненияЗапроса = "";
Если МассивСтрок.Количество() > 1 Тогда
Разделитель = Символы.ПС + Символы.ПС;
Иначе
Разделитель = "";
КонецЕсли;
Для каждого Строка Из МассивСтрок Цикл
ПозицияНачало = Найти(Строка, ",");
СтрокаСдвиг = Сред(Строка, ПозицияНачало + 1);
ПозицияКонец = Найти(СтрокаСдвиг, ",");
ТипСУБД = ВРег(Лев(СтрокаСдвиг, ПозицияКонец -1));
Позиция = Найти(СтрокаСдвиг, "Sql=");
Если Сред(СтрокаСдвиг, Позиция + 4, 1) = """" ИЛИ Сред(СтрокаСдвиг, Позиция + 4, 1) = "'" Тогда
СтрокаСдвиг = Сред(СтрокаСдвиг, Позиция + 5);
Иначе
СтрокаСдвиг = Сред(СтрокаСдвиг, Позиция + 4);
КонецЕсли;
Если ТипСУБД = "DBMSSQL" Тогда
Позиция = Найти(СтрокаСдвиг, ",Rows");
СКЛТекстТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-2);
Позиция = Найти(СтрокаСдвиг, "planSQLText=");
СтрокаСдвиг = Сред(СтрокаСдвиг, Позиция + 13);
Позиция = Найти(СтрокаСдвиг, "'");
ПланВыполненияЗапросаТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-1);
ИначеЕсли ТипСУБД = "DBPOSTGRS" Тогда
Позиция = Найти(СтрокаСдвиг, ",planSQLText=");
СКЛТекстТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-1);
СтрокаСдвиг = Сред(СтрокаСдвиг, Позиция + 13);
Позиция = Найти(СтрокаСдвиг, ",Result");
ПланВыполненияЗапросаТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-1);
Иначе
Позиция = Найти(СтрокаСдвиг, "',");
СКЛТекстТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-2);
Позиция = Найти(СтрокаСдвиг, "planSQLText=");
СтрокаСдвиг = Сред(СтрокаСдвиг, Позиция + 13);
Позиция = Найти(СтрокаСдвиг, "'");
ПланВыполненияЗапросаТекущийЗапрос = Лев(СтрокаСдвиг, Позиция-1);
КонецЕсли;
ПланВыполненияЗапроса = ПланВыполненияЗапроса + ПланВыполненияЗапросаТекущийЗапрос + Разделитель;
СКЛТекстИзТехЖурнала = СКЛТекстИзТехЖурнала + СКЛТекстТекущийЗапрос +Разделитель;
КонецЦикла;
ПрочитанныеДанные.ТипСУБД = ТипСУБД;
ПрочитанныеДанные.СКЛЗапрос = СокрЛП(СКЛТекстИзТехЖурнала);
ПрочитанныеДанные.ПланВыполненияЗапроса = СокрЛП(ПланВыполненияЗапроса);
КонецПроцедуры
// Возвращает идентификатор процесса ОС.
//
Функция ИдентификаторПроцессаОС() Экспорт
ИДТекущегоПроцесса = Неопределено;
ОбъектСистемы = Новый COMОбъект("WScript.Shell");
Если ИДТекущегоПроцесса = Неопределено Тогда
Процесс = ОбъектСистемы.Exec("rundll32.exe kernel32,Sleep");
ИДТекущегоПроцесса = ПолучитьCOMОбъект("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2:Win32_Process.Handle='" + Формат(Процесс.ProcessID,"ЧГ=0") + "'").ParentProcessID;
Процесс.Terminate();
КонецЕсли;
Возврат ИДТекущегоПроцесса;
КонецФункции
#КонецОбласти
#Область ОбработкаЗапросаИПланаВыполненияЗапроса
Функция ИмяСУБД()
СтрокаПодключения = СтрокаСоединенияИнформационнойБазы();
Позиция = Найти(СтрокаПодключения, "Ref=""");
Если Позиция > 0 Тогда
СтрокаПодключения = Сред(СтрокаПодключения, Позиция + 5);
Позиция = Найти(СтрокаПодключения, """");
Если Позиция > 0 Тогда
Возврат Лев(СтрокаПодключения, Позиция - 1);
Иначе
Возврат СтрокаПодключения;
КонецЕсли;
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Преобразовывает объекты запроса к объектам в виде метаданных ИБ.
//
Функция ПреобразоватьВМетаданные(ТекстЗапроса, ПланВыполненияЗапроса, ТипСУБД) Экспорт
ТекстЗапросаВМетаданных = ТекстЗапроса;
ПланЗапросаВМетаданных = ПланВыполненияЗапроса;
ТипСтрока = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150));
ТипСтрокаЗначение = Новый ОписаниеТипов("Строка", , );
ТипЧисло = Новый ОписаниеТипов("Число");
СтруктураБД = ПолучитьСтруктуруХраненияБазыДанных(, Истина);
СтруктураБД.Сортировать("ИмяТаблицыХранения УБЫВ");
СоответствиеБДИндекс = Новый ТаблицаЗначений;
СоответствиеБДИндекс.Колонки.Добавить("Ключ", ТипСтрока);
СоответствиеБДИндекс.Колонки.Добавить("Значение", ТипСтрокаЗначение);
СоответствиеБДИндекс.Колонки.Добавить("КоличествоСимволов", ТипЧисло);
СоответствиеБДИндекс.Индексы.Добавить("Ключ");
СоответствиеБДИндекс.Индексы.Добавить("КоличествоСимволов");
СоответствиеБДПоля = Новый ТаблицаЗначений;
СоответствиеБДПоля.Колонки.Добавить("Ключ", ТипСтрока);
СоответствиеБДПоля.Колонки.Добавить("Значение", ТипСтрокаЗначение);
СоответствиеБДПоля.Колонки.Добавить("КоличествоСимволов", ТипЧисло);
СоответствиеБДПоля.Индексы.Добавить("Ключ");
СоответствиеБДПоля.Индексы.Добавить("КоличествоСимволов");
СоответствиеБД = Новый ТаблицаЗначений;
СоответствиеБД.Колонки.Добавить("Ключ", ТипСтрока);
СоответствиеБД.Колонки.Добавить("Значение", ТипСтрокаЗначение);
СоответствиеБД.Колонки.Добавить("КоличествоСимволов", ТипЧисло);
СоответствиеБД.Индексы.Добавить("Ключ");
СоответствиеБД.Индексы.Добавить("КоличествоСимволов");
Для каждого Строка Из СтруктураБД Цикл
НоваяСтрока = СоответствиеБД.Добавить();
НоваяСтрока.Ключ = Строка.ИмяТаблицыХранения;
НоваяСтрока.Значение = Строка.ИмяТаблицы;
НоваяСтрока.КоличествоСимволов = СтрДлина(Строка.ИмяТаблицыХранения);
КонецЦикла;
СоответствиеБД.Сортировать("КоличествоСимволов Убыв, Ключ Убыв");
Для каждого Строка Из СтруктураБД Цикл
Для каждого Индекс Из Строка.Индексы Цикл
НоваяСтрока = СоответствиеБДИндекс.Добавить();
НоваяСтрока.Ключ = Индекс.ИмяИндексаХранения;
СписокПоле = "";
Разделитель = "";
Для каждого Поле Из Индекс.Поля Цикл
Если ЗначениеЗаполнено(Поле.ИмяПоля) Тогда
СписокПоле = СписокПоле + Разделитель + Поле.ИмяПоля; // + "(" + Поле.Метаданные + ")";
//Если ЗначениеЗаполнено(Поле.Метаданные) Тогда
КонецЕсли;
Разделитель = ", ";
КонецЦикла;
НоваяСтрока.Значение = СписокПоле;
НоваяСтрока.КоличествоСимволов = СтрДлина(Индекс.ИмяИндексаХранения);
КонецЦикла;
Для каждого Поле Из Строка.Поля Цикл
Если ЗначениеЗаполнено(Поле.ИмяПоля) Тогда
НоваяСтрока = СоответствиеБДПоля.Добавить();
НоваяСтрока.Ключ = Поле.ИмяПоляХранения;
НоваяСтрока.Значение = Поле.ИмяПоля;
НоваяСтрока.КоличествоСимволов = СтрДлина(Поле.ИмяПоляХранения);
Иначе
Позиция = Найти(Поле.ИмяПоляХранения, "_IDRRef");
Если Позиция > 1 Тогда
ИмяОбъекта = Лев(Поле.ИмяПоляХранения, Позиция-1);
ИмяТаблицы = СоответствиеБД.Найти(ИмяОбъекта, "Ключ").Значение;
НоваяСтрока = СоответствиеБДПоля.Добавить();
НоваяСтрока.Ключ = Поле.ИмяПоляХранения;
НоваяСтрока.Значение = "Ссылка(" + ИмяТаблицы + ")";
НоваяСтрока.КоличествоСимволов = СтрДлина(Поле.ИмяПоляХранения);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
СоответствиеБДПоля.Сортировать("КоличествоСимволов Убыв, Ключ УБЫВ");
СоответствиеБДИндекс.Сортировать("КоличествоСимволов Убыв, Ключ УБЫВ");
Если ТипСУБД = "DBPOSTGRS" Тогда
ПланЗапросаВМетаданных = НРег(ПланЗапросаВМетаданных);
ИначеЕсли ТипСУБД = "DBMSSQL" Тогда
// Очистка запроса
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, "[" + ИмяСУБД() + "].[dbo].", "");
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, "[tempdb].[dbo].", "");
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, "#tt", "ВременнаяТаблица");
ТекстЗапросаВМетаданных = СтрЗаменить(ТекстЗапросаВМетаданных, "dbo.", "");
ТекстЗапросаВМетаданных = СтрЗаменить(ТекстЗапросаВМетаданных, "#tt", "ВременнаяТаблица");
КонецЕсли;
Для каждого Поле Из СоответствиеБДИндекс Цикл
Если Найти(ПланЗапросаВМетаданных, Поле.Ключ) Тогда
Если ТипСУБД = "DBPOSTGRS" Тогда
Ключ = НРег(Поле.Ключ);
Иначе
Ключ = Поле.Ключ;
КонецЕсли;
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, Ключ, НСтр("ru = 'Индекс по'") + " " + Поле.Значение + "");
КонецЕсли;
КонецЦикла;
Для каждого Поле Из СоответствиеБДПоля Цикл
Если Найти(ТекстЗапросаВМетаданных, Поле.Ключ) Тогда
ТекстЗапросаВМетаданных = СтрЗаменить(ТекстЗапросаВМетаданных, Поле.Ключ, Поле.Значение);
Если ТипСУБД = "DBPOSTGRS" Тогда
Ключ = НРег(Поле.Ключ);
Иначе
Ключ = Поле.Ключ;
КонецЕсли;
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, Ключ, Поле.Значение);
КонецЕсли;
КонецЦикла;
Для каждого Поле Из СоответствиеБД Цикл
Если Найти(ТекстЗапросаВМетаданных, Поле.Ключ) Тогда
ТекстЗапросаВМетаданных = СтрЗаменить(ТекстЗапросаВМетаданных, Поле.Ключ, Поле.Значение);
Если ТипСУБД = "DBPOSTGRS" Тогда
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, НРег(Поле.Ключ), Поле.Значение);
ИначеЕсли ТипСУБД = "DBMSSQL" Тогда
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, "[" + Поле.Ключ + "]", Поле.Значение);
Иначе
ПланЗапросаВМетаданных = СтрЗаменить(ПланЗапросаВМетаданных, Поле.Ключ, Поле.Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
ВВидеМетаданных = Новый Структура();
ВВидеМетаданных.Вставить("ТекстЗапросаВВидеМетаданных", ТекстЗапросаВМетаданных);
ВВидеМетаданных.Вставить("ПланВыполненияЗапросаВМетаданных", ПланЗапросаВМетаданных);
Возврат ВВидеМетаданных;
КонецФункции
// Создает дерево плана выполнения запроса по данным из файла технологического журнала.
//
Процедура ПолучитьДеревоПланаВыполненияЗапроса(Знач ПланЗапросаТекст, Знач ПланЗапросаМетаданные, ДеревоПланЗапроса, СуммарнаяСтоимостьОбщая) Экспорт
СуммарнаяСтоимостьОбщая = 0;
КореньПланаЗапроса = Неопределено;
СтрокиДерева = Неопределено;
Позиция = 1;
Родитель = Неопределено;
ПредыдущаяПозиция = 0;
СтрокаДерево = ДеревоПланЗапроса;
Пока Позиция > 0 Цикл
МассивЯчеек = Новый Массив;
Для Индекс = 1 По 8 Цикл
Позиция = Найти(ПланЗапросаТекст, ",");
МассивЯчеек.Добавить(СокрЛП(Лев(ПланЗапросаТекст, Позиция-1)));
ПланЗапросаТекст = Сред(ПланЗапросаТекст, Позиция + 1);
КонецЦикла;
Позиция = Найти(ПланЗапросаТекст, Символы.ПС);
Если Позиция = 0 Тогда
Оператор = ПланЗапросаТекст;
Иначе
Оператор = Лев(ПланЗапросаТекст, Позиция - 1);
КонецЕсли;
ПланЗапросаТекст = Сред(ПланЗапросаТекст, Позиция + 1);
Для Индекс = 1 По 8 Цикл
ПозицияМетаданные = Найти(ПланЗапросаМетаданные, ",");
ПланЗапросаМетаданные = Сред(ПланЗапросаМетаданные, ПозицияМетаданные + 1);
КонецЦикла;
ПозицияМетаданные = Найти(ПланЗапросаМетаданные, Символы.ПС);
Если ПозицияМетаданные > 0 Тогда
ОператорМетаданные = Лев(ПланЗапросаМетаданные, ПозицияМетаданные - 1);
ПланЗапросаМетаданные = Сред(ПланЗапросаМетаданные, ПозицияМетаданные + 1);
Иначе
ОператорМетаданные = ПланЗапросаМетаданные;
КонецЕсли;
ПозицияМетаданные = Найти(ОператорМетаданные, "|--") - 4;
Если ПозицияМетаданные = 0 Тогда
СтрокаДерево = ДеревоПланЗапроса.Строки.Добавить();
КореньПланаЗапроса = СтрокаДерево;
Иначе
Если ПредыдущаяПозиция < ПозицияМетаданные Тогда
СтрокаДерево = СтрокаДерево.Строки.Добавить();
ИначеЕсли ПредыдущаяПозиция > ПозицияМетаданные Тогда
СтрокаДерево = НайтиПозициюВВетке(СтрокаДерево, ПозицияМетаданные);
Если СтрокаДерево <> Неопределено Тогда
СтрокаДерево = СтрокаДерево.Строки.Добавить();
Иначе
СтрокаДерево = ДеревоПланЗапроса.Строки.Добавить();
КонецЕсли;
Иначе
СтрокаДерево = СтрокаДерево.Родитель.Строки.Добавить();
КонецЕсли;
КонецЕсли;
Если СтрокаДерево.Родитель = Неопределено Тогда
СуммарнаяСтоимостьОбщая = СуммарнаяСтоимостьОбщая + ПреобразоватьВЧисло(МассивЯчеек[6]);
КонецЕсли;
ПозицияSQL = Найти(Оператор, "|--");
СтрокаДерево.Оператор = Сред(Оператор, ПозицияSQL + 3);
СтрокаДерево.ОператорМетаданные = Сред(ОператорМетаданные, ПозицияМетаданные + 7);
СтрокаДерево.Отступ = ПозицияМетаданные;
СтрокаДерево.СтрокиФакт = МассивЯчеек[0];
СтрокаДерево.ВызовыФакт = МассивЯчеек[1];
СтрокаДерево.СтрокиПлан = МассивЯчеек[2];
СтрокаДерево.ЗатратыВводаВывода = МассивЯчеек[3];
СтрокаДерево.ЗагрузкаЦП = МассивЯчеек[4];
СтрокаДерево.СреднийРазмерСтрок = МассивЯчеек[5];
СтрокаДерево.СтоимостьОбщая = ПреобразоватьВЧисло(МассивЯчеек[6]);
СтрокаДерево.ВызовыПлан = МассивЯчеек[7];
ПредыдущаяПозиция = ПозицияМетаданные;
КонецЦикла;
РассчитатьСтоимостьОператоров(ДеревоПланЗапроса.Строки);
КонецПроцедуры
Функция РассчитатьСтоимостьОператоров(ВеткаДерева)
Сумма = 0;
Для каждого строка Из ВеткаДерева Цикл
АккумуляторСтоимости = 0;
Если Строка.Строки.Количество() > 0 Тогда
АккумуляторСтоимости = РассчитатьСтоимостьОператоров(строка.Строки);
КонецЕсли;
СтоимостьОператора = Строка.СтоимостьОбщая - АккумуляторСтоимости;
Строка.Стоимость = ?(СтоимостьОператора < 0, 0, СтоимостьОператора);
Сумма = Сумма + Строка.СтоимостьОбщая;
КонецЦикла;
Возврат Сумма;
КонецФункции
Функция НайтиПозициюВВетке(Ветка, НомерПозиции)
Если Ветка.Отступ > НомерПозиции Тогда
Возврат НайтиПозициюВВетке(Ветка.Родитель, НомерПозиции);
ИначеЕсли Ветка.Отступ = НомерПозиции Тогда
Возврат Ветка.Родитель;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция ПреобразоватьВЧисло(ЧислоСтрокой)
Результат = 0;
ЧислоСтрокой = СокрЛП(ВРег(ЧислоСтрокой));
Если СтрДлина(ЧислоСтрокой) > 0 Тогда
ПозицияЕ = Найти(ЧислоСтрокой, "E");
Если ПозицияЕ = 0 Тогда
Результат = Число(ЧислоСтрокой);
Иначе
ЧислоДоЕ = Число(Лев(ЧислоСтрокой, ПозицияЕ - 1));
ЧислоПослеЕ = Число(Сред(ЧислоСтрокой, ПозицияЕ + 1));
Результат = ЧислоДоЕ * Pow(10 ,ЧислоПослеЕ);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецОбласти
#КонецЕсли