////////////////////////////////////////////////////////////////////////////////
// Подсистема "Инструменты разработчика Tormozit"
// Авторское право (с) 2007-2024, Старых С.А.
// Лицензия MIT
// Разрешается повторное распространение и использование как в виде исходника так и в двоичной форме,
// с модификациями или без, при соблюдении следующих условий:
// - При повторном распространении исходного кода должно оставаться указанное выше уведомление об авторском
// праве, этот список условий и нижеследующий отказ от гарантий.
// - При повторном распространении двоичного кода должно воспроизводиться указанное выше уведомление об
// авторском праве, этот список условий и нижеследующий отказ от гарантий в документации и/или в других
// материалах, поставляемых при распространении.
//
// ЭТО ПРОГРАММА ПРЕДОСТАВЛЕНА БЕСПЛАТНО ДЕРЖАТЕЛЯМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ СТОРОНАМИ "КАК ОНА ЕСТЬ"
// БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ,
// ПОДРАЗУМЕВАЕМЫЕ ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. НИ В КОЕМ СЛУЧАЕ,
// ЕСЛИ НЕ ТРЕБУЕТСЯ СООТВЕТСТВУЮЩИМ ЗАКОНОМ, ИЛИ НЕ УСТАНОВЛЕНО В УСТНОЙ ФОРМЕ, НИ ОДИН ДЕРЖАТЕЛЬ АВТОРСКИХ
// ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, КОТОРОЕ МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, КАК БЫЛО
// РАЗРЕШЕНО ВЫШЕ, НЕ ОТВЕТСТВЕННЫ ПЕРЕД ВАМИ ЗА УБЫТКИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ ИЛИ
// ПОСЛЕДОВАВШИЕ УБЫТКИ, ПРОИСТЕКАЮЩИЕ ИЗ ИСПОЛЬЗОВАНИЯ ИЛИ НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ,
// НО НЕ ОГРАНИЧИВАЯСЬ ПОТЕРЕЙ ДАННЫХ, ИЛИ ДАННЫМИ, СТАВШИМИ НЕПРАВИЛЬНЫМИ, ИЛИ ПОТЕРЯМИ ПРИНЕСЕННЫМИ ИЗ-ЗА
// ВАС ИЛИ ТРЕТЬИХ ЛИЦ, ИЛИ ОТКАЗОМ ПРОГРАММЫ РАБОТАТЬ СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ), ДАЖЕ ЕСЛИ ТАКОЙ
// ДЕРЖАТЕЛЬ ИЛИ ДРУГОЕ ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ.
//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирКлиент Экспорт;
//ирПортативный Перем ирОбщий83 Экспорт; // Неопределено в портативном режиме!
//ирПортативный Перем ирПлатформа Экспорт; // Неопределено в портативном режиме!
////////////////////////////////////////////////////////////////////////////////
// ОТЛАДКА
#Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда
// Присваивает первому параметру второй.
// Удобно вызывать из отладчика через диалог "Вычислить выражение" (в 8.3 есть встроенный аналог) или в условной точке останова для модификации значения переменной без остановки.
//
// Параметры:
// П1 - Произвольный - Указатель на переменную, которой присваиваем значение;
// П2 - Произвольный - значение, которое присваиваем;
// ВернутьЛожь - Булево - если включено, то функция возвращает Ложь, что необходимо для использования в точке останова
//
// Возвращаемое значение:
// Значение параметра П1 после присвоения, либо Ложь.
//
Функция Пр(п1, Знач п2 = Неопределено, Знач ВернутьЛожь = Ложь) Экспорт
п1 = п2;
Если ВернутьЛожь Тогда
Возврат Ложь; // Чтобы в точке останова использовать
Иначе
Возврат п1;
КонецЕсли;
КонецФункции
// Выполняет программный код, переданный в параметре.
// Остальные параметры могут участвовать в теле этого кода. Вернуть результат можно через переменную Р.
// Удобно использовать в отладчике.
//
// Параметры:
// ТекстПрограммы - Строка - текст программы для выполнения
// П1 - Произвольный - параметр1;
// П2 - Произвольный - параметр2;
// П3 - Произвольный - параметр3;
// П4 - Произвольный - параметр4;
//
// Возвращаемое значение:
// Неопределено - Не используется.
//
Функция Ду(Знач ТекстПрограммы, п1 = 0, п2 = 0, п3 = 0, п4 = 0) Экспорт
Перем Р;
Попытка
Выполнить(ТекстПрограммы);
Исключение
Возврат ОписаниеОшибки();
КонецПопытки;
Возврат Р;
КонецФункции
// На клиенте открывает консоль кода с передачей туда всех своих параметров. На сервере сразу выполняет код.
// Длина выражения в отладчике имеет ограничение 255 символов, которое влияет на передачу определения параметров в эту функцию. Если оно мешает, разбей текст на части.
// Изменения параметров возвращаются в вызывающий контекст в модальном режиме. Число параметров связано с см. МаксЧислоПараметровОперироватьЛкс.
// Вызывается из отладчика.
//
// Параметры:
// ТекстПрограммы - Строка - программный код для передачи в консоль кода или выполнения;
// РежимОперации - Число - 0 - немодально, 1 - модально, 2 - неинтерактивно (на сервере всегда);
// СтрокаИменПараметров - Строка - имена параметров для консоли кода через запятую, если не указаны, то будут оригинальные П*;
// П* - Произвольный - параметры для использования при выполнении программного кода;
//
// Возвращаемое значение:
// Строка - описание ошибок.
//
Функция Оперировать(Знач ТекстПрограммы = "", Знач РежимОперации = 0, СтрокаИменПараметров= "",
П1 = Null, П2 = Null, П3 = Null, П4 = Null, П5 = Null, П6 = Null, П7 = Null, П8 = Null, П9 = Null, П10 = Null,
П11 = Null, П12 = Null, П13 = Null, П14 = Null, П15 = Null, П16 = Null, П17 = Null, П18 = Null, П19 = Null, П20 = Null,
П21 = Null, П22 = Null, П23 = Null, П24 = Null, П25 = Null, П26 = Null, П27 = Null, П28 = Null, П29 = Null, П30 = Null,
П31 = Null, П32 = Null, П33 = Null, П34 = Null, П35 = Null, П36 = Null, П37 = Null, П38 = Null, П39 = Null, П40 = Null) Экспорт
УстановитьПривилегированныйРежимЛкс();
#Если Сервер И Не Клиент Тогда
РежимОперации = 2;
#КонецЕсли
МассивИмен = СтрРазделитьЛкс(СтрокаИменПараметров, ",", Истина);
Если МассивИмен.Количество() > 0 Тогда
Если МассивИмен[0] = "" Тогда
МассивИмен.Удалить(0);
КонецЕсли;
КонецЕсли;
ЧислоПараметров = МаксЧислоПараметровОперироватьЛкс();
ПереданныеПараметры = Новый СписокЗначений;
Для Счетчик = 1 По ЧислоПараметров Цикл
ИмяПараметра = "П" + Счетчик;
ЗначениеПараметра = Вычислить(ИмяПараметра);
Если Ложь
Или ЗначениеПараметра <> Null // Опасный трюк в интерактивном режиме. Отрезает параметры, переданные, но имеющие значение Null.
Или РежимОперации = 2
Тогда
ПсевдонимПараметра = ИмяПараметра;
Если МассивИмен.Количество() > Счетчик - 1 Тогда
ПсевдонимПараметра = МассивИмен[Счетчик - 1];
КонецЕсли;
ПереданныеПараметры.Добавить(ЗначениеПараметра, ПсевдонимПараметра);
КонецЕсли;
КонецЦикла;
Сообщения = Новый Массив;
Если РежимОперации < 2 Тогда
#Если Клиент Тогда
ФормаОтладки = ирКлиент.ПолучитьФормуЛкс("Обработка.ирКонсольКода.Форма", , , Новый УникальныйИдентификатор);
ФормаОтладки.мРежимРедактора = Истина;
ФормаОтладки.мСписокВнешнихПараметров = ПереданныеПараметры;
ФормаОтладки.ПараметрТекст = ТекстПрограммы;
Если РежимОперации = 0 Тогда
ФормаОтладки.Открыть();
Возврат Неопределено;
КонецЕсли;
ПолученныеПараметры = ФормаОтладки.ОткрытьМодально();
Если ПолученныеПараметры = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
#КонецЕсли
Иначе
ТекстПрограммы = ТекстПрограммы + Символы.ПС + ";";
Для Индекс = 0 По ПереданныеПараметры.Количество() - 1 Цикл
ВнешнийПараметр = ПереданныеПараметры[Индекс];
// Вход
ТекстПрограммы = ВнешнийПараметр.Представление + "=" + "_АлгоритмОбъект[" + Индекс + "].Значение;" + Символы.ПС + ТекстПрограммы;
// Выход
ТекстПрограммы = ТекстПрограммы + Символы.ПС + "_АлгоритмОбъект[" + Индекс + "].Значение = " + ВнешнийПараметр.Представление + ";";
КонецЦикла;
Попытка
Результат = ВыполнитьАлгоритм(ТекстПрограммы, ПереданныеПараметры);
Исключение
Сообщения.Добавить(ОписаниеОшибки());
КонецПопытки;
ПолученныеПараметры = ПереданныеПараметры;
КонецЕсли;
Если Сообщения.Количество() = 0 Тогда
НовоеЗначение = Неопределено;
Для Счетчик = 1 По ЧислоПараметров Цикл
ИмяПараметра = "П" + Счетчик;
НовоеЗначение = Неопределено;
Если ПолученныеПараметры.Количество() > Счетчик - 1 Тогда
НовоеЗначение = ПолученныеПараметры[Счетчик - 1].Значение;
КонецЕсли;
Если Вычислить(ИмяПараметра) <> НовоеЗначение Тогда
Попытка
Выполнить(ИмяПараметра + " = НовоеЗначение");
Исключение
ПсевдонимПараметра = ИмяПараметра;
Если МассивИмен.Количество() > Счетчик - 1 Тогда
ПсевдонимПараметра = МассивИмен[Счетчик - 1];
КонецЕсли;
ОписаниеОшибки = "Ошибка возвращения параметра " + ПсевдонимПараметра + ": " + ОписаниеОшибки();
Сообщения.Добавить(ОписаниеОшибки);
СообщитьЛкс(ОписаниеОшибки);
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Сообщения.Количество() = 0 И Результат = Неопределено Тогда
Сообщения.Добавить("Успешно выполнено");
КонецЕсли;
Сообщения = СтрСоединитьЛкс(Сообщения, Символы.ПС);
Если ЗначениеЗаполнено(Сообщения) Тогда
Возврат Сообщения;
Иначе
Возврат Результат;
КонецЕсли;
КонецФункции
Функция МаксЧислоПараметровОперироватьЛкс() Экспорт
Возврат 40;
КонецФункции
// Подготавливает выражение встроенного языка для помещения всех переменных в структуру с целью ее дальнейшего вычисления в отладчике "Вычислить(Пер())".
// Длина выражения в отладчике имеет ограничение 255 символов, которое влияет на передачу определения параметров в эту функцию. Если оно мешает, разбей текст на части.
// Строковые литералы должны быть обрамлены удвоенными двойным кавычками.
// В портативном варианте не работает в управляемом приложении и на сервере.
//
// Параметры:
// ТекстПрограммы - Строка, *"" - на клиенте можно не указывать и тогда текст будет браться из буфера обмена, можно вставить имена локальных переменных выведенных в табличный документ
//
// Возвращаемое значение:
// Строка для вычисления в отладчике.
//
Функция Пер(Знач ТекстПрограммы = "") Экспорт
#Если Не ТолстыйКлиентОбычноеПриложение Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ВызватьИсключение "Такой вызов недоступен в варианте Портативный";
КонецЕсли;
#КонецЕсли
выхПеременные = ПеременныеТекстаВстроенногоЯзыкаЛкс(ТекстПрограммы);
ИменаПеременных = СтрСоединитьЛкс(выхПеременные);
СтрокаРезультата = "Новый Структура(""" + ИменаПеременных + """, " + ИменаПеременных + ")";
Возврат СтрокаРезультата;
КонецФункции
// Подготавливает выражение встроенного языка для помещения всех переменных в структуру и ее передачи в метод Ис() в отладчике "Вычислить(ПерИс())".
// Длина выражения в отладчике имеет ограничение 255 символов, которое влияет на передачу определения параметров в эту функцию. Если оно мешает, разбей текст на части.
// Строковые литералы должны быть обрамлены удвоенными двойным кавычками.
// В портативном варианте не работает в управляемом приложении и на сервере.
//
// Параметры:
// ТекстПрограммы - Строка, *"" - на клиенте можно не указывать и тогда текст будет браться из буфера обмена, можно вставить имена локальных переменных выведенных в табличный документ
// ОтложенноеВыполнение - Булево - на сервере игнорируется (равно Истина), вместо открытия инструмента отладки выполняется помещение
// объектов отладки во временное хранилище;
// Возвращаемое значение:
// Строка для вычисления в отладчике.
//
Функция ПерИс(Знач ТекстПрограммы = "", ОтложенноеВыполнение = Ложь) Экспорт
#Если Не ТолстыйКлиентОбычноеПриложение Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ВызватьИсключение "Такой вызов недоступен в варианте Портативный";
КонецЕсли;
#КонецЕсли
Переменные = ПеременныеТекстаВстроенногоЯзыкаЛкс(ТекстПрограммы);
ИменаПеременных = СтрСоединитьЛкс(Переменные);
#Если Сервер И Не Сервер Тогда
ирОбщий.Ис();
#КонецЕсли
СтрокаРезультата = "ирОбщий.Ис(Новый Структура(""" + ИменаПеременных + """, " + ИменаПеременных + "),," + XMLСтрока(ОтложенноеВыполнение) + ")";
Возврат СтрокаРезультата;
КонецФункции
// Подготавливает выражение встроенного языка для вызова функции сборки описания параметров с целью ее дальнейшего вычисления в отладчике "Вычислить(ДокПар())".
// Длина выражения в отладчике имеет ограничение 255 символов, которое влияет на передачу определения параметров в эту функцию. Если оно мешает, разбей текст на части.
// Строковые литералы должны быть обрамлены удвоенными двойным кавычками. Допускается не удваивать их в литерале пустой строки ("").
// В портативном варианте не работает в управляемом приложении и на сервере.
//
// Параметры:
// ТекстПараметров - Строка, *"" - на клиенте можно не указывать и тогда текст будет браться из буфера обмена, например "Знач Текст = ""п"", Знач Рупор = Неопределено"
//
// Возвращаемое значение:
// Строка для вычисления в отладчике.
//
Функция ДокПар(Знач ТекстПараметров = "") Экспорт
#Если Не ТолстыйКлиентОбычноеПриложение Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ВызватьИсключение "Такой вызов недоступен в варианте Портативный";
КонецЕсли;
#КонецЕсли
ТекстПараметров = ТекстПараметров + ","; // На случай литерала пустой строки в конце
ТекстПараметров = СтрЗаменить(ТекстПараметров, "="",", "="""",");
ТекстПараметров = СтрЗаменить(ТекстПараметров, "= "",", "= """",");
Переменные = ПеременныеТекстаВстроенногоЯзыкаЛкс(ТекстПараметров);
ИменаПеременных = СтрСоединитьЛкс(Переменные);
#Если Сервер И Не Сервер Тогда
ирОбщий.СобратьКомментарийМетодаЛкс();
#КонецЕсли
СтрокаРезультата = "ирОбщий.СобратьКомментарийМетодаЛкс(Новый Структура(""" + ИменаПеременных + """, " + ИменаПеременных + "), """ + ИменаПеременных + """)";
Возврат СтрокаРезультата;
КонецФункции
// Функция получает таблицу значений из указанной временной таблицы из менеджера временных таблиц,
// либо структуру из всех входящих в запрос временных таблиц.
// Используется для просмотра временных таблиц серверного менеджера временных таблиц в отладчике.
// Параметры:
// ЗапросИлиМенеджерВременныхТаблиц - Запрос, МенеджерВременныхТаблиц
// ИменаВременныхТаблиц - Строка, *"" - имена существующих, но возможно не используемых в тексте запроса временных таблиц через запятую
// ДопустимоеЧислоСтрок - Число, *500000 - выбирать из временной таблицы не более этого числа строк
//
// Результат - ТаблицаЗначений, Структура
//
Функция ПолВТ(Знач ЗапросИлиМенеджерВременныхТаблиц, Знач ИменаВременныхТаблиц = "", Знач ДопустимоеЧислоСтрок = 500000) Экспорт
МассивИмен = ИменаИспользуемыхВЗапросеВременныхТаблицЛкс(ЗапросИлиМенеджерВременныхТаблиц, ИменаВременныхТаблиц);
Результат = Новый Структура();
Запрос = Новый Запрос;
Если ТипЗнч(ЗапросИлиМенеджерВременныхТаблиц) = Тип("Запрос") Тогда
Запрос.МенеджерВременныхТаблиц = ЗапросИлиМенеджерВременныхТаблиц.МенеджерВременныхТаблиц;
Иначе
Запрос.МенеджерВременныхТаблиц = ЗапросИлиМенеджерВременныхТаблиц;
КонецЕсли;
ТекстЗапроса = "
|ВЫБРАТЬ ПЕРВЫЕ " + XMLСтрока(ДопустимоеЧислоСтрок) + "
| *
|ИЗ
| ИмяВременнойТаблицы КАК Т" + СуффиксСлужебногоСвойстваЛкс() + "
|";
Для Каждого ИмяВременнойТаблицы Из МассивИмен Цикл
Если Не ЛиИмяПеременнойЛкс(ИмяВременнойТаблицы) Тогда
Продолжить;
КонецЕсли;
Если Результат.Свойство(ИмяВременнойТаблицы) Тогда
Продолжить;
КонецЕсли;
Запрос.Текст = СтрЗаменить(ТекстЗапроса, "ИмяВременнойТаблицы", ИмяВременнойТаблицы);
Попытка
РезультатЗапроса = Запрос.Выполнить();
Исключение
Продолжить;
КонецПопытки;
ТаблицаЗначений = РезультатЗапроса.Выгрузить();
ТаблицаЗначений = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаЗначений,,,, Истина);
Результат.Вставить(ИмяВременнойТаблицы, ТаблицаЗначений);
КонецЦикла;
Возврат Результат;
КонецФункции
// Начать трассу в технологическом журнале. Сам технологический журнал надо заранее включить.
Функция ТехН() Экспорт
АнализТехножурнала = ирКэш.АнализТехножурналаЛкс();
Если АнализТехножурнала.НачатьТрассу("Отладчик") Тогда
Возврат "Трасса техножурнала начата";
Иначе
Возврат "Техножурнал не включен. Невозможно начать трассу.";
КонецЕсли;
КонецФункции
// Кончить трассу в технологическом журнале и показать ее анализ
Функция ТехК() Экспорт
АнализТехножурнала = ирКэш.АнализТехножурналаЛкс();
Если АнализТехножурнала.КончитьТрассу() Тогда
//АнализТехножурнала.ПоказатьТрассу();
Возврат "Трасса техножурнала кончена. Для ее анализа откройте в режиме предприятия ""Анализ техножурнала""";
Иначе
Возврат "Трасса техножурнала не была начата ранее.";
КонецЕсли;
КонецФункции
#Если Клиент Тогда
// Подготавливает выражение встроенного языка для вызова Оперировать() в отладчике. Вызывается путем вычисления "Вычислить(Поп())".
// Длина выражения в отладчике имеет ограничение 255 символов, которое влияет на передачу определения параметров в эту функцию. Если оно мешает, разбей текст на части.
// Изменения параметров возвращаются в вызывающий контекст.
// Строковые литералы должны быть обрамлены удвоенными двойным кавычками.
// В портативном варианте не работает в управляемом приложении и на сервере.
//
// Параметры:
// ТекстПрограммы - Строка, *"" - программный код для передачи в консоль кода или выполнения, берется из буфера обмена если пустой;
// РежимОперации - Число - 0 - немодально, 1 - модально, 2 - неинтерактивно (на сервере всегда используется это значение);
//
// Возвращаемое значение:
// Строка для вычисления в отладчике.
//
Функция Поп(Знач ТекстПрограммы = "", РежимОперации = 1) Экспорт
#Если Не ТолстыйКлиентОбычноеПриложение Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ВызватьИсключение "Такой вызов недоступен в варианте Портативный";
КонецЕсли;
#КонецЕсли
Если ПустаяСтрока(ТекстПрограммы) Тогда
ТекстПрограммы = ирКлиент.ТекстИзБуфераОбменаОСЛкс();
КонецЕсли;
Параметры = Новый Структура();
ПолеВстроенногоЯзыка = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстаПрограммы");
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
ПолеВстроенногоЯзыка = Обработки.ирКлсПолеТекстаПрограммы.Создать();
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ПолеВстроенногоЯзыка.ИнициироватьНеинтерактивно();
Пока Истина Цикл
ИнформацияОбОшибке = ПолеВстроенногоЯзыка.ПроверитьТекстИВернутьОшибку(ТекстПрограммы);
Если ИнформацияОбОшибке = Неопределено Тогда
Прервать;
КонецЕсли;
НеопределеннаяПеременная = мПлатформа.ИмяНеопределеннойПеременнойИзИнформацииОбОшибке(ИнформацияОбОшибке);
Если Не ЗначениеЗаполнено(НеопределеннаяПеременная) Тогда
Возврат ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
КонецЕсли;
Если Не Параметры.Свойство(НеопределеннаяПеременная) Тогда
Параметры.Вставить(НеопределеннаяПеременная);
ПолеВстроенногоЯзыка.ДобавитьСловоЛокальногоКонтекста(НеопределеннаяПеременная);
КонецЕсли;
КонецЦикла;
СтрокаИменПараметров = "";
Для Каждого КлючИЗначение Из Параметры Цикл
Если СтрокаИменПараметров <> "" Тогда
СтрокаИменПараметров = СтрокаИменПараметров + ", ";
КонецЕсли;
СтрокаИменПараметров = СтрокаИменПараметров + КлючИЗначение.Ключ;
КонецЦикла;
НовыйТекст = ТекстВВыражениеВстроенногоЯзыкаЛкс(ТекстПрограммы);
СтрокаРезультата = "ирОбщий.Оперировать(" + НовыйТекст + ", " + РежимОперации + ", " + """" + СтрокаИменПараметров + """, " + СтрокаИменПараметров + ")";
Возврат СтрокаРезультата;
КонецФункции
// Обертка Оперировать. Модально открывает консоль кода с передачей туда всех своих параметров.
// Удобно вызывать из отладчика через диалог "Вычислить выражение".
// Изменения параметров возвращаются в вызывающий контекст.
//
// Параметры:
// П* - Произвольный;
//
// Возвращаемое значение:
// Неопределено.
//
Функция Оп(П1 = Null, П2 = Null, П3 = Null, П4 = Null, П5 = Null) Экспорт
Возврат Оперировать(, Истина, , П1, П2, П3, П4, П5);
КонецФункции
// Открывает консоль кода с передачей туда всех параметров из состава структуры.
// Изменения параметров возвращаются в структуру, но не в вызывающий контекст.
//
// Параметры:
// ТекстПрограммы - Строка;
// Модально - Булево - открывать окно модально;
// СтруктураПараметров - Структура - ключи соответствуют именам параметров, а значения их значениям, на выходе содержимое может быть изменено
//
// Возвращаемое значение:
// - Неопределено - для Модально=Истина
// - Форма - для Модально=Ложь
//
Функция ОперироватьСтруктуройЛкс(Знач ТекстПрограммы = "", Модально = Ложь, Знач СтруктураПараметров = Неопределено, Знач НаСервере = Ложь, Знач КлючУникальности = Неопределено) Экспорт
УстановитьПривилегированныйРежимЛкс();
Если Истина
И ПустаяСтрока(ТекстПрограммы)
И СтруктураПараметров <> Неопределено
И СтруктураПараметров.Количество() = 1
Тогда
Для Каждого КлючИЗначение Из СтруктураПараметров Цикл
ТекстПрограммы = КлючИЗначение.Ключ;
КонецЦикла;
КонецЕсли;
Если КлючУникальности = Неопределено Тогда
КлючУникальности = Новый УникальныйИдентификатор;
КонецЕсли;
ФормаОтладки = ирКлиент.ПолучитьФормуЛкс("Обработка.ирКонсольКода.Форма",,, КлючУникальности);
//ФормаОтладки.мСписокВнешнихПараметров = СкопироватьКоллекциюЛкс(СтруктураПараметров);
ПередаваемыеПараметры = Новый СписокЗначений;
Если СтруктураПараметров <> Неопределено Тогда
Для Каждого КлючИЗначение Из СтруктураПараметров Цикл
ПередаваемыеПараметры.Добавить(КлючИЗначение.Значение, КлючИЗначение.Ключ);
КонецЦикла;
ФормаОтладки.мСписокВнешнихПараметров = ПередаваемыеПараметры;
КонецЕсли;
ФормаОтладки.мРежимРедактора = Истина;
ФормаОтладки.ПараметрНаСервере = НаСервере;
ФормаОтладки.ПараметрТекст = ТекстПрограммы;
Если Не Модально Тогда
ФормаОтладки.Открыть();
Возврат ФормаОтладки;
КонецЕсли;
ПолученныеПараметры = ФормаОтладки.ОткрытьМодально();
Если ПолученныеПараметры = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если СтруктураПараметров <> Неопределено Тогда
//ЗаполнитьЗначенияСвойств(СтруктураПараметров, ПолученныеПараметры);
Для Каждого ПолученныйПараметр Из ПолученныеПараметры Цикл
СтруктураПараметров.Вставить(ПолученныйПараметр.Представление, ПолученныйПараметр.Значение);
КонецЦикла;
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Обертка ОперироватьСтруктурой. Модально открывает консоль кода с передачей туда всех параметров из состава структуры.
// Удобно вызывать из отладчика через диалог "Вычислить выражение".
// Изменения параметров возвращаются в структуру, но не в вызывающий контекст.
//
// Параметры:
// СтруктураПараметров - Структура - ключи соответствуют именам параметров, а значения их значениям.
//
// Возвращаемое значение:
// Неопределено.
//
Функция Опс(Знач СтруктураПараметров) Экспорт
Возврат ОперироватьСтруктуройЛкс(, Истина, СтруктураПараметров);
КонецФункции
// Выводит в окно сообщений переданное значение вместе с типом и заданным представлением.
//
// Параметры:
// Значение - Произвольный;
// *Представление - Строка, *"" - представление наблюдаемого значения.
//
Процедура Наблюдать(Знач Значение, Представление = "") Экспорт
Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда
Если Не ПравоДоступа("Использование", Метаданные.Обработки.ирИсследовательОбъектов) Тогда
Возврат;
КонецЕсли;
КонецЕсли;
Строка = Представление + " = " + "<" + ТипЗнч(Значение) + ">" + "[" + Значение + "]";
СообщитьЛкс(Строка);
КонецПроцедуры
#КонецЕсли
// Открывает или формирует снимок объекта для открытия в соответствующем инструменте. Снимок сохраняется в различные места в зависимости от варианта поставки и настроек:
// вариант "Расширение" - если в общих настройках указан КаталогОбъектовДляОтладки, то делается попытка записи в отдельный файл в этом каталоге, иначе в единую для всех пользователей ячейку в хранилище общих настроек в БД
// вариант "Конфигурация" - при возможности в отдельный элемент справочника ирОбъектыДляОтладки, иначе аналогично варианту Расширение
// вариант "Портативный" - делается попытка записи в отдельный файл в подкаталоге ОбъектыДляОтладки рядом с файлом внешней обработки, иначе в единую для всех пользователей ячейку в хранилище общих настроек в БД
// Варианты использования в зависимости от типа параметра Объект:
// Запрос, COMОбъект, HttpСоединение - открывает Запрос или ADODB.Command или ADODB.Connection в консоли запросов
// ПостроительЗапроса - открывает результирующий запрос построителя запросов в консоли запросов
// ПостроительОтчета - открывает построитель отчета в консоли построителей отчетов, откуда можно открыть результирующий запрос построителя отчета в консоли запросов
// СхемаКомпоновки - открывает схему компоновки в консоли компоновки данных, откуда можно открыть результирующие (из макета компоновки) запросы в консоли запросов
// МакетКомпоновкиДанных - открывает запросы макета компоновки в консоли запросов
// ОтчетОбъект - открывает схему и настройки компоновки отчета в консоли компоновки данных, откуда можно открыть результирующие (из макета компоновки) запросы в консоли запросов
// РегистрСведенийНаборЗаписей - открывает группировку таблицы набора записей по измерениям
//
// Параметры:
// Объект - Запрос, ПостроительЗапроса, ПостроительОтчета, СхемаКомпоновкиДанных, МакетКомпоновкиДанных, ОтчетОбъект, ADODB.Command, ADODB.Connection, HttpСоединение,
// РегистрСведенийНаборЗаписей, ДинамическийСписок, ТаблицаФормы - исследуемый объект
// Модально - Булево - открывать окно модально, должно быть Истина для использования функции в отладчике;
// Объект2 - НастройкиКомпоновкиДанных, Строка, *Неопределено -
// если первый параметр СхемаКомпоновкиДанных, то настройки компоновки,
// если первый параметр WMI или ADODB.Connection, то текст запроса,
// если первый параметр HttpСоединение, то HttpЗапрос,
// если первый параметр Запрос, имена временных таблиц разделенных запятыми
// ВнешниеНаборыДанных - Структура, *Неопределено - внешние наборы данных для схемы компоновки
// ОтложенноеВыполнение - Булево - на сервере игнорируется (равно Истина), вместо открытия инструмента отладки выполняется помещение
// объектов отладки во временное хранилище;
// ПорогОбрезкиВременнойТаблицы - Число, *500000 - допустимое количество строк для каждой временной таблицы запроса
// для отложенной отладки, больше этого количества строки не сохраняются, о чем сообщается в результате
// Наименование - Строка, * - наименование сохраняемого объекта отложенной отладки
// МенеджерВременныхТаблиц - МенеджерВременныхТаблиц, * - менеджер временных таблиц для компоновки данных
// ФорматВнутр - Булево - использовать быстрый и компактный сериализатор ЗначениеВСтрокуВнутр, иначе удобный для чтения человеком XML
// СсылкаСтрокиМодуля - Строка - нужна для выявления предыдущих операций менеджера временных таблиц консолью запросов, например {ОбщийМодуль.Сервер1.Модуль(12,5)} https://fastcode.im/Templates/Shared/bc4da1a446444e249e02b6f9b5467296
//
// Возвращаемое значение:
// Неопределено.
//
Функция ОтладитьЛкс(Знач Объект, Модально = Ложь, Знач Объект2 = Неопределено, Знач ВнешниеНаборыДанных = Неопределено, ОтложенноеВыполнение = Ложь, ПорогОбрезкиВременнойТаблицы = 500000,
выхОбъектДляОтладки = Неопределено, Наименование = "", Знач МенеджерВременныхТаблиц = Неопределено, Знач ФорматВнутр = Истина, Знач СсылкаСтрокиМодуля = "") Экспорт
УстановитьПривилегированныйРежимЛкс();
#Если Не Клиент Тогда
ОтложенноеВыполнение = Истина;
#КонецЕсли
Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() И ирКэш.ЛиПортативныйРежимЛкс() Тогда
ОтложенноеВыполнение = Истина;
КонецЕсли;
ТребоватьТипЛкс(Модально, "Модально", Тип("Булево"));
ТребоватьТипЛкс(ОтложенноеВыполнение, "ОтложенноеВыполнение", Тип("Булево"));
ТребоватьТипЛкс(ВнешниеНаборыДанных, "ВнешниеНаборыДанных", Тип("Неопределено"), Тип("Структура"));
ТребоватьТипЛкс(Объект2, "Объект2", Тип("Неопределено"), Тип("Строка"),
Тип("НастройкиКомпоновкиДанных"), Тип("HTTPЗапрос"));
Если ТипЗнч(Объект) = Тип("МенеджерВременныхТаблиц") Тогда
МенеджерВременныхТаблиц = Объект;
Объект = Новый Запрос;
Объект.Текст = "ВЫБРАТЬ 1";
Объект.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
КонецЕсли;
Если Не ОтложенноеВыполнение Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Объект));
#Если Клиент Тогда
Если Ложь
Или ТипЗнч(Объект) = Тип("Запрос")
Или ТипЗнч(Объект) = Тип("COMОбъект")
Тогда
КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов");
#Если Сервер И Не Сервер Тогда
КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать();
#КонецЕсли
Результат = КонсольЗапросов.ОткрытьДляОтладки(Объект, , , Модально, Объект2, СсылкаСтрокиМодуля);
ИначеЕсли ТипЗнч(Объект) = Тип("ПостроительЗапроса") Тогда
КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов");
#Если Сервер И Не Сервер Тогда
КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать();
#КонецЕсли
Результат = КонсольЗапросов.ОткрытьДляОтладки(Объект.ПолучитьЗапрос(), , , Модально);
ИначеЕсли ТипЗнч(Объект) = Тип("ПостроительОтчета") Тогда
КонсольПостроителейОтчетов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольПостроителейОтчетов");
#Если Сервер И Не Сервер Тогда
КонсольПостроителейОтчетов = Обработки.ирКонсольПостроителейОтчетов.Создать();
#КонецЕсли
Результат = КонсольПостроителейОтчетов.ОткрытьДляОтладки(Объект, Модально);
ИначеЕсли Ложь
Или ТипЗнч(Объект) = Тип("СхемаКомпоновкиДанных")
Или ТипЗнч(Объект) = Тип("МакетКомпоновкиДанных")
Тогда
КонсольКомпоновкиДанных = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольКомпоновокДанных");
#Если Сервер И Не Сервер Тогда
КонсольКомпоновкиДанных = Обработки.ирКонсольКомпоновокДанных.Создать();
#КонецЕсли
Результат = КонсольКомпоновкиДанных.ОткрытьДляОтладки(Объект, Объект2, ВнешниеНаборыДанных, Модально,,, МенеджерВременныхТаблиц);
ИначеЕсли Истина
И ОбъектМД <> Неопределено
И Метаданные.Отчеты.Индекс(ОбъектМД) <> -1
Тогда
КонсольКомпоновкиДанных = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольКомпоновокДанных");
#Если Сервер И Не Сервер Тогда
КонсольКомпоновкиДанных = Обработки.ирКонсольКомпоновокДанных.Создать();
#КонецЕсли
//: Объект = 0 // ОтчетОбъект
Если Объект.СхемаКомпоновкиДанных = Неопределено Тогда
Возврат "У отчета не установлена схема компоновки данных";
КонецЕсли;
Результат = КонсольКомпоновкиДанных.ОткрытьДляОтладки(Объект.СхемаКомпоновкиДанных, Объект.КомпоновщикНастроек.ПолучитьНастройки(), ВнешниеНаборыДанных, Модально,,, МенеджерВременныхТаблиц);
ИначеЕсли Истина
И ОбъектМД <> Неопределено
И Не ЛиТабличнаяЧастьЛкс(Объект)
Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
Объект = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ирКлиент.ОткрытьОбъектВРедактореОбъектаБДЛкс(Объект);
Если Метаданные.РегистрыСведений.Индекс(ОбъектМД) <> -1 Тогда
ФормаРедактирования = мПлатформа.ПолучитьФорму("ТаблицаЗначений");
ФормаРедактирования.НачальноеЗначениеВыбора = Объект.Выгрузить();
ФормаРедактирования.Открыть();
ирКлиент.ОткрытьГруппировкуТабличногоПоляЛкс(ФормаРедактирования.ЭлементыФормы.Коллекция,, СтрСоединитьЛкс(ЗначенияСвойстваКоллекцииЛкс(Объект.Метаданные().Измерения)));
КонецЕсли;
ИначеЕсли ТипЗнч(Объект) = Тип("HTTPСоединение") Тогда
КонсольHttpЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольHttpЗапросов");
#Если Сервер И Не Сервер Тогда
КонсольHttpЗапросов = Обработки.ирКонсольHttpЗапросов.Создать();
#КонецЕсли
Результат = КонсольHttpЗапросов.ОткрытьДляОтладки(Объект, Объект2, Модально);
ИначеЕсли ТипЗнч(Объект) = Тип("ДинамическийСписок") Тогда
Если ирОбщий.НаКлиентеИДоступенСерверныйВызовЛкс() Тогда
Возврат "Отладка динамического списка доступна только на сервере";
Иначе
Результат = От(Объект,,, Истина,, Наименование);
КонецЕсли;
Иначе
//Возврат "Не поддерживаемый тип """ + ТипЗнч(Объект) + """ первого параметра";
Ис(Объект,, ОтложенноеВыполнение);
КонецЕсли;
#КонецЕсли
Иначе
ЭтоОбъектБД = Ложь;
СтруктураПараметров = СтруктураОбъектаДляОтладкиЛкс(Объект, Объект2, ВнешниеНаборыДанных, ПорогОбрезкиВременнойТаблицы, МенеджерВременныхТаблиц, ЭтоОбъектБД, СсылкаСтрокиМодуля);
Если СтруктураПараметров.Объект <> Неопределено Тогда
Результат = ОтложитьУпакованныйОбъектДляОтладкиЛкс(СтруктураПараметров, выхОбъектДляОтладки, Наименование, ФорматВнутр И Не ЭтоОбъектБД);
Иначе
Результат = Ис(Объект,, ОтложенноеВыполнение);
Если Результат = Неопределено Тогда
Результат = "Отложенная отладка объекта типа """ + ТипЗнч(Объект) + """ не поддерживается";
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Структура объекта для отладки лкс
//
// Параметры:
// Объект - Произвольный -
// Объект2 - Произвольный -
// ВнешниеНаборыДанных - -
// ПорогОбрезкиВременнойТаблицы - -
// МенеджерВременныхТаблиц - -
//
// Возвращаемое значение:
// -
//
Функция СтруктураОбъектаДляОтладкиЛкс(Знач Объект, Знач Объект2 = Неопределено, Знач ВнешниеНаборыДанных = Неопределено, Знач ПорогОбрезкиВременнойТаблицы = 500000,
Знач МенеджерВременныхТаблиц = Неопределено, выхЭтоОбъектБД = Ложь, Знач СсылкаСтрокиМодуля = "") Экспорт
ТребоватьТипЛкс(ВнешниеНаборыДанных, "ВнешниеНаборыДанных", Тип("Неопределено"), Тип("Структура"));
ТребоватьТипЛкс(Объект2, "НастройкаКомпоновкиИлиТекстЗапросаИлиИменаВременныхТаблиц", Тип("Неопределено"), Тип("Строка"), Тип("НастройкиКомпоновкиДанных"), Тип("HTTPЗапрос"));
СтруктураПараметров = Новый Структура("Объект, НастройкаКомпоновки, ВнешниеНаборыДанных, ВременныеТаблицы, ТипОбъекта, СсылкаСтрокиМодуля");
Результат = Неопределено;
Если ТипЗнч(Объект) = Тип("Запрос") Тогда
#Если Сервер И Не Сервер Тогда
Объект = Новый Запрос;
#КонецЕсли
СтруктураЗапроса = Новый Структура("Текст, Параметры, ВременныеТаблицы, ТипЗапроса");
ВременныеТаблицы = Неопределено;
Если Объект.МенеджерВременныхТаблиц <> Неопределено Тогда
СтруктураЗапроса.ВременныеТаблицы = ПолВТ(Объект, Объект2, ПорогОбрезкиВременнойТаблицы);
ПроверитьОбрезкуВременныхТаблицЛкс(СтруктураЗапроса.ВременныеТаблицы, ПорогОбрезкиВременнойТаблицы);
КонецЕсли;
СтруктураЗапроса.Текст = Объект.Текст;
СтруктураЗапроса.ТипЗапроса = "Обычный";
СтруктураЗапроса.Параметры = ПреобразоватьПараметрыЗапросаДляСериализацииЛкс(Объект.Параметры);
СтруктураПараметров.Объект = СтруктураЗапроса;
СтруктураПараметров.ТипОбъекта = "Запрос";
ИначеЕсли ТипЗнч(Объект) = Тип("COMОбъект") Тогда
Попытка
Пустышка = Объект.CommandText;
ЭтоКомандаADO = Истина;
Исключение
ЭтоКомандаADO = Ложь;
Попытка
Пустышка = Объект.ConnectionString;
ЭтоСоединениеADO = Истина;
Исключение
ЭтоСоединениеADO = Ложь;
КонецПопытки;
КонецПопытки;
СтруктураЗапроса = Новый Структура("Текст, Параметры, ВременныеТаблицы, ТипЗапроса");
Если Ложь
Или ЭтоКомандаADO
Или ЭтоСоединениеADO
Тогда
Если ЭтоСоединениеADO Тогда
СтруктураЗапроса.Текст = Объект2;
Иначе
СтруктураЗапроса.Текст = Объект.CommandText;
// Антибаг платформы 8.2.18. Некорректная сериализация моментов времени http://partners.v8.1c.ru/forum/thread.jsp?id=1159525#1159525
//СтруктураЗапроса.Параметры = КопияОбъектаЛкс(Объект.Параметры);
СтруктураЗапроса.Параметры = Новый Структура();
Для Каждого Parameter Из Объект.Parameters Цикл
КлючПараметра = Parameter.Name;
Если Не ЛиИмяПеременнойЛкс(КлючПараметра) Тогда
КлючПараметра = "_" + КлючПараметра;
КонецЕсли;
Если Не ЛиИмяПеременнойЛкс(КлючПараметра) Тогда
КлючПараметра = КлючПараметра + XMLСтрока(СтруктураЗапроса.Параметры.Количество());
КонецЕсли;
Если СтруктураЗапроса.Параметры.Свойство(КлючПараметра) Тогда
ВызватьИсключение "Не удалось назначить параметру уникальное имя";
КонецЕсли;
СтруктураЗапроса.Параметры.Вставить(КлючПараметра, ЗначениеВСтрокуВнутр(Parameter.Value));
КонецЦикла;
КонецЕсли;
СтруктураЗапроса.ТипЗапроса = "ADO";
//ВременныеТаблицы = Неопределено;
//ВременныеТаблицы = ПолВТ(Объект, ПорогОбрезкиВременнойТаблицы);
//Результат = "";
//Для Каждого КлючИЗначение Из ВременныеТаблицы Цикл
// Если Результат <> "" Тогда
// Результат = Результат + ", ";
// КонецЕсли;
// Если КлючИЗначение.Значение.Количество() = ПорогОбрезкиВременнойТаблицы Тогда
// Результат = Результат + КлючИЗначение.Ключ;
// КонецЕсли;
//КонецЦикла;
//Если Результат <> "" Тогда
// Результат = Результат + Символы.ПС + "Временные таблицы " + Результат + " были сохранены частично!";
//КонецЕсли;
//СтруктураЗапроса.ВременныеТаблицы = ВременныеТаблицы;
СтруктураПараметров.Объект = СтруктураЗапроса;
Иначе
СтруктураЗапроса.ТипЗапроса = "WQL";
СтруктураЗапроса.Текст = Объект2;
КонецЕсли;
СтруктураПараметров.ТипОбъекта = "COMОбъект";
ИначеЕсли Ложь
Или ТипЗнч(Объект) = Тип("ПостроительЗапроса")
Или ТипЗнч(Объект) = Тип("ПостроительОтчета")
Тогда
СтруктураЗапроса = Новый Структура("Текст, Параметры");
ЗаполнитьЗначенияСвойств(СтруктураЗапроса, Объект.ПолучитьЗапрос());
СтруктураЗапроса.Параметры = ПреобразоватьПараметрыЗапросаДляСериализацииЛкс(СтруктураЗапроса.Параметры);
СтруктураПараметров.Объект = СтруктураЗапроса;
СтруктураПараметров.ТипОбъекта = "Запрос";
ИначеЕсли ТипЗнч(Объект) = Тип("МакетКомпоновкиДанных") Тогда
СтруктураПараметров.Объект = Объект;
СтруктураПараметров.ВнешниеНаборыДанных = ВнешниеНаборыДанных;
Если МенеджерВременныхТаблиц <> Неопределено Тогда
СтруктураПараметров.ВременныеТаблицы = ПолВТ(МенеджерВременныхТаблиц,, ПорогОбрезкиВременнойТаблицы);
ПроверитьОбрезкуВременныхТаблицЛкс(СтруктураПараметров.ВременныеТаблицы, ПорогОбрезкиВременнойТаблицы);
КонецЕсли;
СтруктураПараметров.ТипОбъекта = "МакетКомпоновкиДанных";
ИначеЕсли ТипЗнч(Объект) = Тип("СхемаКомпоновкиДанных") Тогда
СтруктураПараметров.Объект = Объект;
СтруктураПараметров.НастройкаКомпоновки = Объект2;
СтруктураПараметров.ВнешниеНаборыДанных = ВнешниеНаборыДанных;
Если МенеджерВременныхТаблиц <> Неопределено Тогда
СтруктураПараметров.ВременныеТаблицы = ПолВТ(МенеджерВременныхТаблиц,, ПорогОбрезкиВременнойТаблицы);
ПроверитьОбрезкуВременныхТаблицЛкс(СтруктураПараметров.ВременныеТаблицы, ПорогОбрезкиВременнойТаблицы);
КонецЕсли;
СтруктураПараметров.ТипОбъекта = "СхемаКомпоновкиДанных";
ИначеЕсли ТипЗнч(Объект) = Тип("HTTPСоединение") Тогда
#Если Сервер И Не Сервер Тогда
Объект = Новый HttpСоединение;
#КонецЕсли
ИменаСвойств = "Сервер, Порт, Пользователь, Пароль, Таймаут, Защищенное, ИспользоватьАутентификациюОС";
СтруктураСоединения = Новый Структура(ИменаСвойств);
ЗаполнитьЗначенияСвойств(СтруктураСоединения, Объект, ИменаСвойств);
Если ТипЗнч(Объект2) = Тип("HTTPЗапрос") Тогда
#Если Сервер И Не Сервер Тогда
Объект2 = Новый HTTPЗапрос;
#КонецЕсли
ИменаСвойств = "АдресРесурса, Заголовки";
СтруктураЗапроса = Новый Структура(ИменаСвойств);
ЗаполнитьЗначенияСвойств(СтруктураЗапроса, Объект2, ИменаСвойств);
СтруктураЗапроса.Вставить("ТелоДвоичныеДанные", Объект2.ПолучитьТелоКакДвоичныеДанные());
КонецЕсли;
СтруктураПараметров.Объект = СтруктураСоединения;
СтруктураПараметров.НастройкаКомпоновки = СтруктураЗапроса;
СтруктураПараметров.ТипОбъекта = "HttpСоединение";
ИначеЕсли ТипЗнч(Объект) = Тип("ДинамическийСписок") Тогда
Если НаКлиентеИДоступенСерверныйВызовЛкс() Тогда
Возврат "Отладка динамического списка доступна только на сервере";
КонецЕсли;
НастройкаКомпоновки = Неопределено;
Схема = Неопределено;
ПолучитьСхемуИНастройкиКомпоновкиДинамическогоСпискаЛкс(Объект, НастройкаКомпоновки, Схема);
СтруктураПараметров.Объект = Схема;
СтруктураПараметров.НастройкаКомпоновки = НастройкаКомпоновки;
СтруктураПараметров.ТипОбъекта = "СхемаКомпоновкиДанных";
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаФормы") Тогда
//! Объект = 0 // РасширениеТаблицыФормыДляДинамическогоСписка
Если НаКлиентеИДоступенСерверныйВызовЛкс() Тогда
Возврат "Отладка динамического списка доступна только на сервере";
КонецЕсли;
Схема = Объект.ПолучитьИсполняемуюСхемуКомпоновкиДанных();
НастройкаКомпоновки = Объект.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();
СтруктураПараметров.Объект = Схема;
СтруктураПараметров.НастройкаКомпоновки = НастройкаКомпоновки;
СтруктураПараметров.ТипОбъекта = "СхемаКомпоновкиДанных";
Иначе
//! Объект = 0 // ОтчетОбъект
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Объект));
Если ОбъектМД <> Неопределено Тогда
Если Метаданные.Отчеты.Индекс(ОбъектМД) <> -1 Тогда
Если Объект.СхемаКомпоновкиДанных = Неопределено Тогда
Возврат "У отчета не установлена схема компоновки данных";
Иначе
СтруктураПараметров.Объект = Объект.СхемаКомпоновкиДанных;
СтруктураПараметров.НастройкаКомпоновки = Объект.КомпоновщикНастроек.ПолучитьНастройки();
СтруктураПараметров.ВнешниеНаборыДанных = ВнешниеНаборыДанных;
СтруктураПараметров.ТипОбъекта = "СхемаКомпоновкиДанных";
КонецЕсли;
ИначеЕсли ЛиТабличнаяЧастьЛкс(Объект) Тогда
СтруктураПараметров.Объект = Объект.Выгрузить();
Иначе //Если Метаданные.РегистрыСведений.Индекс(ОбъектМД) <> -1 Тогда
СтруктураПараметров.Объект = Объект;
выхЭтоОбъектБД = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
СтруктураПараметров.Вставить("ТипОперации", "Отладить");
СтруктураПараметров.Вставить("СсылкаСтрокиМодуля", СсылкаСтрокиМодуля);
СтруктураПараметров.Вставить("ИмяПользователя", ИмяПользователя());
Возврат СтруктураПараметров;
КонецФункции
Процедура ПроверитьОбрезкуВременныхТаблицЛкс(Знач ВременныеТаблицы, Знач ПорогОбрезкиВременнойТаблицы)
Результат = "";
Для Каждого КлючИЗначение Из ВременныеТаблицы Цикл
Если Результат <> "" Тогда
Результат = Результат + ", ";
КонецЕсли;
Если КлючИЗначение.Значение.Количество() = ПорогОбрезкиВременнойТаблицы Тогда
Результат = Результат + КлючИЗначение.Ключ;
КонецЕсли;
КонецЦикла;
Если Результат <> "" Тогда
Результат = "Временные таблицы " + Результат + " были сохранены частично!";
КонецЕсли;
КонецПроцедуры
Функция СнимокОбъектаДляОтладкиЛкс(Знач Объект, Знач Объект2 = Неопределено, Знач ВнешниеНаборыДанных = Неопределено,
Знач ПорогОбрезкиВременнойТаблицы = 500000) Экспорт
СтруктураПараметров = СтруктураОбъектаДляОтладкиЛкс(Объект, Объект2, ВнешниеНаборыДанных, ПорогОбрезкиВременнойТаблицы);
Результат = ОбъектВСтрокуXMLЛкс(СтруктураПараметров);
Возврат Результат;
КонецФункции
// Обертка ирОбщий.ОтладитьЛкс(). Открывает или формирует снимок объекта для открытия в соответствующем инструменте.
// Удобно вызывать из отладчика через диалог "Вычислить выражение".
Функция От(Знач Объект, Знач Объект2 = Неопределено, Знач ВнешниеНаборыДанных = Неопределено, ОтложенноеВыполнение = Ложь, ПорогОбрезкиВременнойТаблицы = 500000, Наименование = "",
Знач МенеджерВременныхТаблиц = Неопределено, Знач СсылкаСтрокиМодуля = "") Экспорт
#Если ТолстыйКлиентОбычноеПриложение Тогда
Если ТипЗнч(ирПортативный) <> Тип("ОбщийМодуль") Тогда
Пустышка = ирПортативный.ПолучитьФорму(Неопределено); // Чтобы использовалась форма именно этого объекта
КонецЕсли;
#КонецЕсли
Результат = ОтладитьЛкс(Объект, Истина, Объект2, ВнешниеНаборыДанных, ОтложенноеВыполнение, ПорогОбрезкиВременнойТаблицы,, Наименование, МенеджерВременныхТаблиц,, СсылкаСтрокиМодуля);
Если ТипЗнч(ирПортативный) <> Тип("ОбщийМодуль") Тогда
ирПортативный.УсловныйДеструктор();
КонецЕсли;
Возврат Результат;
КонецФункции
// Открывает или формирует снимок объекта для открытия в исследователе объектов.
//
// Параметры:
// Объект - Произвольный, *Неопределено - объект, который будет исследован;
// Модально - Булево - открывать окно модально;
// КакКоллекцию - Булево, *Ложь - исследовать как коллекцию вместо объекта;
// ОтложенноеВыполнение - Булево - на сервере игнорируется (равно Истина), вместо открытия инструмента отладки выполняется помещение
// объектов отладки во временное хранилище;
// ТекущееВыражение - Строка - исходное выражение
//
// Возвращаемое значение:
// Сам объект.
//
Функция ИсследоватьЛкс(Знач Объект = Неопределено, Знач Модально = Ложь, Знач КакКоллекцию = Ложь, Знач ОтложенноеВыполнение = Ложь, Знач ТекущееВыражение = Неопределено, Знач ИмяТекущегоСвойства = "",
Знач ПрикрепитьОкно = Ложь, Знач ФорматВнутр = Истина, Знач ВладелецФормы = Неопределено) Экспорт
УстановитьПривилегированныйРежимЛкс();
#Если Не Клиент Тогда
ОтложенноеВыполнение = Истина;
#КонецЕсли
Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() И ирКэш.ЛиПортативныйРежимЛкс() Тогда
ОтложенноеВыполнение = Истина;
КонецЕсли;
ТребоватьТипЛкс(Модально, "Модально", Тип("Булево"));
ТребоватьТипЛкс(КакКоллекцию, "КакКоллекцию", Тип("Булево"));
ТребоватьТипЛкс(ОтложенноеВыполнение, "ОтложенноеВыполнение", Тип("Булево"));
Если Не ОтложенноеВыполнение Тогда
ИсследовательОбъектов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирИсследовательОбъектов");
#Если Сервер И Не Сервер Тогда
ИсследовательОбъектов = Обработки.ирИсследовательОбъектов.Создать();
#КонецЕсли
Если КакКоллекцию Тогда
Результат = ИсследовательОбъектов.ИсследоватьКоллекцию(Объект, Модально);
Иначе
Результат = ИсследовательОбъектов.ИсследоватьОбъект(Объект, Модально, ТекущееВыражение, ИмяТекущегоСвойства, ПрикрепитьОкно, ВладелецФормы);
КонецЕсли;
Если Модально И Результат <> Неопределено Тогда
Объект = Результат;
КонецЕсли;
Иначе
Если ТипЗнч(Объект) = Тип("ДанныеФормыДерево") Тогда
Объект = ДанныеФормыВЗначение(Объект, Тип("ДеревоЗначений"));
ИначеЕсли ТипЗнч(Объект) = Тип("ДанныеФормыКоллекция") Тогда
Объект = ДанныеФормыВЗначение(Объект, Тип("ТаблицаЗначений"));
КонецЕсли;
СтруктураПараметров = Новый Структура("Объект, Модально, КакКоллекцию, СериализацияФабрикой", Объект, Модально, КакКоллекцию, Ложь);
Наименование = РасширенноеПредставлениеЛкс(Объект);
Если Истина
И ТипЗнч(Объект) <> Тип("ОбъектXDTO")
И ТипЗнч(Объект) <> Тип("ЗначениеXDTO")
Тогда
Попытка
ОбъектXDTO = СериализаторXDTO.ЗаписатьXDTO(СтруктураПараметров);
Исключение
ОбъектXDTO = Неопределено;
КонецПопытки;
Иначе
СтруктураПараметров.СериализацияФабрикой = Истина;
Попытка
Объект = ОбъектВСтрокуXMLЛкс(Объект);
ОбъектXDTO = Объект;
Исключение
ОбъектXDTO = Неопределено;
КонецПопытки;
КонецЕсли;
Если ОбъектXDTO = Неопределено Тогда
ОбъектXDTO = Истина;
Объект = ЗначениеВСтрокуВнутр(Объект);
СтруктураПараметров.СериализацияФабрикой = "Внутр";
КонецЕсли;
Если ОбъектXDTO <> Неопределено Тогда
СтруктураПараметров.Вставить("ТипОперации", "Исследовать");
СтруктураПараметров.Вставить("Объект", Объект);
Результат = ОтложитьУпакованныйОбъектДляОтладкиЛкс(СтруктураПараметров,, Наименование, ФорматВнутр);
Иначе
Результат = "Отложенная отладка объекта такого типа не поддерживается";
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Снимок объекта лкс
// Параметры:
// Объект - СсылочныйОбъект, ОбработкаОбъект.ирИмитаторНаборЗаписей, ОбработкаОбъект.ирИмитаторСсылочныйОбъект, ОбработкаОбъект.ирИмитаторКонстантаМенеджер -
// Возвращаемое значение:
// Строка -
Функция СнимокОбъектаЛкс(Объект) Экспорт
Если ЛиТипОбъектаБДЛкс(ТипЗнч(Объект)) Тогда
ПолноеИмяМД = Объект.Метаданные().ПолноеИмя();
ОбъектыНаСервере = Истина;
#Если Клиент Тогда
ОбъектыНаСервере = Неопределено;
#КонецЕсли
СтруктураОбъекта = ОбъектБДПоКлючуЛкс(ПолноеИмяМД,,, Ложь, ОбъектыНаСервере,,,, Ложь);
ИмитаторОбъекта = СтруктураОбъекта.Методы;
Если ЛиТипИмитатораОбъектаЛкс(ТипЗнч(ИмитаторОбъекта)) Тогда
#Если Сервер И Не Сервер Тогда
ИмитаторОбъекта = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
ИмитаторОбъекта.Конструктор(Объект);
КонецЕсли;
ИначеЕсли ЛиТипИмитатораОбъектаЛкс(ТипЗнч(Объект)) Тогда
ПолноеИмяМД = Метаданные.НайтиПоТипу(Объект._Тип).ПолноеИмя();
ИмитаторОбъекта = Объект;
КонецЕсли;
Если ИмитаторОбъекта <> Неопределено Тогда
Результат = Новый Структура;
Результат.Вставить("ПолноеИмяМД", ПолноеИмяМД);
Если ЛиТипИмитатораОбъектаЛкс(ТипЗнч(ИмитаторОбъекта)) Тогда
#Если Сервер И Не Сервер Тогда
ИмитаторОбъекта = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
Результат.Вставить("Снимок", ИмитаторОбъекта.Снимок());
Иначе
Результат.Вставить("Снимок", ОбъектВСтрокуXMLЛкс(Объект));
КонецЕсли;
//Иначе
// Большого смысла пока не увидел, т.к. обратное преобразование не оформлено отдельной функцией
// Результат = СтруктураОбъектаДляОтладкиЛкс(Объект);
КонецЕсли;
Если Результат = Неопределено Тогда
Результат = ЗначениеВСтрокуВнутр(Объект);
#Если Сервер Тогда
Если ирКэш.ПараметрыЗаписиОбъектовЛкс().ОбъектыНаСервере Тогда
// Двойная сериализация нужна для полного удаления неудобных типов (СправочникОбъект) для клиента. Иначе возможны сложные проблемы https://github.com/tormozit/RDT1C/issues/707
Результат = ЗначениеВСтрокуВнутр(ЗначениеИзСтрокиВнутр(Результат));
КонецЕсли;
#КонецЕсли
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// Снимок - см. СнимокОбъектаЛкс -
// ВВидеСтруктуры - -
// Возвращаемое значение:
// -
Функция ОбъектИзСнимкаЛкс(Знач Снимок, Знач ВВидеСтруктуры = Ложь) Экспорт
Если ТипЗнч(Снимок) = Тип("Структура") Тогда
СтруктураОбъекта = ОбъектБДПоКлючуЛкс(ирКэш.ИмяТаблицыИзМетаданныхЛкс(Снимок.ПолноеИмяМД),,, Ложь,,,,, Ложь);
ИмитаторОбъекта = СтруктураОбъекта.Методы;
Если ЛиТипИмитатораОбъектаЛкс(ТипЗнч(ИмитаторОбъекта)) Тогда
#Если Сервер И Не Сервер Тогда
ИмитаторОбъекта = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
ИмитаторОбъекта.ЗагрузитьСнимок(Снимок.Снимок);
Иначе
ИмитаторОбъекта = ОбъектИзСтрокиXMLЛкс(Снимок.Снимок);
СтруктураОбъекта.Методы = ИмитаторОбъекта;
СтруктураОбъекта.Данные = ИмитаторОбъекта;
КонецЕсли;
Если ВВидеСтруктуры Тогда
Результат = СтруктураОбъекта;
Иначе
Результат = ИмитаторОбъекта;
КонецЕсли;
КонецЕсли;
Если Результат = Неопределено Тогда
Результат = ЗначениеИзСтрокиВнутрЛкс(Снимок);
КонецЕсли;
Возврат Результат;
КонецФункции
// Обертка Исследовать. Модально открывает объект в исследователе объектов
// Удобно вызывать из отладчика через диалог "Вычислить выражение".
Функция Ис(Знач Объект = Неопределено, КакКоллекцию = Ложь, ОтложенноеВыполнение = Ложь) Экспорт
#Если ТолстыйКлиентОбычноеПриложение Тогда
Если ТипЗнч(ирПортативный) <> Тип("ОбщийМодуль") Тогда
Пустышка = ирПортативный.ПолучитьФорму(Неопределено); // Чтобы использовалась форма именно этого объекта
КонецЕсли;
#КонецЕсли
Результат = ИсследоватьЛкс(Объект, Истина, КакКоллекцию, ОтложенноеВыполнение);
Если ТипЗнч(ирПортативный) <> Тип("ОбщийМодуль") Тогда
ирПортативный.УсловныйДеструктор();
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает текст из файла
Функция Файл(Знач ИмяФайла, Знач Кодировка = "UTF-8") Экспорт
Текст = Новый ТекстовыйДокумент;
Попытка
Текст.Прочитать(ИмяФайла, Кодировка);
Результат = Текст.ПолучитьТекст();
Исключение
Результат = ОписаниеОшибки();
КонецПопытки;
Возврат Результат;
КонецФункции
// Удаляет все элементы коллекции с возможностью оставить один элемент.
// Параметры:
// Коллекция - Структура, Соответствие, СписокЗначений, ТаблицаЗначений - коллекция из которой надо удалить элементы;
// ОставитьЭлементИлиИндекс - Число, Строка, *Неопределено - при Число Или Строка оставляется элемент с таким ключом (0 - первый), иначе удаляется все
Функция СокрКол(Знач Коллекция, Знач ОставитьЭлементИлиКлюч = Неопределено, Знач ОчищатьЕслиКлючНеНайден = Ложь) Экспорт
Если Ложь
Или ТипЗнч(ОставитьЭлементИлиКлюч) = Тип("Число")
Или ТипЗнч(ОставитьЭлементИлиКлюч) = Тип("Строка")
Тогда
Если ОставитьЭлементИлиКлюч = 0 Тогда
ОставитьЭлемент = "<Первый>";
Иначе
Попытка
ОставитьЭлемент = Коллекция[ОставитьЭлементИлиКлюч];
Исключение
Если ОчищатьЕслиКлючНеНайден Тогда
ОставитьЭлемент = Неопределено;
КонецЕсли;
КонецПопытки;
КонецЕсли;
КонецЕсли;
Если ОставитьЭлемент = Неопределено Тогда
Попытка
Коллекция.Очистить();
Возврат Истина;
Исключение
ОставитьЭлемент = Неопределено;
КонецПопытки;
КонецЕсли;
МассивКУдалению = Новый Массив;
Для Каждого Элемент Из Коллекция Цикл
Если Истина
И ОставитьЭлемент <> Неопределено
И (Ложь
Или ОставитьЭлемент = "<Первый>"
Или ОставитьЭлемент = Элемент)
Тогда
ОставитьЭлемент = Элемент;
Продолжить;
КонецЕсли;
Если Ложь
Или ТипЗнч(Коллекция) = Тип("Структура")
Или ТипЗнч(Коллекция) = Тип("Соответствие")
Тогда
МассивКУдалению.Добавить(Элемент.Ключ);
Иначе
МассивКУдалению.Добавить(Элемент);
КонецЕсли;
КонецЦикла;
Для Каждого УдаляемыйЭлемент Из МассивКУдалению Цикл
Попытка
Коллекция.Удалить(УдаляемыйЭлемент);
Исключение
// Элементы могут быть связанными, например элементы формы
КонецПопытки;
КонецЦикла;
Возврат Коллекция;
КонецФункции
// Проверяет что переданное значение отличается от предыдущего переданного с тем же именем.
// Полезно использовать в условных точках останова например для остановки в том проходе цикла, в котором изменяется значение выражения.
// https://www.hostedredmine.com/issues/892539
// Параметры:
// Значение - Произвольный - проверяемое значение. Все типы, кроме ссылок БД, преобразуются к строке через функцию РасширенноеПредставлениеЛкс(), которая также используется при отображении значений в консоли кода.
// ИмяЗначения - Строка, Число, *"" - имя/идентификатор значения
// НужноеСтароеЗначение - Произвольный, * - игнорировать все старые значения кроме этого
// НужноеНовоеЗначение - Произвольный, * - игнорировать все новые значения кроме этого
// Результат:
// Булево - Истина, если значение изменилось
Функция Изм(Знач Значение, Знач ИмяЗначения = "", Знач НужноеСтароеЗначение = "фйъх13м9", Знач НужноеНовоеЗначение = "фйъх13м9") Экспорт
ИмяЗначения = "_" + XMLСтрока(ИмяЗначения);
СтруктураСтарыхЗначений = ирКэш.ЗначенияДляПроверкиИзмененияЛкс();
Если Не ЛиСсылкаНаОбъектБДЛкс(Значение, Ложь) Тогда
Значение = Лев(РасширенноеПредставлениеЛкс(Значение), 1000); // Чтобы избежать залипания в кэше больших объектов
КонецЕсли;
Если СтруктураСтарыхЗначений.Свойство(ИмяЗначения) Тогда
СтароеЗначение = СтруктураСтарыхЗначений[ИмяЗначения];
Результат = СтароеЗначение <> Значение;
Иначе
Результат = Ложь;
КонецЕсли;
СтруктураСтарыхЗначений.Вставить(ИмяЗначения, Значение);
Если Результат Тогда
Если НужноеСтароеЗначение <> "фйъх13м9" Тогда
Если Не ЛиСсылкаНаОбъектБДЛкс(НужноеСтароеЗначение, Ложь) Тогда
НужноеСтароеЗначение = Лев(РасширенноеПредставлениеЛкс(НужноеСтароеЗначение), 1000);
КонецЕсли;
Если НужноеСтароеЗначение <> СтароеЗначение Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Если НужноеНовоеЗначение <> "фйъх13м9" Тогда
Если Не ЛиСсылкаНаОбъектБДЛкс(НужноеНовоеЗначение, Ложь) Тогда
НужноеНовоеЗначение = Лев(РасширенноеПредставлениеЛкс(НужноеНовоеЗначение), 1000);
КонецЕсли;
Если НужноеНовоеЗначение <> Значение Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция создает структуру из переданного объекта, добавляя к непустым свойствам свойство "<ИмяСвойства>_Инфо" с представлением вложенной коллекции с числом ее элементов.
//
// Параметры:
// Объект - Произвольный -
//
// Возвращаемое значение:
// - Структура
//
Функция Стк(Знач Объект) Экспорт
Возврат СтруктураИзОбъектаЛкс(Объект,,, Истина, Ложь);
КонецФункции
// Функция создает таблицу значений из переданной коллекции или табличного документа, добавляя
// 1. К колонкам, содержащим коллекции, колонку "<ИмяКолонки>_Инфо" с представлением вложенной коллекции, включающем количеством ее элементов.
// 2. К колонкам, содержащим структуры или ссылки на строки таблицы/дерева, колонки "<ИмяКолонки>_<ИмяВложенногоСвойства>" со значениями свойств вложенных объектов
//
// Параметры:
// Объект - ПроизвольнаяКоллекция, ТабличныйДокумент -
// АнализХранилищЗначений - Булево, *Ложь - нужно ли получать представления содержимого хранилищ значений, увеличивает длительность
// МаксЧислоЭлементов - Число, *0 - ограничить число строк в таблице значений, 0 - не ограничивать
// Сортировка - Строка, *"" - строка упорядочивания, выполняется после контроля МаксЧислоЭлементов
//
// Возвращаемое значение:
// - ТаблицаЗначений
//
Функция Кол(Объект, АнализХранилищЗначений = Ложь, МаксЧислоЭлементов = 0, Сортировка = "") Экспорт
Если ТипЗнч(Объект) = Тип("ТабличныйДокумент") Тогда
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Объект.Область());
Результат = Построитель.Результат.Выгрузить();
Иначе
Результат = ТаблицаЗначенийИзКоллекцииЛкс(Объект,,,,,,, Истина, АнализХранилищЗначений, МаксЧислоЭлементов, Сортировка);
КонецЕсли;
Возврат Результат;
КонецФункции
// Формирует строку условия точки останова по значениям примитивных свойств объекта.
// https://www.hostedredmine.com/issues/938460
// Параметры:
// Объект - Произвольный - объект, значения свойств которого нужно проверять, или проверяемое значение примитивного типа
// ИмяПеременной - Строка - имя переменной объекта в контексте проверки условия
// Результат:
// Строка - условие для точки останова, где свойства следуют в алфавитном порядке
Функция Усл(Объект, ИмяПеременной, МаксДлинаСтроки = 20, МаксДробныхЗнаков = 6) Экспорт
Структура = СтруктураИзОбъектаЛкс(Объект);
#Если Сервер И Не Сервер Тогда
Структура = Новый Структура;
#КонецЕсли
Результат = КодПроверкиЗначенияВыраженияЛкс(Объект, ИмяПеременной, МаксДлинаСтроки, МаксДробныхЗнаков);
Если Не ЗначениеЗаполнено(Результат) Тогда
Результат = Новый СписокЗначений;
Для Каждого КлючИЗначение Из Структура Цикл
ПроверяемоеВыражение = ИмяПеременной + "." + КлючИЗначение.Ключ;
ПроверяемоеЗначение = КлючИЗначение.Значение;
УсловиеСвойства = КодПроверкиЗначенияВыраженияЛкс(ПроверяемоеЗначение, ПроверяемоеВыражение, МаксДлинаСтроки, МаксДробныхЗнаков);
Если Не ЗначениеЗаполнено(УсловиеСвойства) Тогда
Продолжить;
КонецЕсли;
Результат.Добавить(УсловиеСвойства, КлючИЗначение.Ключ);
КонецЦикла;
Результат.СортироватьПоПредставлению();
Результат = СтрСоединитьЛкс(Результат.ВыгрузитьЗначения(), " И ");
КонецЕсли;
Возврат Результат;
КонецФункции
#КонецЕсли
// ОТЛАДКА
////////////////////////////////////////////////////////////////////////////////
// Результат: Число
Функция НомерВерсииПлатформыЛкс(Знач СтрокаВерсии, Знач ВключаяНомерСборки = Ложь) Экспорт
Фрагменты = СтрРазделитьЛкс(СтрокаВерсии);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
Для Счетчик = Фрагменты.Количество() По 4 Цикл
Фрагменты.Добавить("0");
КонецЦикла;
Результат = Число(Фрагменты[0]) * 100 * 1000 + Число(Фрагменты[1]) * 1000 + Число(Фрагменты[2]); // 6 цифр
Если ВключаяНомерСборки Тогда
Результат = Результат * 10000 + Число(Фрагменты[3]); // 10 цифр
КонецЕсли;
Возврат Результат;
КонецФункции
Функция АдресОсновногоСайтаЛкс() Экспорт
Возврат "devtool1c.ucoz.ru";
КонецФункции
Функция АдресСайтаЗадачЛкс() Экспорт
Возврат "https://www.hostedredmine.com/projects/devtool1c";
КонецФункции
// Выполняет текст алгоритма. Возращается результат через переменную "Результат".
//
// Параметры:
// ТекстДляВыполнения - Строка;
// _АлгоритмОбъект - СправочникОбъект
// *СтруктураПараметров - Структура, *Неопределено.
//
Функция ВыполнитьАлгоритм(_ТекстДляВыполнения, _АлгоритмОбъект = Null, _Режим = Null,
_П0 = Null, _П1 = Null, _П2 = Null, _П3 = Null, _П4 = Null, _П5 = Null, _П6 = Null, _П7 = Null, _П8 = Null, _П9 = Null) Экспорт
Перем Результат;
Выполнить(_ТекстДляВыполнения);
Возврат Результат;
КонецФункции
Процедура ВыполнитьАлгоритмБезРезультата(_ТекстДляВыполнения) Экспорт
Выполнить(_ТекстДляВыполнения);
КонецПроцедуры
Функция ВычислитьВыражение(Выражение14327783, Параметры = Неопределено, НаСервере14327783 = Ложь) Экспорт
// Здесь должен быть максимально чистый контекст выполнения
Если НаСервере14327783 Тогда
Результат24327783 = ирСервер.ВычислитьВыражение(Выражение14327783, Параметры);
Иначе
Если Параметры = Неопределено Тогда
Результат24327783 = ВычислитьВыражениеБезПараметровЛкс(Выражение14327783);
Иначе
Результат24327783 = Вычислить(Выражение14327783);
КонецЕсли;
КонецЕсли;
Возврат Результат24327783;
КонецФункции
Функция ВычислитьВыражениеБезПараметровЛкс(Выражение9124327783) Экспорт
Возврат Вычислить(Выражение9124327783);
КонецФункции
Функция ОписаниеТиповОдногоТипаИзОписанияТиповЛкс(Тип, ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
Массив = Новый Массив;
Массив.Добавить(Тип);
Результат = Новый ОписаниеТипов(Массив, ОписаниеТипов.КвалификаторыЧисла, ОписаниеТипов.КвалификаторыСтроки, ОписаниеТипов.КвалификаторыДаты, ОписаниеТипов.КвалификаторыДвоичныхДанных);
Возврат Результат;
КонецФункции
Функция ЭтоИмяЛокальногоКомпьютераЛкс(ИмяКомпьютера) Экспорт
Результат = Ложь
Или Не ЗначениеЗаполнено(ИмяКомпьютера)
Или ИмяКомпьютера = "."
Или СтрокиРавныЛкс(ИмяКомпьютера, "localhost")
Или ИмяКомпьютера = "127.0.0.1"
#Если Не ВебКлиент Тогда
Или СтрокиРавныЛкс(ИмяКомпьютера, ИмяКомпьютера())
#КонецЕсли
;
Возврат Результат;
КонецФункции
Функция ИмяКомпьютераКластераЛкс() Экспорт
Результат = ПервыйФрагментЛкс(НСтр(ПервыйФрагментЛкс(СтрокаСоединенияИнформационнойБазы(), ","), "Srvr"), ":");
Возврат Результат;
КонецФункции
Процедура ТребоватьТипЛкс(Значение, ИмяПараметра = "", Тип1, Тип2 = Неопределено, Тип3 = Неопределено, Тип4 = Неопределено, Тип5 = Неопределено, Тип6 = Неопределено) Экспорт
ТипЗначения = ТипЗнч(Значение);
Если Ложь
Или ТипЗначения = Тип1
Или ТипЗначения = Тип2
Или ТипЗначения = Тип3
Или ТипЗначения = Тип4
Или ТипЗначения = Тип5
Или ТипЗначения = Тип6
Тогда
Возврат;
КонецЕсли;
Массив = Новый Массив;
Массив.Добавить(Тип1);
Массив.Добавить(Тип2);
Массив.Добавить(Тип3);
Массив.Добавить(Тип4);
Массив.Добавить(Тип5);
Массив.Добавить(Тип6);
СтрокаТипов = Новый Массив;
Для Каждого Тип Из Массив Цикл
Если Ложь
Или ТипЗначения = Тип
Или (Истина
И Тип = Тип("Булево")
И (Ложь
Или Значение = 0
Или Значение = 1))
Тогда
Возврат;
КонецЕсли;
Если Тип = Неопределено Тогда
Прервать;
КонецЕсли;
СтрокаТипов.Добавить(Тип);
КонецЦикла;
Текст = "";
Если ЗначениеЗаполнено(ИмяПараметра) Тогда
Текст = Текст + "Для параметра """ + ИмяПараметра + """ ";
КонецЕсли;
Текст = Текст + "Получено значение типа """ + ТипЗначения + """ вместо ожидаемых типов: " + СтрСоединитьЛкс(СтрокаТипов) + ".";
ВызватьИсключение Текст;
КонецПроцедуры
#Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда
Функция ЗначениеПеременнойИзТаблицыЛокальногоКонтекстаЛкс(ИмяПеременной, ТаблицаЛокальногоКонтекста) Экспорт
СтруктураКлюча = Новый Структура("нСлово, ТипСлова", НРег(ИмяПеременной), "Свойство");
НайденныеСтроки = ТаблицаЛокальногоКонтекста.НайтиСтроки(СтруктураКлюча);
Если НайденныеСтроки.Количество() > 0 Тогда
Возврат НайденныеСтроки[0].Значение;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
// Вычисляет тип значения функции УК по внутренним параметрам и аргументам.
// Предназначена для вызвова из ирКлсПолеТекстаПрограммы.
//
// Параметры:
// ТаблицаЛокальногоКонтекста - ТаблицаЗначений - (см. ирКлсПолеТекстаПрограммы);
// МассивПараметров - Массив - выражений параметров.
//
// Возвращаемое значение:
// ТаблицаЗначений - ТаблицаТипов (см. ирКлсПолеТекстаПрограммы).
//
Функция ПравилоВычисленияТипаЗначенияКПА(ТаблицаЛокальногоКонтекста, МассивПараметров) Экспорт
лПлатформа = ирКэш.Получить();
ТаблицаТипов = лПлатформа.НоваяТаблицаТипов();
Алгоритм = ЗначениеПеременнойИзТаблицыЛокальногоКонтекстаЛкс(МассивПараметров[0], ТаблицаЛокальногоКонтекста);
Если Алгоритм <> Неопределено Тогда
Структура = ирКПА(Алгоритм);
СтруктураТипа = лПлатформа.СтруктураТипаИзЗначения(Структура);
ЗаполнитьЗначенияСвойств(ТаблицаТипов.Добавить(), СтруктураТипа);
КонецЕсли;
Возврат ТаблицаТипов;
КонецФункции
// Конструктор Параметров Алгоритма.
//
// Параметры:
// Алгоритм - СправочникСсылка.ирАлгоритмы.
//
// Возвращаемое значение:
// Структура - ключ - имя, значение - значение.
//
Функция ирКПА(Знач Алгоритм) Экспорт
#Если Сервер И Не Сервер Тогда
Алгоритм = Справочники.ирАлгоритмы.ПустаяСсылка();
#КонецЕсли
СтруктураПараметров = Новый Структура;
Для Каждого СтрокаПараметра Из Алгоритм.Параметры Цикл
СтруктураПараметров.Вставить(СтрокаПараметра.Имя, СтрокаПараметра.Значение);
КонецЦикла;
Возврат СтруктураПараметров;
КонецФункции // УК()
// Именованный Вызов Алгоритма. Передача параметров выполняется по имени.
//
// Параметры:
// Алгоритм - СправочникСсылка.ирАлгоритмы, Строка - ссылка или GUID или имя сервиса;
// *СтруктураПараметров - Структура, *Неопределено - ключи - имена параметров, значения - значения параметров;
// *пНастройкаАлгоритма - СправочникСсылка.НаборыЗначенийПараметров2iS, *Неопределено - набор значений параметров,
// имеющий приоритет ниже, чем СтруктураПараметров;
// *ПреобразоватьРезультатВСтрокуВнутр - Булево, *Ложь - преобразовать результат в строку внутреннюю (сериализовать)
//
// Возвращаемое значение:
// Произвольный.
//
Функция ирИВА(Знач Алгоритм, Знач СтруктураПараметров = Неопределено) Экспорт
Если СтруктураПараметров = Неопределено Тогда
СтруктураПараметров = Новый Структура;
КонецЕсли;
АлгоритмОбъект = ирОбщий.ПолучитьАлгоритмОбъектПоИдентификаторуЛкс(Алгоритм);
Результат = ирКэш.Получить().ВыполнитьМетодАлгоритма(АлгоритмОбъект, 1, СтруктураПараметров);
Возврат Результат;
КонецФункции // ирИВА()
// Позиционный Вызов Алгоритма. Передача параметров выполняется по позиции.
//
// Параметры
// Алгоритм - СправочникСсылка.Сервисы2iS, Строка - ссылки или имя сервиса;
// *П... - Произвольный, *Null - параметры сервиса.
//
// Возвращаемое значение:
// Произвольное.
//
Функция ирПВА(Знач Алгоритм, П0=Null, П1=Null, П2=Null, П3=Null,
П4=Null, П5=Null, П6=Null, П7=Null, П8=Null, П9=Null) Экспорт
АлгоритмОбъект = ирОбщий.ПолучитьАлгоритмОбъектПоИдентификаторуЛкс(Алгоритм);
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Результат = мПлатформа.ВыполнитьМетодАлгоритма(АлгоритмОбъект, 0, П0, П1, П2, П3, П4, П5, П6, П7, П8, П9);
Возврат Результат;
КонецФункции
// Возвращает стек встроенного языка строкой через выброс и обработку исключения. В точке останова возвращает пустую строку, т.к. там не передается стек предмета отладки.
// Полезна для временного включения записи диагностической информации в журнал регистрации путем временной вставки в код.
//
// Параметры:
// ЗаписатьВЖурналРегистрации - Булево, *Истина - записать стек в журнал регистрации, используется УровеньЖурналаРегистрации.Предупреждение
//
// Возвращаемое значение:
// - Строка
//
Функция СтекЛкс(ЗаписатьВЖурналРегистрации = Истина) Экспорт
Результат = Неопределено;
#Если ТолстыйКлиентОбычноеПриложение Тогда
Если ирКэш.НомерВерсииПлатформыЛкс() < 803019 Тогда
Результат = "Для обычного приложения функция доступна начиная с 8.3.19";
КонецЕсли;
#КонецЕсли
Если Результат = Неопределено Тогда
в8вт9я24хъЭЖ93 = 1;
Попытка
ВызватьИсключение в8вт9я24хъЭЖ93;
Исключение
Результат = ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке());
Результат = ПоследнийФрагментЛкс(Результат, "в8вт9я24хъЭЖ93;" + Символы.ПС);
Маркеры = Новый Массив;
Маркеры.Добавить("СтекЛкс");
Для Каждого Маркер Из Маркеры Цикл
Результат = ПоследнийФрагментЛкс(Результат, Маркер + "();" + Символы.ПС);
Результат = ПоследнийФрагментЛкс(Результат, НРег(Маркер) + "();" + Символы.ПС);
Результат = ПоследнийФрагментЛкс(Результат, Маркер + "()" + Символы.ПС);
Результат = ПоследнийФрагментЛкс(Результат, НРег(Маркер) + "()" + Символы.ПС);
КонецЦикла;
КонецПопытки
КонецЕсли;
Если ЗаписатьВЖурналРегистрации Тогда
ЗаписьЖурналаРегистрации("Стек", УровеньЖурналаРегистрации.Предупреждение,,, Результат);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПодробноеПредставлениеОшибкиЛкс(Знач ИнформацияОбОшибке) Экспорт
#Если Сервер И Не Сервер Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
#КонецЕсли
Если ИнформацияОбОшибке = Неопределено Тогда
// Из аварийного фонового задания нередко возвращается пустое свойство ИнформацияОбОшибке
Результат = "<>";
Иначе
Результат = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
// Антибаг платформы 8.3.19-22+ https://www.hostedredmine.com/issues/941533
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(Результат);
НомерПоследнейСтроки = ТекстовыйДокумент.КоличествоСтрок();
Если Найти(ТекстовыйДокумент.ПолучитьСтроку(НомерПоследнейСтроки), "{") = 0 Тогда
Пока Истина
И ИнформацияОбОшибке.Причина <> Неопределено
И (Ложь
Или ЗначениеЗаполнено(ИнформацияОбОшибке.Причина.ИмяМодуля)
Или ИнформацияОбОшибке.Причина.Причина <> Неопределено)
Цикл
ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
КонецЦикла;
ТекстовыйДокумент.УдалитьСтроку(НомерПоследнейСтроки);
Результат = ТекстовыйДокумент.ПолучитьТекст() + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЗагрузитьЗначениеИзФайлаЛкс(Знач ПолноеИмяФайла, Знач Сжатие = Ложь, Знач Формат = "XML", Знач ВыводитьОшибки = Истина) Экспорт
Если Формат <> "XML" И ирКэш.НомерВерсииПлатформыЛкс() < 803007 Тогда
Формат = "XML";
КонецЕсли;
Файл = Новый Файл(ПолноеИмяФайла);
Если СтрокиРавныЛкс(Файл.Расширение, ".zip") Тогда
Сжатие = Истина;
КонецЕсли;
Если Сжатие Тогда
ВременныйКаталог = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ВременныйКаталог);
Попытка
ЗипЧтение = Новый ЧтениеZipФайла(ПолноеИмяФайла);
Исключение
ОписаниеОшибки = ОписаниеОшибки();
ЗипЧтение = Неопределено;
КонецПопытки;
Если ЗипЧтение <> Неопределено Тогда
ЗипЧтение.ИзвлечьВсе(ВременныйКаталог);
ПолноеИмяФайла = ВременныйКаталог + РазделительПутиКФайлуЛкс() + ЗипЧтение.Элементы[0].Имя;
КонецЕсли;
КонецЕсли;
Если Формат = "XML" Тогда
ЧтениеХМЛ = Новый ЧтениеXML;
Иначе
ЧтениеХМЛ = МойЧтениеJSON();
КонецЕсли;
ЧтениеХМЛ.ОткрытьФайл(ПолноеИмяФайла);
Попытка
//Результат = ЗначениеИзФайла(ВыборФайла.ПолноеИмяФайла);
Если Формат = "XML" Тогда
Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеХМЛ);
Иначе
Результат = СериализаторXDTO.ПрочитатьJSON(ЧтениеХМЛ);
КонецЕсли;
Исключение
Если ВыводитьОшибки Тогда
СообщитьЛкс(ОписаниеОшибки());
КонецЕсли;
Результат = Неопределено;
КонецПопытки;
ЧтениеХМЛ.Закрыть();
Если Сжатие Тогда
УдалитьФайлы(ВременныйКаталог, "*");
КонецЕсли;
Если ТипЗнч(Результат) = Тип("Структура") И Результат.Свойство("ВложенноеНесериализуемоеЗначение") Тогда
Результат = Результат.ВложенноеНесериализуемоеЗначение.Получить();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СохранитьЗначениеВФайлЛкс(Знач Значение, Знач ПолноеИмяФайла, Сжатие = Ложь, УровеньСжатия = Неопределено, Знач Формат = "XML") Экспорт
Если Формат <> "XML" И ирКэш.НомерВерсииПлатформыЛкс() < 803007 Тогда
Формат = "XML";
КонецЕсли;
Если Формат = "XML" Тогда
ЗаписьХМЛ = Новый ЗаписьXML;
Иначе
ЗаписьХМЛ = МойЗаписьJSON();
КонецЕсли;
ЗаписьХМЛ.ОткрытьФайл(ПолноеИмяФайла);
Результат = Истина;
Попытка
//ЗначениеВФайл(ПолноеИмяФайла, Значение);
Если Формат = "XML" Тогда
СериализаторXDTO.ЗаписатьXML(ЗаписьХМЛ, Значение, НазначениеТипаXML.Явное);
Иначе
СериализаторXDTO.ЗаписатьJSON(ЗаписьХМЛ, Значение, НазначениеТипаXML.Явное);
КонецЕсли;
Исключение
ЗаписьХМЛ.Закрыть();
ЗаписьХМЛ = Новый ЗаписьXML;
ЗаписьХМЛ.ОткрытьФайл(ПолноеИмяФайла);
Значение = Новый Структура("ВложенноеНесериализуемоеЗначение", Новый ХранилищеЗначения(Значение));
Попытка
СериализаторXDTO.ЗаписатьXML(ЗаписьХМЛ, Значение);
СообщитьЛкс("При сохранении данных в файл использована сериализация через хранилище значения из-за наличия недопустимых символов XML");
Исключение
СообщитьЛкс(ОписаниеОшибки());
Результат = Ложь;
КонецПопытки;
КонецПопытки;
ЗаписьХМЛ.Закрыть();
Если Результат И Сжатие Тогда
ВременныйКаталог = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ВременныйКаталог);
Файл = Новый Файл(ПолноеИмяФайла);
ИмяВременногоФайла = ВременныйКаталог + РазделительПутиКФайлуЛкс() + Файл.ИмяБезРасширения + ".xml";
ПереместитьФайл(Файл.ПолноеИмя, ИмяВременногоФайла);
ЗаписьЗип = Новый ЗаписьZipФайла(ПолноеИмяФайла,,,, УровеньСжатия);
ЗаписьЗип.Добавить(ИмяВременногоФайла);
ЗаписьЗип.Записать();
УдалитьФайлы(ВременныйКаталог, "*");
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КомпоновщикТаблицыМетаданныхЛкс(Знач ПолноеИмяМД, ВызыватьИсключениеПриОтсутствииПрав = Истина, ИндексПараметраПериодичность = Неопределено,
ВыражениеПараметраПериодичность = "", ИменаВместоПредставлений = Ложь) Экспорт
СхемаКомпоновкиДанных = СоздатьСхемуКомпоновкиПоОбъектуМДЛкс(ПолноеИмяМД,, Ложь,, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность, ИменаВместоПредставлений);
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Попытка
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
Исключение
// Антибаг платформы 8.2.18
// Ошибка при вызове конструктора (ИсточникДоступныхНастроекКомпоновкиДанных)
// ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных);
//по причине:
//Ошибка получения информации набора данных
//по причине:
//Ошибка в запросе набора данных
//по причине:
//{(1, 17)}: Неверное присоединение
//ВЫБРАТЬ Т.* ИЗ <>>КАК Т
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
Если ОбъектМД = Неопределено Тогда
// Возможно эта логика уже есть в какой то функции
лПолноеИмяМД = ПолноеИмяМД;
Фрагменты = СтрРазделитьЛкс(ПолноеИмяМД);
Если Фрагменты.Количество() > 1 Тогда
Фрагменты.Удалить(Фрагменты.Количество() - 1);
лПолноеИмяМД = СтрСоединитьЛкс(Фрагменты, ".");
КонецЕсли;
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(лПолноеИмяМД);
КонецЕсли;
Если Ложь
Или ОбъектМД = Неопределено
Или Не ПравоДоступа("Чтение", ОбъектМД)
Тогда
Если ВызыватьИсключениеПриОтсутствииПрав Тогда
ВызватьИсключение "Таблица отсутствует или нет прав на ее чтение """ + ПолноеИмяМД + """";
Иначе
Возврат Неопределено;
КонецЕсли;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(ИсточникДоступныхНастроек);
// Для сравнения скорости в отладчике. Примерно та же скорость через построитель.
//ПсевдонимТаблицы = "Т";
//ПолноеИмяИлиОбъектМД = ПолноеИмяМД;
//Если ТипЗнч(ПолноеИмяИлиОбъектМД) = Тип("Строка") Тогда
// ПолноеИмяМД = ПолноеИмяИлиОбъектМД;
//Иначе
// ПолноеИмяМД = ПолноеИмяИлиОбъектМД.ПолноеИмя();
//КонецЕсли;
//ПолноеИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД);
//Если ИндексПараметраПериодичность <> Неопределено Тогда
// ПолноеИмяТаблицыБД = ПолноеИмяТаблицыБД + "(";
// Для Индекс = 1 По ИндексПараметраПериодичность Цикл
// ПолноеИмяТаблицыБД = ПолноеИмяТаблицыБД + ",";
// КонецЦикла;
// ПолноеИмяТаблицыБД = ПолноеИмяТаблицыБД + ВыражениеПараметраПериодичность + ")";
//КонецЕсли;
//ТекстЗапроса = "ВЫБРАТЬ " + ПсевдонимТаблицы + ".* ИЗ " + ПолноеИмяТаблицыБД + " КАК " + ПсевдонимТаблицы;
//Построитель = Новый ПостроительЗапроса(ТекстЗапроса);
//Построитель.ЗаполнитьНастройки();
Возврат КомпоновщикНастроек;
КонецФункции
Функция ЕстьНекорректныеЭлементыВКомпоновщикеНастроекЛкс(Знач ПроверочныйКомпоновщик, выхСтрокаТекущихНастроек = "", выхСтрокаИсправленныхНастроек = "") Экспорт
выхСтрокаТекущихНастроек = ОбъектВСтрокуXMLЛкс(ПроверочныйКомпоновщик.Настройки);
КомпоновщикНастроекВосстановитьЛкс(ПроверочныйКомпоновщик);
выхСтрокаИсправленныхНастроек = ОбъектВСтрокуXMLЛкс(ПроверочныйКомпоновщик.Настройки);
ЕстьНекорректныеЭлементы = выхСтрокаИсправленныхНастроек <> выхСтрокаТекущихНастроек;
Возврат ЕстьНекорректныеЭлементы;
КонецФункции
Процедура ОбработкаПолученияФормыЛкс(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка, ЕстьУправляемаяФорма = Ложь) Экспорт
Если ЕстьУправляемаяФорма Тогда
Возврат;
КонецЕсли;
СтандартнаяОбработка = Ложь;
Если Не ирКэш.ЛиСеансТолстогоКлиентаЛкс() Тогда
ВыбраннаяФорма = "Обработка.ирПортативный.Форма.ЗапускСеансаУправляемая";
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
Функция ВыполнитьАлгоритмЧерезВнешнююОбработкуЛкс(ИмяФайлаВнешнейОбработки, СтруктураПараметров, выхВремяНачала = Неопределено, ВерсияАлгоритма = Неопределено, Знач ЛиСинтаксическийКонтроль = Ложь) Экспорт
РазрешитьВыборИсключения = Истина;
#Если Сервер И Не Клиент Тогда
Файл = Новый Файл(ИмяФайлаВнешнейОбработки);
Если Не Файл.Существует() Тогда
КаталогОбъектовДляОтладки = КаталогОбъектовДляОтладкиЛкс();
Если Не ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда
ВызватьИсключение "файл внешней обработки алгоритма не доступен на сервере. Рекомендуется в общих настройках инструментов задать сетевой каталог объектов для отладки.";
КонецЕсли;
КонецЕсли;
Если Не ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда
// Антибаг платформы. Иначе будет выполняться старая версия файла https://www.hostedredmine.com/issues/966275
РазрешитьВыборИсключения = Ложь;
КонецЕсли;
#КонецЕсли
Попытка
ВнешняяОбработка = ВнешниеОбработки.Создать(ИмяФайлаВнешнейОбработки, Ложь);
Если ЛиСинтаксическийКонтроль Тогда
Возврат Неопределено;
КонецЕсли;
Если ВерсияАлгоритма <> Неопределено И ВнешняяОбработка.ВерсияАлгоритма() <> ВерсияАлгоритма Тогда
// Антибаг 8.3.11.2700-?. Testplatform@1c.ru - Support #17972. В обычном приложении на клиенте при повторном создании с одним именем файла и внутренней версией используются метаданные первой обработки в сеансе.
СообщитьЛкс("Внешняя обработка не обновилась в кэше процесса 1С. Пути обхода: выполнение в фоне, выполнение в управляемом приложении, перезапуск процесса.", СтатусСообщения.Внимание);
КонецЕсли;
ОбщиеМодули = ПолучитьСтруктуруОсновныхОбщихМодулейЛкс();
выхВремяНачала = ТекущееВремяВМиллисекундахЛкс();
ВнешняяОбработка.мМетод(СтруктураПараметров, ОбщиеМодули);
Исключение
Если РазрешитьВыборИсключения Тогда
ВызватьИсключение;
КонецЕсли;
// Антибаг платформы. Иначе будет выполняться старая версия файла https://www.hostedredmine.com/issues/966275
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
Возврат ОписаниеОшибки;
КонецФункции
Функция ТекстМодуляСгенерированнойВнешнейОбработки(ПолноеИмяФайла) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Файл = Новый Файл(ПолноеИмяФайла);
Текст = мПлатформа.ТекстМодуляСгенерированнойВнешнейОбработки(Файл);
Возврат Текст;
КонецФункции
Функция ПолучитьСтруктуруОсновныхОбщихМодулейЛкс() Экспорт
ОбщиеМодули = Новый Структура;
ОбщиеМодули.Вставить("ирОбщий", ирОбщий);
#Если Клиент Тогда
ОбщиеМодули.Вставить("ирКлиент", ирКлиент);
#КонецЕсли
ОбщиеМодули.Вставить("ирКэш", ирКэш);
ОбщиеМодули.Вставить("ирСервер", ирСервер);
Возврат ОбщиеМодули;
КонецФункции
Процедура ОбновитьТипЗначенияВСтрокеТаблицыЛкс(ТекущаяСтрока, Знач ИмяКолонкиЗначения = "Значение", Знач ИмяКолонкиИлиОписаниеТипов = "ОписаниеТипов", Знач ИмяКолонкиТипаЗначения = "ТипЗначения",
Знач ИмяКолонкиИмяТипаЗначения = "ИмяТипаЗначения", Знач Колонки = Неопределено, Знач РасширенноеЗначение = Неопределено, Знач ТипЗначения = Неопределено) Экспорт
Если Колонки = Неопределено Тогда
Колонки = ТекущаяСтрока.Владелец().Колонки;
Иначе
ТребоватьТипЛкс(Колонки, Тип("ТаблицаЗначений"), Тип("КоллекцияКолонокТаблицыЗначений"), Тип("КоллекцияКолонокДереваЗначений"), Тип("КоллекцияКолонокРезультатаЗапроса"), , Тип("КоллекцияОбъектовМетаданных"));
#Если Сервер И Не Сервер Тогда
Колонки = Новый ТаблицаЗначений;
Колонки = Колонки.Колонки;
#КонецЕсли
КонецЕсли;
Если ТипЗначения = Неопределено Тогда
Если ЗначениеЗаполнено(ИмяКолонкиЗначения) Тогда
РасширенноеЗначение = ТекущаяСтрока[ИмяКолонкиЗначения];
КонецЕсли;
ТипЗначения = ТипЗнч(РасширенноеЗначение);
КонецЕсли;
Если ТипЗнч(ИмяКолонкиИлиОписаниеТипов) <> Тип("ОписаниеТипов") Тогда
КолонкаОписанияТипов = Колонки.Найти(ИмяКолонкиИлиОписаниеТипов);
Если КолонкаОписанияТипов <> Неопределено Тогда
ИмяКолонкиИлиОписаниеТипов = ТекущаяСтрока[ИмяКолонкиИлиОписаниеТипов];
Иначе
ИмяКолонкиИлиОписаниеТипов = Неопределено;
КонецЕсли;
КонецЕсли;
Если ТипЗнч(Колонки) = Тип("ТаблицаЗначений") Тогда
ЕстьКолонкаТипЗначения = Колонки.Найти(ИмяКолонкиТипаЗначения, "Имя") <> Неопределено;
Иначе
ЕстьКолонкаТипЗначения = Колонки.Найти(ИмяКолонкиТипаЗначения) <> Неопределено;
КонецЕсли;
Если ЕстьКолонкаТипЗначения Тогда
ТекущаяСтрока[ИмяКолонкиТипаЗначения] = ПредставлениеТипаЛкс(ТипЗначения, ИмяКолонкиИлиОписаниеТипов, Ложь);
КонецЕсли;
Если ТипЗнч(Колонки) = Тип("ТаблицаЗначений") Тогда
ЕстьКолонкаИмяТипаЗначения = Колонки.Найти(ИмяКолонкиИмяТипаЗначения, "Имя") <> Неопределено;
Иначе
ЕстьКолонкаИмяТипаЗначения = Колонки.Найти(ИмяКолонкиИмяТипаЗначения) <> Неопределено;
КонецЕсли;
Если ЕстьКолонкаИмяТипаЗначения Тогда
ТекущаяСтрока[ИмяКолонкиИмяТипаЗначения] = ПредставлениеТипаЛкс(ТипЗначения, ИмяКолонкиИлиОписаниеТипов, Истина);
КонецЕсли;
КонецПроцедуры
// Функция - Параметры запуска приложения1 с лкс
//
// Параметры:
// ИмяПользователяИнфобазы - -
// ПарольПользователяИнфобазы - -
// КодРазрешения - -
// РежимКонфигуратора - -
// РежимЗапуска - Строка - ОбычноеПриложение, УправляемоеПриложениеТолстый, УправляемоеПриложениеТонкий
// ПрименитьТекущиеПараметрыЗапуска - -
// ОчисткаКэшаКлиентСерверныхВызовов - -
// ДополнительныеПараметры - -
// СообщитьСтрокуПараметров - -
// СтрокаСоединения - -
// ОткрытьПортативныеИнструменты - -
// РежимИнтерфейсаТакси - -
// РазделениеДанных - -
// ОтключитьАутентификациюОС - -
// КодЯзыка - -
// ПараметрЗапуска - -
// ИмяВСпискеБазПользователя - -
//
// Возвращаемое значение:
// -
//
Функция ПараметрыЗапускаПриложения1СЛкс(Знач ИмяПользователяИнфобазы = "", Знач ПарольПользователяИнфобазы = "", КодРазрешения = "", РежимКонфигуратора = Ложь,
РежимЗапуска = "ОбычноеПриложение", ПрименитьТекущиеПараметрыЗапуска = Истина, ОчисткаКэшаКлиентСерверныхВызовов = Ложь, ДополнительныеПараметры = "", СообщитьСтрокуПараметров = Истина,
СтрокаСоединения = "", ОткрытьПортативныеИнструменты = Ложь, РежимИнтерфейсаТакси = Ложь, РазделениеДанных = "", ОтключитьАутентификациюОС = Ложь, КодЯзыка = "", ПараметрЗапуска = "",
Знач ИмяВСпискеБазПользователя = "", Знач ИмяБазовогоФайлаПортативного = "") Экспорт
Если ПустаяСтрока(СтрокаСоединения) И ПустаяСтрока(ИмяВСпискеБазПользователя) Тогда
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
КонецЕсли;
ПараметрыЗапуска = "";
Если РежимКонфигуратора Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " CONFIG";
Иначе
ПараметрыЗапуска = ПараметрыЗапуска + " ENTERPRISE";
КонецЕсли;
Если ЗначениеЗаполнено(СтрокаСоединения) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /IBConnectionString" + ТекстВВыражениеВстроенногоЯзыкаЛкс(СтрокаСоединения);
КонецЕсли;
Если ЗначениеЗаполнено(ИмяВСпискеБазПользователя) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + ПараметрЗапускаПриложенияДляЭлементаСпискаБазЛкс(ИмяВСпискеБазПользователя);
КонецЕсли;
Если ЗначениеЗаполнено(ДополнительныеПараметры) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " " + ДополнительныеПараметры;
КонецЕсли;
Если ЗначениеЗаполнено(ИмяПользователяИнфобазы) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /N""" + ИмяПользователяИнфобазы + """";
КонецЕсли;
Если ОтключитьАутентификациюОС Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /WA-";
КонецЕсли;
Если ЗначениеЗаполнено(ПарольПользователяИнфобазы) Тогда
СтрокаПараметраПароля = "/P""" + ПарольПользователяИнфобазы + """";
СтрокаЗаменыПароля = "/P""" + "***" + """";
ПараметрыЗапуска = ПараметрыЗапуска + " " + СтрокаПараметраПароля;
КонецЕсли;
Если ЗначениеЗаполнено(ПараметрЗапуска) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /C""" + ПараметрЗапуска + """";
КонецЕсли;
Если ЗначениеЗаполнено(КодРазрешения) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /UC""" + КодРазрешения + """";
КонецЕсли;
Если Не РежимКонфигуратора Тогда
Если ПрименитьТекущиеПараметрыЗапуска Тогда
ПараметрыЗапускаДляОтладки = ПараметрыЗапускаСеансаТекущиеЛкс();
ПараметрыЗапуска = ПараметрыЗапуска + " " + ПараметрыЗапускаДляОтладки;
КонецЕсли;
Если ОчисткаКэшаКлиентСерверныхВызовов Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /ClearCache";
КонецЕсли;
Если РежимИнтерфейсаТакси Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /iTaxi";
КонецЕсли;
Если ОткрытьПортативныеИнструменты Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ИмяБазовогоФайлаПортативного = ирПортативный.ИспользуемоеИмяФайла;
КонецЕсли;
Если ЗначениеЗаполнено(ИмяБазовогоФайлаПортативного) Тогда
Если СтрНачинаетсяСЛкс(РежимЗапуска, "Управляемое") Тогда
ИмяБазовогоФайлаПортативного = СтрЗаменитьЛкс(ИмяБазовогоФайлаПортативного, "ирПортативный.epf", "Модули" + РазделительПутиКФайлуЛкс() + "ирУстановщикРасширения.epf");
КонецЕсли;
ПараметрыЗапуска = ПараметрыЗапуска + " /Execute""" + ИмяБазовогоФайлаПортативного + """";
КонецЕсли;
КонецЕсли;
Если СтрокиРавныЛкс(РежимЗапуска, "Авто") Тогда
// Из-за этого иногда долго стартует почему то
ПараметрыЗапуска = ПараметрыЗапуска + " /AppAutoCheckMode"; // Автоматический выбор типа приложения для запуска
ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "ОбычноеПриложение") Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /RunModeOrdinaryApplication";
ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "УправляемоеПриложениеТолстый") Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /RunModeManagedApplication";
ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "УправляемоеПриложениеТонкий") Тогда
//ПараметрыЗапуска = ПараметрыЗапуска + "/IBConnectionString" + ТекстВВыражениеВстроенногоЯзыкаЛкс(СтрокаСоединения);
КонецЕсли;
Если ЗначениеЗаполнено(РазделениеДанных) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /Z""" + РазделениеДанных + """";
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(КодЯзыка) Тогда
ПараметрыЗапуска = ПараметрыЗапуска + " /L""" + КодЯзыка + """";
КонецЕсли;
Если СообщитьСтрокуПараметров Тогда
СообщитьЛкс(СтрЗаменить(ПараметрыЗапуска, СтрокаПараметраПароля, СтрокаЗаменыПароля));
КонецЕсли;
Возврат ПараметрыЗапуска;
КонецФункции
Функция ПараметрЗапускаПриложенияДляЭлементаСпискаБазЛкс(Знач ИмяВСпискеБазПользователя) Экспорт
Результат = " /IBName" + ТекстВВыражениеВстроенногоЯзыкаЛкс(ИмяВСпискеБазПользователя);
Возврат Результат;
КонецФункции
Функция СоздатьСсылочныйОбъектПоМетаданнымЛкс(ОбъектИлиИмяМД, ЭтоГруппаДляНового = Ложь, ИдентификаторСсылки = Неопределено, ЗаполнитьНовый = Истина) Экспорт
УстановитьПривилегированныйРежим(Истина);
Менеджер = ПолучитьМенеджерЛкс(ОбъектИлиИмяМД);
Если ТипЗнч(ОбъектИлиИмяМД) = Тип("ОбъектМетаданных") Тогда
ОбъектМД = ОбъектИлиИмяМД;
Иначе
ОбъектМД = ПолучитьМетаданныеЛкс(ОбъектИлиИмяМД);
КонецЕсли;
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
ИмяТипаМетаданного = ПеревестиВРусский(ПервыйФрагментЛкс(ПолноеИмяМД));
Попытка
Если ИмяТипаМетаданного = "Справочник" Или ИмяТипаМетаданного = "ПланВидовХарактеристик" Тогда
Если ЭтоГруппаДляНового Тогда
Объект = Менеджер.СоздатьГруппу();
Иначе
Объект = Менеджер.СоздатьЭлемент();
КонецЕсли;
ИначеЕсли ИмяТипаМетаданного = "Документ" Тогда
Объект = Менеджер.СоздатьДокумент();
ИначеЕсли ИмяТипаМетаданного = "Задача" Тогда
Объект = Менеджер.СоздатьЗадачу();
ИначеЕсли ИмяТипаМетаданного = "БизнесПроцесс" Тогда
Объект = Менеджер.СоздатьБизнесПроцесс();
ИначеЕсли ИмяТипаМетаданного = "ПланОбмена" Тогда
Объект = Менеджер.СоздатьУзел();
ИначеЕсли ИмяТипаМетаданного = "ПланВидовРасчета" Тогда
Объект = Менеджер.СоздатьВидРасчета();
ИначеЕсли ИмяТипаМетаданного = "ПланСчетов" Тогда
Объект = Менеджер.СоздатьСчет();
ИначеЕсли ИмяТипаМетаданного = "ВнешнийИсточникДанных" Тогда
Объект = Менеджер.СоздатьОбъект();
Иначе
ВызватьИсключение "Неизвестный тип метаданных """ + ИмяТипаМетаданного + """";
КонецЕсли;
Исключение
ПроверитьОшибкуПодписокНаКлиентеЛкс(ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
Если ИдентификаторСсылки = Неопределено Тогда
ИдентификаторСсылки = Новый УникальныйИдентификатор();
КонецЕсли;
Объект.УстановитьСсылкуНового(Менеджер.ПолучитьСсылку(ИдентификаторСсылки));
Если ЗаполнитьНовый Тогда
Объект.Заполнить(Неопределено);
КонецЕсли;
Возврат Объект;
КонецФункции
Процедура ПроверитьОшибкуПодписокНаКлиентеЛкс(ОписаниеОшибки)
#Если Клиент Тогда
Если Найти(ОписаниеОшибки, "Обработчик события не найден") > 0 Тогда
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
СообщитьЛкс("Для предотвращения ошибок инициализации объектов рекомендуется в общих параметрах записи установить флажок ""Объекты на сервере""=Да или перейти на непортативный вариант инструментов");
Иначе
СообщитьЛкс("Для предотвращения ошибок инициализации объектов рекомендуется в общих параметрах записи установить флажки ""Объекты на сервере""=Да и ""Не использовать имитаторы""=Нет");
КонецЕсли;
КонецЕсли;
#КонецЕсли
КонецПроцедуры
Функция СтрокаПустогоИдентификатораЛкс() Экспорт
Возврат "00000000-0000-0000-0000-000000000000";
КонецФункции
// Функция - Имя типа из полного имени МДЛкс
// Параметры:
// ПолноеИмяИлиОбъектМД - Строка, ОбъектМетаданных -
// ПодтипРус - -
// ФрагментыИмени - -
// Возвращаемое значение:
// -
Функция ИмяТипаИзПолногоИмениМДЛкс(Знач ПолноеИмяИлиОбъектМД, Знач ПодтипРус = "Ссылка", Знач ФрагментыИмени = Неопределено) Экспорт
Если ТипЗнч(ПолноеИмяИлиОбъектМД) <> Тип("Строка") Тогда
ПолноеИмяИлиОбъектМД = ПолноеИмяИлиОбъектМД.ПолноеИмя();
КонецЕсли;
Если ФрагментыИмени = Неопределено Тогда
ФрагментыИмени = СтрРазделитьЛкс(ПолноеИмяИлиОбъектМД);
КонецЕсли;
Если ФрагментыИмени.Количество() = 3 Тогда
ИмяТипа = ИмяТипаИзПолногоИмениТаблицыБДЛкс(ПолноеИмяИлиОбъектМД, ПодтипРус);
Иначе
ИмяПерерасчет = ПеревестиСтроку("Перерасчет");
ПервоеСлово = "";
ИменаМД = "";
Для Счетчик = 1 По ФрагментыИмени.Количество() / 2 Цикл
ДобавкаСлова = ФрагментыИмени[(Счетчик - 1) * 2];
Если ДобавкаСлова = ИмяПерерасчет Тогда
ПервоеСлово = ИмяПерерасчет;
Иначе
ПервоеСлово = ПервоеСлово + ДобавкаСлова;
КонецЕсли;
ИменаМД = ИменаМД + "." + ФрагментыИмени[(Счетчик - 1) * 2 + 1];
КонецЦикла;
Если ЛиРусскаяБукваЛкс(Лев(ПервоеСлово, 1)) Тогда
Подтип = ПодтипРус;
Иначе
Подтип = ПеревестиСтроку(ПодтипРус);
КонецЕсли;
ИмяТипа = ПервоеСлово + Подтип + ИменаМД;
КонецЕсли;
Возврат ИмяТипа;
КонецФункции
Функция ИмяТипаИзПолногоИмениТаблицыБДЛкс(ИмяТаблицыБД, Знач ПодтипРус = "Ссылка") Экспорт
Если Найти(ИмяТаблицыБД, "." + ПеревестиСтроку("Точки")) > 0 Тогда
ОписаниеТаблицыБД = ОписаниеТаблицыБДЛкс(ИмяТаблицыБД);
КонецЕсли;
Если Истина
И ОписаниеТаблицыБД <> Неопределено
И ОписаниеТаблицыБД.Тип = "Точки"
Тогда
Если ПодтипРус = "Ссылка" Тогда
Фрагменты = СтрРазделитьЛкс(ИмяТаблицыБД);
Результат = ПеревестиСтроку("ТочкаМаршрутаБизнесПроцессаСсылка") + "." + Фрагменты[1];
КонецЕсли;
Иначе
ПолноеИмяМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицыБД);
Если ПолноеИмяМД <> Неопределено Тогда
Результат = ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяМД, ПодтипРус);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяТипаЛкс(Знач Тип) Экспорт
Если ТипЗнч(Тип) <> Тип("Тип") Тогда
Тип = ТипЗнч(Тип);
КонецЕсли;
Результат = ПредставлениеТипаЛкс(Тип,, Истина);
Возврат Результат;
КонецФункции
// Возвращает имя типа, который будет использован в xml файле для указанного объекта метаданных
// Используется при поиске и замене ссылок при загрузке, при модификации схемы current-config при записи
//
// Параметры:
// Значение - Объект метаданных или Ссылка
//
// Возвращаемое значение:
// Строка - Строка вида CatalogRef.Валюты, описывающая объект метаданных
//
Функция XMLТипСсылкиЛкс(Знач ОбъектМДИлиСсылка) Экспорт
Если ТипЗнч(ОбъектМДИлиСсылка) = Тип("ОбъектМетаданных") Тогда
Ссылка = Новый (ИмяТипаИзПолногоИмениМДЛкс(ОбъектМДИлиСсылка));
Иначе
Ссылка = ОбъектМДИлиСсылка;
КонецЕсли;
Результат = СериализаторXDTO.XMLТипЗнч(Ссылка).ИмяТипа;
Возврат Результат;
КонецФункции
Функция ИмяТипаДанныхТаблицыРегистраЛкс(ПолноеИмяТаблицыБД, Знач ПодтипРус = "НаборЗаписей") Экспорт
Подтип = ПеревестиСтроку(ПодтипРус);
Фрагменты = СтрРазделитьЛкс(ПолноеИмяТаблицыБД);
Если Фрагменты.Количество() > 2 Тогда
Если Фрагменты[0] = ПеревестиСтроку("РегистрРасчета") Тогда
ИмяТипа = ПеревестиСтроку("Перерасчет") + Подтип + "." + Фрагменты[1] + "." + Фрагменты[2];
ИначеЕсли Фрагменты[0] = ПеревестиСтроку("РегистрБухгалтерии") Тогда
ИмяТипа = ПеревестиСтроку("РегистрБухгалтерии") + Подтип + "." + Фрагменты[1];
ИначеЕсли ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(Фрагменты[0]) Тогда
ИмяТипа = ПеревестиСтроку("ВнешнийИсточникДанныхТаблица") + Подтип + "." + Фрагменты[1] + "." + Фрагменты[3];
КонецЕсли;
Иначе
ИмяТипа = СтрЗаменить(ПеревестиСтроку(Фрагменты[0]) + "." + Фрагменты[1], ".", Подтип + ".");
КонецЕсли;
Возврат ИмяТипа;
КонецФункции
Функция ЗаменитьИдентификаторОбъектаЛкс(Объект, ИдентификаторСсылки = Неопределено) Экспорт
Если ИдентификаторСсылки = Неопределено Тогда
ИдентификаторСсылки = Новый УникальныйИдентификатор;
КонецЕсли;
Если Не ирКэш.ЛиПортативныйРежимЛкс() И ТипЗнч(Объект) = Тип("ОбработкаОбъект.ирИмитаторСсылочныйОбъект") Тогда
#Если Сервер И Не Сервер Тогда
Объект = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
Возврат Объект.ЗаменитьИдентификаторОбъекта(ИдентификаторСсылки);
КонецЕсли;
// Антибаг платформы 8.2.14 http://partners.v8.1c.ru/forum/thread.jsp?id=967697#967697
//Объект = СериализаторXDTO.ЗаписатьXDTO(Объект);
//Объект.Ref = ИдентификаторСсылки;
//Объект.IsFolder = ЭтоГруппаДляНового;
//Объект = СериализаторXDTO.ПрочитатьXDTO(Объект);
//
// Этот метод опасный, т.к. может привести к нежелательным изменениям в объекте!
СтрокаХмл = ОбъектВСтрокуXMLЛкс(Объект, Ложь);
Попытка
ТекущийИДСсылки = XMLСтрока(Объект.Ссылка);
Исключение
// Внешний источник данных
ТекущийИДСсылки = "";
КонецПопытки;
Если ЗначениеЗаполнено(ТекущийИДСсылки) Тогда
ИмяЭлементаСсылки = "Ref";
СтрокаХмл = СтрЗаменитьЛкс(СтрокаХмл, "<" + ИмяЭлементаСсылки + ">" + ТекущийИДСсылки + "" + ИмяЭлементаСсылки + ">",
"<" + ИмяЭлементаСсылки + ">" + XMLСтрока(ИдентификаторСсылки) + "" + ИмяЭлементаСсылки + ">");
//ИмяЭлементаЭтоГруппа = "IsFolder";
//Если Найти(СтрокаХмл, "<" + ИмяЭлементаЭтоГруппа + ">") > 0 Тогда
// СтрокаХмл = СтрЗаменить(СтрокаХмл, "<" + ИмяЭлементаЭтоГруппа + ">" + XMLСтрока(Объект.IsFolder) + "" + ИмяЭлементаЭтоГруппа + ">",
// "<" + ИмяЭлементаЭтоГруппа + ">" + XMLСтрока(ЭтоГруппаДляНового) + "" + ИмяЭлементаЭтоГруппа + ">");
//КонецЕсли;
КонецЕсли;
Объект = ОбъектИзСтрокиXMLЛкс(СтрокаХмл,, Ложь);
Возврат Объект;
КонецФункции
Функция НедоступноИзменениеПоляСсылочногоОбъектаЛкс(Знач ИмяПоля) Экспорт
НИмяПоля = Нрег(ИмяПоля);
НедоступноИзменениеПоля = Ложь
Или НИмяПоля = Нрег("Ссылка")
Или НИмяПоля = Нрег("ВерсияДанных")
Или НИмяПоля = Нрег("ЭтоГруппа")
//Или НИмяПоля = Нрег("ЭтотУзел") // ошибочно помечен как нередактируемый в синтакс-помощнике
Или НИмяПоля = Нрег("Предопределенный");
Возврат НедоступноИзменениеПоля;
КонецФункции
// Функция - Параметры доступа к объекту МДЛкс
//
// Параметры:
// Право - -
// МетаОбъект - -
// РольИлиПользователь - -
// выхПраваНеПрименимы - -
// выхИмяПоля - Строка - Неопределено - сначала подбор полей Ссылка, Период; "" - сразу получаем все поля и берем первое
//
// Возвращаемое значение:
// -
//
Функция ПараметрыДоступаКОбъектуМДЛкс(Знач Право, Знач МетаОбъект, Знач РольИлиПользователь = Неопределено, выхПраваНеПрименимы = Ложь, выхИмяПоля = Неопределено) Экспорт
Если выхИмяПоля = Неопределено Тогда
ИменаПолей = Новый Массив;
ИменаПолей.Добавить("Ссылка");
ИменаПолей.Добавить("Период");
Для Каждого ИмяПоля Из ИменаПолей Цикл
Попытка
ПараметрыДоступа = ПараметрыДоступа(Право, МетаОбъект, ИмяПоля, РольИлиПользователь);
Прервать;
Исключение
КонецПопытки;
КонецЦикла;
ИначеЕсли выхИмяПоля <> "" Тогда
Попытка
ПараметрыДоступа = ПараметрыДоступа(Право, МетаОбъект, выхИмяПоля, РольИлиПользователь);
Исключение
КонецПопытки;
КонецЕсли;
Если ПараметрыДоступа = Неопределено Тогда
Попытка
ПоляТаблицы = ПоляТаблицыМДЛкс(МетаОбъект, Истина,,, Ложь);
ИмяПоля = ПоляТаблицы[0].Имя;
ПараметрыДоступа = ПараметрыДоступа(Право, МетаОбъект, ИмяПоля, РольИлиПользователь);
выхИмяПоля = ИмяПоля;
Исключение
// Например это Обработка, Перечисление
ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
ПараметрыДоступа = Неопределено;
// Баг 8.3.13 Эта функция возвращает Истина даже для некорректных комбинаций параметров
//Попытка
// ПараметрыДоступа = ПравоДоступа(КлючИЗначение.Ключ, МетаОбъект, Роль);
//Исключение
выхПраваНеПрименимы = Истина;
//КонецПопытки;
КонецПопытки;
КонецЕсли;
Возврат ПараметрыДоступа;
КонецФункции
Функция ЕстьОграниченияДоступаКСтрокамТаблицыНаЧтениеЛкс(Знач ОбъектМД) Экспорт
ЕстьПраваДоступаКСтрокам = Ложь;
ПараметрыДоступа = ПараметрыДоступаКОбъектуМДЛкс("Чтение", ОбъектМД);
Если ПараметрыДоступа = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ПараметрыДоступа = ПараметрыДоступа();
#КонецЕсли
Если ПараметрыДоступа.Доступность Тогда
ЕстьПраваДоступаКСтрокам = ПараметрыДоступа.ОграничениеУсловием;
КонецЕсли;
Возврат ЕстьПраваДоступаКСтрокам;
КонецФункции
Функция РежимОбъектыНаСервереПоУмолчаниюЛкс(РазрешитьВПортативномВарианте = Истина) Экспорт
Результат = Истина
И (Ложь
Или Не ирКэш.ЛиПортативныйРежимЛкс()
Или РазрешитьВПортативномВарианте И ирПортативный.ЛиСерверныйМодульДоступенЛкс())
И Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение;
Возврат Результат;
КонецФункции
// Функция - Скопировать колонки коллекции
//
// Параметры:
// КоллекцияИсточник - ТаблицаЗначений, ДеревоЗначений -
// КоллекцияПриемник - ТаблицаЗначений, ДеревоЗначений -
// БезТипов - -
// *ИменаКолонок - Строка, "" - белый список имен колонок через запятую
//
// Возвращаемое значение:
// ТаблицаЗначений, ДеревоЗначений -
//
Функция СкопироватьКолонкиКоллекцииЛкс(КоллекцияИсточник, КоллекцияПриемник = Неопределено, БезТипов = Ложь, Знач ИменаКолонок = "") Экспорт
#Если Сервер И Не Сервер Тогда
КоллекцияИсточник = Новый ТаблицаЗначений;
#КонецЕсли
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый (ТипЗнч(КоллекцияИсточник));
КонецЕсли;
#Если Сервер И Не Сервер Тогда
КоллекцияПриемник = Новый ТаблицаЗначений;
#КонецЕсли
Если ЗначениеЗаполнено(ИменаКолонок) Тогда
СтруктураКолонок = Новый Структура(ИменаКолонок);
КонецЕсли;
Для Каждого Колонка Из КоллекцияИсточник.Колонки Цикл
Если Ложь
Или (Истина
И СтруктураКолонок <> Неопределено
И Не СтруктураКолонок.Свойство(Колонка.Имя))
Или КоллекцияПриемник.Колонки.Найти(Колонка.Имя) <> Неопределено
Тогда
Продолжить;
КонецЕсли;
Если БезТипов Тогда
НовыйТип = Новый ОписаниеТипов;
Иначе
НовыйТип = Колонка.ТипЗначения;
КонецЕсли;
КоллекцияПриемник.Колонки.Добавить(Колонка.Имя, НовыйТип, Колонка.Заголовок, Колонка.Ширина);
КонецЦикла;
Возврат КоллекцияПриемник;
КонецФункции
//
// Параметры:
// УзелИлиМассив - -
// КлючОбъекта - -
// НовоеЗначение - -
// РегистрироватьДвиженияВместеСДокументом - -
// ДвиженияВместеСПоследовательностями - -
// ПропускатьДвиженияВнеПланаОбмена - Булево - при РегистрироватьДвиженияВместеСДокументом = Истина позволяет управлять поведением для тех движений, которые не входят в план обмена,
// Если Истина, то такие движения пропускаются, иначе вызывается исключение
// ПроверятьНаличиеТаблицыИзмененийДляКаждогоУзла - -
//
// Возвращаемое значение:
// -
//
Функция ПланыОбменаИзменитьРегистрациюЛкс(УзелИлиМассив, КлючОбъекта, НовоеЗначение = Истина, РегистрироватьДвиженияВместеСДокументом = Ложь, ДвиженияВместеСПоследовательностями = Ложь,
ПропускатьДвиженияВнеПланаОбмена = Истина, ПроверятьНаличиеТаблицыИзмененийДляКаждогоУзла = Ложь) Экспорт
Если КлючОбъекта = Неопределено Тогда
ВызватьИсключение "Изменение регистрации всех данных недопустимо";
КонецЕсли;
Если ТипЗнч(КлючОбъекта) = Тип("ОбъектМетаданных") Тогда
ОбъектМД = КлючОбъекта;
Иначе
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъектаБДЛкс(КлючОбъекта));
КонецЕсли;
Если РегистрироватьДвиженияВместеСДокументом Тогда
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
ЭтоДокумент = ЛиКорневойТипДокументаЛкс(ПервыйФрагментЛкс(ПолноеИмяМД));
КонецЕсли;
Если РегистрироватьДвиженияВместеСДокументом И ЭтоДокумент И ТипЗнч(КлючОбъекта) = Тип("ОбъектМетаданных") Тогда
Запрос = Новый Запрос("ВЫБРАТЬ Т.Ссылка ИЗ " + ПолноеИмяМД + " КАК Т");
МассивОбъектов = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(0);
Индикатор = ПолучитьИндикаторПроцессаЛкс(МассивОбъектов.Количество(), "Изменение регистрации");
Иначе
МассивОбъектов = Новый Массив;
МассивОбъектов.Добавить(КлючОбъекта);
КонецЕсли;
Если ТипЗнч(УзелИлиМассив) = Тип("Массив") Тогда
Если УзелИлиМассив.Количество() > 0 Тогда
ОдинУзелОбмена = УзелИлиМассив[0];
Иначе
ОдинУзелОбмена = Неопределено;
КонецЕсли;
МассивУзлов = УзелИлиМассив;
Иначе
ОдинУзелОбмена = УзелИлиМассив;
МассивУзлов = Новый Массив;
МассивУзлов.Добавить(УзелИлиМассив);
КонецЕсли;
Если Не ЗначениеЗаполнено(ОдинУзелОбмена) Тогда
СообщитьЛкс("Не указан узел для регистрации изменений");
Возврат Ложь;
КонецЕсли;
//! ОдинУзелОбмена = 0 // ПланОбменаСсылка
Если ПроверятьНаличиеТаблицыИзмененийДляКаждогоУзла Тогда
УзлыДляРегистрации = ПолучитьРазрешенныеУзлыДляОбъектаМДЛкс(ОбъектМД, МассивУзлов);
Если УзлыДляРегистрации.Количество() = 0 Тогда
Возврат Истина;
КонецЕсли;
Иначе
УзлыДляРегистрации = МассивУзлов;
КонецЕсли;
Успех = Истина;
НомерВерсииПлатформы = ирКэш.НомерВерсииПлатформыЛкс();
СоставПланаОбмена = ОдинУзелОбмена.Метаданные().Состав;
Для Каждого Объект Из МассивОбъектов Цикл
Если Индикатор <> Неопределено Тогда
ОбработатьИндикаторЛкс(Индикатор);
КонецЕсли;
Если ТипЗнч(Объект) = Тип("Структура") Тогда
Объект = Объект.Методы;
КонецЕсли;
Если Истина
И ТипЗнч(Объект) = Тип("ОбъектМетаданных")
И Не ПравоДоступа("Изменение", Объект)
Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Нет доступа к таблице %1",, Объект.ПолноеИмя()), СтатусСообщения.Внимание);
Продолжить;
КонецЕсли;
Если Ложь
Или НовоеЗначение
Или СоставПланаОбмена.Содержит(ОбъектМД)
Тогда
ИзменитьРегистрациюОбъектаДляУзлаЛкс(УзлыДляРегистрации, Объект, НовоеЗначение, ОдинУзелОбмена, НомерВерсииПлатформы);
КонецЕсли;
Если РегистрироватьДвиженияВместеСДокументом И ЭтоДокумент Тогда
//! Объект = 0 // ДокументОбъект
ОбъектыМД = МетаданныеНаборовЗаписейПоРегистраторуЛкс(ОбъектМД, ДвиженияВместеСПоследовательностями, Истина);
Для Каждого МетаРегистр из ОбъектыМД Цикл
Если Не СоставПланаОбмена.Содержит(МетаРегистр) Тогда
Если Не НовоеЗначение Или ПропускатьДвиженияВнеПланаОбмена Тогда
Продолжить;
Иначе
ВызватьИсключение "Движение документа по регистру " + МетаРегистр.ПолноеИмя() + " не может быть зарегистрировано в плане обмена " + ОдинУзелОбмена.Метаданные().Имя;
КонецЕсли;
КонецЕсли;
ИмяТаблицыБДРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(МетаРегистр.ПолноеИмя());
ИмяПоляОтбора = ИмяПоляОтбораПодчиненногоНабораЗаписейЛкс(ИмяТаблицыБДРегистра);
СтруктураНабораЗаписей = ОбъектБДПоКлючуЛкс(ИмяТаблицыБДРегистра, Новый Структура(ИмяПоляОтбора, Объект.Ссылка),, Ложь);
ИзменитьРегистрациюОбъектаДляУзлаЛкс(УзлыДляРегистрации, СтруктураНабораЗаписей.Методы, НовоеЗначение, ОдинУзелОбмена, НомерВерсииПлатформы);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Если Индикатор <> Неопределено Тогда
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
Возврат Успех;
КонецФункции
Процедура ИзменитьРегистрациюОбъектаДляУзлаЛкс(Знач УзлыДляРегистрации, Знач Объект, Знач НовоеЗначение, Знач ОдинУзелОбменаДляПроверки, Знач НомерВерсииПлатформы = "") Экспорт
НесобственныеУзлы = Новый Массив;
Для Каждого Узел Из УзлыДляРегистрации Цикл
Если ПланыОбмена[Метаданные.НайтиПоТипу(ТипЗнч(Узел)).Имя].ЭтотУзел() = Узел Тогда
// Изменение регистрации для собственных узлов выбросит исключение
Продолжить;
КонецЕсли;
НесобственныеУзлы.Добавить(Узел);
КонецЦикла;
ТипОбъекта = ТипЗнч(Объект);
ЭтоИмитатор = ЛиТипИмитатораОбъектаЛкс(ТипОбъекта);
Если ЭтоИмитатор Тогда
ОбъектXML = Объект.Снимок();
ирСервер.ИзменитьРегистрациюОбъектаДляУзлаЛкс(ОбъектXML, ТипОбъекта, НесобственныеУзлы, НовоеЗначение, ОдинУзелОбменаДляПроверки, НомерВерсииПлатформы);
Иначе
Если НовоеЗначение Тогда
ПланыОбмена.ЗарегистрироватьИзменения(НесобственныеУзлы, Объект);
Если Не ЗначениеЗаполнено(НомерВерсииПлатформы) Тогда
НомерВерсииПлатформы = ирКэш.НомерВерсииПлатформыЛкс();
КонецЕсли;
// Антибаг платформы 8.2.17-8.3.4
Если Истина
И НомерВерсииПлатформы < 803005
И ТипЗнч(Объект) <> Тип("ОбъектМетаданных")
И Не ПланыОбмена.ИзменениеЗарегистрировано(ОдинУзелОбменаДляПроверки, Объект)
Тогда
Успех = Ложь;
СообщитьЛкс(СтрШаблонИменЛкс("Не удалось зарегистрировать изменение %1 из-за ошибки платформы, исправленной в 8.3.5",, Объект));
КонецЕсли;
Иначе
ПланыОбмена.УдалитьРегистрациюИзменений(НесобственныеУзлы, Объект);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ПолучитьРазрешенныеУзлыДляОбъектаМДЛкс(ОбъектМД, МассивУзлов, ТолькоУзлыСАвторегистрацией = Ложь) Экспорт
УзлыДляРегистрации = Новый Массив;
Для Каждого ПроверяемыйУзел Из МассивУзлов Цикл
ЭлементСостава = ПроверяемыйУзел.Метаданные().Состав.Найти(ОбъектМД);
Если Истина
И ЭлементСостава <> Неопределено
И (Ложь
Или Не ТолькоУзлыСАвторегистрацией
Или ЭлементСостава.АвтоРегистрация = АвтоРегистрацияИзменений.Разрешить)
Тогда
УзлыДляРегистрации.Добавить(ПроверяемыйУзел);
КонецЕсли;
КонецЦикла;
Возврат УзлыДляРегистрации;
КонецФункции
// Копирует регистрацию изменений с узла источника на узлы приемники. Опционально каждый тип данных отдельно равномерно распределяется по узлам приемникам.
// Параметры:
// НомерСообщения - Неопределено - брать номер отправленного с узла, Null - не фильтровать но номеру сообщения, иначе выбираются все изменения с номером равным или меньшим заданного
// Возвращаемое значение: Массив - количество изменений зарегистрированных по каждому узлу
Функция СкопироватьРаспределитьРегистрациюИзмененийПоУзламЛкс(УзелИсточник, УзлыПриемники, Распределять = Ложь, НомерСообщения = Null, МассивМетаданных = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
УзелИсточник = ПланыОбмена.Полный.ПустаяСсылка();
УзлыПриемники = Новый Массив;
#КонецЕсли
#Если Клиент Тогда
СостояниеЛкс("Выбираем все изменения для узла…");
#КонецЕсли
Если НомерСообщения = Неопределено Тогда
НомерСообщения = УзелИсточник.НомерОтправленного;
КонецЕсли;
Результат = Новый Массив;
Для Счетчик = 1 По УзлыПриемники.Количество() Цикл
Если Распределять И ТипЗнч(УзлыПриемники[Счетчик - 1]) <> ТипЗнч(УзелИсточник) Тогда
ВызватьИсключение "Нельзя распределять на узлы другого плана обмена";
КонецЕсли;
Результат.Добавить(0);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Узел", УзелИсточник);
Запрос.УстановитьПараметр("НомерСообщения", НомерСообщения);
МетаПланОбмена = УзелИсточник.Метаданные();
ТекстЗапроса = "";
ТипыДанныхЗапросов = Новый Массив;
Для Каждого ЭлементСостава Из МетаПланОбмена.Состав Цикл
МетаОбъект = ЭлементСостава.Метаданные;
Если Ложь
Или МетаОбъект = Неопределено
Или (Истина
И МассивМетаданных <> Неопределено
И МассивМетаданных.Найти(МетаОбъект) = Неопределено)
Тогда
Продолжить;
КонецЕсли;
Если ТекстЗапроса <> "" Тогда
ТекстЗапроса = ТекстЗапроса + ";" + Символы.ПС;
КонецЕсли;
ПолноеИмяМД = МетаОбъект.ПолноеИмя();
ТипыДанныхЗапросов.Добавить(ПолноеИмяМД);
ИмяТаблицыДляПоискаЗарегистрированных = СтрЗаменить(ПолноеИмяМД, ".Перерасчет.", ".") + ".Изменения";
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ *
|ИЗ
| " + ИмяТаблицыДляПоискаЗарегистрированных + " КАК РегистрацияИзменений
|ГДЕ
| РегистрацияИзменений.Узел = &Узел";
Если НомерСообщения <> Null Тогда
ТекстЗапроса = ТекстЗапроса = " И НомерСообщения <= &НомерСообщения";
КонецЕсли;
КонецЦикла;
Если ТекстЗапроса <> "" Тогда
Запрос.Текст = ТекстЗапроса;
РезультатПакета = Запрос.ВыполнитьПакет();
ИндикаторСостава = ПолучитьИндикаторПроцессаЛкс(РезультатПакета.Количество(), "Распределение изменений");
Для ИндексЗапроса = 0 По РезультатПакета.ВГраница() Цикл
ОбработатьИндикаторЛкс(ИндикаторСостава);
РезультатЗапроса = РезультатПакета[ИндексЗапроса];
#Если Сервер И Не Сервер Тогда
РезультатЗапроса1 = Новый Запрос;
РезультатЗапроса = РезультатЗапроса1.Выполнить();
#КонецЕсли
ПолноеИмяМД = ТипыДанныхЗапросов[ИндексЗапроса];
//Если Ложь
// Или РезультатЗапроса.Колонки.Найти("НомерСообщения1") <> Неопределено
// Или РезультатЗапроса.Колонки.Найти("Узел1") <> Неопределено
//Тогда
// ВызватьИсключение "В таблице " + ПолноеИмяМД + " в основной отбор включены измерения с запрещенными именами (НомерСообщения, Узел)";
//КонецЕсли;
ТаблицаКорректна = Истина;
Для Каждого КолонкаРезультата Из РезультатЗапроса.Колонки Цикл
Если Не ЭтоКорректноеПолеТаблицыИзмененийЛкс(ПолноеИмяМД, КолонкаРезультата.Имя) Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Изменения таблицы %1 не были скопированы, т.к. она имеет некорректное поле %2, порожденное конфликтом имен полей", 1, ПолноеИмяМД, 2, КолонкаРезультата.Имя));
ТаблицаКорректна = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ТаблицаКорректна Тогда
Продолжить;
КонецЕсли;
Выборка = РезультатЗапроса.Выбрать();
ИндексУзла = 0;
КоличествоЭлементов = Выборка.Количество();
Если КоличествоЭлементов > 0 Тогда
Если Распределять Тогда
УзлыРегистрации = УзлыПриемники;
Иначе
УзлыРегистрации = ПолучитьРазрешенныеУзлыДляОбъектаМДЛкс(ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД), УзлыПриемники);
Если УзлыРегистрации.Количество() < УзлыПриемники.Количество() Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Изменения таблицы %1 были скопированы не на все узлы, т.к. некоторые планы обмена приемников не содержат ее.",, ПолноеИмяМД));
КонецЕсли;
КонецЕсли;
Если УзлыРегистрации.Количество() > 0 Тогда
ИндикаторТаблицы = ПолучитьИндикаторПроцессаЛкс(КоличествоЭлементов, ПолноеИмяМД);
ТекущаяГруппаТипаМетаданных = "";
МакетныйОбъект = ПолучитьМакетныйОбъектДанныхТаблицыБДЛкс(ПолноеИмяМД, ТекущаяГруппаТипаМетаданных); //, КлючевыеПоля
Пока Выборка.Следующий() Цикл
ОбработатьИндикаторЛкс(ИндикаторТаблицы);
Объект = ОбъектДанныхИзСтрокиРезультатаЗапросаЛкс(Выборка, МакетныйОбъект, ТекущаяГруппаТипаМетаданных, Ложь, "НомерСообщения, Узел");
// Регистрация
Если Распределять Тогда
УзелПриемник = УзлыРегистрации[ИндексУзла];
ПланыОбменаИзменитьРегистрациюЛкс(УзелПриемник, Объект);
Результат[ИндексУзла] = Результат[ИндексУзла] + 1;
ИндексУзла = ИндексУзла + 1;
Если ИндексУзла = УзлыРегистрации.Количество() Тогда
ИндексУзла = 0;
КонецЕсли;
Иначе
ПланыОбменаИзменитьРегистрациюЛкс(УзлыРегистрации, Объект);
Результат[0] = Результат[0] + 1;
КонецЕсли;
КонецЦикла;
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
КонецЕсли;
КонецЦикла;
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЭтоКорректноеПолеТаблицыИзмененийЛкс(ПолноеИмяМД, ИмяПоля) Экспорт
Если Ложь
Или СтрокиРавныЛкс(ИмяПоля, "Узел1")
Или СтрокиРавныЛкс(ИмяПоля, "НомерСообщения1")
Тогда
//ПолноеИмяРегистра = ТекстМеждуМаркерамиЛкс(ПолноеИмяТаблицыБД,, ".Изменения");
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяМД);
Если ЛиКорневойТипРегистраБДЛкс(КорневойТип) Тогда
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
Если ОбъектМД <> Неопределено Тогда
Если ОбъектМД.Измерения.Найти("" + ИмяПоля) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
// ИгнорироватьКолонки - Строка - имена колонок через запятую, которые не будут учитываться
Функция ОбъектДанныхИзСтрокиРезультатаЗапросаЛкс(Знач ДанныеСтроки, Знач МакетныйОбъект, Знач ТекущаяГруппаТипаМетаданных, СчитатьДанныеОбъекта = Истина,
Знач ИгнорироватьКолонки = "", Заблокировать = Ложь, ОбъектыНаСервере = Неопределено) Экспорт
Если ТекущаяГруппаТипаМетаданных = "Ссылочный" Тогда
ИмяСсылка = ПеревестиСтроку("Ссылка");
СтруктураОбъекта = ДанныеСтроки[ИмяСсылка];
Если Заблокировать Тогда
ЗаблокироватьСсылкуВТранзакцииЛкс(СтруктураОбъекта);
КонецЕсли;
Если СчитатьДанныеОбъекта Тогда
СтруктураОбъекта = ОбъектБДПоКлючуЛкс(СтруктураОбъекта.Метаданные().ПолноеИмя(), СтруктураОбъекта,,, ОбъектыНаСервере);
КонецЕсли;
ИначеЕсли ТекущаяГруппаТипаМетаданных = "Регистр" Тогда
Если ЛиКлючЗаписиРегистраЛкс(ДанныеСтроки) Тогда
ДанныеСтроки = ДанныеСтрокиРегистраИзКлючаЗаписиЛкс(ДанныеСтроки);
КонецЕсли;
СтруктураОбъекта = МакетныйОбъект;
//! СтруктураОбъекта.Методы = 0 // ОбработкаОбъект.ирИмитаторНаборЗаписей
Если ЗначениеЗаполнено(ИгнорироватьКолонки) Тогда
ИгнорироватьКолонки = Нрег(ИгнорироватьКолонки) + ",";
КонецЕсли;
Для Каждого ЭлементОтбора Из СтруктураОбъекта.Методы.Отбор Цикл
Если Найти(ИгнорироватьКолонки, НРег(ЭлементОтбора.Имя) + ",") > 0 Тогда
Продолжить;
КонецЕсли;
Попытка
ЗначениеПоля = ДанныеСтроки[ЭлементОтбора.Имя];
Исключение
// Независимый регистр сведений, у измерения не включен ОсновнойОтбор
Продолжить;
КонецПопытки;
ЭлементОтбора.Значение = ЗначениеПоля;
ЭлементОтбора.Использование = Истина;
КонецЦикла;
Если Заблокировать Тогда
ЗаблокироватьНаборЗаписейПоОтборуЛкс(СтруктураОбъекта);
КонецЕсли;
Если СчитатьДанныеОбъекта Тогда
СтруктураОбъекта.Методы.Прочитать();
КонецЕсли;
ИначеЕсли ТекущаяГруппаТипаМетаданных = "Константа" Тогда
СтруктураОбъекта = МакетныйОбъект;
Если Заблокировать Тогда
ЗаблокироватьКонстантуЛкс(СтруктураОбъекта);
КонецЕсли;
Если СчитатьДанныеОбъекта Тогда
СтруктураОбъекта.Методы.Прочитать();
КонецЕсли;
КонецЕсли;
Возврат СтруктураОбъекта;
КонецФункции
// Добавляет глобальные переменные и методы в контекст поля текстового документа с контекстной подсказкой.
//
// Параметры
// ПолеТекстаПрограммы - ОбработкаОбъект.ПолеТекстаПрограммы.
//
Процедура ИнициироватьГлобальныйКонтекстПодсказкиЛкс(ПолеТекстаПрограммы) Экспорт
#Если Сервер И Не Сервер Тогда
ПолеТекстаПрограммы = Обработки.ирКлсПолеТекстаПрограммы.Создать();
#КонецЕсли
Если ПолеТекстаПрограммы.ЯзыкПрограммы = 1 Тогда
Возврат;
КонецЕсли;
ПолеТекстаПрограммы.ОчиститьТаблицуСловЛокальногоКонтекста();
МассивГлобальныхПеременных = Новый Массив;
МассивГлобальныхПеременных.Добавить("ирПлатформа");
Для Каждого ИмяГлобальнойПеременной Из МассивГлобальныхПеременных Цикл
Попытка
ГлобальнаяПеременная = ВычислитьВыражение(ИмяГлобальнойПеременной);
Исключение
// ирПлатформа может отсутствовать
Продолжить;
КонецПопытки;
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЗнч(ГлобальнаяПеременная));
ПолеТекстаПрограммы.ДобавитьСловоЛокальногоКонтекста(ИмяГлобальнойПеременной, "Свойство", Новый ОписаниеТипов(МассивТипов), ГлобальнаяПеременная);
КонецЦикла;
// Методы
//ПолеТекстаПрограммы.ДобавитьПравилоВычисленияФункции("ирКПА", "ПравилоВычисленияТипаЗначенияКПА");
//СтруктураГлобальныхФункций = Новый Структура;
//СтруктураГлобальныхФункций.Вставить("Исследовать", Тип("Число"));
//СтруктураГлобальныхФункций.Вставить("Отладить", Тип("Число"));
//СтруктураГлобальныхФункций.Вставить("Оперировать", Тип("Число"));
//СтруктураГлобальныхФункций.Вставить("Наблюдать");
//Для Каждого ЭлементГлобальнойФункции Из СтруктураГлобальныхФункций Цикл
// Если ТипЗнч(ЭлементГлобальнойФункции.Значение) = Тип("Тип") Тогда
// МассивТипов = Новый Массив;
// МассивТипов.Добавить(ЭлементГлобальнойФункции.Значение);
// ОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
// ИначеЕсли ТипЗнч(ЭлементГлобальнойФункции.Значение) = Тип("ОписаниеТипов") Тогда
// ОписаниеТипов = ЭлементГлобальнойФункции.Значение;
// КонецЕсли;
// ПолеТекстаПрограммы.ДобавитьСловоЛокальногоКонтекста(ЭлементГлобальнойФункции.Ключ, "Метод", ОписаниеТипов);
//КонецЦикла;
КонецПроцедуры
// Параметры - ТаблицаЗначений с колонкой Имя
Функция ПроверитьТаблицуПараметровЛкс(Параметры, Заголовок = "") Экспорт
Результат = Истина;
Если Параметры.Количество() = 0 Тогда
Возврат Результат;
КонецЕсли;
Для Каждого СтрокаПараметра Из Параметры Цикл
Если Не ЛиИмяПеременнойЛкс(СтрокаПараметра.Имя) Тогда
Результат = Ложь;
СообщитьЛкс(Заголовок + СтрШаблонИменЛкс("Имя параметра %1 некорректно",, """" + СтрокаПараметра.Имя + """"), СтатусСообщения.Внимание);
КонецЕсли;
КонецЦикла;
НеуникальныеИмена = НеуникальныеЗначенияКолонкиТаблицыЛкс(Параметры, "Имя");
Для Каждого НеуникальноеИмя Из НеуникальныеИмена Цикл
СообщитьЛкс(Заголовок + СтрШаблонИменЛкс("Имя параметра %1 встречается более одного раза",, """" + НеуникальноеИмя + """"), СтатусСообщения.Внимание);
Результат = Ложь;
КонецЦикла;
Возврат Результат;
КонецФункции
// Возможно нужно объединить с ПолучитьМетаданныеЛкс
Функция ПолучитьМетаданныеПоПолномуИмениЛкс(ПолноеИмяМД) Экспорт
Объект = СоздатьОбъектПоИмениМетаданныхЛкс(ПолноеИмяМД);
Результат = Объект.Метаданные();
Возврат Результат;
КонецФункции
// Функция - Таблицы внешнего источника данных лкс
//
// Параметры:
// ОбъектМД - -
// ЛиОбъектные - Булево, *Ложь - Если Ложь то вернет только объектные таблицы, иначе - только необъектные
//
// Возвращаемое значение:
// -
//
Функция ТаблицыВнешнегоИсточникаДанныхЛкс(РодительскийОбъектМД, ЛиОбъектные = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
РодительскийОбъектМД = Метаданные.ВнешниеИсточникиДанных.ВнешнийИсточникДанных1;
#КонецЕсли
Результат = Новый Массив;
Для Каждого ОбъектМД Из РодительскийОбъектМД.Таблицы Цикл
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.ВнешниеИсточникиДанных.ВнешнийИсточникДанных1.Таблицы.Таблица1;
#КонецЕсли
Если Ложь
Или (ЛиОбъектные И ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.НеобъектныеДанные)
Или (Не ЛиОбъектные И ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные)
Тогда
Продолжить;
КонецЕсли;
Результат.Добавить(ОбъектМД);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция МножественноеИмяМДЛкс(Единственное) Экспорт
СтрокаТаблицы = ОписаниеТипаМетаданныхЛкс(Единственное);
Если СтрокаТаблицы <> Неопределено Тогда
Результат = СтрокаТаблицы.Множественное;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОписаниеТипаМетаданныхЛкс(Знач Единственное) Экспорт
ТаблицаТиповМетаОбъектов = ирКэш.ТипыМетаОбъектов();
СтрокаТаблицы = ТаблицаТиповМетаОбъектов.Найти(НРег(Единственное), "НЕдинственное");
Возврат СтрокаТаблицы;
КонецФункции
Функция ЕдинственноеИмяМДЛкс(Множественное) Экспорт
ТаблицаТиповМетаОбъектов = ирКэш.ТипыМетаОбъектов();
СтрокаТаблицы = ТаблицаТиповМетаОбъектов.Найти(НРег(Множественное), "НМножественное");
Если СтрокаТаблицы <> Неопределено Тогда
Результат = СтрокаТаблицы.Единственное;
КонецЕсли;
Возврат Результат;
КонецФункции
// Параметры:
// ПолноеИмя - ? -
// ТекстМодуля - ? -
// ТипВыхода - Строка - Служебный параметр для перехода после вызова метода
Функция ПолноеИмяМДЕдинственноеВМножественноеЛкс(ПолноеИмя) Экспорт
Фрагменты = СтрРазделитьЛкс(ПолноеИмя);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
Для Счетчик = 1 По Фрагменты.Количество() / 2 Цикл
Индекс = (Счетчик - 1) * 2;
МножественноеИмяМД = МножественноеИмяМДЛкс(Фрагменты[Индекс]);
Если МножественноеИмяМД = Неопределено Тогда
Для ИндексОстатка = Индекс По Фрагменты.ВГраница() Цикл
Фрагменты.Удалить(Индекс);
КонецЦикла;
Прервать;
КонецЕсли;
Фрагменты[Индекс] = МножественноеИмяМД;
КонецЦикла;
ТекстМодуля = СтрСоединитьЛкс(Фрагменты, ".");
Возврат ТекстМодуля;
КонецФункции
// Получает тип из описания типов, типа или значения.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Тип - найденный тип.
//
Функция ПолучитьТипОбъектаЛкс(пОбъект)
ТипОбъекта = Тип("Неопределено");
ТипПараметра = ТипЗнч(пОбъект);
Если ТипПараметра = Тип("ОписаниеТипов") Тогда
Если пОбъект.Типы().Количество() > 0 Тогда
ТипОбъекта = пОбъект.Типы()[0];
КонецЕсли;
ИначеЕсли ТипПараметра <> Тип("Тип") Тогда
ТипОбъекта = ТипПараметра;
Иначе
ТипОбъекта = пОбъект;
КонецЕсли;
Возврат ТипОбъекта;
КонецФункции // ПолучитьТипОбъектаЛкс()
// Проверяет, является ли строка именем корневого типа объекта БД.
//
// Параметры:
// пИмяКорневогоТипа - Строка, Неопределено - имя корневого типа.
//
// Возвращаемое значение:
// Истина - тип является корневым типом объекта БД;
// Ложь - иначе.
//
Функция ЛиКорневойТипСсылочногоОбъектаБДЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
ИЛИ КорневойТип = "БизнесПроцесс"
ИЛИ КорневойТип = "Задача"
ИЛИ КорневойТип = "Документ"
ИЛИ КорневойТип = "ПланВидовРасчета"
ИЛИ КорневойТип = "ПланВидовХарактеристик"
ИЛИ КорневойТип = "ПланОбмена"
ИЛИ КорневойТип = "ПланСчетов"
ИЛИ КорневойТип = "Справочник"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипКонстантыЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
ИЛИ КорневойТип = "Константа"
ИЛИ КорневойТип = "Константы"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипПланаОбменаЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "ПланОбмена" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипДокументаЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "Документ" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипСправочникаЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "Справочник" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипБизнесПроцессаЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "БизнесПроцесс" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипЗадачиЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Возврат КорневойТип = "Задача";
КонецФункции
Функция ЛиКорневойТипПланВидовХарактеристикЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Возврат КорневойТип = "ПланВидовХарактеристик";
КонецФункции
// Проверяет, является ли строка именем корневого типа ссылки.
//
// Параметры:
// КорневойТип - Строка, Неопределено - имя корневого типа или полное имя типа (с точками).
//
// Возвращаемое значение:
// Истина - тип является корневым типом ссылки;
// Ложь - иначе.
//
Функция ЛиКорневойТипСсылкиЛкс(Знач КорневойТип, ИсключаяСсылкиМетаданных = Ложь) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
ИЛИ Не ИсключаяСсылкиМетаданных И КорневойТип = "Перечисление"
ИЛИ Не ИсключаяСсылкиМетаданных И КорневойТип = "Точки" // Грязно
ИЛИ ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип)
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Проверяет, является ли строка именем корневого типа регистра БД.
//
// Параметры:
// КорневойТип - Строка, Неопределено - имя корневого типа.
//
// Возвращаемое значение:
// Истина - тип является корневым типом регистра БД;
// Ложь - иначе.
//
Функция ЛиКорневойТипРегистраБДЛкс(Знач КорневойТип, СчитатьПоследовательностьРегистром = Истина) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
ИЛИ КорневойТип = "РегистрСведений"
ИЛИ КорневойТип = "РегистрНакопления"
ИЛИ КорневойТип = "РегистрБухгалтерии"
ИЛИ КорневойТип = "ДвиженияССубконто"
ИЛИ КорневойТип = "РегистрРасчета"
ИЛИ КорневойТип = "Перерасчет"
ИЛИ (Истина
И СчитатьПоследовательностьРегистром
И КорневойТип = "Последовательность")
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипРегистраРасчетаЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "РегистрРасчета" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипРегистраСведенийЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "РегистрСведений" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипРегистраБухгалтерииЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "РегистрБухгалтерии" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипРегистраНакопленияЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "РегистрНакопления" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипПоследовательностиЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "Последовательность" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Процедура НормализоватьКорневойТипЛкс(КорневойТип)
Если Найти(КорневойТип, ".") > 0 Тогда
КорневойТип = ПервыйФрагментЛкс(КорневойТип);
КонецЕсли;
Если КодСимвола(КорневойТип, 1) < 128 Тогда
КорневойТип = ПеревестиВРусский(КорневойТип);
КонецЕсли;
КонецПроцедуры
Функция ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "ВнешнийИсточникДанных" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипПеречисленияЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "Перечисление" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиТипТаблицыМетассылкиЛкс(Знач ТипТаблицы) Экспорт
Если КодСимвола(ТипТаблицы, 1) < 128 Тогда
ТипТаблицы = ПеревестиВРусский(ТипТаблицы);
КонецЕсли;
Если Ложь
ИЛИ ТипТаблицы = "Перечисление"
ИЛИ ТипТаблицы = "Точки"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипЖурналаДокументовЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "ЖурналДокументов" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипКритерияОтбораЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если КорневойТип = "КритерийОтбора" Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиКорневойТипТаблицыБДЛкс(Знач КорневойТип, ВключаяВнешниеИсточникиДанных = Истина) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
Или ЛиКорневойТипЖурналаДокументовЛкс(КорневойТип)
Или ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип)
Или ЛиКорневойТипРегистраБДЛкс(КорневойТип)
Или (ВключаяВнешниеИсточникиДанных И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип))
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Проверяет, является ли строка именем типа вложенной таблицы БД.
//
// Параметры:
// ТипТаблицы - Строка, Неопределено - имя типа таблицы.
//
// Возвращаемое значение:
// Булево.
//
Функция ЛиТипВложеннойТаблицыБДЛкс(Знач ТипТаблицы) Экспорт
Если КодСимвола(ТипТаблицы, 1) < 128 Тогда
ТипТаблицы = ПеревестиВРусский(ТипТаблицы);
КонецЕсли;
Если Ложь
ИЛИ ТипТаблицы = "ТабличнаяЧасть"
ИЛИ ЛиИмяПредопределеннойТабличнойЧастиЛкс(ТипТаблицы)
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиИмяПредопределеннойТабличнойЧастиЛкс(Знач ТипТаблицы) Экспорт
Если КодСимвола(ТипТаблицы, 1) < 128 Тогда
ТипТаблицы = ПеревестиВРусский(ТипТаблицы);
КонецЕсли;
Если Ложь
ИЛИ ТипТаблицы = "ВидыСубконто"
ИЛИ ТипТаблицы = "БазовыеВидыРасчета"
ИЛИ ТипТаблицы = "ВедущиеВидыРасчета"
ИЛИ ТипТаблицы = "ВытесняющиеВидыРасчета"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Проверяет, корневой тип на наличие реквизита "Код".
//
// Параметры:
// КорневойТип - Строка, Произвольный.
//
// Возвращаемое значение:
// Истина - реквизит "Код" имеется;
// Ложь - иначе.
//
Функция ЛиКорневойТипОбъектаСКодомЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
Или КорневойТип = "ПланВидовХарактеристик"
Или КорневойТип = "ПланОбмена"
Или КорневойТип = "ПланСчетов"
Или КорневойТип = "ПланРасчета"
Или КорневойТип = "Справочник"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции // ЛиКорневойТипОбъектаСКодомЛкс()
// Проверяет, корневой тип на наличие реквизита "Предопределенный".
//
// Параметры:
// КорневойТип - Строка, Произвольный.
//
// Возвращаемое значение:
// Истина - реквизит "Предопределенный" имеется;
// Ложь - иначе.
//
Функция ЛиКорневойТипОбъектаСПредопределеннымЛкс(Знач КорневойТип) Экспорт
НормализоватьКорневойТипЛкс(КорневойТип);
Если Ложь
Или КорневойТип = "Справочник"
Или КорневойТип = "ПланСчетов"
Или КорневойТип = "ПланВидовХарактеристик"
Или КорневойТип = "ПланВидовРасчета"
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиМетаданныеВнешнегоИсточникаДанныхЛкс(Знач ОбъектМД) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(ОбъектМД);
Возврат ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип);
КонецФункции
// Проверяет, метаданные на иерархию.
// Иначе говоря проверяется наличие реквизита "Родитель".
//
// Параметры:
// пМетаданныеТипа - ОбъектМетаданных, Неопределено.
//
// Возвращаемое значение:
// Истина - метаданные с иерархией;
// Ложь - иначе.
//
Функция ЛиМетаданныеИерархическогоОбъектаЛкс(Знач ОбъектМД) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(ОбъектМД);
Если Ложь
Или КорневойТип = "ПланСчетов"
Или (Истина
И (Ложь
Или КорневойТип = "Справочник"
Или КорневойТип = "ПланВидовХарактеристик")
И ОбъектМД.Иерархический)
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Проверяет, метаданные на иерархию.
// Иначе говоря проверяется начилие реквизита "Родитель".
//
// Параметры:
// пМетаданныеТипа - ОбъектМетаданных, Неопределено.
//
// Возвращаемое значение:
// Истина - метаданные с иерархией;
// Ложь - иначе.
//
Функция ЛиМетаданныеПодчиненногоОбъектаЛкс(Знач ОбъектМД) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(ОбъектМД);
Если Истина
И (Ложь
Или КорневойТип = "Справочник"
Или КорневойТип = "ПланВидовХарактеристик")
И ОбъектМД.Владельцы.Количество() > 0
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Проверяет, метаданные на иерархию с группами.
// Иначе говоря проверяется начилие реквизита "ЭтоГруппа".
//
// Параметры:
// пМетаданныеТипа - ОбъектМетаданных, Неопределено.
//
// Возвращаемое значение:
// Истина - метаданные с иерархией групп;
// Ложь - иначе.
//
Функция ЛиМетаданныеОбъектаСГруппамиЛкс(Знач ОбъектМД) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(ОбъектМД, Истина);
Если Ложь
Или (Истина
И КорневойТип = "Справочник"
И ОбъектМД.Иерархический
И ОбъектМД.ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов)
Или (Истина
И КорневойТип = "ПланВидовХарактеристик"
И ОбъектМД.Иерархический)
Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Функция - Ли метаданные ссылочного объекта лкс
//
// Параметры:
// ОбъектМД - -
// ДляТабличнойЧастиПроверятьРодителя - -
// ИсключаяСсылкиМетаданных - -
// ИсключаяВнешниеИсточникиДанных - -
// ФрагментыИмени - Массив - можно передавать для ускорения
//
// Возвращаемое значение:
// -
//
Функция ЛиМетаданныеСсылочногоОбъектаЛкс(Знач ОбъектМД, ДляТабличнойЧастиПроверятьРодителя = Ложь, ИсключаяСсылкиМетаданных = Ложь, ИсключаяВнешниеИсточникиДанных = Ложь,
Знач ФрагментыИмени = Неопределено) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Если ФрагментыИмени = Неопределено Тогда
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют;
#КонецЕсли
Фрагменты = СтрРазделитьЛкс(ОбъектМД.ПолноеИмя());
Иначе
Фрагменты = ФрагментыИмени;
КонецЕсли;
КорневойТип = Фрагменты[0];
Если Истина
И Не ИсключаяВнешниеИсточникиДанных
И Фрагменты.Количество() = 4
И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип)
Тогда
//! ОбъектМД = 0 // ОбъектМетаданныхТаблица
Возврат (ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные);
Иначе
Если Истина
И Не ДляТабличнойЧастиПроверятьРодителя
И Фрагменты.Количество() > 2
Тогда
Возврат Ложь;
КонецЕсли;
Если ЛиКорневойТипСсылкиЛкс(КорневойТип, ИсключаяСсылкиМетаданных) Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецФункции
Функция ЛиМетаданныеРегистраЛкс(Знач ОбъектМД, СчитатьПоследовательностьРегистром = Истина) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют;
#КонецЕсли
Фрагменты = СтрРазделитьЛкс(ОбъектМД.ПолноеИмя());
КорневойТип = Фрагменты[0];
Если ЛиКорневойТипРегистраБДЛкс(КорневойТип, СчитатьПоследовательностьРегистром) Тогда
Возврат Истина;
ИначеЕсли Истина
И Фрагменты.Количество() = 4
И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип)
Тогда
Возврат (ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.НеобъектныеДанные);
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Функция ЛиМетаданныеНезависимогоРегистраЛкс(Знач ОбъектМД) Экспорт
Если ОбъектМД = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют;
#КонецЕсли
Фрагменты = СтрРазделитьЛкс(ОбъектМД.ПолноеИмя());
КорневойТип = Фрагменты[0];
ЭтоНезависимыйРегистр = Ложь
Или (Истина
И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип)
//! ОбъектМД = 0 // ОбъектМетаданныхТаблица
И ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.НеобъектныеДанные)
Или (Истина
И ЛиКорневойТипРегистраСведенийЛкс(КорневойТип)
//! ОбъектМД = 0 // ОбъектМетаданныхРегистрСведений
И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый);
Возврат ЭтоНезависимыйРегистр;
КонецФункции
// https://www.hostedredmine.com/issues/895490
Функция ЛиДоступноРедактированиеВФормеОбъектаЛкс(ОбъектМД) Экспорт
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.Справочники.Валюты;
#КонецЕсли
Результат = Истина;
Если Ложь
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Или Ложь
//Или Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение
#ИначеЕсли ТолстыйКлиентОбычноеПриложение Тогда
Или Истина
//Или Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение
//Или ТипТаблицыБДЛкс(ОбъектМД.ПолноеИмя()) = "Внешняя" // Обычные формы для таблиц внешних источников не обеспечивает платформа
#КонецЕсли
Тогда
Если ЛиМетаданныеРегистраЛкс(ОбъектМД) Тогда
ИмяФормы = "ФормаЗаписи";
Иначе
ИмяФормы = "ФормаОбъекта";
КонецЕсли;
Попытка
ОсновнаяФорма = ОбъектМД["Основная" + ИмяФормы];
Исключение
ОсновнаяФорма = Неопределено;
КонецПопытки;
Если ОсновнаяФорма = Неопределено Тогда
Результат = Ложь;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверяет, является ли значение ссылкой на объект БД.
// Почему то часто тут тратилось много времени. Поэтому лучше использовать ЛиТипСсылкиБДЛкс().
//
// Параметры:
// пЗначение - ОбъектМетаданных, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - значение является ссылкой на объект БД;
// Ложь - значение не является ссылкой на объект БД.
//
Функция ЛиСсылкаНаОбъектБДЛкс(Знач пЗначение, ИсключаяСсылкиМетаданных = Истина) Экспорт
//Результат = ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТипКонфигурацииЛкс(пЗначение, Истина));
Результат = ЛиТипСсылкиБДЛкс(ТипЗнч(пЗначение), ИсключаяСсылкиМетаданных);
Возврат Результат;
КонецФункции
Функция ЛиТипСсылкиБДЛкс(Знач Тип, Знач ИсключаяСсылкиМетаданных = Истина) Экспорт
Если Тип = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Результат = Ложь;
ХмлТип = XMLТип(Тип);
Если ХмлТип <> Неопределено Тогда
Если Найти(ХмлТип.ИмяТипа, "Ref.") > 0 Тогда
Если Ложь
Или Не ИсключаяСсылкиМетаданных
Или (Истина
И Найти(ХмлТип.ИмяТипа, "BusinessProcessRoutePointRef.") = 0
И Найти(ХмлТип.ИмяТипа, "EnumRef.") = 0)
Тогда
Результат = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Не поддерживает имитаторы
Функция ЛиТипОбъектаБДЛкс(Знач Тип) Экспорт
Результат = Ложь;
ХмлТип = XMLТип(Тип);
Если ХмлТип <> Неопределено Тогда
Если Ложь
Или Найти(ХмлТип.ИмяТипа, "Object.") > 0
Или Найти(ХмлТип.ИмяТипа, "RecordSet.") > 0
Или Найти(ХмлТип.ИмяТипа, "ValueManager.") > 0
Тогда
Результат = Истина;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиТипСсылкиТочкиМаршрутаЛкс(Знач Тип) Экспорт
XMLТип = XMLТип(Тип);
Если XMLТип <> Неопределено Тогда
Если Найти(XMLТип.ИмяТипа, "BusinessProcessRoutePointRef.") > 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиТипСсылкиВнешнейТаблицыЛкс(Знач Тип) Экспорт
XMLТип = XMLТип(Тип);
Если XMLТип <> Неопределено Тогда
Если Найти(XMLТип.ИмяТипа, "ExternalDataSourceTableRef.") > 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Процедура УстановитьВложенноеСвойствоСтруктурыЛкс(Знач НачальнаяСтруктура, Знач ПолноеИмяСвойства, Знач ЗначениеДанных) Экспорт
Фрагменты = СтрРазделитьЛкс("_." + ПолноеИмяСвойства);
ТекущаяСтруктура = Новый Структура("_", НачальнаяСтруктура);
Для Индекс = 0 По Фрагменты.Вграница() - 1 Цикл
ТекущаяСтруктура = ТекущаяСтруктура[Фрагменты[Индекс]];
Если Не ТекущаяСтруктура.Свойство(Фрагменты[Индекс + 1]) Тогда
ТекущаяСтруктура.Вставить(Фрагменты[Индекс + 1], Новый Структура);
КонецЕсли;
КонецЦикла;
ТекущаяСтруктура[Фрагменты[Фрагменты.Вграница()]] = ЗначениеДанных;
КонецПроцедуры
// Проверяет, является ли значение ссылкой на значение перечисления.
//
// Параметры:
// пЗначение - Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - значение является ссылкой на объект БД;
// Ложь - значение не является ссылкой на объект БД.
//
Функция ЛиСсылкаНаПеречислениеЛкс(Знач пЗначение) Экспорт
Возврат (КорневойТипКонфигурацииЛкс(пЗначение) = "Перечисление");
КонецФункции
// Проверка с учетом мультиязычности встроенного языка
Функция ЛиТипыРегистровРодственныЛкс(Знач Объект, Знач Подтип, Знач КоличествоСлов) Экспорт
Попытка
ПредставлениеОбъекта = "" + Объект;
Исключение
// Например ВыборкаИзРезультатаЗапроса
Возврат Ложь;
КонецПопытки;
Если Истина
И Найти(Объект, ПеревестиСтроку(Подтип) + ".") > 0 // Может возникать баг БСП 2 https://www.hostedredmine.com/issues/956894
Тогда
// Внешний источник данных
Результат = Истина;
Иначе
ТипОбразец = ирКэш.ЛюбойТипРегистраЛкс(Подтип);
Если ТипОбразец = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Результат = ЛиПодтипыТиповРавныЛкс(ТипОбразец, Объект, КоличествоСлов);
КонецЕсли;
Возврат Результат;
КонецФункции
// Проверка родственности типов (равенства типа типа), производных от метаданных
//
// Параметры:
// ТипОбразец - Тип -
// ОбъектИлиТип - -
// КоличествоСлов - Число - количество слов представления типа перед двоеточием, обозначающих подтип
//
// Возвращаемое значение:
// - Булево
//
Функция ЛиПодтипыТиповРавныЛкс(Знач ТипОбразец, Знач ОбъектИлиТип, Знач КоличествоСлов)
МаркерТипа = ирКэш.МаркерПодтипаИзТипаЛкс("" + ТипОбразец, КоличествоСлов);
ПредставлениеОбъекта = ПервыйФрагментЛкс(ПолучитьТипОбъектаЛкс(ОбъектИлиТип), ":");
Результат = СтрКончаетсяНаЛкс(ПредставлениеОбъекта, МаркерТипа);
Возврат Результат;
КонецФункции
// Проверяет, является ли ключом записи регистра описание типов, тип или значение.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - тип ключа записи регистра подтвержден;
// Ложь - тип ключа записи регистра не подтвержден.
//
Функция ЛиКлючЗаписиРегистраЛкс(Объект, _ИсключаяВнешниеИсточникиДанных = Ложь) Экспорт
Результат = ЛиТипыРегистровРодственныЛкс(Объект, "КлючЗаписи", 2);
Возврат Результат;
КонецФункции
Функция ЛиКлючСсылкиИлиРегистраЛкс(Знач Объект, ИсключаяСсылкиМетаданных = Истина) Экспорт
Возврат Ложь
Или ЛиСсылкаНаОбъектБДЛкс(Объект, ИсключаяСсылкиМетаданных)
Или ЛиКлючЗаписиРегистраЛкс(Объект);
КонецФункции
// Проверяет, является ли записью регистра описание типов, тип или значение.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - тип записи регистра подтвержден;
// Ложь - тип записи регистра не подтвержден.
//
Функция ЛиЗаписьРегистраЛкс(Объект) Экспорт
Результат = ЛиТипыРегистровРодственныЛкс(Объект, "Запись", 1);
Возврат Результат;
КонецФункции
// Проверяет, является ли набором записей регистра описание типов, тип или значение.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - тип набора записей регистра подтвержден;
// Ложь - тип набора записей регистра не подтвержден.
//
Функция ЛиНаборЗаписейРегистраЛкс(Объект) Экспорт
Результат = ЛиТипыРегистровРодственныЛкс(Объект, "НаборЗаписей", 2);
Возврат Результат;
КонецФункции
// Проверяет, является ли менеджером записи регистра описание типов, тип или значение.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - тип менеджер записи регистра подтвержден;
// Ложь - тип менеджер записи регистра не подтвержден.
//
Функция ЛиМенеджерЗаписиРегистраЛкс(Объект) Экспорт
Результат = ЛиТипыРегистровРодственныЛкс(Объект, "МенеджерЗаписи", 2);
Возврат Результат;
КонецФункции
Функция ЛиТабличнаяЧастьЛкс(Знач ТипЗначенияИлиОбъект, Знач ЗапретитьТип = Ложь) Экспорт
Если Истина
И ЗапретитьТип
И (Ложь
Или ТипЗнч(ТипЗначенияИлиОбъект) = Тип("Тип")
Или ТипЗнч(ТипЗначенияИлиОбъект) = Тип("ОписаниеТипов"))
Тогда
Возврат Ложь;
КонецЕсли;
Результат = ЛиПодтипыТиповРавныЛкс(ирКэш.ЛюбойТипТабличнойЧастиЛкс(), ТипЗначенияИлиОбъект, 2);
Возврат Результат;
КонецФункции
Функция ЛиСтрокаТабличнойЧастиЛкс(Знач ТипЗначенияИлиОбъект) Экспорт
Результат = ЛиПодтипыТиповРавныЛкс(ирКэш.ЛюбойТипСтрокиТабличнойЧастиЛкс(), ТипЗначенияИлиОбъект, 3);
Возврат Результат;
КонецФункции
// Проверяет, является ли субконтом описание типов, тип или значение.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Тип, ОписаниеТипов, Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - тип субконто подтвержден;
// Ложь - тип субконто не подтвержден.
//
Функция ЛиСубконтоЛкс(пОбъект) Экспорт
ТипОбъекта = ПолучитьТипОбъектаЛкс(пОбъект);
Маркер = "субконто:";
Если Найти(Строка(ТипОбъекта), Маркер) > 0 Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции // ЛиСубконтоЛкс()
// Проверяет, является ли значение табличной частью внешней обработки.
//
// Параметры:
// пЗначение - Произвольный - проверяемое значение.
//
// Возвращаемое значение:
// Истина - значение является табличной частью внешней обработки;
// Ложь - значение не является табличной частью внешней обработки.
//
Функция ЛиТабличнаяЧастьВнешнейОбработкиЛкс(Объект) Экспорт
Результат = "ВнешняяОбработкаТабличнаяЧасть" = ПервыйФрагментЛкс(Строка(Объект));
Возврат Результат;
КонецФункции
Функция ЛиВнешняяОбработкаЛкс(Объект) Экспорт
Результат = ПеревестиСтроку("ВнешняяОбработка") + ПеревестиСтроку("Объект") = ПервыйФрагментЛкс(Строка(Объект));
Возврат Результат;
КонецФункции
// Получает ссылочный тип по метаданным.
//
// Параметры:
// пМетаданные - ОбъектМетаданных.
//
// Возвращаемое значение:
// - Тип - ссылочный;
// Неопределено - тип нельзя получить.
//
Функция ПолучитьСсылочныйТипПоМетаданнымЛкс(пМетаданные) Экспорт
Результат = Неопределено;
КорневойТип = КорневойТипКонфигурацииЛкс(пМетаданные, Истина);
Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип) Тогда
Результат = Тип(КорневойТип + "Ссылка." + пМетаданные.Имя);
КонецЕсли;
Возврат Результат;
КонецФункции // ПолучитьСсылочныйТипПоМетаданнымЛкс()
// Получает метаданные по полному имени, описанию типов, типу, ссылке или объекту.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Произвольный - для чего получаем метаданные.
//
// Возвращаемое значение:
// - Метаданные - полученные;
// Неопределено - не удалось получить метаданные.
//
Функция ПолучитьМетаданныеЛкс(пОбъект) Экспорт
Если ТипЗнч(пОбъект) = Тип("Строка") Тогда
Если ПустаяСтрока(пОбъект) Тогда
Результат = Неопределено;
Иначе
Фрагменты = СтрРазделитьЛкс(пОбъект);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
Если Фрагменты.Количество() % 2 = 1 Тогда
// ВидыСубконто, Изменения
Фрагменты.Удалить(Фрагменты.ВГраница());
ПолноеИмяМД = СтрСоединитьЛкс(Фрагменты, ".");
Иначе
ПолноеИмяМД = пОбъект;
КонецЕсли;
Результат = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
КонецЕсли;
Возврат Результат;
КонецЕсли;
Если ЛиВнешняяОбработкаЛкс(пОбъект) Тогда
//! пОбъект =0 // ВнешняяОбработкаОбъект
Результат = пОбъект.Метаданные();
Иначе
ТипОбъекта = ПолучитьТипОбъектаЛкс(пОбъект);
Результат = Метаданные.НайтиПоТипу(ТипОбъекта);
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает метаданные списка по описанию типов, типу или значению.
// Для описания типов берется первый тип массива типов.
//
//
// Параметры:
// пОбъект - Произвольное - проверяемое значение.
//
// Возвращаемое значение:
// - Метаданные - списка;
// Неопределено - значение не является списком.
//
Функция ПолучитьМетаданныеСпискаЛкс(пОбъект) Экспорт
ТипОбъекта = ПолучитьТипОбъектаЛкс(пОбъект);
МаркерСписка = "список:";
Если Найти(Строка(ТипОбъекта), МаркерСписка) > 0 Тогда
Возврат ПолучитьМетаданныеЛкс(ТипОбъекта);
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции // ПолучитьМетаданныеСпискаЛкс()
// Определяет корневой тип конфигурации по описанию типов, типу, метаданным, ссылке или объекту.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Произвольный - для чего получаем метаданные;
// *пЛиТолькоДляКорневого - Булево, *Ложь - возвращать только для объекта корневого типа.
//
// Возвращаемое значение:
// - Строка - имя типа корневого объекта метаданных;
// Неопределено - не удалось получить имя типа.
//
Функция КорневойТипКонфигурацииЛкс(пОбъект, пЛиТолькоДляКорневого = Ложь) Экспорт
Если ТипЗнч(пОбъект) = Тип("ОбъектМетаданных") Тогда
МетаданныеТипа = пОбъект;
Иначе
МетаданныеТипа = ПолучитьМетаданныеЛкс(пОбъект);
КонецЕсли;
Результат = Неопределено;
Если МетаданныеТипа <> Неопределено Тогда
ПолноеИмя = МетаданныеТипа.ПолноеИмя();
Если пЛиТолькоДляКорневого Тогда
МассивФрагментов = СтрРазделитьЛкс(ПолноеИмя);
Если МассивФрагментов.Количество() = 2 Тогда
Результат = МассивФрагментов[0];
КонецЕсли;
Иначе
Результат = ПервыйФрагментЛкс(ПолноеИмя);
КонецЕсли;
//Если Результат = "ВнешнийИсточникДанных" Тогда
// Результат = Результат + "Таблица";
//КонецЕсли;
НормализоватьКорневойТипЛкс(Результат);
КонецЕсли;
Если Результат = "ТабличнаяЧасть" Тогда
// Баг платформы. У внешних метаданных полное имя не включает сам внешний метаобъект
Результат = Неопределено;
КонецЕсли;
Возврат Результат;
КонецФункции
// Определяет имя корневого типа строки табличной части по описанию типов, типу или значению.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Произвольный - для чего получаем корневой тип строки табличной части.
//
// Возвращаемое значение:
// - Строка - имя типа корневого объекта метаданных;
// Неопределено - значение не является строкой табличной части.
//
Функция КорневойТипСтрокиТабличнойЧастиЛкс(пОбъект) Экспорт
ТипОбъекта = ПолучитьТипОбъектаЛкс(пОбъект);
Маркер = "табличная часть строка:";
Если Найти(Строка(ТипОбъекта), Маркер) > 0 Тогда
Возврат ПервыйФрагментЛкс(Метаданные.НайтиПоТипу(ТипОбъекта).ПолноеИмя());
КонецЕсли;
Возврат Неопределено;
КонецФункции // КорневойТипСтрокиТабличнойЧастиЛкс()
// Определяет имя корневого типа табличной части по описанию типов, типу, метаданным, ссылке или объекту.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Произвольный - для чего определяем корневой тип.
//
// Возвращаемое значение:
// - Строка - имя типа корневого объекта метаданных;
// Неопределено - значение не является строкой табличной части.
//
Функция ПолучитьКорневойТипТабличнойЧастиЛкс(пОбъект) Экспорт
Если ТипЗнч(пОбъект) = Тип("ОбъектМетаданных") Тогда
МетаданныеТипа = пОбъект;
Иначе
МетаданныеТипа = ПолучитьМетаданныеЛкс(пОбъект);
КонецЕсли;
Если МетаданныеТипа <> Неопределено Тогда
ПолноеИмя = МетаданныеТипа.ПолноеИмя();
МассивФрагментов = СтрРазделитьЛкс(ПолноеИмя);
Если Истина
И МассивФрагментов.Количество() >= 4
И МассивФрагментов[2] = "ТабличнаяЧасть"
Тогда
Возврат МассивФрагментов[2];
КонецЕсли;
КонецЕсли;
Возврат Неопределено;
КонецФункции // ПолучитьКорневойТипТабличнойЧастиЛкс()
// Определяет имя корневого типа списка по описанию типов, типу или значению.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - Произвольный - для чего получаем корневой тип строки табличной части.
//
// Возвращаемое значение:
// - Строка - имя типа корневого объекта метаданных;
// Неопределено - значение не является списком.
//
Функция ПолучитьКорневойТипСпискаЛкс(пОбъект) Экспорт
ТипОбъекта = ПолучитьТипОбъектаЛкс(пОбъект);
Маркер = "список:";
Если Найти(Строка(ТипОбъекта), Маркер) > 0 Тогда
Возврат ПервыйФрагментЛкс(Метаданные.НайтиПоТипу(ТипОбъекта).ПолноеИмя());
КонецЕсли;
Возврат Неопределено;
КонецФункции // ПолучитьКорневойТипСпискаЛкс()
// Определяет имя табличной части по ее метаданным.
//
// Параметры:
// пМетаданные - ОбъектМетаданных - который проверяем.
//
// Возвращаемое значение:
// - Строка - имя табличной части;
// Неопределено - это метаданные не табличной части.
//
Функция ПолучитьИмяТабличнойЧастиЛкс(пМетаданные) Экспорт
Если пМетаданные <> Неопределено Тогда
МассивФрагментов = СтрРазделитьЛкс(пМетаданные.ПолноеИмя());
Если МассивФрагментов.ВГраница() >= 2 Тогда
Если МассивФрагментов[2] = "ТабличнаяЧасть" Тогда
Возврат МассивФрагментов[3];
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Неопределено;
КонецФункции // ПолучитьИмяТабличнойЧастиЛкс()
// Получает менеджер по описанию типов, типу, метаданным, ссылке или объекту.
// Для описания типов берется первый тип массива типов.
//
// Параметры:
// пОбъект - ОбъектМетаданных, Тип, Ссылка, Произвольный -
//
// Возвращаемое значение:
// СправочникМенеджер, ДокументМенеджер, ЗадачаМенеджер, БизнесПроцессМенеджер, ПланСчетовМенеджер, РегистрСведенийМенеджер, Произвольный, Неопределено
//
Функция ПолучитьМенеджерЛкс(пОбъект) Экспорт
Если ТипЗнч(пОбъект) = Тип("ОбъектМетаданных") Тогда
МетаданныеОбъекта = пОбъект;
Иначе
МетаданныеОбъекта = ПолучитьМетаданныеЛкс(пОбъект);
КонецЕсли;
Если МетаданныеОбъекта = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
МассивФрагментов = СтрРазделитьЛкс(МетаданныеОбъекта.ПолноеИмя());
КорневойТип = МассивФрагментов[0];
Менеджер = Неопределено;
Если Истина
И МассивФрагментов.Количество() = 4
И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип)
Тогда
ИмяТипаМенеджера = МассивФрагментов[0] + ПеревестиСтроку("ТаблицаМенеджер") + "." + МассивФрагментов[1] + "." + МассивФрагментов[3];
Иначе
//КорневойТип = КорневойТипКонфигурацииЛкс(МетаданныеОбъекта, Истина); // Изменил 02.03.2012
Если КорневойТип <> Неопределено Тогда
ИмяТипаМенеджера = КорневойТип + ПеревестиСтроку("Менеджер") + "." + МетаданныеОбъекта.Имя;
Иначе
ИмяТипаМенеджера = "Неопределено";
КонецЕсли;
КонецЕсли;
Попытка
Менеджер = Новый (ИмяТипаМенеджера);
Исключение
КонецПопытки;
Возврат Менеджер;
КонецФункции
// Получает запись регистра по ключу записи.
//
// Параметры:
// пКлючЗаписи - КлючЗаписиРегистра - идентифицирующий запись.
//
// Возвращаемое значение:
// - ЗаписьРегистра - найденная запись.
//
Функция ПолучитьЗаписьРегистраПоКлючуЛкс(пКлючЗаписи) Экспорт
МенеджерЗначения = ПолучитьМенеджерЛкс(пКлючЗаписи);
МенеджерЗаписи = МенеджерЗначения.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, пКлючЗаписи);
МенеджерЗаписи.Прочитать();
Возврат МенеджерЗаписи;
КонецФункции // ПолучитьЗаписьРегистраПоКлючуЛкс()
// Больше не используется. Кандидат на удаление.
// Получает список реквизитов объекта БД.
//
// Параметры:
// пОбъект - определитель объекта метаданных;
// *ЛиВключатьТолькоЧитаемые - Булево, *Ложь - включать ли в список только читаемые реквизиты;
// *ЛиВключатьНедоступные - Булево, *Ложь - включать ли в список недоступные (группы/элементы) реквизиты;
// *ЛиСортировать - Булево, *Ложь - отсортировать ли по представлению;
// *ЛиСКартинками - Булево, *Ложь - добавлять ли картинки;
// *ЛиСТабличнымиЧастями - Булево, *Ложь - включать ли в список табличные части.
//
// Возвращаемое значение:
// СписокЗначений - содержащий в качестве значений имена реквизитов.
//
Функция РеквизитыОбъектаБДЛкс(пОбъект, ЛиВключатьТолькоЧитаемые = Ложь, ЛиВключатьНедоступные = Ложь, ЛиСортировать = Ложь, ЛиСКартинками = Ложь, ЛиСТабличнымиЧастями = Ложь) Экспорт
СписокРеквизитов = Новый СписокЗначений;
Если пОбъект = Неопределено Тогда
Возврат СписокРеквизитов;
КонецЕсли;
Если ТипЗнч(пОбъект) = Тип("ОбъектМетаданных") Тогда
ОбъектМетаданных = пОбъект;
Иначе
ОбъектМетаданных = ПолучитьМетаданныеЛкс(пОбъект);
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(ОбъектМетаданных);
КорневойТип = ПеревестиВРусский(КорневойТип);
ИерархияГрупп = Ложь;
КартинкаРеквизита = Неопределено;
#Если Клиент Тогда
Если ЛиСКартинками Тогда
КартинкаРеквизита = ирКэш.КартинкаПоИмениЛкс("ирРеквизит");
КонецЕсли;
#КонецЕсли
Если КорневойТип = "Задача" Тогда
СписокРеквизитов.Добавить("БизнесПроцесс", "Бизнес процесс", , КартинкаРеквизита);
СписокРеквизитов.Добавить("Дата", "Дата", , КартинкаРеквизита);
Если ОбъектМетаданных.ДлинаНаименования > 0 Тогда
СписокРеквизитов.Добавить("Наименование", "Наименование", , КартинкаРеквизита);
КонецЕсли;
Если ОбъектМетаданных.ДлинаНомера > 0 Тогда
СписокРеквизитов.Добавить("Номер", "Номер", , КартинкаРеквизита);
КонецЕсли;
СписокРеквизитов.Добавить("ТочкаМаршрута", "Точка маршрута", , КартинкаРеквизита);
СписокРеквизитов.Добавить("Выполнена", "Выполнена", , КартинкаРеквизита);
Для Каждого Рекв из ОбъектМетаданных.РеквизитыАдресации Цикл
СписокРеквизитов.Добавить(Рекв.Имя, Рекв.Представление(), , КартинкаРеквизита);
КонецЦикла;
КонецЕсли;
Если КорневойТип = "Документ" Тогда
СписокРеквизитов.Добавить("Дата", "Дата", , КартинкаРеквизита);
Если ОбъектМетаданных.ДлинаНомера > 0 Тогда
СписокРеквизитов.Добавить("Номер", "Номер", , КартинкаРеквизита);
КонецЕсли;
Если ЛиВключатьТолькоЧитаемые Тогда
СписокРеквизитов.Добавить("Проведен", "Проведен", , КартинкаРеквизита);
КонецЕсли;
КонецЕсли;
Если КорневойТип = "Справочник" Тогда
Если ОбъектМетаданных.Владельцы.Количество() > 0 Тогда
СписокРеквизитов.Добавить("Владелец", "Владелец", , КартинкаРеквизита);
КонецЕсли;
КонецЕсли;
ЭтоГруппа = Ложь;
Если ЛиКорневойТипОбъектаСКодомЛкс(КорневойТип) Тогда
Если ОбъектМетаданных.ДлинаКода > 0 Тогда
СписокРеквизитов.Добавить("Код", "Код", , КартинкаРеквизита);
КонецЕсли;
Если ОбъектМетаданных.ДлинаНаименования > 0 Тогда
СписокРеквизитов.Добавить("Наименование", "Наименование", , КартинкаРеквизита);
КонецЕсли;
Если ЛиМетаданныеИерархическогоОбъектаЛкс(ОбъектМетаданных) Тогда
СписокРеквизитов.Добавить("Родитель", "Родитель", , КартинкаРеквизита);
Если ЛиМетаданныеОбъектаСГруппамиЛкс(ОбъектМетаданных) Тогда
ИерархияГрупп = Истина;
Если Не ЛиВключатьНедоступные Тогда
ЭтоГруппа = пОбъект.ЭтоГруппа;
КонецЕсли;
Если ЛиВключатьТолькоЧитаемые Тогда
СписокРеквизитов.Добавить("ЭтоГруппа", "Это группа", , КартинкаРеквизита);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЛиКорневойТипОбъектаСПредопределеннымЛкс(КорневойТип) Тогда
Если ЛиВключатьТолькоЧитаемые Тогда
СписокРеквизитов.Добавить("Предопределенный", "Предопределенный", , КартинкаРеквизита);
КонецЕсли;
КонецЕсли;
Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип) Тогда
СписокРеквизитов.Добавить("ПометкаУдаления", "Пометка удаления", , КартинкаРеквизита);
Если ЛиВключатьТолькоЧитаемые Тогда
СписокРеквизитов.Добавить("Ссылка", "Ссылка", , КартинкаРеквизита);
КонецЕсли;
КонецЕсли;
Для Каждого СтрокаРеквизита Из СписокРеквизитов Цикл
СтрокаРеквизита.Значение = ПеревестиСтроку(СтрокаРеквизита.Значение);
КонецЦикла;
#Если Клиент Тогда
Если ЛиСКартинками Тогда
КартинкаРеквизита = ирКэш.КартинкаПоИмениЛкс("ирРеквизит");
КонецЕсли;
#КонецЕсли
Для Каждого МетаРеквизит Из ОбъектМетаданных.Реквизиты Цикл
Если Ложь
Или ЛиВключатьНедоступные
Или Не ИерархияГрупп
Или МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента
Или (Истина
И ЭтоГруппа
И МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппы)
Или (Истина
И Не ЭтоГруппа
И МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляЭлемента)
Тогда
СписокРеквизитов.Добавить(МетаРеквизит.Имя, МетаРеквизит.Представление(), , КартинкаРеквизита);
КонецЕсли;
КонецЦикла;
Если ирКэш.ДоступноОбщиеРеквизитыЛкс() Тогда
Для Каждого ОбщийРеквизит Из Метаданные.ОбщиеРеквизиты Цикл
Если ЛиОбщийРеквизитИспользуетсяВОбъектеМетаданныхЛкс(ОбщийРеквизит, ОбъектМетаданных) Тогда
СписокРеквизитов.Добавить(ОбщийРеквизит.Имя, ОбщийРеквизит.Представление(), , КартинкаРеквизита);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЛиСТабличнымиЧастями Тогда
#Если Клиент Тогда
Если ЛиСКартинками Тогда
КартинкаРеквизита = БиблиотекаКартинок.ирТабличнаяЧасть;
КонецЕсли;
#КонецЕсли
Для Каждого МетаТабличнаяЧасть Из ОбъектМетаданных.ТабличныеЧасти Цикл
Если Ложь
Или ЛиВключатьНедоступные
Или Не ИерархияГрупп
Или МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппыИЭлемента
Или (Истина
И ЭтоГруппа
И МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппы)
Или (Истина
И Не ЭтоГруппа
И МетаРеквизит.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляЭлемента)
Тогда
СписокРеквизитов.Добавить(МетаТабличнаяЧасть.Имя, МетаТабличнаяЧасть.Представление(), , КартинкаРеквизита);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЛиСортировать Тогда
СписокРеквизитов.СортироватьПоПредставлению();
КонецЕсли;
Возврат СписокРеквизитов;
КонецФункции
Функция ИмяФайлаСпискаИнфобазПользователяОСЛкс() Экспорт
ИмяФайлаСписка = ирКэш.КаталогПлатформыВПрофилеЛкс(Ложь) + СтрЗаменить("\1cestart\ibases.v8i", "\", РазделительПутиКФайлуЛкс());
Возврат ИмяФайлаСписка;
КонецФункции
// .
// Параметры:
// Описатель - ОбъектМетаданных, КолонкиТаблицыЗначений - его реквизиты переносятся в коллекцию в качестве элементов для структуры и в качестве колонок для дерева или таблицы
// Коллекция с элементами РеквизитФормы, ОбъектМетаданныхРеквизит
// КоллекцияПриемник - ТаблицаЗначений, ДеревоЗначений, Структура - по умолчанию создается ТаблицаЗначений
// ИменаКолонок - Структура, Строка - список нужных колонок
// Возвращаемое значение:
// -
Функция УстановитьМетаданныеКоллекцииЛкс(Знач Описатель, КоллекцияПриемник = Неопределено, Знач ИменаКолонок = Неопределено) Экспорт
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый ТаблицаЗначений;
КонецЕсли;
ТипИсходнойКоллекции = ТипЗнч(КоллекцияПриемник);
Если Ложь
Или ТипИсходнойКоллекции = Тип("ДеревоЗначений")
Или ТипИсходнойКоллекции = Тип("ТаблицаЗначений")
Тогда
Коллекция = КоллекцияПриемник.Колонки;
Колонки = Коллекция;
Иначе//Если ТипИсходнойКоллекции = Тип("Структура") Тогда
Коллекция = КоллекцияПриемник;
Если ТипЗнч(КоллекцияПриемник) = Тип("Структура") Тогда
Пустышка = Новый ТаблицаЗначений;
Колонки = Пустышка.Колонки;
Иначе
Колонки = Коллекция;
КонецЕсли;
КонецЕсли;
Если ТипЗнч(Описатель) = Тип("ОбъектМетаданных") Тогда
Реквизиты = Описатель.Реквизиты;
Иначе
Реквизиты = Описатель;
КонецЕсли;
Если ТипЗнч(ИменаКолонок) = Тип("Строка") Тогда
ИменаКолонок = Новый Структура(ИменаКолонок);
КонецЕсли;
Для Каждого Реквизит Из Реквизиты Цикл
Если Ложь
Или Колонки.Найти(Реквизит.Имя) <> Неопределено
Или ИменаКолонок <> Неопределено И Не ИменаКолонок.Свойство(Реквизит.Имя)
Тогда
Продолжить;
КонецЕсли;
Если Ложь
Или ТипЗнч(Реквизит) = Тип("РеквизитФормы")
Или ТипЗнч(Реквизит) = Тип("КолонкаТаблицыЗначений")
Или ТипЗнч(Реквизит) = Тип("КолонкаДереваЗначений")
Или ТипЗнч(Реквизит) = Тип("КолонкаРезультатаЗапроса")
Или ТипЗнч(Реквизит) = Тип("СтрокаТаблицыЗначений")
Тогда
Колонки.Добавить(Реквизит.Имя, Реквизит.ТипЗначения, Реквизит.Заголовок);
ИначеЕсли ТипЗнч(Реквизит) = Тип("ОбъектМетаданных") Тогда
//! Реквизит = 0 // ОбъектМетаданныхРеквизит
Колонки.Добавить(Реквизит.Имя, Реквизит.Тип, Реквизит.Представление());
ИначеЕсли ТипЗнч(Реквизит) = Тип("ПолеНастройки") Тогда
Колонки.Добавить(Реквизит.Имя, Реквизит.ТипЗначения, Реквизит.Представление);
Иначе
ВызватьИсключение "Неизвестный тип описания реквизита """ + ТипЗнч(Реквизит) + """";
КонецЕсли;
КонецЦикла;
Если ТипЗнч(Коллекция) = Тип("Структура") Тогда
Для Каждого Колонка Из Колонки Цикл
Коллекция.Вставить(Колонка.Имя, Колонка.ТипЗначения.ПривестиЗначение(Неопределено));
КонецЦикла;
КонецЕсли;
Возврат КоллекцияПриемник;
КонецФункции
Функция СписокБазПользователяОСЛкс(Знач ПолноеИмяФайла = Неопределено, ВычислятьРазмерыКаталогов = Ложь, ВычислятьПоследнегоПользователя = Ложь, ТаблицаПриемник = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если ТаблицаПриемник = Неопределено Тогда
Результат = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирБазыПользователяОС").БазыПользователя.ВыгрузитьКолонки();
Иначе
Результат = ТаблицаПриемник;
КонецЕсли;
Если ПолноеИмяФайла = Неопределено Тогда
лПолноеИмяФайла = ИмяФайлаОбщегоСпискаИнфобазВсехПользователейОСЛкс();
Если ЗначениеЗаполнено(лПолноеИмяФайла) Тогда
СписокБазПользователяОСЛкс(лПолноеИмяФайла,,, Результат);
КонецЕсли;
лПолноеИмяФайла = ИмяФайлаОбщегоСпискаИнфобазТекущегоПользователяОСЛкс();
Если ЗначениеЗаполнено(лПолноеИмяФайла) Тогда
СписокБазПользователяОСЛкс(лПолноеИмяФайла,,, Результат);
КонецЕсли;
ПолноеИмяФайла = ИмяФайлаСпискаИнфобазПользователяОСЛкс();
КонецЕсли;
Если ЛиИдентификацияБазыВСпискеПоИмениЛкс() Тогда
КолонкаСтрокаСоединения = Неопределено;
Иначе
КолонкаСтрокаСоединения = Результат.Колонки.СтрокаСоединения;
КонецЕсли;
Файл = Новый Файл(ПолноеИмяФайла);
ДобавленныеСтроки = Новый Массив;
Если Файл.Существует() Тогда
ЧтениеФайла = Новый ЧтениеТекста;
Попытка
ЧтениеФайла.Открыть(Файл.ПолноеИмя, КодировкаТекста.UTF8);
СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку();
Исключение
// Файл существует, но недоступен http://www.hostedredmine.com/issues/882846
ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
СтрокаИзФайла = Неопределено;
КонецПопытки;
Пока СтрокаИзФайла <> Неопределено Цикл
Если СтрДлина(СокрЛП(СтрокаИзФайла)) Тогда
ТекущаяСтрока = СокрЛП(СтрокаИзФайла);
Если Лев(ТекущаяСтрока, 1) = "[" Тогда
НовоеИмя = Сред(ТекущаяСтрока, 2, СтрДлина(ТекущаяСтрока) - 2); // Убираем квадратные скобки вначале и вконце
//Если КолонкаСтрокаСоединения = Неопределено Тогда
// // Контроль дублей по имени между списками
// НоваяСтрока = Результат.Найти(НРег(НовоеИмя), "КлючСтроки");
// Если Истина
// И НоваяСтрока <> Неопределено
// И НоваяСтрока.ФайлСписка = Файл.ПолноеИмя
// Тогда
// НоваяСтрока = Неопределено;
// СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку();
// Продолжить;
// КонецЕсли;
//КонецЕсли;
НоваяСтрока = Результат.Добавить();
НоваяСтрока.ФайлСписка = Файл.ПолноеИмя;
НоваяСтрока.ИмяВСписке = НовоеИмя;
ДобавленныеСтроки.Добавить(НоваяСтрока);
КонецЕсли;
ИмяКолонки = ПервыйФрагментЛкс(ТекущаяСтрока, "=", Ложь);
Если НоваяСтрока <> Неопределено И ЗначениеЗаполнено(ИмяКолонки) Тогда
Колонка = Результат.Колонки.Найти(ИмяКолонки);
Если Колонка <> Неопределено Тогда
ПредставлениеЗначения = Сред(ТекущаяСтрока, СтрДлина(ИмяКолонки + "=") + 1);
ЗначениеПараметра = Колонка.ТипЗначения.ПривестиЗначение(ПредставлениеЗначения);
НоваяСтрока[Колонка.Имя] = ЗначениеПараметра;
Если Колонка = КолонкаСтрокаСоединения Тогда
// Контроль дублей по строке соединения между списками
СуществующаяСтрока = Результат.Найти(НРег(ЗначениеПараметра), "КлючСтроки");
Если СуществующаяСтрока <> Неопределено Тогда
Результат.Удалить(НоваяСтрока);
ДобавленныеСтроки.Удалить(ДобавленныеСтроки.ВГраница());
НоваяСтрока = Неопределено;
СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку();
Продолжить;
КонецЕсли;
КонецЕсли;
Иначе
Пустышка = 0; // Для отладки
КонецЕсли;
КонецЕсли;
КонецЕсли;
СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку();
КонецЦикла;
КонецЕсли;
Разделитель = РазделительПутиКФайлуЛкс();
#Если Сервер И Не Сервер Тогда
ДобавленныеСтроки = Результат;
#КонецЕсли
ДобавитьИндексВТаблицуЛкс(Результат, "ID");
ДобавитьИндексВТаблицуЛкс(Результат, "ИмяВСписке");
Для Каждого СтрокаТЧ Из ДобавленныеСтроки Цикл
ЗамещаемаяСтрока = Результат.Найти(СтрокаТЧ.ID, "ID");
Если ЗамещаемаяСтрока <> СтрокаТЧ Тогда
// Удаляем дубли по идентификатору между списками
Результат.Удалить(ЗамещаемаяСтрока);
КонецЕсли;
ЗамещаемаяСтрока = Результат.Найти(СтрокаТЧ.ИмяВСписке, "ИмяВСписке");
Если ЗамещаемаяСтрока <> СтрокаТЧ Тогда
// Удаляем дубли по имени между списками
Результат.Удалить(ЗамещаемаяСтрока);
КонецЕсли;
ИзданиеПлатформы = СтрЗаменить(Лев(СтрокаТЧ.Version, 3), ".", "");
// Мультиметка250121_234547
СтрокаТЧ.ВерсияПлатформы = СтрокаТЧ.Version;
СтрокаТЧ.Идентификатор = СтрокаТЧ.ID;
СтрокаТЧ.СтрокаСоединения = СтрокаТЧ.Connect;
СтрокаТЧ.НСтрокаСоединения = НРег(СтрокаТЧ.СтрокаСоединения);
Если ЛиИдентификацияБазыВСпискеПоИмениЛкс() Тогда
СтрокаТЧ.КлючСтроки = НРег(СтрокаТЧ.ИмяВСписке);
Иначе
СтрокаТЧ.КлючСтроки = НРег(СтрокаТЧ.СтрокаСоединения);
КонецЕсли;
Если ПустаяСтрока(СтрокаТЧ.ID) Тогда
Продолжить;
КонецЕсли;
СтрокаТЧ.КаталогКэша = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(, ИзданиеПлатформы) + Разделитель + СтрокаТЧ.ID;
СтрокаТЧ.КаталогНастроек = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(Ложь, ИзданиеПлатформы) + Разделитель + СтрокаТЧ.ID;
//СтрокаСоединенияКластера = НСтр(СтрокаТЧ.СтрокаСоединения, "Srvr");
//СтруктураURI = СтруктураURIЛкс(СтрокаСоединенияКластера); // Здесь может быть строка одновременно нескольких кластеров - tcp://rocket:1541,tcp://rocket1:1741
//СтрокаТЧ.ИмяКомпьютера = ПервыйФрагментЛкс(СтруктураURI.ИмяСервера, ":");
Если ВычислятьПоследнегоПользователя Тогда
ИмяФайлаПоследнегоПользователя = СтрокаТЧ.КаталогНастроек + Разделитель + "def.usr";
ФайлПоследнегоПользователя = Новый Файл(ИмяФайлаПоследнегоПользователя);
Если ФайлПоследнегоПользователя.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ФайлПоследнегоПользователя.ПолноеИмя);
СтрокаТЧ.ПоследнийПользователь = ТекстМеждуМаркерамиЛкс(ТекстовыйДокумент.ПолучитьТекст(), "{""", """}");
КонецЕсли;
КонецЕсли;
Если ВычислятьРазмерыКаталогов Тогда
СтрокаТЧ.РазмерКэшаКБ = ВычислитьРазмерКаталогаЛкс(СтрокаТЧ.КаталогКэша) / 1024;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ЛиИдентификацияБазыВСпискеПоИмениЛкс() Экспорт
Результат = ирКэш.НомерВерсииПлатформыЛкс() > 803000;
Возврат Результат;
КонецФункции
Функция КлючБазыВСпискеПользователяЛкс(выхКлючомЯвляетсяСтрокаСоединения = Ложь) Экспорт
выхКлючомЯвляетсяСтрокаСоединения = Не ЛиИдентификацияБазыВСпискеПоИмениЛкс();
КлючБазыВСпискеПользователя = ирКэш.КлючБазыВСпискеПользователяИзКоманднойСтрокиЛкс();
Если Не ЗначениеЗаполнено(КлючБазыВСпискеПользователя) Тогда
КлючБазыВСпискеПользователя = СтрокаСоединенияИнформационнойБазы();
выхКлючомЯвляетсяСтрокаСоединения = Истина;
КонецЕсли;
Возврат КлючБазыВСпискеПользователя;
КонецФункции
Функция ИмяФайлаОбщегоСпискаИнфобазТекущегоПользователяОСЛкс(выхИмяКонфигФайла = "") Экспорт
выхИмяКонфигФайла = ирКэш.КаталогПлатформыВПрофилеЛкс(Ложь) + СтрЗаменить("\1cestart\1cestart.cfg", "\", РазделительПутиКФайлуЛкс());
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(выхИмяКонфигФайла);
СписокИмен = "";
Для Счетчик = 1 По СтрЧислоСтрок(Текст.ПолучитьТекст()) Цикл
СтрокаТекста = СокрЛ(Текст.ПолучитьСтроку(Счетчик));
Если Найти(СтрокаТекста, "CommonInfoBases") = 1 Тогда
Результат = Сред(СтрокаТекста, Найти(СтрокаТекста, "=") + 1);
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ИмяФайлаОбщегоСпискаИнфобазВсехПользователейОСЛкс(ИмяКонфигФайла = "") Экспорт
Если Не ирКэш.ЛиПлатформаWindowsЛкс() Тогда
Возврат Неопределено;
Иначе
ПриложениеОболочкиОС = Новый COMobject("Shell.Application");
КаталогОбщихНастроек = ПриложениеОболочкиОС.NameSpace(35).Self.Path;
КонецЕсли;
ИмяКонфигФайла = КаталогОбщихНастроек + СтрЗаменить("\1C\1cestart\1cestart.cfg", "\", РазделительПутиКФайлуЛкс());
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяКонфигФайла);
СписокИмен = "";
Для Счетчик = 1 По СтрЧислоСтрок(Текст.ПолучитьТекст()) Цикл
СтрокаТекста = СокрЛ(Текст.ПолучитьСтроку(Счетчик));
Если Найти(СтрокаТекста, "CommonInfoBases") = 1 Тогда
Результат = Сред(СтрокаТекста, Найти(СтрокаТекста, "=") + 1);
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Получает строку для установки порядка. Пример "Контрагент убыв, Номенклатура.Код возр".
//
// Параметры:
// Порядок - Порядок.
//
// Возвращаемое значение:
// Строка - для установки порядка.
//
Функция ПорядокВСтрокуЛкс(Порядок) Экспорт
Строка = "";
Для Каждого ЭлементПорядка Из Порядок Цикл
Строка = Строка + ", " + ЭлементПорядка.ПутьКДанным + " ";
Если ЭлементПорядка.Направление = НаправлениеСортировки.Возр Тогда
Строка = Строка + "возр";
Иначе
Строка = Строка + "убыв";
КонецЕсли;
КонецЦикла;
Возврат Сред(Строка, 2);
КонецФункции
// Выполняет текст на внутреннем языке. Применяется для безопасного выполнения произвольного кода.
// Безопасность заключается в том, что нет свойств локального контекста
// и недоступны доопределенные Свойства глобального контекста.
//
// Параметры:
// ТекстДляВыполнения - Строка;
// *ЛиСинтаксическийКонтроль - Булево, *Ложь - признак вызова только для синтаксического контроля.
//
Процедура ВыполнитьВКонтекстеОбщегоМодуляЛкс(ТекстДляВыполнения, ЛиСинтаксическийКонтроль = Ложь) Экспорт
Выполнить(ТекстДляВыполнения);
КонецПроцедуры
// Получает копию произвольного объекта. Копирование производится через сериализацию.
//
// Параметры:
// пОбъект - Произвольный - сохраняемое значение;
// ИспользоватьXDTO - Булево - выполнять через ОбъектXDTO, для типов компоновки данных работает быстрее в 2 раза, но не у всех типов есть XDTO отображение, позволяет обходить платформенные ошибки десериализации компоновки
// Истина - не делает глубокого копирования! Применять в основном имеет смысл только для объектов системы компоновки данных
//
// Возвращаемое значение:
// Произвольный - копия объекта.
//
Функция КопияОбъектаЛкс(пОбъект, ИспользоватьXDTO = Ложь) Экспорт
Если ИспользоватьXDTO Тогда
// Быстрее в 2 раза
Попытка
НовыйОбъект = СериализаторXDTO.ПрочитатьXDTO(СериализаторXDTO.ЗаписатьXDTO(пОбъект));
Исключение
// 7ы78аывраы0ав8
// https://partners.v8.1c.ru/forum/t/1918496/m/1918496
// Антибаг платформы 8.3.17-+ В настройках компоновки в элементах отбора с видом сравнения "ВСписке" в правых значениях поля компоновки при десериализации возникает ошибка.
// Чтобы ее обойти оборачиваем каждое такое поле в массив
СтрокаХмл = ОбъектВСтрокуXMLЛкс(пОбъект);
ДокументДом = ТекстВДокументDOMЛкс(СтрокаХмл);
#Если Сервер И Не Сервер Тогда
ДокументДом = Новый ДокументDOM;
#КонецЕсли
РазыменовательПИ = Новый РазыменовательПространствИменDOM("w", "http://v8.1c.ru/8.1/data-composition-system/settings");
РезультатХПути = ДокументДом.ВычислитьВыражениеXPath("//w:comparisonType[text()='InList' or text()='NotInList']/following-sibling::w:right[@xsi:type='dcscor:Field']", ДокументДом,
РазыменовательПИ, ТипРезультатаDOMXPath.НеупорядоченныйИтераторУзлов);
Пока Истина Цикл
УзелПравогоЗначенияОтбора = РезультатХПути.ПолучитьСледующий();
Если УзелПравогоЗначенияОтбора = Неопределено Тогда
Прервать;
КонецЕсли;
ПрефиксЯдра = УзелПравогоЗначенияОтбора.НайтиПрефикс("http://v8.1c.ru/8.1/data/core");
ПрефиксТипов = УзелПравогоЗначенияОтбора.НайтиПрефикс("http://www.w3.org/2001/XMLSchema-instance");
ПрефиксКомпоновки = УзелПравогоЗначенияОтбора.НайтиПрефикс("http://v8.1c.ru/8.1/data-composition-system/core");
НовыйВложенныйУзел = ДокументДом.СоздатьЭлемент("http://v8.1c.ru/8.1/data/core", ПрефиксЯдра + ":Value");
НовыйВложенныйУзел.УстановитьАтрибут("http://www.w3.org/2001/XMLSchema-instance", ПрефиксТипов + ":type", ПрефиксКомпоновки + ":Field");
НовыйВложенныйУзел.ТекстовоеСодержимое = УзелПравогоЗначенияОтбора.ПервыйДочерний.ТекстовоеСодержимое;
УзелПравогоЗначенияОтбора.УдалитьДочерний(УзелПравогоЗначенияОтбора.ПервыйДочерний);
УзелПравогоЗначенияОтбора.УдалитьУзелАтрибута(УзелПравогоЗначенияОтбора.Атрибуты[0]);
УзелПравогоЗначенияОтбора.ДобавитьДочерний(НовыйВложенныйУзел);
УзелПравогоЗначенияОтбора.УстановитьАтрибут("http://www.w3.org/2001/XMLSchema-instance", ПрефиксТипов + ":type", ПрефиксЯдра + ":Array");
КонецЦикла;
СтрокаХМЛ = ДокументDOMВСтрокуЛкс(ДокументДом);
НовыйОбъект = ОбъектИзСтрокиXMLЛкс(СтрокаХМЛ);
КонецПопытки;
Иначе
НовыйОбъект = ЗначениеИзСтрокиВнутрЛкс(ЗначениеВСтрокуВнутр(пОбъект));
КонецЕсли;
Возврат НовыйОбъект;
КонецФункции
Процедура ВосстановитьОтборыКомпоновкиПослеДесериализацииЛкс(Знач НастройкаИлиГруппаОтбора) Экспорт
Если ТипЗнч(НастройкаИлиГруппаОтбора) = Тип("НастройкиКомпоновкиДанных") Тогда
#Если Сервер И Не Сервер Тогда
НастройкаИлиГруппаОтбора = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
ГруппаОтбора = НастройкаИлиГруппаОтбора.Отбор;
Иначе
ГруппаОтбора = НастройкаИлиГруппаОтбора;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ГруппаОтбора = Новый НастройкиКомпоновкиДанных;
ГруппаОтбора = НастройкаИлиГруппаОтбора.Отбор;
#КонецЕсли
// https://partners.v8.1c.ru/forum/t/1623191/m/1623191
Для Каждого ЭлементОтбора Из ГруппаОтбора.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
ВосстановитьОтборыКомпоновкиПослеДесериализацииЛкс(ЭлементОтбора);
Продолжить;
КонецЕсли;
Если ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("Массив") Тогда
МассивЗначенияОтбора = ЭлементОтбора.ПравоеЗначение;
ИначеЕсли Истина
И ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("СписокЗначений")
И ЭлементОтбора.ПравоеЗначение.Количество() = 1
И ТипЗнч(ЭлементОтбора.ПравоеЗначение[0].Значение) = Тип("Массив")
Тогда
МассивЗначенияОтбора = ЭлементОтбора.ПравоеЗначение[0].Значение;
Иначе
МассивЗначенияОтбора = Неопределено;
КонецЕсли;
Если МассивЗначенияОтбора <> Неопределено Тогда
СписокЗначений = Новый СписокЗначений;
Для Каждого ЭлементМассива Из МассивЗначенияОтбора Цикл
Если ТипЗнч(ЭлементМассива) = Тип("ПолеКомпоновкиДанных") Тогда
// 7ы78аывраы0ав8
// https://partners.v8.1c.ru/forum/t/1918496/m/1918496
СписокЗначений = ЭлементМассива;
Прервать;
КонецЕсли;
СписокЗначений.Добавить(ЭлементМассива);
КонецЦикла;
ЭлементОтбора.ПравоеЗначение = СписокЗначений;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Находит элемент коллекции по свойству "ПутьКДанным".
//
// Параметры:
// пКоллекция - Коллекция - все элементы которой имеют свойство "ПутьКДанным";
// пПутьКДанным - Строка - искомое значение.
//
// Возвращаемое значение:
// - ЭлементКоллекции;
// Неопределено - не найден.
//
Функция НайтиЭлементКоллекцииПоПутиКДаннымЛкс(пКоллекция, пПутьКДанным) Экспорт
СуществующаяСтрока = Неопределено;
Для Каждого ЭлементКоллеции Из пКоллекция Цикл
Если ЭлементКоллеции.ПутьКДанным = пПутьКДанным Тогда
СуществующаяСтрока = ЭлементКоллеции;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат СуществующаяСтрока;
КонецФункции
// Находит поле настройки по пути к данным.
//
// Параметры:
// пПоляНастройки - ПоляНастройки;
// пПутьКДанным - Строка - путь к данным поля в виде разыменовывания;
// *пПутьКТекущемуПолю - Строка, "" - путь к текущему полю.
//
// Возвращаемое значение:
// ПолеНастройки - найденное поле;
// Неопределено - иначе.
//
Функция НайтиПолеНастройкиПоПутиКДаннымЛкс(пПоляНастройки, пПутьКДанным, пПутьКТекущемуПолю = "") Экспорт
ПоляНастройки = пПоляНастройки;
МассивФрагментов = СтрРазделитьЛкс(пПутьКДанным);
ТекущееПоле = Неопределено;
Для Каждого Фрагмент Из МассивФрагментов Цикл
пПутьКТекущемуПолю = пПутьКТекущемуПолю + ?(пПутьКТекущемуПолю = "", "", ".") + Фрагмент;
ТекущееПоле = НайтиЭлементКоллекцииПоПутиКДаннымЛкс(ПоляНастройки, пПутьКТекущемуПолю);
Если ТекущееПоле = Неопределено Тогда
Прервать;
КонецЕсли;
ПоляНастройки = ТекущееПоле.Поля;
КонецЦикла;
Возврат ТекущееПоле;
КонецФункции // НайтиПолеНастройкиПоПутиКДаннымЛкс()
// Копирует один элемент отбора в другой. Если Использование = Ложь, то копируется только оно.
//
// Параметры:
// пЭлементОтбораПриемник - ЭлементОтбора - куда копируем;
// пЭлементОтбораИсточник - ЭлементОтбора - откуда копируем.
//
Процедура СкопироватьЭлементОтбораЛкс(пЭлементОтбораПриемник, пЭлементОтбораИсточник) Экспорт
ЗаполнитьЗначенияСвойств(пЭлементОтбораПриемник, пЭлементОтбораИсточник, "Представление, Использование");
МассивСвойствЭлементаОтбора = Новый Массив;
МассивСвойствЭлементаОтбора.Добавить("ВидСравнения");
МассивСвойствЭлементаОтбора.Добавить("Значение");
МассивСвойствЭлементаОтбора.Добавить("ЗначениеС");
МассивСвойствЭлементаОтбора.Добавить("ЗначениеПо");
Для Каждого Свойство Из МассивСвойствЭлементаОтбора Цикл
Значение = пЭлементОтбораИсточник[Свойство];
Если пЭлементОтбораПриемник[Свойство] <> Значение Тогда
пЭлементОтбораПриемник[Свойство] = Значение;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ТрансформироватьОтборВОтборКомпоновкиЛкс(Знач ОтборКомпоновкиДанных, Знач ЭлементыОтбора, Знач СоответствиеИмен = Неопределено,
Знач ПропускатьНедоступныеПоля = Ложь, Знач ДоступныеПоляОтбора = Неопределено, ТолькоИспользуемые = Истина, ОчищатьПриемник = Истина, Знач ИгнорироватьЭлементы = "") Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый НастройкиКомпоновкиДанных;
ОтборКомпоновкиДанных = Пустышка.Отбор;
#КонецЕсли
Если СоответствиеИмен = Неопределено Тогда
СоответствиеИмен = Новый ТаблицаЗначений();
СоответствиеИмен.Колонки.Добавить("Источник");
СоответствиеИмен.Колонки.Добавить("Приемник");
КонецЕсли;
Если ДоступныеПоляОтбора = Неопределено Тогда
ДоступныеПоляОтбора = ОтборКомпоновкиДанных.ДоступныеПоляОтбора;
КонецЕсли;
Если ОчищатьПриемник Тогда
ОтборКомпоновкиДанных.Элементы.Очистить();
КонецЕсли;
Если ЗначениеЗаполнено(ИгнорироватьЭлементы) Тогда
ИгнорироватьСтруктура = Новый Структура(ИгнорироватьЭлементы);
Иначе
ИгнорироватьСтруктура = Новый Структура;
КонецЕсли;
ИндексГраницы = ЭлементыОтбора.Количество() - 1;
ИзмененныеЭлементыОтбора = Новый Массив;
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл
Если Истина
И ТолькоИспользуемые
И Не ЭлементОтбора.Использование
Тогда
Продолжить;
КонецЕсли;
Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
ПриемникОтбора = ОтборКомпоновкиДанных.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ЗаполнитьЗначенияСвойств(ПриемникОтбора, ЭлементОтбора);
ТрансформироватьОтборВОтборКомпоновкиЛкс(ПриемникОтбора, ЭлементОтбора.Элементы, СоответствиеИмен, ПропускатьНедоступныеПоля, ДоступныеПоляОтбора, ТолькоИспользуемые);
Продолжить;
КонецЕсли;
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если ТипЗнч(ЭлементОтбора.ЛевоеЗначение) <> Тип("ПолеКомпоновкиДанных") Тогда
Продолжить;
КонецЕсли;
ПутьКДаннымЛевый = "" + ЭлементОтбора.ЛевоеЗначение;
ПутьКДаннымПравый = Неопределено;
Если ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("ПолеКомпоновкиДанных") Тогда
ПутьКДаннымПравый = "" + ЭлементОтбора.ПравоеЗначение;
Иначе
ПравоеЗначение = ЭлементОтбора.ПравоеЗначение;
КонецЕсли;
Иначе
ПутьКДаннымЛевый = ЭлементОтбора.ПутьКДанным;
ПутьКДаннымПравый = Неопределено;
ПравоеЗначение = ЭлементОтбора.Значение;
Если Истина
И Найти(ПутьКДаннымЛевый, " ") = 0 // Антибаг платформы 8.3.18 В динамическом списке обычной формы регистра бухгалтерии есть "Валюта Кор" https://www.hostedredmine.com/issues/936315
И ИгнорироватьСтруктура.Свойство(ПутьКДаннымЛевый)
Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
//Если ПутьКДаннымЛевый <> Неопределено Тогда
МассивФрагментов = СтрРазделитьЛкс(ПутьКДаннымЛевый);
СтрокаИсточника = СоответствиеИмен.Найти(НРег(МассивФрагментов[0]), "Источник");
Если СтрокаИсточника <> Неопределено Тогда
МассивФрагментов[0] = СтрокаИсточника.Приемник;
КонецЕсли;
ПутьКДанным = СтрСоединитьЛкс(МассивФрагментов, ".");
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
лВидСравнения = ЭлементОтбора.ВидСравнения;
Иначе
//! ЭлементОтбора = 0 //ЭлементОтбора
СтрокаВидаСравнения = мПлатформа.СоответствиеВидовСравнения.Найти(ЭлементОтбора.ВидСравнения, "Построитель");
Если СтрокаВидаСравнения = Неопределено Тогда
Если ЭлементОтбора.ВидСравнения = ВидСравнения.Интервал Тогда
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеС, ВидСравненияКомпоновкиДанных.Больше,, Ложь, ЭлементОтбора.Использование);
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеПо, ВидСравненияКомпоновкиДанных.Меньше,, Ложь, ЭлементОтбора.Использование);
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравнения.ИнтервалВключаяГраницы Тогда
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеС, ВидСравненияКомпоновкиДанных.БольшеИлиРавно,, Ложь, ЭлементОтбора.Использование);
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеПо, ВидСравненияКомпоновкиДанных.МеньшеИлиРавно,, Ложь, ЭлементОтбора.Использование);
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравнения.ИнтервалВключаяНачало Тогда
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеС, ВидСравненияКомпоновкиДанных.БольшеИлиРавно,, Ложь, ЭлементОтбора.Использование);
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеПо, ВидСравненияКомпоновкиДанных.Меньше,, Ложь, ЭлементОтбора.Использование);
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравнения.ИнтервалВключаяОкончание Тогда
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеС, ВидСравненияКомпоновкиДанных.Больше,, Ложь, ЭлементОтбора.Использование);
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборКомпоновкиДанных.Элементы, ПутьКДанным, ЭлементОтбора.ЗначениеПо, ВидСравненияКомпоновкиДанных.МеньшеИлиРавно,, Ложь, ЭлементОтбора.Использование);
КонецЕсли;
Продолжить;
КонецЕсли;
лВидСравнения = СтрокаВидаСравнения.Компоновка;
КонецЕсли;
ПолеКомпоновки = Новый ПолеКомпоновкиДанных(ПутьКДанным);
ЭлементОтбораПриемник = Неопределено;
Для Каждого ЭлементОтбораЦикл Из ОтборКомпоновкиДанных.Элементы Цикл
Если Истина
И ТипЗнч(ЭлементОтбораЦикл) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбораЦикл.ЛевоеЗначение = ПолеКомпоновки
И ИзмененныеЭлементыОтбора.Найти(ЭлементОтбораЦикл) = Неопределено
Тогда
ЭлементОтбораПриемник = ЭлементОтбораЦикл;
ИзмененныеЭлементыОтбора.Добавить(ЭлементОтбораПриемник);
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭлементОтбораПриемник = Неопределено Тогда
ДоступноеПоле = ДоступныеПоляОтбора.НайтиПоле(ПолеКомпоновки);
Если Истина
И ПропускатьНедоступныеПоля
И ДоступноеПоле = Неопределено
Тогда
Продолжить;
КонецЕсли;
ЭлементОтбораПриемник = ОтборКомпоновкиДанных.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбораПриемник.ЛевоеЗначение = ПолеКомпоновки;
КонецЕсли;
//Иначе
// ПолеОтбора.ПравоеЗначение = ЛевоеЗначение;
//КонецЕсли;
Если ПутьКДаннымПравый <> Неопределено Тогда
МассивФрагментов = СтрРазделитьЛкс(ПутьКДаннымПравый);
СтрокаИсточника = СоответствиеИмен.Найти(НРег(МассивФрагментов[0]), "Источник");
Если СтрокаИсточника <> Неопределено Тогда
МассивФрагментов[0] = СтрокаИсточника.Приемник;
КонецЕсли;
ПутьКДанным = СтрСоединитьЛкс(МассивФрагментов, ".");
ПолеКомпоновки = Новый ПолеКомпоновкиДанных(ПутьКДанным);
ЭлементОтбораПриемник.ПравоеЗначение = ПолеКомпоновки;
Иначе
ЭлементОтбораПриемник.ПравоеЗначение = ПравоеЗначение;
КонецЕсли;
ЭлементОтбораПриемник.ВидСравнения = лВидСравнения;
ЭлементОтбораПриемник.Использование = ЭлементОтбора.Использование;
ПроверитьВключитьЭлементНастроекКомпоновкиВПользовательскиеНастройки(ЭлементОтбораПриемник);
КонецЦикла;
КонецФункции
// Порт СкопироватьОтборЛкс.
Процедура СкопироватьОтборЛюбойЛкс(ОтборПриемник, ОтборИсточник, ТолькоИспользуемые = Ложь, ПропускатьНедоступныеПоля = Ложь, ОчищатьПриемник = Истина, ИмяБазовогоПоля = "",
Знач ИгнорироватьЭлементы = "") Экспорт
Если Истина
И ТипЗнч(ОтборИсточник) = Тип("Отбор")
И ТипЗнч(ОтборПриемник) = Тип("Отбор")
Тогда
СкопироватьОтборПостроителяЛкс(ОтборПриемник, ОтборИсточник, , ТолькоИспользуемые, ОчищатьПриемник);
ИначеЕсли Истина
И ТипЗнч(ОтборИсточник) = Тип("Структура")
И ТипЗнч(ОтборПриемник) = Тип("Отбор")
Тогда
Для Каждого КлючИЗначение Из ОтборИсточник Цикл
ИмяПоляПриемника = КлючИЗначение.Ключ;
ЭлементОтбора = ОтборПриемник.Найти(КлючИЗначение.Ключ);
Если ЭлементОтбора <> Неопределено Тогда
УстановитьЭлементОтбораЛкс(ЭлементОтбора,, КлючИЗначение.Значение);
КонецЕсли;
КонецЦикла;
ИначеЕсли Истина
И ТипЗнч(ОтборИсточник) = Тип("ОтборКомпоновкиДанных")
И ТипЗнч(ОтборПриемник) = Тип("ОтборКомпоновкиДанных")
Тогда
СкопироватьЭлементыКомпоновкиЛкс(ОтборПриемник, ОтборИсточник, ОчищатьПриемник,,,, ТолькоИспользуемые);
ИначеЕсли Истина
И ТипЗнч(ОтборИсточник) = Тип("Структура")
И ТипЗнч(ОтборПриемник) = Тип("ОтборКомпоновкиДанных")
Тогда
#Если Сервер И Не Сервер Тогда
ОтборПриемник = Новый НастройкиКомпоновкиДанных;
ОтборПриемник = ОтборПриемник.Отбор;
#КонецЕсли
Для Каждого КлючИЗначение Из ОтборИсточник Цикл
ИмяПоляПриемника = КлючИЗначение.Ключ;
Если ЗначениеЗаполнено(ИмяБазовогоПоля) Тогда
ИмяПоляПриемника = ИмяБазовогоПоля + "." + ИмяПоляПриемника;
КонецЕсли;
Если Истина
И ПропускатьНедоступныеПоля
И ОтборПриемник.ДоступныеПоляОтбора.НайтиПоле(Новый ПолеКомпоновкиДанных(ИмяПоляПриемника)) = Неопределено
Тогда
Продолжить;
КонецЕсли;
ЭлементОтбора = НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ОтборПриемник, ИмяПоляПриемника, КлючИЗначение.Значение);
#Если Сервер И Не Сервер Тогда
ЭлементОтбора = Новый НастройкиКомпоновкиДанных;
ЭлементОтбора = ЭлементОтбора.Отбор.Элементы.Добавить();
#КонецЕсли
ЭлементОтбора.Использование = Истина;
ПроверитьВключитьЭлементНастроекКомпоновкиВПользовательскиеНастройки(ЭлементОтбора);
КонецЦикла;
ИначеЕсли Истина
И ТипЗнч(ОтборИсточник) = Тип("Отбор")
И ТипЗнч(ОтборПриемник) = Тип("ОтборКомпоновкиДанных")
Тогда
ТрансформироватьОтборВОтборКомпоновкиЛкс(ОтборПриемник, ОтборИсточник,, ПропускатьНедоступныеПоля,, ТолькоИспользуемые, ОчищатьПриемник, ИгнорироватьЭлементы);
ИначеЕсли Истина
И ТипЗнч(ОтборИсточник) = Тип("ОтборКомпоновкиДанных")
И ТипЗнч(ОтборПриемник) = Тип("Отбор")
Тогда
#Если Сервер И Не Сервер Тогда
ОтборИсточник = Новый НастройкиКомпоновкиДанных;
ОтборИсточник = ОтборИсточник.Отбор;
#КонецЕсли
Если ОчищатьПриемник Тогда
ОтборПриемник.Сбросить();
КонецЕсли;
Для Каждого ЭлементОтбораИсточник Из ОтборИсточник.Элементы Цикл
Если Истина
И ТипЗнч(ЭлементОтбораИсточник) = Тип("ЭлементОтбораКомпоновкиДанных")
И (ТолькоИспользуемые Или ЭлементОтбораИсточник.Использование)
Тогда
ЭлементОтбораПриемник = ОтборПриемник.Найти("" + ЭлементОтбораИсточник.ЛевоеЗначение);
Если ЭлементОтбораПриемник <> Неопределено Тогда
ИмяВидаСравнения = СтрЗаменитьЛкс(ПолучитьПолноеИмяПредопределенногоЗначения(ЭлементОтбораИсточник.ВидСравнения), "ВидСравненияКомпоновкиДанных", "ВидСравнения");
Попытка
ВидСравненияОтбора = ПредопределенноеЗначение(ИмяВидаСравнения);
Исключение
Продолжить;
КонецПопытки;
ЭлементОтбораПриемник.Использование = ЭлементОтбораИсточник.Использование;
ЭлементОтбораПриемник.ВидСравнения = ВидСравненияОтбора;
ЭлементОтбораПриемник.Значение = ЭлементОтбораИсточник.ПравоеЗначение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Иначе
ВызватьИсключение "Недопустимые типы параметров 1, 2";
КонецЕсли;
КонецПроцедуры
// Важно: установка идентификатора должна выполняться в конце настройки элемента,
// иначе он будет скопирован в пользовательские настройки частично заполненным.
Процедура ПроверитьВключитьЭлементНастроекКомпоновкиВПользовательскиеНастройки(Знач ЭлементНастроек, Знач ИдентификаторНастройки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый НастройкиКомпоновкиДанных;
ЭлементНастроек = Пустышка.Отбор;
#КонецЕсли
Если ЗначениеЗаполнено(ЭлементНастроек.ИдентификаторПользовательскойНастройки) Тогда
Возврат;
КонецЕсли;
//Представление = "" + ЭлементНастроек;
Если ТипЗнч(ЭлементНастроек) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
//Если ЗначениеЗаполнено(ЭлементНастроек.Представление) Тогда
// Представление = ЭлементНастроек.Представление;
//Иначе
// Представление = ЭлементНастроек.ЛевоеЗначение;
//КонецЕсли;
Если Не ЗначениеЗаполнено(ИдентификаторНастройки) Тогда
ИдентификаторНастройки = "" + ЭлементНастроек.ЛевоеЗначение;
КонецЕсли;
Иначе
Если Не ЗначениеЗаполнено(ИдентификаторНастройки) Тогда
Попытка
ИдентификаторНастройки = "" + ЭлементНастроек.Поле;
Исключение
КонецПопытки;
КонецЕсли;
КонецЕсли;
//Попытка
// ЭлементНастроек.ПредставлениеПользовательскойНастройки = Представление;
//Исключение
// // Это ОтборКомпоновкиДанных внутри пользовательских настроек
//КонецПопытки;
Если Не ЗначениеЗаполнено(ИдентификаторНастройки) Тогда
ИдентификаторНастройки = Новый УникальныйИдентификатор;
КонецЕсли;
ЭлементНастроек.ИдентификаторПользовательскойНастройки = ИдентификаторНастройки;
КонецПроцедуры
// Копирует элементы из одной коллекции компоновки в другую коллекцию того же типа
//
// Параметры:
// ПриемникЗначения - УсловноеОформлениеКомпоновкиДанных, ВариантыПользовательскогоПоляВыборКомпоновкиДанных, ОформляемыеПоляКомпоновкиДанных, ЗначенияПараметровДанныхКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных, ОтборКомпоновкиДанных, ПорядокКомпоновкиДанных, ПоляГруппировкиКомпоновкиДанных -
// ИсточникЗначения - УсловноеОформлениеКомпоновкиДанных, ВариантыПользовательскогоПоляВыборКомпоновкиДанных, ОформляемыеПоляКомпоновкиДанных, ЗначенияПараметровДанныхКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных, ОтборКомпоновкиДанных, ПорядокКомпоновкиДанных, ПоляГруппировкиКомпоновкиДанных - тип соответствует приемнику
// ОчищатьПриемник - -
// ЭлементыДляКопирования - -
// ТабличноеПолеПриемник - -
// выхДобавленныеЭлементы - -
// ТолькоИспользуемые - -
//
Процедура СкопироватьЭлементыКомпоновкиЛкс(ПриемникЗначения, ИсточникЗначения, ОчищатьПриемник = Истина, ЭлементыДляКопирования = Неопределено, Знач ТабличноеПолеПриемник = Неопределено,
выхДобавленныеЭлементы = Неопределено, Знач ТолькоИспользуемые = Ложь) Экспорт
//! ИсточникЭлементов = ПриемникЗначения;
Если выхДобавленныеЭлементы = Неопределено Тогда
выхДобавленныеЭлементы = Новый Массив;
КонецЕсли;
Если Ложь
Или ТипЗнч(ИсточникЗначения) = Тип("УсловноеОформлениеКомпоновкиДанных")
ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ВариантыПользовательскогоПоляВыборКомпоновкиДанных")
ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ОформляемыеПоляКомпоновкиДанных")
ИЛИ ТипЗнч(ИсточникЗначения) = Тип("ЗначенияПараметровДанныхКомпоновкиДанных")
Тогда
СоздаватьПоТипу = Ложь;
Иначе
СоздаватьПоТипу = Истина;
КонецЕсли;
ПриемникЭлементов = ПриемникЗначения.Элементы;
ИсточникЭлементов = ИсточникЗначения.Элементы;
Если ОчищатьПриемник Тогда
ПриемникЭлементов.Очистить();
КонецЕсли;
Если ТипЗнч(ТабличноеПолеПриемник) = Тип("ТаблицаФормы") Тогда
Если ТипЗнч(ПриемникЗначения) <> Тип("ОтборКомпоновкиДанных") Тогда
ОтборПриемник = ДанныеЭлементаФормыЛкс(ТабличноеПолеПриемник);
Иначе
ОтборПриемник = ПриемникЗначения;
КонецЕсли;
КонецЕсли;
Для каждого ЭлементИсточник Из ИсточникЭлементов Цикл
Если Истина
И ЭлементыДляКопирования <> Неопределено
И ЭлементыДляКопирования.Найти(ЭлементИсточник) = Неопределено
И ЭлементыДляКопирования.Найти(ИсточникЗначения.ПолучитьИдентификаторПоОбъекту(ЭлементИсточник)) = Неопределено
Тогда
Продолжить;
КонецЕсли;
Если ТолькоИспользуемые И Не ЭлементИсточник.Использование Тогда
Продолжить;
КонецЕсли;
Если ТипЗнч(ЭлементИсточник) = Тип("ЭлементПорядкаКомпоновкиДанных") Тогда
// Элементы порядка добавляем в начало
Индекс = ИсточникЭлементов.Индекс(ЭлементИсточник);
ЭлементПриемник = ПриемникЭлементов.Вставить(Индекс, ТипЗнч(ЭлементИсточник));
Иначе
Если СоздаватьПоТипу Тогда
ЭлементПриемник = ПриемникЭлементов.Добавить(ТипЗнч(ЭлементИсточник));
Иначе
ЭлементПриемник = ПриемникЭлементов.Добавить();
КонецЕсли;
КонецЕсли;
ЗаполнитьЗначенияСвойств(ЭлементПриемник, ЭлементИсточник);
выхДобавленныеЭлементы.Добавить(ЭлементПриемник);
Если ТипЗнч(ТабличноеПолеПриемник) = Тип("ТаблицаФормы") Тогда
ТабличноеПолеПриемник.ВыделенныеСтроки.Добавить(ОтборПриемник.ПолучитьИдентификаторПоОбъекту(ЭлементПриемник));
#Если Клиент Тогда
ИначеЕсли ТипЗнч(ТабличноеПолеПриемник) = Тип("ТабличноеПоле") Тогда
ТабличноеПолеПриемник.ВыделенныеСтроки.Добавить(ЭлементПриемник);
#КонецЕсли
КонецЕсли;
// В некоторых коллекциях необходимо заполнить другие коллекции
Если ТипЗнч(ИсточникЭлементов) = Тип("КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных") Тогда
//! ЭлементИсточник = 0 // ЭлементУсловногоОформленияКомпоновкиДанных
//! ЭлементПриемник = 0 // см. ЭлементИсточник
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник.Поля, ЭлементИсточник.Поля,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник.Отбор, ЭлементИсточник.Отбор,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
ЗаполнитьЭлементыКомпоновкиЛкс(ЭлементПриемник.Оформление, ЭлементИсточник.Оформление);
ИначеЕсли ТипЗнч(ИсточникЭлементов) = Тип("КоллекцияВариантовПользовательскогоПоляВыборКомпоновкиДанных") Тогда
//! ЭлементИсточник = 0 // ВариантПользовательскогоПоляВыборКомпоновкиДанных
//! ЭлементПриемник = 0 // см. ЭлементИсточник
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник.Отбор, ЭлементИсточник.Отбор,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
КонецЕсли;
// В некоторых элементах коллекции необходимо заполнить другие коллекции
Если ТипЗнч(ЭлементИсточник) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник, ЭлементИсточник,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник, ЭлементИсточник,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ПользовательскоеПолеВыборКомпоновкиДанных") Тогда
//! ЭлементПриемник = 0 // см. ЭлементИсточник
СкопироватьЭлементыКомпоновкиЛкс(ЭлементПриемник.Варианты, ЭлементИсточник.Варианты,,, ТабличноеПолеПриемник, выхДобавленныеЭлементы);
ИначеЕсли ТипЗнч(ЭлементИсточник) = Тип("ПользовательскоеПолеВыражениеКомпоновкиДанных") Тогда
//! ЭлементПриемник = 0 // см. ЭлементИсточник
ЭлементПриемник.УстановитьВыражениеДетальныхЗаписей(ЭлементИсточник.ПолучитьВыражениеДетальныхЗаписей());
ЭлементПриемник.УстановитьВыражениеИтоговыхЗаписей(ЭлементИсточник.ПолучитьВыражениеИтоговыхЗаписей());
ЭлементПриемник.УстановитьПредставлениеВыраженияДетальныхЗаписей(ЭлементИсточник.ПолучитьПредставлениеВыраженияДетальныхЗаписей());
ЭлементПриемник.УстановитьПредставлениеВыраженияИтоговыхЗаписей(ЭлементИсточник.ПолучитьПредставлениеВыраженияИтоговыхЗаписей());
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Заполняет элементы одной коллекции из другой
//
Процедура ЗаполнитьЭлементыКомпоновкиЛкс(ПриемникЗначения, ИсточникЗначения, ПервыйУровень = Неопределено) Экспорт
Если ТипЗнч(ПриемникЗначения) = Тип("КоллекцияЗначенийПараметровКомпоновкиДанных") Тогда
КоллекцияЗначений = ИсточникЗначения;
Иначе
КоллекцияЗначений = ИсточникЗначения.Элементы;
КонецЕсли;
Для каждого ЭлементИсточник Из КоллекцияЗначений Цикл
Если ПервыйУровень = Неопределено Тогда
ЭлементПриемник = ПриемникЗначения.НайтиЗначениеПараметра(ЭлементИсточник.Параметр);
Иначе
ЭлементПриемник = ПервыйУровень.НайтиЗначениеПараметра(ЭлементИсточник.Параметр);
КонецЕсли;
Если ЭлементПриемник = Неопределено Тогда
Продолжить;
КонецЕсли;
ЗаполнитьЗначенияСвойств(ЭлементПриемник, ЭлементИсточник);
Если ТипЗнч(ЭлементИсточник) = Тип("ЗначениеПараметраКомпоновкиДанных") Тогда
Если ЭлементИсточник.ЗначенияВложенныхПараметров.Количество() <> 0 Тогда
ЗаполнитьЭлементыКомпоновкиЛкс(ЭлементПриемник.ЗначенияВложенныхПараметров, ЭлементИсточник.ЗначенияВложенныхПараметров, ПриемникЗначения);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Копирует объект Отбор в другой объект Отбор.
// Если нужно, в приемнике создаются отсутствующие элементы отбора.
//
// Параметры:
// пОтборПриемник - Отбор - куда копируем;
// пОтборИсточник - Отбор, Структура - откуда копируем;
// пСоздаватьОтсутствующие - Булево, *Ложь - признак создания отсутствующих элементов отбора в приемнике.
//
Процедура СкопироватьОтборПостроителяЛкс(ОтборПриемник, ОтборИсточник, СоздаватьОтсутствующие = Истина, ТолькоИспользуемые = Ложь, ОчищатьПриемник = Ложь, Знач ЗаменятьСпецсимволыВСодержит = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый ПостроительЗапроса;
ОтборПриемник = Пустышка.Отбор;
#КонецЕсли
Если ОчищатьПриемник Тогда
ОтборПриемник.Сбросить();
КонецЕсли;
//Если пСоздаватьОтсутствующие Тогда
// ДоступныеПоля = пОтборПриемник.ПолучитьДоступныеПоля();
//КонецЕсли;
Для Каждого ЭлементОтбораИсточника Из ОтборИсточник Цикл
Если Истина
И ТолькоИспользуемые
И Не ЭлементОтбораИсточника.Использование
Тогда
Продолжить;
КонецЕсли;
Если ТипЗнч(ЭлементОтбораИсточника) = Тип("КлючИЗначение") Тогда
ЭлементОтбораИсточника = ЭлементОтбораИсточника.Значение;
КонецЕсли;
//Если ЭлементОтбораИсточника.Имя = "" Тогда
// СообщитьЛкс("Невозможно определить элемент отбора приемника при копировании отбора.",
// СтатусСообщения.Внимание);
// Продолжить;
//КонецЕсли;
ЭлементОтбораПриемника = ОтборПриемник.Найти(ЭлементОтбораИсточника.Имя);
Если ЭлементОтбораПриемника = Неопределено Тогда
Если Истина
И СоздаватьОтсутствующие
//И НайтиПолеНастройкиПоПутиКДаннымЛкс(ДоступныеПоля, ЭлементОтбораИсточника.ПутьКДанным) <> Неопределено
Тогда
Попытка
ЭлементОтбораПриемника = ОтборПриемник.Добавить(ЭлементОтбораИсточника.ПутьКДанным, ЭлементОтбораИсточника.Имя);
Исключение
Продолжить;
КонецПопытки;
Иначе
Продолжить;
КонецЕсли;
КонецЕсли;
СкопироватьЭлементОтбораЛкс(ЭлементОтбораПриемника, ЭлементОтбораИсточника);
Если Истина
И ЗаменятьСпецсимволыВСодержит
И (Ложь
Или ЭлементОтбораПриемника.ВидСравнения = ВидСравнения.Содержит
Или ЭлементОтбораПриемника.ВидСравнения = ВидСравнения.НеСодержит)
Тогда
// https://forum.mista.ru/topic/894309
// https://partners.v8.1c.ru/forum/t/2193666/m/2194099
ЭлементОтбораПриемника.Значение = СтрЗаменить(ЭлементОтбораПриемника.Значение, "[", "[[]");
ЭлементОтбораПриемника.Значение = СтрЗаменить(ЭлементОтбораПриемника.Значение, "_", "[_]");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Получает инвертированный вид сравнения.
//
// Параметры:
// ВидСравнения - ВидСравнения.
//
// Возвращаемое значение:
// ВидСравнения;
//
Функция ИнвертированныйВидСравненияЛкс(ВидСравненияП) Экспорт
МассивИнвертируемыхТиповСравнения = Новый Массив;
МассивИнвертируемыхТиповСравнения.Добавить("ВИерархии");
МассивИнвертируемыхТиповСравнения.Добавить("ВСписке");
МассивИнвертируемыхТиповСравнения.Добавить("Равно");
МассивИнвертируемыхТиповСравнения.Добавить("Содержит");
МассивИнвертируемыхТиповСравнения.Добавить("ВСпискеПоИерархии");
Для Каждого ТипСравнения Из МассивИнвертируемыхТиповСравнения Цикл
ПрямойТипСравнения = Вычислить("ВидСравнения." + ТипСравнения);
Если ПрямойТипСравнения = ВидСравненияП Тогда
Возврат Вычислить("ВидСравнения.Не" + ТипСравнения);
КонецЕсли;
ОбратныйТипСравнения = Вычислить("ВидСравнения.Не" + ТипСравнения);
Если ОбратныйТипСравнения = ВидСравненияП Тогда
Возврат Вычислить("ВидСравнения." + ТипСравнения);
КонецЕсли;
КонецЦикла;
Возврат ВидСравненияП;
КонецФункции
// Копирует один порядок в другой. Приемник перед копированием очищается.
//
// Параметры:
// пПорядокПриемник - Порядок - куда копируем;
// пПорядокИсточник - Порядок - откуда копируем.
//
Процедура СкопироватьПорядокПостроителяЛкс(пПорядокПриемник, пПорядокИсточник) Экспорт
пПорядокПриемник.Очистить();
Для Каждого ЭлементПорядка Из пПорядокИсточник Цикл
пПорядокПриемник.Добавить(ЭлементПорядка.ПутьКДанным, ЭлементПорядка.Имя, , ЭлементПорядка.Направление);
КонецЦикла;
КонецПроцедуры // СкопироватьПорядокЛкс()
// Трансформирует порядок в порядок компоновки.
//
// Параметры:
// ПорядокКомпоновки - ПорядокКомпоновкиДанных;
// Порядок - Порядок.
//
Процедура ТрансформироватьПорядокВПорядокКомпоновкиЛкс(ПорядокКомпоновки, Порядок) Экспорт
ЭлементыКомпоновки = ПорядокКомпоновки.Элементы;
ЭлементыКомпоновки.Очистить();
Для Каждого Элемент Из Порядок Цикл
ЭлементКомпоновки = ЭлементыКомпоновки.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных"));
ЭлементКомпоновки.Использование = Истина;
ЭлементКомпоновки.Поле = Новый ПолеКомпоновкиДанных(Элемент.ПутьКДанным);
Если Элемент.Направление = НаправлениеСортировки.Возр Тогда
ЭлементКомпоновки.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр;
Иначе//Если Элемент.Направление = НаправлениеСортировки.Убыв Тогда
ЭлементКомпоновки.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Убыв;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура СкопироватьПорядокЛюбойЛкс(ПорядокПриемник, ПорядокИсточник, ТолькоИспользуемые = Ложь, ПроверятьДоступность = Ложь, ОчищатьПриемник = Истина) Экспорт
Если Истина
И ТипЗнч(ПорядокИсточник) = Тип("Порядок")
И ТипЗнч(ПорядокПриемник) = Тип("Порядок")
Тогда
СкопироватьПорядокПостроителяЛкс(ПорядокПриемник, ПорядокИсточник);
ИначеЕсли Истина
И ТипЗнч(ПорядокИсточник) = Тип("ПорядокКомпоновкиДанных")
И ТипЗнч(ПорядокПриемник) = Тип("ПорядокКомпоновкиДанных")
Тогда
СкопироватьЭлементыКомпоновкиЛкс(ПорядокПриемник, ПорядокИсточник, ОчищатьПриемник);
ИначеЕсли Истина
И ТипЗнч(ПорядокИсточник) = Тип("Порядок")
И ТипЗнч(ПорядокПриемник) = Тип("ПорядокКомпоновкиДанных")
Тогда
ТрансформироватьПорядокВПорядокКомпоновкиЛкс(ПорядокПриемник, ПорядокИсточник);
Иначе
ВызватьИсключение "Неверные типы параметров";
КонецЕсли;
КонецПроцедуры
Функция ПостроительЗапросаКТабличномуДокументуЛкс(Знач ТабличныйДокументИлиОбласть) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокументИлиОбласть = Новый ТабличныйДокумент;
#КонецЕсли
Если ТипЗнч(ТабличныйДокументИлиОбласть) = Тип("ТабличныйДокумент") Тогда
Область = ТабличныйДокументИлиОбласть.Область();
Иначе
Область = ТабличныйДокументИлиОбласть;
КонецЕсли;
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Область);
Построитель.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
Построитель.ЗаполнитьНастройки();
Возврат Построитель;
КонецФункции
// Для Максимум/Минимум лучше использовать ЛучшиеЭлементыКоллекцииЛкс. Для КоличествоРазличных - СвернутьМассивЛкс.
// Параметры:
// Массив - Массив из Число -
// АгрегатноеВыражение - Строка - выражение языка запросов с использованием агрегатных функций, обращаться к значению через "э", например "Сумма(э)"
// Возвращаемое значение:
// Число -
Функция АгрегатОтМассиваЧиселЛкс(Массив, АгрегатноеВыражение) Экспорт
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("э", Новый ОписаниеТипов("Число"));
ирОбщий.ЗагрузитьВКолонкуТаблицыЛкс(Массив, "э", Таблица);
ИсточникДанных = Новый ОписаниеИсточникаДанных(Таблица);
ИсточникДанных.Колонки.э.Итог = АгрегатноеВыражение;
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = ИсточникДанных;
Выборка = Построитель.Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.э;
КонецФункции
// Возвращает текущее время в миллисекундах.
//
// Параметры:
// Нет.
//
// Возвращаемое значение:
// Число.
//
Функция ТекущееВремяВМиллисекундахЛкс() Экспорт
Если ЛиДоступенМодуль83() Тогда
Результат = ирОбщий83.ТекущаяУниверсальнаяДатаВМиллисекундахЛкс();
Иначе
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Результат = мПлатформа.ПолучитьТекущееВремяВМиллисекундах();
КонецЕсли;
Возврат Результат;
КонецФункции
// Выполняет запрос. Опционально сообщает его текст и время выполнения.
// Удобно для оптимизации.
//
// Параметры:
// Запрос - Запрос;
// *ЛиОтладка - Булево, *Ложь - показывать тексты запросов и время выполнения.
// *Заголовок - Строка, *"" - название запроса.
//
// Возвращаемое значение:
// РезультатЗапроса.
//
Функция ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка = Ложь, Знач Заголовок = "") Экспорт
Если ЛиОтладка Тогда
ВремяНачала = ТекущееВремяВМиллисекундахЛкс();
КонецЕсли;
Результат = Запрос.Выполнить();
Если ЛиОтладка Тогда
Заголовок = Заголовок + " - " + Строка(ТекущееВремяВМиллисекундахЛкс() - ВремяНачала) + " мс";
СообщитьЛкс(Заголовок);
//Текст = Новый ТекстовыйДокумент;
//Текст.УстановитьТекст(Запрос.Текст);
//Текст.Показать(Заголовок);
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает константу языка запросов заданного типа с учетом квалификаторов описания типов.
//
// Параметры:
// ТипПоля - Тип;
// ОписаниеТипов - ОписаниеТипов - для обращения к квалификаторам.
//
// Возвращаемое значение:
// Строка.
//
Функция ВыражениеПриведенияТипаНаЯзыкеЗапросовЛкс(Знач ТипПоля, Знач ОписаниеТипов = Неопределено, Знач БазовоеВыражение = "") Экспорт
Если ТипПоля = Тип("Строка") Тогда
Если БазовоеВыражение = "" Тогда
БазовоеВыражение = """""";
КонецЕсли;
Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК СТРОКА(" + XMLСтрока(ОписаниеТипов.КвалификаторыСтроки.Длина) + "))";
ИначеЕсли ТипПоля = Тип("Число") Тогда
Если БазовоеВыражение = "" Тогда
БазовоеВыражение = "0";
КонецЕсли;
Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК ЧИСЛО(" + XMLСтрока(ОписаниеТипов.КвалификаторыЧисла.Разрядность) + ", " + XMLСтрока(ОписаниеТипов.КвалификаторыЧисла.РазрядностьДробнойЧасти) + "))";
ИначеЕсли ТипПоля = Тип("Дата") Тогда
Если БазовоеВыражение = "" Тогда
Если ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда
Результат = "ДАТАВРЕМЯ(1,1,1)";
Иначе
Результат = "ДАТАВРЕМЯ(1,1,1,0,0,0)";
КонецЕсли;
Иначе
Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК ДАТА)";
КонецЕсли;
ИначеЕсли ТипПоля = Тип("Булево") Тогда
Если БазовоеВыражение = "" Тогда
Результат = "ЛОЖЬ";
Иначе
Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК БУЛЕВО)";
КонецЕсли;
ИначеЕсли ТипПоля = Тип("Тип") Тогда
Если БазовоеВыражение = "" Тогда
Результат = "Тип(Булево)";
Иначе
Результат = "NULL";
КонецЕсли;
ИначеЕсли ТипПоля = Тип("NULL") Тогда
Результат = "NULL";
ИначеЕсли ТипПоля = Тип("НЕОПРЕДЕЛЕНО") Тогда
Результат = "НЕОПРЕДЕЛЕНО";
ИначеЕсли ТипПоля = Тип("ВидДвиженияНакопления") Тогда
Результат = "ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)";
ИначеЕсли ТипПоля = Тип("ВидДвиженияБухгалтерии") Тогда
Результат = "ЗНАЧЕНИЕ(ВидДвиженияБухгалтерии.Дебет)";
ИначеЕсли ТипПоля = Тип("ВидСчета") Тогда
Результат = "ЗНАЧЕНИЕ(ВидСчета.Активный)";
Иначе
МетаданныеТипаПоля = Метаданные.НайтиПоТипу(ТипПоля);
Если МетаданныеТипаПоля <> Неопределено Тогда
// Антибаг платформы 8.1.10.50
Если КорневойТипКонфигурацииЛкс(МетаданныеТипаПоля) = "ПланОбмена" Тогда
Результат = "НЕОПРЕДЕЛЕНО";
Возврат Результат;
КонецЕсли;
Если БазовоеВыражение = "" Тогда
Результат = "ЗНАЧЕНИЕ(" + МетаданныеТипаПоля.ПолноеИмя() + ".ПустаяСсылка)";
Иначе
Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК " + МетаданныеТипаПоля.ПолноеИмя() + ")";
КонецЕсли;
Иначе
//СообщитьЛкс("Неизвестный тип поля при формировании имитатора результата: " + ТипПоля, СтатусСообщения.Важное);
Результат = "NULL";
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает текст запроса только из констант, дающий идентичный переданному набор колонок.
//
// Параметры:
// КоллекцияПолей - КоллекцияКолонокТаблицыЗначений, КоллекцияКолонокДереваЗначений, КоллекцияКолонокРезультатаЗапроса, ПоляНастройки.
//
// Возвращаемое значение:
// Текст.
//
Функция ЗапросИмитаторКоллекцииПолейЛкс(КоллекцияПолей) Экспорт
// Формирование запроса-имитатора
ОписаниеПолей = "";
Для Каждого Колонка Из КоллекцияПолей Цикл
ОписаниеПолей = ОписаниеПолей + ", ";
МассивТипов = Колонка.ТипЗначения.Типы();
НачальноеКоличество = МассивТипов.Количество();
Для СчетчикМассивТипов = 1 По НачальноеКоличество Цикл
ТипПоля = МассивТипов[НачальноеКоличество - СчетчикМассивТипов];
Если ТипПоля = Тип("NULL") Тогда
//МассивТипов.Удалить(НачальноеКоличество - СчетчикМассивТипов);
КонецЕсли;
КонецЦикла;
// Этот стиль строго фиксирован и0ие90цаун787
ОписаниеПолей = ОписаниеПолей + "ВЫБОР";
ЭтоПервыйТип = Истина;
Для Каждого ТипПоля Из МассивТипов Цикл
Если ЭтоПервыйТип Тогда
УсловиеТипа = " КОГДА ""!ИмяПоля!""=""" + Колонка.Имя + """";
ЭтоПервыйТип = Ложь;
Иначе
УсловиеТипа = " КОГДА ЛОЖЬ";
КонецЕсли;
ОписаниеПолей = ОписаниеПолей + УсловиеТипа + " ТОГДА " + ВыражениеПриведенияТипаНаЯзыкеЗапросовЛкс(ТипПоля, Колонка.ТипЗначения);
КонецЦикла;
ОписаниеПолей = ОписаниеПолей + " КОНЕЦ КАК " + Колонка.Имя; // запрещенные имена например "Соединение" так вызывают ошибку?
КонецЦикла;
Результат = "ВЫБРАТЬ " + Сред(ОписаниеПолей, 3);
Возврат Результат;
КонецФункции
// Присваивает первому параметру второй в случае их неравенства.
// Удобно использовать для избежания установки признака модифицированности объекта в случае присвоения реквизиту объекта его же значения.
//
// Параметры:
// Переменная - Произвольный - переменная, которой нужно присвоить значение;
// Значение - Произвольный - присваиваемое значение;
// выхМодифицированность - Булево - в эту переменную записывается Истина, если значение было изменено в этом методе
//
// Возвращаемое значение:
// Булево - Истина если переменная теперь содержит указанное значение.
//
Функция ПрисвоитьЕслиНеРавноЛкс(Переменная, Значение, выхМодифицированность = Неопределено, ПодавитьОшибки = Ложь) Экспорт
Если Переменная <> Значение Тогда
Попытка
Переменная = Значение;
Исключение
Если Не ПодавитьОшибки Тогда
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
выхМодифицированность = Истина;
КонецЕсли;
Возврат Переменная = Значение;
КонецФункции
// Получает индекс картинки отражающей корневой тип и статус ссылки.
// Индекс потом используется с общей картинкой ЛксСостояниеСсылки.
//
// Параметры:
// пСсылка - Ссылка - целевая;
// *пЛиОпределятьСтатусСсылки - Булево, *Неопределено - признак необходимости определения статуса.
//
// Возвращаемое значение:
// - Число - индекс картинки.
//
Функция ИндексКартинкиСсылкиЛкс(Ссылка, ЛиОпределятьСтатусСсылки = Неопределено, ЗначенияРеквизитов = Неопределено) Экспорт
Если ЛиОпределятьСтатусСсылки = Неопределено Тогда
//пЛиОпределятьСтатусСсылки = ПараметрыСеанса.ЛксОпределятьСтатусСсылкиПриВыводе;
ЛиОпределятьСтатусСсылки = Ложь;
КонецЕсли;
Если ЗначенияРеквизитов = Неопределено Тогда
ЗначенияРеквизитов = Ссылка;
КонецЕсли;
КорневойТип = КорневойТипКонфигурацииЛкс(Ссылка);
ИндексКартинки = -1;
Если КорневойТип = "Документ" Тогда
ИндексКартинки = 0;
Если ЛиОпределятьСтатусСсылки Тогда
Попытка
Проведен = ЗначенияРеквизитов.Проведен;
Исключение
Проведен = Ложь;
КонецПопытки;
Попытка
ПометкаУдаления = ЗначенияРеквизитов.ПометкаУдаления;
Исключение
ПометкаУдаления = Ложь;
КонецПопытки;
Если Проведен = Истина Тогда
ИндексКартинки = 0;
ИначеЕсли ПометкаУдаления = Истина Тогда
ИндексКартинки = 1;
Иначе
ИндексКартинки = 2;
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "Справочник" Тогда
ИндексКартинки = 3;
Если ЛиОпределятьСтатусСсылки Тогда
Попытка
ЭтоГруппа = ЗначенияРеквизитов.ЭтоГруппа;
Исключение
ЭтоГруппа = Ложь;
КонецПопытки;
Если ЗначенияРеквизитов.ПометкаУдаления Тогда
ИндексКартинки = ?(ЭтоГруппа = Истина, 6, 4);
Иначе
ИндексКартинки = ?(ЭтоГруппа = Истина, 5, 3);
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "Задача" Тогда
ИндексКартинки = 7;
Если ЛиОпределятьСтатусСсылки Тогда
Если ЗначенияРеквизитов.ПометкаУдаления Тогда
ИндексКартинки = 8;
Иначе
ИндексКартинки = 7;
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "ПланВидовХарактеристик" Тогда
ИндексКартинки = 9;
Если ЛиОпределятьСтатусСсылки Тогда
Если ЗначенияРеквизитов.ПометкаУдаления Тогда
ИндексКартинки = 10;
Иначе
ИндексКартинки = 9;
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "ПланОбмена" Тогда
ИндексКартинки = 15;
Если ЛиОпределятьСтатусСсылки Тогда
Если ЗначенияРеквизитов.ПометкаУдаления Тогда
ИндексКартинки = 16;
Иначе
ИндексКартинки = 15;
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "БизнесПроцесс" Тогда
ИндексКартинки = 19;
//Если пЛиОпределятьСтатусСсылки Тогда
// Если ЗначенияРеквизитов.ПометкаУдаления Тогда
// ИндексКартинки = 20;
// Иначе
// ИндексКартинки = 19;
// КонецЕсли;
//КонецЕсли;
ИначеЕсли КорневойТип = "ПланСчетов" Тогда
ИндексКартинки = 20;
//Если пЛиОпределятьСтатусСсылки Тогда
// Если ЗначенияРеквизитов.ПометкаУдаления Тогда
// ИндексКартинки = 20;
// Иначе
// ИндексКартинки = 19;
// КонецЕсли;
//КонецЕсли;
ИначеЕсли КорневойТип = "ПланВидовРасчета" Тогда
ИндексКартинки = 17;
Если ЛиОпределятьСтатусСсылки Тогда
Если ЗначенияРеквизитов.ПометкаУдаления Тогда
ИндексКартинки = 18;
Иначе
ИндексКартинки = 17;
КонецЕсли;
КонецЕсли;
ИначеЕсли КорневойТип = "Перечисление" Тогда
ИндексКартинки = 11;
ИначеЕсли КорневойТип = "РегистрСведений" Тогда
ИндексКартинки = 12;
ИначеЕсли КорневойТип = "Константа" Тогда
ИндексКартинки = 14;
КонецЕсли;
Возврат ИндексКартинки;
КонецФункции
// Добавляет в таблицу строку для каждого элемента массива и помещает элемент в заданную колонку.
//
// Параметры:
// Массив - Массив -
// ИмяКолонки - Строка - если такой колонки нет в таблице значений, то она будет добавлена
// ТаблицаПриемник - ТаблицаЗначений, ТабличнаяЧасть - куда добавляются строки; создается если не определено
// ЗначенияПоУмолчанию - Структура, *Неопределено - значения по умолчанию для добавляемых строк;
//
// Возвращаемое значение:
// ТаблицаЗначений, ТабличнаяЧасть -
//
Функция ЗагрузитьВКолонкуТаблицыЛкс(Знач Массив, Знач ИмяКолонки, Знач ТаблицаПриемник = Неопределено, Знач ЗначенияПоУмолчанию = Неопределено) Экспорт
Если ТаблицаПриемник = Неопределено Тогда
ТаблицаПриемник = Новый ТаблицаЗначений;
КонецЕсли;
Если Истина
И ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений")
И ТаблицаПриемник.Колонки.Найти(ИмяКолонки) = Неопределено
Тогда
ТаблицаПриемник.Колонки.Добавить(ИмяКолонки);
КонецЕсли;
Для Каждого Элемент Из Массив Цикл
Строка = ТаблицаПриемник.Добавить();
Если ЗначенияПоУмолчанию <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(Строка, ЗначенияПоУмолчанию);
КонецЕсли;
Строка[ИмяКолонки] = Элемент;
КонецЦикла;
Возврат ТаблицаПриемник;
КонецФункции
// Быстрый метод очистки колонок таблицы значений, имеющей индексы. Обходит ошибку платформы https://www.hostedredmine.com/issues/999168
// Параметры:
// Таблица - ТаблицаЗначений, ТабличнаяЧасть -
// ИменаКолонок - Строка - например "Сумма, Покупатель"
Процедура ОчиститьКолонкиТаблицыЛкс(Знач Таблица, Знач ИменаКолонок) Экспорт
//Таблица.ЗаполнитьЗначения(, ИменаКолонок); // Платформа 8.3.0-27 всегда обновляет индексы внутри каждого вызова этого метода
//! Таблица[0][ИменаКолонок];
Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Тогда
ВремТаблица = Таблица.Выгрузить(, "НомерСтроки");
Иначе
ВремТаблица = Таблица;
КонецЕсли;
ВремТаблица.Колонки.Добавить("_Пустая");
МассивПустых = ВремТаблица.ВыгрузитьКолонку("_Пустая");
Для Каждого ИмяКолонки Из СтрРазделитьЛкс(ИменаКолонок, ",", Истина) Цикл
Таблица.ЗагрузитьКолонку(МассивПустых, ИмяКолонки);
КонецЦикла;
ВремТаблица.Колонки.Удалить("_Пустая");
КонецПроцедуры
// Добавляет в таблицу строки из другой таблицы и в них значения колонок с совпадающими наименованиями.
//
// Параметры:
// ТаблицаИсточник - ТаблицаЗначений, ТабличнаяЧасть - откуда берутся строки;
// ТаблицаПриемник - ТаблицаЗначений, ТабличнаяЧасть - куда добавляются строки;
// ЗначенияПоУмолчанию - Структура, Неопределено - значения по умолчанию для добавляемых строк;
// НовыеЗначения - Структура, Неопределено - значения колонок для добавляемых строк, имеют высший приоритет.
// ОчиститьПередЗагрузкой - Булево - очищать приемник перед загрузкой, ускоряет выполнение
// ОбязательныеКолонки - Структура, Неопределено - имена колонок таблицы, которые нужно обязательно загрузить если они есть в приемнике.
// Остальные будут загружены, если приемник пустой. Если не указано, то все совпадающие колонки обязательны.
//
Процедура ЗагрузитьВТаблицуЗначенийЛкс(Знач ТаблицаИсточник, Знач ТаблицаПриемник, Знач ЗначенияПоУмолчанию = Неопределено, Знач НовыеЗначения = Неопределено,
Знач ОчиститьПередЗагрузкой = Ложь, Знач ОбязательныеКолонки = Неопределено, Знач НачальныйИндексПриемника = Неопределено) Экспорт
Если ТаблицаИсточник = ТаблицаПриемник Тогда
ВызватьИсключение "Нельзя загружать коллекцию в саму себя";
КонецЕсли;
Если ОчиститьПередЗагрузкой Или ТаблицаПриемник.Количество() = 0 Тогда
ТаблицаПриемник.Очистить();
Если Истина
И ЗначенияПоУмолчанию = Неопределено
И НовыеЗначения = Неопределено
И ЛиТабличнаяЧастьЛкс(ТаблицаПриемник)
Тогда
// оптимизация - для ТЧ это самый быстрый способ
Если ЛиТабличнаяЧастьЛкс(ТаблицаИсточник) Тогда
ТаблицаИсточник = ТаблицаИсточник.Выгрузить();
КонецЕсли;
ТаблицаПриемник.Загрузить(ТаблицаИсточник);
Возврат;
КонецЕсли;
КонецЕсли;
Если ТаблицаИсточник.Количество() = 0 Тогда
Возврат;
КонецЕсли;
СтрокаСовпадающихКолонок = "";
Если ТипЗнч(ТаблицаИсточник) = Тип("ТаблицаЗначений") Тогда
КолонкиИсточника = ТаблицаИсточник.Колонки;
Иначе
КолонкиИсточника = ТаблицаИсточник.Выгрузить(Новый Массив).Колонки;
КонецЕсли;
ЛиПриемникТаблицаЗначений = ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений");
Если ЛиПриемникТаблицаЗначений Тогда
КолонкиПриемника = ТаблицаПриемник.Колонки;
Иначе
КолонкиПриемника = ТаблицаПриемник.Выгрузить(Новый Массив).Колонки;
КонецЕсли;
ИмяПоляНомерСтроки = ПеревестиСтроку("НомерСтроки");
СовпадающиеКолонки = Новый Массив;
// Ранее применялась однострочная форма кода
Для каждого Колонка Из КолонкиПриемника Цикл
Если НовыеЗначения <> Неопределено Тогда
Если НовыеЗначения.Свойство(Колонка.Имя) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Если Истина
И (Ложь
Или ЛиПриемникТаблицаЗначений
Или Колонка.Имя <> ИмяПоляНомерСтроки)
И (Ложь
Или ОбязательныеКолонки = Неопределено
Или ОбязательныеКолонки.Свойство(Колонка.Имя))
И КолонкиИсточника.Найти(Колонка.Имя) <> Неопределено
Тогда
СовпадающиеКолонки.Добавить(НРег(Колонка.Имя));
КонецЕсли;
КонецЦикла;
Если ЛиПриемникТаблицаЗначений И ТаблицаПриемник.Количество() = 0 Тогда
// оптимизация - быстрый способ
Для Счетчик = 1 По ТаблицаИсточник.Количество() Цикл
ТаблицаПриемник.Добавить();
КонецЦикла;
Если НовыеЗначения <> Неопределено Тогда
Для Каждого КлючИЗначение Из НовыеЗначения Цикл
ТаблицаПриемник.ЗаполнитьЗначения(КлючИЗначение.Значение, КлючИЗначение.Ключ); // Несовместимо с ТЧ
КонецЦикла;
КонецЕсли;
ИндексыПересоздать = Новый Соответствие;
Для Каждого ИмяКолонки Из СовпадающиеКолонки Цикл
Массив = ТаблицаИсточник.ВыгрузитьКолонку(ИмяКолонки);
ТаблицаПриемник.ЗагрузитьКолонку(Массив, ИмяКолонки);
Для Каждого ИндексТаблицы Из ТаблицаПриемник.Индексы Цикл
Если Найти(" " + Нрег(ИндексТаблицы) + ",", " " + ИмяКолонки + ",") > 0 Тогда
ИндексыПересоздать.Вставить(ИндексТаблицы);
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Антибаг https://www.hostedredmine.com/issues/936307
Для Каждого КлючИЗначение Из ИндексыПересоздать Цикл
ОпределениеИндекса = "" + КлючИЗначение.Ключ;
ТаблицаПриемник.Индексы.Удалить(КлючИЗначение.Ключ);
ТаблицаПриемник.Индексы.Добавить(ОпределениеИндекса);
КонецЦикла;
Если ЗначенияПоУмолчанию <> Неопределено Тогда
Для Каждого КлючИЗначение Из ЗначенияПоУмолчанию Цикл
Если СовпадающиеКолонки.Найти(НРег(КлючИЗначение.Ключ)) <> Неопределено Тогда
Продолжить;
КонецЕсли;
ТаблицаПриемник.ЗаполнитьЗначения(КлючИЗначение.Значение, КлючИЗначение.Ключ); // Несовместимо с ТЧ
КонецЦикла;
КонецЕсли;
Иначе
Индекс = НачальныйИндексПриемника;
СтрокаСовпадающихКолонок = СтрСоединитьЛкс(СовпадающиеКолонки, ",");
Для каждого СтрокаТаблицыИсточника Из ТаблицаИсточник Цикл
Если Индекс = Неопределено Тогда
СтрокаТаблицыПриемника = ТаблицаПриемник.Добавить();
Иначе
СтрокаТаблицыПриемника = ТаблицаПриемник.Вставить(Индекс);
Индекс = Индекс + 1;
КонецЕсли;
Если ЗначенияПоУмолчанию <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, ЗначенияПоУмолчанию);
КонецЕсли;
// Заполним значения в совпадающих колонках.
ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтрокаТаблицыИсточника, СтрокаСовпадающихКолонок);
//Для каждого ЭлементМассива Из МассивСовпадающихКолонок Цикл
// СтрокаТаблицыПриемника[ЭлементМассива] = СтрокаТаблицыИсточника[ЭлементМассива];
//КонецЦикла;
Если НовыеЗначения <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, НовыеЗначения);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Слияние таблиц значений одинаковой структуры. Меньшая из таблиц вливается в бОльшую.
//
// Параметры:
// Таблица1 - ТаблицаЗначений -
// Таблица2 - ТаблицаЗначений -
// ОбязательныеКолонки1 - Структура, *Неопределено - имена колонок таблицы, которые нужно обязательно загрузить если они есть в приемнике.
// Остальные будут загружены, если приемник пустой. Если не указано, то все совпадающие колонки обязательны.
// ОбязательныеКолонки2 - Структура, *Неопределено - имена колонок таблицы, которые нужно обязательно загрузить если они есть в приемнике.
// Остальные будут загружены, если приемник пустой. Если не указано, то все совпадающие колонки обязательны.
//
// Возвращаемое значение:
// ТаблицаЗначений -
//
Функция ОбъединитьТаблицыЗначенийЛкс(Знач Таблица1, Знач Таблица2, Знач ОбязательныеКолонки1 = Неопределено, Знач ОбязательныеКолонки2 = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица1 = Новый ТаблицаЗначений;
Таблица2 = Новый ТаблицаЗначений;
#КонецЕсли
Если Ложь
Или Таблица1 = Таблица2
Или Таблица2.Количество() = 0
Тогда
Возврат Таблица1;
ИначеЕсли Ложь
Или Таблица1.Количество() = 0
Тогда
Возврат Таблица2;
КонецЕсли;
Если Таблица1.Количество() > Таблица2.Количество() Тогда
ЗагрузитьВТаблицуЗначенийЛкс(Таблица2, Таблица1,,,, ОбязательныеКолонки2);
Результат = Таблица1;
Иначе
ЗагрузитьВТаблицуЗначенийЛкс(Таблица1, Таблица2,,,, ОбязательныеКолонки1);
Результат = Таблица2;
КонецЕсли;
Возврат Результат;
КонецФункции
// Непростетирована. Добавляет в дерево значений строки из другой таблицы значений и
// в них значения колонок с совпадающими наименованиями.
//
// Параметры:
// ТаблицаИсточник - таблица значений, откуда берутся значения;
// ТаблицаПриемник - таблица значений, куда добавляются строки;
// *ЗначенияПоУмолчанию - Структура, *Неопределено - значения по умолчанию для добавляемых строк;
// *НовыеЗначения - Структура, *Неопределено - значения колонок для добавляемых строк, имеют высший приоритет.
//
Процедура ЗагрузитьВДеревоЗначенийЛкс(ДеревоИсточник, ДеревоПриемник, Знач ЗначенияПоУмолчанию = Неопределено, НовыеЗначения = Неопределено, ОчиститьПередЗагрузкой = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ДеревоИсточник = Новый ДеревоЗначений;
ДеревоПриемник = Новый ДеревоЗначений;
#КонецЕсли
СтрокаСовпадающихКолонок = "";
Разделитель = ",";
КолонкиИсточника = ДеревоИсточник.Колонки;
Для каждого Колонка Из ДеревоПриемник.Колонки Цикл
Если НовыеЗначения <> Неопределено Тогда
Если НовыеЗначения.Свойство(Колонка.Имя) Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Если КолонкиИсточника.Найти(Колонка.Имя) <> Неопределено Тогда
СтрокаСовпадающихКолонок = СтрокаСовпадающихКолонок + Разделитель+ Колонка.Имя;
КонецЕсли;
КонецЦикла;
СтрокаСовпадающихКолонок = Сред(СтрокаСовпадающихКолонок, СтрДлина(Разделитель) + 1);
Если ОчиститьПередЗагрузкой Тогда
ДеревоПриемник.Строки.Очистить();
КонецЕсли;
ЗагрузитьВСтрокиДереваЗначенийЛкс(ДеревоИсточник.Строки, ДеревоПриемник, ЗначенияПоУмолчанию, НовыеЗначения, СтрокаСовпадающихКолонок);
КонецПроцедуры
// Непростетирована. Добавляет в дерево значений строки из другой таблицы значений и
// в них значения колонок с совпадающими наименованиями.
//
// Параметры:
// КоллекцияСтрокИсточника - КоллекцияСтрокДереваЗначений, ТаблицаЗначений -
// СтрокаРодительПриемника - СтрокаДереваЗначений -
// ЗначенияПоУмолчанию - Структура - значения по умолчанию для добавляемых строк;
// НовыеЗначения - Структура - значения колонок для добавляемых строк, имеют высший приоритет.
// СовпадающиеКолонки - Строка - значения колонок для добавляемых строк, имеют высший приоритет.
//
Процедура ЗагрузитьВСтрокиДереваЗначенийЛкс(Знач КоллекцияСтрокИсточника, Знач СтрокаРодительПриемника, Знач ЗначенияПоУмолчанию = Неопределено, Знач НовыеЗначения = Неопределено,
Знач СовпадающиеКолонки = Неопределено, Знач ДобавлятьКонечнымДочернююСтроку = Ложь) Экспорт
СтрокиПриемника = СтрокаРодительПриемника.Строки;
Для каждого СтрокаИсточника Из КоллекцияСтрокИсточника Цикл
СтрокаПриемника = СтрокиПриемника.Добавить();
Если ЗначенияПоУмолчанию <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СтрокаПриемника, ЗначенияПоУмолчанию);
КонецЕсли;
// Заполним значения в совпадающих колонках.
ЗаполнитьЗначенияСвойств(СтрокаПриемника, СтрокаИсточника, СовпадающиеКолонки);
Если НовыеЗначения <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(СтрокаПриемника, НовыеЗначения);
КонецЕсли;
Если ТипЗнч(СтрокаИсточника) = Тип("СтрокаДереваЗначений") Тогда
ЗагрузитьВСтрокиДереваЗначенийЛкс(СтрокаИсточника.Строки, СтрокаПриемника, ЗначенияПоУмолчанию, НовыеЗначения, СовпадающиеКолонки, ДобавлятьКонечнымДочернююСтроку);
КонецЕсли;
Если Истина
И ДобавлятьКонечнымДочернююСтроку
И СтрокаПриемника.Строки.Количество() = 0
Тогда
СтрокаПриемника.Строки.Добавить();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Устарела. Вместо нее нужно вызывать СообщитьЛкс()
//
// Параметры:
// ТекстСообщения - Строка;
// МодальныйРежим - Булево, *Ложь;
// *Статус - СтатусСообщения, *Неопределено.
//
Процедура СообщитьСУчетомМодальностиЛкс(ТекстСообщения, _МодальныйРежим = Ложь, Статус = Неопределено) Экспорт
СообщитьЛкс(ТекстСообщения, Статус);
КонецПроцедуры
// Сообщает итог индикации (длительность).
//
// Параметры:
// Индикатор - Структура - индикатора, полученная методом ПолучитьИндикаторПроцессаЛкс.
//
Процедура СообщитьИтогИндикацииЛкс(Индикатор) Экспорт
ТекущаяДата = ТекущаяДата();
ПрошлоВремени = ТекущаяДата - Индикатор.ДатаНачалаПроцесса;
ПрошлоВремениСтрока = Формат(Дата(1,1,1) + ПрошлоВремени, "ДЛФ=T; ДП=");
Если Индикатор.КоличествоПроходов = 1 Тогда
ТекстСообщения = СтрШаблонЛкс("%1 завершено за %2 (%3 сек)", Индикатор.ПредставлениеПроцесса, ПрошлоВремениСтрока, ПрошлоВремени);
Иначе
ТекстСообщения = СтрШаблонЛкс(НСтр("ru = '%1 завершено за %2 (%3 сек), обработано %4 элементов.';
|en = '%1 completed in %2 (%3 sec), processed %4 elements.'"), Индикатор.ПредставлениеПроцесса, ПрошлоВремениСтрока, ПрошлоВремени, Индикатор.Счетчик);
Если Индикатор.Счетчик > 0 Тогда
ТекстСообщения = ТекстСообщения + СтрШаблонЛкс(НСтр("ru = 'Среднее время элемента - %1 мс';
|en = Average element time: %1 ms'"), Формат(ПрошлоВремени / Индикатор.Счетчик * 1000, "ЧЦ=15; ЧДЦ=2; ЧН="));
КонецЕсли;
КонецЕсли;
СообщитьЛкс(ТекстСообщения);
КонецПроцедуры
// Получает более подробное представление значения, чем штатное приведение к строковому типу.
//
// Параметры:
// Значение - Произвольный - что нужно представить.
//
// Возвращаемое значение:
// Строка - представление.
//
Функция РасширенноеПредставлениеЛкс(Значение, Знач КолонкаТабличногоПоля = Неопределено, Знач ДобавлятьПредставлениеТипа = Ложь, РасширенноеПредставлениеХранилищЗначений = Ложь,
Знач ПолучатьПредставленияСсылок = Истина, Знач ЯвноеПреставлениеПустого = Ложь, Знач МаксЭлементовДляПредставления = 10, Знач ИменаТиповВместоПредставлений = Ложь) Экспорт
ирПлатформа = ирКэш.Получить();
Результат = "";
ТипЗначения = ТипЗнч(Значение);
Если ТипЗначения = Тип("Строка") Тогда
Если ДобавлятьПредставлениеТипа Или ЯвноеПреставлениеПустого Тогда
Результат = Результат + """" + Значение + """";
Иначе
Результат = Результат + Значение;
КонецЕсли;
ИначеЕсли ТипЗначения = Тип("Дата") Тогда
Результат = "" + Значение; // Хорошо бы формат колонки применить
Миллисекунды = МиллисекундыДатыЛкс(Значение);
Если Миллисекунды > 0 Тогда
Результат = Результат + "." + Формат(Миллисекунды, "ЧЦ=3; ЧВН=");
КонецЕсли;
Иначе
Разделитель = ", ";
КоличествоЭлементов = КоличествоЭлементовКоллекцииЛкс(Значение);
Если ТипЗначения = Тип("ДеревоЗначений") Тогда
КоличествоЭлементов = Значение.Строки.Количество();
КонецЕсли;
Если Истина
И КоличествоЭлементов <> Неопределено
И (Ложь
Или ЯвноеПреставлениеПустого
Или КоличествоЭлементов <> 0)
Тогда
Результат = "(" + КоличествоЭлементов + ")";
КонецЕсли;
Представления = Новый СписокЗначений;
Если ТипЗначения = Тип("Граница") Тогда
Если ДобавлятьПредставлениеТипа Тогда
Результат = Результат + ТипЗначения;
КонецЕсли;
Если ЗначениеЗаполнено(Результат) Тогда
Результат = Результат + ": ";
КонецЕсли;
Результат = Результат + Значение.ВидГраницы + ", " + Значение.Значение;
ИначеЕсли ЛиТипСсылкиТочкиМаршрутаЛкс(ТипЗначения) Тогда
Результат = "" + Значение;
Если Не ЗначениеЗаполнено(Результат) Тогда
Результат = "(" + Значение.Имя + ")";
КонецЕсли;
ИначеЕсли ТипЗначения = Тип("ОписаниеТипов") Тогда
#Если Сервер И Не Сервер Тогда
Значение = Новый ОписаниеТипов;
#КонецЕсли
ПредставлениеКоллекции = "";
Коллекция = Значение.Типы();
ПредставлениеОбрезано = Ложь;
Для Каждого Тип Из Коллекция Цикл
Если МаксЭлементовДляПредставления = 0 Тогда
ПредставлениеОбрезано = Истина;
Прервать;
КонецЕсли;
Представления.Добавить(ПредставлениеТипаЛкс(Тип, Значение, ИменаТиповВместоПредставлений));
МаксЭлементовДляПредставления = МаксЭлементовДляПредставления - 1;
КонецЦикла;
Если ПредставлениеОбрезано Тогда
Представления.Добавить("…");
Иначе
Представления.СортироватьПоЗначению();
КонецЕсли;
Если Коллекция.Количество() > 1 Тогда
Результат = "(" + XMLСтрока(Коллекция.Количество()) + ")";
Если ДобавлятьПредставлениеТипа Тогда
Результат = Результат + ТипЗначения;
КонецЕсли;
Если ЗначениеЗаполнено(Результат) Тогда
Результат = Результат + ": ";
КонецЕсли;
КонецЕсли;
Результат = Результат + СтрСоединитьЛкс(Представления, Разделитель);
ИмяОпределяемогоТипа = ИмяНабораТиповИзОписанияТиповЛкс(Значение);
Если ЗначениеЗаполнено(ИмяОпределяемогоТипа) Тогда
Результат = Результат + " = " + ИмяОпределяемогоТипа;
КонецЕсли;
ИначеЕсли Ложь
Или ТипЗначения = Тип("Структура")
Или ТипЗначения = Тип("Соответствие")
Или ТипЗначения = Тип("ФиксированнаяСтруктура")
Или ТипЗначения = Тип("ФиксированноеСоответствие")
Тогда
ПредставлениеКоллекции = "";
ПредставлениеОбрезано = Ложь;
Для Каждого КлючИЗначение Из Значение Цикл
Если МаксЭлементовДляПредставления = 0 Тогда
ПредставлениеОбрезано = Истина;
Прервать;
КонецЕсли;
Представления.Добавить("" + КлючИЗначение.Ключ + " = " + КлючИЗначение.Значение);
МаксЭлементовДляПредставления = МаксЭлементовДляПредставления - 1;
КонецЦикла;
Если ПредставлениеОбрезано Тогда
Представления.Добавить("…");
Иначе
Представления.СортироватьПоЗначению();
КонецЕсли;
Если ДобавлятьПредставлениеТипа Тогда
Результат = Результат + ТипЗначения;
КонецЕсли;
Если ЗначениеЗаполнено(Результат) Тогда
Результат = Результат + ": ";
КонецЕсли;
Результат = Результат + СтрСоединитьЛкс(Представления, Разделитель);
ИначеЕсли Ложь
Или ТипЗначения = Тип("Массив")
Или ТипЗначения = Тип("ФиксированныйМассив")
Или ТипЗначения = Тип("СписокЗначений")
Или ТипЗначения = Тип("КоллекцияОбъектовМетаданных")
Или ТипЗначения = Тип("КоллекцияЗначенийСвойстваОбъектаМетаданных")
Тогда
ПредставлениеКоллекции = "";
НомерВерсииПлатформы = ирКэш.НомерВерсииПлатформыЛкс();
ПредставлениеОбрезано = Ложь;
Для Каждого ЭлементМассива Из Значение Цикл
Если МаксЭлементовДляПредставления = 0 Тогда
ПредставлениеОбрезано = Истина;
Представления.Добавить("…");
Прервать;
КонецЕсли;
Если Ложь
Или (Истина
// http://www.hostedredmine.com/issues/881633
И НомерВерсииПлатформы >= 803006
И ТипЗнч(ЭлементМассива) = Тип("РасширениеКонфигурации"))
Или ТипЗнч(ЭлементМассива) = Тип("ЗначениеПоляАнализаДанных") // https://www.hostedredmine.com/issues/932745
Тогда
ПредставлениеЭлемента = "" + ТипЗнч(ЭлементМассива);
Иначе
ПредставлениеЭлемента = "" + ЭлементМассива;
КонецЕсли;
Представления.Добавить(ПредставлениеЭлемента);
МаксЭлементовДляПредставления = МаксЭлементовДляПредставления - 1;
КонецЦикла;
Если ДобавлятьПредставлениеТипа Тогда
Результат = Результат + ТипЗначения;
КонецЕсли;
Если ЗначениеЗаполнено(Результат) Тогда
Результат = Результат + ": ";
КонецЕсли;
Результат = Результат + СтрСоединитьЛкс(Представления, Разделитель);
ИначеЕсли ТипЗначения = Тип("ТабличныйДокумент") Тогда
#Если Сервер И Не Сервер Тогда
Значение = Новый ТабличныйДокумент;
#КонецЕсли
Результат = "(" + Значение.ВысотаТаблицы + ")" + Значение;
ИначеЕсли ТипЗначения = Тип("ТекстовыйДокумент") Тогда
#Если Сервер И Не Сервер Тогда
Значение = Новый ТабличныйДокумент;
#КонецЕсли
Результат = "(" + Значение.КоличествоСтрок() + ")" + Значение;
ИначеЕсли ТипЗначения = Тип("COMОбъект") Тогда
ИмяОбщегоТипа = ирПлатформа.ПолноеИмяТипаCOMОбъекта(Значение);
ПолноеИмяОсновногоКласса = ТекстМеждуМаркерамиЛкс(ИмяОбщегоТипа, "{", "}", Ложь);
ИмяОбщегоТипа = СтрЗаменить(ИмяОбщегоТипа, ".{" + ПолноеИмяОсновногоКласса + "}", "");
Результат = Результат + ИмяОбщегоТипа;
ИначеЕсли Истина
И РасширенноеПредставлениеХранилищЗначений
И ТипЗначения = Тип("ХранилищеЗначения")
Тогда
Результат = Результат + ТипЗначения;
Попытка
ВложенноеЗначение = Значение.Получить();
Исключение
ВложенноеЗначение = "<Ошибка формата потока>";
КонецПопытки;
Результат = Результат + ": " + ВложенноеЗначение;
ИначеЕсли ТипЗначения = Тип("Файл") Тогда
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + Значение.ПолноеИмя;
ИначеЕсли ТипЗначения = Тип("РезультатЗапроса") Тогда
Результат = Результат + ТипЗначения;
ИначеЕсли ТипЗначения = Тип("СочетаниеКлавиш") Тогда
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + ПредставлениеСочетанияКлавишЛкс(Значение);
ИначеЕсли ТипЗначения = ТипУправляемаяФормаЛкс() Тогда
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + Значение.ИмяФормы;
ИначеЕсли Ложь
Или ирПлатформа.мМассивТиповЭлементовУправляемойФормы.Найти(ТипЗначения) <> Неопределено
Или ирПлатформа.мМассивТиповЭлементовОбычнойФормы.Найти(ТипЗначения) <> Неопределено
Тогда
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + Значение.Имя;
ИначеЕсли Истина
И РасширенноеПредставлениеХранилищЗначений
И ТипЗначения = Тип("Картинка")
Тогда
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + ИмяКартинкиИзБиблиотекиЛкс(Значение);
ИначеЕсли ТипЗначения = Тип("Цвет") Тогда
#Если Сервер И Не Сервер Тогда
Значение = Новый Цвет;
#КонецЕсли
Результат = Результат + ТипЗначения;
Результат = Результат + ": " + Значение.Красный + ", " + Значение.Зеленый + ", " + Значение.Синий + "";
Иначе
Если ДобавлятьПредставлениеТипа Тогда
Результат = Результат + ТипЗначения + ": ";
КонецЕсли;
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗначения);
Если ОбъектМД <> Неопределено Тогда
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
Если ЛиКлючЗаписиРегистраЛкс(Значение) Тогда
СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяМД, , Ложь, Ложь);
Результат = "";
Для Каждого ЭлементСписка Из СтруктураКлюча Цикл
Если Результат <> "" Тогда
Результат = Результат + ", ";
КонецЕсли;
ПредставлениеЗначения = Значение[ЭлементСписка.Представление];
Если Не ПолучатьПредставленияСсылок И ЛиСсылкаНаОбъектБДЛкс(ПредставлениеЗначения) Тогда
ПредставлениеЗначения = "" + ИдентификаторСсылкиЛкс(ПредставлениеЗначения);
Иначе
ПредставлениеЗначения = "" + ПредставлениеЗначения;
КонецЕсли;
Результат = Результат + ЭлементСписка.Представление + " = " + ПредставлениеЗначения;
КонецЦикла;
ИначеЕсли ЛиКорневойТипКонстантыЛкс(ПервыйФрагментЛкс(ПолноеИмяМД)) Тогда
Результат = ПолноеИмяМД;
ИначеЕсли ЛиСсылкаНаОбъектБДЛкс(Значение) Тогда
Если ПолучатьПредставленияСсылок Тогда
Результат = "" + Значение;
КонецЕсли;
ИначеЕсли Найти(Значение, "ТабличнаяЧасть.") Тогда
Результат = Результат + Значение;
ИначеЕсли Найти(Значение, "ТабличнаяЧастьСтрока.") Тогда
Результат = "" + Значение;
КонецЕсли;
Иначе
СтрокаФормата = "ЧН=";
Если КолонкаТабличногоПоля <> Неопределено Тогда
СтрокаФормата = КолонкаТабличногоПоля.Формат;
// Отключено из-за потери дробной части при 0,0. Зачем это было сделано изначально, пока не разобрался
//Если Истина
// И ПустаяСтрока(СтрокаФормата)
// И ТипЗнч(КолонкаТабличногоПоля.ЭлементУправления) = Тип("ПолеВвода")
//Тогда
// КвалификаторыЧисла = КолонкаТабличногоПоля.ЭлементУправления.ТипЗначения.КвалификаторыЧисла;
// СтрокаФормата = "ЧЦ = " + КвалификаторыЧисла.Разрядность + "; ЧДЦ = " + КвалификаторыЧисла.РазрядностьДробнойЧасти;
//КонецЕсли;
КонецЕсли;
Результат = Результат + Формат(Значение, СтрокаФормата);
Если Истина
И ЯвноеПреставлениеПустого
//И Не ЗначениеЗаполнено(Значение)
И Не ЗначениеЗаполнено(Результат)
Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Результат = мПлатформа.ПредставлениеПустогоЗначенияЛкс(Значение);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// РасширенноеЗначение - Картинка -
// Возвращаемое значение:
// Строка, Неопределено -
Функция ИмяКартинкиИзБиблиотекиЛкс(Знач РасширенноеЗначение) Экспорт
Объект = СериализаторXDTO.ЗаписатьXDTO(РасширенноеЗначение);
Если Объект.ref <> Неопределено Тогда
ИмяКартинки = Объект.ref.ЛокальноеИмя;
КонецЕсли;
Возврат ИмяКартинки;
КонецФункции
// Безопасное приведение к строке
Функция ПредставлениеЗначенияЛкс(Значение) Экспорт
Попытка
Результат = "" + Значение;
Исключение
// Некоторые типы ошибочно не имеют отображения в строку https://www.hostedredmine.com/issues/937039
Результат = ТипЗнч(Значение);
КонецПопытки;
Возврат Результат;
КонецФункции
Функция КодПроверкиЗначенияВыраженияЛкс(Знач ПроверяемоеЗначение, Знач ПроверяемоеВыражение, МаксДлинаСтроки = 20, МаксДробныхЗнаков = 6)
ТипЗначения = ТипЗнч(ПроверяемоеЗначение);
Если Ложь
Или ТипЗначения = Тип("Булево")
Или ТипЗначения = Тип("Дата")
Или ТипЗначения = Тип("Неопределено")
Или ТипЗначения = Тип("Null")
Тогда
УсловиеСвойства = ПроверяемоеВыражение + "=" + СтрЗаменить(ПредставлениеЗначенияВоВстроенномЯзыкеЛкс(ПроверяемоеЗначение), " ", "");
ИначеЕсли ТипЗначения = Тип("Число") Тогда
УсловиеСвойства = "Окр(" + ПроверяемоеВыражение + "," + XMLСтрока(МаксДробныхЗнаков) + ")=" + ПредставлениеЗначенияВоВстроенномЯзыкеЛкс(Окр(ПроверяемоеЗначение, МаксДробныхЗнаков));
Иначе
Попытка
ПолучитьПолноеИмяПредопределенногоЗначения(ПроверяемоеЗначение);
ЭтоПримитивное = Истина;
Исключение
ЭтоПримитивное = Ложь
Или ТипЗначения = Тип("Строка")
Или ЛиТипСсылкиБДЛкс(ТипЗначения, Ложь);
КонецПопытки;
Если ЭтоПримитивное Тогда
УсловиеСвойства = "Лев(" + ПроверяемоеВыражение + "," + XMLСтрока(МаксДлинаСтроки) + ")=""" + Лев(ПроверяемоеЗначение, МаксДлинаСтроки) + """";
Иначе
УсловиеСвойства = "";
КонецЕсли;
КонецЕсли;
Возврат УсловиеСвойства;
КонецФункции
Функция МиллисекундыДатыЛкс(Знач Дата) Экспорт
Возврат 1000 * (Дата - НачалоМинуты(Дата) - Секунда(Дата));
КонецФункции
Функция ПредставлениеСвязейПараметровВыбораЛкс(ПолеФормыИлиРеквизитМетаданных) Экспорт
Попытка
СвязиПараметровВыбора = ПолеФормыИлиРеквизитМетаданных.СвязиПараметровВыбора;
Исключение
Возврат "";
КонецПопытки;
#Если Сервер И Не Сервер Тогда
СвязиПараметровВыбора = Новый ФиксированныйМассив();
#КонецЕсли
Результат = "";
Для Каждого Связь Из СвязиПараметровВыбора Цикл
#Если Сервер И Не Сервер Тогда
Связь = Новый СвязьПараметраВыбора;
#КонецЕсли
Если Результат <> "" Тогда
Результат = Результат + ", ";
КонецЕсли;
Результат = Результат + Связь.ПутьКДанным;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПредставлениеТипаЛкс(Знач Тип, Знач ОписаниеТипов = Неопределено, ИспользоватьИмя = Ложь) Экспорт
Если ИспользоватьИмя Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
СтруктураТипа = мПлатформа.СтруктураТипаИзКонкретногоТипа(Тип);
ПредставлениеТипа = мПлатформа.ИмяТипаИзСтруктурыТипа(СтруктураТипа);
Иначе
ПредставлениеТипа = "" + Тип;
КонецЕсли;
Если ОписаниеТипов <> Неопределено Тогда
ДобавитьКвалификаторыВПредставлениеТипаЛкс(ПредставлениеТипа, Тип, ОписаниеТипов);
КонецЕсли;
Возврат ПредставлениеТипа;
КонецФункции
Функция ВыражениеВстроенногоЯзыкаСозданиеОписанияТиповЛкс(Знач ТипЗначения, Знач МаксЧислоТипов = 10) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
ТипЗначения = Новый ОписаниеТипов;
#КонецЕсли
ИменаТипов = Новый СписокЗначений;
ТекстКвалификаторыЧисла = "";
ТекстКвалификаторыСтроки = "";
ТекстКвалификаторыДаты = "";
Если ТипЗначения.Типы().Количество() <= МаксЧислоТипов Тогда
Для Каждого Тип Из ТипЗначения.Типы() Цикл
ИменаТипов.Добавить(мПлатформа.ИмяТипаИзСтруктурыТипа(мПлатформа.СтруктураТипаИзКонкретногоТипа(Тип)));
КонецЦикла;
ИменаТипов.СортироватьПоЗначению();
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Число")) Тогда
ТекстКвалификаторыЧисла = "Новый КвалификаторыЧисла(" + ТипЗначения.КвалификаторыЧисла.Разрядность + ", " + ТипЗначения.КвалификаторыЧисла.РазрядностьДробнойЧасти;
Если ТипЗначения.КвалификаторыЧисла.ДопустимыйЗнак <> ДопустимыйЗнак.Любой Тогда
ТекстКвалификаторыЧисла = ТекстКвалификаторыЧисла + ", " + ПолучитьПолноеИмяПредопределенногоЗначения(ТипЗначения.КвалификаторыЧисла.ДопустимыйЗнак);
КонецЕсли;
ТекстКвалификаторыЧисла = ТекстКвалификаторыЧисла + ")";
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Строка")) Тогда
ТекстКвалификаторыСтроки = "Новый КвалификаторыСтроки(" + XMLСтрока(ТипЗначения.КвалификаторыСтроки.Длина);
Если ТипЗначения.КвалификаторыСтроки.ДопустимаяДлина <> ДопустимаяДлина.Переменная Тогда
ТекстКвалификаторыСтроки = ТекстКвалификаторыСтроки + ", " + ПолучитьПолноеИмяПредопределенногоЗначения(ТипЗначения.КвалификаторыСтроки.ДопустимаяДлина);
КонецЕсли;
ТекстКвалификаторыСтроки = ТекстКвалификаторыСтроки + ")";
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Дата")) И ТипЗначения.КвалификаторыДаты.ЧастиДаты <> ЧастиДаты.ДатаВремя Тогда
ТекстКвалификаторыДаты = "Новый КвалификаторыДаты(" + ПолучитьПолноеИмяПредопределенногоЗначения(ТипЗначения.КвалификаторыДаты.ЧастиДаты) + ")";
КонецЕсли;
ТекстОписанияТипов = "Новый ОписаниеТипов(""" + СтрСоединитьЛкс(ИменаТипов, ", ") + """, " + ТекстКвалификаторыЧисла + ", " + ТекстКвалификаторыСтроки + ", " + ТекстКвалификаторыДаты + ")";
Возврат ТекстОписанияТипов;
КонецФункции
Процедура ДобавитьКвалификаторыВПредставлениеТипаЛкс(ПредставлениеТипа, Знач Тип, Знач ОписаниеТипов) Экспорт
Если Тип = Тип("Число") Тогда
ПредставлениеТипа = ПредставлениеТипа + "(" + ОписаниеТипов.КвалификаторыЧисла.Разрядность + "," + ОписаниеТипов.КвалификаторыЧисла.РазрядностьДробнойЧасти
+ ?(ОписаниеТипов.КвалификаторыЧисла.ДопустимыйЗнак = ДопустимыйЗнак.Неотрицательный, ",Н", "") + ")";
ИначеЕсли Тип = Тип("Строка") Тогда
Если ОписаниеТипов.КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Переменная Тогда
//ВариантДлины = "п";
Иначе
ВариантДлины = ",Ф";
КонецЕсли;
ПредставлениеТипа = ПредставлениеТипа + "(" + XMLСтрока(ОписаниеТипов.КвалификаторыСтроки.Длина) + ВариантДлины + ")";
ИначеЕсли Тип = Тип("Дата") Тогда
Если ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Время Тогда
ПредставлениеКвалификатора = "В";
ИначеЕсли ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.ДатаВремя Тогда
ПредставлениеКвалификатора = "ДВ";
ИначеЕсли ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда
ПредставлениеКвалификатора = "Д";
КонецЕсли;
ПредставлениеТипа = ПредставлениеТипа + "(" + ПредставлениеКвалификатора + ")";
КонецЕсли;
КонецПроцедуры
Функция ЛиИмяТипаСКвалификаторамиЛкс(Знач ТипЗначения) Экспорт
Возврат Ложь
Или ТипЗначения = "Дата"
Или ТипЗначения = "Строка"
Или ТипЗначения = "Число";
КонецФункции
// Сравнивает значения свойств объекта <Первый> со значениями свойств объекта <Второй>. Сопоставление производится по именам свойств.
// Отсутствие свойства приравнивается к значению Неопределено.
//
// Параметры:
// Первый - Произвольный - первый объект для сравнения;
// Второй - Произвольный - первый объект для сравнения;
// СвойстваДляСравнения - Строка - перечисленные через запятую свойства для сравнения; допускается не указывать, если второй объект является структурой - тогда используется еще и как кэш;
// Глубокое - Булево - полная сериализация;
//
// Возвращаемое значение:
// Булево - Равны ли значения всех указанных свойств.
//
Функция СравнитьЗначенияСвойствЛкс(Знач Первый, Знач Второй, СвойстваДляСравнения = "", Знач Глубокое = Ложь) Экспорт
Если ТипЗнч(Второй) = Тип("Структура") И Не ЗначениеЗаполнено(СвойстваДляСравнения) Тогда
СвойстваДляСравнения = СтрСоединитьЛкс(ВыгрузитьСвойствоЛкс(Второй, "Ключ"));
Структура2 = Второй;
ИначеЕсли ТипЗнч(Второй) = Тип("Структура") И СтрЧислоВхождений(СвойстваДляСравнения, ",") = Второй.Количество() - 1 Тогда
Структура2 = Второй;
Иначе
Структура2 = Новый Структура(СвойстваДляСравнения);
ЗаполнитьЗначенияСвойств(Структура2, Второй);
КонецЕсли;
Структура1 = Новый Структура(СвойстваДляСравнения);
ЗаполнитьЗначенияСвойств(Структура1, Первый);
Если Глубокое Тогда
Результат = ОбъектВСтрокуДляСравненияВнутрЛкс(Структура1) = ОбъектВСтрокуДляСравненияВнутрЛкс(Структура2);
Иначе
Результат = Истина;
Для Каждого КлючИЗначение Из Структура1 Цикл
Если Структура2[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
// Если Объект2 не передан, то первый вызов запоминает Объект1, а второй - вычисляет таблицу различий между текущим и предыдущим объектами.
// Вызывается из адаптера.
// Параметры:
// Объект1 - -
// Возвращаемое значение:
// Строка, ТаблицаЗначений, Неопределено - таблица раличий или сообщение о запоминании объекта или Неопределено в случае невозможности сохранить объект
Функция ЗапомнитьДляСравненияЛкс(Знач Объект1, Знач Представление1 = "", Знач Объект2 = Неопределено, Знач Представление2 = "") Экспорт
Если Объект2 = Неопределено Тогда
МассивСравнения = ирКэш.БуферСравненияЛкс("ХранилищеОбъектаДляСравнения");
Если МассивСравнения.Количество() > 0 Тогда
Хранилище = МассивСравнения[0]; // Структура
МассивСравнения.Удалить(0);
Представление2 = Хранилище.Представление;
Если Хранилище.Объект = Объект1 Тогда
// 2 состояния одного объекта
Объект2 = Хранилище.Снимок;
Объект1 = СтруктураИзОбъектаЛкс(Объект1,,, Истина, Истина, Истина); // Текстовый снимок 1-го уровня
Иначе
Объект2 = Хранилище.Объект;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Объект2 = Неопределено Тогда
Хранилище = Новый Структура;
Хранилище.Вставить("Представление", Представление1);
Хранилище.Вставить("Объект", Объект1);
Хранилище.Вставить("Снимок", СтруктураИзОбъектаЛкс(Объект1,,, Истина, Истина, Истина)); // Текстовый снимок 1-го уровня
МассивСравнения.Добавить(Хранилище);
Возврат "Объект для сравнения запомнен";
Иначе
ТаблицаОбъектов = Новый ТаблицаЗначений;
ТаблицаОбъектов.Колонки.Добавить("Объект");
ТаблицаОбъектов.Колонки.Добавить("ПредставлениеОбъекта");
СтрокаОбъекта = ТаблицаОбъектов.Добавить();
СтрокаОбъекта.Объект = Объект2;
СтрокаОбъекта.ПредставлениеОбъекта = Представление2;
СтрокаОбъекта = ТаблицаОбъектов.Добавить();
СтрокаОбъекта.Объект = Объект1;
СтрокаОбъекта.ПредставлениеОбъекта = Представление1;
ТаблицаРазличий = СравнитьТаблицуОбъектовЛкс(ТаблицаОбъектов,,,,, Истина);
РассчитатьРазностиВТаблицеРазличийОбъектовЛкс(ТаблицаОбъектов, ТаблицаРазличий);
ТаблицаРазличий.Колонки.Удалить("Разность1");
Если Истина
И ТаблицаРазличий.Колонки.Найти("Разность2") <> Неопределено
И ТаблицаРазличий.НайтиСтроки(Новый Структура("Разность2")).Количество() >= ТаблицаРазличий.Количество() - 1
Тогда
ТаблицаРазличий.Колонки.Удалить("Разность2");
КонецЕсли;
ТаблицаРазличий.Колонки.Удалить("Представление");
ТаблицаРазличий.Колонки.Удалить("ТипЗначения1");
Возврат ТаблицаРазличий;
КонецЕсли;
КонецФункции
Функция СравнитьТаблицуОбъектовЛкс(ТаблицаОбъектов, Знач ТолькоРазличия = Истина, Знач СвойстваОбъектов = Неопределено, ТипОбъекта = Неопределено, Знач ИмяСвойстваНомерСтороны = "<Номер>",
Знач ЛиПредставленияВВидеТекста = Ложь) Экспорт
Если СвойстваОбъектов = Неопределено Тогда
СвойстваОбъектов = Новый ТаблицаЗначений;
СвойстваОбъектов.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("ОписаниеТипов", Новый ОписаниеТипов("ОписаниеТипов"));
СвойстваОбъектов.Колонки.Добавить("ТипРазличия", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("Значение1");
СвойстваОбъектов.Колонки.Добавить("ПредставлениеЗначения1", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("ЗначениеУстановлено1", Новый ОписаниеТипов("Булево"));
СвойстваОбъектов.Колонки.Добавить("ИмяТипаЗначения1", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("ТипЗначения1", Новый ОписаниеТипов("Строка"));
СвойстваОбъектов.Колонки.Добавить("Разность1", Новый ОписаниеТипов("Строка, Число"));
КонецЕсли;
Если ТаблицаОбъектов.Колонки.Найти("НомерСтороны") = Неопределено Тогда
ТаблицаОбъектов.Колонки.Добавить("НомерСтороны", Новый ОписаниеТипов("Число"));
КонецЕсли;
СтрокаСвойства = СвойстваОбъектов.Добавить();
СтрокаСвойства.Имя = ИмяСвойстваНомерСтороны;
СтрокаСвойства.Представление = ИмяСвойстваНомерСтороны;
ТипОбъекта = "";
Для НомерСтороны = 1 По ТаблицаОбъектов.Количество() Цикл
СтрокаОбъекта = ТаблицаОбъектов[НомерСтороны - 1];
СтрокаОбъекта.НомерСтороны = НомерСтороны;
Объект = СтрокаОбъекта.Объект;
ПоляТаблицыБД = Неопределено;
СтруктураОбъекта = СтруктураИзОбъектаЛкс(Объект, ТипОбъекта, ПоляТаблицыБД);
Для Каждого КлючИЗначение Из СтруктураОбъекта Цикл
СтрокаСвойства = СвойстваОбъектов.Найти(КлючИЗначение.Ключ, "Имя");
Если СтрокаСвойства = Неопределено Тогда
СтрокаСвойства = СвойстваОбъектов.Добавить();
СтрокаСвойства.Имя = КлючИЗначение.Ключ;
Если ПоляТаблицыБД <> Неопределено Тогда
СтрокаПоля = ПоляТаблицыБД.Найти(КлючИЗначение.Ключ, "Имя");
Если СтрокаПоля <> Неопределено Тогда
СтрокаСвойства.Представление = СтрокаПоля.Заголовок;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(СтрокаСвойства.Представление) Тогда
СтрокаСвойства.Представление = СтрокаСвойства.Имя;
КонецЕсли;
КонецЕсли;
ЗначениеСвойства = КлючИЗначение.Значение;
Если СвойстваОбъектов.Колонки.Найти("Значение" + НомерСтороны) = Неопределено Тогда
СвойстваОбъектов.Колонки.Добавить("Значение" + НомерСтороны);
КолонкаТЗ = СвойстваОбъектов.Колонки.Добавить("ПредставлениеЗначения" + НомерСтороны, СвойстваОбъектов.Колонки.ПредставлениеЗначения1.ТипЗначения);
КолонкаТЗ = СвойстваОбъектов.Колонки.Добавить("Разность" + НомерСтороны, СвойстваОбъектов.Колонки.Разность1.ТипЗначения);
СвойстваОбъектов.Колонки.Добавить("ЗначениеУстановлено" + НомерСтороны, Новый ОписаниеТипов("Булево"));
КонецЕсли;
СтрокаСвойства["Значение" + НомерСтороны] = ЗначениеСвойства;
ПредставлениеЗначения = ЗначениеСвойства;
Если ЛиПредставленияВВидеТекста Тогда
ПредставлениеЗначения = РасширенноеПредставлениеЛкс(ЗначениеСвойства,,, Истина, Ложь);
КонецЕсли;
СтрокаСвойства["ПредставлениеЗначения" + НомерСтороны] = ПредставлениеЗначения;
СтрокаСвойства["ЗначениеУстановлено" + НомерСтороны] = Истина;
ОбновитьТипЗначенияВСтрокеТаблицыЛкс(СтрокаСвойства, "Значение" + НомерСтороны,, "ТипЗначения" + НомерСтороны, "ИмяТипаЗначения" + НомерСтороны,, ЗначениеСвойства);
КонецЦикла;
Если СтруктураОбъекта.Количество() Тогда
СтрокаНомераСтороны = СвойстваОбъектов.Найти(ИмяСвойстваНомерСтороны, "Имя");
Если ЛиПредставленияВВидеТекста Тогда
СтрокаНомераСтороны["Значение" + НомерСтороны] = СтрокаОбъекта.ПредставлениеОбъекта;
Иначе
СтрокаНомераСтороны["Значение" + НомерСтороны] = НомерСтороны;
КонецЕсли;
СтрокаНомераСтороны["ПредставлениеЗначения" + НомерСтороны] = НомерСтороны;
СтрокаНомераСтороны["ЗначениеУстановлено" + НомерСтороны] = НомерСтороны;
СтрокаНомераСтороны["Разность" + НомерСтороны] = НомерСтороны;
КонецЕсли;
КонецЦикла;
Если СвойстваОбъектов.Количество() > 1 Тогда
Для Каждого СтрокаСвойства Из СвойстваОбъектов Цикл
Если СтрокаСвойства.Имя = ИмяСвойстваНомерСтороны Тогда
СтрокаСвойства.ОписаниеТипов = Новый ОписаниеТипов("Число");
Продолжить;
КонецЕсли;
МассивТипов = Новый Массив;
Если СтрокаСвойства.ЗначениеУстановлено1 И Не СтрокаСвойства.ЗначениеУстановлено2 Тогда
СтрокаСвойства.ТипРазличия = "Только 1";
МассивТипов.Добавить(ТипЗнч(СтрокаСвойства["Значение1"]));
ИначеЕсли СтрокаСвойства.ЗначениеУстановлено2 И Не СтрокаСвойства.ЗначениеУстановлено1 Тогда
СтрокаСвойства.ТипРазличия = "Только 2";
МассивТипов.Добавить(ТипЗнч(СтрокаСвойства["Значение2"]));
Иначе
Значение1 = СтрокаСвойства["Значение1"];
СтрокаЗначения1 = ирОбщий.ОбъектВСтрокуДляСравненияВнутрЛкс(Значение1);
МассивТипов.Добавить(ТипЗнч(Значение1));
Для Счетчик = 2 По ТаблицаОбъектов.Количество() Цикл
ЗначениеХ = СтрокаСвойства["Значение" + Счетчик];
СтрокаЗначенияХ = ирОбщий.ОбъектВСтрокуДляСравненияВнутрЛкс(ЗначениеХ);
МассивТипов.Добавить(ТипЗнч(ЗначениеХ));
Если Ложь
Или СтрокаСвойства.ТипРазличия = "Изменено"
Или (Истина
//И Не ирОбщий.ЛиКоллекцияЛкс(Значение1)
И Значение1 = ЗначениеХ)
Или (Истина
И СтрокаЗначения1 <> Неопределено
И СтрокаЗначенияХ <> Неопределено
И СтрокаЗначения1 = СтрокаЗначенияХ)
Тогда
Иначе
СтрокаСвойства.ТипРазличия = "Изменено";
КонецЕсли;
КонецЦикла;
КонецЕсли;
СтрокаСвойства.ОписаниеТипов = Новый ОписаниеТипов(МассивТипов);
КонецЦикла;
СвойстваОбъектов.Сортировать("Имя");
Если ТолькоРазличия Тогда
Для Каждого СтрокаРавныхЗначений Из СвойстваОбъектов.НайтиСтроки(Новый Структура("ТипРазличия", "")) Цикл
Если СтрокаРавныхЗначений.Имя = ИмяСвойстваНомерСтороны Тогда
Продолжить;
КонецЕсли;
СвойстваОбъектов.Удалить(СтрокаРавныхЗначений);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат СвойстваОбъектов;
КонецФункции
Процедура РассчитатьРазностиВТаблицеРазличийОбъектовЛкс(Знач ТаблицаОбъектов, Знач СвойстваОбъектов, Знач НомерЭталона = 1, Знач ИмяСвойстваНомерСтороны = "<Номер>") Экспорт
Для Каждого СтрокаСвойства Из СвойстваОбъектов Цикл
Если СтрокаСвойства.Имя = ИмяСвойстваНомерСтороны Тогда
Продолжить;
КонецЕсли;
ЗначениеЭталона = Неопределено;
Если Истина
И СтрокаСвойства.ОписаниеТипов.СодержитТип(Тип("Число"))
И НомерЭталона <> Неопределено
Тогда
ЗначениеЭталона = СтрокаСвойства["Значение" + НомерЭталона];
КонецЕсли;
Для каждого СтрокаОбъекта Из ТаблицаОбъектов Цикл
РазностьЗначения = Неопределено;
Если ТипЗнч(ЗначениеЭталона) = Тип("Число") Тогда
ЗначениеСвойства = СтрокаСвойства["Значение" + СтрокаОбъекта.НомерСтороны];
Если ТипЗнч(ЗначениеСвойства) = Тип("Число") Тогда
РазностьЗначения = ЗначениеСвойства - ЗначениеЭталона;
КонецЕсли;
КонецЕсли;
СтрокаСвойства["Разность" + СтрокаОбъекта.НомерСтороны] = РазностьЗначения;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция КоличествоОшибокВЖурналеЛкс(Знач Начало, Знач Конец, Знач СтруктураОтбора, Знач МаксимальныйРазмерВыгрузки = Неопределено) Экспорт
АнализЖурналаРегистрации = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирАнализЖурналаРегистрации");
#Если Сервер И Не Сервер Тогда
АнализЖурналаРегистрации = Обработки.ирАнализЖурналаРегистрации.Создать();
#КонецЕсли
СобытияЗадания = АнализЖурналаРегистрации.ПолучитьДанные(Начало, Конец, СтруктураОтбора, МаксимальныйРазмерВыгрузки);
КоличествоОшибокВЖурнале = СобытияЗадания.Количество();
Возврат КоличествоОшибокВЖурнале;
КонецФункции
Функция ШаблонРазметкиВхожденийЛкс() Экспорт
// https://unicode-table.com/ru/sets/brackets/
Результат = ирКэш.Получить().ВыделениеРезультатовПоиска;
Результат = Лев(Результат, 1) + "$1" + Прав(Результат, 1);
Возврат Результат;
КонецФункции
Процедура ДобавитьСловаПоискаВСтруктуруРеквизитовЛкс(Знач ИмяСвойства, Знач Слово, Знач СловаПоСвойствам) Экспорт
Слова = Неопределено;
Если Не СловаПоСвойствам.Свойство(ИмяСвойства, Слова) Тогда
Слова = Новый Массив;
СловаПоСвойствам.Вставить(ИмяСвойства, Слова);
КонецЕсли;
Если Слова.Найти(Слово) = Неопределено Тогда
Слова.Добавить(Слово);
КонецЕсли;
КонецПроцедуры
Функция СловаПоискаПоКолонкамИзОтбораКомпоновкиЛкс(Знач Отбор) Экспорт
СловаПоСвойствам = Новый Структура;
#Если Сервер И Не Сервер Тогда
Отбор = Новый НастройкиКомпоновкиДанных;
Отбор = Отбор.Отбор;
#КонецЕсли
Для Каждого ЭлементОтбора Из Отбор.Элементы Цикл
Если Истина
И ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбора.Использование
И ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит
И ЭлементОтбора.ПравоеЗначение <> ""
Тогда
ДобавитьСловаПоискаВСтруктуруРеквизитовЛкс(СтрЗаменить(ЭлементОтбора.ЛевоеЗначение, ".", "_"), ЭлементОтбора.ПравоеЗначение, СловаПоСвойствам);
КонецЕсли;
КонецЦикла;
Возврат СловаПоСвойствам;
КонецФункции
Функция КоличествоИзмененийПоУзлуЛкс(Узел, МассивМетаданных = Неопределено) Экспорт
#Если Клиент Тогда
СостояниеЛкс("Вычисление количества изменений на узле…");
#КонецЕсли
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Узел", Узел);
МетаПланОбмена = Узел.Метаданные();
ТекстЗапроса = "";
Для Каждого ЭлементСОстава Из МетаПланОбмена.Состав Цикл
МетаОбъект = ЭлементСОстава.Метаданные;
Если Ложь
Или МетаОбъект = Неопределено
Или (Истина
И МассивМетаданных <> Неопределено
И МассивМетаданных.Найти(МетаОбъект) = Неопределено)
Тогда
Продолжить;
КонецЕсли;
ИмяТаблицыДляПоискаЗарегистрированных = ирКэш.ИмяТаблицыИзМетаданныхЛкс(МетаОбъект.ПолноеИмя(), Истина);
Если ИмяТаблицыДляПоискаЗарегистрированных = Неопределено Тогда
Продолжить;
КонецЕсли;
Если ТекстЗапроса <> "" Тогда
ТекстЗапроса = ТекстЗапроса + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС;
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ Количество(*) КАК Количество
|ИЗ
| " + ИмяТаблицыДляПоискаЗарегистрированных + " КАК РегистрацияИзменений
|ГДЕ
| РегистрацияИзменений.Узел = &Узел
|";
КонецЦикла;
Если ТекстЗапроса <> "" Тогда
Запрос.Текст = ТекстЗапроса;
ТаблицаКоличестваИзменений = Запрос.Выполнить().Выгрузить();
КоличествоИзменений = ТаблицаКоличестваИзменений.Итог("Количество");
Иначе
КоличествоИзменений = 0;
КонецЕсли;
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
Возврат КоличествоИзменений;
КонецФункции
// .
// Параметры:
// СтрокаТаблицыИлиДерева - СтрокаТаблицыЗначений, СтрокаДереваЗначений, ВыборкаИзРезультатаЗапроса
// Результат - Структура
Функция СтруктураИзСтрокиТаблицыИлиДереваИлиВыборкиЛкс(СтрокаТаблицыИлиДереваИлиВыборки) Экспорт
Результат = Новый Структура;
Для Каждого МетаРеквизит Из СтрокаТаблицыИлиДереваИлиВыборки.Владелец().Колонки Цикл
Если ЗначениеЗаполнено(МетаРеквизит.Имя) Тогда // В значении перетаскивания платформа делает копию таблицы и добавляет в нее колонку с пустым именем
Результат.Вставить(МетаРеквизит.Имя, СтрокаТаблицыИлиДереваИлиВыборки[МетаРеквизит.Имя]);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Получает структуру свойств объекта по имени типа или объекту.
//
// Параметры:
// ОбъектИлиТип - Произвольный - имя типа или сам объект;
//
// Возвращаемое значение:
// - Структура - свойств.
//
Функция СтруктураСвойствСтрокиТаблицыИлиДереваЛкс(ОбъектИлиТип) Экспорт
СтруктураСвойств = Новый Структура;
ТипОбъекта = ТипЗнч(ОбъектИлиТип);
МетаОбъект = ПолучитьМетаданныеЛкс(ТипОбъекта);
Если МетаОбъект <> Неопределено Тогда
КорневойТип = КорневойТипКонфигурацииЛкс(МетаОбъект, Истина);
Если Ложь
ИЛИ КорневойТип = "Обработка"
ИЛИ КорневойТип = "Отчет"
Тогда
Для Каждого МетаРеквизит Из МетаОбъект.Реквизиты Цикл
СтруктураСвойств.Вставить(МетаРеквизит.Имя);
КонецЦикла;
Для Каждого МетаРеквизит Из МетаОбъект.ТабличныеЧасти Цикл
СтруктураСвойств.Вставить(МетаРеквизит.Имя);
КонецЦикла;
КонецЕсли;
Если КорневойТипСтрокиТабличнойЧастиЛкс(ТипОбъекта) <> Неопределено Тогда
Для Каждого МетаРеквизит Из МетаОбъект.Реквизиты Цикл
СтруктураСвойств.Вставить(МетаРеквизит.Имя);
КонецЦикла;
КонецЕсли;
ИначеЕсли Ложь
Или ТипОбъекта = Тип("СтрокаТаблицыЗначений")
Или ТипОбъекта = Тип("СтрокаДереваЗначений")
Тогда
//! ОбъектИлиТип = 0 // СтрокаТаблицыЗначений
Попытка
МетаОбъект = ОбъектИлиТип.Владелец();
Исключение
// Строка была удалена
МетаОбъект = Неопределено;
КонецПопытки;
Если МетаОбъект <> Неопределено Тогда
Для Каждого МетаРеквизит Из МетаОбъект.Колонки Цикл
СтруктураСвойств.Вставить(МетаРеквизит.Имя);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат СтруктураСвойств;
КонецФункции
// Переустанавливает значения недоступных параметров из схемы https://partners.v8.1c.ru/forum/t/690982/m/691218 .
//
// Параметры:
// СхемаКомпоновкиДанных - СхемаКомпоновкиДанных;
// КомпоновщикНастроек - КомпоновщикНастроекКомпоновкиДанных.
//
Процедура ОбновитьЗначенияНедоступныхПараметровИзСхемыЛкс(Знач КомпоновщикНастроек, Знач СхемаКомпоновкиДанных, Знач ТолькоНеиспользуемые = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Для Каждого ЗначениеПараметра Из КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы Цикл
ПараметрСхемы = СхемаКомпоновкиДанных.Параметры.Найти("" + ЗначениеПараметра.Параметр);
Если Истина
И ПараметрСхемы <> Неопределено
И ПараметрСхемы.ОграничениеИспользования
И (Ложь
Или Не ТолькоНеиспользуемые
Или Не ЗначениеПараметра.Использование)
Тогда
//Если ЗначениеЗаполнено(ЗначениеПараметра.Выражение) Тогда
// Попытка
// ЗначениеПараметра.Значение = Вычислить();
// Исключение
// КонецПопытки;
//Иначе
ЗначениеПараметра.Значение = ПараметрСхемы.Значение;
//КонецЕсли;
//ЗначениеПараметра.Использование = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ДобавитьВСхемуКомпоновкиАвтополеКоличествоСтрокЛкс(СхемаКомпоновкиДанных) Экспорт
ПолеКоличества = "КоличествоСтрокАвто";
ВычисляемоеПоле = СхемаКомпоновкиДанных.ВычисляемыеПоля.Добавить();
ВычисляемоеПоле.Выражение = "1";
ВычисляемоеПоле.Заголовок = "Количество строк (авто)";
ВычисляемоеПоле.ПутьКДанным = ПолеКоличества;
РесурсКоличествоЗаписей = СхемаКомпоновкиДанных.ПоляИтога.Добавить();
РесурсКоличествоЗаписей.ПутьКДанным = ПолеКоличества;
РесурсКоличествоЗаписей.Выражение = "Сумма(1)";
КонецПроцедуры
Функция СоздатьСхемуПоТаблицеЗначенийЛкс(Знач ТаблицаЗначений, выхНаборыДанных = Неопределено, Знач ТаблицаБезДанныхСУзкимиТипами = Неопределено, Знач ДобавитьФиктивноеПоле = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
Если ТаблицаБезДанныхСУзкимиТипами = Неопределено Тогда
ТаблицаБезДанныхСУзкимиТипами = ТаблицаЗначений;
КонецЕсли;
выхНаборыДанных = Новый Структура("ТаблицаЗначений", ТаблицаБезДанныхСУзкимиТипами);
Схема = СоздатьСхемуПоТаблицамЗначенийЛкс(выхНаборыДанных,,,, Ложь, ДобавитьФиктивноеПоле);
выхНаборыДанных.ТаблицаЗначений = ТаблицаЗначений;
Возврат Схема;
КонецФункции
// Создает новую или добавляет в существующую схему компоновки наборы данных объекты из структуры таблиц значений.
//
// Параметры:
// СтруктураТаблиц - Структура - <описание параметра>
// <продолжение описания параметра>;
// <Параметр2> - <Тип.Вид> - <описание параметра>
// <продолжение описания параметра>.
//
Функция СоздатьСхемуПоТаблицамЗначенийЛкс(СтруктураТаблиц, СхемаКомпоновкиДанных = Неопределено, СоздаватьПапкиПолей = Ложь, СоздаватьРесурсыЧисловыхПолей = Ложь,
ДобавитьАвтополеКоличествоСтрок = Истина, Знач ДобавитьФиктивноеПоле = Ложь, Знач РазрешитьПостроениеИерархииВДеревьях = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
СтруктураТаблиц = Новый Структура;
#КонецЕсли
Если СхемаКомпоновкиДанных = Неопределено Тогда
СхемаКомпоновкиДанных = СоздатьСхемуКомпоновкиЛкс();
КонецЕсли;
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Для Каждого КлючИЗначение Из СтруктураТаблиц Цикл
КолонкиНабора = КолонкиИсточникаДанныхЛкс(КлючИЗначение.Значение);
Если РазрешитьПостроениеИерархииВДеревьях И ТипЗнч(КлючИЗначение.Значение) = Тип("ДеревоЗначений") Тогда
#Если Сервер И Не Сервер Тогда
КолонкиНабора1 = Новый ТаблицаЗначений;
КолонкиНабора = КолонкиНабора1.Колонки;
#КонецЕсли
Дерево = КлючИЗначение.Значение;
#Если Сервер И Не Сервер Тогда
Дерево = Новый ДеревоЗначений;
#КонецЕсли
ИмяКлюча = ИмяКлючаСтрокиДереваЛкс();
ИмяКлючаРодителя = ИмяКлючаСтрокиРодителяЛкс();
Колонка = КолонкиНабора.Найти(ИмяКлюча);
//Если Колонка <> Неопределено И Не Колонка.ТипЗначения.СодержитТип(Тип("Число")) Тогда
// ИмяКлюча = ИмяКлюча + СуффиксСлужебногоСвойстваЛкс();
// ИмяКлючаРодителя = ИмяКлючаРодителя + СуффиксСлужебногоСвойстваЛкс();
//КонецЕсли;
Если КолонкиНабора.Найти(ИмяКлюча) = Неопределено Тогда
Дерево.Колонки.Добавить(ИмяКлюча, Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить(ИмяКлючаРодителя, Новый ОписаниеТипов("Число"));
КонецЕсли;
Счетчик = 1;
Для Каждого СтрокаДерева Из ВсеСтрокиДереваЗначенийЛкс(Дерево) Цикл
СтрокаДерева[ИмяКлюча] = Счетчик;
Если СтрокаДерева.Родитель <> Неопределено Тогда
СтрокаДерева[ИмяКлючаРодителя] = СтрокаДерева.Родитель[ИмяКлюча];
КонецЕсли;
Счетчик = Счетчик + 1;
КонецЦикла;
Связь = СхемаКомпоновкиДанных.СвязиНаборовДанных.Добавить();
Связь.НаборДанныхИсточник = КлючИЗначение.Ключ;
Связь.НаборДанныхПриемник = КлючИЗначение.Ключ;
Связь.ВыражениеИсточник = ИмяКлюча;
Связь.ВыражениеПриемник = ИмяКлючаРодителя;
Связь.НачальноеВыражение = "0";
КонецЕсли;
СоздатьИлиОбновитьНаборДанныхОбъектПоМетаданнымЛкс(СхемаКомпоновкиДанных, КолонкиНабора, КлючИЗначение.Ключ, СоздаватьПапкиПолей, СоздаватьРесурсыЧисловыхПолей, КлючИЗначение.Значение);
КонецЦикла;
Если ДобавитьАвтополеКоличествоСтрок Тогда
ДобавитьВСхемуКомпоновкиАвтополеКоличествоСтрокЛкс(СхемаКомпоновкиДанных);
КонецЕсли;
Если ДобавитьФиктивноеПоле Тогда
// Антибаг платформы 8.3 https://www.hostedredmine.com/issues/950769
ФиктивноеПоле = СхемаКомпоновкиДанных.НаборыДанных[0].Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ФиктивноеПоле.ПутьКДанным = ИмяФиктивногоПоляСхемыКомпоновкиЛкс();
УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ФиктивноеПоле, Истина, Истина, Истина, Истина);
КонецЕсли;
Возврат СхемаКомпоновкиДанных;
КонецФункции
Функция ИмяКлючаСтрокиДереваЛкс() Экспорт
Возврат "_КлючСтрокиДерева";
КонецФункции
Функция ИмяКлючаСтрокиРодителяЛкс() Экспорт
Возврат "_КлючСтрокиРодителя";
КонецФункции
Функция СоздатьСхемуКомпоновкиЛкс() Экспорт
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
ДобавитьЛокальныйИсточникДанныхЛкс(СхемаКомпоновкиДанных);
Возврат СхемаКомпоновкиДанных;
КонецФункции
Функция КолонкиИсточникаДанныхЛкс(Знач ИсточникДанных)
Если Ложь
Или ТипЗнч(ИсточникДанных) = Тип("ДеревоЗначений")
Или ТипЗнч(ИсточникДанных) = Тип("ТаблицаЗначений")
Тогда
КолонкиНабора = ИсточникДанных.Колонки;
Иначе
//! ИсточникДанных = 0 // ТабличнаяЧасть
КолонкиНабора = ИсточникДанных.ВыгрузитьКолонки().Колонки;
КонецЕсли;
Возврат КолонкиНабора;
КонецФункции
// Создает новую или добавляет в существующую схему компоновки набор данных объект из полей настройки.
//
// Параметры:
// ПоляНастройки - ПоляНастройки - <описание параметра>
// <продолжение описания параметра>;
// <Параметр2> - <Тип.Вид> - <описание параметра>
// <продолжение описания параметра>.
//
Функция СоздатьСхемуПоПолямНастройкиЛкс(ПоляНастройки, СхемаКомпоновкиДанных = Неопределено, ИмяНабора = "Основной") Экспорт
Если СхемаКомпоновкиДанных = Неопределено Тогда
СхемаКомпоновкиДанных = СоздатьСхемуКомпоновкиЛкс();
КонецЕсли;
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
НаборДанных = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
НаборДанных.Имя = ИмяНабора;
НаборДанных.ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных[0].Имя;
НаборДанных.ИмяОбъекта = ИмяНабора;
Для Каждого ПолеНастройки Из ПоляНастройки Цикл
Поле = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Поле.ПутьКДанным = ПолеНастройки.Имя;
Поле.Поле = ПолеНастройки.ПутьКДанным;
Поле.Заголовок = ПолеНастройки.Представление;
Поле.ТипЗначения = ПолеНастройки.ТипЗначения;
ОграничениеИспользования = Поле.ОграничениеИспользования;
ОграничениеИспользования.Поле = Не ПолеНастройки.Поле;
ОграничениеИспользования.Условие = Не ПолеНастройки.Отбор;
ОграничениеИспользования.Порядок = Не ПолеНастройки.Порядок;
ОграничениеИспользования.Группировка = Не ПолеНастройки.Измерение;
ЗначениеОграничения = ПолеНастройки.Поля.Количество() = 0;
ОграничениеИспользованияРеквизитов = Поле.ОграничениеИспользованияРеквизитов;
ОграничениеИспользованияРеквизитов.Поле = ЗначениеОграничения;
ОграничениеИспользованияРеквизитов.Условие = ЗначениеОграничения;
ОграничениеИспользованияРеквизитов.Порядок = ЗначениеОграничения;
ОграничениеИспользованияРеквизитов.Группировка = ЗначениеОграничения;
КонецЦикла;
Возврат СхемаКомпоновкиДанных;
КонецФункции
Функция УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(Знач ПолеИлиОграничениеИспользования, Знач Ограничивать = Ложь, Знач ПрименитьГруппировка = Истина,
Знач ПрименитьПоле = Истина, Знач ПрименитьПорядок = Истина, Знач ПрименитьУсловие = Истина) Экспорт
МассивГруппОграничений = Новый Массив;
Если ТипЗнч(ПолеИлиОграничениеИспользования) = Тип("ОграничениеИспользованияПоляСхемыКомпоновкиДанных") Тогда
МассивГруппОграничений.Добавить(ПолеИлиОграничениеИспользования);
Иначе
Поле = ПолеИлиОграничениеИспользования; // ПолеНабораДанныхСхемыКомпоновкиДанных
МассивГруппОграничений.Добавить(Поле.ОграничениеИспользования);
Попытка
МассивГруппОграничений.Добавить(Поле.ОграничениеИспользованияРеквизитов);
Исключение
КонецПопытки;
КонецЕсли;
Для Каждого ОграничениеИспользования Из МассивГруппОграничений Цикл
Если ПрименитьГруппировка Тогда
ОграничениеИспользования.Группировка = Ограничивать;
КонецЕсли;
Если ПрименитьПоле Тогда
ОграничениеИспользования.Поле = Ограничивать;
КонецЕсли;
Если ПрименитьПорядок Тогда
ОграничениеИспользования.Порядок = Ограничивать;
КонецЕсли;
Если ПрименитьУсловие Тогда
ОграничениеИспользования.Условие = Ограничивать;
КонецЕсли;
КонецЦикла;
КонецФункции
// Функция добавляет в схему компоновки источник данных с типом "Local"
Функция ДобавитьЛокальныйИсточникДанныхЛкс(СхемаКомпоновкиДанных) Экспорт
ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить();
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
Возврат ИсточникДанных;
КонецФункции
// Функция добавляет набор данных - запрос в указанную в параметре коллекцию наборов данных
Функция ДобавитьНаборДанныхЗапросЛкс(НаборыДанных, ИсточникДанных, ИмяНабораДанных = "Основной") Экспорт
НаборДанных = НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = ИмяНабораДанных;
НаборДанных.ИсточникДанных = ИсточникДанных.Имя;
Возврат НаборДанных;
КонецФункции
Функция МассивВСписокЗначенийЛкс(Знач Массив) Экспорт
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(Массив);
Возврат Список;
КонецФункции
// Получает строку путем отсечения заданного числа последних символов.
//
// Параметры:
// пСтрока - Строка - исходная;
// пДлинаКонца - Число, *1 - количество отсекаемых символов;
//
// Возвращаемое значение:
// - Строка.
//
Функция СтрокаБезКонцаЛкс(пСтрока, пДлинаКонца = 1) Экспорт
Если СтрДлина(пСтрока) < пДлинаКонца Тогда
Возврат "";
Иначе
Возврат Лев(пСтрока, СтрДлина(пСтрока) - пДлинаКонца);
КонецЕсли;
КонецФункции
// Разделитель тоже удаляется.
Функция СтрокаБезПервогоФрагментаЛкс(Знач Строка, Знач Разделитель = ".", Знач БратьГраницуЕслиНеНайден = Ложь) Экспорт
Позиция = Найти(Строка, Разделитель);
Если Позиция = 0 Тогда
Если БратьГраницуЕслиНеНайден Тогда
Результат = Строка;
Иначе
Результат = "";
КонецЕсли;
Иначе
Результат = Сред(Строка, Позиция + СтрДлина(Разделитель));
КонецЕсли;
Возврат Результат;
КонецФункции
// Разделитель тоже удаляется.
Функция СтрокаБезПоследнегоФрагментаЛкс(Знач Строка, Знач Разделитель = ".", Знач БратьГраницуЕслиНеНайден = Ложь) Экспорт
Позиция = СтрНайтиЛкс(Строка, Разделитель, Истина);
Если Позиция = 0 Тогда
Если БратьГраницуЕслиНеНайден Тогда
Результат = Строка;
Иначе
Результат = "";
КонецЕсли;
Иначе
Результат = Лев(Строка, Позиция - 1);
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает строку путем повтора переданной строки заданное количество раз.
//
// Параметры:
// СтрокаДляПовтора - Строка;
// ЧислоПовторов - Число.
//
// Возвращаемое значение:
// Строка.
//
Функция СтрокаПовторомЛкс(СтрокаДляПовтора, ЧислоПовторов) Экспорт
Результат = "";
Для Счетчик = 1 По ЧислоПовторов Цикл
Результат = Результат + СтрокаДляПовтора;
КонецЦикла;
Возврат Результат;
КонецФункции
// Преобразует исходную строку в число без вызова исключений.
//
// Параметры:
// Значение - Строка - строка, которую необходимо привести к числу.
// Например, "10", "+10", "010", вернет 10;
// "(10)", "-10",вернет -10;
// "10,2", "10.2",вернет 10.2;
// "000", " ", "",вернет 0;
// "10текст", вернет Неопределено
// "3 312", вернет 3312
// ОписаниеТипов - ОписаниеТипов - Допустимое описание типов численного значения
// выхПримечание - Строка - описание ошибки
//
// Возвращаемое значение:
// Число - полученное число.
//
Функция СтрокаВЧислоЛкс(Представление, Знач ОписаниеТипов = Неопределено, выхПримечание = "") Экспорт
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Если ОписаниеТипов = Неопределено Тогда
ОписаниеТипов = Новый ОписаниеТипов("Число");
КонецЕсли;
НРегПредставление = НРег(Представление);
Если Ложь
Или НРегПредставление = "да"
Или НРегПредставление = "yes"
или НРегПредставление = "истина"
Или НРегПредставление = "true"
или НРегПредставление = "включено"
или НРегПредставление = "on"
Тогда
Возврат 1;
ИначеЕсли Ложь
Или НРегПредставление = "нет"
Или НРегПредставление = "no"
или НРегПредставление = "ложь"
Или НРегПредставление = "false"
или НРегПредставление = "выключено"
или НРегПредставление = "off"
Тогда
Возврат 0;
КонецЕсли;
Результат = Представление;
Результат = СтрЗаменить(Результат, " ", "");
Результат = СтрЗаменить(Результат, "−", "-");
Если Найти(Результат, ",") > 0 И Найти(Результат, ".") > 0 Тогда
Результат = СтрЗаменить(Результат, ",", "");
КонецЕсли;
Попытка
Результат = Число(Результат);
Исключение
Результат = СокрП(Результат);
Если Прав(Результат, 1) = "%" Тогда
Результат = СтрокаБезКонцаЛкс(Результат, 1);
Попытка
Результат = Число(Результат) / 100;
Исключение
КонецПопытки;
КонецЕсли;
КонецПопытки;
Если ТипЗнч(Результат) = Тип("Строка") Тогда
Если ОписаниеТипов.СодержитТип(Тип("Булево")) Тогда
ИмяТипа = "булева";
Иначе
ИмяТипа = "числа";
КонецЕсли;
выхПримечание = "Неправильный формат " + ИмяТипа;
Возврат 0;
КонецЕсли;
Результат1 = ОписаниеТипов.ПривестиЗначение(Результат);
Если Результат1 <> Результат Тогда
выхПримечание = "Числовое значение вне границ типа";
КонецЕсли;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если ОписаниеТипов = Неопределено Тогда ОписаниеТипов = Новый ОписаниеТипов("Число"); КонецЕсли; НРегПредставление = НРег(Представление); Если Ложь Или НРегПредставление = "да" Или НРегПредставление = "yes" или НРегПредставление = "истина" Или НРегПредставление = "true" или НРегПредставление = "включено" или НРегПредставление = "on" Тогда Возврат 1; ИначеЕсли Ложь Или НРегПредставление = "нет" Или НРегПредставление = "no" или НРегПредставление = "ложь" Или НРегПредставление = "false" или НРегПредставление = "выключено" или НРегПредставление = "off" Тогда Возврат 0; КонецЕсли; Результат = Представление; Результат = СтрЗаменить(Результат, " ", ""); Результат = СтрЗаменить(Результат, "−", "-"); Если Найти(Результат, ",") > 0 И Найти(Результат, ".") > 0 Тогда Результат = СтрЗаменить(Результат, ",", ""); КонецЕсли; Попытка Результат = Число(Результат); Исключение Результат = СокрП(Результат); Если Прав(Результат, 1) = "%" Тогда Результат = СтрокаБезКонцаЛкс(Результат, 1); Попытка Результат = Число(Результат) / 100; Исключение КонецПопытки; КонецЕсли; КонецПопытки; Если ТипЗнч(Результат) = Тип("Строка") Тогда Если ОписаниеТипов.СодержитТип(Тип("Булево")) Тогда ИмяТипа = "булева"; Иначе ИмяТипа = "числа"; КонецЕсли; выхПримечание = "Неправильный формат " + ИмяТипа; Возврат 0; КонецЕсли; Результат1 = ОписаниеТипов.ПривестиЗначение(Результат); Если Результат1 <> Результат Тогда выхПримечание = "Числовое значение вне границ типа"; КонецЕсли;
КонецЕсли;
Возврат Результат1;
КонецФункции
// Функция возвращает части представления даты
//
// Параметры:
// Представление - Представление даты
//
// Возвращаемое значение:
// массив частей даты
//
Функция ЧастиПредставленияДаты(Знач Представление, выхПозицияГода = Неопределено)
МассивЧастей = Новый Массив;
НачалоЧисла = 0;
// TODO переделать на рег. выражения
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для к = 1 По СтрДлина(Представление) Цикл
Символ = Сред(Представление, к ,1);
Если ЛиЦифраЛкс(Символ) Тогда
Если НачалоЧисла = 0 Тогда
НачалоЧисла = к;
КонецЕсли;
Иначе
Если НачалоЧисла <> 0 Тогда
СтрокаЧисла = Сред(Представление, НачалоЧисла, к - НачалоЧисла);
Если СтрДлина(СтрокаЧисла) = 4 Тогда
выхПозицияГода = МассивЧастей.Количество();
КонецЕсли;
МассивЧастей.Добавить(Число(СтрокаЧисла));
КонецЕсли;
НачалоЧисла = 0;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для к = 1 По СтрДлина(Представление) Цикл Символ = Сред(Представление, к ,1); Если ЛиЦифраЛкс(Символ) Тогда Если НачалоЧисла = 0 Тогда НачалоЧисла = к; КонецЕсли; Иначе Если НачалоЧисла <> 0 Тогда СтрокаЧисла = Сред(Представление, НачалоЧисла, к - НачалоЧисла); Если СтрДлина(СтрокаЧисла) = 4 Тогда выхПозицияГода = МассивЧастей.Количество(); КонецЕсли; МассивЧастей.Добавить(Число(СтрокаЧисла)); КонецЕсли; НачалоЧисла = 0; КонецЕсли; КонецЦикла;
КонецЕсли;
Если НачалоЧисла <> 0 Тогда
МассивЧастей.Добавить(Число(Сред(Представление, НачалоЧисла)));
КонецЕсли;
Возврат МассивЧастей;
КонецФункции
// Функция приводит строковое представление даты к его значению
//
// Параметры:
// Представление - Представление числа
// ОписаниеТипов - Допустимое описание типов значения типа дата
//
// Возвращаемое значение:
// Значение типа дата
//
Функция СтрокаВДатуЛкс(Представление, ОписаниеТипов = Неопределено, выхПримечание = "", АмериканскоеПоложениеМесяца = Ложь) Экспорт
Если ОписаниеТипов = Неопределено Тогда
ОписаниеТипов = Новый ОписаниеТипов("Дата");
КонецЕсли;
Результат = ОписаниеТипов.ПривестиЗначение(Представление);
Если Результат = '00010101' Тогда
ЛиНеправильныйФормат = Ложь;
ПозицияГода = Неопределено;
МассивЧастей = ЧастиПредставленияДаты(Представление, ПозицияГода);
Если ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Время Тогда
Попытка
Если МассивЧастей.Количество() = 3 Тогда
Результат = Дата(1,1,1, МассивЧастей[0], МассивЧастей[1], МассивЧастей[2]);
ИначеЕсли МассивЧастей.Количество() = 6 Тогда
Результат = Дата(1,1,1, МассивЧастей[3], МассивЧастей[4], МассивЧастей[5]);
КонецЕсли;
Исключение
ЛиНеправильныйФормат = Истина;
КонецПопытки;
ИначеЕсли Ложь
Или МассивЧастей.Количество() = 3
Или МассивЧастей.Количество() = 6
Или МассивЧастей.Количество() = 7 // С миллисекундами. Просто выбрасываем их
Тогда
Если МассивЧастей[0] >= 1000 Тогда
ПозицияГода = 0;
КонецЕсли;
Если Истина
И ПозицияГода <> Неопределено
И ПозицияГода <> 2
Тогда
Временно = МассивЧастей[ПозицияГода];
МассивЧастей[ПозицияГода] = МассивЧастей[2];
МассивЧастей[2] = Временно;
КонецЕсли;
// Теперь год всегда на 3-й позиции (индекс=2)
Если МассивЧастей[2] < 100 Тогда
МассивЧастей[2] = МассивЧастей[2] + ?(МассивЧастей[2] < 30, 2000,1900);
КонецЕсли;
//Если МассивЧастей.Количество() = 7 Тогда
// ДробнаяЧасть = МассивЧастей[7];
//Иначе
// ДробнаяЧасть = 0;
//КонецЕсли;
Если АмериканскоеПоложениеМесяца Тогда
Временно = МассивЧастей[0];
МассивЧастей[0] = МассивЧастей[1];
МассивЧастей[1] = Временно;
КонецЕсли;
Попытка
Если МассивЧастей.Количество() = 3 или ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда
Результат = Дата(МассивЧастей[2], МассивЧастей[1], МассивЧастей[0]);
Иначе
Результат = Дата(МассивЧастей[2], МассивЧастей[1], МассивЧастей[0], МассивЧастей[3], МассивЧастей[4], МассивЧастей[5]);
КонецЕсли;
Исключение
ЛиНеправильныйФормат = Истина;
КонецПопытки;
Иначе
ЛиНеправильныйФормат = Истина;
КонецЕсли;
Если ЛиНеправильныйФормат Тогда
выхПримечание = "Неправильный формат даты";
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Разделяет URL по составным частям: протокол, сервер, путь к ресурсу.
//
// Параметры:
// URL - Строка - ссылка на ресурс в сети Интернет
//
// Возвращаемое значение:
// Структура:
// Протокол - Строка - протокол доступа к ресурсу
// ИмяСервера - Строка - сервер, на котором располагается ресурс
// ПутьКФайлуНаСервере - Строка - путь к ресурсу на сервере
//
Функция РазделитьURLЛкс(Знач URL) Экспорт
СтруктураURL = СтруктураURIЛкс(URL);
Результат = Новый Структура;
Результат.Вставить("Протокол", ?(ПустаяСтрока(СтруктураURL.Схема), "http", СтруктураURL.Схема));
Результат.Вставить("ИмяСервера", СтруктураURL.ИмяСервера);
Результат.Вставить("ПутьКФайлуНаСервере", СтруктураURL.ПутьНаСервере);
Возврат Результат;
КонецФункции
// Разбирает строку URI на составные части и возвращает в виде структуры.
// На основе RFC 3986.
//
// Параметры:
// СтрокаURI - Строка - ссылка на ресурс в формате: <схема>://<логин>:<пароль>@<хост>:<порт>/<путь>?<параметры>#<якорь>
//
// Возвращаемое значение:
// Структура - составные части URI согласно формату:
// * Схема - Строка
// * Логин - Строка
// * Пароль - Строка
// * ИмяСервера - Строка - часть <хост>:<порт> входного параметра
// * Хост - Строка
// * Порт - Строка
// * ПутьНаСервере - Строка - часть <путь>?<параметры>#<якорь> входного параметра
//
Функция СтруктураURIЛкс(Знач СтрокаURI) Экспорт
СтрокаURI = СокрЛП(СтрокаURI);
// схема
Схема = "";
Позиция = Найти(СтрокаURI, "://");
Если Позиция > 0 Тогда
Схема = НРег(Лев(СтрокаURI, Позиция - 1));
СтрокаURI = Сред(СтрокаURI, Позиция + 3);
КонецЕсли;
// строка соединения и путь на сервере
СтрокаСоединения = СтрокаURI;
ПутьНаСервере = "";
Позиция = Найти(СтрокаСоединения, "/");
Если Позиция > 0 Тогда
ПутьНаСервере = Сред(СтрокаСоединения, Позиция + 1);
СтрокаСоединения = Лев(СтрокаСоединения, Позиция - 1);
КонецЕсли;
// информация пользователя и имя сервера
СтрокаАвторизации = "";
ИмяСервера = СтрокаСоединения;
Позиция = Найти(СтрокаСоединения, "@");
Если Позиция > 0 Тогда
СтрокаАвторизации = Лев(СтрокаСоединения, Позиция - 1);
ИмяСервера = Сред(СтрокаСоединения, Позиция + 1);
КонецЕсли;
// логин и пароль
Логин = СтрокаАвторизации;
Пароль = "";
Позиция = Найти(СтрокаАвторизации, ":");
Если Позиция > 0 Тогда
Логин = Лев(СтрокаАвторизации, Позиция - 1);
Пароль = Сред(СтрокаАвторизации, Позиция + 1);
КонецЕсли;
// хост и порт
Хост = ИмяСервера;
Порт = "";
Позиция = Найти(ИмяСервера, ":");
Если Позиция > 0 Тогда
Хост = Лев(ИмяСервера, Позиция - 1);
Порт = Сред(ИмяСервера, Позиция + 1);
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Схема", Схема);
Результат.Вставить("ИспользоватьHTTPS", СтрокиРавныЛкс(Схема, "HTTPS"));
Результат.Вставить("Логин", Логин);
Результат.Вставить("Пароль", Пароль);
Результат.Вставить("ИмяСервера", ИмяСервера);
Результат.Вставить("Хост", Хост);
Результат.Вставить("Порт", ?(ПустаяСтрока(Порт), Неопределено, Число(Порт)));
Результат.Вставить("ПортHTTP", ?(ПустаяСтрока(Порт), ?(Результат.ИспользоватьHTTPS, 443, 80), Результат.Порт));
Результат.Вставить("ПутьНаСервере", ПутьНаСервере);
Возврат Результат;
КонецФункции
// Получает значения параметров из строки.
//
// Параметры:
// СтрокаПараметров - Строка - строка, содержащая параметры, каждый из которых представляет собой
// фрагмент вида <Имя параметра>=<Значение>, где:
// Имя параметра - имя параметра;
// Значение - его значение.
// Фрагменты отделяются друг от друга символами ';'.
// Если значение содержит пробельные символы, то оно должно быть заключено в двойные
// кавычки (").
// Например:
// "File=""c:\InfoBases\Trade""; Usr=""Director"";"
// Разделитель - Строка - символ, которым фрагменты отделяются друг от друга.
//
// Возвращаемое значение:
// Структура - значения параметров, где ключ - имя параметра, значение - значение параметра.
//
// Пример:
// Результат = СтроковыеФункцииКлиентСервер.ПараметрыИзСтроки("File=""c:\InfoBases\Trade""; Usr=""Director"";""", ";");
// - вернет структуру:
// ключ "File" и значение "c:\InfoBases\Trade"
// ключ "Usr" и значение "Director".
//
Функция ЗначенияПараметровИзСтрокиЛкс(Знач СтрокаПараметров, Знач Разделитель = ";") Экспорт
Результат = Новый Структура;
ОписаниеПараметра = "";
НайденоНачалоСтроки = Ложь;
НомерПоследнегоСимвола = СтрДлина(СтрокаПараметров);
Для НомерСимвола = 1 По НомерПоследнегоСимвола Цикл
Символ = Сред(СтрокаПараметров, НомерСимвола, 1);
Если Символ = """" Тогда
НайденоНачалоСтроки = Не НайденоНачалоСтроки;
КонецЕсли;
Если Символ <> Разделитель Или НайденоНачалоСтроки Тогда
ОписаниеПараметра = ОписаниеПараметра + Символ;
КонецЕсли;
Если Символ = Разделитель И Не НайденоНачалоСтроки Или НомерСимвола = НомерПоследнегоСимвола Тогда
Позиция = Найти(ОписаниеПараметра, "=");
Если Позиция > 0 Тогда
ИмяПараметра = СокрЛП(Лев(ОписаниеПараметра, Позиция - 1));
ЗначениеПараметра = СокрЛП(Сред(ОписаниеПараметра, Позиция + 1));
ЗначениеПараметра = ТекстИзВстроенногоЯзыкаЛкс(ЗначениеПараметра);
Результат.Вставить(ИмяПараметра, ЗначениеПараметра);
КонецЕсли;
ОписаниеПараметра = "";
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Получает представление из идентификатора по правилу
// "Дебиторка_По_контрагентамСИнтерваламиСНГДля__Руководства" => "Дебиторка По контрагентам с интервалами СНГ для Руководства".
// После символа "_" регистр не меняется, а сам символ заменяется на " ".
//
// Параметры:
// ИсходнаяСтрока - Строка - идентификатор.
//
// Возвращаемое значение:
// - Строка - представление.
//
Функция ПредставлениеИзИдентификатораЛкс(ИсходнаяСтрока) Экспорт
СтрокаВозврата = Сред(ИсходнаяСтрока, 1, 1);
Для Сч = 2 По СтрДлина(ИсходнаяСтрока) Цикл
ПредыдущийСимвол = Сред(ИсходнаяСтрока, Сч - 1, 1);
ТекущийСимвол = Сред(ИсходнаяСтрока, Сч, 1);
СледующийСимвол = Сред(ИсходнаяСтрока, Сч + 1, 1);
ПослеследующийСимвол = Сред(ИсходнаяСтрока, Сч + 2, 1);
Если ТекущийСимвол = "_" Тогда
СтрокаВозврата = СтрокаВозврата + " ";
Продолжить;
ИначеЕсли Истина
И ВРЕГ(ТекущийСимвол) = ТекущийСимвол
// В идентификаторе не должны встречаться пробелы. Поэтому было решено закомментировать следующую строку.
//И ПредыдущийСимвол <> " "
Тогда
Если Ложь
ИЛИ ТекущийСимвол <> " " И ВРЕГ(ПредыдущийСимвол) <> ПредыдущийСимвол
ИЛИ (Истина
И ПредыдущийСимвол <> "_"
И ВРЕГ(ПредыдущийСимвол) = ПредыдущийСимвол
И ВРЕГ(СледующийСимвол) <> СледующийСимвол)
Тогда
СтрокаВозврата = СтрокаВозврата + " ";
Если Ложь
ИЛИ ВРЕГ(СледующийСимвол) <> СледующийСимвол
ИЛИ ВРЕГ(ПослеследующийСимвол) <> ПослеследующийСимвол
Тогда
ТекущийСимвол = НРЕГ(ТекущийСимвол);
КонецЕсли;
КонецЕсли;
КонецЕсли;
СтрокаВозврата = СтрокаВозврата + ТекущийСимвол;
КонецЦикла;
Возврат СтрокаВозврата;
КонецФункции
// Преобразует строку для использования в регулярных выражениях путем экранирования управляющих символов.
// Параметры:
// Текст - Строка.
// Возвращаемое значение:
// Строка - для вставки в регулярные выражения.
Функция ТекстДляРегВыраженияЛкс(Знач Текст) Экспорт
СтрокаСлужебныхСимволов = "\[]^$()?*+.|{}"; // "\" должен быть первым
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Счетчик = 1 По СтрДлина(СтрокаСлужебныхСимволов) Цикл
СпецСимвол = Сред(СтрокаСлужебныхСимволов, Счетчик, 1);
Текст = СтрЗаменить(Текст, СпецСимвол, "\" + СпецСимвол);
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Счетчик = 1 По СтрДлина(СтрокаСлужебныхСимволов) Цикл СпецСимвол = Сред(СтрокаСлужебныхСимволов, Счетчик, 1); Текст = СтрЗаменить(Текст, СпецСимвол, "\" + СпецСимвол); КонецЦикла;
КонецЕсли;
Возврат Текст;
КонецФункции
// Шаблон для вызова:
// Вхождения = ирОбщий.НайтиРегВыражениеЛкс(Текст, Шаблон);
// #Если Сервер И Не Сервер Тогда
// Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
// #КонецЕсли
// Для каждого Вхождение Из Вхождения Цикл
// КонецЦикла;
//
// Параметры:
// Текст - Строка -
// Шаблон - Строка, Неопределено - если Неопределено то используем готовый Вычислитель!
// ИменаГрупп - -
// ИскатьВсеВхождения - -
// ИгнорироватьРегистрБукв - -
// МногострочныйРежим - -
// ВызыватьИсключение - -
// БезГрупп - -
// РегВыражение - - можно пердавать готовый вычислитель для ускорения
// ИгнорироватьВхожденияБезГрупп - -
// Результат - ТаблицаЗначений - таблица результата, можно передавать для ускорения, очищается перед заполнением
// выхДлительность - Число, Неопределено - если число, то в параметр будет возвращена длительность в милисекундах
//
// Возвращаемое значение:
// см. ОбработкаОбъект.ирОболочкаРегВыражение.НоваяТаблицаВхождений() - при БезГрупп колонка Группы содержит сырое вхождение
//
Функция НайтиРегВыражениеЛкс(Знач Текст, Знач Шаблон = Неопределено, Знач ИменаГрупп = "", Знач ИскатьВсеВхождения = Истина, Знач ИгнорироватьРегистрБукв = Истина,
Знач МногострочныйРежим = Ложь, Знач ВызыватьИсключение = Истина, Знач БезГрупп = Ложь, РегВыражение = Неопределено, Знач ИгнорироватьВхожденияБезГрупп = Ложь, Знач Результат = Неопределено,
выхДлительность = Неопределено) Экспорт
Если РегВыражение = Неопределено Тогда
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
#Если Сервер И Не Сервер Тогда
РегВыражение = Обработки.ирОболочкаРегВыражение.Создать();
#КонецЕсли
//ПроверитьПлатформаНеWindowsЛкс();
Если Не ЗначениеЗаполнено(Шаблон) Тогда
Возврат РегВыражение.НоваяТаблицаВхождений();
КонецЕсли;
КонецЕсли;
Если Результат = Неопределено Тогда
// ирПлатформа.ВхожденияРегВыражения
Результат = РегВыражение.НоваяТаблицаВхождений();
Иначе
Результат.Очистить();
КонецЕсли;
Если Шаблон <> Неопределено Тогда
РегВыражение.IgnoreCase = ИгнорироватьРегистрБукв;
РегВыражение.Global = ИскатьВсеВхождения;
РегВыражение.Multiline = МногострочныйРежим;
РегВыражение.Pattern = Шаблон;
КонецЕсли;
ИндексПервойКолонкиГруппы = Результат.Колонки.Количество();
Если Не БезГрупп И ЗначениеЗаполнено(ИменаГрупп) Тогда
ИменаГруппМассив = СтрРазделитьЛкс(ИменаГрупп, ",", Истина, Ложь);
Для Каждого ИмяГруппы Из ИменаГруппМассив Цикл
Если ПустаяСтрока(ИмяГруппы) Тогда
ИмяГруппы = АвтоУникальноеИмяВКоллекцииЛкс(Результат.Колонки, "Колонка");
КонецЕсли;
Если Результат.Колонки.Найти(ИмяГруппы) <> Неопределено Тогда
ВызватьИсключение "Имя """ + ИмяГруппы + """ добавляемой колонки Группы результатов поиска не уникально";
КонецЕсли;
Результат.Колонки.Добавить(ИмяГруппы);
КонецЦикла;
КоличествоИменГрупп = ИменаГруппМассив.Количество();
Иначе
КоличествоИменГрупп = 0;
КонецЕсли;
Если Не ЗначениеЗаполнено(Текст) Тогда
Возврат Результат;
КонецЕсли;
Попытка
Вхождения = РегВыражение.НайтиВхождения(Текст,,,, выхДлительность);
Исключение
Если Не ВызыватьИсключение Тогда
Возврат ОписаниеОшибки();
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
ДобавитьКолонкиГрупп = КоличествоИменГрупп = 0 И Результат.Колонки.Найти("Группа" + "0") = Неопределено;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Вхождение Из Вхождения Цикл
#Если Сервер И Не Сервер Тогда
Вхождение = Обработки.ирОболочкаРегВхождение.Создать();
#КонецЕсли
//Если Результат.Количество() = 0 Тогда
// Для ИндексГруппы = ИменаГруппМассив.Количество() По Вычислитель.КоличествоГрупп(Вхождение) - 1 Цикл
// Результат.Колонки.Добавить("Группа" + XMLСтрока(ИндексГруппы));
// КонецЦикла;
//КонецЕсли;
СтрокаРезультата = Результат.Добавить();
Если Не БезГрупп Тогда
Группы = Новый Массив;
ЕстьГруппыВхождения = Ложь;
Для ИндексГруппы = 0 По РегВыражение.КоличествоГрупп(Вхождение) - 1 Цикл
Если ДобавитьКолонкиГрупп Тогда
Результат.Колонки.Добавить("Группа" + ИндексГруппы);
КоличествоИменГрупп = КоличествоИменГрупп + 1;
КонецЕсли;
ЗначениеГруппы = Вхождение.SubMatches(ИндексГруппы);
Если ИндексГруппы < КоличествоИменГрупп Тогда
СтрокаРезультата[ИндексПервойКолонкиГруппы + ИндексГруппы] = ЗначениеГруппы;
КонецЕсли;
Группы.Добавить(ЗначениеГруппы);
Если Не ЕстьГруппыВхождения И ЗначениеГруппы <> Неопределено Тогда
ЕстьГруппыВхождения = Истина;
КонецЕсли;
КонецЦикла;
Если ДобавитьКолонкиГрупп Тогда
ДобавитьКолонкиГрупп = Ложь;
КонецЕсли;
Если ИгнорироватьВхожденияБезГрупп И Не ЕстьГруппыВхождения Тогда
Результат.Удалить(СтрокаРезультата);
Продолжить;
КонецЕсли;
СтрокаРезультата.Группы = Группы;
Иначе
СтрокаРезультата.Группы = Вхождение;
КонецЕсли;
СтрокаРезультата.ТекстВхождения = Вхождение.Value;
СтрокаРезультата.ПозицияВхождения = Вхождение.FirstIndex;
СтрокаРезультата.ДлинаВхождения = Вхождение.Length;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Каждого Вхождение Из Вхождения Цикл Если Ложь Тогда Вхождение = Обработки.ирОболочкаРегВхождение.Создать(); КонецЕсли; СтрокаРезультата = Результат.Добавить(); Если Не БезГрупп Тогда Группы = Новый Массив; ЕстьГруппыВхождения = Ложь; Для ИндексГруппы = 0 По РегВыражение.КоличествоГрупп(Вхождение) - 1 Цикл Если ДобавитьКолонкиГрупп Тогда Результат.Колонки.Добавить("Группа" + ИндексГруппы); КоличествоИменГрупп = КоличествоИменГрупп + 1; КонецЕсли; ЗначениеГруппы = Вхождение.SubMatches(ИндексГруппы); Если ИндексГруппы < КоличествоИменГрупп Тогда СтрокаРезультата[ИндексПервойКолонкиГруппы + ИндексГруппы] = ЗначениеГруппы; КонецЕсли; Группы.Добавить(ЗначениеГруппы); Если Не ЕстьГруппыВхождения И ЗначениеГруппы <> Неопределено Тогда ЕстьГруппыВхождения = Истина; КонецЕсли; КонецЦикла; Если ДобавитьКолонкиГрупп Тогда ДобавитьКолонкиГрупп = Ложь; КонецЕсли; Если ИгнорироватьВхожденияБезГрупп И Не ЕстьГруппыВхождения Тогда Результат.Удалить(СтрокаРезультата); Продолжить; КонецЕсли; СтрокаРезультата.Группы = Группы; Иначе СтрокаРезультата.Группы = Вхождение; КонецЕсли; СтрокаРезультата.ТекстВхождения = Вхождение.Value; СтрокаРезультата.ПозицияВхождения = Вхождение.FirstIndex; СтрокаРезультата.ДлинаВхождения = Вхождение.Length; КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЗаменитьРегВыражениеЛкс(Знач Текст, Знач ШаблонПоиска, Знач ШаблонЗамены, Знач ТребоватьФактИзменения = Истина, Знач ИскатьВсеВхождения = Истина, Знач ИгнорироватьРегистрБукв = Истина,
Знач МногострочныйРежим = Ложь, Вычислитель = Неопределено, выхЛиИзменен = Ложь) Экспорт
Если Вычислитель = Неопределено Тогда
Вычислитель = ирКэш.ВычислительРегВыраженийЛкс();
#Если Сервер И Не Сервер Тогда
Вычислитель = Обработки.ирОболочкаРегВыражение.Создать();
#КонецЕсли
КонецЕсли;
Вычислитель.IgnoreCase = ИгнорироватьРегистрБукв;
Вычислитель.Global = ИскатьВсеВхождения;
Вычислитель.Multiline = МногострочныйРежим;
Вычислитель.Pattern = ШаблонПоиска;
Результат = Вычислитель.Заменить(Текст, ШаблонЗамены);
выхЛиИзменен = Результат <> Текст;
Если ТребоватьФактИзменения И Не выхЛиИзменен Тогда
ВызватьИсключение "Шаблонная строка не найдена в тексте";
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Новый вычислитель рег выражений
//
// Возвращаемое значение:
// - Вычислитель - свойство IgnoreCase = Истина
//
Функция НовоеРегВыражениеЛкс() Экспорт
Результат = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирОболочкаРегВыражение");
#Если Сервер И Не Сервер Тогда
Результат = Обработки.ирОболочкаРегВыражение.Создать();
#КонецЕсли
Возврат Результат;
КонецФункции
// Возвращаемое значение:
// ОбработкаОбъект.ирКлсПолеТекстаПрограммы -
Функция НовыйАнализаторКодаЛкс(Знач ЯзыкПрограммы = Неопределено) Экспорт
Результат = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстаПрограммы");
Если ЯзыкПрограммы <> Неопределено Тогда
Результат.ИнициироватьНеинтерактивно(ЯзыкПрограммы);
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Стр найти слово
//
// Параметры:
// ГдеИскать - -
// ЧтоИскать - -
// НачальнаяПозиция - Число - начиная с 0
// СловоЦеликом - Булево, Строка - если строка, то регулярное выражение с подстановкой "#Слово#"
//
// Возвращаемое значение:
// СтрокаТаблицыЗначений, Неопределено - Вхождение
//
Функция СтрНайтиСловоЛкс(Знач ГдеИскать, Знач ЧтоИскать, Знач НачальнаяПозиция = 0, Знач СловоЦеликом = Истина, Знач РазбиватьНаСлова = Ложь, Вхождения = Неопределено) Экспорт
Позиция = 0;
Вхождения = НайтиРегВыражениеЛкс(ГдеИскать, ШаблонПоискаСловаЛкс(ЧтоИскать, СловоЦеликом, РазбиватьНаСлова),,,,,,,, ТипЗнч(СловоЦеликом) = Тип("Строка"));
СловоЦеликом = СловоЦеликом <> Ложь;
Для каждого Вхождение Из Вхождения Цикл
ПозицияВхождения = Вхождение.ПозицияВхождения;
Если СловоЦеликом <> Ложь Тогда
ПозицияВхождения = ПозицияВхождения + СтрДлина(Вхождение.Группа0);
КонецЕсли;
Если Вхождение.ПозицияВхождения >= НачальнаяПозиция Тогда
Результат = Вхождение;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Шаблон поиска слова лкс
//
// Параметры:
// СтрокаПоиска - -
// СловоЦеликомИлиШаблонШаблона - Булево, Строка - если строка, то регулярное выражение с подстановкой "#Слово#"
//
// Возвращаемое значение:
// Строка -
//
Функция ШаблонПоискаСловаЛкс(Знач СтрокаПоиска, Знач СловоЦеликомИлиШаблонШаблона = Истина, Знач РазбиватьНаСлова = Ложь) Экспорт
Если РазбиватьНаСлова Тогда
СловаПоиска = РазделитьСтрокуПоискаНаСловаПоискаЛкс(СтрокаПоиска);
Иначе
СловаПоиска = ЗначенияВМассивЛкс(СтрокаПоиска);
КонецЕсли;
Результат = Новый Массив;
Для Каждого Слово Из СловаПоиска Цикл
ШаблонСлова = ТекстДляРегВыраженияЛкс(Слово);
Если ТипЗнч(СловоЦеликомИлиШаблонШаблона) = Тип("Строка") Тогда
ШаблонСлова = СтрЗаменить(СловоЦеликомИлиШаблонШаблона, "#Слово#", ШаблонСлова);
КонецЕсли;
Результат.Добавить(ШаблонСлова);
КонецЦикла;
Результат = СтрСоединитьЛкс(Результат, "|");
Если СловоЦеликомИлиШаблонШаблона = Истина Тогда
Результат = "(^|[^_a-zа-яё0-9])(" + Результат + ")($|[^_a-zа-яё0-9])";
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// НайденныеВхождения - см. ОбработкаОбъект.ирОболочкаРегВыражение.НоваяТаблицаВхождений() -
// Возвращаемое значение:
// Число -
Функция ЧислоНепустыхГруппРезультатаРегВыраженияЛкс(Знач НайденныеВхождения) Экспорт
ЧислоНепустыхГрупп = НайденныеВхождения.Количество();
Если ЧислоНепустыхГрупп > 0 Тогда
ЧислоНепустыхГрупп = ЧислоНепустыхГрупп - НайденныеВхождения.НайтиСтроки(Новый Структура("Группа0")).Количество();
КонецЕсли;
Возврат ЧислоНепустыхГрупп;
КонецФункции
// Функция - Разделить строку поиска на слова поиска лкс
//
// Параметры:
// СтрокаПоиска - -
// ВыделитьРодителя - Булево - Часть до первой точки трактуется как слово поиска в родителе (для дерева), но если точки нет то этот параметр станет Ложь
//
// Возвращаемое значение:
// - Массив строк
//
Функция РазделитьСтрокуПоискаНаСловаПоискаЛкс(Знач СтрокаПоиска, ВыделитьРодителя = Ложь) Экспорт
УИД = "" + Новый УникальныйИдентификатор;
СтрокаПоиска = СтрЗаменить(СтрокаПоиска, """""", УИД);
Фрагменты = СтрРазделитьЛкс(СтрокаПоиска, """");
СловаПоиска = Новый Массив;
Для Индекс = 0 По Фрагменты.ВГраница() Цикл
Фрагмент = СтрЗаменить(Фрагменты[Индекс], УИД, """");
Если ПустаяСтрока(Фрагмент) Тогда
Продолжить;
КонецЕсли;
Если Индекс % 2 = 0 Тогда
СкопироватьКоллекциюЛкс(СтрРазделитьЛкс(Фрагмент, " ", Истина, Ложь), СловаПоиска);
Иначе
СловаПоиска.Добавить(Фрагмент);
КонецЕсли;
КонецЦикла;
Если ВыделитьРодителя Тогда
ВыделитьРодителя = Ложь;
ПозицияТочки = Найти(СловаПоиска[0], ".");
Если ПозицияТочки > 0 Тогда
СловоРодителя = СокрП(Лев(СловаПоиска[0], ПозицияТочки - 1));
Если СловоРодителя <> "" Тогда
НовоеСлово = СокрЛ(Сред(СловаПоиска[0], ПозицияТочки + 1));
Если НовоеСлово = "" Тогда
СловаПоиска.Удалить(0);
ВыделитьРодителя = СловаПоиска.Количество() > 0;
Если Не ВыделитьРодителя Тогда
СловоРодителя = СловоРодителя + "."; // Возвращаем точку обратно
КонецЕсли;
Иначе
СловаПоиска[0] = НовоеСлово;
ВыделитьРодителя = Истина;
КонецЕсли;
СловаПоиска.Вставить(0, СловоРодителя);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат СловаПоиска;
КонецФункции
Функция РегВыражениеСтрокиПоискаЛкс(Знач СтрокаИлиСловаПоиска, Знач ГруппыДляСлов = Истина) Экспорт
Если ТипЗнч(СтрокаИлиСловаПоиска) = Тип("Строка") Тогда
СловаПоиска = РазделитьСтрокуПоискаНаСловаПоискаЛкс(СтрокаИлиСловаПоиска);
Иначе
СловаПоиска = СтрокаИлиСловаПоиска;
КонецЕсли;
ВыраженияПоиска = Новый Массив;
Если Не ГруппыДляСлов Тогда
НачалоГруппы = "?:";
КонецЕсли;
Для Каждого СловоПоиска Из СловаПоиска Цикл
ВыраженияПоиска.Добавить("(" + НачалоГруппы + ТекстДляРегВыраженияЛкс(СловоПоиска) + ")");
КонецЦикла;
ФинальноеВыражение = СтрСоединитьЛкс(ВыраженияПоиска, "|");
Если Не ГруппыДляСлов Тогда
ФинальноеВыражение = "(" + ФинальноеВыражение + ")";
КонецЕсли;
Возврат ФинальноеВыражение;
КонецФункции
// Преобразует строку для правого операнда оператора ПОДОБНО языка запросов.
//
// Параметры:
// пТекст - Строка.
//
// Возвращаемое значение:
// Строка.
//
Функция ПреобразоватьСтрокуДляПОДОБНОЛкс(Знач Результат, Спецсимвол = "~") Экспорт
ЗарезервированныеСимволы = Новый Массив;
ЗарезервированныеСимволы.Добавить("~");
//ЗарезервированныеСимволы.Добавить("%");
ЗарезервированныеСимволы.Добавить("_");
ЗарезервированныеСимволы.Добавить("[");
ЗарезервированныеСимволы.Добавить("-");
ЗарезервированныеСимволы.Добавить("]");
Для Каждого ЗарезервированныйСимвол Из ЗарезервированныеСимволы Цикл
Результат = СтрЗаменить(Результат, ЗарезервированныйСимвол, Спецсимвол + ЗарезервированныйСимвол);
КонецЦикла;
Возврат Результат;
КонецФункции // ПреобразоватьСтрокуДляПОДОБНОЛкс()
// Обновляет в строковом свойстве объекта часть, которая следует за маркером.
// Если маркер не находится, то он добавляется.
//
// Параметры:
// ОбъектИлиСвойство - Объект, Строка - объект, строковое свойство которого будем обновлять, или само свойство по ссылке;
// ИмяСвойства - Строка, *"" - имя строкового Свойства объекта, указывается в случае, если свойство не передается по ссылке;
// НовыйТекст - Строка - новая часть, которая следует за разделителем;
// пМаркер - Строка, *"," - маркер.
//
Процедура ОбновитьТекстПослеМаркераЛкс(ОбъектИлиСвойство, Знач ИмяСвойства = "", Знач НовыйТекст, Знач пМаркер = ", ", Знач ОбрезатьПосле = 100) Экспорт
Если ЗначениеЗаполнено(ИмяСвойства) Тогда
СтараяСтрока = ОбъектИлиСвойство[ИмяСвойства];
Иначе
СтараяСтрока = ОбъектИлиСвойство;
КонецЕсли;
ПозицияРазделителя = Найти(СтараяСтрока, пМаркер);
Если ПозицияРазделителя = 0 Тогда
ПозицияРазделителя = СтрДлина(СтараяСтрока) + 1;
КонецЕсли;
Если ЗначениеЗаполнено(ОбрезатьПосле) Тогда
НовыйТекст = ПредставлениеЗначенияСОграничениемДлиныЛкс(НовыйТекст, ОбрезатьПосле);
КонецЕсли;
НоваяСтрока = Лев(СтараяСтрока, ПозицияРазделителя - 1) + пМаркер + НовыйТекст;
Если ИмяСвойства <> "" Тогда
ПрисвоитьЕслиНеРавноЛкс(ОбъектИлиСвойство[ИмяСвойства], НоваяСтрока);
Иначе
ПрисвоитьЕслиНеРавноЛкс(ОбъектИлиСвойство, НоваяСтрока);
КонецЕсли;
КонецПроцедуры
// Результат - Строка - длинна не более ПорогДлины
Функция ПредставлениеЗначенияСОграничениемДлиныЛкс(Знач Значение, Знач ПорогДлины = 100, МаркерОтрезки = "…") Экспорт
Если ТипЗнч(Значение) = Тип("Строка") Тогда
ПредставлениеЗначения = Значение;
Иначе
ПредставлениеЗначения = РасширенноеПредставлениеЛкс(Значение); // Нельзя напрямую преобразоывать к строке, т.к. у ряда типов (ИсторияПоискаТаблицы, ВыборкаИзРезультатаЗапроса,
КонецЕсли;
Если СтрДлина(ПредставлениеЗначения) > ПорогДлины Тогда
ПредставлениеЗначения = Лев(ПредставлениеЗначения, ПорогДлины - СтрДлина(МаркерОтрезки)) + МаркерОтрезки;
КонецЕсли;
Возврат ПредставлениеЗначения;
КонецФункции
Функция ДополнитьСтрокуЛкс(Знач Строка, Знач НужнаяДлина, Знач Символ = " ", Знач Слева = Истина) Экспорт
Если СтрДлина(Строка) < НужнаяДлина Тогда
Дополнение = СтрокаПовторомЛкс(Символ, НужнаяДлина - СтрДлина(Строка));
Если Слева Тогда
Строка = Дополнение + Строка;
Иначе
Строка = Строка + Дополнение;
КонецЕсли;
КонецЕсли;
Возврат Строка;
КонецФункции
// Взято отсюда http://infostart.ru/public/100845/
// ИсходныеДанные - <примитивное значение>, ДвоичныеДанные, ХранилищеЗначения
//
// Возвращаемое значение
// Число
Функция ВычислитьХэшЛкс(ИсходныеДанные, Хэш=5381, М=33, Разрядность=18446744073709551616) Экспорт
// приведем к строке
Если ТипЗнч(ИсходныеДанные) = Тип("ДвоичныеДанные") Тогда
СтрокаДляКодирования = Base64Строка(ИсходныеДанные);
ИначеЕсли ТипЗнч(ИсходныеДанные) = Тип("ХранилищеЗначения") Тогда
СтрокаДляКодирования = ЗначениеВСтрокуВнутр(ИсходныеДанные);
Иначе
СтрокаДляКодирования = Строка(ИсходныеДанные);
КонецЕсли;
ДлинаБлока = 11;
НачПозиция = 1;
ДлинаСтроки = СтрДлина(СтрокаДляКодирования);
Пока НачПозиция <= ДлинаСтроки Цикл
СтрокаБлока = Сред(СтрокаДляКодирования, НачПозиция, ДлинаБлока);
ДлинаПодстроки = СтрДлина(СтрокаБлока);
Если ДлинаПодстроки = ДлинаБлока Тогда
Хэш = ((((((((((( Хэш*М + КодСимвола(СтрокаБлока, 1))*М + КодСимвола(СтрокаБлока, 2))*М
+ КодСимвола(СтрокаБлока, 3))*М + КодСимвола(СтрокаБлока, 4))*М + КодСимвола(СтрокаБлока, 5))*М
+ КодСимвола(СтрокаБлока, 6))*М + КодСимвола(СтрокаБлока, 7))*М + КодСимвола(СтрокаБлока, 8))*М
+ КодСимвола(СтрокаБлока, 9))*М + КодСимвола(СтрокаБлока, 10))*М + КодСимвола(СтрокаБлока, 11))
Иначе
Для к = 1 По ДлинаПодстроки Цикл
Хэш = М * Хэш + КодСимвола(СтрокаБлока, к)
КонецЦикла
КонецЕсли;
Хэш = Хэш % Разрядность;
НачПозиция = НачПозиция + ДлинаБлока
КонецЦикла;
Возврат Хэш;
КонецФункции
Функция ПолучитьГУИДИнверсныйИзПрямогоЛкс(ПрямойГУИД) Экспорт
С = СтрЗаменить(ПрямойГУИД, "-", "");
Возврат Сред(С,17,16)+Сред(С,13,4)+Сред(С,9,4)+Сред(С,1,4)+Сред(С,5,4);
КонецФункции
Функция ПолучитьГУИДПрямойИзИнверсногоЛкс(ИнверсныйГУИД) Экспорт
С = ИнверсныйГУИД;
Возврат Сред(С,25,8)+"-"+Сред(С,21,4)+"-"+Сред(С,17,4)+"-"+Сред(С,1,4)+"-"+Сред(С,5,12);
КонецФункции
Функция ОписаниеТиповПланОбменаСсылкаЛкс(ВключаяТипыРасширений = Истина) Экспорт
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(
"
| cc:ExchangePlanRef
|");
Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Если ВключаяТипыРасширений И ирКэш.НомерРежимаСовместимостиЛкс() >= 803011 И ПравоДоступа("АдминистрированиеРасширенийКонфигурации", Метаданные) Тогда
ТипыРасширений = ирКэш.ТипыРасширенийКонфигурацииЛкс("ПланОбмена");
Результат = Новый ОписаниеТипов(Результат, ТипыРасширений);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОписаниеТиповВсеСсылкиЛкс(ВключаяТипыРасширений = Истина, ВключаяТипыВнешнихИсточниковДанных = Истина) Экспорт
ЧтениеXML = Новый ЧтениеXML;
// TODO AnyRef->AnyIBRef https://dl03.1c.ru/content/Platform/8_3_23_1865/1cv8upd_8_3_23_1865.htm#a31d2902-0e7a-11ed-aa69-0050569f678a
ЧтениеXML.УстановитьСтроку(
"
| cc:AnyRef
|");
Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Если ВключаяТипыРасширений И ирКэш.НомерРежимаСовместимостиЛкс() >= 803011 И ПравоДоступа("АдминистрированиеРасширенийКонфигурации", Метаданные) Тогда
ТипыРасширений = ирКэш.ТипыРасширенийКонфигурацииЛкс();
Результат = Новый ОписаниеТипов(Результат, ТипыРасширений);
КонецЕсли;
Если ирКэш.НомерРежимаСовместимостиЛкс() >= 803001 И ВключаяТипыВнешнихИсточниковДанных Тогда
Для Каждого ВнешнийИсточникДанных Из Вычислить("ВнешниеИсточникиДанных") Цикл // Для компиляции на платформе 8.2.13-
Результат = Новый ОписаниеТипов(Результат, ВнешнийИсточникДанных.Таблицы.ТипВсеСсылки().Типы());
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОписаниеТиповСоСсылкойНаОпределяемыйТипЛкс(ИмяОпределяемогоТипа) Экспорт
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(
"
| cc:DefinedType." + ИмяОпределяемогоТипа + "
|");
Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
Возврат Результат;
КонецФункции
Функция ИмяНабораТиповИзОписанияТиповЛкс(Знач ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
ИмяОпределяемогоТипа = ТекстМеждуМаркерамиЛкс(ОбъектВСтрокуXMLЛкс(ОписаниеТипов), "Characteristic.", "", Ложь);
Если ЗначениеЗаполнено(ИмяОпределяемогоТипа) Тогда
ИмяОпределяемогоТипа = "ПланВидовХарактеристик." + ИмяОпределяемогоТипа;
ИначеЕсли ирКэш.НомерВерсииПлатформыЛкс() > 803001 Тогда
ИмяОпределяемогоТипа = ТекстМеждуМаркерамиЛкс(ОбъектВСтрокуXMLЛкс(ОписаниеТипов), "DefinedType.", "", Ложь);
Если ЗначениеЗаполнено(ИмяОпределяемогоТипа) Тогда
ИмяОпределяемогоТипа = "ОпределяемыйТип." + ИмяОпределяемогоТипа;
КонецЕсли;
КонецЕсли;
Возврат ИмяОпределяемогоТипа;
КонецФункции
Функция ОписаниеТиповВсеРедактируемыеТипыЛкс() Экспорт
ОписаниеТипов = ОписаниеТиповВсеСсылкиЛкс();
ДополнительныеТипы = Новый Массив();
ДополнительныеТипы.Добавить(Тип("Строка"));
ДополнительныеТипы.Добавить(Тип("Число"));
ДополнительныеТипы.Добавить(Тип("Дата"));
ДополнительныеТипы.Добавить(Тип("Булево"));
ДополнительныеТипы.Добавить(Тип("СписокЗначений"));
ДополнительныеТипы.Добавить(Тип("Массив"));
ДополнительныеТипы.Добавить(Тип("ФиксированныйМассив"));
ДополнительныеТипы.Добавить(Тип("ОписаниеТипов"));
ДополнительныеТипы.Добавить(Тип("МоментВремени"));
ДополнительныеТипы.Добавить(Тип("Граница"));
ДополнительныеТипы.Добавить(Тип("СтандартнаяДатаНачала"));
ДополнительныеТипы.Добавить(Тип("СтандартныйПериод"));
ДополнительныеТипы.Добавить(Тип("ТаблицаЗначений"));
ДополнительныеТипы.Добавить(Тип("ДеревоЗначений"));
ДополнительныеТипы.Добавить(Тип("ТабличныйДокумент"));
ДополнительныеТипы.Добавить(Тип("Картинка"));
ДополнительныеТипы.Добавить(Тип("ВидДвиженияНакопления"));
ДополнительныеТипы.Добавить(Тип("ВидДвиженияБухгалтерии"));
ДополнительныеТипы.Добавить(Тип("ВидСчета"));
ДополнительныеТипы.Добавить(Тип("Тип"));
ДополнительныеТипы.Добавить(Тип("Null"));
ДополнительныеТипы.Добавить(Тип("ПолеКомпоновкиДанных"));
ДополнительныеТипы.Добавить(Тип("УникальныйИдентификатор"));
ДополнительныеТипы.Добавить(Тип("ХранилищеЗначения"));
ДополнительныеТипы.Добавить(Тип("ДвоичныеДанные"));
ДополнительныеТипы.Добавить(Тип("ГоризонтальноеПоложение"));
ДополнительныеТипы.Добавить(Тип("ВертикальноеПоложение"));
ДополнительныеТипы.Добавить(Тип("Цвет"));
ДополнительныеТипы.Добавить(Тип("Шрифт"));
ДополнительныеТипы.Добавить(Тип("СхемаКомпоновкиДанных"));
Если Не ирКэш.ЛиПортативныйРежимЛкс() И ирКэш.ДоступноФорматированнаяСтрокаЛкс() Тогда
ДополнительныеТипы.Добавить(Тип("ФорматированнаяСтрока"));
ДополнительныеТипы.Добавить(Тип("ФорматированныйДокумент"));
КонецЕсли;
//ДополнительныеТипы.Добавить(Тип("НаправлениеСортировки")); // нельзя добавить, т.к. для этого типа не поддерживается XML сериализация
//ДополнительныеТипы.Добавить(Тип("ТипИзмеренияПостроителяОтчета")); // нельзя добавить, т.к. для этого типа не поддерживается XML сериализация
//ДополнительныеТипы.Добавить(Тип("ВидТочкиМаршрутаБизнесПроцесса")); // нельзя добавить, т.к. для этого типа не поддерживается XML сериализация
//ДополнительныеТипы.Добавить(Тип("ВидПериодаРегистраРасчета")); // нельзя добавить, т.к. для этого типа не поддерживается XML сериализация
// Из-за бага платформы отключены
//ДополнительныеТипы.Добавить(Тип("ПериодичностьАгрегатаРегистраНакопления"));
//ДополнительныеТипы.Добавить(Тип("ИспользованиеАгрегатаРегистраНакопления"));
КвалификаторыЧисла = Новый КвалификаторыЧисла; //(25, 5); // Важно!
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, ДополнительныеТипы, , КвалификаторыЧисла);
Возврат ОписаниеТипов;
КонецФункции
// Проверяет что значение имеет тип Дата или СтандартнаяДатаНачала
Функция ЛиДатаЛкс(Знач Значение) Экспорт
Результат = Ложь
Или ТипЗнч(Значение) = Тип("Дата")
Или ТипЗнч(Значение) = Тип("СтандартнаяДатаНачала");
Возврат Результат;
КонецФункции
Функция ОписаниеТиповИзТипаЛкс(Тип) Экспорт
Массив = Новый Массив;
Массив.Добавить(Тип);
Результат = Новый ОписаниеТипов(Массив);
Возврат Результат;
КонецФункции
Функция ОписаниеТиповИзТекстаЛкс(Знач ТекстТипов, выхНеопознанныеТипы = Неопределено) Экспорт
ОписаниеТипов = Новый Массив;
выхНеопознанныеТипы = Новый Массив;
Для Каждого ИмяТипа Из СтрРазделитьЛкс(ТекстТипов, ",", Истина) Цикл
Если Не ЗначениеЗаполнено(ИмяТипа) Тогда
Продолжить;
КонецЕсли;
Попытка
Тип = Тип(ИмяТипа);
Исключение
выхНеопознанныеТипы.Добавить(ИмяТипа);
Продолжить;
КонецПопытки;
ОписаниеТипов.Добавить(Тип);
КонецЦикла;
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов);
Возврат ОписаниеТипов;
КонецФункции
Функция ИменаМетаданныхИзОписанияТиповЛкс(Знач ОписаниеТипов) Экспорт
Если ТипЗнч(ОписаниеТипов) = Тип("Строка") Тогда
ОписаниеТипов = ОписаниеТиповИзТекстаЛкс(ОписаниеТипов);
КонецЕсли;
Массив = Новый Массив;
Для Каждого Тип Из ОписаниеТипов.Типы() Цикл
ОбъектМД = Метаданные.НайтиПоТипу(Тип);
Если ОбъектМД <> Неопределено Тогда
Массив.Добавить(ПолноеИмяМДСРасширениемЛкс(ОбъектМД));
КонецЕсли;
Массив = СвернутьМассивЛкс(Массив);
КонецЦикла;
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(Массив);
Возврат Список;
КонецФункции
//.
// Параметры:
// ОбъектМД - ОбъектМетаданныхОбработка -
// Возвращаемое значение:
// Строка -
Функция ПолноеИмяМДСРасширениемЛкс(Знач ОбъектМД) Экспорт
КлючПерехода = ОбъектМД.ПолноеИмя();
РасширениеКонфигурации = ОбъектМД.РасширениеКонфигурации();
Если РасширениеКонфигурации <> Неопределено Тогда
КлючПерехода = РасширениеКонфигурации.Имя + " " + КлючПерехода;
КонецЕсли;
Возврат КлючПерехода;
КонецФункции
Функция ЛиОписаниеТиповПростогоСсылочногоТипаЛкс(Знач ОписаниеТипов, БезУчетаNULL = Истина, Знач ИсключаяСсылкиМетаданных = Истина) Экспорт
Если БезУчетаNULL Тогда
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, , "NULL");
КонецЕсли;
ЭтоОписаниеТиповПростогоСсылочногоТипа = ОписаниеТипов.Типы().Количество() = 1 И ЛиТипСсылкиБДЛкс(ОписаниеТипов.Типы()[0], ИсключаяСсылкиМетаданных);
Возврат ЭтоОписаниеТиповПростогоСсылочногоТипа;
КонецФункции
Функция ЛиОписаниеТиповПростогоСтроковогоТипаЛкс(Знач ОписаниеТипов, БезУчетаNULL = Истина) Экспорт
Если БезУчетаNULL Тогда
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, , "NULL");
КонецЕсли;
Возврат ОписаниеТипов.СодержитТип(Тип("Строка")) И ОписаниеТипов.Типы().Количество() = 1;
КонецФункции
Функция ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
Возврат Истина
И ОписаниеТипов.СодержитТип(Тип("Строка"))
И ОписаниеТипов.КвалификаторыСтроки.Длина = 0;
КонецФункции
Функция ЛиОписаниеТиповНеограниченнойДлиныЛкс(Знач ОписаниеТипов) Экспорт
Возврат Ложь
Или ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ОписаниеТипов)
Или ОписаниеТипов.СодержитТип(Тип("ХранилищеЗначения"))
Или ОписаниеТипов.СодержитТип(Тип("ТаблицаЗначений"));
КонецФункции
Функция ЛиОписаниеТиповБулевоЛкс(Знач ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
Возврат Истина
И ОписаниеТипов.СодержитТип(Тип("Булево"))
И ОписаниеТипов.Типы().Количество() = 1;
КонецФункции
Функция ОкончаниеВыраженияПодстрокиДинСпискаЛкс(Знач Длина = Неопределено) Экспорт
Если Длина = Неопределено Тогда
Длина = ДлинаПредставленияСтрокиНеограниченнойЛкс();
КонецЕсли;
Возврат ", 1, " + XMLСтрока(Длина) + ")";
КонецФункции
Функция ДлинаПредставленияСтрокиНеограниченнойЛкс() Экспорт
Возврат 999;
КонецФункции
Функция СтруктураИзОписанияТиповЛкс(ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
СтруктураОписанияТипов = СтруктураИзОбъектаЛкс(ОписаниеТипов);
СписокТипов = Новый СписокЗначений;
СписокТипов.ЗагрузитьЗначения(ОписаниеТипов.Типы());
СписокТипов.СортироватьПоЗначению();
СтруктураОписанияТипов.Вставить("Типы", СписокТипов.ВыгрузитьЗначения());
Возврат СтруктураОписанияТипов;
КонецФункции
Функция РежимСовместимостиМеньше8_3_4Лкс() Экспорт
Возврат ирКэш.НомерРежимаСовместимостиЛкс() < 803004;
КонецФункции
Процедура ДобавитьКолонкуЕслиНетЛкс(КолонкиДереваИлиТаблицы, ИмяКолонки, ОписаниеТипов = Неопределено,
Заголовок = Неопределено, Ширина = 0) Экспорт
Если КолонкиДереваИлиТаблицы.Найти(ИмяКолонки) <> Неопределено Тогда
Возврат;
КонецЕсли;
КолонкиДереваИлиТаблицы.Добавить(ИмяКолонки, ОписаниеТипов, Заголовок, Ширина);
КонецПроцедуры
Процедура НайтиДобавитьКолонкуНомераСтрокиЛкс(Знач ТаблицаЗначений, Знач ИмяКолонкиНомерСтроки, Знач ТаблицаБезДанныхСУзкимиТипами = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
Если ТаблицаЗначений.Колонки.Найти(ИмяКолонкиНомерСтроки) = Неопределено Тогда
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиНомерСтроки, Новый ОписаниеТипов("Число"));
Если ТаблицаБезДанныхСУзкимиТипами <> Неопределено Тогда
ТаблицаБезДанныхСУзкимиТипами.Колонки.Добавить(ИмяКолонкиНомерСтроки, Новый ОписаниеТипов("Число"));
КонецЕсли;
Счетчик = 1;
Для Каждого СтрокаТаблицы Из ТаблицаЗначений Цикл
СтрокаТаблицы[ИмяКолонкиНомерСтроки] = Счетчик;
Счетчик = Счетчик + 1;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция Дерево_ПутьМассивомЛкс(СтрокаДерева, ИмяКлючевойКолонки = "") Экспорт
Координаты = Новый Массив();
Родитель = СтрокаДерева;
Пока Родитель <> Неопределено Цикл
Если ЗначениеЗаполнено(ИмяКлючевойКолонки) Тогда
Координата = Родитель[ИмяКлючевойКолонки];
Иначе
Координата = РодительСтрокиДереваЛкс(Родитель).Строки.Индекс(Родитель);
КонецЕсли;
Координаты.Вставить(0, Координата);
Родитель = Родитель.Родитель;
КонецЦикла;
Возврат Координаты;
КонецФункции
Функция Дерево_НайтиПоПутиМассивомЛкс(Дерево, Координаты, ИмяКлючевойКолонки = "") Экспорт
#Если Сервер И Не Сервер Тогда
Дерево = Новый ДеревоЗначений;
#КонецЕсли
СтрокаДерева = Дерево;
Для Каждого Координата Из Координаты Цикл
Если ЗначениеЗаполнено(ИмяКлючевойКолонки) Тогда
СтрокаДерева = СтрокаДерева.Строки.Найти(Координата, ИмяКлючевойКолонки);
Иначе
СтрокаДерева = СтрокаДерева.Строки[Координата];
КонецЕсли;
КонецЦикла;
Возврат СтрокаДерева;
КонецФункции
// Полученный адрес можно затем использовать в см. НайтиСтрокуДереваФормыПоАдресуЛкс()
// Параметры:
// СтрокаДерева - ДанныеФормыЭлементДерева, СтрокаДереваЗначений, ПолеФормы, ГруппаФормы, ТаблицаФормы, КнопкаФормы, ДекорацияФормы -
// ИмяКлючевойКолонки - Строка - если пустое, то будет использован индекс элементов дерева (только для СтрокаДереваЗначений)
// Дерево - ДеревоЗначений, ДанныеФормыДерево, ОтборКомпоновкиДанных - иерархический объект, которому принадлежит элемент, для дерева значений не нужно передавать
// Возвращаемое значение:
// Массив -
Функция АдресСтрокиДереваЛкс(Знач СтрокаДерева, Знач ИмяКлючевойКолонки = "Ссылка", Знач Дерево = Неопределено) Экспорт
КлючиУровней = Новый Массив();
ТекущаяСтрока = СтрокаДерева;
Пока Истина
И ТипЗнч(ТекущаяСтрока) <> Тип("ФормаКлиентскогоПриложения")
И ТекущаяСтрока <> Неопределено
Цикл
Если ИмяКлючевойКолонки = "" Тогда
КлючСтроки = ДочерниеЭлементыДереваЛкс(РодительСтрокиДереваЛкс(ТекущаяСтрока, Дерево)).Индекс(ТекущаяСтрока);
Иначе
КлючСтроки = ТекущаяСтрока[ИмяКлючевойКолонки];
КонецЕсли;
КлючиУровней.Вставить(0, КлючСтроки);
Если ТипЗнч(ТекущаяСтрока) = Тип("ДанныеФормыЭлементДерева") Тогда
ТекущаяСтрока = ТекущаяСтрока.ПолучитьРодителя();
Иначе
ТекущаяСтрока = ТекущаяСтрока.Родитель;
КонецЕсли;
КонецЦикла;
Возврат КлючиУровней;
КонецФункции
// Формирует путь строкой для элемента древовидной структуры.
// Параметры:
// ИмяКолонки - Строка - если задать пустое значение, то будет использован индекс строк дерева;
// ИгнорироватьПростойПервыйУровень - Булево - если на первом уровне только одна строка, то игнорировать ее;
Функция Дерево_ПутьСтрокойЛкс(СтрокаДерева, ИмяКолонки = "Имя", ИгнорироватьПростойПервыйУровень = Ложь, Разделитель = ".", Дерево = Неопределено, Исключения = Неопределено) Экспорт
Если СтрокаДерева = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда
Родитель = РодительСтрокиДереваЛкс(СтрокаДерева, Дерево);
Дочерние = ДочерниеЭлементыДереваЛкс(Родитель);
Результат = Дочерние.Индекс(СтрокаДерева);
Иначе
Если Исключения <> Неопределено Тогда
Для Каждого Структура Из Исключения Цикл
Если СравнитьЗначенияСвойствЛкс(СтрокаДерева, Структура, Структура.СвойстваДляСравнения) Тогда
Результат = Структура[ИмяКолонки];
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Результат = Неопределено Тогда
Результат = СтрокаДерева[ИмяКолонки];
КонецЕсли;
КонецЕсли;
Если ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева") Тогда
Родитель = СтрокаДерева.ПолучитьРодителя();
Иначе
Родитель = СтрокаДерева.Родитель; // СтрокаДереваЗначений
КонецЕсли;
Если Родитель = Неопределено Тогда
Если Истина
И ИгнорироватьПростойПервыйУровень
И СтрокаДерева.Владелец().Строки.Количество() = 1
Тогда
Результат = Неопределено;
КонецЕсли;
Иначе
РезультатСверху = Дерево_ПутьСтрокойЛкс(Родитель, ИмяКолонки, ИгнорироватьПростойПервыйУровень, Разделитель, Дерево, Исключения);
Если РезультатСверху <> Неопределено Тогда
Результат = РезультатСверху + Разделитель + Результат;
КонецЕсли;
КонецЕсли;
Возврат XMLСтрока(Результат);
КонецФункции
// Ищет элемент древовидной структуры по пути строкой.
// Параметры:
// ИмяКолонки - Строка - если задать пустое значение, то будет использован индекс строк дерева;
// ИгнорироватьПростойПервыйУровень - Булево - если на первом уровне только одна строка, то игнорировать ее;
Функция Дерево_НайтиПоПутиСтрокойЛкс(СтрокаДерева, ИмяКолонки = "Имя", Путь, ИгнорироватьПростойПервыйУровень = Ложь, Разделитель = ".") Экспорт
Если Истина
И ИгнорироватьПростойПервыйУровень
И ТипЗнч(СтрокаДерева) = Тип("ДеревоЗначений")
И СтрокаДерева.Строки.Количество() = 1
Тогда
Возврат Дерево_НайтиПоПутиСтрокойЛкс(СтрокаДерева.Строки[0], ИмяКолонки, Сред(Путь, 2));
КонецЕсли;
ТекущийУровень = ПервыйФрагментЛкс(Путь, Разделитель);
Если Не ЗначениеЗаполнено(ТекущийУровень) Тогда
Возврат СтрокаДерева;
КонецЕсли;
ОстальнойПуть = Сред(Путь, СтрДлина(ТекущийУровень + Разделитель) + 1);
Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда
ЗначениеИндекса = Число(ТекущийУровень);
Дочерние = ДочерниеЭлементыДереваЛкс(СтрокаДерева);
Если Дочерние.Количество() > ЗначениеИндекса Тогда
ТекущаяСтрока = Дочерние[ЗначениеИндекса];
КонецЕсли;
Иначе
Если Ложь
Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыДерево")
Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева")
Тогда
ТекущаяСтрока = Неопределено;
ДочерниеЭлементы = СтрокаДерева.ПолучитьЭлементы();
Для Каждого ДочернийЭлемент Из ДочерниеЭлементы Цикл
Если ДочернийЭлемент[ИмяКолонки] = ТекущийУровень Тогда
ТекущаяСтрока = ДочернийЭлемент;
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
ТекущаяСтрока = СтрокаДерева.Строки.Найти(ТекущийУровень, ИмяКолонки);
КонецЕсли;
КонецЕсли;
Если ТекущаяСтрока <> Неопределено Тогда
Возврат Дерево_НайтиПоПутиСтрокойЛкс(ТекущаяСтрока, ИмяКолонки, ОстальнойПуть,, Разделитель);
Иначе
Возврат СтрокаДерева;
КонецЕсли;
КонецФункции
// Функция - Дочерние элементы дерева лкс
// Параметры:
// СтрокаДерева - Произвольный -
// ТребоватьИерархию - -
// Возвращаемое значение:
// Произвольный -
Функция ДочерниеЭлементыДереваЛкс(Знач СтрокаДерева, Знач ТребоватьИерархию = Истина) Экспорт
ТипРодителя = ТипЗнч(СтрокаДерева);
Если Ложь
Или ТипРодителя = Тип("ДеревоЗначений")
Или ТипРодителя = Тип("СтрокаДереваЗначений")
Тогда
//! СтрокаДерева = 0 // ДеревоЗначений
Дочерние = СтрокаДерева.Строки;
ИначеЕсли Ложь
Или ТипРодителя = Тип("ОтборКомпоновкиДанных")
Или ТипРодителя = Тип("ГруппаЭлементовОтбораКомпоновкиДанных")
Или ТипРодителя = Тип("ДоступныеПоляКомпоновкиДанных")
Или ТипРодителя = Тип("ДоступноеПолеКомпоновкиДанных")
Или ТипРодителя = Тип("ДоступноеПолеОтбораКомпоновкиДанных")
Тогда
//! СтрокаДерева = 0 // ОтборКомпоновкиДанных
Дочерние = СтрокаДерева.Элементы;
ИначеЕсли Ложь
Или ТипРодителя = Тип("ДанныеФормыДерево")
Или ТипРодителя = Тип("ДанныеФормыЭлементДерева")
Тогда
//! СтрокаДерева = 0 // ДанныеФормыДерево
Дочерние = СтрокаДерева.ПолучитьЭлементы();
ИначеЕсли Ложь
Или ТипРодителя = Тип("СхемаКомпоновкиДанных")
Или ТипРодителя = Тип("МакетКомпоновкиДанных")
Тогда
//! СтрокаДерева = 0 // СхемаКомпоновкиДанных
Дочерние = СтрокаДерева.НаборыДанных;
ИначеЕсли Ложь
Или ТипРодителя = Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных")
Или ТипРодителя = Тип("НаборДанныхОбъединениеМакетаКомпоновкиДанных")
Тогда
//! СтрокаДерева = 0 // НаборДанныхОбъединениеСхемыКомпоновкиДанных
Дочерние = СтрокаДерева.Элементы;
ИначеЕсли Ложь
Или ТипРодителя = Тип("ГруппаФормы")
Или ТипРодителя = Тип("ТаблицаФормы")
Тогда
//! СтрокаДерева = 0 // ГруппаФормы
Дочерние = СтрокаДерева.ПодчиненныеЭлементы;
#Если Клиент Тогда
ИначеЕсли Ложь
Или ТипРодителя = Тип("КоманднаяПанель")
Или ТипРодителя = Тип("КнопкаКоманднойПанели") И СтрокаДерева.ТипКнопки = ТипКнопкиКоманднойПанели.Подменю
Тогда
//! СтрокаДерева = 0 // КнопкаКоманднойПанели
Дочерние = СтрокаДерева.Кнопки;
#КонецЕсли
ИначеЕсли ТребоватьИерархию Тогда
ВызватьИсключение "Неподдерживаемый тип элемента дерева - " + ТипРодителя;
Иначе
Дочерние = Новый Массив;
КонецЕсли;
Возврат Дочерние; // Массив из см. СтрокаДерева
КонецФункции
// Процедура заполняет колонку дерева значением.
//
// Параметры
// ЭлементДЗ - ДеревоЗначений;
// ИмяКолонки - Строка;
// ЗначениеКолонки - Произвольный.
//
Процедура ЗаполнитьКолонкуДереваЛкс(ЭлементДЗ, ИмяКолонки, ЗначениеКолонки) Экспорт
Для Каждого ПодчиненнаяСтрока Из ЭлементДЗ.Строки Цикл
ПодчиненнаяСтрока[ИмяКолонки] = ЗначениеКолонки;
ЗаполнитьКолонкуДереваЛкс(ПодчиненнаяСтрока, ИмяКолонки, ЗначениеКолонки);
КонецЦикла;
КонецПроцедуры
Процедура ЗаполнитьКолонкуТабличнойЧастиЛкс(ТабличнаяЧасть, Знач ИмяКолонки, Знач Значение = Неопределено) Экспорт
ВыгрузкаКолонки = ТабличнаяЧасть.Выгрузить(, ИмяКолонки);
ВыгрузкаКолонки.ЗаполнитьЗначения(Значение);
ТабличнаяЧасть.ЗагрузитьКолонку(ВыгрузкаКолонки.ВыгрузитьКолонку(0), ИмяКолонки);
КонецПроцедуры
// Процедура удаляет все строки таблицы или дерева со значением в колонке.
//
// Параметры:
// ТаблицаИлиДерево - ТабличнаяЧасть, ТаблицаЗначений, ДеревоЗначений, СтрокаДереваЗначений -
// ИмяКолонки - Строка -
// ЗначениеКолонки - Произвольный -
//
Процедура УдалитьСтрокиТаблицыИлиДереваПоЗначениюЛкс(Знач ТаблицаИлиДерево, Знач ИмяКолонки, Знач ЗначениеКолонки) Экспорт
Если Ложь
Или ТипЗнч(ТаблицаИлиДерево) = Тип("ДеревоЗначений")
Или ТипЗнч(ТаблицаИлиДерево) = Тип("СтрокаДереваЗначений")
Тогда
Строки = ТаблицаИлиДерево.Строки;
НачальноеКоличество = Строки.Количество();
Для Счетчик = 1 По НачальноеКоличество Цикл
ПодчиненнаяСтрока = Строки[НачальноеКоличество - Счетчик];
Если ПодчиненнаяСтрока[ИмяКолонки] = ЗначениеКолонки Тогда
Строки.Удалить(ПодчиненнаяСтрока);
Иначе
УдалитьСтрокиТаблицыИлиДереваПоЗначениюЛкс(ПодчиненнаяСтрока, ИмяКолонки, ЗначениеКолонки);
КонецЕсли;
КонецЦикла;
Иначе
Найденные = ТаблицаИлиДерево.НайтиСтроки(Новый Структура(ИмяКолонки, ЗначениеКолонки));
Для Каждого Строка Из Найденные Цикл
ТаблицаИлиДерево.Удалить(Строка);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция ДекодироватьТекстИзXMLЛкс(Знач Текст) Экспорт
//{ Заменяем символы, критичные для XML
Текст = СтрЗаменить(Текст,"&","&");
Текст = СтрЗаменить(Текст,"<","<");
Текст = СтрЗаменить(Текст,">",">");
Текст = СтрЗаменить(Текст," "," ");
Результат = Текст;
// Этот способ вернет пустую строку, если текст содержит XML элемент
//ЧтениеXML = Новый ЧтениеXML;
//ЧтениеXML.УстановитьСтроку("<ф>" + Текст + "ф>");
//ЧтениеXML.Прочитать();
//ЧтениеXML.Прочитать();
//Результат = ЧтениеXML.Значение;
Возврат Результат;
КонецФункции
Функция КодироватьТекстВXMLЛкс(Текст) Экспорт
Если Текст = "" Тогда
Возврат "";
КонецЕсли;
//{ Заменяем символы, критичные для XML
//выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&");
//выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<");
//выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">");
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("");
ЗаписьXML.ЗаписатьНачалоЭлемента("ф");
ЗаписьXML.ЗаписатьТекст(Текст);
ЗаписьXML.ЗаписатьКонецЭлемента();
Результат = ТекстМеждуМаркерамиЛкс(ЗаписьXML.Закрыть(), "<ф>", "ф>", Ложь);
Возврат Результат;
КонецФункции
Функция СтрокаВнутрВХМЛТелоЛкс(Знач вхСтрока, выхХМЛТело = Неопределено, Знач ДобавитьПереносыСтрок = Ложь) Экспорт
выхХМЛТело = вхСтрока;
выхХМЛТело = КодироватьТекстВXMLЛкс(выхХМЛТело);
МаркерПодмены = "по!ап17ъzg";
выхХМЛТело = СтрЗаменить(выхХМЛТело, ", ", МаркерПодмены);
//выхХМЛТело = СтрЗаменить(выхХМЛТело, "{", ""); // Ложные срабатывания были
выхХМЛТело = СтрЗаменить(Символы.ПС + выхХМЛТело, Символы.ПС + "{", Символы.ПС + "");
//выхХМЛТело = СтрЗаменить(выхХМЛТело, "}", ""); // Ложные срабатывания были
выхХМЛТело = СтрЗаменить(выхХМЛТело, "},", ",");
выхХМЛТело = СтрЗаменить(выхХМЛТело + Символы.ПС, "}" + Символы.ПС, "" + Символы.ПС);
// Замена одинарных символов
выхХМЛТело = СтрЗаменить(выхХМЛТело, ",", "");
// Удаляем лишние блоки и
выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "");
выхХМЛТело = СтрЗаменить(выхХМЛТело, "" + Символы.ПС + "", "");
выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "");
выхХМЛТело = СтрЗаменить(выхХМЛТело, "" + Символы.ПС + "", "");
выхХМЛТело = СтрЗаменить(выхХМЛТело, МаркерПодмены, ", ");
Если ДобавитьПереносыСтрок Тогда
// Добавляем перенос строки к и к для удобства поиска различий
выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "" + СИМВОЛЫ.ПС);
выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "" + СИМВОЛЫ.ПС);
КонецЕсли;
Возврат выхХМЛТело;
КонецФункции
Функция НоваяВКОбщаяЛкс(Счетчик = 0) Экспорт
Пока Счетчик < 60 Цикл
Суффикс = XMLСтрока(Счетчик);
КэшКомпонентыИспорчен = Ложь;
Попытка
//ВК = Новый ("AddIn.ирОбщая" + Суффикс + ".AddIn"); // При порче кэша тут попытка не срабатывала и исключение шло в вызывающий метод
ВК = СоздатьВКОбщая(КэшКомпонентыИспорчен, Суффикс, Счетчик);
Прервать;
Исключение
Если ЗначениеЗаполнено(Счетчик) И Не КэшКомпонентыИспорчен Тогда
ВызватьИсключение;
КонецЕсли;
// https://www.hostedredmine.com/issues/889213
// Занимаем новую ячейку в кэше внутренних компонент рабочего процесса.
Это64битныйПроцесс = ирКэш.Это64битныйПроцессЛкс();
ИмяМакета = "ВК";
Если Это64битныйПроцесс Тогда
ИмяМакета = ИмяМакета + "64";
Иначе
ИмяМакета = ИмяМакета + "32";
КонецЕсли;
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ДвоичныеДанные = ирПортативный.ПолучитьМакет(ИмяМакета);
АдресКомпоненты = ПолучитьИмяВременногоФайла("dll");
ДвоичныеДанные.Записать(АдресКомпоненты);
//АдресКомпоненты = "D:\VC\Native_Comp_RDT\binWin32\AddInNative.dll"; // Для отладки
Иначе
// https://www.hostedredmine.com/issues/967297
//ДвоичныеДанные = Обработки.ирПортативный.ПолучитьМакет(ИмяМакета);
АдресКомпоненты = "Обработка.ирПортативный.Макет." + ИмяМакета;
КонецЕсли;
ИмяОбъекта = "ирОбщая" + Суффикс;
//Если ирКэш.НомерРежимаСовместимостиЛкс() >= 803021 Тогда
// Результат = Вычислить("ПодключитьВнешнююКомпоненту(АдресКомпоненты, ИмяОбъекта, ТипВнешнейКомпоненты.Native, ТипПодключенияВнешнейКомпоненты.НеИзолированно");
//Иначе
Результат = ПодключитьВнешнююКомпоненту(АдресКомпоненты, ИмяОбъекта, ТипВнешнейКомпоненты.Native);
//КонецЕсли;
Если Не Результат Тогда
ВызватьИсключение "Не удалось подключить внешнюю компоненту Общая";
КонецЕсли;
КонецПопытки;
КонецЦикла;
Возврат ВК;
КонецФункции
Функция ВКОбщаяЛкс() Экспорт
ВК = НоваяВКОбщаяЛкс();
Возврат ВК;
КонецФункции
// Проблему с порчей кэша удалось обойти только после вынесения этого кода в отдельную функцию https://www.hostedredmine.com/issues/889213
Функция СоздатьВКОбщая(КэшКомпонентыИспорчен, Знач Суффикс, Счетчик)
ВК = Новый ("AddIn.ирОбщая" + Суффикс + ".AddIn"); // ОбработкаОбъект.ирТипКомпонентаОбщая - 1-2мс
КэшКомпонентыИспорчен = Истина;
Счетчик = Счетчик + 1;
ВК.PID();
Возврат ВК;
КонецФункции
// Получает структуру для индикации прогресса цикла.
//
// Параметры:
// КоличествоПроходов - Число - максимальное значение счетчика, 0 - динамическое, -1 - только 1 выполнение и сразу вызвать ОбработатьИндикаторЛкс
// ПредставлениеПроцесса - Строка, *"Выполнено" - отображаемое название процесса;
// КоличествоОбновлений - Число, *100 - всего количество обновлений индикатора;
// ЛиВыводитьВремя - Булево, *Истина - выводить приблизительное время до окончания процесса;
// РазрешитьПрерывание - Булево, *Истина - разрешает пользователю прерывать процесс.
// МинимальныйПериодОбновления - Число, *1 - с, обновлять не чаще чем этот период, 0 - по количеству обновлений,
// эта реализация не поддерживает дробные значения;
// ТаблицаИндикаторов - ТаблицаЗначений,* - передается при необходимости многоуровневой индикации
//
// Возвращаемое значение:
// Структура - которую потом нужно будет передавать в метод ОбработатьИндикаторЛкс.
//
Функция ПолучитьИндикаторПроцессаЛкс(Знач КоличествоПроходов = 0, ПредставлениеПроцесса = "Выполнение", Знач КоличествоОбновлений = 0, ЛиВыводитьВремя = Истина, РазрешитьПрерывание = Истина,
МинимальныйПериодОбновления = 1, ТаблицаИндикаторов = Неопределено) Экспорт
ирПлатформа = ирКэш.Получить();
Если Не ЗначениеЗаполнено(КоличествоПроходов) Тогда
//#Если Клиент Тогда
// СостояниеЛкс(ПредставлениеПроцесса + "…");
//#КонецЕсли
КоличествоПроходов = 0;
КонецЕсли;
КоличествоПроходов = Цел(КоличествоПроходов);
ТаблицаИндикаторов = ирПлатформа.мИндикаторы;
Если ТаблицаИндикаторов.Количество() = 0 Тогда
#Если Клиент Тогда
ирКлиент.ПодключитьГлобальныйОбработчикОжиданияЛкс("ОсвободитьВсеИндикаторыПроцессовОтложенноЛкс");
#КонецЕсли
ИначеЕсли ТаблицаИндикаторов.Количество() >= 10 Тогда
ВызватьИсключение "Превышена допустимая глубина вложенности индикаторов";
КонецЕсли;
Индикатор = ТаблицаИндикаторов.Добавить();
Индикатор.КоличествоПроходов = КоличествоПроходов;
Индикатор.ПредставлениеПроцесса = ПредставлениеПроцесса;
Индикатор.ЛиВыводитьВремя = ЛиВыводитьВремя;
Индикатор.РазрешитьПрерывание = РазрешитьПрерывание;
Индикатор.РежимОтладки = ирКэш.РежимОтладкиЛкс();
Индикатор.ДатаНачалаПроцесса = ТекущаяДата();
Индикатор.МинимальныйПериодОбновления = МинимальныйПериодОбновления;
Индикатор.СледующееОбновление = Индикатор.ДатаНачалаПроцесса + Индикатор.МинимальныйПериодОбновления;
Индикатор.СледующаяПроверкаПрерывания = Индикатор.ДатаНачалаПроцесса + 5;
Если КоличествоОбновлений > 0 Тогда
Шаг = КоличествоПроходов / КоличествоОбновлений;
Иначе
Шаг = 0;
КонецЕсли;
Индикатор.Шаг = Шаг;
//Индикатор.СледующийСчетчик = 0;
//Индикатор.Счетчик = 0;
Если КоличествоПроходов = 1 Тогда
ОбработатьИндикаторЛкс(Индикатор);
Индикатор.Счетчик = 0;
КонецЕсли;
Возврат Индикатор;
КонецФункции
// Вызов метода при без параметра СтрокаИндикатора освобождает один полученный последним индикатор процесса. В качестве параметра этого метода можно передавать и конкретный индикатор процесса.
// При освобождении индикатора процесса выполняется либо его удаление из базы данных (без постоянного хранения состояния), либо сохранение его текущего состояния в базу данных (с постоянным хранением состояния)
// Параметры:
// СтрокаИндикатора - Неопределено, СтрокаТаблицыЗначений - Если Неопределено, то освобождается последний индикатор
// ВывестиИтогИндикации - Булево
// ТолькоВосстановитьСостояние - Булево - Устанавливается при обратном COM вызове
//
Процедура ОсвободитьИндикаторПроцессаЛкс(Знач Индикатор = Неопределено, Знач ВывестиИтогИндикации = Ложь, ДовестиСчетчикДоКонца = Истина) Экспорт
ирПлатформа = ирКэш.Получить();
ТаблицаИндикаторов = ирПлатформа.мИндикаторы;
Если Индикатор = Неопределено Тогда
Если ТаблицаИндикаторов.Количество() > 0 Тогда
Индикатор = ТаблицаИндикаторов[ТаблицаИндикаторов.Количество() - 1];
КонецЕсли;
КонецЕсли;
ИзменялосьСостояние = Индикатор <> Неопределено И ЗначениеЗаполнено(Индикатор.ТекстСостояния);
Если Индикатор <> Неопределено Тогда
Если ДовестиСчетчикДоКонца И Индикатор.КоличествоПроходов > 1 Тогда
ОбработатьИндикаторЛкс(Индикатор, Индикатор.КоличествоПроходов);
КонецЕсли;
Если ВывестиИтогИндикации Тогда
СообщитьИтогИндикацииЛкс(Индикатор);
КонецЕсли;
Если ТаблицаИндикаторов <> Неопределено Тогда
Если ТаблицаИндикаторов.Индекс(Индикатор) <> -1 Тогда
ТаблицаИндикаторов.Удалить(Индикатор);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ИзменялосьСостояние Тогда
Если Ложь
Или ТаблицаИндикаторов = Неопределено
Или ТаблицаИндикаторов.Количество() = 0
Тогда
НовоеСостояние = "";
Иначе
ОбновитьТекстСостоянияВсехИндикаторовЛкс(ТаблицаИндикаторов);
НовоеСостояние = ТаблицаИндикаторов[ТаблицаИндикаторов.Количество() - 1].ТекстСостояния;
КонецЕсли;
#Если Клиент Тогда
СостояниеЛкс(НовоеСостояние,, Истина);
#КонецЕсли
КонецЕсли;
КонецПроцедуры
Процедура ОсвободитьВсеИндикаторыПроцессовЛкс() Экспорт
ирПлатформа = ирКэш.Получить();
ТаблицаИндикаторов = ирПлатформа.мИндикаторы;
//Для Каждого СтрокаИндикатора Из ТаблицаИндикаторов Цикл
// ОбработатьИндикаторЛкс(СтрокаИндикатора, , Истина);
//КонецЦикла;
ТаблицаИндикаторов.Очистить();
КонецПроцедуры
// Проверяет и обновляет индикатор. Нужно вызывать на каждом проходе индицируемого цикла.
//
// Параметры:
// Индикатор - Структура - индикатора, полученная методом ПолучитьИндикаторПроцессаЛкс;
// Счетчик - Число, *Неопределено - внешний счетчик цикла.
// ДопТекст - -
//
// Возвращаемое значение:
// Булево - было ли обновление отображения
//
Функция ОбработатьИндикаторЛкс(Знач Индикатор, Счетчик = Неопределено, Знач ДопТекст = "") Экспорт
#Если Клиент Тогда
Попытка
Если Индикатор.РазрешитьПрерывание Тогда
ОбработкаПрерыванияПользователя();
КонецЕсли;
Исключение
// На клиенте бывает, что строка таблицы индикаторов уже была удалена из-за модальности и обработчиков ожидания
Возврат Ложь;
КонецПопытки;
#КонецЕсли
Если Индикатор.РежимОтладки Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Если Счетчик = Неопределено Тогда
Счетчик = Индикатор.Счетчик + 1;
КонецЕсли;
Индикатор.Счетчик = Счетчик;
ОбновитьИндикатор = Истина;
ОчиститьСостояние = Ложь;
Если Ложь
Или Счетчик < Индикатор.КоличествоПроходов
Или Индикатор.КоличествоПроходов = 0
Тогда
Если Индикатор.МинимальныйПериодОбновления > 0 Тогда
ТекущаяДата = ТекущаяДата();
Если ТекущаяДата >= Индикатор.СледующееОбновление Тогда
Индикатор.СледующееОбновление = ТекущаяДата + Индикатор.МинимальныйПериодОбновления;
Иначе
ОбновитьИндикатор = Ложь;
КонецЕсли;
КонецЕсли;
Если ОбновитьИндикатор Тогда
Если Индикатор.Шаг > 0 Тогда
Если Счетчик < Индикатор.СледующийСчетчик Тогда
ОбновитьИндикатор = Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иначе
Если ТипЗнч(Индикатор) <> Тип("СтрокаТаблицыЗначений") Тогда
ОчиститьСостояние = Истина;
ОбновитьИндикатор = Ложь;
КонецЕсли;
КонецЕсли;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если Счетчик = Неопределено Тогда Счетчик = Индикатор.Счетчик + 1; КонецЕсли; Индикатор.Счетчик = Счетчик; ОбновитьИндикатор = Истина; ОчиститьСостояние = Ложь; Если Ложь Или Счетчик < Индикатор.КоличествоПроходов Или Индикатор.КоличествоПроходов = 0 Тогда ТекущаяДата = ТекущаяДата(); Если Индикатор.МинимальныйПериодОбновления > 0 Тогда Если ТекущаяДата >= Индикатор.СледующееОбновление Тогда Индикатор.СледующееОбновление = ТекущаяДата + Индикатор.МинимальныйПериодОбновления; Иначе ОбновитьИндикатор = Ложь; КонецЕсли; КонецЕсли; Если ОбновитьИндикатор Тогда Если Индикатор.Шаг > 0 Тогда Если Счетчик < Индикатор.СледующийСчетчик Тогда ОбновитьИндикатор = Ложь; КонецЕсли; КонецЕсли; КонецЕсли; Иначе Если ТипЗнч(Индикатор) <> Тип("СтрокаТаблицыЗначений") Тогда ОчиститьСостояние = Истина; ОбновитьИндикатор = Ложь; КонецЕсли; КонецЕсли;
КонецЕсли;
#Если Клиент Тогда
Если ОчиститьСостояние Тогда
СостояниеЛкс("",, Истина);
КонецЕсли;
#КонецЕсли
Если ОбновитьИндикатор Тогда
Индикатор.СледующийСчетчик = Цел(Счетчик + Индикатор.Шаг);
Если ТипЗнч(Индикатор) = Тип("СтрокаТаблицыЗначений") Тогда
МассивИндикаторов = Индикатор.Владелец();
Иначе
МассивИндикаторов = Новый Массив;
МассивИндикаторов.Добавить(Индикатор);
КонецЕсли;
Если ирКэш.ЭтоФоновоеЗаданиеЛкс() Тогда
СтруктураИндикатора = СтруктураИзСтрокиТаблицыИлиДереваИлиВыборкиЛкс(Индикатор);
ТекстСостояния = "#Индикатор-" + ЗначениеВСтрокуВнутр(МассивИндикаторов);
СообщитьЛкс(ТекстСостояния);
Иначе
#Если Клиент Тогда
лИндикатор = ОбновитьТекстСостоянияВсехИндикаторовЛкс(МассивИндикаторов);
СостояниеЛкс(лИндикатор.ТекстСостояния + " " + ДопТекст, Индикатор.РазрешитьПрерывание, Истина);
#КонецЕсли
КонецЕсли;
КонецЕсли;
Возврат ОбновитьИндикатор;
КонецФункции
Функция ЛиПрерватьФоновоеЗаданиеЛкс(Индикатор) Экспорт
Результат = Ложь;
ТекущаяДата = ТекущаяДата();
Если Истина
И ирКэш.ДоступноСтрогаяСвязьСеансаСФоновымЗаданиемЛкс()
И ТекущаяДата >= Индикатор.СледующаяПроверкаПрерывания
И ирКэш.ЭтоФоновоеЗаданиеЛкс()
Тогда
Индикатор.СледующаяПроверкаПрерывания = ТекущаяДата + 5; // Проверяем не чаще раза в 5 секунд
ФлагиПрерыванияЗаданий = ВосстановитьЗначениеЛкс("ФлагиПрерыванияЗаданий");
Если ФлагиПрерыванияЗаданий <> Неопределено Тогда
ИД = ирКэш.ТекущийСеансЛкс().ПолучитьФоновоеЗадание().УникальныйИдентификатор;
Если ФлагиПрерыванияЗаданий.Найти(ИД) <> Неопределено Тогда
Результат = Истина;
СообщитьЛкс("Прервано по запросу пользователя", СтатусСообщения.Внимание);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция сравнивает две таблицы значений на идентичность структуры и данных. Обычно быстрее чем сравнение через сериализацию.
//
// Параметры
// ТаблицаЗначений1 - ТаблицаЗначений для сравнения
// ТаблицаЗначений2 - ТаблицаЗначений для сравнения
//
// Возвращаемое значение:
// Булево, идентичны или нет две таблицы
//
Функция ТаблицыЗначенийРавныЛкс(ТаблицаЗначений1, ТаблицаЗначений2) Экспорт
Если ТипЗнч(ТаблицаЗначений1) <> Тип("ТаблицаЗначений") ИЛИ ТипЗнч(ТаблицаЗначений2) <> Тип("ТаблицаЗначений") Тогда
Возврат Ложь;
КонецЕсли;
Если ТаблицаЗначений1.Количество() <> ТаблицаЗначений2.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Если ТаблицаЗначений1.Колонки.Количество() <> ТаблицаЗначений2.Колонки.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для каждого Колонка Из ТаблицаЗначений1.Колонки Цикл
Если ТаблицаЗначений2.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Если ирКэш.РежимОтладкиЛкс() Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для каждого СтрокаТаблицы1 Из ТаблицаЗначений1 Цикл
СтрокаТаблицы2 = ТаблицаЗначений2[ТаблицаЗначений1.Индекс(СтрокаТаблицы1)];
Если СтрокаТаблицы1[Колонка.Имя] <> СтрокаТаблицы2[Колонка.Имя] Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для каждого СтрокаТаблицы1 Из ТаблицаЗначений1 Цикл СтрокаТаблицы2 = ТаблицаЗначений2[ТаблицаЗначений1.Индекс(СтрокаТаблицы1)]; Если СтрокаТаблицы1[Колонка.Имя] <> СтрокаТаблицы2[Колонка.Имя] Тогда Возврат Ложь; КонецЕсли; КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции // СравнитьТаблицыЗначений()
Процедура ФункциональныеОпцииОбъектаМДЛкс(ОбъектМД, выхЗначенияФункОпций, выхСписокФункОпций = Неопределено, выхФункциональныеОпцииВключены = Неопределено) Экспорт
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
выхЗначенияФункОпций = Новый Структура;
выхФункциональныеОпцииВключены = Неопределено;
ОпцииОбъектовМД = ирКэш.ФункциональныеОпцииОбъектовМДЛкс();
Для Каждого СтрокаОпции Из ОпцииОбъектовМД.НайтиСтроки(Новый Структура("ИмяОбъектаМД", ПолноеИмяМД)) Цикл
выхФункциональныеОпцииВключены = Ложь;
ОпцияВключена = ПолучитьФункциональнуюОпцию(СтрокаОпции.ИмяОпции);
выхЗначенияФункОпций.Вставить(СтрокаОпции.ИмяОпции, ОпцияВключена);
Если ОпцияВключена Тогда
выхФункциональныеОпцииВключены = Истина;
КонецЕсли;
КонецЦикла;
Если выхФункциональныеОпцииВключены = Неопределено Тогда
выхФункциональныеОпцииВключены = Истина;
КонецЕсли;
выхСписокФункОпций = Новый СписокЗначений;
Для Каждого КлючИЗначение Из выхЗначенияФункОпций Цикл
выхСписокФункОпций.Добавить(КлючИЗначение.Ключ, КлючИЗначение.Ключ + " = " + ОпцияВключена);
КонецЦикла;
//Результат = Новый Структура;
//Результат.Вставить("ЗначенияФункОпций", выхЗначенияФункОпций);
//Результат.Вставить("СписокФункОпций", выхСписокФункОпций);
//Результат.Вставить("ФункциональныеОпцииВключены", выхФункциональныеОпцииВключены);
//Результат = ФункциональныеОпцииПоИмениОбъектаМДЛкс(ОбъектМД.ПолноеИмя());
//выхЗначенияФункОпций = Результат.ЗначенияФункОпций;
//выхФункциональныеОпцииВключены = Результат.ФункциональныеОпцииВключены;
//выхСписокФункОпций = Результат.СписокФункОпций;
КонецПроцедуры
Функция ЛиЕстьПравоПросмотраТиповЛкс(Знач ОписаниеТипов) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
ЕстьДоступКТипам = Истина;
Типы = ОписаниеТипов.Типы();
Если Типы.Количество() < 4 Тогда
ЕстьДоступКТипам = Ложь;
Для Каждого Тип Из Типы Цикл
ЕстьДоступ = Ложь;
ОбъектМДТипа = Метаданные.НайтиПоТипу(Тип);
Если ОбъектМДТипа <> Неопределено Тогда
ФункциональныеОпцииВключены = Неопределено;
ФункциональныеОпцииОбъектаМДЛкс(ОбъектМДТипа,,, ФункциональныеОпцииВключены);
Если ФункциональныеОпцииВключены И ПравоДоступа("Просмотр", ОбъектМДТипа) Тогда
ЕстьДоступ = Истина;
КонецЕсли;
Иначе
ЕстьДоступ = Истина;
КонецЕсли;
Если ЕстьДоступ Тогда
ЕстьДоступКТипам = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат ЕстьДоступКТипам;
КонецФункции
Функция СтруктураИзОбъектаЛкс(Знач Объект, выхТипОбъекта = Неопределено, выхПоляТаблицыБД = Неопределено, Знач ДобавлятьРасширенныеПредставления = Ложь, Знач ЯвноеПреставлениеПустого = Ложь,
Знач ЛиЗначенияВВидеТекста = Ложь) Экспорт
Если ЛиСсылкаНаОбъектБДЛкс(Объект) Тогда
Возврат Новый Структура;
КонецЕсли;
СтруктураОбъекта = Неопределено;
выхТипОбъекта = ТипОбъектаБДЛкс(Объект);
Если ЛиТипОбъектаБДЛкс(выхТипОбъекта) Тогда
ОбъектМД = Метаданные.НайтиПоТипу(выхТипОбъекта);
ПолноеИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ОбъектМД.ПолноеИмя());
Если Не ЛиКорневойТипРегистраБДЛкс(ПервыйФрагментЛкс(ПолноеИмяТаблицыБД)) Тогда
выхПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД);
#Если Сервер И Не Сервер Тогда
выхПоляТаблицыБД = Новый ТаблицаЗначений;
#КонецЕсли
СтруктураОбъекта = Новый Структура(СтрСоединитьЛкс(выхПоляТаблицыБД.ВыгрузитьКолонку("Имя")));
СтруктураОбъекта.Вставить("ДополнительныеСвойства");
Если ЛиТипИмитатораОбъектаЛкс(ТипЗнч(Объект)) Тогда
//! Объект = 0 // см. докОбъектБДПоКлючуСсылочный()
ЗаполнитьЗначенияСвойств(СтруктураОбъекта, Объект.Данные);
Иначе
ЗаполнитьЗначенияСвойств(СтруктураОбъекта, Объект);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если СтруктураОбъекта = Неопределено Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
СтруктураТипа = мПлатформа.СтруктураТипаИзЗначения(Объект,,, Истина);
//ТаблицаСлов = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипа,,,, Ложь,, "Свойство");
ПараметрыЗаполнения = мПлатформа.НовыеПараметрыЗаполненияСлов("Свойство",,,,, Ложь);
ТаблицаСлов = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипа, ПараметрыЗаполнения);
#Если Сервер И Не Сервер Тогда
ТаблицаСлов = Новый ТаблицаЗначений;
#КонецЕсли
СтруктураОбъекта = Новый Структура(СтрСоединитьЛкс(ТаблицаСлов.ВыгрузитьКолонку("Слово")));
Если ЗначениеЗаполнено(ПолноеИмяТаблицыБД) Тогда
// Регистр
СтруктураОбъекта.Удалить("ЭтотОбъект");
КонецЕсли;
Если СтруктураОбъекта.Количество() > 0 Тогда
//ЗаполнитьЗначенияСвойств(СтруктураОбъекта, Объект); // Закомментировано из-за недоступных на клиенте свойств https://www.hostedredmine.com/issues/955978
Для Каждого КлючИЗначение Из СтруктураОбъекта Цикл
Попытка
ЗаполнитьЗначенияСвойств(СтруктураОбъекта, Объект, КлючИЗначение.Ключ);
Исключение
СтруктураОбъекта[КлючИЗначение.Ключ] = "<Недоступно>";
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если ДобавлятьРасширенныеПредставления Или ЛиЗначенияВВидеТекста Тогда
НовыеСвойства = Новый Структура;
Для Каждого КлючИЗначение Из СтруктураОбъекта Цикл
ЗначениеСвойства = КлючИЗначение.Значение;
Если ТипЗнч(ЗначениеСвойства) = Тип("Строка") Тогда
РасширенноеПредставление = ЗначениеСвойства;
ДлинаСтроки = СтрДлина(ЗначениеСвойства);
Если ДлинаСтроки > 500 Тогда
РасширенноеПредставление = "" + ДлинаСтроки;
КонецЕсли;
Иначе
РасширенноеПредставление = РасширенноеПредставлениеЛкс(ЗначениеСвойства,,, Истина, Ложь, ЯвноеПреставлениеПустого);
КонецЕсли;
Если ЛиЗначенияВВидеТекста Тогда
НовыеСвойства.Вставить(КлючИЗначение.Ключ, "" + РасширенноеПредставление);
ИначеЕсли РасширенноеПредставление <> "" И РасширенноеПредставление <> "" + ЗначениеСвойства Тогда
НовыеСвойства.Вставить(КлючИЗначение.Ключ + "_Инфо", РасширенноеПредставление);
КонецЕсли;
КонецЦикла;
СкопироватьКоллекциюЛкс(НовыеСвойства, СтруктураОбъекта);
КонецЕсли;
Возврат СтруктураОбъекта;
КонецФункции
// Функция - Таблица значений из коллекции
//
// Параметры:
// Коллекция - -
// СтруктураТипаКоллекции - -
// ТаблицаКоллекции - -
// ОписанияКолонок - -
// СтруктураТипаЭлементаКоллекции - -
// ДобавитьКолонкуЗначенияЭлемента - -
// ДобавлятьРасширенныеПредставления - -
// РасширенноеПредставлениеХранилищЗначений - -
// МаксЧислоЭлементов - Число, *0 - ограничить число строк в таблице значений, 0 - не ограничивать
// Сортировка - Строка, *"" - строка упорядочивания, выполняется после контроля МаксЧислоЭлементов
//
// Возвращаемое значение:
// -
//
Функция ТаблицаЗначенийИзКоллекцииЛкс(Коллекция, СтруктураТипаКоллекции = Неопределено, ТаблицаКоллекции = Неопределено, выхОписанияКолонок = Неопределено,
СтруктураТипаЭлементаКоллекции = Неопределено, ДобавитьКолонкуТипаЭлемента = Истина, ДобавитьКолонкуЗначенияЭлемента = Ложь, ДобавлятьРасширенныеПредставления = Ложь,
РасширенноеПредставлениеХранилищЗначений = Ложь, МаксЧислоЭлементов = 0, Сортировка = "", СписокТиповОбнаруженныхЭлементов = Неопределено) Экспорт
Если ТипЗнч(Коллекция) = Тип("Массив") Тогда
ДобавитьКолонкуЗначенияЭлемента = Истина;
КонецЕсли;
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если СтруктураТипаКоллекции = Неопределено Тогда
СтруктураТипаКоллекции = мПлатформа.СтруктураТипаИзЗначения(Коллекция);
КонецЕсли;
Если ТаблицаКоллекции = Неопределено Тогда
ТаблицаКоллекции = Новый ТаблицаЗначений;
КонецЕсли;
Если ТаблицаКоллекции.Колонки.Количество() = 0 Тогда
Если ДобавитьКолонкуТипаЭлемента Тогда
ТаблицаКоллекции.Колонки.Добавить("_ТипЭлементаКоллекции", Новый ОписаниеТипов("Тип"), "Тип элемента коллекции");
КонецЕсли;
Если ДобавитьКолонкуЗначенияЭлемента Тогда
ТаблицаКоллекции.Колонки.Добавить("_ЗначениеЭлементаКоллекции",, "Значение элемента коллекции");
КонецЕсли;
КонецЕсли;
Если выхОписанияКолонок = Неопределено Тогда
выхОписанияКолонок = Новый Соответствие;
КонецЕсли;
ИмяКолонкиИндекс = "_Индекс_" + СуффиксСлужебногоСвойстваЛкс();
СвойстваЭлементовКоллекции = Новый Массив;
МассивТиповЭлементовКоллекции = мПлатформа.ТипыЭлементовКоллекции(СтруктураТипаКоллекции);
ЕстьИндекс = Ложь;
СтруктураТипаЭлементаКоллекции = мПлатформа.НоваяСтруктураТипа(); // т.к. цикл может и не выполниться ни разу
Для Каждого ТипЭлементаКоллекции Из МассивТиповЭлементовКоллекции Цикл
СтруктураТипаЭлементаКоллекции = мПлатформа.НоваяСтруктураТипа();
Если ТипЗнч(СтруктураТипаКоллекции.Метаданные) <> Тип("COMОбъект") Тогда // Сделано для ISWbemObject {WbemScripting.SwbemLocator}
СтруктураТипаЭлементаКоллекции.Метаданные = СтруктураТипаКоллекции.Метаданные; // Было закомментировано
КонецЕсли;
СтруктураТипаЭлементаКоллекции.ИмяОбщегоТипа = ТипЭлементаКоллекции;
// Создадим колонки таблицы
СтруктураКлюча = Новый Структура("БазовыйТип, ЯзыкПрограммы", ТипЭлементаКоллекции, 0);
НайденныеСтроки = мПлатформа.ТаблицаОбщихТипов.НайтиСтроки(СтруктураКлюча);
Если НайденныеСтроки.Количество() > 0 Тогда
СтруктураТипаЭлементаКоллекции.СтрокаОписания = НайденныеСтроки[0];
СтруктураТипаЭлементаКоллекции.ИмяОбщегоТипа = НайденныеСтроки[0].Слово;
КонецЕсли;
ДобавитьТипЭлементаВТаблицуКоллекции(ТаблицаКоллекции, СвойстваЭлементовКоллекции, ИмяКолонкиИндекс, выхОписанияКолонок, СтруктураТипаЭлементаКоллекции, ЕстьИндекс);
КонецЦикла;
// Заполним таблицу
КоличествоЭлементов = КоличествоЭлементовКоллекцииЛкс(Коллекция);
Если ТипЗнч(КоличествоЭлементов) <> Тип("Число") Тогда
КоличествоЭлементов = 0;
КонецЕсли;
Если КоличествоЭлементов > 0 И МаксЧислоЭлементов > 0 Тогда
КоличествоЭлементов = Мин(МаксЧислоЭлементов, КоличествоЭлементов);
Иначе
КоличествоЭлементов = Макс(МаксЧислоЭлементов, КоличествоЭлементов);
КонецЕсли;
СписокТиповОбнаруженныхЭлементов = Новый СписокЗначений;
СписокТиповОбнаруженныхЭлементов.ТипЗначения = Новый ОписаниеТипов("Тип");
НепустыеСвойства = Новый Структура;
Индикатор = ПолучитьИндикаторПроцессаЛкс(КоличествоЭлементов, "Подготовка таблицы");
Для Каждого ЭлементКоллекции Из Коллекция Цикл
ОбработатьИндикаторЛкс(Индикатор);
Если КоличествоЭлементов > 0 И КоличествоЭлементов = ТаблицаКоллекции.Количество() Тогда
Прервать;
КонецЕсли;
СтрокаЭлемента = ТаблицаКоллекции.Добавить();
Если ДобавитьКолонкуТипаЭлемента Тогда
СтрокаЭлемента._ТипЭлементаКоллекции = ТипЗнч(ЭлементКоллекции);
КонецЕсли;
Если ДобавитьКолонкуЗначенияЭлемента Тогда
СтрокаЭлемента._ЗначениеЭлементаКоллекции = ЭлементКоллекции;
КонецЕсли;
Если ЕстьИндекс Тогда
СтрокаЭлемента[ИмяКолонкиИндекс] = Коллекция.Индекс(ЭлементКоллекции); //@skip-check unknown-method-property
КонецЕсли;
Если СписокТиповОбнаруженныхЭлементов.НайтиПоЗначению(ТипЗнч(ЭлементКоллекции)) = Неопределено Тогда
СписокТиповОбнаруженныхЭлементов.Добавить(ТипЗнч(ЭлементКоллекции));
//лСтруктураТипаЭлементаКоллекции = мПлатформа.СтруктураТипаИзКонкретногоТипа(ТипЗнч(ЭлементКоллекции));
лСтруктураТипаЭлементаКоллекции = мПлатформа.СтруктураТипаИзЗначения(ЭлементКоллекции);
ДобавитьТипЭлементаВТаблицуКоллекции(ТаблицаКоллекции, СвойстваЭлементовКоллекции, ИмяКолонкиИндекс, выхОписанияКолонок, лСтруктураТипаЭлементаКоллекции);
КонецЕсли;
Если ТипЗнч(ЭлементКоллекции) = Тип("ОбъектXDTO") Тогда
Для Каждого СвойствоXDTO Из ЭлементКоллекции.Свойства() Цикл
Если ТаблицаКоллекции.Колонки.Найти(СвойствоXDTO.Имя) = Неопределено Тогда
ТаблицаКоллекции.Колонки.Добавить(СвойствоXDTO.Имя);
СвойстваЭлементовКоллекции.Добавить(СвойствоXDTO.Имя);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Для Каждого СвойствоЭлементаКоллекции Из СвойстваЭлементовКоллекции Цикл
Попытка
ЗначениеСвойства = ЭлементКоллекции[СвойствоЭлементаКоллекции];
Исключение
СтрокаЭлемента[СвойствоЭлементаКоллекции] = "<Недоступно>";
Продолжить;
КонецПопытки;
Если Не НепустыеСвойства.Свойство(СвойствоЭлементаКоллекции) Тогда
НепустыеСвойства.Вставить(СвойствоЭлементаКоллекции);
КонецЕсли;
//Попытка
// КоличествоДочернее = ЗначениеСвойства.Количество();
//Исключение
// Продолжить;
//КонецПопытки;
СтрокаЭлемента[СвойствоЭлементаКоллекции] = ЗначениеСвойства;
Если ДобавлятьРасширенныеПредставления Тогда
БазоваяКолонка = ТаблицаКоллекции.Колонки[СвойствоЭлементаКоллекции];
Если ТипЗнч(ЗначениеСвойства) = Тип("Строка") Тогда
РасширенноеПредставление = ЗначениеСвойства;
ДлинаСтроки = СтрДлина(ЗначениеСвойства);
Если ДлинаСтроки > 500 Тогда
РасширенноеПредставление = "" + ДлинаСтроки;
КонецЕсли;
Иначе
РасширенноеПредставление = РасширенноеПредставлениеЛкс(ЗначениеСвойства,,, РасширенноеПредставлениеХранилищЗначений, Ложь);
КонецЕсли;
Если РасширенноеПредставление <> "" И РасширенноеПредставление <> "" + ЗначениеСвойства Тогда
ИмяКолонки = СвойствоЭлементаКоллекции + "__Инфо";
БазоваяКолонка = ДобавитьКолонкуВТаблицуКоллекции(ТаблицаКоллекции, ИмяКолонки,, БазоваяКолонка, Новый ОписаниеТипов("Строка"));
СтрокаЭлемента[ИмяКолонки] = РасширенноеПредставление;
КонецЕсли;
ВложеннаяСтруктура = Неопределено;
Если Ложь
Или ТипЗнч(ЗначениеСвойства) = Тип("Структура")
Или ТипЗнч(ЗначениеСвойства) = Тип("ФиксированнаяСтруктура")
Тогда
ВложеннаяСтруктура = ЗначениеСвойства;
ИначеЕсли Ложь
Или ТипЗнч(ЗначениеСвойства) = Тип("СтрокаТаблицыЗначений")
Или ТипЗнч(ЗначениеСвойства) = Тип("СтрокаДереваЗначений")
Тогда
ВложеннаяСтруктура = СтруктураСвойствСтрокиТаблицыИлиДереваЛкс(ЗначениеСвойства);
ЗаполнитьЗначенияСвойств(ВложеннаяСтруктура, ЗначениеСвойства);
КонецЕсли;
Если ВложеннаяСтруктура <> Неопределено Тогда
Для Каждого КлючИЗначение Из ВложеннаяСтруктура Цикл
ИмяВложеннойКолонки = СвойствоЭлементаКоллекции + "_" + КлючИЗначение.Ключ;
Для Счетчик = 1 По 2 Цикл
Попытка
СтрокаЭлемента[ИмяВложеннойКолонки] = КлючИЗначение.Значение;
Прервать;
Исключение
ДобавитьКолонкуВТаблицуКоллекции(ТаблицаКоллекции, ИмяВложеннойКолонки,, БазоваяКолонка);
КонецПопытки;
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ОсвободитьИндикаторПроцессаЛкс();
// https://www.hostedredmine.com/issues/893358
Для Каждого СвойствоЭлементаКоллекции Из СвойстваЭлементовКоллекции Цикл
Если Не НепустыеСвойства.Свойство(СвойствоЭлементаКоллекции) Тогда
ТаблицаКоллекции.Колонки.Удалить(СвойствоЭлементаКоллекции);
КонецЕсли;
КонецЦикла;
Если Не ДобавлятьРасширенныеПредставления Тогда
ТаблицаКоллекции = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаКоллекции);
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ТаблицаКоллекции = Новый ТаблицаЗначений;
#КонецЕсли
Если ЗначениеЗаполнено(Сортировка) Тогда
ТаблицаКоллекции.Сортировать(Сортировка);
КонецЕсли;
СписокТиповОбнаруженныхЭлементов.СортироватьПоЗначению();
Возврат ТаблицаКоллекции;
КонецФункции
// Бинарным поиском находим упорядоченную позицию и вставляем туда строку. Очень быстрый алгоритм.
// Одинаковые значения вставляются всегда в конец серии.
// Параметры:
// НаправлениеСортировки - Число - если отрицательное, тогда убывающее, иначе возрастающее
Функция ВставитьСтрокуВУпорядоченнуюТаблицуЛкс(Знач ТаблицаЗначений, Знач ЗначениеПорядка, Знач ИмяКолонки, НаправлениеСортировки = +1) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ПозицияВставки = Неопределено;
Если ТаблицаЗначений.Количество() > 0 Тогда
КонечныйИндекс = ТаблицаЗначений.Количество() - 1;
НачальныйИндекс = 0;
КонечноеЗначение = ТаблицаЗначений[КонечныйИндекс][ИмяКолонки];
НачальноеЗначение = ТаблицаЗначений[НачальныйИндекс][ИмяКолонки];
Если Ложь
Или НаправлениеСортировки < 0 И НачальноеЗначение < ЗначениеПорядка
Или НаправлениеСортировки >= 0 И НачальноеЗначение > ЗначениеПорядка
Тогда
ПозицияВставки = 0;
ИначеЕсли Ложь
Или НаправлениеСортировки < 0 И КонечноеЗначение >= ЗначениеПорядка
Или НаправлениеСортировки >= 0 И КонечноеЗначение <= ЗначениеПорядка
Тогда
ПозицияВставки = КонечныйИндекс + 1;
Иначе
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Пока Истина Цикл
СреднийИндекс = Окр((КонечныйИндекс + НачальныйИндекс) / 2);
СреднееЗначение = ТаблицаЗначений[СреднийИндекс][ИмяКолонки];
Если Ложь
Или НаправлениеСортировки < 0 И СреднееЗначение >= ЗначениеПорядка
Или НаправлениеСортировки >= 0 И СреднееЗначение <= ЗначениеПорядка
Тогда
НачальныйИндекс = СреднийИндекс;
Иначе
КонечныйИндекс = СреднийИндекс;
КонецЕсли;
Если КонечныйИндекс - НачальныйИндекс <= 1 Тогда
ПозицияВставки = НачальныйИндекс + 1;
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Пока Истина Цикл СреднийИндекс = Окр((КонечныйИндекс + НачальныйИндекс) / 2); СреднееЗначение = ТаблицаЗначений[СреднийИндекс][ИмяКолонки]; Если Ложь Или НаправлениеСортировки < 0 И СреднееЗначение >= ЗначениеПорядка Или НаправлениеСортировки >= 0 И СреднееЗначение <= ЗначениеПорядка Тогда НачальныйИндекс = СреднийИндекс; Иначе КонечныйИндекс = СреднийИндекс; КонецЕсли; Если КонечныйИндекс - НачальныйИндекс <= 1 Тогда ПозицияВставки = НачальныйИндекс + 1; Прервать; КонецЕсли; КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ПозицияВставки = Неопределено Тогда
НоваяСтрока = ТаблицаЗначений.Добавить();
Иначе
НоваяСтрока = ТаблицаЗначений.Вставить(ПозицияВставки);
КонецЕсли;
НоваяСтрока[ИмяКолонки] = ЗначениеПорядка;
Возврат НоваяСтрока;
КонецФункции
Процедура ДобавитьТипЭлементаВТаблицуКоллекции(ТаблицаКоллекции, СвойстваЭлементовКоллекции, ИмяКолонкиИндекс, выхОписанияКолонок, СтруктураТипаЭлементаКоллекции, выхЕстьИндекс = Неопределено)
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
//ТаблицаСлов = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипаЭлементаКоллекции);
ТаблицаСлов = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипаЭлементаКоллекции);
Если СтруктураТипаЭлементаКоллекции.ИмяОбщегоТипа = "КлючИЗначение" Тогда
ТаблицаСлов.Сортировать("Слово Убыв");
КонецЕсли;
Для Каждого ВнутренняяСтрокаСлова Из ТаблицаСлов Цикл
Если ВнутренняяСтрокаСлова.ТипСлова = "Метод" Тогда
// Методы здесь игнорируем
Если ВнутренняяСтрокаСлова.Слово = "Индекс" И ТаблицаКоллекции.Колонки.Найти(ИмяКолонкиИндекс) = Неопределено Тогда
ТаблицаКоллекции.Колонки.Добавить(ИмяКолонкиИндекс, Новый ОписаниеТипов("Число"), "Индекс*");
выхЕстьИндекс = Истина;
КонецЕсли;
Продолжить;
КонецЕсли;
СтруктураСтрокОписаний = выхОписанияКолонок[ВнутренняяСтрокаСлова.Слово];
Если СтруктураСтрокОписаний = Неопределено Тогда
СтруктураСтрокОписаний = Новый Соответствие;
выхОписанияКолонок[ВнутренняяСтрокаСлова.Слово] = СтруктураСтрокОписаний;
КонецЕсли;
//КонкретныйТип = ирКэш.Получить().ПолучитьКонкретныйТипИзСтруктурыТипа(СтруктураТипаЭлементаКоллекции);
//Если КонкретныйТип <> Неопределено Тогда
//КонецЕсли;
СтруктураСтрокОписаний.Вставить(СтруктураТипаЭлементаКоллекции.ИмяОбщегоТипа, ВнутренняяСтрокаСлова.ТаблицаТипов);
ДобавитьКолонкуВТаблицуКоллекции(ТаблицаКоллекции, ВнутренняяСтрокаСлова.Слово, СвойстваЭлементовКоллекции);
КонецЦикла;
КонецПроцедуры
Функция ДобавитьКолонкуВТаблицуКоллекции(Знач ТаблицаКоллекции, Знач ИмяКолонки, Знач СвойстваЭлементовКоллекции = Неопределено, Знач БазоваяКолонка = Неопределено, Знач ОписаниеТипов = Неопределено)
#Если Сервер И Не Сервер Тогда
ТаблицаКоллекции = Новый ТаблицаЗначений;
#КонецЕсли
Результат = ТаблицаКоллекции.Колонки.Найти(ИмяКолонки);
Если Результат = Неопределено Тогда
Если БазоваяКолонка = Неопределено Тогда
Результат = ТаблицаКоллекции.Колонки.Добавить(ИмяКолонки, ОписаниеТипов);
Иначе
Результат = ТаблицаКоллекции.Колонки.Вставить(ТаблицаКоллекции.Колонки.Индекс(БазоваяКолонка) + 1, ИмяКолонки, ОписаниеТипов);
КонецЕсли;
Если СвойстваЭлементовКоллекции <> Неопределено Тогда
СвойстваЭлементовКоллекции.Добавить(ИмяКолонки);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПреобразоватьЗначениеИзSDBLЛкс(Знач ЗначениеSDBL, АдресЧужойСхемыБД = "", РазрешитьНаходитьБезСкобок = Ложь) Экспорт
Если СтрДлина(ЗначениеSDBL) > 100 Тогда
Возврат Неопределено;
КонецЕсли;
Если СтрЧислоВхождений(ЗначениеSDBL, ":") <> 1 Тогда
Возврат Неопределено;
КонецЕсли;
Если РазрешитьНаходитьБезСкобок Тогда
ЗначениеSDBL = "(" + ЗначениеSDBL + ")";
КонецЕсли;
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
#Если Сервер И Не Сервер Тогда
РегВыражение = обработки.ирОболочкаРегВыражение.Создать();
#КонецЕсли
РегВыражение.Pattern = "\((\d+):([\dA-F]{32})\)";
Вхождения = РегВыражение.НайтиВхождения(ЗначениеSDBL);
Если Вхождения.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;
Вхождение = Вхождения[0];
#Если Сервер И Не Сервер Тогда
Вхождение = Обработки.ирОболочкаРегВхождение.Создать();
#КонецЕсли
СтрокаНомераТаблицы = Вхождение.SubMatches(0);
ИдентификаторОбъекта = Вхождение.SubMatches(1);
ПолноеИмяМД = МетаданныеПоНомеруСсылочнойТаблицыЛкс(СтрокаНомераТаблицы, АдресЧужойСхемыБД);
ОбъектМетаданныхНайден = Истина;
Если Не ЗначениеЗаполнено(ПолноеИмяМД) Тогда
ПолноеИмяМД = "НеизвестныйСсылочныйТип" + СтрокаНомераТаблицы;
ОбъектМетаданныхНайден = Ложь;
КонецЕсли;
Результат = ПолноеИмяМД + "._" + ИдентификаторОбъекта;
Если ОбъектМетаданныхНайден И Не ЗначениеЗаполнено(АдресЧужойСхемыБД) Тогда
//СтруктураБД = ирКэш.СтруктураХраненияБДЛкс(Ложь);
// Этот способ не работал для перечислений
//УникальныйИдентификатор = Новый УникальныйИдентификатор(ПолучитьГУИДПрямойИзИнверсногоЛкс(Фрагменты[1]));
//Массив = Новый Массив();
//Если ЗначениеЗаполнено(УникальныйИдентификатор) Тогда
// Массив.Добавить(УникальныйИдентификатор);
//КонецЕсли;
//Значение = Новый (Тип(ПолучитьИмяТипаСсылкиТаблицыБДЛкс(ПолноеИмяМД)), Массив);
//
ПустаяСсылка = Новый (Тип(ИмяТипаИзПолногоИмениТаблицыБДЛкс(ПолноеИмяМД)));
ПустаяСсылкаВнутр = ЗначениеВСтрокуВнутр(ПустаяСсылка);
ФрагментыПустойСсылки = СтрРазделитьЛкс(ПустаяСсылкаВнутр, ":");
СсылкаВнутр = ФрагментыПустойСсылки[0] + ":" + ИдентификаторОбъекта + "}";
Попытка
Результат = ЗначениеИзСтрокиВнутрЛкс(СсылкаВнутр);
Исключение
// Например, если Фрагменты[1] содержит неверное число символов
Пустышка = 0;
КонецПопытки;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция НавигационнаяСсылкаВЗначениеЛкс(Знач ТекущеееЗначение) Экспорт
//e1cib/data/Справочник.ирОбъектыДляОтладки?ref=aa3a0009dd50223411e1c2907cccb6b7
//Справочник.ирОбъектыДляОтладки?ref=aa3a0009dd50223411e1c2907cccb6b7
ТекстСсылки = ПоследнийФрагментЛкс(ТекущеееЗначение, "e1cib/data/");
Разделитель = "?ref=";
Фрагменты = СтрРазделитьЛкс(ТекстСсылки, Разделитель);
Если Фрагменты.Количество() = 1 Тогда
Возврат Неопределено;
КонецЕсли;
Идентификатор = Фрагменты[1];
Идентификатор = ПолучитьГУИДПрямойИзИнверсногоЛкс(Идентификатор);
ПолноеИмяМД = Фрагменты[0];
ОбъектМД = ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
Если ОбъектМД = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
МенеджерМД = Новый (ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяМД, "Менеджер"));
ЗначениеСсылки = МенеджерМД.ПолучитьСсылку(Новый УникальныйИдентификатор(Идентификатор));
Возврат ЗначениеСсылки;
КонецФункции
Функция ВнешняяНавигационнаяСсылкаЛкс(Знач Ссылка) Экспорт
Возврат ПолучитьНавигационнуюСсылкуИнформационнойБазы() + "#" + ПолучитьНавигационнуюСсылку(Ссылка);
КонецФункции
Функция МетаданныеПоНомеруСсылочнойТаблицыЛкс(СтрокаНомерТаблицы, АдресЧужойСхемыБД = "") Экспорт
СтруктураБД = ирКэш.СтруктураХраненияБДЛкс(, АдресЧужойСхемыБД);
#Если Сервер И Не Сервер Тогда
СтруктураБД = Новый ТаблицаЗначений;
#КонецЕсли
СловарьШаблоновМетаданных = ирКэш.СловарьШаблоновХраненияБДЛкс(, АдресЧужойСхемыБД);
Для Каждого СтрокаШаблона Из СловарьШаблоновМетаданных.НайтиСтроки(Новый Структура("КоличествоПараметров", 1)) Цикл
ИмяКандидат = СтрЗаменить(СтрокаШаблона.ПозиционныйШаблон, "1", СтрокаНомерТаблицы);
СтрокаСтруктуры = СтруктураБД.Найти(ИмяКандидат, "КраткоеИмяТаблицыХранения");
Если СтрокаСтруктуры <> Неопределено Тогда
Возврат СтрокаСтруктуры.Метаданные;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
// Функция - Преобразовать представление в ссылку лкс
//
// Параметры:
// МенеджерИлиОбъектМД - ОбъектМетаданных, СправочникМенеджер, ДокументМенеджер, Строка -
// Текст - -
// ПроверятьПредставлениеТипаДокумента - -
// КэшПоиска - -
//
// Возвращаемое значение:
// Неопределено, Ссылка, СписокЗначений -
//
Функция ПреобразоватьПредставлениеВСсылкуЛкс(Знач МенеджерИлиОбъектМД = Неопределено, Знач Текст, Знач ПроверятьПредставлениеТипаДокумента = Ложь, КэшПоиска = Неопределено) Экспорт
Текст = СокрЛП(Текст);
Если ТипЗнч(МенеджерИлиОбъектМД) = Тип("Строка") Тогда
МенеджерИлиОбъектМД = Метаданные.НайтиПоПолномуИмени(МенеджерИлиОбъектМД);
КонецЕсли;
Если МенеджерИлиОбъектМД = Неопределено Тогда
Для Каждого МетаДокумент Из Метаданные.Документы Цикл
ПредставлениеТипа = ПредставлениеСсылкиИзОбъектаМДЛкс(МетаДокумент);
Если СтрНачинаетсяСЛкс(Текст, ПредставлениеТипа) Тогда
ОбъектМД = МетаДокумент;
Менеджер = Документы[МетаДокумент.Имя];
Прервать;
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(МенеджерИлиОбъектМД) = Тип("ОбъектМетаданных") Тогда
ОбъектМД = МенеджерИлиОбъектМД;
Менеджер = ПолучитьМенеджерЛкс(МенеджерИлиОбъектМД);
Иначе
Менеджер = МенеджерИлиОбъектМД; // ДокументМенеджер, СправочникМенеджер
КонецЕсли;
Если Менеджер = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Если Не ПроверятьПредставлениеТипаДокумента Тогда
УникальныйИдентификатор = ирКэш.Получить().УникальныйИдентификаторИзСтроки(Текст);
Если УникальныйИдентификатор <> Неопределено Тогда
Значение = Менеджер.ПолучитьСсылку(УникальныйИдентификатор);
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(Значение) Тогда
Если ОбъектМД = Неопределено Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Менеджер));
КонецЕсли;
ПоляБД = ирКэш.ПоляТаблицыБДЛкс(ОбъектМД.ПолноеИмя());
РегВыражение = ирКэш.Получить().мРегВыражение;
РегВыражение.Pattern = "([^ ]+)\ от\ (\d+\.\d+\.\d+\ \d+\:\d+\:\d+)$"; // станадартное представление документа
Результаты = РегВыражение.НайтиВхождения(Текст);
Если Истина
И ПоляБД.Найти("Номер") <> Неопределено
И ПоляБД.Найти("Дата") <> Неопределено
И Результаты.Количество() > 0
Тогда
Номер = Результаты[0].SubMatches(0);
Дата = Результаты[0].SubMatches(1);
Попытка
Дата = Дата(Дата);
Исключение
Дата = Неопределено;
КонецПопытки;
ПредставлениеТипа = ПредставлениеСсылкиИзОбъектаМДЛкс(ОбъектМД);
Если Истина
И Дата <> Неопределено
И (Ложь
Или Не ПроверятьПредставлениеТипаДокумента
Или СтрокиРавныЛкс(Лев(Текст, Результаты[0].FirstIndex), ПредставлениеТипа + " "))
Тогда
КлючКэша = ОбъектМД.ПолноеИмя() + "." + Текст;
Если КэшПоиска <> Неопределено Тогда
Значение = КэшПоиска[КлючКэша];
КонецЕсли;
Если Значение = Неопределено Тогда
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| _Т.Ссылка
|ИЗ
| " + ОбъектМД.ПолноеИмя() + " КАК _Т
|ГДЕ
| _Т.Номер = &Номер
| И _Т.Дата = &Дата
|";
Запрос.УстановитьПараметр("Номер", Номер);
Запрос.УстановитьПараметр("Дата", Дата);
Значение = Новый СписокЗначений;
Значение.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(0));
Если Значение.Количество() > 0 Тогда
Для Каждого ЭлементСписка Из Значение Цикл
ЭлементСписка.Представление = "" + ЭлементСписка.Значение + " (" + ЭлементСписка.Значение.УникальныйИдентификатор() + ")";
КонецЦикла;
КонецЕсли;
Если КэшПоиска <> Неопределено Тогда
КэшПоиска[КлючКэша] = Значение;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Значение;
КонецФункции
Функция ПредставлениеСсылкиИзОбъектаМДЛкс(Знач ОбъектМД) Экспорт
ПредставлениеТипа = ОбъектМД.ПредставлениеОбъекта;
Если Не ЗначениеЗаполнено(ПредставлениеТипа) Тогда
ПредставлениеТипа = ОбъектМД.Представление();
КонецЕсли;
Возврат ПредставлениеТипа;
КонецФункции
// Функция - Ключ основного объекта формы лкс
//
// Параметры:
// Форма - -
//
// Возвращаемое значение:
// ЛюбаяСсылка -
//
Функция КлючОсновногоОбъектаФормыЛкс(Форма = Неопределено) Экспорт
Если Форма = Неопределено Тогда
#Если Клиент Тогда
Форма = ирКлиент.АктивнаяУправляемаяФормаЛкс();
#КонецЕсли
КонецЕсли;
Если ТипЗнч(Форма) = ТипУправляемаяФормаЛкс() Тогда
Ссылка = СсылкаОсновногоОбъектаФормыЛкс(Форма);
Если Не ЛиКлючСсылкиИлиРегистраЛкс(Ссылка) Тогда
Попытка
Ссылка = Форма.Параметры.Ключ;
Исключение
КонецПопытки;
КонецЕсли;
ИначеЕсли Истина
И ТипЗнч(Форма) = Тип("Структура")
И Форма.Тип = ирОбщий.ТипУправляемаяФормаЛкс()
И Форма.Свойство("Реквизиты")
Тогда
ИменаРеквизитов = ирКэш.Получить().ИменаРеквизитовФормы(Форма, "");
//ИмяОсновного = ИменаРеквизитов.Основной;
ИмяОсновного = "Объект";
Попытка
ОписаниеТипов = ИменаРеквизитов.Все[ИмяОсновного];
Ссылка = ОписаниеТипов.ПривестиЗначение().Ссылка;
Исключение
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
Иначе
Попытка
Ссылка = Форма.Ссылка;
Исключение
Попытка
Ссылка = Форма.ВыбОбъект;
Исключение
КонецПопытки;
КонецПопытки;
КонецЕсли;
Если Не ЛиКлючСсылкиИлиРегистраЛкс(Ссылка) Тогда
Ссылка = Неопределено;
КонецЕсли;
Возврат Ссылка;
КонецФункции
Функция СсылкаОсновногоОбъектаФормыЛкс(Знач ТекущаяФорма) Экспорт
ИмяОсновногоРеквизита = "Объект";
Попытка
Ссылка = ТекущаяФорма[ИмяОсновногоРеквизита].Ссылка;
Исключение
ИмяОсновногоРеквизита = ПеревестиСтроку(ИмяОсновногоРеквизита);
Ссылка = Неопределено;
КонецПопытки;
Если Ссылка = Неопределено Тогда
Попытка
Ссылка = ТекущаяФорма[ИмяОсновногоРеквизита].Ссылка;
Исключение
Ссылка = Неопределено;
КонецПопытки;
КонецЕсли;
Возврат Ссылка;
КонецФункции
//.
// Параметры:
// ОбъектМД - ОбъектМетаданных -
// Возвращаемое значение:
// ОбъектМетаданныхФорма, Неопределено -
Функция ОсновнаяФормаОбъектаМДЛкс(Знач ОбъектМД) Экспорт
РолиФормы = Новый Массив();
КорневойТип = ПервыйФрагментЛкс(ОбъектМД.ПолноеИмя());
ТипМета = ОписаниеТипаМетаданныхЛкс(КорневойТип);
Если ТипМета.Категория = 0 Тогда
РолиФормы.Добавить("ОсновнаяФормаОбъекта");
РолиФормы.Добавить("ОсновнаяФормаЗаписи");
Иначе
РолиФормы.Добавить("ОсновнаяФорма");
КонецЕсли;
Для Каждого ИмяСвойстваОсновнойФормы Из РолиФормы Цикл
Попытка
МетаФорма = ОбъектМД[ИмяСвойстваОсновнойФормы];
Прервать;
Исключение
КонецПопытки;
КонецЦикла;
Возврат МетаФорма;
КонецФункции
Функция ОбщийМодульЛкс(Имя) Экспорт
Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда
Модуль = Вычислить(Имя);
Иначе
Модуль = Неопределено;
КонецЕсли;
Возврат Модуль;
КонецФункции
// https://its.1c.ru/db/bsp317doc/content/538/hdoc
Функция НеблокирующиеМетаданныеБСПЛкс() Экспорт
Если ирКэш.НомерВерсииБСПЛкс() < 203 Тогда
Возврат Новый Массив;
КонецЕсли;
#Если ТолстыйКлиентУправляемоеПриложение И Не Сервер Тогда
ИменаМД = ирСервер.НеблокирующиеМетаданныеБСПЛкс();
#Иначе
Массив = Новый Массив;
ИнтеграцияПодсистемБСПМой = ОбщийМодульЛкс("ИнтеграцияПодсистемБСП");
Если ИнтеграцияПодсистемБСПМой <> Неопределено Тогда
#Если Сервер И Не Сервер Тогда
ИнтеграцияПодсистемБСПМой = ИнтеграцияПодсистемБСП;
#КонецЕсли
ИнтеграцияПодсистемБСПМой.ПриДобавленииИсключенийПоискаСсылок(Массив); //@skip-check unknown-method-property
КонецЕсли;
ОбщегоНазначенияПереопределяемыйМой = ОбщийМодульЛкс("ОбщегоНазначенияПереопределяемый");
Если ОбщегоНазначенияПереопределяемыйМой <> Неопределено Тогда
#Если Сервер И Не Сервер Тогда
ОбщегоНазначенияПереопределяемыйМой = ОбщегоНазначенияПереопределяемый;
#КонецЕсли
ОбщегоНазначенияПереопределяемыйМой.ПриДобавленииИсключенийПоискаСсылок(Массив); //@skip-check unknown-method-property
КонецЕсли;
ИменаМД = Новый Массив;
Для Каждого ОбъектМД Из Массив Цикл
Если ТипЗнч(ОбъектМД) = Тип("ОбъектМетаданных") Тогда
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
Иначе
ПолноеИмяМД = ОбъектМД;
КонецЕсли;
ИменаМД.Добавить(ПолноеИмяМД);
КонецЦикла;
#КонецЕсли
Возврат ИменаМД;
КонецФункции
Функция ДопРеквизитыБСПОбъектаЛкс(СсылкаОбъекта) Экспорт
#Если Сервер И Не Сервер Тогда
СсылкаОбъекта = Справочники.ирАлгоритмы.ПустаяСсылка();
#КонецЕсли
СписокСвойств = Новый Массив;
Если Истина
И ирКэш.ДоступноДопРеквизитыБСПЛкс()
И ТабличныеЧастиОбъектаЛкс(СсылкаОбъекта).Свойство("ДополнительныеРеквизиты")
И Метаданные.ОпределяемыеТипы.ВладелецДополнительныхСведений.Тип.СодержитТип(ТипЗнч(СсылкаОбъекта)) //@skip-check unknown-method-property
Тогда
СписокСвойств = ирСервер.СписокДопСвойствОбъектаБСПЛкс(СсылкаОбъекта);
КонецЕсли;
Возврат СписокСвойств;
КонецФункции
// Доп. сведение сразу записывается, а доп. реквизит только устанавливается в ТЧ.ДополнительныеРеквизиты без записи
//
// Параметры:
// Объект - - ? -
// ДопРеквизит - - ?, ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения -
// НовоеЗначение - - ? -
// ИмяПоляСсылка - - ? -
// ОбработатьРеквизит - -
// ОбработатьСведение - -
//
Процедура УстановитьЗначениеДопРеквизитаБСПЛкс(Объект, ДопРеквизит, НовоеЗначение, ИмяПоляСсылка = Неопределено, ОбработатьРеквизит = Истина, ОбработатьСведение = Истина, ТаблицаДопСведения = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ДопРеквизит = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПустаяСсылка(); //@skip-check unknown-method-property
#КонецЕсли
Если Не ЗначениеЗаполнено(ИмяПоляСсылка) Тогда
ИмяПоляСсылка = ПеревестиСтроку("Ссылка");
КонецЕсли;
Если Не ДопРеквизит.ЭтоДополнительноеСведение Тогда // изменение дополнительного реквизита
Если Не ОбработатьРеквизит Тогда
Возврат;
КонецЕсли;
//Если Не СвойствоНужноИзменять(Объект.Ссылка, ДопРеквизит, Параметры) Тогда
// Продолжить;
//КонецЕсли;
НайденнаяСтрока = Объект.ДополнительныеРеквизиты.Найти(ДопРеквизит, "Свойство");
Если ЗначениеЗаполнено(НовоеЗначение) Тогда
Если НайденнаяСтрока = Неопределено Тогда
НайденнаяСтрока = Объект.ДополнительныеРеквизиты.Добавить();
НайденнаяСтрока.Свойство = ДопРеквизит;
КонецЕсли;
НайденнаяСтрока.Значение = НовоеЗначение;
//Если УправлениеСвойствамиСлужебный.ИспользоватьНеограниченнуюСтроку(ДопРеквизит.ТипЗначения, ДопРеквизит.МногострочноеПолеВвода) Тогда // Недоступен в управляемом клиенте
Если Ложь
Или ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ДопРеквизит.ТипЗначения)
Или ЛиОписаниеТиповПростогоСтроковогоТипаЛкс(ДопРеквизит.ТипЗначения) И ДопРеквизит.МногострочноеПолеВвода
Тогда
НайденнаяСтрока.ТекстоваяСтрока = НовоеЗначение;
КонецЕсли;
Иначе
Если НайденнаяСтрока <> Неопределено Тогда
Объект.ДополнительныеРеквизиты.Удалить(НайденнаяСтрока);
КонецЕсли;
КонецЕсли;
Иначе // изменение дополнительного сведения
Если Не ОбработатьСведение Тогда
Возврат;
КонецЕсли;
//Если Не СвойствоНужноИзменять(Объект.Ссылка, ДопРеквизит, Параметры) Тогда
// Продолжить;
//КонецЕсли;
МенеджерРегистра = РегистрыСведений.ДополнительныеСведения; //@skip-check unknown-method-property
МенеджерЗаписи = МенеджерРегистра.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = Объект[ИмяПоляСсылка];
МенеджерЗаписи.Свойство = ДопРеквизит;
МенеджерЗаписи.Значение = НовоеЗначение;
Если ТаблицаДопСведения = Неопределено Тогда
НаборЗаписей = МенеджерРегистра.СоздатьНаборЗаписей();
ДопСведения = НаборЗаписейИзКлючаЛкс(НаборЗаписей, МенеджерЗаписи, Истина);
ЗаписатьОбъектЛкс(ДопСведения);
Иначе
#Если Сервер И Не Сервер Тогда
ТаблицаДопСведения = Новый ТаблицаЗначений;
#КонецЕсли
СтрокаНабора = ТаблицаДопСведения.Найти(МенеджерЗаписи.Свойство , "Свойство");
Если СтрокаНабора = Неопределено Тогда
СтрокаНабора = ТаблицаДопСведения.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаНабора, МенеджерЗаписи);
КонецЕсли;
СтрокаНабора.Значение = МенеджерЗаписи.Значение;
Если Не ЗначениеЗаполнено(СтрокаНабора.Значение) Или СтрокаНабора.Значение = Ложь Тогда
ТаблицаДопСведения.Удалить(СтрокаНабора);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ЗначениеДопРеквизитаБСПЛкс(Знач Объект, ДопРеквизит, Знач ИмяПоляСсылка = "") Экспорт
Если Не ЗначениеЗаполнено(ИмяПоляСсылка) Тогда
ИмяПоляСсылка = ПеревестиСтроку("Ссылка");
КонецЕсли;
Если Не ДопРеквизит.ЭтоДополнительноеСведение Тогда // изменение дополнительного реквизита
НайденнаяСтрока = Объект.ДополнительныеРеквизиты.Найти(ДопРеквизит, "Свойство");
Если НайденнаяСтрока <> Неопределено Тогда
ТекущееЗначение = НайденнаяСтрока.Значение;
КонецЕсли;
Иначе
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| ДополнительныеСведения.Значение КАК Значение
|ИЗ
| РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения
|ГДЕ
| ДополнительныеСведения.Свойство = &Свойство
| И ДополнительныеСведения.Объект = &Объект
|";
Запрос.УстановитьПараметр("Объект", Объект[ИмяПоляСсылка]);
Запрос.УстановитьПараметр("Свойство", ДопРеквизит);
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() > 0 Тогда
ТекущееЗначение = Результат[0].Значение;
Иначе
ТекущееЗначение = Неопределено;
КонецЕсли;
КонецЕсли;
Возврат ТекущееЗначение;
КонецФункции
Функция ЭтоУпрДинамическийСписокИРЛкс(Знач Форма) Экспорт
Возврат Форма.ИмяФормы = "Обработка.ирДинамическийСписок.Форма.ФормаУпр";
КонецФункции
Функция УправляемаяФормаБСП_ВыполнитьНаСервереЛкс(Знач Форма, Знач Обработчик, ПараметрКоманды = Неопределено) Экспорт
ИмяКомандыВФорме = ПоследнийФрагментЛкс(Обработчик);
ПараметрыВызова = Новый Структура;
ПараметрыВызова.Вставить("ИмяКомандыВФорме", ИмяКомандыВФорме);
ПараметрыВызова.Вставить("ПараметрКоманды", ПараметрКоманды);
ПараметрыВызова.Вставить("Результат", Новый Структура("Текст"));
Если ЭтоУпрДинамическийСписокИРЛкс(Форма) Тогда
Форма.Подключаемый_ВыполнитьКомандуНаСервере(ПараметрыВызова);
РезультатВызова = ПараметрыВызова.Результат.Текст;
ИначеЕсли Истина
И ирКэш.НомерВерсииБСПЛкс() > 200
И (Ложь
Или МетодРеализованЛкс(Форма, "Подключаемый_ВыполнитьКомандуНаСервере")
Или МетодРеализованЛкс(Форма, "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере"))
Тогда
Попытка
ТаблицаКомандБСП = ПолучитьИзВременногоХранилища(Форма.ПараметрыПодключаемыхКоманд.АдресТаблицыКоманд);
Исключение
ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
Возврат Неопределено;
КонецПопытки;
#Если Сервер И Не Сервер Тогда
ТаблицаКомандБСП = Новый ТаблицаЗначений;
УправляемаяФормаБСП_СерверныеМетаданныеЛкс();
#КонецЕсли
Если ТаблицаКомандБСП.Найти(ИмяКомандыВФорме, "ИмяВФорме") = Неопределено Тогда
ОписаниеКоманды = ТаблицаКомандБСП.Добавить();
ОписаниеКоманды.ИмяВФорме = ИмяКомандыВФорме;
ОписаниеКоманды.Обработчик = Обработчик;
АдресТаблицыКомандБСП = ПоместитьВоВременноеХранилище(ТаблицаКомандБСП, Форма.УникальныйИдентификатор);
Форма.ПараметрыПодключаемыхКоманд.АдресТаблицыКоманд = АдресТаблицыКомандБСП;
КонецЕсли;
Если МетодРеализованЛкс(Форма, "Подключаемый_ВыполнитьКомандуНаСервере") Тогда
Форма.Подключаемый_ВыполнитьКомандуНаСервере(ПараметрыВызова, );
ИначеЕсли МетодРеализованЛкс(Форма, "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере") Тогда
Форма.Подключаемый_ПродолжитьВыполнениеКомандыНаСервере(ПараметрыВызова, );
КонецЕсли;
РезультатВызова = ПараметрыВызова.Результат.Текст;
КонецЕсли;
Возврат РезультатВызова;
КонецФункции
Функция УправляемаяФормаБСП_СерверныеМетаданныеЛкс(ПараметрКоманды, Контекст) Экспорт
Результат = Новый Структура;
НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных;
СкопироватьЭлементыКомпоновкиЛкс(НастройкиКомпоновки.УсловноеОформление, Контекст.Форма.УсловноеОформление);
ОбработчикиСобытий = ВсеОбработчикиСобытийФормаЛкс(Контекст.Форма);
ОбработчикиСобытий.ЗаполнитьЗначения(Неопределено, "СтрокаОписания");
Результат.Вставить("ОбработчикиСобытий", ОбработчикиСобытий);
Результат.Вставить("Компоновка", НастройкиКомпоновки);
Контекст.Результат.Текст = Результат;
КонецФункции
Функция ВсеОбработчикиСобытийФормаЛкс(Знач Форма, Знач Кэшировать = Ложь) Экспорт
СлужебныеДанные = СлужебныеДанныеФормыЛкс(Форма);
Результат = Неопределено;
Если Ложь
Или Не Кэшировать
Или СлужебныеДанные <> Неопределено И Не СлужебныеДанные.Свойство("ВсеОбработчикиСобытий", Результат)
Тогда
Если Истина
И ТипЗнч(Форма) = Тип("Структура")
И Не Форма.Свойство("Элементы")
Тогда
Возврат Результат;
КонецЕсли;
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(Форма) = Тип("Форма")
#КонецЕсли
Тогда
Элементы = Форма.ЭлементыФормы;
Иначе
Элементы = Форма.Элементы;
КонецЕсли;
Элементы = МассивИзКоллекцииЛкс(Элементы);
Элементы.Вставить(0, Форма);
Результат = Новый ТаблицаЗначений;
Результат.Колонки.Добавить("Имя");
Результат.Колонки.Добавить("Событие");
Результат.Колонки.Добавить("Обработчик");
Результат.Колонки.Добавить("НОбработчик");
Результат.Колонки.Добавить("СтрокаОписания");
Для Каждого ГлавныйЭлемент Из Элементы Цикл
Если ТипЗнч(ГлавныйЭлемент) = Тип("ГруппаФормы") Тогда
Продолжить;
КонецЕсли;
ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(ГлавныйЭлемент,, Результат, СлужебныеДанные);
#Если Клиент Тогда
Если ТипЗнч(ГлавныйЭлемент) = Тип("ТабличноеПоле") Тогда
Для Каждого Колонка Из ГлавныйЭлемент.Колонки Цикл
Если Колонка <> Неопределено Тогда
ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(Колонка.ЭлементУправления, ГлавныйЭлемент.Имя + ".Колонки." + Колонка.Имя + ".ЭлементУправления", Результат);
КонецЕсли;
КонецЦикла;
КонецЕсли;
#КонецЕсли
КонецЦикла;
Результат.Индексы.Добавить("НОбработчик");
Если СлужебныеДанные <> Неопределено Тогда
СлужебныеДанные.Вставить("ВсеОбработчикиСобытий", Результат);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// Элемент - Структура, ЭлементФормы -
// ОбработчикиСобытий - ТаблицаЗначений -
Процедура ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(Знач Элемент, Знач ПолноеИмя = "", Знач ТаблицаОбработчиков, Знач СлужебныеДанные = Неопределено)
События = СобытияЭлементаФормыЛкс(Элемент);
Если События.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ЭтоФорма = ЛиФормаИлиИмитаторЛкс(Элемент);
Если Истина
И СлужебныеДанные <> Неопределено
И СлужебныеДанные.Тип = ирОбщий.ТипУправляемаяФормаЛкс()
Тогда
Если Не ЭтоФорма Тогда
Если ТипЗнч(Элемент) = Тип("КлючИЗначение") Тогда
ИмяЭлемента = Элемент.Ключ;
Иначе
ИмяЭлемента = Элемент.Имя;
КонецЕсли;
КонецЕсли;
Если СлужебныеДанные.Свойство("ИменаОбработчиков") Тогда
Если ЭтоФорма Тогда
ИменаОбработчиков = СлужебныеДанные.ИменаОбработчиков;
Иначе
ЭлементыФормы = СлужебныеДанные.Элементы;
Попытка
ИменаОбработчиков = ЭлементыФормы[ИмяЭлемента].ИменаОбработчиков;
Исключение
ИменаОбработчиков = Новый Массив;
КонецПопытки;
КонецЕсли;
КонецЕсли;
ИначеЕсли Не ЭтоФорма Тогда
Если ЗначениеЗаполнено(ПолноеИмя) Тогда
ИмяЭлемента = ПолноеИмя;
Иначе
ИмяЭлемента = Элемент.Имя;
КонецЕсли;
КонецЕсли;
Для Каждого СтрокаСобытия Из События Цикл
ИмяСобытия = СтрокаСобытия.Слово;
ОбработчикСобытия = "";
// Управляемая форма
Если ИменаОбработчиков <> Неопределено Тогда
Для Каждого ИмяОбработчика Из ИменаОбработчиков Цикл
Если СтрКончаетсяНаЛкс(ИмяОбработчика, ИмяСобытия) Тогда
ОбработчикСобытия = ИмяОбработчика;
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
Попытка
ОбработчикСобытия = Элемент.ПолучитьДействие(ИмяСобытия);
Исключение
КонецПопытки;
КонецЕсли;
Если ОбработчикСобытия <> "" И ОбработчикСобытия <> Неопределено Тогда
СтрокаОбработчика = ТаблицаОбработчиков.Добавить();
Если Не ЭтоФорма Тогда
СтрокаОбработчика.Имя = ИмяЭлемента;
КонецЕсли;
СтрокаОбработчика.Событие = ИмяСобытия;
СтрокаОбработчика.СтрокаОписания = СтрокаСобытия;
СтрокаОбработчика.Обработчик = "" + ОбработчикСобытия;
ирОбщий.ОбновитьКопиюСвойстваВНижнемРегистреЛкс(СтрокаОбработчика, "Обработчик");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция УправляемаяФормаБСП_ИсполняемыеСхемаИНастройкиТаблицыЛкс(ПараметрКоманды, Контекст) Экспорт
Форма = Контекст.Форма;
Если Не ЗначениеЗаполнено(ПараметрКоманды) Тогда
ИмяТаблицыФормы = Контекст.Форма.ТекущийЭлемент.Имя;
Иначе
ИмяТаблицыФормы = ПараметрКоманды;
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Схема", Форма.Элементы[ИмяТаблицыФормы].ПолучитьИсполняемуюСхемуКомпоновкиДанных());
Результат.Вставить("Настройки", Форма.Элементы[ИмяТаблицыФормы].ПолучитьИсполняемыеНастройкиКомпоновкиДанных());
Если ЭтоУпрДинамическийСписокИРЛкс(Форма) Тогда
//Результат = Форма.ИсполняемыеСхемаИНастройкиНаСервере();
Схема = Результат.Схема;
#Если Сервер И Не Сервер Тогда
Схема = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Схема.НаборыДанных[0].Запрос = СтрЗаменить(Схема.НаборыДанных[0].Запрос, ОкончаниеВыраженияПодстрокиДинСпискаЛкс() + " КАК", ОкончаниеВыраженияПодстрокиДинСпискаЛкс(1000000000) + " КАК");
КонецЕсли;
Контекст.Результат.Текст = Результат;
КонецФункции
// Функция - События элемента формы лкс
// Параметры:
// ЭлементФормы - КлючИЗначение, Структура, ЭлементФормы, Строка - :
// *Тип
// *ИмяТипаРасширения
// ИмяОбщегоТипа - -
// Возвращаемое значение:
// -
Функция СобытияЭлементаФормыЛкс(Знач ЭлементФормы = Неопределено, Знач ИмяОбщегоТипа = "") Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ТипЭлемента = ТипЗнч(ЭлементФормы);
Если ТипЭлемента = Тип("КлючИЗначение") Тогда
ЭлементФормы = ЭлементФормы.Значение;
ТипЭлемента = ТипЗнч(ЭлементФормы);
КонецЕсли;
Если ТипЭлемента = Тип("Структура") Тогда
ТипЭлемента = ЭлементФормы.Тип;
Если ЭлементФормы.Свойство("ИмяТипаРасширения") Тогда
ИмяТипаРасширения = ЭлементФормы.ИмяТипаРасширения;
ИначеЕсли ТипЗнч(ТипЭлемента) = Тип("Строка") Тогда
ОписаниеРасширенногоТипа = мПлатформа.ОписаниеРасширенногоТипа(ТипЭлемента);
Если ОписаниеРасширенногоТипа <> Неопределено Тогда
ИмяТипаРасширения = ТипЭлемента;
ИмяОбщегоТипа = ОписаниеРасширенногоТипа.ОсновнойТип;
КонецЕсли;
КонецЕсли;
ИначеЕсли ТипЭлемента = Тип("Строка") Тогда
ИмяТипаРасширения = ЭлементФормы;
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяОбщегоТипа) Тогда
СтруктураТипа = мПлатформа.СтруктураТипаИзКонкретногоТипа(ТипЭлемента);
ИмяОбщегоТипа = СтруктураТипа.ИмяОбщегоТипа;
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяТипаРасширения) И ЭлементФормы <> Неопределено Тогда
ИмяТипаРасширения = мПлатформа.ИмяТипаРасширенияЭлементаФормы(ИмяОбщегоТипа, ЭлементФормы);
КонецЕсли;
СобытияЭлементаФормы = ирКэш.СобытияПоИмениОбщегоТипаЛкс(ИмяОбщегоТипа, ИмяТипаРасширения);
Возврат СобытияЭлементаФормы;
КонецФункции
Функция ПраваСОграничениямиДоступаКДаннымЛкс() Экспорт
ДоступныеПрава = Новый СписокЗначений;
ДоступныеПрава.Добавить("Чтение", "Read");
ДоступныеПрава.Добавить("Добавление", "Insert");
ДоступныеПрава.Добавить("Изменение", "Update");
ДоступныеПрава.Добавить("Удаление", "Delete");
Возврат ДоступныеПрава;
КонецФункции
// Процедура - Обновить заголовок формы с открытым файлом лкс
//
// Параметры:
// ЭтаФорма - Форма -
// ИмяОткрытогоФайла - -
//
Процедура ОбновитьЗаголовокФормыСОткрытымФайломЛкс(Знач ЭтаФорма, Знач ИмяОткрытогоФайла = Неопределено) Экспорт
Если ЗначениеЗаполнено(ИмяОткрытогоФайла) Тогда
НоваяСтрока = ИмяОткрытогоФайла;
Иначе
Если Найти(ЭтаФорма.Заголовок, ": <") > 0 Тогда
Возврат;
КонецЕсли;
НоваяСтрока = СтрШаблонЛкс("<%1>", ТекущееВремяЛкс());
КонецЕсли;
ОбновитьТекстПослеМаркераЛкс(ЭтаФорма.Заголовок, , НоваяСтрока, ": ");
КонецПроцедуры
Функция ТекущееВремяЛкс() Экспорт
Возврат Формат(ТекущаяДата(), "ДЛФ=T");
КонецФункции
Функция ОбновитьЗаголовкиСтраницПанелиЛкс(ЭтаФорма, ЭлементыФормы, Панель) Экспорт
ТабличноеПолеСтраниц = ЭлементыФормы.Найти("Страницы" + Панель.Имя); // ТабличноеПоле
Если ТабличноеПолеСтраниц <> Неопределено Тогда
ТаблицаСтраниц = ДанныеЭлементаФормыЛкс(ТабличноеПолеСтраниц); // ТаблицаЗначений
//! ТаблицаСтраниц.Колонки.Добавить("ИмяСтраницы");
//! ТаблицаСтраниц.Колонки.Добавить("Непустая");
//! ТаблицаСтраниц.Колонки.Добавить("Количество");
КонецЕсли;
ОбщееКоличество = 0;
НеготовыеСтраницы = СлужебныеДанныеФормыЛкс(ЭтаФорма).НеготовыеСтраницы;
#Если Сервер И Не Сервер Тогда
НеготовыеСтраницы = Новый СписокЗначений;
#КонецЕсли
Если ТипЗнч(Панель) = Тип("ГруппаФормы") Тогда
Страницы = Панель.ПодчиненныеЭлементы;
Иначе
//! Панель = 0 // Панель
Страницы = Панель.Страницы;
КонецЕсли;
Для Каждого Страница Из Страницы Цикл
ИмяСтраницы = Страница.Имя;
Если ИмяСтраницы = "" Тогда // Служебная страница. Появляется после очистки страниц.
Продолжить;
КонецЕсли;
Если Найти("." + ИмяСтраницы, ".Страница") = 1 Тогда
ИмяСтраницы = СтрЗаменить("." + ИмяСтраницы, ".Страница", "");
КонецЕсли;
ЗначениеСтраницы = Неопределено;
ЭУ = Null;
#Если Клиент Тогда
Если ТипЗнч(Страница) = Тип("СтраницаПанели") Тогда
ЗначениеСтраницы = Страница.Значение;
Если ТипЗнч(ЗначениеСтраницы) <> Тип("Структура") Тогда
ЗначениеСтраницы = Новый Структура;
Страница.Значение = ЗначениеСтраницы;
КонецЕсли;
Если Не ЗначениеСтраницы.Свойство("ТабличноеПоле") Тогда
// Битая ссылка на табличное поле может возникать https://www.hostedredmine.com/issues/928852
ЗначениеСтраницы.Вставить("ТабличноеПоле", ЭлементыФормы.Найти(ИмяСтраницы));
КонецЕсли;
ЭУ = ЗначениеСтраницы.ТабличноеПоле;
КонецЕсли;
#КонецЕсли
Если ЭУ = Null Тогда
ЭУ = ЭлементыФормы.Найти(ИмяСтраницы);
КонецЕсли;
Если ЭУ = Неопределено Тогда
Продолжить;
КонецЕсли;
СтрокаСтраницы = Неопределено;
Если ТаблицаСтраниц <> Неопределено Тогда
НайденныеСтроки = ТаблицаСтраниц.НайтиСтроки(Новый Структура("ИмяСтраницы", ИмяСтраницы));
Если НайденныеСтроки.Количество() > 0 Тогда
СтрокаСтраницы = НайденныеСтроки[0];
КонецЕсли;
КонецЕсли;
Если Ложь
Или НеготовыеСтраницы.НайтиПоЗначению(Страница.Имя) <> Неопределено
Или (Истина
И ТипЗнч(ЗначениеСтраницы) = Тип("Структура")
И ЗначениеСтраницы.Свойство("Рассчитано")
И Не ЗначениеСтраницы.Рассчитано)
Тогда
Количество = "-";
Иначе
Суффикс = "";
Количество = Неопределено;
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(ЭУ) = Тип("ТабличноеПоле")
#КонецЕсли
Или ТипЗнч(ЭУ) = Тип("ТаблицаФормы")
Тогда
Если Истина
И ТабличноеПолеСтраниц <> Неопределено
И ТипЗнч(ЗначениеСтраницы) = Тип("Структура")
И ЗначениеСтраницы.Свойство("ТаблицаЗначений")
Тогда
ЗначениеЭУ = ЗначениеСтраницы.ТаблицаЗначений; // Редактор объекта БД
Иначе
ЗначениеЭУ = ДанныеЭлементаФормыЛкс(ЭУ,, ЭтаФорма);
КонецЕсли;
Если ТипЗнч(ЗначениеЭУ) = Тип("ДеревоЗначений") Тогда
Количество = ЗначениеЭУ.Строки.Количество();
Суффикс = "*";
ИначеЕсли ТипЗнч(ЗначениеЭУ) = Тип("ДанныеФормыДерево") Тогда
Количество = ЗначениеЭУ.ПолучитьЭлементы().Количество();
Суффикс = "*";
Иначе
Попытка
Количество = ЗначениеЭУ.Количество();
Исключение КонецПопытки;
Если Количество = Неопределено Тогда
// Компоновка
Попытка
Количество = ЗначениеЭУ.Элементы.Количество();
//Суффикс = "*";
Исключение КонецПопытки;
КонецЕсли;
КонецЕсли;
//Если Количество = 0 Тогда
// Попытка
// КоличествоКолонок = ЗначениеЭУ.Колонки.Количество();
// Исключение
// КоличествоКолонок = 1;
// КонецПопытки;
// Если КоличествоКолонок = 0 Тогда
// Количество = "-";
// КонецЕсли;
//КонецЕсли;
#Если Клиент Тогда
ИначеЕсли Ложь
Или ТипЗнч(ЭУ) = Тип("ПолеТабличногоДокумента")
Тогда
//Количество = ?(ЭУ.ВысотаТаблицы > 0, 1, 0);
Количество = ЭУ.ВысотаТаблицы;
ИначеЕсли Ложь
Или ТипЗнч(ЭУ) = Тип("ПолеТекстовогоДокумента")
Тогда
//Количество = ?(ЭУ.КоличествоСтрок() > 0, 1, 0);
Количество = ЭУ.КоличествоСтрок();
ИначеЕсли Ложь
Или ТипЗнч(ЭУ) = Тип("ПолеВвода")
Тогда
//Количество = ?(СтрДлина(ЭУ.Значение) > 0, 1, 0);
Количество = СтрДлина(ЭУ.Значение);
ИначеЕсли Ложь
Или ТипЗнч(ЭУ) = Тип("ПолеГрафическойСхемы")
Тогда
Количество = ЭУ.ЭлементыГрафическойСхемы.Количество();
#КонецЕсли
ИначеЕсли Ложь
#Если Клиент Тогда
Или ТипЗнч(ЭУ) = Тип("Панель")
#КонецЕсли
Или (Истина
И ТипЗнч(ЭУ) = Тип("ГруппаФормы")
И ЭУ.Вид = ВидГруппыФормы.Страницы)
Тогда
//Количество = ЭУ.Страницы.Количество();
//Если Количество = 1 Тогда
// Если ЭУ.Страницы[0].Имя = "" Тогда
// Количество = 0;
// КонецЕсли;
//КонецЕсли;
Количество = ОбновитьЗаголовкиСтраницПанелиЛкс(ЭтаФорма, ЭлементыФормы, ЭУ);
КонецЕсли;
Если ТипЗнч(Количество) = Тип("Число") Тогда
ОбщееКоличество = ОбщееКоличество + Количество;
КонецЕсли;
КонецЕсли;
Если СтрокаСтраницы <> Неопределено Тогда
СтрокаСтраницы.Количество = Количество;
СтрокаСтраницы.Непустая = СтрокаСтраницы.Количество > 0;
КонецЕсли;
ОбновитьТекстПослеМаркераЛкс(Страница.Заголовок, , "" + Количество + Суффикс + ")", "(");
КонецЦикла;
Возврат ОбщееКоличество;
КонецФункции
// Надежно проверяет существование у объекта метода с заданным именем
Функция МетодРеализованЛкс(Знач Объект, Знач ИмяМетода) Экспорт
Если Объект = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Выражение = "Объект." + ИмяМетода + "(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)";
Попытка
Выполнить(Выражение);
Исключение
Инфо = ИнформацияОбОшибке();
Описание = Инфо.Описание;
КонецПопытки;
Результат = ЛиОшибкаСлишкомМногоПараметровЛкс(Инфо);
Возврат Результат;
КонецФункции
// Проверка, что описание ошибки содержит имя метода в круглых скобках
Функция ЛиОшибкаСлишкомМногоПараметровЛкс(Знач Инфо) Экспорт
#Если Сервер И Не Сервер Тогда
Инфо = ИнформацияОбОшибке();
#КонецЕсли
Пока Инфо.Причина <> Неопределено Цикл
Инфо = Инфо.Причина;
КонецЦикла;
Описание = Инфо.Описание;
Результат = Ложь
// Поддержка языка системы RU, EN, UK.
// Тест: Справочники.ТипВсеСсылки(1)
Или Найти(Описание, "Слишком много фактических параметров") > 0
Или Найти(Описание, "Too many actual parameters") > 0
Или Найти(Описание, "Занадто багато фактичних параметрів") > 0; // Украинский
Возврат Результат;
КонецФункции
// Параметры:
// КоличествоПроходов - Число(Н8,0)
// КлючЗамера - Строка
// ВыдатьСообщение - Булево
//
Функция НачатьЗамерЛкс(Знач КоличествоПроходов = 1, Знач КлючЗамера = "", Знач ВыдатьСообщение = Ложь) Экспорт
ирПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
ирПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ТаблицаЗамеров = ирПлатформа.мТаблицаЗамеров;
Если Не ЗначениеЗаполнено(КлючЗамера) Тогда
КлючЗамера = "Замер" + ТаблицаЗамеров.Колонки[0].Имя;
КонецЕсли;
ТаблицаЗамеров.Колонки[0].Имя = "_" + XMLСтрока(Число(Сред(ТаблицаЗамеров.Колонки[0].Имя, 2)) + 1);
СтрокаЗамера = ТаблицаЗамеров.Добавить();
СтрокаЗамера.Ключ = КлючЗамера;
СтрокаЗамера.ОтладкаРазрешена = ирКэш.ЛиОтладкаРазрешенаЛкс();
СтрокаЗамера.КоличествоПроходов = КоличествоПроходов;
Если Ложь
Или ВыдатьСообщение
//Или СтрокаЗамера.ОтладкаРазрешена
Тогда
Сообщение = СтрШаблонИменЛкс("Начало замера %1, количество проходов = %2",, СтрокаЗамера.Ключ, 2, КоличествоПроходов);
Если СтрокаЗамера.ОтладкаРазрешена Тогда
Сообщение = Сообщение + СообщениеОВлиянииРазрешенияОтладкиЛкс();
КонецЕсли;
СообщитьЛкс(Сообщение);
КонецЕсли;
СтрокаЗамера.ДатаНачала = ТекущееВремяВМиллисекундахЛкс();
Результат = КоличествоПроходов;
Возврат Результат;
КонецФункции
Функция СообщениеОВлиянииРазрешенияОтладкиЛкс()
Возврат ". Возможно включено разрешение отладки. Оно замедляет выполнение легкого многострочного кода!";
КонецФункции
// Параметры:
// КлючЗамера - Строка - По умолчанию последний замер
//
Функция КончитьЗамерЛкс(Знач КлючЗамера = "", Знач ПорогДлительностиДляЗаписиВЖурнал = 0) Экспорт
ТекущееВремя = ТекущееВремяВМиллисекундахЛкс();
ирПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
ирПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ТаблицаЗамеров = ирПлатформа.мТаблицаЗамеров;
Если Не ЗначениеЗаполнено(КлючЗамера) Тогда
Если ТаблицаЗамеров.Количество() > 0 Тогда
СтрокаЗамера = ТаблицаЗамеров[ТаблицаЗамеров.Количество() - 1];
КонецЕсли;
Иначе
СтрокаЗамера = ТаблицаЗамеров.Найти(КлючЗамера, "Ключ");
КонецЕсли;
Если СтрокаЗамера = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Длительность = ТекущееВремя - СтрокаЗамера.ДатаНачала;
Длительность = Длительность / 1000;
Сообщение = СтрШаблонИменЛкс("Окончание замера %1 - Длительность = %2с",, СтрокаЗамера.Ключ, 2, Длительность);
Если СтрокаЗамера.КоличествоПроходов > 1 Тогда
Среднее = Длительность / СтрокаЗамера.КоличествоПроходов;
Сообщение = Сообщение + СтрШаблонИменЛкс(", Среднее = %1с",, Среднее);
КонецЕсли;
Если Ложь
Или СтрокаЗамера.ОтладкаРазрешена
#Если Клиент Тогда
Или ирПлатформа.ИдентификаторыПроцессовОтладчиков().Количество() > 0
#КонецЕсли
Тогда
Сообщение = Сообщение + СообщениеОВлиянииРазрешенияОтладкиЛкс();
КонецЕсли;
СообщитьЛкс(Сообщение);
ТаблицаЗамеров.Удалить(СтрокаЗамера);
Если ЗначениеЗаполнено(ПорогДлительностиДляЗаписиВЖурнал) И Длительность > ПорогДлительностиДляЗаписиВЖурнал Тогда
ЗаписьЖурналаРегистрации("ДолгаяОперация",,,, Сообщение);
КонецЕсли;
Возврат Длительность;
КонецФункции
Функция ЗамерСтрокНачатьЛкс() Экспорт
ТаблицаСтрок = Новый ТаблицаЗначений;
ТаблицаСтрок.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"),, 5);
ТаблицаСтрок.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"),, 6);
ТаблицаСтрок.Колонки.Добавить("Длительность", Новый ОписаниеТипов("Число"),, 6);
ТаблицаСтрок.Колонки.Добавить("Максимум", Новый ОписаниеТипов("Число"),, 6);
ТаблицаСтрок.Индексы.Добавить("НомерСтроки");
ПерваяСтрока = ТаблицаСтрок.Добавить();
ПерваяСтрока.НомерСтроки = 1;
Результат = Новый Структура;
Результат.Вставить("Таблица", ТаблицаСтрок);
Результат.Вставить("ТекущееВремя", ТекущееВремяВМиллисекундахЛкс());
Возврат Результат;
КонецФункции
Функция ЗамерСтрокиЛкс(ЗамерСтрок, НомерСтроки) Экспорт
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
СтрокаСтроки = ЗамерСтрок.Таблица.Найти(НомерСтроки, "НомерСтроки");
Если СтрокаСтроки = Неопределено Тогда
СтрокаСтроки = ЗамерСтрок.Таблица.Добавить();
СтрокаСтроки.НомерСтроки = НомерСтроки;
КонецЕсли;
СтрокаСтроки.Количество = СтрокаСтроки.Количество + 1;
Если СтрокаСтроки.Количество > 1000 Тогда
// так быстрее
СтрокаСтроки.Длительность = СтрокаСтроки.Длительность + Цел((СтрокаСтроки.Длительность - СтрокаСтроки.Максимум) / (СтрокаСтроки.Количество - 1));
ЗамерСтрок.ТекущееВремя = ЗамерСтрок.ТекущееВремя + СтрокаСтроки.Длительность;
Иначе
ТекущееВремя = ТекущееВремяВМиллисекундахЛкс();
Длительность = Макс(0, ТекущееВремя - ЗамерСтрок.ТекущееВремя); // Аппроксимация могла обогнать реальное время
Если СтрокаСтроки.Максимум < Длительность Тогда
СтрокаСтроки.Максимум = Длительность;
КонецЕсли;
СтрокаСтроки.Длительность = СтрокаСтроки.Длительность + Длительность;
ЗамерСтрок.ТекущееВремя = ТекущееВремя;
КонецЕсли;
КонецФункции
// Копирует таблицу значений из исходной таблицы значений с безусловным удалением типа Null из описаний типов колонок.
// Если есть значения NULL, то они теряются. Если нужно их сохранять, то используй СузитьТипыКолонокТаблицыБезПотериДанныхЛкс().
// Эта функция нацелена на быстрое выполнение.
//
// Параметры:
// Таблица - ТаблицаЗначений -
// ЗагружатьДанныеВНовуюТаблицу - Булево - после создания новой таблицы загрузить в нее данные из исходной
// ОбрабатыватьТолькоКолонки - Строка - имена колонок разделенные запятыми
// НеОбрабатыватьКолонки - Строка - имена колонок разделенные запятыми
// НеУдалятьЗначенияNULL - Булево - тип NULL будет удаляться только если в колонке нет значений NULL, долго
//
// Возвращаемое значение:
// ТаблицаЗначений - новая таблица
//
Функция ТаблицаСКолонкамиБезТипаNullЛкс(Знач Таблица, Знач ЗагружатьДанныеВНовуюТаблицу = Истина, Знач ОбрабатыватьТолькоКолонки = "", Знач НеОбрабатыватьКолонки = "") Экспорт
Результат = Новый ТаблицаЗначений;
НовыеКолонки = Результат.Колонки;
ИсходныеКолонки = Таблица.Колонки;
ИменаОбрабатываемыхКолонок = Новый Массив();
Если ОбрабатыватьТолькоКолонки <> "" Тогда
ИменаОбрабатываемыхКолонок = СтрРазделитьЛкс(ОбрабатыватьТолькоКолонки, ",", Истина);
КонецЕсли;
ИменаНеобрабатываемыхКолонок = Новый Массив();
Если НеОбрабатыватьКолонки <> "" Тогда
ИменаНеобрабатываемыхКолонок = СтрРазделитьЛкс(НеОбрабатыватьКолонки, ",", Истина);
КонецЕсли;
Если ирКэш.РежимОтладкиЛкс() Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Колонка Из ИсходныеКолонки Цикл
ОписаниеТипов = Колонка.ТипЗначения;
Если Ложь
Или (Истина
И ОбрабатыватьТолькоКолонки <> ""
И ИменаОбрабатываемыхКолонок.Найти(Колонка.Имя) = Неопределено)
Или (Истина
И НеОбрабатыватьКолонки <> ""
И ИменаНеобрабатываемыхКолонок.Найти(Колонка.Имя) <> Неопределено)
Тогда
//
Иначе
// Антибаг платформы 8.3 - потеря квалификаторов определяемого типа https://www.hostedredmine.com/issues/924721
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, , "NULL", ОписаниеТипов.КвалификаторыЧисла, ОписаниеТипов.КвалификаторыСтроки, ОписаниеТипов.КвалификаторыДаты);
КонецЕсли;
НовыеКолонки.Добавить(Колонка.Имя, ОписаниеТипов, Колонка.Заголовок, Колонка.Ширина);
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого Колонка Из ИсходныеКолонки Цикл ОписаниеТипов = Колонка.ТипЗначения; Если Ложь Или (Истина И ОбрабатыватьТолькоКолонки <> "" И ИменаОбрабатываемыхКолонок.Найти(Колонка.Имя) = Неопределено) Или (Истина И НеОбрабатыватьКолонки <> "" И ИменаНеобрабатываемыхКолонок.Найти(Колонка.Имя) <> Неопределено) Тогда Иначе ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов, , "NULL", ОписаниеТипов.КвалификаторыЧисла, ОписаниеТипов.КвалификаторыСтроки, ОписаниеТипов.КвалификаторыДаты); КонецЕсли; НовыеКолонки.Добавить(Колонка.Имя, ОписаниеТипов, Колонка.Заголовок, Колонка.Ширина); КонецЦикла;
КонецЕсли;
Если ЗагружатьДанныеВНовуюТаблицу Тогда
ЗагрузитьВТаблицуЗначенийЛкс(Таблица, Результат);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьОпределениеТаблицыБДДляИЗЛкс(ИмяТаблицы) Экспорт
Результат = ИмяТаблицы;
ТипТаблицы = ТипТаблицыБДЛкс(ИмяТаблицы);
Если ТипТаблицы = "ДвиженияССубконто" Тогда
Результат = Результат + "(,, {Регистратор.*, НомерСтроки, Активность})";
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьМакетныйОбъектДанныхТаблицыБДЛкс(Знач ПолноеИмяТаблицы, выхТекущаяГруппаТипаМетаданных = Неопределено, выхКлючевыеПоля = Неопределено,
Знач ОбъектыНаСервере = Неопределено) Экспорт
выхКлючевыеПоля = Новый Массив;
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
Если ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД) Тогда
выхМакетныйОбъект = ОбъектБДПоКлючуЛкс(ПолноеИмяТаблицы,,,, ОбъектыНаСервере,,,, Ложь);
выхТекущаяГруппаТипаМетаданных = "Ссылочный";
выхКлючевыеПоля.Добавить("С|сылка");
ИначеЕсли ЛиМетаданныеРегистраЛкс(ОбъектМД) Тогда
выхМакетныйОбъект = СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ПолноеИмяТаблицы, ОбъектыНаСервере);
выхТекущаяГруппаТипаМетаданных = "Регистр";
Для Каждого ЭлементОтбора Из выхМакетныйОбъект.Методы.Отбор Цикл
выхКлючевыеПоля.Добавить(ЭлементОтбора.ПутьКДанным);
КонецЦикла;
ИначеЕсли ЛиКорневойТипКонстантыЛкс(ТипТаблицы) Тогда
выхМакетныйОбъект = ОбъектБДПоКлючуЛкс(ПолноеИмяТаблицы,,,, ОбъектыНаСервере,,,, Ложь);
выхТекущаяГруппаТипаМетаданных = "Константа";
Иначе
Если ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда
выхТекущаяГруппаТипаМетаданных = "ВложеннаяТаблица";
КонецЕсли;
//ВызватьИсключение "Макетный объект данных для таблицы типа " + ТипТаблицы + " не допустим";
КонецЕсли;
Возврат выхМакетныйОбъект;
КонецФункции
Функция ОписаниеТиповОбъектаИлиСтрокиБДПоИменамТаблицЛкс(Знач МассивИлиИмяТаблицыБД, Знач НуженТипОбъекта, РежимОбходаДанных = "Строки", Знач ТипТаблицы = Неопределено, выхПолноеИмяТаблицы = Неопределено) Экспорт
МассивИменТаблицБД = Новый Массив();
Если ТипЗнч(МассивИлиИмяТаблицыБД) = Тип("Строка") Тогда
ТипТаблицы = ТипТаблицыБДЛкс(МассивИлиИмяТаблицыБД);
МассивИменТаблицБД.Добавить(МассивИлиИмяТаблицыБД);
Иначе
МассивИменТаблицБД = МассивИлиИмяТаблицыБД;
КонецЕсли;
МассивТипов = Новый Массив();
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(МассивИменТаблицБД[0]);
Если ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД) Тогда
Для Каждого ИмяТаблицыБД Из МассивИменТаблицБД Цикл
Если РежимОбходаДанных = "КлючиОбъектов" Или ЛиКорневойТипПеречисленияЛкс(ПервыйФрагментЛкс(ИмяТаблицыБД)) Тогда
РасширениеТипа = "Ссылка";
Иначе
РасширениеТипа = "Объект";
КонецЕсли;
ИмяТипа = ИмяТипаИзПолногоИмениТаблицыБДЛкс(ИмяТаблицыБД, РасширениеТипа);
МассивТипов.Добавить(Тип(ИмяТипа));
КонецЦикла;
ИначеЕсли Ложь
Или ЛиКорневойТипЖурналаДокументовЛкс(ТипТаблицы)
Тогда
Если РежимОбходаДанных = "КлючиОбъектов" Тогда
РасширениеТипа = "Ссылка";
Иначе
РасширениеТипа = "Объект";
КонецЕсли;
Поля = ПоляТаблицыБДЛкс(МассивИменТаблицБД[0]);
Поле = Поля.Найти("Ссылка", "Имя");
Для Каждого ТипЗначения Из Поле.ТипЗначения.Типы() Цикл
ИмяТипа = ИмяТипаИзПолногоИмениМДЛкс(Метаданные.НайтиПоТипу(ТипЗначения), РасширениеТипа);
МассивТипов.Добавить(Тип(ИмяТипа));
КонецЦикла;
ИначеЕсли ЛиТипТаблицыМетассылкиЛкс(ТипТаблицы) Тогда
Для Каждого ИмяТаблицыБД Из МассивИменТаблицБД Цикл
ИмяТипа = ИмяТипаИзПолногоИмениТаблицыБДЛкс(ИмяТаблицыБД);
МассивТипов.Добавить(Тип(ИмяТипа));
КонецЦикла;
ИначеЕсли ЛиКорневойТипКонстантыЛкс(ТипТаблицы) Тогда
РасширениеТипа = "МенеджерЗначения";
Для Каждого ИмяТаблицыБД Из МассивИменТаблицБД Цикл
ИмяТипа = ИмяТипаИзПолногоИмениМДЛкс(ИмяТаблицыБД, РасширениеТипа);
МассивТипов.Добавить(Тип(ИмяТипа));
КонецЦикла;
ИначеЕсли ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда
СловоСтрока = ПеревестиСтроку("Строка");
СловоТипТаблицы = ПеревестиСтроку(ТипТаблицы);
Для Каждого ИмяТаблицыБД Из МассивИменТаблицБД Цикл
МассивФрагментов = СтрРазделитьЛкс(ИмяТаблицыБД);
выхПолноеИмяТаблицы = МассивФрагментов[0] + "." + МассивФрагментов[1];
Если Не НуженТипОбъекта И РежимОбходаДанных = "Строки" Тогда
Если Ложь
Или ТипТаблицы = "ТабличнаяЧасть"
Или ТипТаблицы = "ВидыСубконто"
Тогда
ИмяТипа = МассивФрагментов[0] + СловоТипТаблицы + СловоСтрока + "." + МассивФрагментов[1];
Иначе // Виды расчета
ИмяТипа = СловоТипТаблицы + СловоСтрока + "." + МассивФрагментов[1];
КонецЕсли;
Если ТипТаблицы = "ТабличнаяЧасть" Тогда
ИмяТипа = ИмяТипа + "." + МассивФрагментов[2];
выхПолноеИмяТаблицы = выхПолноеИмяТаблицы + "." + МассивФрагментов[2];
Иначе
выхПолноеИмяТаблицы = выхПолноеИмяТаблицы + "." + СловоТипТаблицы;
КонецЕсли;
МассивТипов.Добавить(Тип(ИмяТипа));
ИначеЕсли РежимОбходаДанных = "КлючиОбъектов" Тогда
МассивТипов.Добавить(Тип(ИмяТипаИзПолногоИмениМДЛкс(ИмяТаблицыБД, "Ссылка", МассивФрагментов)));
Иначе
Если МассивФрагментов.Количество() = 3 Тогда
МассивФрагментов.Удалить(МассивФрагментов.ВГраница());
КонецЕсли;
МассивТипов.Добавить(Тип(ИмяТипаИзПолногоИмениМДЛкс(ИмяТаблицыБД, "Объект", МассивФрагментов)));
КонецЕсли;
КонецЦикла;
ИначеЕсли ЛиМетаданныеРегистраЛкс(ОбъектМД) Тогда
Если Не НуженТипОбъекта И РежимОбходаДанных = "Строки" Тогда
РасширениеТипа = "Запись";
Иначе
РасширениеТипа = "НаборЗаписей";
КонецЕсли;
Для Каждого ИмяТаблицыБД Из МассивИменТаблицБД Цикл
ТипЭлементаДанных = Тип(ИмяТипаДанныхТаблицыРегистраЛкс(ИмяТаблицыБД, РасширениеТипа));
МассивТипов.Добавить(ТипЭлементаДанных);
КонецЦикла;
Иначе
ВызватьИсключение "Неподдерживаемый тип таблицы """ + ТипТаблицы + """";
КонецЕсли;
Результат = Новый ОписаниеТипов(МассивТипов);
Возврат Результат;
КонецФункции
Функция ЛиПолноеИмяРегистраБухгалтерииЛкс(ПолноеИмяМД, Знач ФрагментыИмени = Неопределено) Экспорт
Если ФрагментыИмени = Неопределено Тогда
ФрагментыИмени = СтрРазделитьЛкс(ПолноеИмяМД);
КонецЕсли;
Результат = Истина
И ФрагментыИмени.Количество() = 2
И (Ложь
Или ФрагментыИмени[0] = "AccountingRegister"
Или ФрагментыИмени[0] = "РегистрБухгалтерии");
Возврат Результат;
КонецФункции
// Создает тип из метаданных.
//
// Параметры:
// Метаданные - ОбъектМетаданных;
// *Расширение - Строка, "Ссылка" - расширение типа.
//
// Возвращаемое значение:
// Тип.
//
Функция ПолучитьТипИзМетаданныхЛкс(ОбъектМД, Расширение = "Ссылка") Экспорт
Возврат Тип(ИмяТипаИзПолногоИмениМДЛкс(ОбъектМД, Расширение));
КонецФункции // ПолучитьТипИзМетаданных()
Функция ЛиОбщийРеквизитИспользуетсяВОбъектеМетаданныхЛкс(ОбщийРеквизит, ОбъектМетаданных) Экспорт
Если ОбщийРеквизит.ИспользованиеРазделенияДанных <> Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Состав = ирКэш.СоставОбщегоРеквизитаЛкс(ОбщийРеквизит.Имя);
ЭлементСостава = Состав[ОбъектМетаданных.ПолноеИмя()];
Результат = Истина
И ЭлементСостава <> Неопределено
И (Ложь
Или ЭлементСостава.Использование = Метаданные.СвойстваОбъектов.ИспользованиеОбщегоРеквизита.Использовать
Или (Истина
И ЭлементСостава.Использование = Метаданные.СвойстваОбъектов.ИспользованиеОбщегоРеквизита.Авто
И ОбщийРеквизит.АвтоИспользование = Метаданные.СвойстваОбъектов.АвтоИспользованиеОбщегоРеквизита.Использовать));
Возврат Результат;
КонецФункции
Функция ПолучитьАлгоритмОбъектПоИдентификаторуЛкс(Знач Алгоритм) Экспорт
Если ТипЗнч(Алгоритм) <> Тип("СправочникСсылка.ирАлгоритмы") Тогда
Алгоритм = "" + Алгоритм;
Если Найти(Алгоритм, "-") > 0 Тогда
// Передан GUID
Алгоритм = Справочники.ирАлгоритмы.ПолучитьСсылку(Новый УникальныйИдентификатор(Алгоритм));
Иначе
// Передано имя алгоритма
Попытка
Алгоритм = ПредопределенноеЗначение("Справочник.ирАлгоритмы." + Алгоритм);
Исключение
КонецПопытки;
Если ТипЗнч(Алгоритм) <> Тип("СправочникСсылка.ирАлгоритмы") Тогда
Алгоритм = Справочники.ирАлгоритмы.НайтиПоНаименованию(Алгоритм, Истина);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(Алгоритм) Тогда
ВызватьИсключение "Алгоритм по идентификатору """ + Алгоритм + """ не найден";
КонецЕсли;
Возврат Алгоритм.ПолучитьОбъект();
КонецФункции
//Если объекту не назначена ссылка, назначает эту ссылку
Функция ПолучитьТочнуюСсылкуОбъектаЛкс(ОбъектБД) Экспорт
Ссылка = ОбъектБД.Ссылка;
Если Ссылка.Пустая() Тогда
Ссылка = ОбъектБД.ПолучитьСсылкуНового();
Если Ссылка.Пустая() Тогда
Ссылка = XMLЗначение(ТипЗнч(Ссылка), "" + Новый УникальныйИдентификатор);
ОбъектБД.УстановитьСсылкуНового(Ссылка);
//ОбъектБД.ДополнительныеСвойства.Вставить("СсылкаНового", Ссылка); // Для обхода кривого кода в конфигурациях фиры 1С https://www.forum.mista.ru/topic.php?id=826103#58
КонецЕсли;
КонецЕсли;
Возврат Ссылка;
КонецФункции
Функция ВсеСтрокиДереваЗначенийЛкс(
Знач СтрокаИлиДеревоЗначений // СтрокаДереваЗначений, ДеревоЗначений
) Экспорт // Массив из СтрокаДереваЗначений
Если ТипЗнч(СтрокаИлиДеревоЗначений) = Тип("СтрокаДереваЗначений") Тогда
ДеревоЗначений = СтрокаИлиДеревоЗначений.Владелец();
Иначе
ДеревоЗначений = СтрокаИлиДеревоЗначений;
КонецЕсли;
Идентификатор = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
ДеревоЗначений.Колонки.Добавить(Идентификатор);
МассивСтрок = СтрокаИлиДеревоЗначений.Строки.НайтиСтроки(Новый Структура(Идентификатор, Неопределено), Истина);
ДеревоЗначений.Колонки.Удалить(Идентификатор);
Если ТипЗнч(СтрокаИлиДеревоЗначений) = Тип("СтрокаДереваЗначений") Тогда
МассивСтрок.Вставить(0, СтрокаИлиДеревоЗначений);
КонецЕсли;
Возврат МассивСтрок;
КонецФункции
// Функция - Все элементы дерева лкс
//
// Параметры:
// РодительскийЭлемент - Произвольный - элемент иерархической структуры (дерева)
// ФильтрПоТипу - Тип -
// Результат - - служебный
//
// Возвращаемое значение:
// -
//
Функция ВсеЭлементыДереваЛкс(Знач РодительскийЭлемент, Знач ФильтрПоТипу = Неопределено, Результат = Неопределено) Экспорт
ЭлементыГруппы = ДочерниеЭлементыДереваЛкс(РодительскийЭлемент, Ложь);
Если Результат = Неопределено Тогда
Результат = Новый Массив;
КонецЕсли;
Для Каждого ЭлементГруппы ИЗ ЭлементыГруппы Цикл
Если Ложь
Или ФильтрПоТипу = Неопределено
Или ТипЗнч(ЭлементГруппы) = ФильтрПоТипу
Тогда
Результат.Добавить(ЭлементГруппы);
КонецЕсли;
ВсеЭлементыДереваЛкс(ЭлементГруппы,, Результат);
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Дерево значений в таблицу лкс
//
// Параметры:
// СтрокаИлиДеревоЗначений - -
// МассивСтрок - Массив -
// ИменаКолонокТаблицы - -
//
// Возвращаемое значение:
// -
//
Функция ДеревоЗначенийВТаблицуЛкс(Знач СтрокаИлиДеревоЗначений, Знач МассивСтрок = Неопределено, Знач ИменаКолонокТаблицы = "") Экспорт
Если ТипЗнч(СтрокаИлиДеревоЗначений) = Тип("СтрокаДереваЗначений") Тогда
ДеревоЗначений = СтрокаИлиДеревоЗначений.Владелец();
Иначе
ДеревоЗначений = СтрокаИлиДеревоЗначений;
КонецЕсли;
Если МассивСтрок = Неопределено Тогда
МассивСтрок = ВсеСтрокиДереваЗначенийЛкс(ДеревоЗначений);
КонецЕсли;
ТаблицаСтрокДерева = СкопироватьКолонкиКоллекцииЛкс(ДеревоЗначений, Новый ТаблицаЗначений,, ИменаКолонокТаблицы);
Для Каждого СтрокаДерева Из МассивСтрок Цикл
ЗаполнитьЗначенияСвойств(ТаблицаСтрокДерева.Добавить(), СтрокаДерева);
КонецЦикла;
Возврат ТаблицаСтрокДерева;
КонецФункции
Процедура СкопироватьСтрокиДереваЛкс(СтрокаИсточник, СтрокаПриемник, СтопСтрока = Неопределено, Рекурсивно = Истина) Экспорт
Если СтопСтрока = Неопределено Тогда
Если СтрокаПриемник.Родитель <> Неопределено Тогда
СтопСтрока = СтрокаПриемник.Родитель;
КонецЕсли;
КонецЕсли;
Дерево = СтрокаПриемник.Владелец();
Для Каждого Колонка Из Дерево.Колонки Цикл
СтрокаПриемник[Колонка.Имя] = КопияОбъектаЛкс(СтрокаИсточник[Колонка.Имя]);
КонецЦикла;
Если Рекурсивно Тогда
Для Каждого Строка Из СтрокаИсточник.Строки Цикл
Если Строка = СтопСтрока Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = СтрокаПриемник.Строки.Добавить();
СкопироватьСтрокиДереваЛкс(Строка, НоваяСтрока, СтопСтрока, Рекурсивно);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция СериализацииРавныЛкс(Значение1, Значение2, СУчетомРегистра = Истина) Экспорт
СтрокаXML1 = ОбъектВСтрокуXMLЛкс(Значение1);
СтрокаXML2 = ОбъектВСтрокуXMLЛкс(Значение2);
Если Не СУчетомРегистра Тогда
СтрокаXML1 = НРег(СтрокаXML1);
СтрокаXML2 = НРег(СтрокаXML2);
КонецЕсли;
Результат = СтрокаXML1 = СтрокаXML2;
Возврат Результат;
КонецФункции
// ВариантОбрезания - 1
// ВариантОбрезания - 2
Функция ПолучитьИнформациюОбОшибкеБезВерхнегоМодуляЛкс(ИнформацияОбОшибке = Неопределено, ВариантОбрезания = 2) Экспорт
Если ИнформацияОбОшибке = Неопределено Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
КонецЕсли;
Если ВариантОбрезания = 1 Тогда
ОписаниеОшибки = ИнформацияОбОшибке.Описание;
Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
ОписаниеОшибки = ОписаниеОшибки + ": " + ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке.Причина);
КонецЕсли;
ИначеЕсли Истина
И ВариантОбрезания = 2
И ИнформацияОбОшибке.Причина <> Неопределено
Тогда
ОписаниеОшибки = ИнформацияОбОшибке.Описание + ": " + ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке.Причина);
Иначе
ОписаниеОшибки = ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
КонецЕсли;
Возврат ОписаниеОшибки;
КонецФункции
// МаксимальнаяГлубинаПричины - на сколько уровней вниз надо опуститься, пока есть вложенная причина
Функция ПредставлениеИнформацииОбОшибкеЛкс(Знач ИнформацияОбОшибке, Знач МаксимальнаяГлубинаПричины = 0, УбратьСтрокуКодаСПервогоУровня = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
#КонецЕсли
ОписаниеОшибки = "";
Если ТипЗнч(ИнформацияОбОшибке) = Тип("ИнформацияОбОшибке") Тогда
Для Счетчик = 1 По МаксимальнаяГлубинаПричины Цикл
Если ТипЗнч(ИнформацияОбОшибке.Причина) = Тип("ИнформацияОбОшибке") Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
#Если Сервер И Не Сервер Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
#КонецЕсли
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Если УбратьСтрокуКодаСПервогоУровня Тогда
ОписаниеОшибки = ИнформацияОбОшибке.Описание;
Если ТипЗнч(ИнформацияОбОшибке.Причина) = Тип("ИнформацияОбОшибке") Тогда
ОписаниеОшибки = ОписаниеОшибки + ": " + ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке.Причина);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ОписаниеОшибки) Тогда
Если ТипЗнч(ИнформацияОбОшибке) = Тип("ИнформацияОбОшибке") Тогда
ОписаниеОшибки = ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
Иначе
// Такое может случаться в свойстве ИнформацияОбОшибке объекта ФоновоеЗадание из-за ошибки платформы
ОписаниеОшибки = "Описание ошибки отсутствует";
КонецЕсли;
КонецЕсли;
Возврат ОписаниеОшибки;
КонецФункции
// Первая строка табличного документа содержит заголовки
// Параметры:
// ТабличныйДокумент - ТабличныйДокумент -
// ЛиПерваяСтрокаСодержитИменаКолонок - -
// ДлинаСтрокиТипаКолонки - -
// ВычислятьНетипизированныеЗначения - -
// ЛиВтораяСтрокаСодержитТипыЗначений - Булево - неявный способ трактовать вторую строку как атрибут "<Тип>". Кроме этого параметра еще можно использовать СобиратьАтрибутыИзПервойКолонки
// ОписанияТиповКолонок - Структура, ТаблицаЗначений, КоллекцияКолонокТаблицыЗначений -
// выхАтрибутыКолонок - Структура - выходной
// Русский - -
// СобиратьАтрибутыИзПервойКолонки - Булево - если у первой ШаблонПриемника задано имя, то собирать из нее атрибуты обрамленные в треугольные скобки; например "<Тип>", "<Перевод>".
// Из безымянной первой ШаблонПриемника атрибуты извлекаются независимо от этого параметра и могут быть без треугольных скобок.
// Возвращаемое значение:
// -
Функция ТаблицаЗначенийИзТабличногоДокументаЛкс(Знач ТабличныйДокумент, Знач ЛиПерваяСтрокаСодержитИменаКолонок = Истина, _ДлинаСтрокиТипаКолонки = 0,
Знач ВычислятьНетипизированныеЗначения = Ложь, Знач ЛиВтораяСтрокаСодержитТипыЗначений = Ложь, Знач ОписанияТиповКолонок = Неопределено, выхАтрибутыКолонок = Неопределено, Знач Русский = Ложь,
Знач СобиратьАтрибутыИзПервойКолонки = Истина,
Знач ТолькоВыделеннаяОбласть = Ложь, выхТекущаяСтрока = Неопределено, Знач ОбрезватьКонечныеПробелы = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокумент = Новый ТабличныйДокумент
#КонецЕсли
Если ТабличныйДокумент.ТекущаяОбласть <> Неопределено Тогда
НомерТекущейСтроки = ТабличныйДокумент.ТекущаяОбласть.Верх;
КонецЕсли;
ОбластьДляАнализа = Неопределено;
Если ТолькоВыделеннаяОбласть = Истина Тогда
ОбластьДляАнализа = ТабличныйДокумент.ТекущаяОбласть;
ИначеЕсли ТипЗнч(ТолькоВыделеннаяОбласть) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
ОбластьДляАнализа = ТолькоВыделеннаяОбласть;
КонецЕсли;
Если ОбластьДляАнализа <> Неопределено Тогда
НомерТекущейСтроки = НомерТекущейСтроки - ОбластьДляАнализа.Верх + 1;
ТабличныйДокумент = ТабличныйДокумент.ПолучитьОбласть(ОбластьДляАнализа.Имя);
КонецЕсли;
Если ТипЗнч(ОписанияТиповКолонок) = Тип("ТаблицаЗначений") Тогда
ОписанияТиповКолонок = ОписанияТиповКолонок.Колонки
КонецЕсли;
Если ТипЗнч(ОписанияТиповКолонок) = Тип("КоллекцияКолонокТаблицыЗначений") Тогда
ТипыКолонок = Новый Структура;
Для Каждого Колонка Из ОписанияТиповКолонок Цикл
ТипыКолонок.Вставить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;
Иначе
ТипыКолонок = ОписанияТиповКолонок;
КонецЕсли;
НачальнаяСтрока = 1;
Если ЛиПерваяСтрокаСодержитИменаКолонок Тогда
НачальнаяСтрока = НачальнаяСтрока + 1;
КонецЕсли;
Если ЛиВтораяСтрокаСодержитТипыЗначений Тогда
НачальнаяСтрока = НачальнаяСтрока + 1;
КонецЕсли;
НомерТекущейСтроки = НомерТекущейСтроки - НачальнаяСтрока + 1;
ТипизированныеКолонки = Новый Соответствие;
НачальныйНомерКолонки = 1;
Если Русский Тогда
ТабличныйДокумент.КодЯзыка = "ru";
КонецЕсли;
ШаблонПриемника = Новый ТаблицаЗначений;
Для СчетчикКолонок = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
Если ЛиПерваяСтрокаСодержитИменаКолонок Тогда
ИмяКолонки = ТабличныйДокумент.Область(1, СчетчикКолонок).Текст;
Если Найти(ИмяКолонки, ".") > 0 Тогда
Если Найти(ИмяКолонки, "_") > 0 Тогда
ВызватьИсключение "В именах колонок макета не допускается использование одновременно ""_"" и "".""";
КонецЕсли;
ИмяКолонки = СтрЗаменить(ИмяКолонки, ".", "_");
КонецЕсли;
ИмяКолонки = АвтоУникальноеИмяВКоллекцииЛкс(ШаблонПриемника.Колонки, ИмяКолонки,,, "Колонка1");
Иначе
ИмяКолонки = "Колонка" + СчетчикКолонок;
КонецЕсли;
Если СчетчикКолонок = 1 Тогда
ИмяПервойКолонки = ИмяКолонки;
КонецЕсли;
Если ШаблонПриемника.Колонки.Найти(ИмяКолонки) <> Неопределено Тогда
ВызватьИсключение "Обнаружено дублирование имени колонки " + ИмяКолонки + " в табличном документе-источнике таблицы значений";
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда
Если СчетчикКолонок = 1 Тогда
НачальныйНомерКолонки = 2;
Продолжить;
Иначе
ВызватьИсключение СтрШаблонЛкс("Не указано имя колонки №%1 в первой строке табличного документа-источника таблицы значений", СчетчикКолонок);
КонецЕсли;
КонецЕсли;
Если ТипыКолонок <> Неопределено И ТипыКолонок.Свойство(ИмяКолонки) Тогда
ИменаТипов = ТипыКолонок[ИмяКолонки];
ИначеЕсли ЛиВтораяСтрокаСодержитТипыЗначений Тогда
ИменаТипов = ТабличныйДокумент.Область(2, СчетчикКолонок).Текст;
Иначе
ИменаТипов = "";
КонецЕсли;
Если ЗначениеЗаполнено(ИменаТипов) Тогда
ТипизированныеКолонки[СчетчикКолонок] = 1;
ИначеЕсли Не ВычислятьНетипизированныеЗначения Тогда
ИменаТипов = "Строка";
КонецЕсли;
ШаблонПриемника.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов(ИменаТипов));
КонецЦикла;
ВысотаТаблицы = ТабличныйДокумент.ВысотаТаблицы;
Если НачальныйНомерКолонки = 2 Или СобиратьАтрибутыИзПервойКолонки Тогда
Для НомерСтроки = НачальнаяСтрока По ВысотаТаблицы Цикл
ИмяАтрибута = ТабличныйДокумент.Область(НомерСтроки, 1).Текст;
Если ЗначениеЗаполнено(ИмяАтрибута) Тогда
Если Истина
И СобиратьАтрибутыИзПервойКолонки
И (Ложь
Или Найти(ИмяАтрибута, "<") = 0
Или Найти(ИмяАтрибута, ">") = 0)
Тогда
Прервать;
КонецЕсли;
ИмяАтрибута = СтрЗаменить(ИмяАтрибута, "<", "");
ИмяАтрибута = СтрЗаменить(ИмяАтрибута, ">", "");
Если Не ЛиИмяПеременнойЛкс(ИмяАтрибута) Тогда
ВызватьИсключение СтрШаблонЛкс("Некорректное имя атрибута колонки макета (%1)", ИмяАтрибута);
КонецЕсли;
Если выхАтрибутыКолонок = Неопределено Тогда
выхАтрибутыКолонок = Новый Структура;
КонецЕсли;
Для НомерКолонки = 2 По ТабличныйДокумент.ШиринаТаблицы Цикл
Область = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки);
ИмяКолонки = ШаблонПриемника.Колонки[НомерКолонки - НачальныйНомерКолонки].Имя;
АтрибутыКолонки = Неопределено;
Если Не выхАтрибутыКолонок.Свойство(ИмяКолонки, АтрибутыКолонки) Тогда
АтрибутыКолонки = Новый Структура;
выхАтрибутыКолонок.Вставить(ИмяКолонки, АтрибутыКолонки);
КонецЕсли;
АтрибутыКолонки.Вставить(ИмяАтрибута, Область.Текст);
КонецЦикла;
НачальнаяСтрока = НачальнаяСтрока + 1;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ТаблицаПриемник = Новый ТаблицаЗначений;
НомерКолонки = НачальныйНомерКолонки;
Для Каждого КолонкаШаблона Из ШаблонПриемника.Колонки Цикл
ОписаниеТипов = ирОбщий.СвойствоСтруктурыЛкс(ТипыКолонок, КолонкаШаблона.Имя);
Если ОписаниеТипов = Неопределено Тогда
ОписаниеТипов = КолонкаШаблона.ТипЗначения;
КонецЕсли;
Если Истина
И (Ложь
Или ОписаниеТипов = Новый ОписаниеТипов
Или ОписаниеТипов = Новый ОписаниеТипов("Строка"))
И выхАтрибутыКолонок <> Неопределено
И выхАтрибутыКолонок.Свойство(КолонкаШаблона.Имя, АтрибутыКолонки)
Тогда
АтрибутыКолонки.Свойство("Тип", ОписаниеТипов);
Если ОписаниеТипов <> Неопределено Тогда
ОписаниеТипов = Новый ОписаниеТипов(ОписаниеТипов);
КонецЕсли;
КонецЕсли;
Если Истина
И ОписаниеТипов <> Неопределено
И ОписаниеТипов.Типы().Количество() > 0
Тогда
ТипизированныеКолонки[НомерКолонки] = 1;
КонецЕсли;
ТаблицаПриемник.Колонки.Добавить(КолонкаШаблона.Имя, ОписаниеТипов, КолонкаШаблона.Имя);
НомерКолонки = НомерКолонки + 1;
КонецЦикла;
//Индикатор = ПолучитьИндикаторПроцессаЛкс(ТабличныйДокумент.ВысотаТаблицы);
Для НомерСтроки = НачальнаяСтрока По ВысотаТаблицы Цикл
// Добавление строки результирующей таблицы
НоваяСтрокаТЗ = ТаблицаПриемник.Добавить();
Для НомерКолонки = НачальныйНомерКолонки По ТабличныйДокумент.ШиринаТаблицы Цикл
Область = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки);
ТекстЯчейки = Область.Текст;
Если ОбрезватьКонечныеПробелы Тогда
ТекстЯчейки = СокрП(ТекстЯчейки);
КонецЕсли;
Если Не ЗначениеЗаполнено(ТекстЯчейки) Тогда
Поддокумент = ТабличныйДокумент.ПолучитьОбласть(НомерСтроки, НомерКолонки);
Если Поддокумент.Рисунки.Количество() > 0 Тогда
ТекстЯчейки = Поддокумент.Рисунки[0].Картинка;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ТекстЯчейки) И АтрибутыКолонки <> Неопределено Тогда
АтрибутыКолонки.Свойство("БазовоеЗначение", ТекстЯчейки);
КонецЕсли;
ЗначениеЯчейки = Неопределено;
ОписаниеТиповКолонки = Неопределено;
Если ТипизированныеКолонки[НомерКолонки] <> Неопределено Тогда
ОписаниеТиповКолонки = ТаблицаПриемник.Колонки[НомерКолонки - НачальныйНомерКолонки].ТипЗначения;
Если ОписаниеТиповКолонки.СодержитТип(Тип("ОписаниеТипов")) Тогда
Попытка
ЗначениеЯчейки = Новый ОписаниеТипов(ТекстЯчейки);
Исключение
КонецПопытки;
ИначеЕсли ОписаниеТиповКолонки.СодержитТип(Тип("Тип")) Тогда
Попытка
ЗначениеЯчейки = Тип(ТекстЯчейки);
Исключение
КонецПопытки;
ИначеЕсли ОписаниеТиповКолонки.СодержитТип(Тип("Картинка")) Тогда
Поддокумент = ТабличныйДокумент.ПолучитьОбласть(НомерСтроки, НомерКолонки); // Тяжелая операция
Если Поддокумент.Рисунки.Количество() > 0 Тогда
ЗначениеЯчейки = Поддокумент.Рисунки[0].Картинка;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Ложь
Или ВычислятьНетипизированныеЗначения
Или (Истина
И ОписаниеТиповКолонки <> Неопределено
И ЗначениеЯчейки = Неопределено)
Тогда
Если ВычислятьНетипизированныеЗначения Или ОписаниеТиповКолонки.СодержитТип(Тип("Булево")) Тогда
Если СтрокиРавныЛкс(ТекстЯчейки, "Да",, Истина) Тогда
ЗначениеЯчейки = Истина;
ИначеЕсли СтрокиРавныЛкс(ТекстЯчейки, "Нет",, Истина) Тогда
ЗначениеЯчейки = Ложь;
КонецЕсли;
КонецЕсли;
//Если ВычислятьНетипизированныеЗначения И Лев(ТекстЯчейки, 1) = """" И Прав(ТекстЯчейки, 1) = """" Тогда
// ЗначениеЯчейки = ТекстИзВстроенногоЯзыкаЛкс(ТекстЯчейки);
//КонецЕсли;
//Если ВычислятьНетипизированныеЗначения И ЛиЦифраЛкс(Лев(ТекстЯчейки, 1)) Тогда
// ЗначениеЯчейки = СтрокаВЧислоЛкс(ТекстЯчейки);
//КонецЕсли;
Если Истина
И ЗначениеЯчейки = Неопределено
И ЗначениеЗаполнено(ТекстЯчейки)
И Не ОписаниеТиповКолонки.СодержитТип(Тип("Строка"))
Тогда
Попытка
ЗначениеЯчейки = Вычислить(ТекстЯчейки);
Исключение
КонецПопытки;
КонецЕсли;
КонецЕсли;
Если ЗначениеЯчейки = Неопределено Тогда
ЗначениеЯчейки = ТекстЯчейки;
КонецЕсли;
НоваяСтрокаТЗ[НомерКолонки - НачальныйНомерКолонки] = ЗначениеЯчейки;
КонецЦикла;
КонецЦикла;
Если Истина
И ТаблицаПриемник.Количество() > 0
И ТаблицаПриемник.Колонки[0].Имя = ИмяПервойКолонки
И ТаблицаПриемник.НайтиСтроки(Новый Структура(ИмяПервойКолонки, "")).Количество() = ТаблицаПриемник.Количество()
Тогда
ТаблицаПриемник.Колонки.Удалить(ИмяПервойКолонки);
КонецЕсли;
Если НомерТекущейСтроки > 0 Тогда
выхТекущаяСтрока = ТаблицаПриемник[НомерТекущейСтроки - 1];
КонецЕсли;
Возврат ТаблицаПриемник;
КонецФункции
Процедура УпроститьРасшифровкиТабличногоДокументаКомпоновкиЛкс(ТабличныйДокумент, ДанныеРасшифровки) Экспорт
#Если Сервер И Не Сервер Тогда
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
ТабличныйДокумент = Новый ТабличныйДокумент;
#КонецЕсли
ВысотаТаблицы = ТабличныйДокумент.ВысотаТаблицы;
Для НомерСтроки = 1 По ВысотаТаблицы Цикл
Для НомерКолонки = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
Область = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки);
Если ТипЗнч(Область.Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
Для каждого ЗначениеПоля Из ДанныеРасшифровки.Элементы[Область.Расшифровка].ПолучитьПоля() Цикл
Если Не ЛиСсылкаНаОбъектБДЛкс(ЗначениеПоля.Значение, Ложь) Тогда
Продолжить;
КонецЕсли;
Область.Расшифровка = ЗначениеПоля.Значение;
Прервать;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция ИдентификаторТипаЛкс(Тип) Экспорт
Результат = ТекстМеждуМаркерамиЛкс("" + ЗначениеВСтрокуВнутр(Тип), ",", "}", Ложь);
Возврат Результат;
КонецФункции
// Возвращает имена всех переменных текста программы встроенного языка
//
// Параметры:
// ТекстПрограммы - Строка - Если не передано, то на клиете берется из буфера обмена, а в других случаях выбрасыват исключение
// ВернутьМассив - Булево - если Истина, возвращается массив, иначе - структура
//
// Возвращаемое значение:
// - Массив, Структура
//
Функция ПеременныеТекстаВстроенногоЯзыкаЛкс(Знач ТекстПрограммы = "") Экспорт
Если ПустаяСтрока(ТекстПрограммы) Тогда
#Если Клиент Тогда
ТекстПрограммы = ирКлиент.ТекстИзБуфераОбменаОСЛкс();
#Иначе
ВызватьИсключение "Получение текста из буфера обмена возможно только на клиенте";
#КонецЕсли
КонецЕсли;
ПолеВстроенногоЯзыка = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстаПрограммы");
#Если Сервер И Не Сервер Тогда
ПолеВстроенногоЯзыка = Обработки.ирКлсПолеТекстаПрограммы.Создать();
#КонецЕсли
ПолеВстроенногоЯзыка.ИнициироватьНеинтерактивно();
ПолеВстроенногоЯзыка.ЗаполнитьЛокальныеСвойстваИМетодыПоТексту(,,,, Истина, ТекстПрограммы);
СтрокиЛокальныхПеременных = ПолеВстроенногоЯзыка.ТаблицаСлов.НайтиСтроки(Новый Структура("ТипСлова, Определение", "Свойство", "Статистический"));
//СтрокиЛокальныхПеременных = ПолеВстроенногоЯзыка.ТаблицаСлов.НайтиСтроки(Новый Структура("ТипСлова", "Свойство"));
Результат = ВыгрузитьСвойствоЛкс(СтрокиЛокальныхПеременных, "Слово");
Возврат Результат;
КонецФункции
// Формирует заголовок метода.
//
// Параметры:
// ЗначенияПараметров - Структура -
// ИменаПараметров - Строка - имена параметров, разделенные запятой
//
// Возвращаемое значение:
// Строка
//
Функция СобратьКомментарийМетодаЛкс(Знач ЗначенияПараметров, Знач ИменаПараметров) Экспорт
мПлатформа = ирКэш.Получить();
ПолеВстроенногоЯзыка = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстаПрограммы");
#Если Сервер И Не Сервер Тогда
ПолеВстроенногоЯзыка = Обработки.ирКлсПолеТекстаПрограммы.Создать();
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ПолеВстроенногоЯзыка.ИнициироватьНеинтерактивно();
Для Каждого Переменная Из СтрРазделитьЛкс(ИменаПараметров, ",", Истина) Цикл
Параметр = ПолеВстроенногоЯзыка.Параметры.Добавить();
Параметр.Имя = Переменная;
КонецЦикла;
СтрокаРезультата = Новый Структура("ТипЗначения, Комментарий");
Возврат ПолеВстроенногоЯзыка.СобратьКомментарийМетода(, СтрокаРезультата, ЗначенияПараметров);
КонецФункции
// КолонкиНабора - КоллекцияКолонокДереваЗначений, КоллекцияКолонокТаблицыЗначений, КоллекцияКолонокРезультатаЗапроса
Функция СоздатьИлиОбновитьНаборДанныхОбъектПоМетаданнымЛкс(Знач СхемаИлиМакетКомпоновкиДанных, Знач КолонкиНабора, Знач ИмяНабора = "Основной", Знач СоздаватьПапкиПолей = Ложь,
Знач СоздаватьРесурсыЧисловыхПолей = Ложь, ТаблицаЗначений = Неопределено, Знач СоздатьПоляТиповЗначений = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
СхемаИлиМакетКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
КолонкиНабора = Новый ТаблицаЗначений;
КолонкиНабора = КолонкиНабора.Колонки;
#КонецЕсли
Результат = СхемаИлиМакетКомпоновкиДанных.НаборыДанных.Найти(ИмяНабора);
Если Результат = Неопределено Тогда
Результат = СхемаИлиМакетКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных"));
КонецЕсли;
Результат.Имя = ИмяНабора;
Результат.ИсточникДанных = СхемаИлиМакетКомпоновкиДанных.ИсточникиДанных[0].Имя;
Результат.ИмяОбъекта = ИмяНабора;
Для Каждого ЭлементМетаданных Из КолонкиНабора Цикл
Если Ложь
Или ТипЗнч(ЭлементМетаданных) = Тип("КолонкаДереваЗначений")
Или ТипЗнч(ЭлементМетаданных) = Тип("КолонкаТаблицыЗначений")
Тогда
ИмяПоля = ЭлементМетаданных.Имя;
ЗаголовокПоля = ЭлементМетаданных.Заголовок;
ИначеЕсли Ложь
Или ТипЗнч(ЭлементМетаданных) = Тип("КолонкаРезультатаЗапроса")
Тогда
ИмяПоля = ЭлементМетаданных.Имя;
ЗаголовокПоля = ИмяПоля;
ИначеЕсли Ложь
Или ТипЗнч(ЭлементМетаданных) = Тип("ПолеНастройки")
Тогда
ИмяПоля = ЭлементМетаданных.Имя;
ЗаголовокПоля = ЭлементМетаданных.Представление;
ИначеЕсли Ложь
Или ТипЗнч(ЭлементМетаданных) = Тип("ДоступноеПолеОтбораКомпоновкиДанных")
Тогда
ИмяПоля = "" + ЭлементМетаданных.Поле;
ЗаголовокПоля = ЭлементМетаданных.Заголовок;
Иначе
Продолжить;
КонецЕсли;
Поле = Результат.Поля.Найти(ИмяПоля);
Если Поле = Неопределено Тогда
Если ТипЗнч(Результат) = Тип("НаборДанныхОбъектМакетаКомпоновкиДанных") Тогда
Поле = Результат.Поля.Добавить();
Поле.Имя = ИмяПоля;
Иначе
Поле = Результат.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
Поле.Поле = ИмяПоля;
КонецЕсли;
КонецЕсли;
ПутьКДанным = ИмяПоля;
Если СоздаватьПапкиПолей Тогда
ПутьКДанным = Результат.Имя + "." + ПутьКДанным;
КонецЕсли;
Поле.ПутьКДанным = ПутьКДанным;
Если ТипЗнч(Результат) = Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
Поле.Заголовок = ЗаголовокПоля;
Поле.ТипЗначения = ЭлементМетаданных.ТипЗначения;
Если Истина
И ТаблицаЗначений <> Неопределено
И ЭлементМетаданных.ТипЗначения.СодержитТип(Тип("Тип"))
И ЭлементМетаданных.ТипЗначения.Типы().Количество() = 1
Тогда
// Без установки доступных такая колонка не станет доступной для отбора https://partners.v8.1c.ru/forum/t/1917313/m/1917685
СписокТипов = Новый СписокЗначений;
СписокТипов.ЗагрузитьЗначения(РазличныеЗначенияКолонкиТаблицыЛкс(ТаблицаЗначений, ИмяПоля));
СписокТипов.СортироватьПоПредставлению();
Поле.УстановитьДоступныеЗначения(СписокТипов);
КонецЕсли;
Если Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И ЭлементМетаданных.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений"))
И Не ЭлементМетаданных.ТипЗначения.СодержитТип(Тип("ХранилищеЗначения")) // Антибаг платформы https://www.hostedredmine.com/issues/944097
Тогда
#Если Сервер И Не Сервер Тогда
ирОбщий.РасширенноеПредставлениеЛкс();
#КонецЕсли
Поле.ВыражениеПредставления = "ирОбщий.РасширенноеПредставлениеЛкс(" + ИмяПоля + ")";
КонецЕсли;
Если СоздатьПоляТиповЗначений Тогда
ДобавитьВычисляемоеПолеКомпоновкиТипЗначенияЛкс(СхемаИлиМакетКомпоновкиДанных, Поле);
КонецЕсли;
Если Истина
И СоздаватьРесурсыЧисловыхПолей
И Поле.ТипЗначения.СодержитТип(Тип("Число"))
Тогда
Ресурс = СхемаИлиМакетКомпоновкиДанных.ПоляИтога.Добавить();
Ресурс.Выражение = "Сумма(" + ИмяПоля + ")";
Ресурс.ПутьКДанным = ПутьКДанным;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Процедура ДобавитьВычисляемоеПолеКомпоновкиТипЗначенияЛкс(Знач СхемаКомпоновкиДанных, Знач ПолеНабора)
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
ПолеНабора = СхемаКомпоновкиДанных.НаборыДанных[0].Поля[0];
#КонецЕсли
ПутьКДанным = ПолеНабора.ПутьКДанным + "._ТипЗначения";
Если Истина
И ПолеНабора.ТипЗначения.Типы().Количество() > 1
И СхемаКомпоновкиДанных.ВычисляемыеПоля.Найти(ПутьКДанным) = Неопределено
Тогда
ВычисляемоеПоле = СхемаКомпоновкиДанных.ВычисляемыеПоля.Добавить();
ВычисляемоеПоле.Заголовок = ПолеНабора.Заголовок + "._Тип";
ВычисляемоеПоле.Выражение = "ТипЗначения(" + ПолеНабора.Поле + ")";
ВычисляемоеПоле.ПутьКДанным = ПутьКДанным;
ВычисляемоеПоле.ТипЗначения = Новый ОписаниеТипов("Тип");
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьПараметрыСхемыПоЗапросуЛкс(Знач СхемаКомпоновкиДанных, Знач Запрос, Знач ОчиститьТекущие = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Если ОчиститьТекущие Тогда
СхемаКомпоновкиДанных.Параметры.Очистить();
КонецЕсли;
ОписанияПараметров = Запрос.НайтиПараметры(); // Здесь могут быть ложные ошибки синтаксического контроля
Для Каждого ОписаниеПараметра Из ОписанияПараметров Цикл
Если Не Запрос.Параметры.Свойство(ОписаниеПараметра.Имя) Тогда
Запрос.Параметры.Вставить(ОписаниеПараметра.Имя);
КонецЕсли;
КонецЦикла;
Для Каждого КлючИЗначение Из Запрос.Параметры Цикл
ЗначениеПараметра = КлючИЗначение.Значение;
Если ТипЗнч(ЗначениеПараметра) = Тип("Массив") Тогда
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(ЗначениеПараметра);
ЗначениеПараметра = Список;
КонецЕсли;
ПараметрСхемы = СхемаКомпоновкиДанных.Параметры.Найти(КлючИЗначение.Ключ);
Если ПараметрСхемы = Неопределено Тогда
ПараметрСхемы = СхемаКомпоновкиДанных.Параметры.Добавить();
КонецЕсли;
ПараметрСхемы.Имя = КлючИЗначение.Ключ;
ПараметрСхемы.ДоступенСписокЗначений = ТипЗнч(ЗначениеПараметра) = Тип("СписокЗначений");
//Тип надо задавать, чтобы значение корректно записалось. Иначе ссылки будут преобразованы к строке.
Если ПараметрСхемы.ДоступенСписокЗначений Тогда
ПараметрСхемы.ТипЗначения = ЗначениеПараметра.ТипЗначения;
Иначе
// Ограничиваем строковый тип. Иначе будет ошибка "Нельзя сравнивать поля неограниченной длины и поля несовместимых типов" https://www.hostedredmine.com/issues/966382
ПараметрСхемы.ТипЗначения = Новый ОписаниеТипов(ЗначенияВМассивЛкс(ТипЗнч(ЗначениеПараметра)),,,, Новый КвалификаторыСтроки(1000));
КонецЕсли;
ПараметрСхемы.Значение = ЗначениеПараметра;
ПараметрСхемы.ОграничениеИспользования = Истина;
//ПараметрСхемы.ВключатьВДоступныеПоля = Ложь; // Закомментировано, т.к. ломает вычисление зависимых параметров СКД в консоли запросов https://www.hostedredmine.com/issues/953469
КонецЦикла;
КонецПроцедуры
Функция СоздатьИлиОбновитьНаборДанныхЗапросПоЗапросуЛкс(Знач СхемаКомпоновкиДанных, Знач Запрос, Знач ИмяНабора = "Основной", Знач ПредставленияПолей = Неопределено,
Знач АвтоЗаполнениеДоступныхПолей = Истина, Знач ПредставленияПапок = Неопределено) Экспорт
НаборДанных = ДобавитьНаборДанныхЗапросЛкс(СхемаКомпоновкиДанных.НаборыДанных, СхемаКомпоновкиДанных.ИсточникиДанных[0]);
НаборДанных.АвтоЗаполнениеДоступныхПолей = АвтоЗаполнениеДоступныхПолей;
НаборДанных.Запрос = Запрос.Текст;
Если ПредставленияПолей <> Неопределено Тогда
Для Каждого КлючИЗначение Из ПредставленияПолей Цикл
ПолеНабора = НаборДанных.Поля.Найти(КлючИЗначение.Ключ);
Если ПолеНабора = Неопределено Тогда
ПолеНабора = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
КонецЕсли;
ПолеНабора.Поле = КлючИЗначение.Ключ;
ПолеНабора.ПутьКДанным = КлючИЗначение.Ключ;
ПолеНабора.Заголовок = КлючИЗначение.Значение;
КонецЦикла;
КонецЕсли;
Если ПредставленияПапок <> Неопределено Тогда
Для Каждого КлючИЗначение Из ПредставленияПапок Цикл
ПапкаПолей = НаборДанных.Поля.Найти(КлючИЗначение.Ключ);
Если ПапкаПолей = Неопределено Тогда
ПапкаПолей = НаборДанных.Поля.Добавить(Тип("ПапкаПолейНабораДанныхСхемыКомпоновкиДанных"));
КонецЕсли;
ПапкаПолей.ПутьКДанным = КлючИЗначение.Ключ;
ПапкаПолей.Заголовок = КлючИЗначение.Значение;
КонецЦикла;
КонецЕсли;
ЗаполнитьПараметрыСхемыПоЗапросуЛкс(СхемаКомпоновкиДанных, Запрос);
Возврат НаборДанных;
КонецФункции
// Представления - Структура
Функция СоздатьСхемуКомпоновкиПоЗапросуЛкс(Знач ЗапросИлиТекст, ИмяНабораДанных = "Основной", ПредставленияПолей = Неопределено, АвтоЗаполнениеДоступныхПолей = Истина, ПредставленияПапок = Неопределено) Экспорт
СхемаКомпоновки = СоздатьСхемуКомпоновкиЛкс();
#Если Сервер И Не Сервер Тогда
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Если ТипЗнч(ЗапросИлиТекст) = Тип("Строка") Тогда
Запрос = Новый Запрос;
Запрос.Текст = ЗапросИлиТекст;
Иначе
Запрос = ЗапросИлиТекст;
КонецЕсли;
СоздатьИлиОбновитьНаборДанныхЗапросПоЗапросуЛкс(СхемаКомпоновки, Запрос, ИмяНабораДанных, ПредставленияПолей, АвтоЗаполнениеДоступныхПолей, ПредставленияПапок);
Возврат СхемаКомпоновки;
КонецФункции
Функция КомпоновщикПоСхемеКомпоновкиЛкс(Знач Схема) Экспорт
#Если Сервер И Не Сервер Тогда
Схема = Новый СхемаКомпоновкиДанных;
#КонецЕсли
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема);
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроек.Инициализировать(ИсточникДоступныхНастроек);
Возврат КомпоновщикНастроек;
КонецФункции
Функция ДобавитьВсеДоступныеПоляКомпоновкиВВыбранныеЛкс(Знач СхемаКомпоновки, Знач НастройкаКомпоновки = Неопределено) Экспорт
Если НастройкаКомпоновки = Неопределено Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
КонецЕсли;
КомпоновщикНастройки = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастройки.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки));
КомпоновщикНастройки.ЗагрузитьНастройки(НастройкаКомпоновки);
Если НастройкаКомпоновки.Структура.Количество() = 0 Тогда
ЭлементСтруктуры = НастройкаКомпоновки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Иначе
ЭлементСтруктуры = НастройкаКомпоновки.Структура[0];
КонецЕсли;
ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
Для Каждого ДоступноеПоле Из КомпоновщикНастройки.Настройки.ДоступныеПоляВыбора.Элементы Цикл
// Чтобы пропустить системные папки
Если Не ДоступноеПоле.Папка Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ДоступноеПоле.Поле);
КонецЕсли;
КонецЦикла;
Возврат НастройкаКомпоновки;
КонецФункции
Функция СоздатьСхемуКомпоновкиПоОбъектуМДЛкс(Знач ПолноеИмяИлиОбъектМД, Знач ИмяНабораДанных = "Основной", Знач ДобавитьАвтополеКоличествоСтрок = Истина,
Знач ПсевдонимТаблицы = "Т", Знач ИндексПараметраПериодичность = Неопределено, Знач ВыражениеПараметраПериодичность = "", Знач ИменаВместоПредставлений = Ложь, Знач ЧислоПервых = 0) Экспорт
Если ТипЗнч(ПолноеИмяИлиОбъектМД) = Тип("Строка") Тогда
ПолноеИмяМД = ПолноеИмяИлиОбъектМД;
Иначе
ПолноеИмяМД = ПолноеИмяИлиОбъектМД.ПолноеИмя();
КонецЕсли;
ПолноеИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД);
Схема = СоздатьСхемуКомпоновкиТаблицыБДЛкс(ПолноеИмяТаблицыБД, ВыражениеПараметраПериодичность, ДобавитьАвтополеКоличествоСтрок, ИндексПараметраПериодичность, ПсевдонимТаблицы,
ИменаВместоПредставлений,, ЧислоПервых);
Возврат Схема;
КонецФункции
// Функция - Поля таблицы БДЛкс
//
// Параметры:
// ПолноеИмяТаблицыБД - -
// НужныТолькоТипы - -
// ИндексПараметраПериодичность - -
// ВыражениеПараметраПериодичность - -
//
// Возвращаемое значение:
// см. ТаблицаЗначенийВТаблицуПолейБДЛкс -
//
Функция ПоляТаблицыБДЛкс(Знач ПолноеИмяТаблицыБД, Знач НужныТолькоТипы = Ложь, Знач ИндексПараметраПериодичность = Неопределено, Знач ВыражениеПараметраПериодичность = "") Экспорт
Если НужныТолькоТипы Тогда
ТаблицаРезультата = ПустаяТаблицаЗначенийИзТаблицыБДЛкс(ПолноеИмяТаблицыБД, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность);
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяТаблицыБД);
УдалитьТипNull = Истина
И Не ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип)
И Не ЛиКорневойТипРегистраБухгалтерииЛкс(КорневойТип);
Результат = ТаблицаЗначенийВТаблицуПолейБДЛкс(ТаблицаРезультата, УдалитьТипNull);
Возврат Результат;
Иначе
Результат = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД, Истина, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность);
КонецЕсли;
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Если ТипТаблицы = "ДвиженияССубконто" Тогда
ПолноеИмяТаблицыБД = СтрокаБезПоследнегоФрагментаЛкс(ПолноеИмяТаблицыБД);
КонецЕсли;
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД, Истина); // ОбъектМетаданныхСправочник
Если ОбъектМД <> Неопределено Тогда
Если ТипТаблицы = "Внешняя" Тогда
//! ОбъектМД = 0 // ОбъектМетаданныхТаблица
Для Каждого ПолеТаблицы Из ОбъектМД.Поля Цикл
СтрокаПоля = Результат.Найти(ПолеТаблицы.Имя, "Имя");
Если СтрокаПоля <> Неопределено Тогда
СтрокаПоля.Метаданные = ПолеТаблицы;
Заголовок = ПолеТаблицы.Представление();
Если ЗначениеЗаполнено(Заголовок) Тогда
СтрокаПоля.Заголовок = Заголовок;
КонецЕсли;
КонецЕсли;
КонецЦикла;
СловоСсылка = ПеревестиСтроку("Ссылка");
Если Истина
И ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные
И ОбъектМД.Поля.Найти(СловоСсылка) <> Неопределено
Тогда
// https://www.hostedredmine.com/issues/966649
Результат.Удалить(Результат.Найти(СловоСсылка + "1", "Имя"));
СообщитьЛкс(СтрШаблонЛкс("В таблице ""%1"" поле ""%2"" заблокировано пересечением с системным полем", ПолноеИмяТаблицыБД, СловоСсылка));
КонецЕсли;
Иначе
ПрефиксРеквизита = ОбъектМД.ПолноеИмя() + ".Реквизит.";
ИмяОстаток = Неопределено;
СтрокиСтруктурыТаблицы = СтруктураХраненияТаблицыБДЛкс(ПолноеИмяТаблицыБД, ТипТаблицы, ОбъектМД, ИмяОстаток, Ложь);
Если СтрокиСтруктурыТаблицы.Количество() = 0 Тогда
Если Истина
И ТипТаблицы <> "Изменения"
И ТипТаблицы <> "Константа"
И ТипТаблицы <> "КритерийОтбора"
И ТипТаблицы <> "ЗадачиПоИсполнителю"
//И ТипТаблицы <> "Границы"
Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Не удалось найти в структуре хранения БД описание таблицы %1",, ПолноеИмяТаблицыБД));
Иначе
// Для отладки
// Сюда попадаем для констант, у которых у таблицы изменений имя ошибочно указано то же, что и у основной таблицы.
// Сюда попадаем для границ последовательностей, у которых ошибочно пустое имя таблицы.
Пустышка = 1;
КонецЕсли;
Иначе
Если СтрокиСтруктурыТаблицы.Количество() > 1 Тогда
Пустышка = 1; // Для отладки. Сюда попадаем для констант, у которых у таблицы изменений имя ошибочно указано то же, что и у основной таблицы
КонецЕсли;
ТаблицаХраненияПолей = СтрокиСтруктурыТаблицы[0].Поля; // ТаблицаЗначений
ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(ТаблицаХраненияПолей);
ИмяНомерСтроки = ПеревестиСтроку("НомерСтроки");
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. ирОбщий.Пр(_РежимОтладки, 1, 1)
Для Каждого ПолеТаблицы Из ТаблицаХраненияПолей Цикл
ПолноеИмяРеквизита = ПолеТаблицы.Метаданные;
ИмяПоля = ПолеТаблицы.ИмяПоля;
СуффиксЗаголовка = "";
Если Не ЗначениеЗаполнено(ПолноеИмяРеквизита) Тогда
Попытка
МетаРеквизит = ОбъектМД.СтандартныеРеквизиты[ИмяПоля];
Исключение
Продолжить;
КонецПопытки;
СтрокаПоля = Результат.Найти(ИмяПоля, "Имя");
Если СтрокаПоля = Неопределено Тогда
// https://www.hostedredmine.com/issues/932788
Продолжить;
КонецЕсли;
ИначеЕсли Ложь
Или ИмяПоля <> ИмяНомерСтроки
Или Найти(ПолноеИмяРеквизита, ".ТабличнаяЧасть.") = 0
Тогда
СтрокаПоля = Результат.Найти(ИмяПоля, "Имя");
Если СтрокаПоля = Неопределено И ТипТаблицы = "ВиртуальнаяТаблица" Тогда
СтрокаПоля = Результат.Найти(ИмяПоля + ИмяОстаток, "Имя");
СуффиксЗаголовка = " Остаток";
Иначе
Если Не ирОбщий.СтрКончаетсяНаЛкс(ПолноеИмяРеквизита, "." + ИмяПоля, Истина) Тогда
СуффиксЗаголовка = " " + ирОбщий.ПоследнийФрагментЛкс(ИмяПоля, ирОбщий.ПоследнийФрагментЛкс(ПолноеИмяРеквизита), Ложь);
КонецЕсли;
КонецЕсли;
Если СтрокаПоля = Неопределено Тогда
Продолжить;
КонецЕсли;
Если Найти(ПолноеИмяРеквизита, ПрефиксРеквизита) = 1 Тогда
// Для ускорения
МетаРеквизит = ОбъектМД.Реквизиты[ИмяПоля];
Иначе
// Общий реквизит
МетаРеквизит = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяРеквизита); // ОбъектМетаданныхРеквизит
КонецЕсли;
Иначе
Продолжить;
КонецЕсли;
СтрокаПоля.Метаданные = МетаРеквизит;
Заголовок = МетаРеквизит.Представление();
Если ЗначениеЗаполнено(Заголовок) Тогда
СтрокаПоля.Заголовок = Заголовок + СуффиксЗаголовка;
КонецЕсли;
Попытка
СтрокаПоля.РежимПароля = МетаРеквизит.РежимПароля;
Исключение
КонецПопытки;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого ПолеТаблицы Из ТаблицаХраненияПолей Цикл ПолноеИмяРеквизита = ПолеТаблицы.Метаданные; ИмяПоля = ПолеТаблицы.ИмяПоля; СуффиксЗаголовка = ""; Если Не ЗначениеЗаполнено(ПолноеИмяРеквизита) Тогда Попытка МетаРеквизит = ОбъектМД.СтандартныеРеквизиты[ИмяПоля]; Исключение Продолжить; КонецПопытки; СтрокаПоля = Результат.Найти(ИмяПоля, "Имя"); Если СтрокаПоля = Неопределено Тогда Продолжить; КонецЕсли; ИначеЕсли Ложь Или ИмяПоля <> ИмяНомерСтроки Или Найти(ПолноеИмяРеквизита, ".ТабличнаяЧасть.") = 0 Тогда СтрокаПоля = Результат.Найти(ИмяПоля, "Имя"); Если СтрокаПоля = Неопределено И ТипТаблицы = "ВиртуальнаяТаблица" Тогда СтрокаПоля = Результат.Найти(ИмяПоля + ИмяОстаток, "Имя"); СуффиксЗаголовка = " Остаток"; Иначе Если Не ирОбщий.СтрКончаетсяНаЛкс(ПолноеИмяРеквизита, "." + ИмяПоля, Истина) Тогда СуффиксЗаголовка = " " + ирОбщий.ПоследнийФрагментЛкс(ИмяПоля, ирОбщий.ПоследнийФрагментЛкс(ПолноеИмяРеквизита), Ложь); КонецЕсли; КонецЕсли; Если СтрокаПоля = Неопределено Тогда Продолжить; КонецЕсли; Если Найти(ПолноеИмяРеквизита, ПрефиксРеквизита) = 1 Тогда МетаРеквизит = ОбъектМД.Реквизиты[ИмяПоля]; Иначе МетаРеквизит = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяРеквизита); КонецЕсли; Иначе Продолжить; КонецЕсли; Если Ложь Тогда МетаРеквизит = Метаданные.Справочники.ирАлгоритмы.Реквизиты.ДатаИзменения; КонецЕсли; СтрокаПоля.Метаданные = МетаРеквизит; Заголовок = МетаРеквизит.Представление(); Если ЗначениеЗаполнено(Заголовок) Тогда СтрокаПоля.Заголовок = Заголовок + СуффиксЗаголовка; КонецЕсли; Попытка СтрокаПоля.РежимПароля = МетаРеквизит.РежимПароля; Исключение КонецПопытки; КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИменаПолейТаблицыБДВРежимеПароляЛкс(ПолноеИмяТаблицы) Экспорт
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицы);
КолонкиВРежимеПароля = Новый Массив;
Для Каждого ПолеТаблицы Из ПоляТаблицыБД.НайтиСтроки(Новый Структура("РежимПароля", Истина)) Цикл
Если Не ПолеТаблицы.ТипЗначения.СодержитТип(Тип("Строка")) Тогда
Продолжить;
КонецЕсли;
КолонкиВРежимеПароля.Добавить(ПолеТаблицы.Имя);
КонецЦикла;
Возврат КолонкиВРежимеПароля;
КонецФункции
Функция ТаблицаЗначенийВТаблицуПолейБДЛкс(Знач ТаблицаРезультата, УдалитьТипNull = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаРезультата = Новый ТаблицаЗначений;
#КонецЕсли
Результат = Новый ТаблицаЗначений;
Результат.Колонки.Добавить("Имя"); // Строка
Результат.Колонки.Добавить("ТипЗначения", Новый ОписаниеТипов("ОписаниеТипов"));
Результат.Колонки.Добавить("Метаданные"); // ОбъектМетаданныхРеквизит
Результат.Колонки.Добавить("Заголовок"); // Строка
Результат.Колонки.Добавить("РежимПароля", Новый ОписаниеТипов("Булево"));
ПоляТаблицы = ТаблицаРезультата.Колонки;
Если УдалитьТипNull Тогда
ПоляТаблицы = ТаблицаСКолонкамиБезТипаNullЛкс(ТаблицаРезультата).Колонки;
КонецЕсли;
Для Каждого ПолеТаблицы Из ПоляТаблицы Цикл
СтрокаПоля = Результат.Добавить();
СтрокаПоля.Имя = ПолеТаблицы.Имя;
СтрокаПоля.Заголовок = ПолеТаблицы.Имя;
СтрокаПоля.ТипЗначения = ПолеТаблицы.ТипЗначения;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ТаблицаЗначенийВJSONЛкс(Знач Таблица) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
Массив = Новый Массив;
ИменаКолонок = ВыгрузитьСвойствоЛкс(Таблица.Колонки);
ИменаКолонок = СтрСоединитьЛкс(ИменаКолонок);
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого СтрокаТаблицы Из Таблица Цикл
СтруктураСтроки = Новый Структура(ИменаКолонок);
ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТаблицы);
Массив.Добавить(СтруктураСтроки);
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Каждого СтрокаТаблицы Из Таблица Цикл СтруктураСтроки = Новый Структура(ИменаКолонок); ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТаблицы); Массив.Добавить(СтруктураСтроки); КонецЦикла;
КонецЕсли;
Результат = ОбъектВСтрокуJSONЛкс(Массив, Истина);
Возврат Результат;
КонецФункции
Функция ПустаяТаблицаЗначенийИзТаблицыБДЛкс(Знач ПолноеИмяТаблицыБД, Знач ИндексПараметраПериодичность = Неопределено, Знач ВыражениеПараметраПериодичность = "") Экспорт
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Если ТипТаблицы = "ТабличнаяЧасть" Тогда
// Ускорение
ТаблицаРезультата = Новый ТаблицаЗначений;
Фрагменты = СтрРазделитьЛкс(ПолноеИмяТаблицыБД);
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(Фрагменты[0] + "." + Фрагменты[1]);
КолонкиТаблицы = ТаблицаРезультата.Колонки;
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.Справочники.Контрагенты;
#КонецЕсли
КолонкиТаблицы.Добавить(ПеревестиСтроку("Ссылка"), Новый ОписаниеТипов(Фрагменты[0] + ПеревестиСтроку("Ссылка") + "." + Фрагменты[1]), "Ссылка", 25); // 25 - такую ширину ставит платформа
КолонкиТаблицы.Добавить(ПеревестиСтроку("НомерСтроки"), Новый ОписаниеТипов("Число",,, Новый КвалификаторыЧисла(5, 0, ДопустимыйЗнак.Неотрицательный)), "Номер строки", 5);
Для Каждого Реквизит Из ОбъектМД.ТабличныеЧасти[Фрагменты[2]].Реквизиты Цикл
#Если Сервер И Не Сервер Тогда
Реквизит = Метаданные.Справочники.Валюты.Реквизиты.НаименованиеПолное;
#КонецЕсли
Если КолонкиТаблицы.Найти(Реквизит.Имя) <> Неопределено Тогда
// В режиме совместимости 8.2.13 допускалось создание реквизитов "Ссылка" и "НомерСтроки" https://www.hostedredmine.com/issues/926152
Продолжить;
КонецЕсли;
КолонкиТаблицы.Добавить(Реквизит.Имя, Реквизит.Тип, Реквизит.Представление(), ШиринаОписанияТиповЛкс(Реквизит.Тип));
КонецЦикла;
Возврат ТаблицаРезультата;
КонецЕсли;
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ТекстЗапроса = ПолучитьТекстЗапросаПолейТаблицыБДЛкс(ПолноеИмяТаблицыБД, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность);
ТаблицаРезультата = ПустаяТаблицаЗначенийИзТекстаЗапросаЛкс(ТекстЗапроса, ТипТаблицы);
Возврат ТаблицаРезультата;
КонецФункции
Функция ПустаяТаблицаЗначенийИзТекстаЗапросаЛкс(Знач ТекстЗапроса, Знач ТипТаблицы = "", Знач ВыбрасыватьИсключения = Ложь, Знач ВыводитьСообщения = Истина) Экспорт
УстановитьПривилегированныйРежим(Истина);
Если Истина
И ирКэш.ДоступноСхемаЗапросаЛкс()
И ТипТаблицы <> "Внешняя" // Антибаг платформы 8.3.18 схема запроса как и компоновка неоправдано удаляет тип NULL из описаний типов колонок
Тогда
// Этот способ в 4 раза быстрее, но инициирует модули менеджеров
Схема = Вычислить("Новый СхемаЗапроса");
#Если Сервер И Не Сервер Тогда
Схема = Новый СхемаЗапроса;
#КонецЕсли
Попытка
Схема.УстановитьТекстЗапроса(ТекстЗапроса);
Исключение
// Например некорректная подписка https://github.com/tormozit/RDT1C/issues/720
Если ВыбрасыватьИсключения Тогда
ВызватьИсключение;
КонецЕсли;
Схема = Неопределено;
Если ВыводитьСообщения Тогда
СообщитьЛкс(ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке().Причина));
КонецЕсли;
//Возврат Неопределено;
КонецПопытки;
Если Схема <> Неопределено Тогда
ТаблицаРезультата = Новый ТаблицаЗначений;
Для Каждого КолонкаСхемы Из Схема.ПакетЗапросов[Схема.ПакетЗапросов.Количество() - 1].Колонки Цикл
Если ТипЗнч(КолонкаСхемы) = Тип("КолонкаВложеннаяТаблицаСхемыЗапроса") Тогда
ТипЗначения = Новый ОписаниеТипов("ТаблицаЗначений");
Иначе
ТипЗначения = КолонкаСхемы.ТипЗначения;
КонецЕсли;
ТаблицаРезультата.Колонки.Добавить(КолонкаСхемы.Псевдоним, ТипЗначения);
КонецЦикла;
Возврат ТаблицаРезультата;
КонецЕсли;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса + Символы.ПС + "ГДЕ ЛОЖЬ";
Попытка
ТаблицаРезультата = Запрос.Выполнить().Выгрузить(); // Опасно
Исключение
// Долгий способ пробуем только если быстрый не удался
ПостроительЗапроса = Новый ПостроительЗапроса;
Попытка
ПостроительЗапроса.Текст = ТекстЗапроса;
ПостроительЗапроса.ЗаполнитьНастройки();
Исключение
Если ВыбрасыватьИсключения Тогда
ВызватьИсключение;
КонецЕсли;
СообщитьЛкс(ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке().Причина));
//Возврат Неопределено;
КонецПопытки;
ТаблицаРезультата = Новый ТаблицаЗначений;
Для Каждого ДоступноеПоле Из ПостроительЗапроса.ДоступныеПоля Цикл
ТаблицаРезультата.Колонки.Добавить(ДоступноеПоле.ПутьКДанным, ДоступноеПоле.ТипЗначения);
КонецЦикла;
КонецПопытки;
Возврат ТаблицаРезультата;
КонецФункции
// Процедура - Дополнить таблицу полей таблицы БДВиртуальными полями лкс
//
// Параметры:
// ТаблицаПолей - ТаблицаЗначений - :
// *Имя
// *ТипЗначения - ОписаниеТипов
// ОписаниеТаблицыБД - -
// ДляКонструктораЗапросов - -
//
Процедура ДополнитьТаблицуПолейТаблицыБДВиртуальнымиПолямиЛкс(Знач ТаблицаПолей, Знач ОписаниеТаблицыБД, Знач ДляКонструктораЗапросов = Ложь) Экспорт
Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(ОписаниеТаблицыБД.Тип) Тогда
СтрокаПоля = ТаблицаПолей.Добавить();
СтрокаПоля.Имя = "Представление";
Если ТаблицаПолей.Колонки.Найти("НИмя") <> Неопределено Тогда
СтрокаПоля.НИмя = НРег(СтрокаПоля.Имя);
КонецЕсли;
Если ДляКонструктораЗапросов Тогда
ТипЗначения = Новый ОписаниеТипов("ХранилищеЗначения");
Иначе
ТипЗначения = Новый ОписаниеТипов("Строка");
КонецЕсли;
СтрокаПоля.ТипЗначения = ТипЗначения;
КонецЕсли;
Если Ложь
Или ЛиКорневойТипДокументаЛкс(ОписаниеТаблицыБД.Тип)
Или (Истина
И ЛиКорневойТипРегистраБДЛкс(ОписаниеТаблицыБД.Тип)
И Не ЛиКорневойТипРегистраРасчетаЛкс(ОписаниеТаблицыБД.Тип)
И Не ЛиМетаданныеНезависимогоРегистраЛкс(ирКэш.ОбъектМДПоПолномуИмениЛкс(ОписаниеТаблицыБД.ПолноеИмя)))
Тогда
СтрокаПоля = ТаблицаПолей.Добавить();
СтрокаПоля.Имя = "МоментВремени";
Если ТаблицаПолей.Колонки.Найти("НИмя") <> Неопределено Тогда
СтрокаПоля.НИмя = НРег(СтрокаПоля.Имя);
КонецЕсли;
Если ДляКонструктораЗапросов Тогда
ТипЗначения = Новый ОписаниеТипов("ХранилищеЗначения");
Иначе
ТипЗначения = Новый ОписаниеТипов("МоментВремени");
КонецЕсли;
СтрокаПоля.ТипЗначения = ТипЗначения;
КонецЕсли;
КонецПроцедуры
Функция ШиринаОписанияТиповЛкс(Знач ТипЗначения, Знач ДляОбычнойФормы = Истина, выхРастягивать = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТипЗначения = Новый ОписаниеТипов;
#КонецЕсли
ШиринаКолонки = 2;
ЧислоПримитивныхТипов = 0;
ЧислоБольшихСтроковыхТипов = 0;
Если ТипЗначения.СодержитТип(Тип("Булево")) Тогда
Если ДляОбычнойФормы Тогда
ШиринаКолонки = 2;
Иначе
ШиринаКолонки = 5;
КонецЕсли;
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Строка")) Тогда
Длина = ТипЗначения.КвалификаторыСтроки.Длина;
Делитель = 1;
Если ТипЗначения.КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Фиксированная Тогда
Если ДляОбычнойФормы Тогда
Делитель = 2; // К сожалению для поля "Номер" тип значения в отборе имеет неверный тип длины (всегда переменный)
Иначе
Если Длина > 0 Тогда
Длина = Длина + 2;
КонецЕсли;
КонецЕсли;
КонецЕсли;
МаксШирина = 30;
Если Длина = 0 Или МаксШирина < Длина Тогда
ЧислоБольшихСтроковыхТипов = 1;
КонецЕсли;
ШиринаКолонки = Макс(ШиринаКолонки, Мин(МаксШирина, Длина) / Делитель);
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Число")) Тогда
ДлинаЧисло = 11;
Разрядность = ТипЗначения.КвалификаторыЧисла.Разрядность;
Если Разрядность = 0 Тогда
// 38 - максимальная из запроса
Разрядность = 38;
КонецЕсли;
Делитель = 1;
Если ДляОбычнойФормы Тогда
//Делитель = 2; // По непонятной причине в обычной форме для числовой колонки и строки фикс. длины единица ширины фактически умножается платформой на 2
Если Разрядность <= 5 Тогда
Разрядность = Разрядность + 1;
КонецЕсли;
КонецЕсли;
ШиринаКолонки = Макс(ШиринаКолонки, Мин(ДлинаЧисло, Разрядность)/Делитель);
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("Дата")) Тогда
Если ДляОбычнойФормы Тогда
ДлинаДатаВремя = 18;
ДлинаДата = 10;
Иначе
ДлинаДатаВремя = 13;
ДлинаДата = 7;
КонецЕсли;
Если ТипЗначения.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.ДатаВремя Тогда
ШиринаКолонки = Макс(ШиринаКолонки, ДлинаДатаВремя);
Иначе
ШиринаКолонки = Макс(ШиринаКолонки, ДлинаДата);
КонецЕсли;
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("УникальныйИдентификатор")) Тогда
ШиринаКолонки = Макс(ШиринаКолонки, 25);
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ТипЗначения.СодержитТип(Тип("ХранилищеЗначения")) Тогда
ЧислоПримитивныхТипов = ЧислоПримитивныхТипов + 1;
КонецЕсли;
Если ЧислоПримитивныхТипов < ТипЗначения.Типы().Количество() Тогда
// Ссылочные
ШиринаКолонки = Мин(ШиринаКолонки, 20);
КонецЕсли;
ШиринаКолонки = Мин(ШиринаКолонки, 32);
выхРастягивать = ЧислоПримитивныхТипов - ЧислоБольшихСтроковыхТипов = 0;
Если выхРастягивать Тогда
ШиринаКолонки = Макс(ШиринаКолонки, 10);
КонецЕсли;
Возврат ШиринаКолонки;
КонецФункции
Функция ПроверитьПропуститьНедоступнуюТаблицуБДЛкс(Знач ОписаниеТаблицы) Экспорт
Пропустить = Ложь;
Если Не ОписаниеТаблицы.ЕстьДоступ Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Пропускаем недоступную таблицу БД %1",, ОписаниеТаблицы.ПолноеИмя) , СтатусСообщения.Внимание);
Пропустить = Истина;
КонецЕсли;
Возврат Пропустить;
КонецФункции
Функция ТаблицаВсехТаблицБДБезОжиданияЛкс() Экспорт
СостояниеРасчета = ирКэш.СостояниеПодготовкиКэшМДСеансаЛкс();
Если СостояниеРасчета <> Неопределено Тогда
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(СостояниеРасчета.ИдентификаторЗадания);
КонецЕсли;
Если ФоновоеЗадание <> Неопределено Тогда
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Результат = ирКэш.ТаблицаВсехТаблицБДЛкс();
Возврат Результат;
КонецФункции
Процедура КэшМДСеансаВФонеЛкс(АдресВременногоХранилища) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Кэш = Новый Структура;
Кэш.Вставить("ТаблицаВсехТаблицБД", ирКэш.ТаблицаВсехТаблицБДЛкс());
Кэш.Вставить("ДеревоОбъектовМД", ирКэш.ДеревоОбъектовМДЛкс());
ПоместитьВоВременноеХранилище(Кэш, АдресВременногоХранилища);
КонецПроцедуры
// Параметры:
// НужныПредставления - Булево - для стандартных полей будут заполняться представления (дольше)
Функция ПоляТаблицыМДЛкс(ПолноеИмяИлиОбъектМД, НужныТолькоТипы = Ложь, ИндексПараметраПериодичность = Неопределено, ВыражениеПараметраПериодичность = "", НужныПредставления = Истина) Экспорт
Если ТипЗнч(ПолноеИмяИлиОбъектМД) = Тип("ОбъектМетаданных") Тогда
ПолноеИмяМД = ПолноеИмяИлиОбъектМД.ПолноеИмя();
Иначе
ПолноеИмяМД = ПолноеИмяИлиОбъектМД;
КонецЕсли;
ПолноеИмяТаблицыБД = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД);
ПоляТаблицы = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД, НужныТолькоТипы, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность);
Если НужныПредставления Тогда
// Нужно для заполнения представлений системных полей, которые не заполняются в ПоляТаблицыБДЛкс()
КомпоновщикТаблицы = ирКэш.КомпоновщикТаблицыМетаданныхЛкс(ПолноеИмяМД);
#Если Сервер И Не Сервер Тогда
КомпоновщикТаблицы = Новый КомпоновщикНастроекКомпоновкиДанных;
#КонецЕсли
Для Каждого ДоступноеПоле Из КомпоновщикТаблицы.Настройки.ДоступныеПоляВыбора.Элементы Цикл
Если Истина
И Найти("" + ДоступноеПоле.Заголовок, " ") < 1
Тогда
Продолжить;
КонецЕсли;
ПолеТаблицы = ПоляТаблицы.Найти("" + ДоступноеПоле.Поле, "Имя");
Если ПолеТаблицы <> Неопределено И Найти(ПолеТаблицы, " ") < 1 Тогда
ПолеТаблицы.Заголовок = ДоступноеПоле.Заголовок;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат ПоляТаблицы;
КонецФункции
// Добавляет в набор данных поле набора данных
Функция ДобавитьПолеНабораДанныхЛкс(НаборДанных, Поле, Заголовок, ПутьКДанным = Неопределено) Экспорт
Если ПутьКДанным = Неопределено Тогда
ПутьКДанным = Поле;
КонецЕсли;
ПолеНабораДанных = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ПолеНабораДанных.Поле = Поле;
ПолеНабораДанных.Заголовок = Заголовок;
ПолеНабораДанных.ПутьКДанным = ПутьКДанным;
Возврат ПолеНабораДанных;
КонецФункции
Функция ДобавитьПоляПериодаВНаборДанныхЛкс(НаборДанных)
СписокПериодов = Новый СписокЗначений;
СписокПериодов.Добавить("ПериодСекунда", "Период секунда");
СписокПериодов.Добавить("ПериодМинута", "Период минута");
СписокПериодов.Добавить("ПериодЧас", "Период час");
СписокПериодов.Добавить("ПериодДень", "Период день");
СписокПериодов.Добавить("ПериодНеделя", "Период неделя");
СписокПериодов.Добавить("ПериодДекада", "Период декада");
СписокПериодов.Добавить("ПериодМесяц", "Период месяц");
СписокПериодов.Добавить("ПериодКвартал", "Период квартал");
СписокПериодов.Добавить("ПериодПолугодие", "Период полугодие");
СписокПериодов.Добавить("ПериодГод", "Период год");
ИмяПапки = "Периоды";
СписокПолейНабораДанных = Новый СписокЗначений;
ПапкаПолейНабораДанных = НаборДанных.Поля.Добавить(Тип("ПапкаПолейНабораДанныхСхемыКомпоновкиДанных"));
ПапкаПолейНабораДанных.Заголовок = ИмяПапки;
ПапкаПолейНабораДанных.ПутьКДанным = ИмяПапки;
Для каждого Период Из СписокПериодов Цикл
ПолеНабораДанных = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ПолеНабораДанных.Поле = Период.Значение;
ПолеНабораДанных.Заголовок = Период.Представление;
ПолеНабораДанных.ПутьКДанным = ИмяПапки + "." + Период.Значение;
СписокПолейНабораДанных.Добавить(ПолеНабораДанных);
КонецЦикла;
Возврат СписокПолейНабораДанных;
КонецФункции
// Функция добавляет поле итога в схему компоновки данных. Если параметр Выражение не указан, используется Сумма(ПутьКДанным)
Функция ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, ПутьКДанным, Выражение = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
Если Выражение = Неопределено Тогда
Выражение = "Сумма(" + ПутьКДанным + ")";
КонецЕсли;
ПолеИтога = СхемаКомпоновкиДанных.ПоляИтога.Добавить();
ПолеИтога.ПутьКДанным = ПутьКДанным;
ПолеИтога.Выражение = Выражение;
Возврат ПолеИтога;
КонецФункции
Функция СуффиксыРесурсовВиртТаблицЛкс() Экспорт
Суффиксы = Новый Массив;
Суффиксы.Добавить("Остаток");
Суффиксы.Добавить("РазвернутыйОстаток");
Суффиксы.Добавить("НачальныйОстаток");
Суффиксы.Добавить("НачальныйРазвернутыйОстаток");
Суффиксы.Добавить("Оборот");
Суффиксы.Добавить("КорОборот");
Суффиксы.Добавить("Приход");
Суффиксы.Добавить("Расход");
Суффиксы.Добавить("КонечныйОстаток");
Суффиксы.Добавить("КонечныйРазвернутыйОстаток");
Возврат Суффиксы;
КонецФункции
Процедура ДобавитьПоляНабораДанныхЛкс(ПолноеИмяТаблицыБД, СхемаКомпоновкиДанных) Экспорт
#Если Сервер И Не Сервер Тогда
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
#КонецЕсли
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяТаблицыБД);
Если СтрокиРавныЛкс(ТипТаблицы, "ВиртуальнаяТаблица") Тогда
ИмяВиртуальнойТаблицы = ПоследнийФрагментЛкс(ПолноеИмяТаблицыБД);
ПолноеИмяМД = ПолноеИмяТаблицыБД;
Иначе
ИмяВиртуальнойТаблицы = "";
ПолноеИмяМД = ПолноеИмяТаблицыБД;
КонецЕсли;
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Если ЛиМетаданныеРегистраЛкс(ОбъектМД) И Не СтрокиРавныЛкс(ТипТаблицы, "Изменения") Тогда
// Добавляем измерения
Для каждого Измерение Из ОбъектМД.Измерения Цикл
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Измерение.Имя, Измерение.Синоним);
КонецЦикла;
// Добавляем реквизиты
Если Истина
И Не ЛиКорневойТипПоследовательностиЛкс(КорневойТип)
И Не СтрокиРавныЛкс(ТипТаблицы, "Перерасчет")
Тогда
//Если ПустаяСтрока(ИмяВиртуальнойТаблицы) Тогда
Для каждого Реквизит Из ОбъектМД.Реквизиты Цикл
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Реквизит.Имя, Реквизит.Синоним);
КонецЦикла;
//КонецЕсли;
// Добавляем поля периода
Если Ложь
Или ИмяВиртуальнойТаблицы = "ОстаткиИОбороты"
Или ИмяВиртуальнойТаблицы = "Обороты"
Или (Истина
И КорневойТип = "РегистрБухгалтерии"
И ИмяВиртуальнойТаблицы = "")
Тогда
ДобавитьПоляПериодаВНаборДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0]);
КонецЕсли;
// Добавляем ресурсы
Для каждого Ресурс Из ОбъектМД.Ресурсы Цикл
Если ИмяВиртуальнойТаблицы = "Обороты" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним);
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Оборот");
Если КорневойТип = "РегистрНакопления" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Приход", Ресурс.Синоним + " приход", Ресурс.Имя + "Приход");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Приход");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Расход", Ресурс.Синоним + " расход", Ресурс.Имя + "Расход");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Расход");
ИначеЕсли КорневойТип = "РегистрБухгалтерии" ТОгда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотДт", Ресурс.Синоним + " оборот Дт", Ресурс.Имя + "ОборотДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотКт", Ресурс.Синоним + " оборот Кт", Ресурс.Имя + "ОборотКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотКт");
Если НЕ Ресурс.Балансовый Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КорОборот", Ресурс.Синоним + " кор. оборот", Ресурс.Имя + "КорОборот");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КорОборот");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КорОборотДт", Ресурс.Синоним + " кор. оборот Дт", Ресурс.Имя + "КорОборотДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КорОборотДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КорОборотКт", Ресурс.Синоним + " кор. оборот Кт", Ресурс.Имя + "КорОборотКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КорОборотКт");
КонецЕсли;
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "ОборотыДтКт" Тогда
Если Ресурс.Балансовый Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним);
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Оборот");
Иначе
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотДт", Ресурс.Синоним + " оборот Дт", Ресурс.Имя + "ОборотДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотКт", Ресурс.Синоним + " оборот Кт", Ресурс.Имя + "ОборотКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотКт");
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "ДвиженияССубконто" Тогда
Если Ресурс.Балансовый Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя);
Иначе
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Дт", Ресурс.Синоним + " Дт", Ресурс.Имя + "Дт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Дт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Кт", Ресурс.Синоним + " Кт", Ресурс.Имя + "Кт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Кт");
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "ОстаткиИОбороты" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстаток", Ресурс.Синоним + " нач. остаток", Ресурс.Имя + "НачальныйОстаток");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйОстаток");
Если КорневойТип = "РегистрБухгалтерии" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстатокДт", Ресурс.Синоним + " нач. остаток Дт", Ресурс.Имя + "НачальныйОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйОстатокКт", Ресурс.Синоним + " нач. остаток Кт", Ресурс.Имя + "НачальныйОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйОстатокКт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйРазвернутыйОстатокДт", Ресурс.Синоним + " нач. развернутый остаток Дт", Ресурс.Имя + "НачальныйРазвернутыйОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйРазвернутыйОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "НачальныйРазвернутыйОстатокКт", Ресурс.Синоним + " нач. развернутый остаток Кт", Ресурс.Имя + "НачальныйРазвернутыйОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "НачальныйРазвернутыйОстатокКт");
КонецЕсли;
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Оборот", Ресурс.Синоним + " оборот", Ресурс.Имя + "Оборот");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Оборот");
Если КорневойТип = "РегистрНакопления" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Приход", Ресурс.Синоним + " приход", Ресурс.Имя + "Приход");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Приход");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Расход", Ресурс.Синоним + " расход", Ресурс.Имя + "Расход");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Расход");
ИначеЕсли КорневойТип = "РегистрБухгалтерии" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотДт", Ресурс.Синоним + " оборот Дт", Ресурс.Имя + "ОборотДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОборотКт", Ресурс.Синоним + " оборот Кт", Ресурс.Имя + "ОборотКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОборотКт");
КонецЕсли;
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстаток", Ресурс.Синоним + " кон. остаток", Ресурс.Имя + "КонечныйОстаток");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйОстаток");
Если КорневойТип = "РегистрБухгалтерии" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстатокДт", Ресурс.Синоним + " кон. остаток Дт", Ресурс.Имя + "КонечныйОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйОстатокКт", Ресурс.Синоним + " кон. остаток Кт", Ресурс.Имя + "КонечныйОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйОстатокКт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйРазвернутыйОстатокДт", Ресурс.Синоним + " кон. развернутый остаток Дт", Ресурс.Имя + "КонечныйРазвернутыйОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйРазвернутыйОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "КонечныйРазвернутыйОстатокКт", Ресурс.Синоним + " кон. развернутый остаток Кт", Ресурс.Имя + "КонечныйРазвернутыйОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "КонечныйРазвернутыйОстатокКт");
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "Остатки" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Остаток", Ресурс.Синоним + " остаток", Ресурс.Имя + "Остаток");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Остаток");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОстатокДт", Ресурс.Синоним + " остаток Дт", Ресурс.Имя + "ОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "ОстатокКт", Ресурс.Синоним + " остаток Кт", Ресурс.Имя + "ОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "ОстатокКт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "РазвернутыйОстатокДт", Ресурс.Синоним + " развернутый остаток Дт", Ресурс.Имя + "РазвернутыйОстатокДт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "РазвернутыйОстатокДт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "РазвернутыйОстатокКт", Ресурс.Синоним + " развернутый остаток Кт", Ресурс.Имя + "РазвернутыйОстатокКт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "РазвернутыйОстатокКт");
ИначеЕсли КорневойТип = "РегистрСведений" Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
Если Ресурс.Тип.СодержитТип(Тип("Число")) Тогда
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя, Ресурс.Имя);
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "" Тогда
Если КорневойТип = "РегистрБухгалтерии" Тогда
Если Ресурс.Балансовый Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя);
Иначе
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Дт", Ресурс.Синоним + " Дт", Ресурс.Имя + "Дт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Дт");
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя + "Кт", Ресурс.Синоним + " Кт", Ресурс.Имя + "Кт");
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя + "Кт");
КонецЕсли;
Иначе
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Ресурс.Имя, Ресурс.Синоним);
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Ресурс.Имя);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ИначеЕсли ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД) Тогда
Если ИмяВиртуальнойТаблицы = "" Тогда
ОбъектМетаданных = ОбъектМД;
Иначе
ОбъектМетаданных = ОбъектМД.ТабличныеЧасти.Найти(ИмяВиртуальнойТаблицы);
Если ОбъектМетаданных = Неопределено Тогда
ОбъектМетаданных = ОбъектМД;
КонецЕсли;
КонецЕсли;
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], "Ссылка", "Ссылка");
Если ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМетаданных,, Истина) Тогда
Если ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип) Тогда
Реквизиты = ОбъектМетаданных.Поля;
Иначе
Реквизиты = ОбъектМетаданных.Реквизиты;
КонецЕсли;
Для каждого Реквизит Из Реквизиты Цикл
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], Реквизит.Имя, Реквизит.Синоним);
Если Реквизит.Тип.СодержитТип(Тип("Число")) Тогда
ДобавитьПолеИтогаЛкс(СхемаКомпоновкиДанных, Реквизит.Имя);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
// Тут добавляются Период, НомерСтроки, Регистратор
Для Каждого КлючИЗначение Из СтруктураКлючаТаблицыБДЛкс(ПолноеИмяТаблицыБД) Цикл
Если СхемаКомпоновкиДанных.НаборыДанных[0].Поля.Найти(КлючИЗначение.Ключ) = Неопределено Тогда
ДобавитьПолеНабораДанныхЛкс(СхемаКомпоновкиДанных.НаборыДанных[0], КлючИЗначение.Ключ, КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ДобавитьВыбранныеПоляКомпоновкиПоТаблицеБДЛкс(ПолноеИмяТаблицыБД, НастройкаКомпоновки) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяТаблицыБД);
Если СтрокиРавныЛкс(ТипТаблицы, "ВиртуальнаяТаблица") Тогда
ИмяВиртуальнойТаблицы = ПоследнийФрагментЛкс(ПолноеИмяТаблицыБД);
Иначе
ИмяВиртуальнойТаблицы = "";
КонецЕсли;
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
ВыбранныеПоля = НастройкаКомпоновки.Выбор;
Если ИмяВиртуальнойТаблицы = "ОстаткиИОбороты" Тогда
ВыбранныеПоляНачальныйОстаток = ВыбранныеПоля.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
ВыбранныеПоляНачальныйОстаток.Заголовок = "Нач. остаток";
ВыбранныеПоляНачальныйОстаток.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
Если КорневойТип = "РегистрНакопления" Тогда
ВыбранныеПоляПриход = ВыбранныеПоля.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
ВыбранныеПоляПриход.Заголовок = "Приход";
ВыбранныеПоляПриход.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
ВыбранныеПоляРасход = ВыбранныеПоля.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
ВыбранныеПоляРасход.Заголовок = "Расход";
ВыбранныеПоляРасход.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
ИначеЕсли КорневойТип = "РегистрБухгалтерии" Тогда
ВыбранныеПоляОбороты = ВыбранныеПоля.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
ВыбранныеПоляОбороты.Заголовок = "Обороты";
ВыбранныеПоляОбороты.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
КонецЕсли;
ВыбранныеПоляКонечныйОстаток = ВыбранныеПоля.Элементы.Добавить(Тип("ГруппаВыбранныхПолейКомпоновкиДанных"));
ВыбранныеПоляКонечныйОстаток.Заголовок = "Кон. остаток";
ВыбранныеПоляКонечныйОстаток.Расположение = РасположениеПоляКомпоновкиДанных.Горизонтально;
КонецЕсли;
Если КорневойТип = "РегистрНакопления" Тогда
Для каждого Ресурс Из ОбъектМД.Ресурсы Цикл
Если ИмяВиртуальнойТаблицы = "Обороты" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Оборот");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Приход",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Расход",, Ложь);
ИначеЕсли ИмяВиртуальнойТаблицы = "ОстаткиИОбороты" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйОстаток");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Оборот",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляПриход, Ресурс.Имя + "Приход");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляРасход, Ресурс.Имя + "Расход");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйОстаток");
ИначеЕсли ИмяВиртуальнойТаблицы = "Остатки" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Остаток");
ИначеЕсли ИмяВиртуальнойТаблицы = "" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя);
КонецЕсли;
КонецЦикла;
ИначеЕсли КорневойТип = "РегистрСведений" Тогда
Для каждого Ресурс Из ОбъектМД.Ресурсы Цикл
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя);
КонецЦикла;
ИначеЕсли КорневойТип = "РегистрБухгалтерии" Тогда
Для каждого Ресурс Из ОбъектМД.Ресурсы Цикл
Если ИмяВиртуальнойТаблицы = "Обороты" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Оборот",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОборотДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОборотКт");
Если Не Ресурс.Балансовый Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "КорОборот",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "КорОборотДт",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "КорОборотКт",, Ложь);
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "ОборотыДтКт" Тогда
Если Ресурс.Балансовый Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Оборот");
Иначе
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОборотДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОборотКт");
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "Остатки" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Остаток");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОстатокДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "ОстатокКт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "РазвернутыйОстатокДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "РазвернутыйОстатокКт");
ИначеЕсли ИмяВиртуальнойТаблицы = "ОстаткиИОбороты" Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйОстаток",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйОстатокДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйОстатокКт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйРазвернутыйОстатокДт",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляНачальныйОстаток, Ресурс.Имя + "НачальныйРазвернутыйОстатокКт",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляОбороты, Ресурс.Имя + "Оборот",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляОбороты, Ресурс.Имя + "ОборотДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляОбороты, Ресурс.Имя + "ОборотКт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйОстаток",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйОстатокДт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйОстатокКт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйРазвернутыйОстатокДт",, Ложь);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоляКонечныйОстаток, Ресурс.Имя + "КонечныйРазвернутыйОстатокКт",, Ложь);
ИначеЕсли ИмяВиртуальнойТаблицы = "ДвиженияССубконто" Тогда
Если Ресурс.Балансовый Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя);
Иначе
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Дт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Кт");
КонецЕсли;
ИначеЕсли ИмяВиртуальнойТаблицы = "" Тогда
Если Ресурс.Балансовый Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя);
Иначе
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Дт");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, Ресурс.Имя + "Кт");
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(КорневойТип) Тогда
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Для каждого ПолеТаблицы Из ПоляТаблицыБД Цикл
Если ПолеТаблицы.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Продолжить;
КонецЕсли;
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ВыбранныеПоля, ПолеТаблицы.Имя);
КонецЦикла;
//КонецЕсли;
КонецПроцедуры
Процедура ДобавитьПолеГруппировкиЛкс(Группировка, Наименование, Синоним)
Если Группировка.Найти(Наименование, "Поле") = Неопределено Тогда
ГруппировкаСтр = Группировка.Добавить();
ГруппировкаСтр.Поле = Наименование;
ГруппировкаСтр.Использование = Истина;
ГруппировкаСтр.Представление = Синоним;
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьСтруктуруКомпоновкиПоУмолчаниюПоТаблицеБДЛкс(ПолноеИмяТаблицыБД, НастройкаКомпоновки) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяТаблицыБД);
Если СтрокиРавныЛкс(ТипТаблицы, "ВиртуальнаяТаблица") Тогда
ИмяВиртуальнойТаблицы = ПоследнийФрагментЛкс(ПолноеИмяТаблицыБД);
Иначе
ИмяВиртуальнойТаблицы = "";
КонецЕсли;
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
ЭлементСтруктуры = НастройкаКомпоновки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
////ПолеГруппировки = ЭлементСтруктуры.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
//Если ТипТаблицы = "Справочники" Тогда
// Если ИмяВиртуальнойТаблицы = "" Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "Наименование", "Наименование");
// Иначе
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "Ссылка.Наименование", "Наименование");
// КонецЕсли;
//ИначеЕсли ТипТаблицы = "Документы" Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "Ссылка", "Ссылка");
//ИначеЕсли Истина
// И ЭлементСтруктуры.ПоляГруппировки.ДоступныеПоляПолейГруппировок.Элементы.Количество() > 0
// И ОбъектМД.Измерения.Количество() > 0
//Тогда
// Если ТипТаблицы = "РегистрБухгалтерии" Тогда
// Если ИмяВиртуальнойТаблицы = "" Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "Регистратор", "Регистратор");
// ИначеЕсли ИмяВиртуальнойТаблицы = "ДвиженияССубконто" Тогда
// ЭлементСтруктуры.ПоляГруппировки.Элементы.Удалить(ПолеГруппировки);
// // Группировки по забалансовым
// Для каждого Измерение Из ОбъектМД.Измерения Цикл
// Если Измерение.Балансовый Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, Измерение.Имя, Измерение.Синоним);
// КонецЕсли
// КонецЦикла;
// // ИзмеренияДт
// Для каждого Измерение Из ОбъектМД.Измерения Цикл
// Если НЕ Измерение.Балансовый Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, Измерение.Имя + "Дт", Измерение.Синоним + " Дт");
// КонецЕсли
// КонецЦикла;
// Для К = 1 По 3 Цикл
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "СубконтоДт" + К, "СубконтоДт" + К);
// КонецЦикла;
// // ИзмеренияКт
// Для каждого Измерение Из ОбъектМД.Измерения Цикл
// Если НЕ Измерение.Балансовый Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, Измерение.Имя + "Кт", Измерение.Синоним + " Кт");
// КонецЕсли
// КонецЦикла;
// Для К = 1 По 3 Цикл
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "СубконтоКт" + К, "СубконтоКт" + К);
// КонецЦикла;
// Иначе
// Если ЭлементСтруктуры.ПоляГруппировки.ДоступныеПоляПолейГруппировок.Элементы.Найти("Счет")<> Неопределено Тогда
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "Счет", "Счет");
// Иначе
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "СчетДт", "СчетДт");
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка, "СчетКт", "СчетКт");
// КонецЕсли;
// КонецЕсли;
// Иначе
// ДобавитьПолеГруппировкиЛкс(ПараметрыОтчета.Группировка,
// ОбъектМД.Измерения[0].Имя,
// ОбъектМД.Измерения[0].Синоним);
// КонецЕсли
//КонецЕсли;
ЭлементПорядка = ЭлементСтруктуры.Порядок.Элементы.Добавить(Тип("АвтоЭлементПорядкаКомпоновкиДанных"));
ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
КонецПроцедуры
Процедура УстановитьПараметрыВыводаКомпоновкиПоУмолчаниюЛкс(Знач НастройкаКомпоновки) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
НастройкаКомпоновки.ПараметрыВывода.УстановитьЗначениеПараметра("РасположениеРеквизитов", РасположениеРеквизитовКомпоновкиДанных.Отдельно);
КонецПроцедуры
Функция СоздатьСхемуКомпоновкиТаблицыБДЛкс(ПолноеИмяТаблицыБД, ВыражениеПараметраПериодичность = Неопределено, ДобавитьАвтополеКоличествоСтрок = Истина,
Знач ИндексПараметраПериодичность = Неопределено, Знач ПсевдонимТаблицы = "Т", ИменаВместоПредставлений = Ложь, РасширенноеЗаполнение = Ложь, ЧислоПервых = 0,
Знач СоздатьВычисляемыеПоляТиповЗначений = Ложь) Экспорт
СхемаКомпоновки = СоздатьСхемуКомпоновкиЛкс();
#Если Сервер И Не Сервер Тогда
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
#КонецЕсли
НаборДанных = ДобавитьНаборДанныхЗапросЛкс(СхемаКомпоновки.НаборыДанных, СхемаКомпоновки.ИсточникиДанных[0]);
#Если Сервер И Не Сервер Тогда
НаборДанных = СхемаКомпоновки.НаборыДанных.Добавить();
#КонецЕсли
НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
НаборДанных.Запрос = ПолучитьТекстЗапросаПолейТаблицыБДЛкс(ПолноеИмяТаблицыБД, ИндексПараметраПериодичность, ВыражениеПараметраПериодичность, ПсевдонимТаблицы, Ложь, ЧислоПервых);
Если ДобавитьАвтополеКоличествоСтрок Тогда
ДобавитьВСхемуКомпоновкиАвтополеКоличествоСтрокЛкс(СхемаКомпоновки);
КонецЕсли;
Если Ложь
Или СоздатьВычисляемыеПоляТиповЗначений
Или ИменаВместоПредставлений
Или Метаданные.РежимСовместимости = Метаданные.СвойстваОбъектов.РежимСовместимости.Версия8_1 // Антибаг платформы в режиме совместимости. Предопределенные реквизиты имеют англ. имена полей
Тогда
Построитель = Новый ПостроительЗапроса(НаборДанных.Запрос);
Построитель.ЗаполнитьНастройки();
КонецЕсли;
Если Ложь
Или ИменаВместоПредставлений
Или Метаданные.РежимСовместимости = Метаданные.СвойстваОбъектов.РежимСовместимости.Версия8_1 // Антибаг платформы в режиме совместимости. Предопределенные реквизиты имеют англ. имена полей
Тогда
Для Каждого ДоступноеПоле Из Построитель.ДоступныеПоля Цикл
ПолеНабора = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
ПолеНабора.Поле = ДоступноеПоле.ПутьКДанным;
ПолеНабора.ТипЗначения = ДоступноеПоле.ТипЗначения;
//ПолеНабора.ПутьКДанным = ДоступноеПоле.ПутьКДанным;
Если ИменаВместоПредставлений Тогда
ПолеНабора.Заголовок = ДоступноеПоле.Имя;
Иначе
ПолеНабора.Заголовок = ДоступноеПоле.Представление;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если СоздатьВычисляемыеПоляТиповЗначений Тогда
Для Каждого ДоступноеПоле Из Построитель.ДоступныеПоля Цикл
ПолеНабора = Новый Структура("Поле, ТипЗначения, ПутьКДанным, Заголовок");
ПолеНабора.Поле = ДоступноеПоле.ПутьКДанным;
ПолеНабора.ТипЗначения = ДоступноеПоле.ТипЗначения;
ПолеНабора.ПутьКДанным = ДоступноеПоле.ПутьКДанным;
Если ИменаВместоПредставлений Тогда
ПолеНабора.Заголовок = ДоступноеПоле.Имя;
Иначе
ПолеНабора.Заголовок = ДоступноеПоле.Представление;
КонецЕсли;
ДобавитьВычисляемоеПолеКомпоновкиТипЗначенияЛкс(СхемаКомпоновки, ПолеНабора);
КонецЦикла;
КонецЕсли;
Если РасширенноеЗаполнение Тогда
ДобавитьПоляНабораДанныхЛкс(ПолноеИмяТаблицыБД, СхемаКомпоновки);
ЗаполнитьСтруктуруКомпоновкиПоУмолчаниюПоТаблицеБДЛкс(ПолноеИмяТаблицыБД, СхемаКомпоновки.НастройкиПоУмолчанию);
ДобавитьВыбранныеПоляКомпоновкиПоТаблицеБДЛкс(ПолноеИмяТаблицыБД, СхемаКомпоновки.НастройкиПоУмолчанию);
//БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметрВывода(
// Отчет.КомпоновщикНастроек, "Title", Метаданные[Отчет.ТипДанных][Отчет.ИмяОбъекта].Синоним);
//БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметрВывода(
// Отчет.КомпоновщикНастроек, "TitleOutput", ТипВыводаТекстаКомпоновкиДанных.НеВыводить);
//БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметрВывода(
// Отчет.КомпоновщикНастроек, "FilterOutput", ТипВыводаТекстаКомпоновкиДанных.НеВыводить);
//БухгалтерскиеОтчетыКлиентСервер.УстановитьПараметрВывода(
// Отчет.КомпоновщикНастроек, "DataParametersOutput", ТипВыводаТекстаКомпоновкиДанных.НеВыводить);
КонецЕсли;
Возврат СхемаКомпоновки;
КонецФункции
//.
// Параметры:
// ПолноеИмяОтчета - Строка -
// Возвращаемое значение:
// СхемаКомпоновкиДанных
Функция ОсновнаяСхемаКомпоновкиОтчетаЛкс(Знач ПолноеИмяОтчета) Экспорт
НоваяСхемаКомпоновки = Неопределено;
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяОтчета); // ОбъектМетаданныхОтчет
Если ОбъектМД.ОсновнаяСхемаКомпоновкиДанных <> Неопределено Тогда
НоваяСхемаКомпоновки = Отчеты[ОбъектМД.Имя].ПолучитьМакет(ОбъектМД.ОсновнаяСхемаКомпоновкиДанных.Имя); // СхемаКомпоновкиДанных
КонецЕсли;
Возврат НоваяСхемаКомпоновки;
КонецФункции
Функция ПолучитьТекстЗапросаПолейТаблицыБДЛкс(Знач ПолноеИмяТаблицыБД, Знач ИндексПараметраПериодичность = Неопределено, Знач ВыражениеПараметраПериодичность = Неопределено, ПсевдонимТаблицы = "Т",
Знач БлокироватьПолучениеДанных = Истина, КоличествоПервых = 0, ИменаВыбранныхПолей = Неопределено) Экспорт
// Оптимизация. Все ветки, кроме последней, предотвращают вызов тяжелой функции ОписаниеТаблицыБДЛкс, но не являются логически необходимыми
Если Не ЗначениеЗаполнено(ПолноеИмяТаблицыБД) Тогда
//
ИначеЕсли СтрЧислоВхождений(ПолноеИмяТаблицыБД, ".") = 1 Тогда
Если ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяТаблицыБД) <> Неопределено Тогда
ОписаниеТаблицы = Новый Структура("ИндексПараметраОтбора");
КонецЕсли;
ИначеЕсли СтрокиРавныЛкс(ПолноеИмяТаблицыБД, "Константы") Тогда
ОписаниеТаблицы = Новый Структура("ИндексПараметраОтбора");
ИначеЕсли ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД) = "ДвиженияССубконто" Тогда
ОписаниеТаблицы = Новый Структура("ИндексПараметраОтбора", 2);
Иначе
ОписаниеТаблицы = ОписаниеТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КонецЕсли;
Если ОписаниеТаблицы = Неопределено Тогда
ВызватьИсключение "Таблица БД с именем """ + ПолноеИмяТаблицыБД + """ не найдена";
КонецЕсли;
ПараметрыВиртуальнойТаблицы = "";
Если БлокироватьПолучениеДанных И ОписаниеТаблицы <> Неопределено Тогда
ИндексПараметраОтбора = ОписаниеТаблицы.ИндексПараметраОтбора;
Иначе
ИндексПараметраОтбора = Неопределено;
КонецЕсли;
МаксимальныйИндекс = ИндексПараметраОтбора;
Если ИндексПараметраПериодичность <> Неопределено Тогда
Если МаксимальныйИндекс <> Неопределено Тогда
МаксимальныйИндекс = Макс(МаксимальныйИндекс, ИндексПараметраПериодичность);
Иначе
МаксимальныйИндекс = ИндексПараметраПериодичность;
КонецЕсли;
КонецЕсли;
Если МаксимальныйИндекс <> Неопределено Тогда
МассивВыраженийПараметров = Новый Массив;
Для Счетчик = 0 По МаксимальныйИндекс Цикл
МассивВыраженийПараметров.Добавить("");
КонецЦикла;
Если ИндексПараметраОтбора <> Неопределено Тогда
МассивВыраженийПараметров[ИндексПараметраОтбора] = "ЛОЖЬ";
КонецЕсли;
Если ИндексПараметраПериодичность <> Неопределено Тогда
МассивВыраженийПараметров[ИндексПараметраПериодичность] = ВыражениеПараметраПериодичность;
КонецЕсли;
ПараметрыВиртуальнойТаблицы = СтрСоединитьЛкс(МассивВыраженийПараметров);
КонецЕсли;
Если ЗначениеЗаполнено(ПараметрыВиртуальнойТаблицы) Тогда
ПолноеИмяТаблицыБД = ПолноеИмяТаблицыБД + "(" + ПараметрыВиртуальнойТаблицы + ")";
КонецЕсли;
Если Не ЗначениеЗаполнено(ПсевдонимТаблицы) Тогда
ПсевдонимТаблицы = "Т";
КонецЕсли;
ТекстЗапроса = "ВЫБРАТЬ ";
Если ЗначениеЗаполнено(КоличествоПервых) Тогда
ТекстЗапроса = ТекстЗапроса + "ПЕРВЫЕ " + XMLСтрока(КоличествоПервых) + " ";
КонецЕсли;
Если ИменаВыбранныхПолей <> Неопределено Тогда
ВыраженияПолей = Новый Массив;
Для Каждого ИмяПоля Из ИменаВыбранныхПолей Цикл
ВыраженияПолей.Добавить(ПсевдонимТаблицы + "." + ИмяПоля);
КонецЦикла;
ТекстВыбораПолей = СтрСоединитьЛкс(ВыраженияПолей, ", ");
Иначе
ТекстВыбораПолей = ПсевдонимТаблицы + ".*";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + ТекстВыбораПолей + " ИЗ " + ПолноеИмяТаблицыБД + " КАК " + ПсевдонимТаблицы;
Возврат ТекстЗапроса;
КонецФункции
Функция ДобавитьДоступнуюТаблицуБДЛкс(ДоступныеТаблицыБД, ПолноеИмяТаблицы, ПолноеИмяМД = "", ТипТаблицы = "", ИмяТаблицы = "", Представление = "", СхемаТаблицы = "", ПроверятьУникальность = Ложь,
ОбъектМД = Неопределено, ИндексПараметраОтбора = Неопределено, ФрагментыИмениТаблицы = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ДоступныеТаблицыБД = Обработки.ирКлсПолеТекстаПрограммы.Создать().ДоступныеТаблицы;
#КонецЕсли
Если Не ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда
ПолноеИмяТаблицы = ПолноеИмяМД;
КонецЕсли;
Если ФрагментыИмениТаблицы <> Неопределено Тогда
Фрагменты = ФрагментыИмениТаблицы;
Иначе
Фрагменты = СтрРазделитьЛкс(ПолноеИмяТаблицы);
КонецЕсли;
Если ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД,,,, Фрагменты) Тогда
ТипСсылки = Тип(ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяМД,, Фрагменты));
КонецЕсли;
Если ПроверятьУникальность Тогда
СтрокаТаблицы = ДоступныеТаблицыБД.Найти(НРег(ПолноеИмяТаблицы), "НПолноеИмя");
Иначе
СтрокаТаблицы = Неопределено;
КонецЕсли;
Если СтрокаТаблицы = Неопределено Тогда
СтрокаТаблицы = ДоступныеТаблицыБД.Добавить();
СтрокаТаблицы.Схема = СхемаТаблицы;
СтрокаТаблицы.ПолноеИмяМД = ПолноеИмяМД;
СтрокаТаблицы.ПолноеИмя = ПолноеИмяТаблицы;
СтрокаТаблицы.НПолноеИмя = НРег(СтрокаТаблицы.ПолноеИмя);
СтрокаТаблицы.ИндексПараметраОтбора = ИндексПараметраОтбора;
Если Не ЗначениеЗаполнено(ИмяТаблицы) Тогда
Если Фрагменты.Количество() > 1 Тогда
//Если Не ЗначениеЗаполнено(СхемаТаблицы) Тогда
// СхемаТаблицы = Фрагменты[0];
//КонецЕсли;
НачальныйФрагмент = 2;
Иначе
НачальныйФрагмент = 1;
КонецЕсли;
СтрокаТаблицы.Имя = СтрСоединитьЛкс(Фрагменты, ".",, НачальныйФрагмент);
Иначе
СтрокаТаблицы.Имя = ИмяТаблицы;
КонецЕсли;
СтрокаТаблицы.Представление = Представление;
Если Не ЗначениеЗаполнено(ТипТаблицы) Тогда
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
КонецЕсли;
СтрокаТаблицы.Тип = ТипТаблицы;
Если ТипТаблицы = "Перерасчет" Тогда
МетаРегистрРасчета = ОбъектМД.Родитель();
СтрокаТаблицы.Имя = МетаРегистрРасчета.Имя + "." + СтрокаТаблицы.Имя;
СтрокаТаблицы.Представление = МетаРегистрРасчета.Представление() + "." + СтрокаТаблицы.Представление;
КонецЕсли;
ЗначениеПрава = Истина;
Если ОбъектМД <> Неопределено Тогда
Попытка
ЗначениеПрава = ПравоДоступа("Чтение", ОбъектМД);
Исключение
ЗначениеПрава = Истина;
КонецПопытки;
КонецЕсли;
СтрокаТаблицы.ЕстьДоступ = ЗначениеПрава;
//СтрокаТаблицы.Описание = МетаИсточник.Представление();
СтрокаТаблицы.КоличествоСтрок = "?";
Попытка
СтрокаТаблицы.ТипСсылки = ТипСсылки;
Исключение
// ТЧ.ДоступныеТаблицы
КонецПопытки;
КонецЕсли;
Возврат СтрокаТаблицы;
КонецФункции
// Функция - Найти добавить элемент настроек компоновки по представлению лкс
//
// Параметры:
// ЭлементыНастройки - ВыбранныеПоляКомпоновкиДанных, КоллекцияВыбранныхПолейКомпоновкиДанных, ОтборКомпоновкиДанных, КоллекцияЭлементовОтбораКомпоновкиДанных, КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных -
// Представление - -
// ПроверятьУникальность - -
// ИспользованиеДляНового - -
//
// Возвращаемое значение:
// -
//
Функция НайтиДобавитьЭлементНастроекКомпоновкиПоПредставлениюЛкс(Знач ЭлементыНастройки, Знач Представление = "", Знач ПроверятьУникальность = Истина, Знач ИспользованиеДляНового = Истина) Экспорт
Попытка
ЭлементыНастройки = ЭлементыНастройки.Элементы;
Исключение
КонецПопытки;
Если ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияЭлементовОтбораКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ЭлементОтбораКомпоновкиДанных");
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных") Тогда
ТипЭлемента = Неопределено;
КонецЕсли;
Если ПроверятьУникальность Тогда
ЭлементНастроек = НайтиЭлементКоллекцииЛкс(ЭлементыНастройки, "Представление", Представление, ТипЭлемента);
КонецЕсли;
Если ЭлементНастроек = Неопределено Тогда
Если ТипЭлемента <> Неопределено Тогда
ЭлементНастроек = ЭлементыНастройки.Добавить(ТипЭлемента);
Иначе
ЭлементНастроек = ЭлементыНастройки.Добавить();
КонецЕсли;
ЭлементНастроек.Представление = Представление;
ЭлементНастроек.Использование = ИспользованиеДляНового;
КонецЕсли;
Возврат ЭлементНастроек;
КонецФункции
// Параметры:
// ЭлементыНастройки - ТабличноеПоле, ЭлементыНастроек
Функция НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(Знач ЭлементыНастройки, Знач Поле = "", Знач ПроверятьУникальность = Истина,
Знач ИспользованиеДляНового = Истина, выхСтандартнаяОбработка = Истина, Знач ТипЭлемента = Неопределено) Экспорт
ТабличноеПоле = Неопределено;
#Если Клиент Тогда
Если ТипЗнч(ЭлементыНастройки) = Тип("ТабличноеПоле") Тогда
ТабличноеПоле = ЭлементыНастройки;
ЭлементыНастройки = ТабличноеПоле.Значение;
КонецЕсли;
#КонецЕсли
Если ТипЗнч(Поле) = Тип("Строка") Тогда
Поле = Новый ПолеКомпоновкиДанных(Поле);
КонецЕсли;
Попытка
ЭлементыНастройки = ЭлементыНастройки.Элементы;
Исключение
КонецПопытки;
Если ТипЭлемента = Неопределено Тогда
ТипЭлемента = ТипЭлементаИзТипаКоллекцииКомпоновкиЛкс(ЭлементыНастройки);
КонецЕсли;
Если ПроверятьУникальность Тогда
ЭлементНастроек = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементыНастройки, Поле,, ТипЭлемента);
КонецЕсли;
Если ЭлементНастроек = Неопределено Тогда
Если ТипЭлемента <> Неопределено Тогда
ЭлементНастроек = ЭлементыНастройки.Добавить(ТипЭлемента);
Иначе
ЭлементНастроек = ЭлементыНастройки.Добавить();
КонецЕсли;
ЭлементНастроек.Поле = Поле;
ЭлементНастроек.Использование = ИспользованиеДляНового;
КонецЕсли;
Если ТабличноеПоле <> Неопределено Тогда
ТабличноеПоле.ТекущаяСтрока = ЭлементНастроек;
выхСтандартнаяОбработка = Ложь;
КонецЕсли;
Возврат ЭлементНастроек;
КонецФункции
Процедура ОтключитьНастройкиКомпоновкиЛкс(Знач ГруппаНастроек) Экспорт
Для Каждого ЭлементОтбора Из ГруппаНастроек.Элементы Цикл
ЭлементОтбора.Использование = Ложь;
КонецЦикла;
КонецПроцедуры
Функция ТипЭлементаИзТипаКоллекцииКомпоновкиЛкс(ЭлементыНастройки) Экспорт
Если ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияЭлементовПорядкаКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ЭлементПорядкаКомпоновкиДанных");
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияВыбранныхПолейКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ВыбранноеПолеКомпоновкиДанных");
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияПолейГруппировкиКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ПолеГруппировкиКомпоновкиДанных");
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияЭлементовУсловногоОформленияКомпоновкиДанных") Тогда
ТипЭлемента = Неопределено;
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("КоллекцияЭлементовОтбораКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ЭлементОтбораКомпоновкиДанных");
ИначеЕсли ТипЗнч(ЭлементыНастройки) = Тип("ОформляемыеПоляКомпоновкиДанных") Тогда
ТипЭлемента = Тип("ОформляемоеПолеКомпоновкиДанных");
КонецЕсли;
Возврат ТипЭлемента;
КонецФункции
// .
// Параметры:
// ЭлементыНастройки - КоллекцияЭлементовОтбораКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных
// Поле - ПолеКомпоновкиДанных, Строка - если не заполнено, то подходит любое имя поля
// ВсеНайденныеПоля - Массив - если Массив, то находим все поля
Функция НайтиЭлементНастроекКомпоновкиПоПолюЛкс(Знач ЭлементыНастройки, Знач Поле = Неопределено, Знач ТолькоВключенный = Ложь, ТипЭлементаРекурсия = Неопределено, ВсеНайденныеПоля = Неопределено) Экспорт
Если ТипЗнч(Поле) = Тип("Строка") Тогда
Поле = Новый ПолеКомпоновкиДанных(Поле);
КонецЕсли;
Если ТипЭлементаРекурсия = Неопределено Тогда
ТипЭлементаРекурсия = ТипЭлементаИзТипаКоллекцииКомпоновкиЛкс(ЭлементыНастройки);
КонецЕсли;
//ИскомоеПолеЗаполнено = ЗначениеЗаполнено(Поле); // Не поддерживается в 8.2 http://www.hostedredmine.com/issues/878299
ИскомоеПолеЗаполнено = ЗначениеЗаполнено("" + Поле);
Для Каждого ЭлементНастроек Из ЭлементыНастройки Цикл
Если Истина
И ТипЭлементаРекурсия <> Неопределено
И ТипЗнч(ЭлементНастроек) <> ТипЭлементаРекурсия
Тогда
Попытка
ДочерниеЭлементыНастройки = ЭлементНастроек.Элементы;
Исключение
ДочерниеЭлементыНастройки = Неопределено;
КонецПопытки;
Если ДочерниеЭлементыНастройки <> Неопределено Тогда
НайденныйЭлемент = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ДочерниеЭлементыНастройки, Поле, ТолькоВключенный, ТипЭлементаРекурсия, ВсеНайденныеПоля);
Если НайденныйЭлемент <> Неопределено Тогда
Если ВсеНайденныеПоля <> Неопределено Тогда
ВсеНайденныеПоля.Добавить(НайденныйЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иначе
Если ТипЭлементаРекурсия = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
ПолеЭлемента = ЭлементНастроек.ЛевоеЗначение;
Иначе //! Если ТипЗнч(ЭлементНастроек) = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
ПолеЭлемента = ЭлементНастроек.Поле;
КонецЕсли;
Если Истина
И (Ложь
Или ПолеЭлемента = Поле
Или Не ИскомоеПолеЗаполнено)
И (Ложь
Или Не ТолькоВключенный
Или ЭлементНастроек.Использование)
Тогда
НайденныйЭлемент = ЭлементНастроек;
Если ВсеНайденныеПоля <> Неопределено Тогда
ВсеНайденныеПоля.Добавить(НайденныйЭлемент);
Иначе
Прервать;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ВсеНайденныеПоля <> Неопределено И ВсеНайденныеПоля.Количество() > 0 Тогда
НайденныйЭлемент = ВсеНайденныеПоля[0];
КонецЕсли;
Возврат НайденныйЭлемент;
КонецФункции
// Функция - Найти элемент условного оформления по полю лкс
//
// Параметры:
// УсловноеОформление - -
// Поле - -
// ТолькоВключенный - -
// выхЭлементПоля - Соответствие, * - если Соответствие, то оно очищается и в нее помещаются все найденные пары ЭлементПоля-ЭлементОформления
//
// Возвращаемое значение:
// -
//
Функция НайтиЭлементУсловногоОформленияПоПолюЛкс(Знач УсловноеОформление, Знач Поле, Знач ТолькоВключенный = Ложь, выхЭлементПоля = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
УсловноеОформление = Новый НастройкиКомпоновкиДанных;
УсловноеОформление = УсловноеОформление.УсловноеОформление;
выхЭлементПоля = Новый Соответствие;
#КонецЕсли
Если ТипЗнч(выхЭлементПоля) = Тип("Соответствие") Тогда
выхЭлементПоля.Очистить();
КонецЕсли;
Для Каждого ЭлементОформления Из УсловноеОформление.Элементы Цикл
ЭлементПоля = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементОформления.Поля.Элементы, Поле, ТолькоВключенный);
Если ЭлементПоля <> Неопределено Тогда
Если ТипЗнч(выхЭлементПоля) = Тип("Соответствие") Тогда
выхЭлементПоля.Вставить(ЭлементПоля, ЭлементОформления);
Иначе
выхЭлементПоля = ЭлементПоля;
Возврат ЭлементОформления;
КонецЕсли;
КонецЕсли;
ЭлементОтбора = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементОформления.Отбор.Элементы, Поле, ТолькоВключенный);
Если ЭлементОтбора <> Неопределено Тогда
Если ТипЗнч(выхЭлементПоля) = Тип("Соответствие") Тогда
выхЭлементПоля.Вставить(ЭлементОтбора, ЭлементОформления);
Иначе
выхЭлементПоля = ЭлементОтбора;
Возврат ЭлементОформления;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ТипЗнч(выхЭлементПоля) = Тип("Соответствие") Тогда
Возврат выхЭлементПоля;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Функция НайтиЭлементНастроекКомпоновкиПоПолюПоВсейСтруктуреЛкс(Знач КорневойЭлементСтруктуры, Знач Поле, Знач ТолькоВключенный = Ложь, Знач ТипНастроек = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
КорневойЭлементСтруктуры = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
ВсеГруппировки = ВсеГруппировкиКомпоновкиЛкс(КорневойЭлементСтруктуры.Структура);
ВсеГруппировки.Добавить(КорневойЭлементСтруктуры);
Результат = Новый Структура("ЭлементСтруктуры, ЭлементНастройки, ЭлементНастройки2");
Для Каждого ЭлементСтруктуры Из ВсеГруппировки Цикл
ПолеНайдено = Ложь;
Если Истина
И Не ПолеНайдено
И ТипЗнч(ЭлементСтруктуры) <> Тип("НастройкиКомпоновкиДанных")
И (Ложь
Или ТипНастроек = Неопределено
Или ТипНастроек = Тип("ПолеГруппировкиКомпоновкиДанных"))
Тогда
ПолеГруппировки = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементСтруктуры.ПоляГруппировки.Элементы, Поле, ТолькоВключенный);
Если ПолеГруппировки <> Неопределено Тогда
Результат.ЭлементСтруктуры = ЭлементСтруктуры;
Результат.ЭлементНастройки = ПолеГруппировки;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Если Истина
И Не ПолеНайдено
И (Ложь
Или ТипНастроек = Неопределено
Или ТипНастроек = Тип("ВыбранныеПоляКомпоновкиДанных"))
Тогда
ВыбранноеПоле = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементСтруктуры.Выбор.Элементы, Поле, ТолькоВключенный);
Если ВыбранноеПоле <> Неопределено Тогда
Результат.ЭлементСтруктуры = ЭлементСтруктуры;
Результат.ЭлементНастройки = ВыбранноеПоле;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Если Истина
И Не ПолеНайдено
И (Ложь
Или ТипНастроек = Неопределено
Или ТипНастроек = Тип("ПорядокКомпоновкиДанных"))
Тогда
ЭлементПорядка = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементСтруктуры.Порядок.Элементы, Поле, ТолькоВключенный);
Если ЭлементПорядка <> Неопределено Тогда
Результат.ЭлементСтруктуры = ЭлементСтруктуры;
Результат.ЭлементНастройки = ЭлементПорядка;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Если Истина
И Не ПолеНайдено
И (Ложь
Или ТипНастроек = Неопределено
Или ТипНастроек = Тип("ОтборКомпоновкиДанных"))
Тогда
ЭлементОтбора = НайтиЭлементНастроекКомпоновкиПоПолюЛкс(ЭлементСтруктуры.Отбор.Элементы, Поле, ТолькоВключенный);
Если ЭлементОтбора <> Неопределено Тогда
Результат.ЭлементСтруктуры = ЭлементСтруктуры;
Результат.ЭлементНастройки = ЭлементОтбора;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Если Истина
И Не ПолеНайдено
И (Ложь
Или ТипНастроек = Неопределено
Или ТипНастроек = Тип("УсловноеОформлениеКомпоновкиДанных"))
Тогда
ЭлементПоля = Неопределено;
ЭлементОФормления = НайтиЭлементУсловногоОформленияПоПолюЛкс(ЭлементСтруктуры.УсловноеОформление, Поле, ТолькоВключенный, ЭлементПоля);
Если ЭлементОФормления <> Неопределено Тогда
Результат.ЭлементСтруктуры = ЭлементСтруктуры;
Результат.ЭлементНастройки = ЭлементОФормления;
Результат.ЭлементНастройки2 = ЭлементПоля;
Возврат Результат;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция ВсеГруппировкиКомпоновкиЛкс(Группировки, Знач ТолькоВключенный = Ложь, МассивЭлементов = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Группировки = Новый НастройкиКомпоновкиДанных;
Группировки = Группировки.Структура;
#КонецЕсли
Если МассивЭлементов = Неопределено Тогда
МассивЭлементов = Новый Массив;
КонецЕсли;
Для Каждого Группировка Из Группировки Цикл
ТипЭлемента = ТипЗнч(Группировка);
Если Ложь
Или ТипЭлемента = Тип("ГруппировкаДиаграммыКомпоновкиДанных")
Или ТипЭлемента = Тип("ГруппировкаКомпоновкиДанных")
Или ТипЭлемента = Тип("ГруппировкаТаблицыКомпоновкиДанных")
Тогда
ВсеГруппировкиКомпоновкиЛкс(Группировка.Структура, ТолькоВключенный, МассивЭлементов);
Если Ложь
Или ТолькоВключенный
Или Группировка.Использование
Тогда
МассивЭлементов.Добавить(Группировка);
КонецЕсли;
ИначеЕсли ТипЭлемента = Тип("ТаблицаКомпоновкиДанных") Тогда
ВсеГруппировкиКомпоновкиЛкс(Группировка.Строки, ТолькоВключенный, МассивЭлементов);
ВсеГруппировкиКомпоновкиЛкс(Группировка.Колонки, ТолькоВключенный, МассивЭлементов);
ИначеЕсли ТипЭлемента = Тип("ДиаграммаКомпоновкиДанных") Тогда
ВсеГруппировкиКомпоновкиЛкс(Группировка.Серии, ТолькоВключенный, МассивЭлементов);
ВсеГруппировкиКомпоновкиЛкс(Группировка.Точки, ТолькоВключенный, МассивЭлементов);
Иначе
Продолжить;
КонецЕсли;
КонецЦикла;
Возврат МассивЭлементов;
КонецФункции
// .
// Параметры:
// ВыбранныеПоля - ВыбранныеПоляКомпоновкиДанных -
// ТолькоВключенные - -
// МассивРезультата - -
// ВернутьТолькоПоля - Булево - вместо выбранных полей вернуть поля
//
// Возвращаемое значение:
// -
//
Функция ВсеВыбранныеПоляГруппировкиКомпоновкиЛкс(Знач ВыбранныеПоля, Знач ТолькоВключенные = Ложь, МассивРезультата = Неопределено, ВернутьТолькоПоля = Ложь) Экспорт
Если МассивРезультата <> Неопределено Тогда
Результат = МассивРезультата;
Иначе
Результат = Новый Массив();
КонецЕсли;
Для Каждого ВыбранноеПоле Из ВыбранныеПоля.Элементы Цикл
Если ТипЗнч(ВыбранноеПоле) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных") Тогда
РезультатВложенный = ВсеВыбранныеПоляГруппировкиКомпоновкиЛкс(ВыбранноеПоле, ТолькоВключенные, Результат, ВернутьТолькоПоля);
ИначеЕсли ТипЗнч(ВыбранноеПоле) = Тип("АвтоВыбранноеПолеКомпоновкиДанных") Тогда
Пустышка = 0;
ИначеЕсли ТипЗнч(ВыбранноеПоле) = Тип("ВыбранноеПолеКомпоновкиДанных") Тогда
Если Ложь
Или Не ТолькоВключенные
Или ВыбранноеПоле.Использование
Тогда
Если ВернутьТолькоПоля Тогда
Результат.Добавить(ВыбранноеПоле.Поле);
Иначе
Результат.Добавить(ВыбранноеПоле);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолеИзОписанияОшибкиЛкс(ОписаниеОшибки) Экспорт
// {Обработка.ирКонсольКомпоновокДанных.Форма.Форма.Форма(503)}: Ошибка при вызове метода контекста (Выполнить): Ошибка компоновки макета: Поле не найдено "НомерВерсииПлатформы"
Результат = ТекстМеждуМаркерамиЛкс(ОписаниеОшибки, "Поле не найдено """, """", Ложь);
Возврат Результат;
КонецФункции
// Функция - Найти добавить элемент структуры группировка компоновки лкс
//
// Параметры:
// Группировки - КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных, КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных -
// Поле - -
// Добавлять - -
// НовоеИспользование - -
//
// Возвращаемое значение:
// -
//
Функция НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(Знач Группировки, Знач Поле = "", Добавлять = Истина, НовоеИспользование = Истина) Экспорт
Если ТипЗнч(Поле) = Тип("Строка") Тогда
Поле = Новый ПолеКомпоновкиДанных(Поле);
КонецЕсли;
Группировка = НайтиГруппировкуКомпоновкиПоПолюЛкс(Группировки, Поле);
ЭлементСуществует = Группировка <> Неопределено;
Если Истина
И Не ЭлементСуществует
И Добавлять
Тогда
Если ТипЗнч(Группировки) = Тип("КоллекцияЭлементовСтруктурыНастроекКомпоновкиДанных") Тогда
Группировка = Группировки.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Иначе //Если ТипЗнч(Группировки) = Тип("КоллекцияЭлементовСтруктурыТаблицыКомпоновкиДанных") Тогда
Группировка = Группировки.Добавить();
КонецЕсли;
Группировка.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
Группировка.Порядок.Элементы.Добавить(Тип("АвтоЭлементПорядкаКомпоновкиДанных"));
Если "" + Поле <> "" Тогда
ПолеГруппировки = Группировка.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
ПолеГруппировки.Поле = Поле;
КонецЕсли;
ЭлементСуществует = Истина;
КонецЕсли;
Если ЭлементСуществует Тогда
Если НовоеИспользование <> Неопределено Тогда
Группировка.Использование = НовоеИспользование;
КонецЕсли;
Результат = Группировка;
Иначе
Результат = Неопределено;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция НайтиГруппировкуКомпоновкиПоПолюЛкс(Знач Группировки, Знач Поле) Экспорт
ГруппировкаПоИскомомуПолю = Неопределено;
Для Каждого Группировка Из Группировки Цикл
ТипЭлемента = Тип(Группировка);
Если ТипЭлемента = Тип("ТаблицаКомпоновкиДанных") Тогда
ИначеЕсли ТипЭлемента = Тип("ДиаграммаКомпоновкиДанных") Тогда
Иначе
Поля = Группировка.ПоляГруппировки.Элементы;
Если Ложь
Или (Истина
И "" + Поле = ""
И Поля.Количество() = 0)
Или (Истина
И Поля.Количество() = 1
И ТипЗнч(Поля[0]) = Тип("ПолеГруппировкиКомпоновкиДанных")
И Поля[0].Поле = Поле)
Тогда
ГруппировкаПоИскомомуПолю = Группировка;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ГруппировкаПоИскомомуПолю;
КонецФункции
// Функция - Найти элемент отбора компоновки лкс
//
// Параметры:
// Отбор - Отбор, ОтборКомпоновкиДанных -
// ИменаПолей - -
// НайденныеЭлементы - Соответствие* -
// ТолькоВключенныеНаРавенствоЗначению - -
// ВключатьПодчиненные - -
//
// Возвращаемое значение:
// Соответствие, ЭлементОтбора, ЭлементОтбораКомпоновкиДанных -
//
Функция НайтиЭлементОтбораЛкс(Знач Отбор, Знач ИменаПолей = Неопределено, Знач НайденныеЭлементы = Неопределено, Знач ТолькоВключенныеНаРавенствоЗначению = Ложь,
Знач ВключатьПодчиненные = Ложь, Знач МассивПолейРекурсия = Неопределено, Знач ТолькоВключенные = Ложь) Экспорт
Если ТипЗнч(Отбор) = Тип("Отбор") Тогда
Возврат Отбор.Найти(ИменаПолей);
КонецЕсли;
Если ТипЗнч(Отбор) = Тип("ОтборКомпоновкиДанных") Тогда
ЭлементыОтбора = Отбор.Элементы;
Иначе
ЭлементыОтбора = Отбор;
КонецЕсли;
Если МассивПолейРекурсия = Неопределено Тогда
Если ТипЗнч(ИменаПолей) = Тип("Строка") Тогда
МассивИменПолей = СтрРазделитьЛкс(ИменаПолей, ",", Истина);
Иначе
МассивИменПолей = ИменаПолей;
КонецЕсли;
МассивПолейРекурсия = Новый Массив;
Если МассивИменПолей <> Неопределено Тогда
Для Каждого ИмяПоля Из МассивИменПолей Цикл
МассивПолейРекурсия.Добавить(Новый ПолеКомпоновкиДанных(ИмяПоля));
КонецЦикла;
КонецЕсли;
КонецЕсли;
МассивПолейПуст = МассивПолейРекурсия.Количество() = 0;
Если НайденныеЭлементы = Неопределено Тогда
НайденныеЭлементы = Новый Соответствие;
КонецЕсли;
Для Каждого ЭлементОтбора ИЗ ЭлементыОтбора Цикл
Если Истина
И ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И (Ложь
Или Не ТолькоВключенные
Или ЭлементОтбора.Использование)
И (Ложь
Или Не ТолькоВключенныеНаРавенствоЗначению
Или (Истина
И ЭлементОтбора.Использование
И ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно
И ТипЗнч(ЭлементОтбора.ЛевоеЗначение) = Тип("ПолеКомпоновкиДанных")
И ТипЗнч(ЭлементОтбора.ПравоеЗначение) <> Тип("ПолеКомпоновкиДанных")))
Тогда
Если Ложь
Или МассивПолейПуст
Или МассивПолейРекурсия.Найти(ЭлементОтбора.ЛевоеЗначение) <> Неопределено
Тогда
НайденныеЭлементы.Вставить("" + ЭлементОтбора.ЛевоеЗначение, ЭлементОтбора);
КонецЕсли;
ИначеЕсли Истина
И ВключатьПодчиненные
И ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных")
Тогда
НайтиЭлементОтбораЛкс(ЭлементОтбора.Элементы,, НайденныеЭлементы, ТолькоВключенныеНаРавенствоЗначению, ВключатьПодчиненные, МассивПолейРекурсия, ТолькоВключенные);
КонецЕсли;
КонецЦикла;
Если МассивИменПолей <> Неопределено И МассивИменПолей.Количество() = 1 Тогда
Результат = НайденныеЭлементы[МассивИменПолей[0]];
Иначе
Результат = НайденныеЭлементы;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОтключитьЭлементОтбораРавноЛкс(Знач Отбор, Знач ИмяКолонки) Экспорт
ЭлементОтбора = НайтиЭлементОтбораЛкс(Отбор, ИмяКолонки,, Истина); // ЭлементОтбораКомпоновкиДанных
Если ЭлементОтбора <> Неопределено Тогда
ЭлементОтбора.Использование = Ложь;
КонецЕсли;
Возврат ЭлементОтбора;
КонецФункции
// При ИспользованиеДляНового=Ложь для существующего элемента отбора не меняется правое значение
Функция НайтиДобавитьЭлементОтбораКомпоновкиЛкс(Знач НастройкаИлиОтборИлиЭлементы, Знач Поле = "", Знач Значение = Неопределено, Знач Сравнение = "", Знач ДоступныеПоляОтбора = Неопределено,
Знач ПроверятьУникальность = Истина, Знач ИспользованиеДляНового = Истина, Знач СообщитьОДобавлении = Ложь, Знач НазначитьПользовательскийИдентификатор = Ложь) Экспорт
ОтборИлиЭлементы = НастройкаИлиОтборИлиЭлементы;
Если ТипЗнч(НастройкаИлиОтборИлиЭлементы) = Тип("НастройкиКомпоновкиДанных") Тогда
ОтборИлиЭлементы = НастройкаИлиОтборИлиЭлементы.Отбор;
КонецЕсли;
Если ТипЗнч(ОтборИлиЭлементы) = Тип("ОтборКомпоновкиДанных") Тогда
ДоступныеПоляОтбора = ОтборИлиЭлементы.ДоступныеПоляОтбора;
ЭлементыОтбора = ОтборИлиЭлементы.Элементы;
ИначеЕсли ТипЗнч(ОтборИлиЭлементы) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
ЭлементыОтбора = ОтборИлиЭлементы.Элементы;
ИначеЕсли ТипЗнч(ОтборИлиЭлементы) = Тип("КоллекцияЭлементовОтбораКомпоновкиДанных") Тогда // Проверка нужна для анализатора кода
ЭлементыОтбора = ОтборИлиЭлементы;
КонецЕсли;
Если ТипЗнч(Поле) = Тип("Строка") Тогда
Поле = Новый ПолеКомпоновкиДанных(Поле);
КонецЕсли;
Если ПроверятьУникальность Тогда
ЭлементОтбора = НайтиЭлементОтбораЛкс(ЭлементыОтбора, "" + Поле); // ЭлементОтбораКомпоновкиДанных
КонецЕсли;
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = ЭлементыОтбора.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.Использование = ИспользованиеДляНового;
ЭлементОтбора.ЛевоеЗначение = Поле;
ИначеЕсли Не ИспользованиеДляНового Тогда // Опасно
Возврат ЭлементОтбора;
КонецЕсли;
Если ТипЗнч(Значение) = Тип("ФиксированныйМассив") Тогда
Значение = Новый Массив(Значение);
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Массив") Тогда
СписокЗначений = Новый СписокЗначений;
СписокЗначений.ЗагрузитьЗначения(Значение);
Значение = СписокЗначений;
КонецЕсли;
// Вид сравнения
Если ТипЗнч(Сравнение) = Тип("ВидСравненияКомпоновкиДанных") Тогда
Иначе
Если ТипЗнч(Значение) = Тип("СписокЗначений") Тогда
Сравнение = ВидСравненияКомпоновкиДанных.ВСписке;
Иначе
Сравнение = ВидСравненияКомпоновкиДанных.Равно;
КонецЕсли;
КонецЕсли;
Если Истина
И Сравнение = ВидСравненияКомпоновкиДанных.Равно
И ДоступныеПоляОтбора <> Неопределено
И ТипЗнч(Значение) <> Тип("ПолеКомпоновкиДанных")
Тогда
ДоступноеПолеОтбора = ДоступныеПоляОтбора.НайтиПоле(Поле);
Если ДоступноеПолеОтбора <> Неопределено Тогда
Значение = ДоступноеПолеОтбора.ТипЗначения.ПривестиЗначение(Значение);
Если ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ДоступноеПолеОтбора.ТипЗначения) Тогда
Сравнение = ВидСравненияКомпоновкиДанных.Содержит;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ЭлементОтбора.ВидСравнения = Сравнение;
ЭлементОтбора.ПравоеЗначение = Значение;
Если НазначитьПользовательскийИдентификатор Тогда
ПроверитьВключитьЭлементНастроекКомпоновкиВПользовательскиеНастройки(ЭлементОтбора);
КонецЕсли;
Если СообщитьОДобавлении Тогда
СообщитьЛкс(СтрШаблонИменЛкс("В отбор установлен элемент %1",, ПредставлениеЭлементаОтбораЛкс(ЭлементОтбора)));
КонецЕсли;
Возврат ЭлементОтбора;
КонецФункции
Функция ДобавитьГруппуОтбораЛкс(Знач НастройкаКомпоновкиИлиГруппа, Знач ТипГруппы = Неопределено) Экспорт
Если ТипГруппы = Неопределено Тогда
ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
КонецЕсли;
ГруппаИли = НастройкаКомпоновкиИлиГруппа.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппы;
Возврат ГруппаИли;
КонецФункции
// Функция - Все элементы иерарихии настроек компоновки лкс
//
// Параметры:
// ГруппаНастроекКомпоновки - ОтборКомпоновкиДанных, ВыбранныеПоляКомпоновкиДанных, СтруктураНастроекКомпоновкиДанных -
// ТолькоВключенные - Булево -
// БезГрупп - Булево -
// Результат - Массив, Неопределено -
//
// Возвращаемое значение:
// Массив Из Произвольный -
//
Функция ВсеЭлементыИерарихииНастроекКомпоновкиЛкс(Знач ГруппаНастроекКомпоновки, Знач ТолькоВключенные = Истина, Знач БезГрупп = Ложь, Результат = Неопределено) Экспорт
Если ЛиКоллекцияЛкс(ГруппаНастроекКомпоновки) Тогда
ЭлементыГруппы = ГруппаНастроекКомпоновки;
Иначе
ЭлементыГруппы = ГруппаНастроекКомпоновки.Элементы;
КонецЕсли;
Если Результат = Неопределено Тогда
Результат = Новый Массив;
КонецЕсли;
Для Каждого ЭлементГруппы ИЗ ЭлементыГруппы Цикл
ЭтоГруппа = Ложь
Или ТипЗнч(ЭлементГруппы) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных")
Или ТипЗнч(ЭлементГруппы) = Тип("ГруппаВыбранныхПолейКомпоновкиДанных");
Если Истина
И (Не ТолькоВключенные Или ЭлементГруппы.Использование)
И Не (ЭтоГруппа И БезГрупп)
Тогда
Результат.Добавить(ЭлементГруппы);
КонецЕсли;
Если ЭтоГруппа Тогда
ВсеЭлементыИерарихииНастроекКомпоновкиЛкс(ЭлементГруппы.Элементы, ТолькоВключенные, БезГрупп, Результат);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ЛиКоллекцияКомпоновкиЛкс(Значение) Экспорт
// Пока грязно
Попытка
Пустышка = Значение.Количество();
Исключение
Попытка
Пустышка = Значение.Элементы;
Возврат Истина;
Исключение
КонецПопытки;
КонецПопытки;
Возврат Ложь;
КонецФункции
Функция ЛиЕстьНеактуальныеПоляВГруппеОтбораЛкс(Знач КомпоновщикНастроек, Знач ГруппаОтбора) Экспорт
#Если Сервер И Не Сервер Тогда
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
ГруппаОтбора = КомпоновщикНастроек.Настройки.Отбор;
#КонецЕсли
Результат = Ложь;
Для Каждого ЭлементОтбора Из ГруппаОтбора.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
Результат = ЛиЕстьНеактуальныеПоляВГруппеОтбораЛкс(КомпоновщикНастроек, ЭлементОтбора);
Иначе
Результат = КомпоновщикНастроек.Настройки.ДоступныеПоляВыбора.НайтиПоле(ЭлементОтбора.ЛевоеЗначение) = Неопределено;
КонецЕсли;
Если Результат Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ДоступныеПоляКоллекцииНастроекКомпоновкиЛкс(Знач КоллекцияНастроек) Экспорт
Если ТипЗнч(КоллекцияНастроек) = Тип("ВыбранныеПоляКомпоновкиДанных") Тогда
ДоступныеПоля = КоллекцияНастроек.ДоступныеПоляВыбора;
ИначеЕсли ТипЗнч(КоллекцияНастроек) = Тип("ОтборКомпоновкиДанных") Тогда
ДоступныеПоля = КоллекцияНастроек.ДоступныеПоляОтбора;
ИначеЕсли ТипЗнч(КоллекцияНастроек) = Тип("ПорядокКомпоновкиДанных") Тогда
ДоступныеПоля = КоллекцияНастроек.ДоступныеПоляПорядка;
ИначеЕсли ТипЗнч(КоллекцияНастроек) = Тип("ПоляГруппировкиКомпоновкиДанных") Тогда
ДоступныеПоля = КоллекцияНастроек.ДоступныеПоляПолейГруппировок;
КонецЕсли;
Возврат ДоступныеПоля;
КонецФункции
Функция ПредставлениеЭлементаОтбораЛкс(ЭлементОтбора) Экспорт
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбора") Тогда
Результат = "" + ЭлементОтбора.Представление + " " + ЭлементОтбора.ВидСравнения + " " + ЭлементОтбора.Значение;
Иначе
Результат = "" + ЭлементОтбора.ЛевоеЗначение + " " + ЭлементОтбора.ВидСравнения + " " + ЭлементОтбора.ПравоеЗначение;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция НайтиДоступноеПолеКомпоновкиПоИмениКолонкиЛкс(Знач ДоступныеПоля, Знач ДанныеКолонки) Экспорт
#Если Сервер И Не Сервер Тогда
ДоступныеПоля = Новый НастройкиКомпоновкиДанных;
ДоступныеПоля = ДоступныеПоля.ДоступныеПоляОтбора;
#КонецЕсли
ДоступноеПоле = ДоступныеПоля.НайтиПоле(Новый ПолеКомпоновкиДанных(ДанныеКолонки));
Если ДоступноеПоле = Неопределено Тогда
ДоступноеПоле = ДоступныеПоля.НайтиПоле(Новый ПолеКомпоновкиДанных(СтрЗаменить(ДанныеКолонки, "_", ".")));
КонецЕсли;
Возврат ДоступноеПоле;
КонецФункции
// Функция - Найти доступное поле компоновки по полному имени лкс
//
// Параметры:
// ТекущееПоле - ДоступноеПолеКомпоновкиДанных -
// ПолноеИмяПоля - -
// ДопустимоеКоличествоТипов - -
// МожноРодителя - -
// ПрефиксПараметра - -
//
// Возвращаемое значение:
// ДоступноеПолеКомпоновкиДанных -
//
Функция НайтиДоступноеПолеКомпоновкиПоПолномуИмениЛкс(Знач ТекущееПоле, Знач ПолноеИмяПоля, Знач ДопустимоеКоличествоТипов = 100, Знач МожноРодителя = Ложь, Знач ПрефиксПараметра = "&") Экспорт
ПолноеИмяПоля = НРег(ПолноеИмяПоля);
Фрагменты = СтрРазделитьЛкс(ПолноеИмяПоля);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
ТекущееПоле = Новый НастройкиКомпоновкиДанных;
ТекущееПоле = ГруппаДоступныхПолей.ДоступныеПоляВыбора;
#КонецЕсли
// TODO Конструктор запроса. Надо еще папку "ПараметрыДанных" заменить на свою, т.к. системная одноуровневая
Если Лев(Фрагменты[0], 1) = "(" Тогда
Фрагменты[0] = СокрЛП(УдалитьВнешниеСкобкиВыраженияЛкс(Фрагменты[0]));
КонецЕсли;
Если Лев(Фрагменты[0], 1) = ПрефиксПараметра Тогда // Длину префикса параметра для ускорения считаем 1
Фрагменты[0] = Сред(Фрагменты[0], СтрДлина(ПрефиксПараметра) + 1);
Фрагменты.Вставить(0, "ПараметрыДанных");
КонецЕсли;
ТекущееИмяПоля = "";
Для Каждого Фрагмент Из Фрагменты Цикл
Если Фрагмент = "ссылка" И Найти(ТекущееИмяПоля, ".") > 0 Тогда
// Дочерние поля "ссылка" в дереве доступных полей компоновки отсутствуют
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(ТекущееИмяПоля) Тогда
ТекущееИмяПоля = ТекущееИмяПоля + ".";
КонецЕсли;
ТекущееИмяПоля = ТекущееИмяПоля + Фрагмент;
НовоеТекущееПоле = ТекущееПоле.Элементы.Найти(Новый ПолеКомпоновкиДанных(ТекущееИмяПоля));
Если Истина
И ТекущееИмяПоля <> ПолноеИмяПоля
И (Ложь
Или НовоеТекущееПоле = Неопределено
Или НовоеТекущееПоле.ТипЗначения.Типы().Количество() > ДопустимоеКоличествоТипов)
Тогда
Если Ложь
Или Не МожноРодителя
Или ТипЗнч(ТекущееПоле) = Тип("ДоступныеПоляКомпоновкиДанных")
Тогда
ТекущееПоле = Неопределено;
КонецЕсли;
Прервать;
КонецЕсли;
ТекущееПоле = НовоеТекущееПоле;
КонецЦикла;
Возврат ТекущееПоле;
КонецФункции
// .
// Параметры:
// Таблица - ТаблицаЗначений, ТабличнаяЧасть, НаборЗаписей
Функция НеуникальныеЗначенияКолонкиТаблицыЛкс(Таблица, ИмяКолонки, ИгнорироватьРегистрДляПростогоСтрокогоТипа = Истина, ОтборСтрок = Неопределено) Экспорт
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
КопияТаблицы = Таблица.Скопировать(ОтборСтрок, ИмяКолонки);
Иначе
//! Таблица = 0 // ТабличнаяЧасть
КопияТаблицы = Таблица.Выгрузить(ОтборСтрок, ИмяКолонки);
КонецЕсли;
Типы = КопияТаблицы.Колонки[ИмяКолонки].ТипЗначения.Типы();
Если Истина
И Типы.Количество() = 1
И Типы[0] = Тип("Строка")
И ИгнорироватьРегистрДляПростогоСтрокогоТипа
Тогда
ИмяКолонкиНрег = ИмяКолонки + "_Нрег777233464645";
КопияТаблицы.Колонки.Добавить(ИмяКолонкиНрег);
Для Каждого СтрокаКопииТаблицы Из КопияТаблицы Цикл
СтрокаКопииТаблицы[ИмяКолонкиНрег] = НРег(СтрокаКопииТаблицы[ИмяКолонки]);
КонецЦикла;
Иначе
ИмяКолонкиНрег = ИмяКолонки;
КонецЕсли;
КолонкаКоличества = ИмяКолонки + "7773534765"; //гарантировано уникальное имя колонки
КопияТаблицы.Колонки.Добавить(КолонкаКоличества);
КопияТаблицы.ЗаполнитьЗначения(1, КолонкаКоличества);
КопияТаблицы.Свернуть(ИмяКолонкиНрег, КолонкаКоличества);
КопияТаблицы.Сортировать(КолонкаКоличества + " Убыв");
МассивНеуникальных = Новый Массив;
Для Индекс = 0 По КопияТаблицы.Количество() - 1 Цикл
СтрокаКопии = КопияТаблицы[Индекс];
Если СтрокаКопии[КолонкаКоличества] > 1 Тогда
МассивНеуникальных.Добавить(СтрокаКопии[ИмяКолонкиНрег]);
КонецЕсли;
КонецЦикла;
Возврат МассивНеуникальных;
КонецФункции
// .
// Параметры:
// Таблица - ТаблицаЗначений, ТабличнаяЧасть, НаборЗаписей
// ИменаКолонок - Строка, Массив - имена колонок (в строке через запятую)
// ИсключаяОтбор - Структура - не учитывать строки по этому отбору
Функция НеуникальныеКлючиТаблицыЛкс(Таблица, Знач ИменаКолонок = "", ИсключаяОтбор = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
Если ТипЗнч(ИменаКолонок) = Тип("Массив") Тогда
ИменаКолонок = СтрСоединитьЛкс(ИменаКолонок);
ИначеЕсли Не ЗначениеЗаполнено(ИменаКолонок) Тогда
ИменаКолонок = "";
Для Каждого КолонкаТаблицы Из Таблица.Колонки Цикл
Если Ложь
Или КолонкаТаблицы.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений"))
Или КолонкаТаблицы.ТипЗначения.СодержитТип(Тип("ХранилищеЗначения"))
Тогда
Продолжить;
КонецЕсли;
Если ИменаКолонок <> "" Тогда
ИменаКолонок = ИменаКолонок + ",";
КонецЕсли;
ИменаКолонок = ИменаКолонок + КолонкаТаблицы.Имя;
КонецЦикла;
КонецЕсли;
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
КопияТаблицы = Таблица.Скопировать(, ИменаКолонок);
Иначе
//! Таблица = 0 // ТабличнаяЧасть
КопияТаблицы = Таблица.Выгрузить(, ИменаКолонок);
КонецЕсли;
Если ИсключаяОтбор <> Неопределено Тогда
Для Каждого УдаляемаяСтрока Из КопияТаблицы.НайтиСтроки(ИсключаяОтбор) Цикл
КопияТаблицы.Удалить(УдаляемаяСтрока);
КонецЦикла;
КонецЕсли;
КолонкаКоличества = "Количество" + СуффиксСлужебногоСвойстваЛкс() + "65"; //гарантировано уникальное имя колонки
КопияТаблицы.Колонки.Добавить(КолонкаКоличества);
КопияТаблицы.ЗаполнитьЗначения(1, КолонкаКоличества);
КопияТаблицы.Свернуть(ИменаКолонок, КолонкаКоличества);
КопияТаблицы.Сортировать(КолонкаКоличества + " Убыв");
МассивНеуникальных = Новый Массив;
Если ирКэш.РежимОтладкиЛкс() Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Индекс = 0 По КопияТаблицы.Количество() - 1 Цикл
СтрокаКопии = КопияТаблицы[Индекс];
Если СтрокаКопии[КолонкаКоличества] > 1 Тогда
НеуникальныйКлюч = Новый Структура(ИменаКолонок);
ЗаполнитьЗначенияСвойств(НеуникальныйКлюч, СтрокаКопии);
МассивНеуникальных.Добавить(НеуникальныйКлюч);
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Индекс = 0 По КопияТаблицы.Количество() - 1 Цикл СтрокаКопии = КопияТаблицы[Индекс]; Если СтрокаКопии[КолонкаКоличества] > 1 Тогда НеуникальныйКлюч = Новый Структура(ИменаКолонок); ЗаполнитьЗначенияСвойств(НеуникальныйКлюч, СтрокаКопии); МассивНеуникальных.Добавить(НеуникальныйКлюч); Иначе Прервать; КонецЕсли; КонецЦикла;
КонецЕсли;
Возврат МассивНеуникальных;
КонецФункции
// Отбирает строки таблицы значений и сортирует их.
// Расширенный вариант метода ТаблицаЗначений.НайтиСтроки(). Оригинал не сохраняет сортировку при наличии индексов.
// Из-за ошибки платформы если есть индекс и ранее использован ЗагрузитьКолонку() https://www.hostedredmine.com/issues/936307 здесь может вернуться больше строк чем есть в таблице!
//
// Параметры:
// ТаблицаЗначений - ТаблицаЗначений -
// Отбор - Структура -
// СтрокаСортировки - Строка -
// СравнениеЗначений - *СравнениеЗначений - если передан, то представления ссылок не будут использоваться (быстрее)
//
// Возвращаемое значение:
// - Массив - отсортированные строки оригинальной таблицы
//
Функция НайтиСтрокиТаблицыЛкс(ТаблицаЗначений, ОтборИлиСтроки = Неопределено, СтрокаСортировки, СравнениеЗначений = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
Если ТипЗнч(ОтборИлиСтроки) = Тип("Массив") Тогда
Строки = ОтборИлиСтроки;
ИначеЕсли ОтборИлиСтроки <> Неопределено Тогда
Строки = ТаблицаЗначений.НайтиСтроки(ОтборИлиСтроки);
Иначе
Идентификатор = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
ТаблицаЗначений.Колонки.Добавить(Идентификатор);
Строки = ТаблицаЗначений.НайтиСтроки(Новый Структура(Идентификатор, Неопределено));
ТаблицаЗначений.Колонки.Удалить(Идентификатор);
КонецЕсли;
Если Строки.Количество() > 1 И СтрокаСортировки <> Неопределено Тогда
ИменаКолонок = НРег(СтрокаСортировки);
ИменаКолонок = СтрЗаменить(ИменаКолонок, " убыв", "");
ИменаКолонок = СтрЗаменить(ИменаКолонок, " возр", "");
Копия = ТаблицаЗначений.Скопировать(Строки, ИменаКолонок);
Копия.Колонки.Добавить("Оригинал");
Копия.ЗагрузитьКолонку(Строки, "Оригинал");
Копия.Сортировать(СтрокаСортировки, СравнениеЗначений);
Строки = Копия.ВыгрузитьКолонку("Оригинал");
КонецЕсли;
Возврат Строки;
КонецФункции
Функция ПредставлениеОтбораЛкс(Знач Отбор, выхПустой = Ложь) Экспорт
ПредставлениеОтбора = "" + Отбор;
выхПустой = Ложь;
Если Не ЗначениеЗаполнено(ПредставлениеОтбора) Тогда
ПредставлениеОтбора = "Без отбора";
выхПустой = Истина;
КонецЕсли;
Возврат ПредставлениеОтбора;
КонецФункции
Функция ПредставлениеДлительностиЛкс(Знач ДлительностьСекунд) Экспорт
Результат = "";
КолвоЧасов = Цел(ДлительностьСекунд / 3600);
ДлительностьДата = '00010101' + ДлительностьСекунд - КолвоЧасов * 3600;
Если КолвоЧасов > 0 Тогда
Результат = Результат + Формат(КолвоЧасов, "ЧН=; ЧГ=0") + ":";
КонецЕсли;
Результат = Результат + Формат(ДлительностьДата, "ДФ=мм:сс; ДП=");
Возврат Результат;
КонецФункции
Функция ПредставлениеЗначенияВоВстроенномЯзыкеЛкс(Знач Значение) Экспорт
Если ТипЗнч(Значение) = Тип("Неопределено") Тогда
Результат = ПеревестиСтроку("Неопределено");
ИначеЕсли ТипЗнч(Значение) = Тип("Null") Тогда
Результат = "Null";
Иначе
Если ТипЗнч(Значение) = Тип("Дата") Тогда
Разделитель = ", ";
Результат = ПеревестиСтроку("Дата") + "(" + XMLСтрока(Год(Значение)) + Разделитель + XMLСтрока(Месяц(Значение)) + Разделитель + XMLСтрока(День(Значение));
Если НачалоДня(Значение) <> Значение Тогда
Результат = Результат + Разделитель + " " + XMLСтрока(Час(Значение)) + Разделитель + XMLСтрока(Минута(Значение)) + Разделитель + XMLСтрока(Секунда(Значение));
КонецЕсли;
Результат = Результат + ")";
ИначеЕсли ТипЗнч(Значение) = Тип("Число") Тогда
Результат = XMLСтрока(Значение);
ИначеЕсли ТипЗнч(Значение) = Тип("Булево") Тогда
Если Значение Тогда
Результат = ПеревестиСтроку("Истина");
Иначе
Результат = ПеревестиСтроку("Ложь");
КонецЕсли;
ИначеЕсли ТипЗнч(Значение) = Тип("Строка") Тогда
Результат = ТекстВВыражениеВстроенногоЯзыкаЛкс(Значение);
ИначеЕсли XMLТипЗнч(Значение) = Неопределено Тогда
Результат = ПолучитьПолноеИмяПредопределенногоЗначения(Значение);
Иначе
ВызватьИсключение "Для типа значения """ + ТипЗнч(Значение) + """ не определено литеральное представление во встроенном языке";
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Различные значения колонки таблицы лкс
//
// Параметры:
// Таблица - ТаблицаЗначений, ТабличнаяЧасть -
// ИмяКолонки - -
// ОтборСтрок - Структура -
//
// Возвращаемое значение:
// Массив -
//
Функция РазличныеЗначенияКолонкиТаблицыЛкс(Таблица, ИмяКолонки, ОтборСтрок = Неопределено) Экспорт
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
КопияТаблицы = Таблица.Скопировать(ОтборСтрок, ИмяКолонки);
Иначе
КопияТаблицы = Таблица.Выгрузить(ОтборСтрок, ИмяКолонки);
КонецЕсли;
#Если Сервер И Не Сервер Тогда
КопияТаблицы = Новый ТаблицаЗначений;
#КонецЕсли
КопияТаблицы.Свернуть(ИмяКолонки);
РазличныеЗначения = КопияТаблицы.ВыгрузитьКолонку(ИмяКолонки);
Возврат РазличныеЗначения;
КонецФункции
// Функция - Различные значения массива лкс
//
// Параметры:
// Массив - Массив -
// КромеПустых - Булево -
//
// Возвращаемое значение:
// Массив -
//
Функция РазличныеЗначенияМассиваЛкс(Знач Массив, Знач КромеПустых = Ложь) Экспорт
НовыйМассив = Новый Массив;
Соответствие = Новый Соответствие;
ЕстьНеопределено = Ложь;
Для Каждого Элемент Из Массив Цикл
Если КромеПустых И Не ЗначениеЗаполнено(Элемент) Тогда
Продолжить;
КонецЕсли;
Если Элемент = Неопределено Тогда
// Раньше Ключ=Неопределено было невозможно вставить в соответсвие. Исправлено в платформе в режиме совместимости 8.3.20
ЕстьНеопределено = Истина;
Продолжить;
КонецЕсли;
Если Соответствие[Элемент] = 1 Тогда
Продолжить;
КонецЕсли;
Соответствие.Вставить(Элемент, 1);
НовыйМассив.Добавить(Элемент);
КонецЦикла;
Если ЕстьНеопределено Тогда
НовыйМассив.Добавить(Неопределено);
КонецЕсли;
Возврат НовыйМассив; // см. Массив
КонецФункции
Функция СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД, ОбъектыНаСервере = Неопределено) Экспорт
СтруктураНабораЗаписей = ОбъектБДПоКлючуЛкс(ПолноеИмяТаблицыБД,,, Ложь, ОбъектыНаСервере);
//! СтруктураНабораЗаписей.Методы = 0 // ОбработкаОбъект.ирИмитаторНаборЗаписей
Возврат СтруктураНабораЗаписей;
КонецФункции
// Переводит системный идентификатор на язык варианта встроенного языка
Функция ПеревестиСтроку(Русский) Экспорт
// Для ускорения
//Если Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский Тогда
Если "" + Метаданные.ВариантВстроенногоЯзыка = "Русский" Тогда
Возврат Русский;
Иначе
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Локальный = мПлатформа.ПеревестиСтроку("" + Русский, Истина);
Возврат Локальный;
КонецЕсли;
КонецФункции
// Переводит системный идентификатор на русский язык
Функция ПеревестиВРусский(Локальный) Экспорт
//Если Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский Тогда // Долго
Если КодСимвола(Локальный, 1) >= 128 Тогда
Возврат Локальный;
Иначе
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Русский = мПлатформа.ПеревестиВРусский("" + Локальный, Истина);
Возврат Русский;
КонецЕсли;
КонецФункции
// Переводит системный идентификатор на английский язык
Функция ПеревестиИзРусскогоВАнглийскийЛкс(Локальный) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Русский = мПлатформа.ПеревестиСтроку("" + Локальный, Истина);
Возврат Русский;
КонецФункции
Функция ПеревестиПолноеИмяМДВАнглийскийЛкс(ПолноеИмяМД) Экспорт
Фрагменты = СтрРазделитьЛкс(ПолноеИмяМД);
Результат = "";
Для Счетчик = 1 По Фрагменты.Количество() / 2 Цикл
Если Результат <> "" Тогда
Результат = Результат + ".";
КонецЕсли;
Английский = ПеревестиИзРусскогоВАнглийскийЛкс(Фрагменты[(Счетчик-1)*2]);
Результат = Результат + Английский + "." + Фрагменты[(Счетчик-1)*2+1];
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ТипКлючаЗаписиТаблицыЛкс(ПолноеИмяТаблицы) Экспорт
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
Если ЛиКорневойТипСсылкиЛкс(ТипТаблицы) Тогда
Результат = Тип(ИмяТипаИзПолногоИмениТаблицыБДЛкс(ПолноеИмяТаблицы));
ИначеЕсли Истина
И ЛиКорневойТипРегистраБДЛкс(ТипТаблицы)
И ТипТаблицы <> "Перерасчет"
И ТипТаблицы <> "Последовательность"
Тогда
Результат = Тип(ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяТаблицы, "КлючЗаписи"));
Иначе
Результат = Тип("Неопределено");
КонецЕсли;
Возврат Результат;
КонецФункции
// .
//
// Параметры:
// ПолноеИмяТаблицыБД - -
// ВключатьНомерСтроки - -
// ВернутьСтруктуру - Булево - возвращать структуру иначе список значений
// ДляНабораЗаписейРегистраСведений - Булево - для регистров сведений подчиненных регистратору вернуть ключ записываемого объекта
// СТипами - -
// ТипТаблицы - -
//
// Возвращаемое значение:
// Структура, СписокЗначений -
//
Функция СтруктураКлючаТаблицыБДЛкс(Знач ПолноеИмяТаблицыБД, Знач ВключатьНомерСтроки = Истина, Знач ВернутьСтруктуру = Истина, Знач ДляНабораЗаписейРегистраСведений = Истина, Знач СТипами = Истина,
ТипТаблицы = Неопределено) Экспорт
Если ТипТаблицы = Неопределено Тогда
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КонецЕсли;
ТипЗначения = Неопределено;
Если СТипами Тогда
ПоляБД = ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КонецЕсли;
СписокПолей = Новый СписокЗначений;
Если Ложь
Или ЛиТипТаблицыМетассылкиЛкс(ТипТаблицы)
Или ЛиКорневойТипСсылочногоОбъектаБДЛкс(ТипТаблицы)
Тогда
ИмяПоля = ПеревестиСтроку("Ссылка");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
ИначеЕсли ЛиКорневойТипРегистраБДЛкс(ТипТаблицы) Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
НаборЗаписей = ирКэш.ЭталонныйНаборЗаписейЛкс(ПолноеИмяТаблицыБД);
#Если Сервер И Не Сервер Тогда
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют;
#КонецЕсли
Если Истина
И ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы)
И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору
И Не ДляНабораЗаписейРегистраСведений
Тогда
Если ОбъектМД.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда
ИмяПоля = ПеревестиСтроку("Период");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
КонецЕсли;
Если ОбъектМД.ПериодичностьРегистраСведений = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.ПозицияРегистратора Тогда
ИмяПоля = ПеревестиСтроку("Регистратор");
Если СТипами Тогда
ТипЗначения = НаборЗаписей.Отбор[ИмяПоля].ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
КонецЕсли;
Для Каждого Измерение Из ОбъектМД.Измерения Цикл
Если СТипами Тогда
ТипЗначения = Измерение.Тип;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, Измерение.Имя);
КонецЦикла;
КонецЕсли;
Если СписокПолей.Количество() = 0 Тогда
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
Если Ложь
Или ЭлементОтбора.Использование
Или ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы)
Тогда
Если СТипами Тогда
ТипЗначения = ЭлементОтбора.ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ЭлементОтбора.Имя);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ВключатьНомерСтроки Тогда
Если ЛиКорневойТипПоследовательностиЛкс(ТипТаблицы) Тогда
Для Каждого Измерение Из ОбъектМД.Измерения Цикл
Если СТипами Тогда
ТипЗначения = Измерение.Тип;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, Измерение.Имя);
КонецЦикла;
ИначеЕсли Истина
И ТипТаблицы <> "Перерасчет"
И (Ложь
Или Не ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы)
Или (Истина
И ДляНабораЗаписейРегистраСведений
И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору))
Тогда
ИмяПоля = ПеревестиСтроку("НомерСтроки");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
КонецЕсли;
КонецЕсли;
ИначеЕсли ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда
ИмяПоля = ПеревестиСтроку("Ссылка");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
Если ВключатьНомерСтроки Тогда
ИмяПоля = ПеревестиСтроку("НомерСтроки");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
КонецЕсли;
ИначеЕсли ТипТаблицы = "Изменения" Тогда
ДоступноОбщиеРеквизиты = ирКэш.ДоступноОбщиеРеквизитыЛкс();
Для Каждого ПолеБД Из ПоляБД Цикл
Если СтрокиРавныЛкс(ПолеБД.Имя, ПеревестиСтроку("НомерСообщения")) Тогда
Продолжить;
КонецЕсли;
Если ДоступноОбщиеРеквизиты Тогда
// https://www.hostedredmine.com/issues/997740
Если Метаданные.ОбщиеРеквизиты.Найти(ПолеБД.Имя) <> Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Если СТипами Тогда
ТипЗначения = ПолеБД.ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ПолеБД.Имя);
КонецЦикла;
ИначеЕсли ТипТаблицы = "Внешняя" Тогда
ТаблицаМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяТаблицыБД);
Если ТаблицаМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные Тогда
СписокПолей.Добавить(Новый ОписаниеТипов(ИмяТипаДанныхТаблицыРегистраЛкс(ПолноеИмяТаблицыБД, "Ссылка")), ПеревестиСтроку("Ссылка"));
Иначе
НаборЗаписей = ирКэш.ЭталонныйНаборЗаписейЛкс(ПолноеИмяТаблицыБД);
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
Если СТипами Тогда
ТипЗначения = ЭлементОтбора.ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ЭлементОтбора.Имя);
КонецЦикла;
КонецЕсли;
ИначеЕсли ТипТаблицы = "ЖурналДокументов" Тогда
ИмяПоля = ПеревестиСтроку("Ссылка");
Если СТипами Тогда
ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения;
КонецЕсли;
СписокПолей.Добавить(ТипЗначения, ИмяПоля);
ИначеЕсли ТипТаблицы = "Константа" Тогда
ИначеЕсли ТипТаблицы = "Константы" Тогда
ИначеЕсли Истина
И ТипТаблицы = "ВиртуальнаяТаблица"
И (Ложь
Или СтрНачинаетсяСЛкс(ПолноеИмяТаблицыБД, "РегистрНакопления.")
Или СтрНачинаетсяСЛкс(ПолноеИмяТаблицыБД, "РегистрБухгалтерии."))
Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Для Каждого Поле Из ПоляБД Цикл
Если Не ЛиПолеРожденоРесурсомНакопленияЛкс(ОбъектМД, Поле.Имя) Тогда
СписокПолей.Добавить(Поле.ТипЗначения, Поле.Имя);
КонецЕсли;
КонецЦикла;
Иначе
ВызватьИсключение "Получение структуры ключа таблицы БД """ + ПолноеИмяТаблицыБД + """ не поддерживается";
КонецЕсли;
Если ВернутьСтруктуру Тогда
Результат = Новый Структура();
Для Каждого ЭлементСписка Из СписокПолей Цикл
Результат.Вставить(ЭлементСписка.Представление, ЭлементСписка.Значение);
КонецЦикла;
Иначе
Результат = СписокПолей;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиПолеРожденоРесурсомНакопленияЛкс(ОбъектМД, ИмяПоля) Экспорт
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.РегистрыБухгалтерии.Хозрасчетный;
#КонецЕсли
Успех = Ложь;
Для Каждого Ресурс Из ОбъектМД.Ресурсы Цикл
Если СтрНачинаетсяСЛкс(ИмяПоля, Ресурс.Имя) Тогда
Успех = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Успех;
КонецФункции
Функция ДанныеСтрокиРегистраИзКлючаЗаписиЛкс(Знач КлючЗаписи, Знач ИмяТаблицыРегистра = "") Экспорт
Если Не ЗначениеЗаполнено(ИмяТаблицыРегистра) Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(КлючЗаписи));
ИмяТаблицыРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ОбъектМД.ПолноеИмя());
КонецЕсли;
СтруктураКлючаСтроки = СтруктураКлючаТаблицыБДЛкс(ИмяТаблицыРегистра,,, Ложь);
ЗаполнитьЗначенияСвойств(СтруктураКлючаСтроки, КлючЗаписи);
СхемаКомпоновки = СоздатьСхемуКомпоновкиТаблицыБДЛкс(ИмяТаблицыРегистра);
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, СтруктураКлючаСтроки);
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицыРегистра);
Для Каждого ПолеТаблицы Из ПоляТаблицыБД Цикл
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ПолеТаблицы.Имя);
КонецЦикла;
ДанныеСтроки = СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(СхемаКомпоновки, НастройкаКомпоновки);
Результат = Неопределено;
Если ДанныеСтроки.Количество() > 0 Тогда
Результат = ДанныеСтроки[0];
КонецЕсли;
Возврат Результат;
КонецФункции
// Поддерживает безопасно любые типы
Функция ЗначениеИзСтрокиВнутрЛкс(Знач Текст) Экспорт
// Антибаг платформы 8.3.18 критическая ошибка преобразования текста Внутр содержащего схему запроса с неизвестными таблицами https://www.hostedredmine.com/issues/946508
// Очищаем все значения типа СхемаЗапроса
Текст = СтрЗаменить(Текст, "{""#"",3758b52f-1b2b-4374-a802-0ecc73031c28,", "{""#"",3758b52f-1b2b-4374-0000-000000000000,");
// Очищаем все значения типа ОписаниеСтандартногоРеквизита https://www.hostedredmine.com/issues/948202
Текст = СтрЗаменить(Текст, "{""#"",973665f2-16c6-44ef-b190-b0190c6fd23e}", "{""#"",973665f2-16c6-44ef-0000-000000000000}");
Результат = ЗначениеИзСтрокиВнутр(Текст);
Возврат Результат;
КонецФункции
// На выходе неглубокая копия структуры, где несериализуемые значения заменены на описания ошибок
Функция УдалитьМутабельныеЗначенияВСтруктуреЛкс(Знач Структура) Экспорт
#Если Сервер И Не Сервер Тогда
Структура = Новый Структура;
#КонецЕсли
НоваяСтруктура = Новый Структура;
Для Каждого КлючИЗначение Из Структура Цикл
НовоеЗначение = КлючИЗначение.Значение;
Попытка
Копия = КопияОбъектаЛкс(КлючИЗначение.Значение, Истина);
Исключение
НовоеЗначение = СтрШаблонЛкс("Ошибка сериализации ""%1"": " + ОписаниеОшибки(), ТипЗнч(КлючИЗначение.Значение));
КонецПопытки;
НоваяСтруктура.Вставить(КлючИЗначение.Ключ, НовоеЗначение);
КонецЦикла;
Возврат НоваяСтруктура;
КонецФункции
// Функция - Заполнить значения свойств обязательно.
//
// Параметры:
// Объект - -
// Структура - -
// выхИменаСвойств - Строка - передается для ускорения, заполняется автоматически
//
// Возвращаемое значение:
// -
//
Функция ЗаполнитьЗначенияСвойствОбязательноЛкс(Объект, Структура, выхИменаСвойств = "") Экспорт
#Если Сервер И Не Сервер Тогда
Структура = Новый Структура;
#КонецЕсли
Если Не ЗначениеЗаполнено(выхИменаСвойств) Тогда
выхИменаСвойств = ИменаСвойствСтруктурыЛкс(Структура);
КонецЕсли;
ЗаполнитьЗначенияСвойств(Объект, Структура, выхИменаСвойств);
КонецФункции
// В методе ЗаполнитьЗначенияСвойств() выброс исключения при отсутствии исключаемого свойства у источника является вредным и недокументированным https://partners.v8.1c.ru/forum/t/1942320/m/1942490
Функция ЗаполнитьЗначенияСвойствСтруктуройЛкс(Знач Приемник, Знач Источник, Знач СписокСвойств = Неопределено, Знач ИсключаяСвойства = Неопределено) Экспорт
ИсключитьСвойстваИсточника = Новый Массив;
для Каждого КлючИЗначение Из Новый Структура(ИсключаяСвойства) Цикл
Если Источник.Свойство(КлючИЗначение.Ключ) Тогда
ИсключитьСвойстваИсточника.Добавить(КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
ЗаполнитьЗначенияСвойств(Приемник, Источник, СписокСвойств, СтрСоединитьЛкс(ИсключитьСвойстваИсточника));
КонецФункции
Функция ИменаСвойствСтруктурыЛкс(Знач СтруктураИлиСтрокаТаблицы) Экспорт
ИменаСвойств = "";
Если ТипЗнч(СтруктураИлиСтрокаТаблицы) <> Тип("Структура") Тогда
//! СтруктураИлиСтрокаТаблицы = 0 // СтрокаТаблицыЗначений
СтруктураИлиСтрокаТаблицы = СтруктураИлиСтрокаТаблицы.Владелец().Колонки;
КонецЕсли;
Для Каждого КлючИЗначение Из СтруктураИлиСтрокаТаблицы Цикл
Если ТипЗнч(КлючИЗначение) = Тип("КлючИЗначение") Тогда
ИмяСвойства = КлючИЗначение.Ключ;
Иначе
ИмяСвойства = КлючИЗначение.Имя;
КонецЕсли;
ИменаСвойств = ИменаСвойств + "," + ИмяСвойства;
КонецЦикла;
ИменаСвойств = Сред(ИменаСвойств, 2);
Возврат ИменаСвойств
КонецФункции
Функция СуффиксСлужебногоСвойстваЛкс() Экспорт
Возврат "3463";
КонецФункции
Функция ИмяКолонкиНомерСтрокиЛкс() Экспорт
Возврат "НомерСтроки" + ирОбщий.СуффиксСлужебногоСвойстваЛкс();
КонецФункции
// Получает уникальную строку, подходящую для именования элемента структуры.
//
// Параметры:
// Нет.
//
// Возвращаемое значение:
// Строка.
//
Функция НовоеУникальноеИмяЛкс() Экспорт
Результат = "_" + ИдентификаторИзПредставленияЛкс(Новый УникальныйИдентификатор);
Возврат Результат;
КонецФункции
Функция ИмяКолонкиВнутреннегоИДСтрокиЛкс() Экспорт
Возврат "_НомерСтроки" + СуффиксСлужебногоСвойстваЛкс();
КонецФункции
Функция ЦветТекстаНеактивностиЛкс() Экспорт
Возврат Новый Цвет(100, 100, 100);
КонецФункции
Функция ЦветТекстаАктивностиЛкс() Экспорт
Возврат WebЦвета.Синий;
КонецФункции
Функция ЦветТекстаТекущегоЭлементаЛкс() Экспорт
Возврат Новый Цвет(20, 40, 160);
КонецФункции
Функция ЦветТекстаИзмененныхДанныхЛкс() Экспорт
Возврат WebЦвета.КожаноКоричневый;
КонецФункции
Функция ЦветТекстаПустогоЗначенияЛкс() Экспорт
Возврат Новый Цвет(180, 180, 180);
КонецФункции
Функция ЦветФонаПустогоЗначенияЛкс() Экспорт
Цвет = Новый Цвет(248, 248, 255);
Возврат Цвет;
КонецФункции
Функция ЦветФонаТекущегоЗначенияЛкс() Экспорт
Цвет = ЦветСтиляЛкс("ирЦветФонаРасширенногоПредставленияЗначения");
Возврат Цвет;
КонецФункции
Функция ЦветФонаАкцентаЛкс() Экспорт
//Возврат Новый Цвет(240, 240, 250); // Сиреневый
Возврат Новый Цвет(255, 255, 220); // Белдно-Желтый слабее чем ЦветФонаТекущегоЗначенияЛкс
КонецФункции
Функция ЦветФонаОшибкиЛкс() Экспорт
Возврат Новый Цвет(250, 240, 240);
КонецФункции
Функция ЧислоHEXВЦветЛкс(ЧислоHEX) Экспорт
Красный = СтрокаHEXtoINTЛкс(Лев(ЧислоHEX, 2));
Зеленый = СтрокаHEXtoINTЛкс(Сред(ЧислоHEX, 3, 2));
Синий = СтрокаHEXtoINTЛкс(Сред(ЧислоHEX, 5, 2));
Результат = Новый Цвет(Красный, Зеленый, Синий);
Возврат Результат;
КонецФункции
Функция ЦветСтиляЛкс(ИмяЦвета) Экспорт
//Результат = ирПортативный.ЦветСтиляЛкс(Имя);
Если ИмяЦвета = "ирТекстИнформационнойНадписи" Тогда
Возврат Новый Цвет(83, 106, 194);
ИначеЕсли ИмяЦвета = "ирЦветФонаЧередованияСтрок" Тогда
//Возврат WebЦвета.МятныйКрем;
Возврат Новый Цвет(240, 255, 225);
ИначеЕсли ИмяЦвета = "ирЦветФонаВычисляемогоЗначения" Тогда
Возврат WebЦвета.ГолубойСКраснымОттенком;
ИначеЕсли ИмяЦвета = "ирЦветФонаОшибки" Тогда
Возврат Новый Цвет(255, 235, 235);
ИначеЕсли ИмяЦвета = "ирЦветФонаРасширенногоПредставленияЗначения" Тогда
Возврат Новый Цвет(255, 255, 210);
Иначе
Результат = ЦветаСтиля[ИмяЦвета];
КонецЕсли;
Возврат Результат;
КонецФункции
// Для подчиненного регистра сведений выполняет чтение из БД
// Параметры:
// Результат - Структура
Функция СтруктураИзКлючаЗаписиЛкс(КлючЗаписи, ПолноеИмяМДЭлемента = "", ДляПодчиненногоРегистраСведенийНомерСтроки = Ложь) Экспорт
Если Не ЗначениеЗаполнено(ПолноеИмяМДЭлемента) Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(КлючЗаписи));
ПолноеИмяМДЭлемента = ОбъектМД.ПолноеИмя();
Иначе
ОбъектМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМДЭлемента);
КонецЕсли;
СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяМДЭлемента, Истина,, Ложь);
ЗаполнитьЗначенияСвойств(СтруктураКлюча, КлючЗаписи);
Если ДляПодчиненногоРегистраСведенийНомерСтроки Тогда
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяМДЭлемента);
Если Истина
И ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы)
И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору
Тогда
ДанныеСтроки = СтрокаТаблицыБДПоКлючуЛкс(ПолноеИмяМДЭлемента, СтруктураКлюча);
СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяМДЭлемента);
ЗаполнитьЗначенияСвойств(СтруктураКлюча, ДанныеСтроки);
КонецЕсли;
КонецЕсли;
Возврат СтруктураКлюча;
КонецФункции
Функция XMLКлючОбъектаБДЛкс(Знач ОбъектДанных, Знач ИспользоватьСсылкуДляСсылочных = Ложь) Экспорт
Если ОбъектДанных = Неопределено Тогда
Результат = "Неопределено";
Возврат Результат;
КонецЕсли;
ПредставлениеОбъекта = "";
Если ТипЗнч(ОбъектДанных) = Тип("УдалениеОбъекта") Тогда
Класс = "Удаление";
Иначе
Попытка
ЭтоНовый = ОбъектДанных.ЭтоНовый();
Класс = "Ссылочный";
ПредставлениеОбъекта = "" + ОбъектДанных + ",";
Исключение
Попытка
ИдентификаторСсылки = ОбъектДанных.УникальныйИдентификатор();
Класс = "Ссылочный";
Исключение
Попытка
Пустышка = ОбъектДанных.Количество();
Класс = "НаборЗаписей";
Исключение
Попытка
Пустышка = ОбъектДанных.Значение;
Класс = "Константы";
Исключение
Класс = "Примитив";
КонецПопытки;
КонецПопытки;
КонецПопытки;
КонецПопытки;
Если Истина
И Класс = "Ссылочный"
И ИспользоватьСсылкуДляСсылочных
Тогда
Результат = ОбъектДанных;
Возврат Результат;
КонецЕсли;
КонецЕсли;
Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда
Если ТипЗнч(ОбъектДанных) = Тип("ОбработкаОбъект.ирИмитаторНаборЗаписей") Тогда
Класс = "НаборЗаписей";
ИначеЕсли ТипЗнч(ОбъектДанных) = Тип("ОбработкаОбъект.ирИмитаторКонстантаМенеджер") Тогда
Класс = "Константы";
КонецЕсли;
КонецЕсли;
// Антибаг 8.3.11 На перерасчетах ЗаписьXML ошибку выдает. https://partners.v8.1c.ru/forum/t/1674609/m/1674609
//XMLКлюч = "" + XMLТип(ТипОбъектаБДЛкс(ОбъектДанных)).ИмяТипа + "(";
XMLКлюч = "" + СериализаторXDTO.XMLТип(ТипОбъектаБДЛкс(ОбъектДанных)).ИмяТипа + "(";
Если Класс = "Ссылочный" Тогда
Если ЭтоНовый = Истина Тогда
ИдентификаторСсылки = "!" + ИдентификаторСсылки = ИдентификаторСсылкиЛкс(ОбъектДанных.ПолучитьСсылкуНового());
КонецЕсли;
Если ИдентификаторСсылки = Неопределено Тогда
ИдентификаторСсылки = ИдентификаторСсылкиЛкс(ОбъектДанных.Ссылка);
КонецЕсли;
XMLКлюч = XMLКлюч + ПредставлениеОбъекта + ИдентификаторСсылки;
ИначеЕсли Класс = "Удаление" Тогда
XMLКлюч = XMLКлюч + XMLКлючОбъектаБДЛкс(ОбъектДанных.Ссылка);
ИначеЕсли Класс = "НаборЗаписей" Тогда
ПредставлениеОтбора = "";
Разделитель = ", ";
Для Каждого ЭлементОтбора Из ОбъектДанных.Отбор Цикл
Если ЭлементОтбора.Использование Тогда
ПредставлениеОтбора = ПредставлениеОтбора + Разделитель + ЭлементОтбора.Имя
+ ":" + XMLКлючОбъектаБДЛкс(ЭлементОтбора.Значение);
КонецЕсли;
КонецЦикла;
XMLКлюч = XMLКлюч + Сред(ПредставлениеОтбора, СтрДлина(Разделитель) + 1);
ИначеЕсли Класс = "Константы" Тогда
//
Иначе
// Примитивный тип
XMLКлюч = XMLКлюч + ОбъектДанных;
КонецЕсли;
XMLКлюч = XMLКлюч + ")";
Результат = XMLКлюч;
Возврат Результат;
КонецФункции
Функция ИдентификаторСсылкиЛкс(Знач Ссылка) Экспорт
Попытка
ИдентификаторСсылки = Ссылка.УникальныйИдентификатор();
Исключение
//! Ссылка = 0 // ВнешнийИсточникДанныхТаблицаСсылка
ИдентификаторСсылки = Ссылка.Значение();
КонецПопытки;
Возврат ИдентификаторСсылки;
КонецФункции
// .
// Параметры:
// Объект - ОбъектБД, ОбъектМД
Функция ТабличныеЧастиОбъектаЛкс(Объект, ФрагментыИмени = Неопределено) Экспорт
СтруктураТЧ = Новый Структура();
Если Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И ТипЗнч(Объект) = Тип("ОбработкаОбъект.ирИмитаторСсылочныйОбъект")
Тогда
ОбъектМД = Метаданные.НайтиПоТипу(Объект._Тип);
ОбъектБД = Объект.Данные;
ИначеЕсли ТипЗнч(Объект) = Тип("ОбъектМетаданных") Тогда
ОбъектМД = Объект;
ОбъектБД = Неопределено;
Иначе
Если ЛиТипСсылкиТочкиМаршрутаЛкс(ТипЗнч(Объект)) Тогда
Возврат СтруктураТЧ;
КонецЕсли;
ОбъектМД = Объект.Метаданные();
ОбъектБД = Объект;
КонецЕсли;
Если Не ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД, Ложь, Истина, Истина, ФрагментыИмени) Тогда
Возврат СтруктураТЧ;
КонецЕсли;
ИмяСвойстваЭтоГруппа = ПеревестиСтроку("ЭтоГруппа");
Для Каждого МетаТЧ из ОбъектМД.ТабличныеЧасти Цикл
// Для реквизитов справочников, принадлежащих только группе или только элементу нужно игнорировать те объекты, для которых эти реквизиты не используются
Если Истина
И ОбъектБД <> Неопределено
И ЛиМетаданныеОбъектаСГруппамиЛкс(ОбъектМД)
Тогда
ЭтоГруппа = ОбъектБД[ИмяСвойстваЭтоГруппа];
Если Ложь
Или (Истина
И ЭтоГруппа
И МетаТЧ.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляЭлемента)
Или (Истина
И Не ЭтоГруппа
И МетаТЧ.Использование = Метаданные.СвойстваОбъектов.ИспользованиеРеквизита.ДляГруппы)
Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
СтруктураТЧ.Вставить(МетаТЧ.Имя, МетаТЧ.Представление());
КонецЦикла;
Если Метаданные.ПланыСчетов.Индекс(ОбъектМД) >= 0 Тогда
//! ОбъектМД = 0 // ОбъектМетаданныхПланСчетов
Если ОбъектМД.ВидыСубконто <> Неопределено Тогда
СтруктураТЧ.Вставить(ПеревестиСтроку("ВидыСубконто"), "Виды субконто");
КонецЕсли;
КонецЕсли;
Если Метаданные.ПланыВидовРасчета.Индекс(ОбъектМД) >= 0 Тогда
//! ОбъектМД = 0 // ОбъектМетаданныхПланВидовРасчета
Если ОбъектМД.ЗависимостьОтВидовРасчета <> Метаданные.СвойстваОбъектов.ИспользованиеБазыПланаВидовРасчета.НеИспользовать Тогда
СтруктураТЧ.Вставить(ПеревестиСтроку("БазовыеВидыРасчета"), "Базовые виды расчета");
КонецЕсли;
СтруктураТЧ.Вставить(ПеревестиСтроку("ВедущиеВидыРасчета"), "Ведущие виды расчета");
Если ОбъектМД.ИспользованиеПериодаДействия Тогда
СтруктураТЧ.Вставить(ПеревестиСтроку("ВытесняющиеВидыРасчета"), "Вытесняющие виды расчета");
КонецЕсли;
КонецЕсли;
Возврат СтруктураТЧ;
КонецФункции
Функция ЛиСтрокаСодержитВсеПодстрокиЛкс(Знач Строка, Знач ПодстрокиНРег, Знач Родитель = "", выхПрерватьРодителя = Ложь) Экспорт
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Если ТипЗнч(ПодстрокиНРег) = Тип("Строка") Тогда
ПодстрокиНРег = СтрРазделитьЛкс(НРег(ПодстрокиНРег), " ", Истина);
КонецЕсли;
Если Родитель <> "" Тогда
Если Найти(НРег(Родитель), ПодстрокиНРег[0]) = 0 Тогда
выхПрерватьРодителя = Истина;
Возврат Ложь;
КонецЕсли;
Индекс = 1;
Иначе
Индекс = 0;
КонецЕсли;
НСтрока = НРег(Строка);
Для Индекс = Индекс По ПодстрокиНРег.ВГраница() Цикл
Если Найти(НСтрока, ПодстрокиНРег[Индекс]) = 0 Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Если ТипЗнч(ПодстрокиНРег) = Тип("Строка") Тогда ПодстрокиНРег = СтрРазделитьЛкс(НРег(ПодстрокиНРег), " ", Истина); КонецЕсли; Если Родитель <> "" Тогда Если Найти(НРег(Родитель), ПодстрокиНРег[0]) = 0 Тогда выхПрерватьРодителя = Истина; Возврат Ложь; КонецЕсли; Индекс = 1; Иначе Индекс = 0; КонецЕсли; НСтрока = НРег(Строка); Для Индекс = Индекс По ПодстрокиНРег.ВГраница() Цикл Если Найти(НСтрока, ПодстрокиНРег[Индекс]) = 0 Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Возврат Истина;
КонецЕсли;
КонецФункции
Функция СтрокаТаблицыБДПоКлючуЛкс(ПолноеИмяТаблицы, СтруктураКлюча) Экспорт
Запрос = Новый Запрос;
ТекстОтбора = Новый Массив;
Если СтрКончаетсяНаЛкс(ПолноеИмяТаблицы, ".ДвиженияССубконто") > 0 Тогда
Для Каждого КлючИЗначение Из СтруктураКлюча Цикл
ТекстОтбора.Добавить(КлючИЗначение.Ключ + " = &" + КлючИЗначение.Ключ);
КонецЦикла;
ТекстОтбора = СтрСоединитьЛкс(ТекстОтбора, " И ");
ТекстЗапроса = "ВЫБРАТЬ Т.* ИЗ " + ПолноеИмяТаблицы + "(,, " + ТекстОтбора + ") КАК Т";
Иначе
Для Каждого КлючИЗначение Из СтруктураКлюча Цикл
ТекстОтбора.Добавить("Т." + КлючИЗначение.Ключ + " = &" + КлючИЗначение.Ключ);
КонецЦикла;
ТекстОтбора = СтрСоединитьЛкс(ТекстОтбора, " И ");
ТекстЗапроса = "ВЫБРАТЬ Т.* ИЗ " + ПолноеИмяТаблицы + " КАК Т ГДЕ " + ТекстОтбора;
КонецЕсли;
СкопироватьКоллекциюЛкс(СтруктураКлюча, Запрос.Параметры);
Запрос.Текст = ТекстЗапроса;
Таблица = Запрос.Выполнить().Выгрузить();
Если Таблица.Количество() > 1 Тогда
ВызватьИсключение "По переданному ключу (" + ПредставлениеСтруктурыЛкс(СтруктураКлюча) + ") найдено несколько строк таблицы";
ИначеЕсли Таблица.Количество() > 0 Тогда
СтрокаРезультата = Таблица[0];
Иначе
СтрокаРезультата = Неопределено;
КонецЕсли;
Возврат СтрокаРезультата;
КонецФункции
// Присваивает ячейке по указателю значение. Если после этого ячейка получает другое значение, то ячейке присваивается ее старое значение.
Функция БезопасноПрисвоитьПроизвольнуюСсылкуЛкс(П1, П2) Экспорт
СтароеП1 = П1;
П1 = П2;
Если П1 <> П2 Тогда
П1 = СтароеП1;
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
Функция ПолноеИмяКолонкиБДИзМД(ПолноеИмяМД) Экспорт
Фрагменты = СтрРазделитьЛкс(ПолноеИмяМД);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
Для Счетчик = 1 По Фрагменты.Количество() / 2 - 1 Цикл
Фрагменты.Удалить(Фрагменты.ВГраница() - Счетчик);
КонецЦикла;
Возврат СтрСоединитьЛкс(Фрагменты, ".");
КонецФункции
Функция КолонкаБДПоПолномуИмениЛкс(Знач ПолноеИмяКолонкиБД) Экспорт
ИмяПоля = ПоследнийФрагментЛкс(ПолноеИмяКолонкиБД);
ИмяТаблицы = СтрокаБезПоследнегоФрагментаЛкс(ПолноеИмяКолонкиБД);
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицы);
КолонкаБД = ПоляТаблицыБД.Найти(ИмяПоля, "Имя");
Возврат КолонкаБД;
КонецФункции
// ЛиНаходитьОбразующий - Булево - находить ближайший объект метаданных, если точный найти не удается
Функция ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД, ЛиНаходитьОбразующий = Ложь) Экспорт
Результат = Неопределено;
Если Истина
И Не ПустаяСтрока(ПолноеИмяТаблицыБД)
И ПолноеИмяТаблицыБД <> "Константы"
Тогда
Фрагменты = СтрРазделитьЛкс(ПолноеИмяТаблицыБД);
Если Фрагменты.Количество() < 2 Тогда
Возврат Неопределено;
КонецЕсли;
ОбразующийМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(Фрагменты[0] + "." + Фрагменты[1]);
Если Ложь
Или ОбразующийМД = Неопределено
Или Фрагменты.Количество() = 2
Тогда
Результат = ОбразующийМД;
Иначе
Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(Фрагменты[0]) Тогда
ДочерняяКоллекция = ОбразующийМД.ТабличныеЧасти;
ИначеЕсли Фрагменты[0] = ПеревестиСтроку("РегистрРасчета") Тогда
ДочерняяКоллекция = ОбразующийМД.Перерасчеты;
ИначеЕсли ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(Фрагменты[0]) Тогда
ДочерняяКоллекция = ОбразующийМД.Таблицы;
Если Фрагменты.Количество() = 4 Тогда
Результат = ДочерняяКоллекция.Найти(Фрагменты[3]);
КонецЕсли;
//ИначеЕсли Фрагменты[0] = "РегистрБухгалтерии" Тогда
ИначеЕсли Ложь
Или ЛиКорневойТипРегистраБДЛкс(Фрагменты[0])
Или Фрагменты[0] = ПеревестиСтроку("Константа")
Тогда
Результат = ОбразующийМД;
Иначе
ВызватьИсключение "Неизвестный корневой тип метаданных (" + Фрагменты[0] + ") с дочерней таблицей";
КонецЕсли;
Если Результат = Неопределено И Фрагменты.Количество() = 3 Тогда
ДочернийОбъектМД = ДочерняяКоллекция.Найти(Фрагменты[2]);
Если ДочернийОбъектМД <> Неопределено Тогда
Результат = ДочернийОбъектМД;
ИначеЕсли ЛиНаходитьОбразующий Тогда
// ВидыСубконто, Изменения, Точки
Результат = ОбразующийМД;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД) Экспорт
Если Найти(ПолноеИмяМД, ".") = 0 Тогда
// Защита от засорения кэша
Возврат Неопределено;
КонецЕсли;
Результат = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяМД);
Возврат Результат;
КонецФункции
Функция ЛиОписаниеТипов1ВходитВОписаниеТипов2Лкс(ОписаниеТипов1, ОписаниеТипов2, ИгнорироватьNULL = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов1 = Новый ОписаниеТипов;
ОписаниеТипов2 = Новый ОписаниеТипов;
#КонецЕсли
Результат = Не (ОписаниеТипов2.Типы().Количество() > 0 И ОписаниеТипов1.Типы().Количество() = 0);
Если Результат Тогда
Для Каждого Тип Из ОписаниеТипов1.Типы() Цикл
Если Истина
И ИгнорироватьNULL
И Тип = Тип("Null")
Тогда
Продолжить;
КонецЕсли;
Если Не ОписаниеТипов2.СодержитТип(Тип) Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Результат Тогда
Результат = Истина
И (Ложь
Или Не ОписаниеТипов1.СодержитТип(Тип("Строка"))
Или ОписаниеТипов2.КвалификаторыСтроки.Длина = 0
Или (Истина
И ОписаниеТипов1.КвалификаторыСтроки.Длина <> 0
И ОписаниеТипов2.КвалификаторыСтроки.Длина >= ОписаниеТипов1.КвалификаторыСтроки.Длина))
И (Ложь
Или Не ОписаниеТипов1.СодержитТип(Тип("Дата"))
Или ОписаниеТипов2.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.ДатаВремя
Или ОписаниеТипов1.КвалификаторыДаты.ЧастиДаты = ОписаниеТипов2.КвалификаторыДаты.ЧастиДаты)
И (Ложь
Или Не ОписаниеТипов1.СодержитТип(Тип("Число"))
Или (Истина
И (Ложь
Или ОписаниеТипов1.КвалификаторыЧисла.ДопустимыйЗнак = ДопустимыйЗнак.Неотрицательный
Или ОписаниеТипов2.КвалификаторыЧисла.ДопустимыйЗнак = ДопустимыйЗнак.Любой)
И (Ложь
Или ОписаниеТипов2.КвалификаторыЧисла.Разрядность = 0
Или (Истина
И ОписаниеТипов1.КвалификаторыЧисла.Разрядность > 0
И ОписаниеТипов2.КвалификаторыЧисла.Разрядность >= ОписаниеТипов1.КвалификаторыЧисла.Разрядность
И ОписаниеТипов2.КвалификаторыЧисла.РазрядностьДробнойЧасти >= ОписаниеТипов1.КвалификаторыЧисла.РазрядностьДробнойЧасти))))
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЕстьПустыеКвалификаторыВТаблицеЗначенийЛкс(Знач ТаблицаЗначений) Экспорт
ЕстьПустыеКвалификаторы = Ложь;
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
Если Ложь
Или (Истина
И Колонка.ТипЗначения.СодержитТип(Тип("Строка"))
И Колонка.ТипЗначения.КвалификаторыСтроки.Длина = 0)
Или (Истина
И Колонка.ТипЗначения.СодержитТип(Тип("Число"))
И Колонка.ТипЗначения.КвалификаторыЧисла.Разрядность = 0)
Тогда
ЕстьПустыеКвалификаторы = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ЕстьПустыеКвалификаторы;
КонецФункции
Функция ОписаниеТаблицыБДЛкс(ИмяТаблицыБД) Экспорт
Возврат ирКэш.ТаблицаВсехТаблицБДЛкс().Найти(НРег(ИмяТаблицыБД), "НПолноеИмя");
КонецФункции
Функция ЛиТаблицаБДСуществуетЛкс(ИмяТаблицыБД, СообщитьОшибку = Ложь) Экспорт
Результат = Ложь;
Если ЗначениеЗаполнено(ИмяТаблицыБД) Тогда
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ 1 ИЗ " + ИмяТаблицыБД + " ГДЕ ЛОЖЬ";
Попытка
Запрос.Выполнить();
Результат = Истина;
Исключение
Результат = Ложь;
Если ЗначениеЗаполнено(ИмяТаблицыБД) И СообщитьОшибку Тогда
СообщитьЛкс(ОписаниеОшибки());
КонецЕсли;
КонецПопытки;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПредставлениеТаблицыБДЛкс(ИмяТаблицыБД) Экспорт
Если Не ЗначениеЗаполнено(ИмяТаблицыБД) Тогда
Возврат Неопределено;
КонецЕсли;
ОбъектМД = ОбъектМДПоПолномуИмениЛкс(ИмяТаблицыБД);
Если ОбъектМД <> Неопределено Тогда
Результат = ОбъектМД.Представление();
Иначе
Результат = ОписаниеТаблицыБДЛкс(ИмяТаблицыБД).Представление;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращаемое значение - всегда русский вариант
Функция ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД) Экспорт
//ОписаниеТаблицы = ирКэш.ТаблицаВсехТаблицБДЛкс().Найти(НРег(ПолноеИмяТаблицыБД), "НПолноеИмя");
//Если ОписаниеТаблицы <> Неопределено Тогда
// Возврат ОписаниеТаблицы.Тип;
//КонецЕсли;
Фрагменты = СтрРазделитьЛкс(ПолноеИмяТаблицыБД);
ТипТаблицы = Фрагменты[0];
Если Фрагменты.Количество() > 2 Тогда
ПоследнийФрагмент = Фрагменты[Фрагменты.ВГраница()];
Если Ложь
Или ПоследнийФрагмент = ПеревестиСтроку("Изменения")
Или ПоследнийФрагмент = ПеревестиСтроку("ДвиженияССубконто")
//Или ПоследнийФрагмент = "Границы"
Тогда
ТипТаблицы = ПеревестиВРусский(ПоследнийФрагмент);
//// Если ЛиКорневойТипСсылочногоОбъектаБДЛкс(МассивФрагментов[0]) Тогда
//// //ТипТаблицы = "ТабличнаяЧасть";
//// ТипТаблицы = МассивФрагментов[2];
//// КонецЕсли;
Иначе
Если Истина
И ЛиКорневойТипСсылочногоОбъектаБДЛкс(Фрагменты[0])
И НЕ (Фрагменты[0] = "Задача" И Фрагменты[Фрагменты.ВГраница()] = "ЗадачиПоИсполнителю")
Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД);
Если ОбъектМД = Неопределено Тогда
ТипТаблицы = ПеревестиВРусский(Фрагменты[2]); // ВидыРасчета, ВидыСубконто
Иначе
ТипТаблицы = "ТабличнаяЧасть";
КонецЕсли;
//ИначеЕсли СтрокиРавныЛкс(Фрагменты[2], "ДвиженияССубконто") Тогда
// ТипТаблицы = Фрагменты[0];
ИначеЕсли Истина
И Фрагменты[0] = ПеревестиСтроку("РегистрРасчета")
И ПоследнийФрагмент <> "ДанныеГрафика"
И ПоследнийФрагмент <> "ФактическийПериодДействия"
И Не СтрНачинаетсяСЛкс(ПоследнийФрагмент, ПеревестиСтроку("База"))
Тогда
ТипТаблицы = "Перерасчет";
ИначеЕсли ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(Фрагменты[0]) Тогда
ТипТаблицы = "Внешняя";
Иначе
ТипТаблицы = "ВиртуальнаяТаблица";
КонецЕсли;
КонецЕсли;
Иначе
ТипТаблицы = ПеревестиВРусский(ТипТаблицы);
КонецЕсли;
Возврат ТипТаблицы;
КонецФункции
Функция ЛиСуществуетОбъектПоСсылкеЛкс(Знач Ссылка) Экспорт
Если Не ЗначениеЗаполнено(Ссылка) Тогда
Возврат Ложь;
КонецЕсли;
Запрос = Новый Запрос("ВЫБРАТЬ 1 ИЗ " + ПолучитьПолноеИмяМДТипаЛкс(ТипЗнч(Ссылка)) + " ГДЕ Ссылка = &Ссылка");
Запрос.УстановитьПараметр("Ссылка", Ссылка);
ОбъектСуществует = Не Запрос.Выполнить().Пустой();
Возврат ОбъектСуществует;
КонецФункции
// ВариантИсточников -
//
// Параметры:
// ИменаТаблиц - -
// ВариантИсточников - Число, *0
// 0 - Основные таблицы
// 1 - Таблицы изменений
// 2 - Внутреннее соединение основных таблиц с их таблицами изменений с отбором по узлу
// ПервыеNКаждойТаблицы - -
// ПодключатьПоляКоличестваДвижений - -
// ИмяПоляПолногоИмениТаблицы - -
// ИмяПоляКоличестваСтрок - Строка - если заполнено, то используется режим выбора только количества строк!
//
// Возвращаемое значение:
// -
//
Функция ТекстЗапросаПоВыбраннымТаблицамЛкс(ИменаТаблиц, ВариантИсточников = 0, ПервыеNКаждойТаблицы = 0, ПодключатьПоляКоличестваДвижений = Ложь, ИмяПоляПолногоИмениТаблицы = Неопределено,
ИмяПоляКоличестваСтрок = "", ПредставленияПолей = Неопределено, ИменаКоличестваПодчиненных = Неопределено) Экспорт
Если ПредставленияПолей = Неопределено Тогда
ПредставленияПолей = Новый Структура;
КонецЕсли;
Если ИменаКоличестваПодчиненных = Неопределено Тогда
ИменаКоличестваПодчиненных = Новый Структура;
КонецЕсли;
ЛитералЗаменыОтсутствующихПолей = "НЕОПРЕДЕЛЕНО"; // NULL нельзя использовать из-за ошибок платформы 8.2.14
Если Не ЗначениеЗаполнено(ИмяПоляПолногоИмениТаблицы) Тогда
ИмяПоляПолногоИмениТаблицы = "_ПолноеИмяТаблицы";
КонецЕсли;
// Сначала определим общие реквизиты
СистемныеПоля = Новый Массив;
ТипыОбъектовМД = Новый Структура;
Для Каждого ИмяОбъектаМД Из ИменаТаблиц Цикл
ТипОбъектаМД = ТипТаблицыБДЛкс(ИмяОбъектаМД);
ТипыОбъектовМД.Вставить(ТипОбъектаМД);
КонецЦикла;
Если ТипыОбъектовМД.Количество() > 1 Тогда
ТипОбъектаМД = Неопределено;
КонецЕсли;
Если ЗначениеЗаполнено(ТипОбъектаМД) Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
СтрокаКорневогоТипа = мПлатформа.ОписаниеТипаМетаОбъектов(ТипОбъектаМД);
Если СтрокаКорневогоТипа <> Неопределено Тогда
СтрокаВида = мПлатформа.ТаблицаИменЭлементовКоллекций.Найти(СтрокаКорневогоТипа.Множественное, "ИмяКоллекции");
Если СтрокаВида <> Неопределено Тогда
Если СтрокиРавныЛкс(ТипОбъектаМД, "ТабличнаяЧасть") Тогда
ТипОбъектаМД = "Справочник.<Имя справочника>";
КонецЕсли;
ИмяОбщегоТипа = ТипОбъектаМД + "." + СтрокаВида.ИмяЭлементаКоллекции;
Если ВариантИсточников = 1 Тогда
ИмяОбщегоТипа = ИмяОбщегоТипа + ".Изменения";
КонецЕсли;
мПлатформа.ИнициацияОписанияМетодовИСвойств();
СтрокиИменПолей = мПлатформа.ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ТипКонтекста, ЯзыкПрограммы", ИмяОбщегоТипа, 1));
Для Каждого СтрокаСлова Из СтрокиИменПолей Цикл
Если Ложь
Или СтрокаСлова.ТипСлова = "Таблица"
Или СтрокаСлова.ТипЗначения = "РезультатЗапроса"
Или СистемныеПоля.Найти(СтрокаСлова.Слово) <> Неопределено // Для таблиц бухгалтерии могут быть дубли из-за вариантов с корреспонденцией и без
Тогда
Продолжить;
КонецЕсли;
СистемныеПоля.Добавить(СтрокаСлова.Слово);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
// Находим максимум общих реквизитов
ОбщиеМетаПоля = Новый Массив;
ОписанияТиповПолей = Новый Структура;
ЭтоПервыйПроход = Истина;
Для Каждого ИмяТаблицы Из ИменаТаблиц Цикл
ОбъектМетаданных = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы);
Если ВариантИсточников > 0 Тогда
Если ОбъектМетаданных = Неопределено Тогда
ВызватьИсключение "У таблицы " + ИмяТаблицы + " нет таблицы регистрации изменений";
КонецЕсли;
ЕстьТаблицаИзменений = ЕстьТаблицаИзмененийОбъектаМетаданных(ОбъектМетаданных);
Если ЕстьТаблицаИзменений Тогда
Если ВариантИсточников = 1 Тогда
ИмяТаблицы = ИмяТаблицы + ".Изменения";
КонецЕсли;
КонецЕсли;
КонецЕсли;
КоллекцияПолей = Новый Массив;
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицы);
Для Каждого ПолеТаблицы Из ПоляТаблицыБД Цикл
Если ПолеТаблицы.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Продолжить;
КонецЕсли;
ИмяПоля = ПолеТаблицы.Имя;
Если ОписанияТиповПолей.Свойство(ИмяПоля) Тогда
ОписанияТиповПолей[ИмяПоля] = ОбъединитьОписанияТиповЛкс(ПолеТаблицы.ТипЗначения, ОписанияТиповПолей[ИмяПоля]);
Иначе
ОписанияТиповПолей.Вставить(ИмяПоля, ПолеТаблицы.ТипЗначения);
КонецЕсли;
Если СистемныеПоля.Найти(ИмяПоля) <> Неопределено Тогда
Продолжить;
КонецЕсли;
КоллекцияПолей.Добавить(ИмяПоля);
КонецЦикла;
Если ЭтоПервыйПроход Тогда
Для Каждого ИмяПоля Из КоллекцияПолей Цикл
ОбщиеМетаПоля.Добавить(ИмяПоля);
КонецЦикла;
Иначе
НачальноеКоличество = ОбщиеМетаПоля.Количество();
Для СчетчикОбщиеМетаПоля = 1 По НачальноеКоличество Цикл
ИмяПоля = ОбщиеМетаПоля[НачальноеКоличество - СчетчикОбщиеМетаПоля];
Если КоллекцияПолей.Найти(ИмяПоля) = Неопределено Тогда
ОбщиеМетаПоля.Удалить(НачальноеКоличество - СчетчикОбщиеМетаПоля);
КонецЕсли;
КонецЦикла;
Если ОбщиеМетаПоля.Количество() = 0 Тогда
Прервать;
КонецЕсли;
КонецЕсли;
ЭтоПервыйПроход = Ложь;
КонецЦикла;
ТекстОбщихМетаПолей = "";
Для Каждого ИмяПоля Из ОбщиеМетаПоля Цикл
ПутьКПолю = ИмяПоля;
Если Истина
И ЛиКорневойТипСсылкиЛкс(ИменаТаблиц[0])
И ВариантИсточников > 0
Тогда
ПутьКПолю = "Ссылка." + ИмяПоля;
КонецЕсли;
ОписаниеТиповПоля = ОписанияТиповПолей[ИмяПоля];
ВыражениеИзменено = Ложь;
ВыражениеПоля = ВыражениеПоляСУчетомСоставногоТипаЛкс("Т." + ПутьКПолю, ОписаниеТиповПоля, ВыражениеИзменено);
Если Не ВыражениеИзменено И ЗначениеЗаполнено(ИмяПоляКоличестваСтрок) Тогда
ВыражениеПоля = ВыражениеПоля + ".*";
КонецЕсли;
ТекстОбщихМетаПолей = ТекстОбщихМетаПолей + ", " + ВыражениеПоля + " КАК " + ИмяПоля;
КонецЦикла;
Если ПодключатьПоляКоличестваДвижений И ЛиКорневойТипДокументаЛкс(ТипТаблицыБДЛкс(ИмяТаблицы)) Тогда
Движения = Новый Соответствие;
Для Каждого ИмяТаблицы Из ИменаТаблиц Цикл
ОбъектМетаданных = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы);
Для Каждого МетаРегистр Из ОбъектМетаданных.Движения Цикл
Движения[МетаРегистр] = 1;
КонецЦикла;
КонецЦикла;
ТекстОбщееЧислоДвижений = "";
ТекстОбщихУсловийСоединения = "";
ПрефиксИмениПоля = "Регистр";
Для Каждого МетаРегистр Из Движения Цикл
МетаРегистр = МетаРегистр.Ключ;
ПолноеИмяРегистра = МетаРегистр.ПолноеИмя();
КраткоеИмяРегистра = МетаРегистр.Имя + "_";
ТекстОбщихУсловийСоединения = ТекстОбщихУсловийСоединения + Символы.ПС + " { ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ _Регистр_.Регистратор, КОЛИЧЕСТВО(*) КАК КоличествоСтрок
| ИЗ " + ПолноеИмяРегистра + " КАК _Регистр_ СГРУППИРОВАТЬ ПО _Регистр_.Регистратор) КАК " + КраткоеИмяРегистра + "
| ПО " + КраткоеИмяРегистра + ".Регистратор = Т.Ссылка}";
ВыражениеКоличества = "ЕСТЬNULL(" + КраткоеИмяРегистра + ".КоличествоСтрок, 0)";
Если ТекстОбщееЧислоДвижений <> "" Тогда
ТекстОбщееЧислоДвижений = ТекстОбщееЧислоДвижений + " + ";
КонецЕсли;
ИмяПоля = "ЧислоСтрок_" + ПрефиксИмениПоля + "_" + КраткоеИмяРегистра;
ТекстОбщееЧислоДвижений = ТекстОбщееЧислоДвижений + ВыражениеКоличества;
ТекстОбщееЧислоДвижений = ВыражениеКоличества + " КАК " + ИмяПоля + ",
|" + ТекстОбщееЧислоДвижений;
ИменаКоличестваПодчиненных.Вставить(ИмяПоля, ПрефиксИмениПоля + " " + КраткоеИмяРегистра);
КонецЦикла;
Если ЗначениеЗаполнено(ТекстОбщееЧислоДвижений) Тогда
ТекстОбщихМетаПолей = ТекстОбщихМетаПолей + ",
|" + ТекстОбщееЧислоДвижений + " КАК ЧислоСтрокВсеРегистры";
ИменаКоличестваПодчиненных.Вставить("ЧислоСтрокВсеРегистры", "Все регистры");
КонецЕсли;
КонецЕсли;
#Если Клиент Тогда
Индикатор = ПолучитьИндикаторПроцессаЛкс(ИменаТаблиц.Количество(), "Генерация текста запроса");
#КонецЕсли
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("");
ЗаписьXMLПустая = Истина;
ТекстУсловияСоединения = "";
Для Каждого ИмяТаблицы Из ИменаТаблиц Цикл
#Если Клиент Тогда
ОбработатьИндикаторЛкс(Индикатор);
#КонецЕсли
ОбъектМетаданных = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы);
Если ВариантИсточников > 0 Тогда
ЕстьТаблицаИзменений = ЕстьТаблицаИзмененийОбъектаМетаданных(ОбъектМетаданных);
Если ЕстьТаблицаИзменений Тогда
Если ВариантИсточников = 1 Тогда
ИмяТаблицы = ИмяТаблицы + ".Изменения";
Иначе
ТекстУсловияСоединения = "_Изменения_.Узел = &Узел";
СтруктураКлючаИзменений = СтруктураКлючаТаблицыБДЛкс(ИмяТаблицы + ".Изменения");
Для Каждого КлючИЗначение Из СтруктураКлючаИзменений Цикл
Если СтрокиРавныЛкс(КлючИЗначение.Ключ, "Узел") Тогда
Продолжить;
КонецЕсли;
Если ТекстУсловияСоединения <> "" Тогда
ТекстУсловияСоединения = ТекстУсловияСоединения + Символы.ПС + " И";
КонецЕсли;
ТекстУсловияСоединения = ТекстУсловияСоединения + " _Изменения_." + КлючИЗначение.Ключ + " = Т." + КлючИЗначение.Ключ;
КонецЦикла;
ТекстУсловияСоединения = Символы.ПС + " ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ИмяТаблицы + ".Изменения КАК _Изменения_
| ПО " + ТекстУсловияСоединения;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ТекстНеобязательныхПолей = "";
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицы);
Для Каждого ПроверяемоеПоле Из СистемныеПоля Цикл
Если ПоляТаблицыБД.Найти(ПроверяемоеПоле, "Имя") = Неопределено Тогда
ВыражениеПоля = ЛитералЗаменыОтсутствующихПолей;
Иначе
ВыражениеПоля = "Т." + ПроверяемоеПоле;
КонецЕсли;
ВыражениеИзменено = Ложь;
Если ОписанияТиповПолей.Свойство(ПроверяемоеПоле) Тогда
ОписаниеТиповПоля = ОписанияТиповПолей[ПроверяемоеПоле];
ВыражениеПоля = ВыражениеПоляСУчетомСоставногоТипаЛкс(ВыражениеПоля, ОписаниеТиповПоля, ВыражениеИзменено);
КонецЕсли;
Если Истина
И ЗначениеЗаполнено(ИмяПоляКоличестваСтрок)
И Не ВыражениеИзменено
И ВыражениеПоля <> ЛитералЗаменыОтсутствующихПолей
Тогда
ВыражениеПоля = ВыражениеПоля + ".*";
КонецЕсли;
ТекстНеобязательныхПолей = ТекстНеобязательныхПолей + ", " + ВыражениеПоля + " КАК " + ПроверяемоеПоле;
КонецЦикла;
Если Не ЗаписьXMLПустая Тогда
ЗаписьXML.ЗаписатьБезОбработки("
|ОБЪЕДИНИТЬ ВСЕ
|");
КонецЕсли;
ЗаписьXMLПустая = Ложь;
МассивЧастейПолей = Новый Массив;
Если ЗначениеЗаполнено(ТекстНеобязательныхПолей) Тогда
МассивЧастейПолей.Добавить(Сред(ТекстНеобязательныхПолей, 2));
КонецЕсли;
Если ЗначениеЗаполнено(ТекстОбщихМетаПолей) Тогда
МассивЧастейПолей.Добавить(Сред(ТекстОбщихМетаПолей, 2));
КонецЕсли;
ТекстПолей = СтрСоединитьЛкс(МассивЧастейПолей);
ЗаписьXML.ЗаписатьБезОбработки("ВЫБРАТЬ ");
Если ЗначениеЗаполнено(ПервыеNКаждойТаблицы) Тогда
ЗаписьXML.ЗаписатьБезОбработки("ПЕРВЫЕ " + XMLСтрока(ПервыеNКаждойТаблицы) + " ");
КонецЕсли;
Если ЗначениеЗаполнено(ИмяПоляКоличестваСтрок) Тогда
ЗаписьXML.ЗаписатьБезОбработки("КОЛИЧЕСТВО(*) КАК " + ИмяПоляКоличестваСтрок + ", ");
Иначе
ЗаписьXML.ЗаписатьБезОбработки(ТекстПолей + ", ");
КонецЕсли;
ЗаписьXML.ЗаписатьБезОбработки("""" + ИмяТаблицы + """ КАК " + ИмяПоляПолногоИмениТаблицы + " ИЗ " + ИмяТаблицы + " КАК Т" + ТекстУсловияСоединения + ТекстОбщихУсловийСоединения);
Если ЗначениеЗаполнено(ИмяПоляКоличестваСтрок) Тогда
ЗаписьXML.ЗаписатьБезОбработки("
|{ГДЕ " + ТекстПолей + "}");
КонецЕсли;
КонецЦикла;
//Если ЗначениеЗаполнено(ПервыеNОбщие) Тогда
// ТекстЗапроса = "ВЫБРАТЬ ПЕРВЫЕ " + XMLСтрока(ПервыеNОбщие) + " * ИЗ (" + ТекстЗапроса + ") КАК Т";
//КонецЕсли;
ТекстЗапроса = ЗаписьXML.Закрыть();
ОсвободитьИндикаторПроцессаЛкс();
Возврат ТекстЗапроса;
КонецФункции
Функция ПолучитьТекстЗапросаСтатистикиПоТаблицеЛкс(ПолноеИмяМДИлиТаблицы, ИмяКлючевойКолонки = "ПолноеИмяОбъекта", ИмяКолонкиКоличества = "КоличествоСтрок", ЛиТаблицыИзменений = Ложь,
СтруктураОтбора = Неопределено, ТолькоРазрешенные = Ложь, ЭтоПолноеИмяТаблицы = Ложь) Экспорт
//ЗаписьXML = Новый ЗаписьXML; // Так будет дольше
ТекстЧастиОбъединения = "
|SELECT";
Если Не ЭтоПолноеИмяТаблицы Тогда
ИмяТаблицы = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМДИлиТаблицы, ЛиТаблицыИзменений, Ложь, ТолькоРазрешенные);
Если ИмяТаблицы = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ИмяРезультата = ИмяТаблицы;
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| """ + ПолноеИмяМДИлиТаблицы + """ AS " + ИмяКлючевойКолонки + ",";
Иначе
ИмяТаблицы = ПолноеИмяМДИлиТаблицы;
ИмяРезультата = ИмяТаблицы;
Если ИмяКлючевойКолонки = "ПолноеИмяКолонки" Тогда
ИмяРезультата = ИмяРезультата + "." + СтруктураОтбора.ИмяПоля;
КонецЕсли;
КонецЕсли;
Если ТипТаблицыБДЛкс(ИмяТаблицы) = "ВиртуальнаяТаблица" Тогда
Возврат Неопределено;
КонецЕсли;
//ОписаниеТаблицы = ОписаниеТаблицыБДЛкс(ИмяТаблицы);
//Если ОписаниеТаблицы.ЕстьДоступ = Ложь Тогда
// Возврат Неопределено;
//КонецЕсли;
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| """ + ИмяРезультата + """ AS ИмяТаблицы,
| COUNT(*) AS " + ИмяКолонкиКоличества + ",";
Если ЛиТаблицыИзменений Тогда
// псевдоним "Узел" нужнен для англ. встроенного языка
// ВЫРАЗИТЬ добавлено для обхода ошибки MSSQL https://www.hostedredmine.com/issues/940031
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| Т.Узел КАК Узел,
| СУММА(ВЫРАЗИТЬ(ВЫБОР КОГДА Т.НомерСообщения ЕСТЬ NULL ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК ЧИСЛО(15))) КАК КоличествоНевыгруженных,
| СУММА(ВЫРАЗИТЬ(ВЫБОР КОГДА Т.НомерСообщения ЕСТЬ NULL ТОГДА 0 ИНАЧЕ 1 КОНЕЦ КАК ЧИСЛО(15))) КАК КоличествоВыгруженных,";
КонецЕсли;
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| 1
|FROM " + ИмяТаблицы + " AS Т";
Если СтруктураОтбора <> Неопределено Тогда
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
|WHERE 1 = 1";
Если ИмяКлючевойКолонки = "ПолноеИмяКолонки" Тогда
ОписаниеПоля = ОписаниеПоляТаблицыБДЛкс(ИмяТаблицы, СтруктураОтбора.ИмяПоля);
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| И Т." + СтруктураОтбора.ИмяПоля + " " + ВыражениеСравненияСПараметромВЗапросеЛкс(ОписаниеПоля, СтруктураОтбора.ВидСравнения, СтруктураОтбора.ИмяПараметра);
Иначе
Для Каждого КлючИЗначение Из СтруктураОтбора Цикл
Если СтрокиРавныЛкс("_ТипУзла_", КлючИЗначение.Ключ) Тогда
ОпределениеПоля = "ТИПЗНАЧЕНИЯ(Т.Узел)";
Иначе
ОпределениеПоля = "Т." + КлючИЗначение.Ключ;
КонецЕсли;
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
| И " + ОпределениеПоля + " В (&" + КлючИЗначение.Ключ + ")";
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если ЛиТаблицыИзменений Тогда
ТекстЧастиОбъединения = ТекстЧастиОбъединения + "
|СГРУППИРОВАТЬ ПО Узел";
КонецЕсли;
Возврат ТекстЧастиОбъединения;
КонецФункции
// Не поддерживает таблицы внешних источников данных. Надо переделать вызывы этой функции на ирКлиент.ВычислитьКоличествоСтрокТаблицВДеревеМетаданныхЛкс
Функция ЗапросПодсчетаКоличестваСтрокСоЗначениемИзТаблицыКолонокБДЛкс(Знач СтрокиКолонокДляОбновления, Знач ЗначениеОтбора, Знач ВидСравненияНовый = Неопределено) Экспорт
ТекстЗапроса = Новый ЗаписьXML;
ТекстЗапроса.УстановитьСтроку();
ЛиТекстПустой = Истина;
Для Каждого СтрокаКолонкиБД Из СтрокиКолонокДляОбновления Цикл
Если СтрокаКолонкиБД.ТипТаблицы = "Внешняя" Тогда
Продолжить;
КонецЕсли;
// Антибаг 8.2.14 http://partners.v8.1c.ru/forum/thread.jsp?id=1017264#1017264
Если Истина
И СтрокаКолонкиБД.ТипТаблицы = "Изменения"
И Найти(СтрокаКолонкиБД.ПолноеИмяТаблицы, "РегистрСведений.") = 1
И ирКэш.ДоступноОбщиеРеквизитыЛкс()
Тогда
Если Метаданные.ОбщиеРеквизиты.Найти(СтрокаКолонкиБД.ИмяКолонки) <> Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Если Не СтрокаКолонкиБД.ЕстьДоступ Тогда
Продолжить;
КонецЕсли;
Если Не ЛиТекстПустой Тогда
ТекстЗапроса.ЗаписатьБезОбработки("
|ОБЪЕДИНИТЬ ВСЕ");
Иначе
ЛиТекстПустой = Ложь;
КонецЕсли;
ТекстЗапроса.ЗаписатьБезОбработки("
|ВЫБРАТЬ """ + СтрокаКолонкиБД.ПолноеИмяТаблицы + """ КАК ПолноеИмяТаблицы, """ + СтрокаКолонкиБД.ИмяКолонки + """ КАК ИмяКолонки, КОЛИЧЕСТВО(*) КАК Количество
|ИЗ " + СтрокаКолонкиБД.ПолноеИмяТаблицы + " КАК Т");
// Очень долгий способ
// ТекстЗапроса.ЗаписатьБезОбработки("
// |{ГДЕ Т." + СтрокаКолонкиБД.ИмяКолонки + " КАК ПолеОтбора}");
//КонецЦикла;
//Схема = СоздатьСхемуКомпоновкиПоЗапросуЛкс(ТекстЗапроса,,, Истина);
//НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
//НайтиДобавитьЭлементОтбораКомпоновкиЛкс(НастройкаКомпоновки, "ПолеОтбора", ЗначениеОтбора, ВидСравненияНовый);
//Запрос = ЗапросИзКомпоновкиЛкс(Схема, НастройкаКомпоновки);
//
ОписаниеПоля = ОписаниеПоляТаблицыБДЛкс(СтрокаКолонкиБД.ПолноеИмяТаблицы, СтрокаКолонкиБД.ИмяКолонки);
ВыражениеСравнения = ВыражениеСравненияСПараметромВЗапросеЛкс(ОписаниеПоля, ВидСравненияНовый, "ЗначениеОтбора");
ТекстЗапроса.ЗаписатьБезОбработки("
|ГДЕ Т." + СтрокаКолонкиБД.ИмяКолонки + " " + ВыражениеСравнения);
КонецЦикла;
Запрос = Новый Запрос(ТекстЗапроса.Закрыть());
Запрос.Параметры.Вставить("ЗначениеОтбора", ЗначениеОтбора);
Возврат Запрос;
КонецФункции
Функция ИмяВременнойТаблицыДляТаблицыБДЛкс(ПолноеИмяТаблицы, ИмяВременнойТаблицы = "ВТ") Экспорт
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
Если ТипТаблицы = "Внешняя" Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы, Истина);
ИмяВременнойТаблицы = ОбъектМД.Родитель().ПолноеИмя() + ".ВременнаяТаблица." + ИмяВременнойТаблицы;
КонецЕсли;
Возврат ИмяВременнойТаблицы;
КонецФункции
Функция ОписаниеПоляТаблицыБДЛкс(Знач ИмяТаблицыИлиПолноеИмяПоля, Знач ИмяПоля = "") Экспорт
Если Не ЗначениеЗаполнено(ИмяПоля) Тогда
ИмяПоля = ПоследнийФрагментЛкс(ИмяТаблицыИлиПолноеИмяПоля);
ИмяТаблицыИлиПолноеИмяПоля = СтрокаБезПоследнегоФрагментаЛкс(ИмяТаблицыИлиПолноеИмяПоля);
КонецЕсли;
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицыИлиПолноеИмяПоля);
ОписаниеПоля = ПоляТаблицыБД.Найти(ИмяПоля, "Имя");
Возврат ОписаниеПоля;
КонецФункции
// Вызывается из адаптера
Функция ИмяТипаПоляТаблицыБДЛкс(Знач ИмяТаблицыИлиПолноеИмяПоля, Знач ИмяПоля = "") Экспорт
ОписаниеПоля = ОписаниеПоляТаблицыБДЛкс(ИмяТаблицыИлиПолноеИмяПоля, ИмяПоля);
Если ОписаниеПоля = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Возврат ИмяТипаЛкс(ОписаниеПоля.ТипЗначения.Типы()[0]);
КонецФункции
Функция ПолноеИмяМДПоляТаблицыЛкс(ПолеТаблицыБД) Экспорт
Попытка
ПолноеИмя = ПолеТаблицыБД.Метаданные.ПолноеИмя();
Исключение
ПолноеИмя = "";
КонецПопытки;
Возврат ПолноеИмя;
КонецФункции
Функция ВыражениеСравненияСПараметромВЗапросеЛкс(Знач ОписаниеПоля, Знач ВидСравненияНовый, Знач ИмяПараметра) Экспорт
Если ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ОписаниеПоля.ТипЗначения) Тогда
ВидСравненияНовый = ВидСравненияКомпоновкиДанных.Содержит;
КонецЕсли;
Если ОписаниеПоля.Имя = "ИмяПредопределенныхДанных" Тогда
ВыражениеСравнения = " = NULL"; // Пустой результат без ошибки выполнения
ИначеЕсли Истина
И ОписаниеПоля.Имя <> "ВерсияДанных"
И ВидСравненияНовый = ВидСравненияКомпоновкиДанных.Содержит
Тогда
ВыражениеСравнения = "ПОДОБНО ""%"" + &" + ИмяПараметра + " + ""%""";
Иначе
ВыражениеСравнения = "В (&" + ИмяПараметра + ")";
КонецЕсли;
Возврат ВыражениеСравнения;
КонецФункции
// https://www.hostedredmine.com/issues/896348
// Параметры:
// ВыражениеПоля - Строка -
// ОписаниеТиповПоля - ОписаниеТипов -
Функция ВыражениеПоляСУчетомСоставногоТипаЛкс(Знач ВыражениеПоля, ОписаниеТиповПоля, выхВыражениеИзменено = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТиповПоля = Новый ОписаниеТипов;
#КонецЕсли
выхВыражениеИзменено = Ложь;
Если Истина
И ОписаниеТиповПоля.Типы().Количество() > 1
И ОписаниеТиповПоля.СодержитТип(Тип("Строка"))
Тогда
// https://www.hostedredmine.com/issues/896348
ВыражениеПоля = "
| ВЫБОР КОГДА ЛОЖЬ ТОГДА """" ИНАЧЕ
| " + ВыражениеПоля + " КОНЕЦ";
выхВыражениеИзменено = Истина;
КонецЕсли;
Возврат ВыражениеПоля;
КонецФункции
Функция ТекстЗапросаПоместитьИзПараметраЛкс(Знач ИмяТаблицы = "ВТ", Знач ИмяПараметра = "ТЗ", Знач ЯвноВыбратьКаждоеПоле = Ложь, Знач Колонки = Неопределено, Знач ДобавитьЗапросВыборки = Ложь,
Знач ДекларироватьТипы = Ложь) Экспорт
Если ЯвноВыбратьКаждоеПоле Тогда
#Если Сервер И Не Сервер Тогда
Колонки = Новый ТаблицаЗначений;
Колонки = Колонки.Колонки;
#КонецЕсли
ВыраженияПолей = Новый Массив;
Для Каждого Колонка Из Колонки Цикл
ВыражениеПоля = "Т." + Колонка.Имя;
Если ДекларироватьТипы Тогда
ТекстыТипов = Новый Массив;
ТекстыТипов.Добавить("ВЫБОР
| КОГДА ИСТИНА
| ТОГДА " + ВыражениеПоля);
Для Каждого ТипПоля Из Колонка.ТипЗначения.Типы() Цикл
ТекстыТипов.Добавить("
| КОГДА ЛОЖЬ
| ТОГДА " + ВыражениеПриведенияТипаНаЯзыкеЗапросовЛкс(ТипПоля, Колонка.ТипЗначения));
КонецЦикла;
ТекстыТипов.Добавить("
|КОНЕЦ КАК " + Колонка.Имя);
ВыражениеПоля = СтрСоединитьЛкс(ТекстыТипов, "");
КонецЕсли;
ВыраженияПолей.Добавить(ВыражениеПоля);
КонецЦикла;
ВыраженияПолей = "
| " + СтрСоединитьЛкс(ВыраженияПолей, "," + Символы.ПС);
Иначе
ВыраженияПолей = "*";
КонецЕсли;
ТекстЗапросаПоместить =
"ВЫБРАТЬ " + ВыраженияПолей + "
|ПОМЕСТИТЬ " + ИмяТаблицы + " ИЗ &" + ИмяПараметра + " КАК Т";
Если ДобавитьЗапросВыборки Тогда
ТекстЗапросаПоместить = ТекстЗапросаПоместить + ";
|ВЫБРАТЬ * ИЗ " + ИмяТаблицы + " КАК " + ИмяТаблицы;
КонецЕсли;
Возврат ТекстЗапросаПоместить;
КонецФункции
Функция ЕстьТаблицаИзмененийОбъектаМетаданных(ПолноеИмяИлиОбъектМетаданных) Экспорт
ЕстьТаблицаИзменений = Ложь;
Если ТипЗнч(ПолноеИмяИлиОбъектМетаданных) = Тип("Строка") Тогда
ОбъектМетаданных = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяИлиОбъектМетаданных);
Если ОбъектМетаданных = Неопределено Тогда
ВызватьИсключение "Объект метаданных не найден """ + ПолноеИмяИлиОбъектМетаданных + """";
КонецЕсли;
Иначе
ОбъектМетаданных = ПолноеИмяИлиОбъектМетаданных;
КонецЕсли;
//// Способ 1
//Для Каждого МетаПланОбмена Из Метаданные.ПланыОбмена Цикл
// Если МетаПланОбмена.Состав.Содержит(ОбъектМетаданных) Тогда // Долго на больших конфигурациях
// ЕстьТаблицаИзменений = Истина;
// Прервать;
// КонецЕсли;
//КонецЦикла;
//// Способ 2
//Запрос = Новый Запрос("ВЫБРАТЬ 1 ИЗ " + ирКэш.ИмяТаблицыИзМетаданныхЛкс(ОбъектМетаданных.ПолноеИмя(), Истина) + " КАК Т");
//Попытка
// Запрос.НайтиПараметры(); // Долго, но стабильно. Длительность не зависит от количества планов обмена
// ЕстьТаблицаИзменений = Истина;
//Исключение
// //Описание = ОписаниеОшибки();
// Пустышка = 1;
//КонецПопытки;
//// Способ 3
//Массив = Новый Массив;
//Массив.Добавить(ОбъектМетаданных);
//СтруктураХранения = ПолучитьСтруктуруХраненияБазыДанных(Массив); // очень долго
//ЕстьТаблицаИзменений = СтруктураХранения.Найти("РегистрацияИзменений", "Назначение") <> Неопределено;
// Способ 4 Быстрый при небольшом количестве планов обмена, а при большом?
ОбъектыМетаданныхСРегистрациейИзменений = ирКэш.ОбъектыМетаданныхСРегистрациейИзменений();
ЕстьТаблицаИзменений = ОбъектыМетаданныхСРегистрациейИзменений[ОбъектМетаданных.ПолноеИмя()] <> Неопределено;
Возврат ЕстьТаблицаИзменений;
КонецФункции
Функция ПрочитатьНаборЗаписейВТаблицуЛкс(НаборЗаписей, НовыйРежимБлокировки = Неопределено) Экспорт
Если НовыйРежимБлокировки <> Неопределено Тогда
ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, Истина, НовыйРежимБлокировки);
КонецЕсли;
ЭтоИмитатор = Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И (Ложь
Или ТипЗнч(НаборЗаписей) = Тип("ОбработкаОбъект.ирИмитаторНаборЗаписей"));
Если ЭтоИмитатор Тогда
#Если Сервер И Не Сервер Тогда
НаборЗаписей = Обработки.ирИмитаторНаборЗаписей.Создать();
#КонецЕсли
НаборЗаписей.Прочитать(, Ложь);
Результат = НаборЗаписей.Выгрузить();
Иначе
#Если Сервер И Не Сервер Тогда
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
#КонецЕсли
Данные = НаборЗаписей;
ПолноеИмяМД = НаборЗаписей.Метаданные().ПолноеИмя();
КорневойТип = ПервыйФрагментЛкс(ПолноеИмяМД);
Если ЛиКорневойТипРегистраБухгалтерииЛкс(КорневойТип) Тогда
// Чтобы в таблице правильно расставились субконто https://partners.v8.1c.ru/forum/t/1168440/m/1711008
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ Т.*
|ИЗ " + ПолноеИмяМД + "." + ПеревестиСтроку("ДвиженияССубконто") + "(,, Регистратор = &Регистратор) КАК Т
|";
Запрос.УстановитьПараметр("Регистратор", НаборЗаписей.Отбор.Регистратор.Значение);
ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, Истина, РежимБлокировкиДанных.Разделяемый);
// Избавиться от NULL в колонках видов субконто надо, чтобы потом метод Загрузить не выдавал ошибку
Результат = ТаблицаСКолонкамиБезТипаNullЛкс(Запрос.Выполнить().Выгрузить());
Иначе
НаборЗаписей.Прочитать();
Результат = НаборЗаписей.Выгрузить();
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СериализоватьДополнительныеСвойстваОбъектаЛкс(Объект, ВызыватьИсключение = Истина) Экспорт
Структура = Новый Структура;
СтруктураОбменаДанными = СтруктураОбменаДаннымиОбъектаЛкс(Объект);
Если СтруктураОбменаДанными <> Неопределено Тогда
Структура.Вставить("ОбменДанными", СтруктураОбменаДанными);
КонецЕсли;
Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта") Тогда
ДополнительныеСвойстваXML = ОбъектВСтрокуXMLЛкс(Объект.ДополнительныеСвойства,,, ВызыватьИсключение);
Структура.Вставить("ДополнительныеСвойстваXML", ДополнительныеСвойстваXML);
КонецЕсли;
Возврат Структура;
КонецФункции
Функция СтруктураОбменаДаннымиОбъектаЛкс(Знач Объект = Неопределено) Экспорт
Попытка
ОбменДаннымиМой = Объект.ОбменДанными;
Исключение
// Элемент плана обмена в 8.3.4-
ОбменДаннымиМой = Неопределено;
КонецПопытки;
Узлы = Новый Массив;
Если ОбменДаннымиМой <> Неопределено Тогда
Попытка
Получатели = ОбменДаннымиМой.Получатели;
Исключение
// Элемент плана обмена в 8.3.5+
Получатели = Неопределено;
КонецПопытки;
Если Получатели <> Неопределено Тогда
Для Каждого Получатель Из ОбменДаннымиМой.Получатели Цикл
Узлы.Добавить(Получатель);
КонецЦикла;
Автозаполнение = ОбменДаннымиМой.Получатели.Автозаполнение;
Отправитель = ОбменДаннымиМой.Отправитель;
Загрузка = ОбменДаннымиМой.Загрузка;
КонецЕсли;
КонецЕсли;
Получатели = Новый Структура;
Получатели.Вставить("Автозаполнение", Автозаполнение = Ложь);
Получатели.Вставить("Узлы", Узлы);
Результат = Новый Структура;
Результат.Вставить("Загрузка", Загрузка = Истина);
Результат.Вставить("Отправитель", Отправитель);
Результат.Вставить("Получатели", Получатели);
Возврат Результат;
КонецФункции // СериализоватьПараметрыОбменаДанными()
Процедура ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, СтруктураДополнительныхСвойств) Экспорт
Если СтруктураДополнительныхСвойств.Свойство("ОбменДанными") Тогда
ВосстановитьСтруктуруОбменаДаннымиОбъектаЛкс(Объект, СтруктураДополнительныхСвойств.ОбменДанными);
КонецЕсли;
Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта") Тогда
ДополнительныеСвойства = ОбъектИзСтрокиXMLЛкс(СтруктураДополнительныхСвойств.ДополнительныеСвойстваXML);
Если ДополнительныеСвойства <> Неопределено Тогда
СкопироватьКоллекциюЛкс(ДополнительныеСвойства, Объект.ДополнительныеСвойства);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ВосстановитьСтруктуруОбменаДаннымиОбъектаЛкс(Знач Объект, Знач СтруктураОбменаДанными) Экспорт
Если СтруктураОбменаДанными = Неопределено Тогда
Возврат;
КонецЕсли;
Попытка
ОбменДаннымиМой = Объект.ОбменДанными; // ПараметрыОбменаДанными
Исключение
// Элемент плана обмена в 8.3.4-
Возврат;
КонецПопытки;
ЗаполнитьЗначенияСвойств(ОбменДаннымиМой, СтруктураОбменаДанными, "Загрузка");
Попытка
Получатели = Объект.Получатели;
Исключение
// Элемент плана обмена в 8.3.5+
Возврат;
КонецПопытки;
Если СтруктураОбменаДанными.Свойство("Получатели") Тогда
ЗаполнитьЗначенияСвойств(ОбменДаннымиМой.Получатели, СтруктураОбменаДанными.Получатели);
ОбменДаннымиМой.Получатели.Очистить();
Для Каждого Получатель Из СтруктураОбменаДанными.Получатели.Узлы Цикл
ОбменДаннымиМой.Получатели.Добавить(Получатель);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Записывает объект с параметризованным контекстом (клиент/сервер).
// Обеспечивает запись объекта с попытками. Позволяет обойти неинтенсивные дедлоки и превышения ожиданий блокировки.
// Также обеспечивает обход оптимистичных объектных блокировок в случае, если в БД пишутся точно те же данные объекта, что и актуальные.
// Эффективно для многопоточной записи объектов.
//
// Параметры:
// Объект - ОбъектБД - может вернуться другой экземпляр объекта, если имитаторы недоступны и объект записывается на сервере
// ЛиПервичныйВызов - Булево - не рекомендуется изменять
// РежимЗаписи - РежимЗаписиДокумента, Булево -
// РежимПроведения - -
// ОтключатьКонтрольЗаписи - -
// БезАвторегистрацииИзменений - -
// ПривилегированныйРежим - -
// ОтключатьЗаписьВерсии - -
// ПроверятьЗаполнение - -
// АдресСообщений - Строка - имя общей настройки, куда сервер сохранит накопленные сообщения пользователю
//
Процедура ЗаписатьОбъектЛкс(Объект, Знач ЛиПервичныйВызов = Истина, Знач РежимЗаписи = Неопределено, Знач РежимПроведения = Неопределено, Знач ОтключатьКонтрольЗаписи = Неопределено,
Знач БезАвторегистрацииИзменений = Неопределено, Знач ПривилегированныйРежим = Неопределено, ОтключатьЗаписьВерсии = Неопределено, Знач ПроверятьЗаполнение = Неопределено, АдресСообщений = 0) Экспорт
//#Если Сервер И Не Клиент Тогда
// НаСервере = Ложь;
//#КонецЕсли
Если ЛиПервичныйВызов Тогда
ПараметрыЗаписи = ирКэш.ПараметрыЗаписиОбъектовЛкс();
НаСервере = ПараметрыЗаписи.ОбъектыНаСервере;
Если ОтключатьКонтрольЗаписи = Неопределено Тогда
ОтключатьКонтрольЗаписи = ПараметрыЗаписи.ОтключатьКонтрольЗаписи;
КонецЕсли;
Если ПроверятьЗаполнение = Неопределено Тогда
ПроверятьЗаполнение = ПараметрыЗаписи.ПроверятьЗаполнение;
КонецЕсли;
Если ОтключатьЗаписьВерсии = Неопределено Тогда
ОтключатьЗаписьВерсии = ПараметрыЗаписи.ОтключатьЗаписьВерсии;
КонецЕсли;
Если БезАвторегистрацииИзменений = Неопределено Тогда
БезАвторегистрацииИзменений = ПараметрыЗаписи.БезАвторегистрацииИзменений;
КонецЕсли;
Если ПривилегированныйРежим = Неопределено Тогда
ПривилегированныйРежим = ПараметрыЗаписи.ПривилегированныйРежим;
КонецЕсли;
Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта") Тогда
УстановитьДопСвойстваИзПарамертовЗаписиОбъектаЛкс(Объект, ПараметрыЗаписи);
КонецЕсли;
Иначе
НаСервере = Ложь;
//Если ОтключатьКонтрольЗаписи = Неопределено Тогда
// ОтключатьКонтрольЗаписи = Ложь; // Мешает изменению идентфикатора объекта
//КонецЕсли;
Если ПроверятьЗаполнение = Неопределено Тогда
ПроверятьЗаполнение = Ложь;
КонецЕсли;
Если ОтключатьЗаписьВерсии = Неопределено Тогда
ОтключатьЗаписьВерсии = Ложь;
КонецЕсли;
Если БезАвторегистрацииИзменений = Неопределено Тогда
БезАвторегистрацииИзменений = Ложь;
КонецЕсли;
Если ПривилегированныйРежим = Неопределено Тогда
ПривилегированныйРежим = Ложь;
КонецЕсли;
КонецЕсли;
Если НаСервере И НаКлиентеИДоступенСерверныйВызовЛкс() Тогда
ТипОбъекта = ТипЗнч(Объект);
ЭтоИмитатор = ЛиТипИмитатораОбъектаЛкс(ТипОбъекта);
Если ЭтоИмитатор Тогда
ОбъектXML = Объект.Снимок(, Ложь);
Иначе
ДополнительныеСвойства = СериализоватьДополнительныеСвойстваОбъектаЛкс(Объект);
ОбъектXML = ОбъектВСтрокуXMLЛкс(Объект);
КонецЕсли;
ирСервер.ЗаписатьОбъектXMLЛкс(ОбъектXML, ДополнительныеСвойства, РежимЗаписи, РежимПроведения, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений, ТипОбъекта, ПривилегированныйРежим,
ОтключатьЗаписьВерсии, ПроверятьЗаполнение, АдресСообщений);
Если ЭтоИмитатор Тогда
Объект.ЗагрузитьСнимок(ОбъектXML);
Иначе
Объект = ОбъектИзСтрокиXMLЛкс(ОбъектXML);
ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, ДополнительныеСвойства);
КонецЕсли;
//#Если Клиент Тогда
// Попытка
// СсылкаОбъекта = Объект.Ссылка;
// Исключение
// КонецПопытки;
// Если СсылкаОбъекта <> Неопределено Тогда
// // При групповых обработках видимо будут большие потери
// ОповеститьОбИзменении(СсылкаОбъекта);
// КонецЕсли;
//#КонецЕсли
Иначе
#Если Сервер И Не Сервер Тогда
Объект = Справочники.ирАлгоритмы.СоздатьЭлемент();
#КонецЕсли
Если ПривилегированныйРежим Тогда
УстановитьПривилегированныйРежимЛкс();
КонецЕсли;
Если ТипЗнч(Объект) <> Тип("УдалениеОбъекта") Тогда
НаборЗаписейПослеЗагрузкиИзТаблицыЗначенийЛкс(Объект);
КонецЕсли;
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъектаБДЛкс(Объект));
Если Истина
И ПроверятьЗаполнение
И ОтключатьКонтрольЗаписи <> Истина
И ирКэш.НомерРежимаСовместимостиЛкс() >= 802000
И Не ЛиКорневойТипПоследовательностиЛкс(ОбъектМД.ПолноеИмя()) // Обход аварийного завершения https://www.hostedredmine.com/issues/963555
Тогда
Если Не Объект.ПроверитьЗаполнение() Тогда
Если ЗначениеЗаполнено(АдресСообщений) Тогда
Сообщения = МассивИзКоллекцииЛкс(ПолучитьСообщенияПользователю());
// Временное хранилище пока нельзя использовать для этой цели из-за ошибки платформы https://www.hostedredmine.com/issues/957168
//ПоместитьВоВременноеХранилище(Сообщения, АдресСообщений);
СохранитьЗначениеЛкс(АдресСообщений, Сообщения);
КонецЕсли;
ВызватьИсключение "Не пройдена проверка заполнения";
КонецЕсли;
КонецЕсли;
Если ОтключатьКонтрольЗаписи = Истина Тогда
ОтключатьКонтрольЗаписи = Ложь
Или РежимЗаписи = Неопределено
Или РежимЗаписи = РежимЗаписиДокумента.Запись;
КонецЕсли;
НачалоПопыток = ТекущаяДата();
// Для обхода дедлоков и оптимистичной объектной блокировки при высокой параллельности
Если РежимЗаписи = Неопределено Тогда
ПопытокЗаписиОбъекта = 5;
Иначе
ПопытокЗаписиОбъекта = 3;
КонецЕсли;
ПредельнаяДлительность = 20;
Для СчетчикПопыток = 1 По ПопытокЗаписиОбъекта Цикл
УстановитьПараметрыЗаписиОбъектаЛкс(Объект, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений, ОтключатьЗаписьВерсии);
Попытка
Если РежимЗаписи = Неопределено Тогда
Объект.Записать();
ИначеЕсли РежимЗаписи = "ПометкаУдаления" Тогда
Объект.Записать();
Объект.ОбменДанными.Загрузка = Ложь;
Если Не ирКэш.ЛиПортативныйРежимЛкс() И ТипЗнч(Объект) = Тип("ОбработкаОбъект.ирИмитаторСсылочныйОбъект") Тогда
ПометкаУдаления = Объект.Данные.ПометкаУдаления;
Иначе
ПометкаУдаления = Объект.ПометкаУдаления;
КонецЕсли;
Объект.УстановитьПометкуУдаления(Не ПометкаУдаления);
ИначеЕсли Истина
И ТипЗнч(РежимЗаписи) = Тип("РежимЗаписиДокумента")
И РежимЗаписи <> РежимЗаписиДокумента.Запись
Тогда
//: Объект = 0 // ДокументОбъект
Объект.ОбменДанными.Загрузка = Ложь;
Объект.Записать(РежимЗаписи, РежимПроведения);
Иначе
//: Объект = 0 // РегистрСведенийНаборЗаписей
Объект.Записать(РежимЗаписи);
КонецЕсли;
Прервать;
Исключение
НужноВызватьИсключение = Истина;
ОписаниеОшибки = ОписаниеОшибки();
НовоеОписаниеОшибки = "";
Если ТранзакцияАктивна() Тогда
//НовоеОписаниеОшибки = "Транзакция активна" + Символы.ПС + ОписаниеОшибки;
Иначе
НОписаниеОшибки = НРег(ОписаниеОшибки);
Если Истина
И РежимЗаписи = Неопределено
И (Ложь
Или Найти(НОписаниеОшибки, "несоответствия версии или отсутствия записи базы данных") > 0
Или Найти(НОписаниеОшибки, "version mismatch or lack of database record") > 0)
Тогда
НужноВызватьИсключение = Ложь;
ТекущийXML = ОбъектВСтрокуXMLЛкс(Объект, Ложь);
//Объект.Прочитать(); // Чтение с блокировкой нам не нужно
ОбъектДляСравнения = ПеречитатьОбъектЗапросомЛкс(Объект);
Если Объект <> Неопределено Тогда
НовыйXML = ОбъектВСтрокуXMLЛкс(ОбъектДляСравнения, Ложь);
Если ТекущийXML = НовыйXML Тогда
Прервать;
Иначе
Попытка
лРежимЗагрузка = Объект.ОбменДанными.Загрузка;
Исключение
лРежимЗагрузка = Неопределено;
КонецПопытки;
ПолноеИмяМД = Объект.Метаданные().ПолноеИмя();
Если лРежимЗагрузка = Истина И СчетчикПопыток = 2 Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Возможно в обработчиках ПередЗаписью объекта %1 в режиме Загрузка выполняется его нестабильная модификация",, ПолноеИмяМД));
КонецЕсли;
НужноВызватьИсключение = СчетчикПопыток = ПопытокЗаписиОбъекта;
Если НужноВызватьИсключение Тогда
НовоеОписаниеОшибки = "Обход оптимистичной блокировки объекта " + ПолноеИмяМД + " отменен из-за его нестабильной модификации в обработчиках ПередЗаписью (Загрузка="
+ XMLСтрока(лРежимЗагрузка) + ")" + Символы.ПС + ОписаниеОшибки;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ИначеЕсли Ложь
Или Найти(ОписаниеОшибки, "взаимоблокировк") > 0
Или Найти(ОписаниеОшибки, "deadlock") > 0
Тогда
НужноВызватьИсключение = Ложь;
КонецЕсли;
КонецЕсли;
Если Не НужноВызватьИсключение Тогда
Если СчетчикПопыток = ПопытокЗаписиОбъекта Тогда
//НовоеОписаниеОшибки = "Кончились попытки записи" + Символы.ПС + ОписаниеОшибки;
НужноВызватьИсключение = Истина;
ИначеЕсли ТекущаяДата() - НачалоПопыток >= ПредельнаяДлительность Тогда
//НовоеОписаниеОшибки = "Кончилось время записи" + Символы.ПС + ОписаниеОшибки;
НужноВызватьИсключение = Истина;
ИначеЕсли СчетчикПопыток = ПопытокЗаписиОбъекта Тогда
//НовоеОписаниеОшибки = "Кончились попытки записи" + Символы.ПС + ОписаниеОшибки;
НужноВызватьИсключение = Истина;
КонецЕсли;
КонецЕсли;
#Если Клиент Тогда
Если ВОписанииОшибкиЕстьПередачаМутабельногоЗначенияЛкс(НОписаниеОшибки, Ложь) Тогда
ВызватьИсключение;
КонецЕсли;
#КонецЕсли
Если НужноВызватьИсключение Тогда
СостояниеОбъекта = ПредставлениеДопСвойствОбъектаЛкс(Объект);
Если ЗначениеЗаполнено(СостояниеОбъекта) Тогда
Если ЗначениеЗаполнено(НовоеОписаниеОшибки) Тогда
НовоеОписаниеОшибки = НовоеОписаниеОшибки + СостояниеОбъекта;
Иначе
НовоеОписаниеОшибки = ОписаниеОшибки + СостояниеОбъекта;
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(НовоеОписаниеОшибки) Тогда
ВызватьИсключение НовоеОписаниеОшибки;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецЕсли;
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура УстановитьПривилегированныйРежимЛкс() Экспорт
ТребоватьРольИРЛкс();
УстановитьПривилегированныйРежим(Истина);
КонецПроцедуры
Процедура ТребоватьРольИРЛкс() Экспорт
Если Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И Не ПравоДоступа("Использование", Метаданные.Обработки.ирКонсольКода)
Тогда
ВызватьИсключение "Требуется роль ирРазработчик или ирОтладкаПользователя из подсистемы ""Инструменты разработчика Tormozit""";
КонецЕсли;
КонецПроцедуры
Функция ВОписанииОшибкиЕстьПередачаМутабельногоЗначенияЛкс(Знач ОписаниеОшибки, ЭтоПроизвольныйАлгоритм = Ложь, Знач ЛиМодально = Ложь) Экспорт
Результат = Ложь;
Если Истина
//И (Ложь
// Или Не ирКэш.ЛиПортативныйРежимЛкс()
// Или ирПортативный.ЛиСерверныйМодульДоступенЛкс())
И Найти(ОписаниеОшибки, "мутабельн") > 0
И Найти(ОписаниеОшибки, "Записать") > 0
Тогда
ТекстСообщения = "Чтобы избежать ошибки передачи мутабельного значения при записи объектов, используйте ";
Если ирКэш.ЛиПортативныйРежимЛкс() И Не ирПортативный.ЛиСерверныйМодульДоступенЛкс() Тогда
ТекстСообщения = ТекстСообщения + " вариант ""Расширение"" http://devtool1c.ucoz.ru/index/rasshirenie_variant/0-52";
Иначе
Если ЭтоПроизвольныйАлгоритм Тогда
ТекстСообщения = ТекстСообщения + "функцию ""ирОбщий.ЗаписатьОбъектЛкс(Объект)""";
Иначе
ТекстСообщения = ТекстСообщения + "опцию ""Запись на сервере"" инструмента";
КонецЕсли;
КонецЕсли;
СообщитьЛкс(ТекстСообщения, СтатусСообщения.Внимание);
Результат = Истина;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура УстановитьДопСвойстваИзПарамертовЗаписиОбъектаЛкс(Знач Объект, Знач ПараметрыЗаписи) Экспорт
#Если Сервер И Не Сервер Тогда
ПараметрыЗаписи = ирКэш.ПараметрыЗаписиОбъектовЛкс();
#КонецЕсли
Для Каждого СтрокаДопСвойства Из ПараметрыЗаписи.ДополнительныеСвойства.НайтиСтроки(Новый Структура("Пометка", Истина)) Цикл
Объект.ДополнительныеСвойства.Вставить(СтрокаДопСвойства.Имя, СтрокаДопСвойства.РасширенноеЗначение);
КонецЦикла;
КонецПроцедуры
// https://www.hostedredmine.com/issues/965654
Функция НаКлиентеИДоступенСерверныйВызовЛкс() Экспорт
Если ирКэш.ЛиФайловаяБазаЛкс() Тогда
// Другого способа понять это в файловом режиме нет. Нельзя кэшировать, т.к. в файловом режиме кэш не делится на клиент и сервер.
Массив = Новый Массив;
Результат = Массив <> ирСервер.ВернутьПараметрЛкс(Массив);
Иначе
Результат = Ложь
#Если Не Сервер Тогда
Или Истина
#КонецЕсли
;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиТипИмитатораОбъектаЛкс(ТипОбъекта) Экспорт
ЭтоИмитатор = Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И (Ложь
Или ТипОбъекта = Тип("ОбработкаОбъект.ирИмитаторНаборЗаписей")
Или ТипОбъекта = Тип("ОбработкаОбъект.ирИмитаторКонстантаМенеджер")
Или ТипОбъекта = Тип("ОбработкаОбъект.ирИмитаторСсылочныйОбъект"));
Возврат ЭтоИмитатор;
КонецФункции
// Параметры:
// НаборЗаписейКуда - НаборЗаписей, ирИмитаторНаборЗаписей
// КоллекцияПолученаВыгрузкойНабора - Булево - используется при ЗаполнитьВидыСубконто = Истина
Процедура ЗагрузитьКоллекциюВНаборЗаписейЛкс(КоллекцияСтрокДвижений, НаборЗаписейКуда, ЗаполнитьВидыСубконто = Ложь, КоллекцияПолученаВыгрузкойНабора = Ложь) Экспорт
ТаблицаДляЗагрузки = НаборЗаписейКуда.ВыгрузитьКолонки();
Для Каждого СтрокаНовойТаблицы Из КоллекцияСтрокДвижений Цикл
ЗаполнитьЗначенияСвойств(ТаблицаДляЗагрузки.Добавить(), СтрокаНовойТаблицы);
КонецЦикла;
Если ЗаполнитьВидыСубконто Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъектаБДЛкс(НаборЗаписейКуда));
КорневойТип = ПервыйФрагментЛкс(ОбъектМД.ПолноеИмя());
Если ЛиКорневойТипРегистраБухгалтерииЛкс(КорневойТип) Тогда
ЗаполнитьВидыСубконтоВТаблицеЛкс(ТаблицаДляЗагрузки, ОбъектМД, КоллекцияПолученаВыгрузкойНабора);
КонецЕсли;
КонецЕсли;
НаборЗаписейКуда.Загрузить(ТаблицаДляЗагрузки);
//НаборЗаписейПослеЗагрузкиИзТаблицыЗначенийЛкс(НаборЗаписейКуда); //Теперь это делается в ЗаписатьОбъектЛкс()
КонецПроцедуры
Процедура ЗаполнитьВидыСубконтоВТаблицеЛкс(ТаблицаДляЗагрузки, ОбъектМД, ТаблицаПолученаВыгрузкойНабора = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаДляЗагрузки = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
ОбъектМД = ТаблицаДляЗагрузки.Метаданные();
#КонецЕсли
СписокСчетов = Новый Массив;
Для Каждого Проводка Из ТаблицаДляЗагрузки Цикл
СписокСчетов.Добавить(Проводка.СчетДт);
СписокСчетов.Добавить(Проводка.СчетКт);
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Т.НомерСтроки КАК НомерСтроки,
| Т.ВидСубконто КАК ВидСубконто,
| Т.Ссылка КАК Ссылка
|ИЗ
| " + ОбъектМД.ПланСчетов.ПолноеИмя() + ".ВидыСубконто КАК Т
|ГДЕ
| Т.Ссылка В(&Счет)
|УПОРЯДОЧИТЬ ПО ВидСубконто
|";
// Порядок видов субконто в Набор.Выгрузить() и "ВЫБРАТЬ * ИЗ Регистр" могут не совпадать https://partners.v8.1c.ru/forum/t/1168440/m/1711008
Запрос.УстановитьПараметр("Счет", СписокСчетов);
ТаблицаВидовСубконто = Запрос.Выполнить().Выгрузить();
МассивСторон = Новый Массив;
МассивСторон.Добавить("Дт");
МассивСторон.Добавить("Кт");
Для Каждого Проводка Из ТаблицаДляЗагрузки Цикл
Для Каждого Сторона Из МассивСторон Цикл
СтрокиВидовСубконто = ТаблицаВидовСубконто.НайтиСтроки(Новый Структура("Ссылка", Проводка["Счет" + Сторона]));
Счетчик = 1;
Для Каждого СтрокаВидаСубконто Из СтрокиВидовСубконто Цикл
Если ТаблицаПолученаВыгрузкойНабора Тогда
НомерСубконто = Счетчик;
Иначе
НомерСубконто = СтрокаВидаСубконто.НомерСтроки;
КонецЕсли;
Проводка["ВидСубконто" + Сторона + НомерСубконто] = СтрокаВидаСубконто.ВидСубконто;
Счетчик = Счетчик + 1;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Процедура УстановитьПометкуУдаленияОбъектаЛкс(Объект, НаСервере = Неопределено, ЗначениеПометки = Истина, БезАвторегистрацииИзменений = Неопределено,
ПривилегированныйРежим = Неопределено, ОтключатьЗаписьВерсии = Неопределено) Экспорт
Если НаСервере = Неопределено Тогда
ПараметрыЗаписи = ирКэш.ПараметрыЗаписиОбъектовЛкс();
Если НаСервере = Неопределено Тогда
НаСервере = ПараметрыЗаписи.ОбъектыНаСервере;
КонецЕсли;
Если БезАвторегистрацииИзменений = Неопределено Тогда
БезАвторегистрацииИзменений = ПараметрыЗаписи.БезАвторегистрацииИзменений;
КонецЕсли;
Если ПривилегированныйРежим = Неопределено Тогда
ПривилегированныйРежим = ПараметрыЗаписи.ПривилегированныйРежим;
КонецЕсли;
Если ОтключатьЗаписьВерсии = Неопределено Тогда
ОтключатьЗаписьВерсии = ПараметрыЗаписи.ОтключатьЗаписьВерсии;
КонецЕсли;
УстановитьДопСвойстваИзПарамертовЗаписиОбъектаЛкс(Объект, ПараметрыЗаписи);
КонецЕсли;
Если НаСервере Тогда
ТипОбъекта = ТипЗнч(Объект);
ЭтоИмитатор = ЛиТипИмитатораОбъектаЛкс(ТипОбъекта);
Если ЭтоИмитатор Тогда
#Если Сервер И Не Сервер Тогда
Объект = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
ОбъектXML = Объект.Снимок();
Иначе
ДополнительныеСвойства = СериализоватьДополнительныеСвойстваОбъектаЛкс(Объект);
ОбъектXML = ОбъектВСтрокуXMLЛкс(Объект);
КонецЕсли;
ирСервер.УстановитьПометкуУдаленияОбъектаЛкс(ОбъектXML, ДополнительныеСвойства, ЗначениеПометки, БезАвторегистрацииИзменений, ТипОбъекта, ПривилегированныйРежим, ОтключатьЗаписьВерсии);
Если ЭтоИмитатор Тогда
Объект.ЗагрузитьСнимок(ОбъектXML);
Иначе
Объект = ОбъектИзСтрокиXMLЛкс(ОбъектXML);
ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, ДополнительныеСвойства);
КонецЕсли;
#Если Клиент Тогда
ОповеститьОбИзменении(Объект.Ссылка);
#КонецЕсли
Иначе
Если ПривилегированныйРежим Тогда
УстановитьПривилегированныйРежимЛкс();
КонецЕсли;
УстановитьПараметрыЗаписиОбъектаЛкс(Объект, , БезАвторегистрацииИзменений, ОтключатьЗаписьВерсии);
//Если РежимЗаписи = Неопределено Тогда
// Объект.УстановитьПометкуУдаления(ЗначениеПометки);
//Иначе
Объект.УстановитьПометкуУдаления(ЗначениеПометки);
//КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура УдалитьОбъектЛкс(Знач Объект, Знач НаСервере = Неопределено, Знач ОтключатьКонтрольЗаписи = Неопределено, Знач БезАвторегистрацииИзменений = Неопределено,
ПривилегированныйРежим = Неопределено, ОтключатьЗаписьВерсии = Неопределено) Экспорт
Если НаСервере = Неопределено Тогда
ПараметрыЗаписи = ирКэш.ПараметрыЗаписиОбъектовЛкс();
Если НаСервере = Неопределено Тогда
НаСервере = ПараметрыЗаписи.ОбъектыНаСервере;
КонецЕсли;
Если ОтключатьКонтрольЗаписи = Неопределено Тогда
ОтключатьКонтрольЗаписи = ПараметрыЗаписи.ОтключатьКонтрольЗаписи;
КонецЕсли;
Если ОтключатьЗаписьВерсии = Неопределено Тогда
ОтключатьЗаписьВерсии = ПараметрыЗаписи.ОтключатьЗаписьВерсии;
КонецЕсли;
Если БезАвторегистрацииИзменений = Неопределено Тогда
БезАвторегистрацииИзменений = ПараметрыЗаписи.БезАвторегистрацииИзменений;
КонецЕсли;
Если ПривилегированныйРежим = Неопределено Тогда
ПривилегированныйРежим = ПараметрыЗаписи.ПривилегированныйРежим;
КонецЕсли;
УстановитьДопСвойстваИзПарамертовЗаписиОбъектаЛкс(Объект, ПараметрыЗаписи);
КонецЕсли;
УстановитьПараметрыЗаписиОбъектаЛкс(Объект, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений, ОтключатьЗаписьВерсии);
Если НаСервере Тогда
ТипОбъекта = ТипЗнч(Объект);
ЭтоИмитатор = ЛиТипИмитатораОбъектаЛкс(ТипОбъекта);
Если ЭтоИмитатор Тогда
#Если Сервер И Не Сервер Тогда
Объект = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
ОбъектXML = Объект.Снимок(, Ложь);
Иначе
ДополнительныеСвойства = СериализоватьДополнительныеСвойстваОбъектаЛкс(Объект);
ОбъектXML = ОбъектВСтрокуXMLЛкс(Объект);
КонецЕсли;
ирСервер.УдалитьОбъектXMLЛкс(ОбъектXML, ДополнительныеСвойства, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений, ТипОбъекта, ПривилегированныйРежим, ОтключатьЗаписьВерсии);
//// https://partners.v8.1c.ru/forum/t/1728509/m/1728509 , https://www.hostedredmine.com/issues/893636
//// Вероятно теперь этот антибаг платформы больше не нужен, т.к. сделан другой - в самих имитаторах
//Если ЭтоИмитатор Тогда
//// Объект.ЗагрузитьСнимок(ОбъектXML);
// Объект.СброситьМодифицированность();
////Иначе
//// Объект = ОбъектИзСтрокиXMLЛкс(ОбъектXML);
//// ВосстановитьДополнительныеСвойстваОбъектаЛкс(Объект, ДополнительныеСвойства);
//КонецЕсли;
#Если Клиент Тогда
ОповеститьОбИзменении(Объект.Ссылка);
#КонецЕсли
Иначе
Если ПривилегированныйРежим Тогда
УстановитьПривилегированныйРежимЛкс();
КонецЕсли;
Объект.Удалить();
КонецЕсли;
КонецПроцедуры
// Продублирована в ОбработкаОбъект.ирПортативныйСервер.УстановитьПараметрыЗаписиОбъектаЛкс
Процедура УстановитьПараметрыЗаписиОбъектаЛкс(Знач Объект, ОтключатьКонтрольЗаписи = Неопределено, БезАвторегистрацииИзменений = Неопределено, ОтключатьЗаписьВерсии = Неопределено) Экспорт
Попытка
ОбменДаннымиМой = Объект.ОбменДанными;
Исключение
// Элемент плана обмена в 8.3.4-
ОбменДаннымиМой = Неопределено;
КонецПопытки;
Если ОбменДаннымиМой <> Неопределено Тогда
Если ОтключатьКонтрольЗаписи <> Неопределено Тогда
ОбменДаннымиМой.Загрузка = ОтключатьКонтрольЗаписи;
КонецЕсли;
Если БезАвторегистрацииИзменений <> Неопределено Тогда
Попытка
Получатели = ОбменДаннымиМой.Получатели;
Исключение
// Элемент плана обмена в 8.3.5+
Получатели = Неопределено;
КонецПопытки;
Если Получатели <> Неопределено Тогда
Получатели.Автозаполнение = Не БезАвторегистрацииИзменений;
КонецЕсли;
Если БезАвторегистрацииИзменений Тогда
Попытка
Объект.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов"); // Для БСП
Исключение
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Попытка
ЗаписьИсторииДанных = Объект.ЗаписьИсторииДанных;
Исключение
// 8.3.14-
ЗаписьИсторииДанных = Неопределено;
КонецПопытки;
Если ЗаписьИсторииДанных <> Неопределено Тогда
Если ОтключатьЗаписьВерсии <> Неопределено Тогда
ЗаписьИсторииДанных.Отказ = ОтключатьЗаписьВерсии;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция НовыеПараметрыПоискаСсылокЛкс(Знач СтандартныйПоиск = Истина, Знач ИсключаемыеТаблицы = Неопределено, Знач ОтображатьЗамеры = Неопределено, Знач ИсключаемыеКолонки = Неопределено) Экспорт
Если ИсключаемыеТаблицы = Неопределено Тогда
ИсключаемыеТаблицы = Новый СписокЗначений;
КонецЕсли;
Если ИсключаемыеКолонки = Неопределено Тогда
ИсключаемыеКолонки = Новый СписокЗначений;
КонецЕсли;
Если СтандартныйПоиск = Неопределено Тогда
СтандартныйПоиск = Истина;
КонецЕсли;
Если ОтображатьЗамеры = Неопределено Тогда
ОтображатьЗамеры = Ложь;
КонецЕсли;
ТекущиеПараметры = Новый Структура;
ТекущиеПараметры.Вставить("ИсключаемыеТаблицы", ИсключаемыеТаблицы);
ТекущиеПараметры.Вставить("СтандартныйПоиск", СтандартныйПоиск);
ТекущиеПараметры.Вставить("ОтображатьЗамеры", ОтображатьЗамеры);
ТекущиеПараметры.Вставить("ИсключаемыеКолонки", ИсключаемыеКолонки);
Возврат ТекущиеПараметры;
КонецФункции
Функция ПараметрыПоискаСсылокЛкс() Экспорт
ТекущиеПараметры = ВосстановитьЗначениеЛкс("ПараметрыПоискаСсылок");
Если ТекущиеПараметры = Неопределено Тогда
ТекущиеПараметры = НовыеПараметрыПоискаСсылокЛкс();
КонецЕсли;
ОбновитьИсключенияПоискаСсылокЛкс(ТекущиеПараметры.ИсключаемыеТаблицы, ТекущиеПараметры.ИсключаемыеКолонки);
Возврат ТекущиеПараметры;
КонецФункции
Процедура ОбновитьИсключенияПоискаСсылокЛкс(ИсключаемыеТаблицы, ИсключаемыеКолонки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ИсключаемыеТаблицы = Новый СписокЗначений;
ИсключаемыеКолонки = Новый СписокЗначений;
#КонецЕсли
ИменаМД = НеблокирующиеМетаданныеБСПЛкс();
Для Каждого ПолноеИмяМД Из ИменаМД Цикл
Если СтрЧислоВхождений(ПолноеИмяМД, ".") > 1 Тогда
ПолноеИмяКолонки = ПолноеИмяКолонкиБДИзМД(ПолноеИмяМД);
Если ЗначениеЗаполнено(ПолноеИмяКолонки) И ИсключаемыеКолонки.НайтиПоЗначению(ПолноеИмяКолонки) = Неопределено Тогда
ИсключаемыеКолонки.Добавить(ПолноеИмяКолонки);
КонецЕсли;
Иначе
Если ИсключаемыеТаблицы.НайтиПоЗначению(ПолноеИмяМД) = Неопределено Тогда
ИсключаемыеТаблицы.Добавить(ПолноеИмяМД);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// .
//
// Параметры:
// ИмяТаблицы - -
// КлючОбъекта - - Произвольный, *Неопределено - для нового ссылочного объекта Истина=Папка, для регистров передается Структура
// СохранятьИдентификаторСсылки - -
// ЧитатьДанныеРегистраИлиКонстанты - Булево - применяется только если задан КлючОбъекта
// ОбъектыНаСервере - -
// выхИдентификаторСсылки - -
// РазрешитьВложенныйВызов - -
// НомерВерсии - -
// ЗаполнитьНовыйСсылочный - -
//
// Возвращаемое значение:
// см. докОбъектБДПоКлючуСсылочный(), см. докОбъектБДПоКлючуРегистр(), см. докОбъектБДПоКлючуКонстанта() -
//
Функция ОбъектБДПоКлючуЛкс(Знач ИмяТаблицы = "", Знач КлючОбъекта = Неопределено, Знач СохранятьИдентификаторСсылки = Ложь, Знач ЧитатьДанныеРегистраИлиКонстанты = Истина,
Знач ОбъектыНаСервере = Неопределено, выхИдентификаторСсылки = Неопределено, РазрешитьВложенныйВызов = Истина, НомерВерсии = Неопределено, Знач ЗаполнитьНовыйСсылочный = Истина) Экспорт
Если Не ЗначениеЗаполнено(ИмяТаблицы) Тогда
ИмяТаблицы = КлючОбъекта.Метаданные().ПолноеИмя();
Если СтрЧислоВхождений(ИмяТаблицы, ".") > 1 Тогда
ИмяТаблицы = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ИмяТаблицы);
КонецЕсли;
КонецЕсли;
Если ОбъектыНаСервере = Неопределено Тогда
ПараметрыЗаписи = ирКэш.ПараметрыЗаписиОбъектовЛкс();
#Если Сервер И Не Клиент Тогда
ОбъектыНаСервере = Ложь;
#Иначе
//ОбъектыНаСервере = РежимОбъектыНаСервереПоУмолчаниюЛкс();
ОбъектыНаСервере = ПараметрыЗаписи.ОбъектыНаСервере;
#КонецЕсли
КонецЕсли;
ТипОсновнойТаблицы = ТипТаблицыБДЛкс(ИмяТаблицы);
ЭтоМетаСсылка = ЛиТипТаблицыМетассылкиЛкс(ТипОсновнойТаблицы);
РазрешитьИмитаторы = Истина
И ОбъектыНаСервере <> Ложь
//И Не ирКэш.ЛиФайловаяБазаЛкс() // В управляемом приложении в файловой базе они тоже нужны https://www.hostedredmine.com/issues/962142
И Не ирКэш.ЛиПортативныйРежимЛкс()
И Не ЭтоМетаСсылка
И Не ирКэш.ПараметрыЗаписиОбъектовЛкс().НеИспользоватьИмитаторыОбъектовДанных;
мМетаданныеОбъекта = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы, Истина);
Если мМетаданныеОбъекта = Неопределено Тогда
Если ЗначениеЗаполнено(ИмяТаблицы) Тогда
ИмяТаблицы = Неопределено;
КонецЕсли;
Иначе
мПолноеИмяМД = мМетаданныеОбъекта.ПолноеИмя();
КонецЕсли;
ЭтоСсылочныйОбъект = Ложь
Или ЛиКорневойТипСсылкиЛкс(ТипОсновнойТаблицы)
Или (Истина
И ТипОсновнойТаблицы = "Внешняя"
И мМетаданныеОбъекта.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные);
Если Истина
И РазрешитьИмитаторы
И РазрешитьВложенныйВызов
И (Ложь
Или ЭтоСсылочныйОбъект
Или ОбъектыНаСервере = "Обязательно")
Тогда
СтруктураСнимка = ирСервер.ПолучитьСнимокОбъектаБДПоКлючуЛкс(ИмяТаблицы, КлючОбъекта, СохранятьИдентификаторСсылки, ЧитатьДанныеРегистраИлиКонстанты, выхИдентификаторСсылки, НомерВерсии,
ЗаполнитьНовыйСсылочный);
Если СтруктураСнимка <> Неопределено Тогда
Имитатор = Новый (СтруктураСнимка.ТипОбъекта);
#Если Сервер И Не Сервер Тогда
Имитатор = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
Имитатор.ЗагрузитьСнимок(СтруктураСнимка.Снимок);
Результат = Новый Структура;
Результат.Вставить("Методы", Имитатор);
Результат.Вставить("Данные", Имитатор.Данные);
КонецЕсли;
Иначе
ЭтоКонстанта = ЛиКорневойТипКонстантыЛкс(ТипОсновнойТаблицы);
ЭтоПланОбмена = ЛиКорневойТипПланаОбменаЛкс(ТипОсновнойТаблицы);
ЭтоДокумент = ЛиКорневойТипДокументаЛкс(ТипОсновнойТаблицы);
//ЭтоВнешнийОбъект = ТипОсновнойТаблицы = "Внешняя";
Если Ложь
Или Не ЗначениеЗаполнено(ТипОсновнойТаблицы)
Или (Истина
И ЭтоСсылочныйОбъект
И ТипЗнч(КлючОбъекта) = Тип("Строка"))
Тогда
Возврат Неопределено;
КонецЕсли;
Результат = Новый Структура;
Если ЭтоСсылочныйОбъект Тогда
Если ЭтоМетаСсылка Тогда
Объект = КлючОбъекта;
выхСтруктураОбъекта = КлючОбъекта;
Данные = Объект;
Методы = Объект;
Иначе
Если Истина
//И ЧитатьДанные
И ЛиТипСсылкиБДЛкс(ТипЗнч(КлючОбъекта))
И ЗначениеЗаполнено(КлючОбъекта)
Тогда
Если ЗначениеЗаполнено(НомерВерсии) Тогда
ИсторияДанныхМоя = ирОбщий.ИсторияДанныхЛкс();
#Если Сервер И Не Сервер Тогда
ИсторияДанныхМоя = ИсторияДанных;
#КонецЕсли
Объект = ИсторияДанныхМоя.СформироватьПоВерсии(КлючОбъекта, НомерВерсии);
Объект.ДополнительныеСвойства.Вставить("НомерЗагруженнойВерсии", НомерВерсии);
Иначе
Попытка
Объект = КлючОбъекта.ПолучитьОбъект();
Исключение
ПроверитьОшибкуПодписокНаКлиентеЛкс(ОписаниеОшибки());
ВызватьИсключение;
КонецПопытки;
//Если Объект <> Неопределено Тогда
// Объект.Прочитать(); // Получаем гарантировано свежие данные мимо объектного кэша, но объектный кэш не обновится https://partners.v8.1c.ru/forum/topic/1383852
//КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Объект = Неопределено Тогда
Если ЛиТипСсылкиБДЛкс(ТипЗнч(КлючОбъекта)) Тогда
Если ТипОсновнойТаблицы = "Внешняя" Тогда
#Если Сервер И Не Сервер Тогда
КлючОбъекта = ВнешниеИсточникиДанных.ВнешнийИсточникДанных1.Таблицы.Таблица1.ПустаяСсылка();
#КонецЕсли
выхИдентификаторСсылки = КлючОбъекта.Значение();
Иначе
#Если Сервер И Не Сервер Тогда
КлючОбъекта = Справочники.Валюты.ПустаяСсылка();
#КонецЕсли
выхИдентификаторСсылки = КлючОбъекта.УникальныйИдентификатор();
КонецЕсли;
ИначеЕсли Не СохранятьИдентификаторСсылки Тогда
выхИдентификаторСсылки = Неопределено;
КонецЕсли;
Если КлючОбъекта <> "" Тогда
ЭтоГруппаДляНового = КлючОбъекта = Истина;
Попытка
Объект = СоздатьСсылочныйОбъектПоМетаданнымЛкс(мПолноеИмяМД, ЭтоГруппаДляНового, выхИдентификаторСсылки, ЗаполнитьНовыйСсылочный);
Исключение
//// Может не быть прав на создание объекта или ошибка в обработчике заполнения или ошибка подключения подписок
//СообщитьЛкс(СтрШаблонЛкс("Ошибка создания объекта %1: " + ОписаниеОшибки(), мПолноеИмяМД));
//Возврат Неопределено;
ВызватьИсключение;
КонецПопытки;
КонецЕсли;
КонецЕсли;
Данные = Объект;
Методы = Объект;
//#Если Не Клиент И Сервер Тогда
Если РазрешитьИмитаторы Тогда
ИмитаторОбъекта = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирИмитаторСсылочныйОбъект");
#Если Сервер И Не Сервер Тогда
ИмитаторОбъекта = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
ИмитаторОбъекта.Конструктор(Объект);
Данные = ИмитаторОбъекта.Данные;
Методы = ИмитаторОбъекта;
КонецЕсли;
//#КонецЕсли
КонецЕсли;
Иначе
Если РазрешитьИмитаторы Тогда
Если ЭтоКонстанта Тогда
ИмитаторОбъекта = Обработки.ирИмитаторКонстантаМенеджер.Создать();
ИмитаторОбъекта.КонструкторПоКлючу(ИмяТаблицы);
Иначе
ИмитаторОбъекта = Обработки.ирИмитаторНаборЗаписей.Создать();
ИмитаторОбъекта.КонструкторПоКлючу(ИмяТаблицы, КлючОбъекта);
КонецЕсли;
Данные = ИмитаторОбъекта.Данные;
Методы = ИмитаторОбъекта;
Иначе
Если ЭтоКонстанта Тогда
Объект = Новый (СтрЗаменить(ИмяТаблицы, ".", "МенеджерЗначения."));
Иначе
Объект = Новый (ИмяТипаДанныхТаблицыРегистраЛкс(ИмяТаблицы));
#Если Сервер И Не Сервер Тогда
Объект = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
#КонецЕсли
Если КлючОбъекта <> Неопределено Тогда
ЗаполнитьОтборПоКлючуЛкс(Объект.Отбор, КлючОбъекта);
КонецЕсли;
КонецЕсли;
Данные = Объект;
Методы = Объект;
КонецЕсли;
Если КлючОбъекта <> Неопределено И ЧитатьДанныеРегистраИлиКонстанты Тогда
Методы.Прочитать();
КонецЕсли;
КонецЕсли;
Результат.Вставить("Данные", Данные);
Результат.Вставить("Методы", Методы); // ОбработкаОбъект.ирИмитаторСсылочныйОбъект
Возврат Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращаемое значение:
// Структура:
// * Данные - Структура:
// ** Ссылка - ДокументСсылка
// ** ПометкаУдаления - Булево
// ** Проведен - Булево
// ** Код - Строка
// ** Номер - Строка
// ** Дата - Строка
// ** ВерсияДанных
// * Методы - ОбработкаОбъект.ирИмитаторСсылочныйОбъект
Функция докОбъектБДПоКлючуСсылочный() Экспорт
КонецФункции
// Возвращаемое значение:
// Структура:
// * Данные - ТаблицаЗначений
// * Методы - ОбработкаОбъект.ирИмитаторНаборЗаписей
Функция докОбъектБДПоКлючуРегистр() Экспорт
КонецФункции
// Возвращаемое значение:
// Структура:
// * Данные - Структура:
// ** Значение - Ссылка
// * Методы - ОбработкаОбъект.ирИмитаторКонстантаМенеджер
Функция докОбъектБДПоКлючуКонстанта() Экспорт
КонецФункции
Процедура ЗаполнитьОтборПоКлючуЛкс(Знач Отбор, Знач КлючОбъекта) Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый ПостроительЗапроса;
Отбор = Пустышка.Отбор;
#КонецЕсли
Для Каждого ЭлементОтбора Из Отбор Цикл
СтруктураЧтенияЗначения = Новый Структура(ЭлементОтбора.Имя, null);
ЗаполнитьЗначенияСвойств(СтруктураЧтенияЗначения, КлючОбъекта);
Если СтруктураЧтенияЗначения[ЭлементОтбора.Имя] <> Null Тогда
Отбор[ЭлементОтбора.Имя].Установить(КлючОбъекта[ЭлементОтбора.Имя]);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция МетаданныеОбъектаБДЛкс(Знач ОбъектБД) Экспорт
Если ТипЗнч(ОбъектБД) = Тип("УдалениеОбъекта") Тогда
ОбъектМД = ОбъектБД.Ссылка.Метаданные();
Иначе
ТипОбъекта = ТипОбъектаБДЛкс(ОбъектБД);
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъекта);
КонецЕсли;
Возврат ОбъектМД;
КонецФункции
// Из имитатора объекта БД вернет реальный тип объекта БД
Функция ТипОбъектаБДЛкс(ОбъектБД) Экспорт
Результат = ТипЗнч(ОбъектБД);
Если Истина
И Результат = Тип("Структура")
И ОбъектБД.Свойство("Методы")
И ОбъектБД.Свойство("Данные")
Тогда
Имитатор = ОбъектБД.Методы;
Иначе
Имитатор = ОбъектБД;
КонецЕсли;
Результат = ТипЗнч(Имитатор);
Если ЛиТипИмитатораОбъектаЛкс(Результат) Тогда
Результат = Имитатор._Тип;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КопияОбъектаБДЛкс(СтруктураОбъекта) Экспорт
СтруктураОбъекта = СтруктураОбъекта.Методы.Скопировать();
Если ТипЗнч(СтруктураОбъекта) <> Тип("Структура") Тогда
СтруктураОбъектаНовая = Новый Структура;
СтруктураОбъектаНовая.Вставить("Методы", СтруктураОбъекта);
СтруктураОбъектаНовая.Вставить("Данные", СтруктураОбъекта);
СтруктураОбъекта = СтруктураОбъектаНовая;
КонецЕсли;
Возврат СтруктураОбъекта;
КонецФункции
// Функция - Скопировать таблицу
//
// Параметры:
// ТаблицаИлиТабличнаяЧасть - ТаблицаЗначений, ТабличнаяЧасть -
// ПараметрыОтбора - -
// Колонки - -
// БезТиповКолонок - Булево - полезно для создания максимально компактной таблицы
//
// Возвращаемое значение:
// - ТаблицаЗначений
//
Функция СкопироватьТаблицуЛкс(ТаблицаИлиТабличнаяЧасть, ПараметрыОтбора = Неопределено, Колонки = Неопределено, БезТиповКолонок = Ложь) Экспорт
Если ТипЗнч(ТаблицаИлиТабличнаяЧасть) = Тип("ТаблицаЗначений") Тогда
Результат = ТаблицаИлиТабличнаяЧасть.Скопировать(ПараметрыОтбора, Колонки);
Иначе
Результат = ТаблицаИлиТабличнаяЧасть.Выгрузить(ПараметрыОтбора, Колонки);
КонецЕсли;
#Если Сервер И Не Сервер Тогда
Результат = Новый ТаблицаЗначений;
#КонецЕсли
Если БезТиповКолонок Тогда
//РезультатБезТипов = СкопироватьКолонкиКоллекцииЛкс(Результат,, Истина);
//ЗагрузитьВТаблицуЗначенийЛкс(РезультатБезТипов, Результат);
Для Каждого Колонка Из Результат.Колонки Цикл
Если Колонка.ТипЗначения.Типы().Количество() > 0 Тогда
ИзменитьТипКолонкиТаблицыЗначенийЛкс(Результат, Колонка.Имя, Новый ОписаниеТипов);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СсылкаВПолныйИдентификаторЛкс(Знач ЗначениеЯчейки) Экспорт
ИдентификаторСсылки = СтроковыйИдентификаторСсылкиЛкс(ЗначениеЯчейки, Истина);
Возврат ИдентификаторСсылки;
КонецФункции
Функция СсылкаИзПолногоИдентификатораЛкс(Знач Идентификатор) Экспорт
Фрагменты = СтрРазделитьЛкс(Идентификатор);
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
СтрокаЗначения = Фрагменты[0];
Фрагменты.Удалить(0);
Ссылка = XMLЗначение(Тип(СтрСоединитьЛкс(Фрагменты, ".")), СтрокаЗначения);
Возврат Ссылка;
КонецФункции
Функция СтроковыйИдентификаторЗначенияЛкс(Значение, СсылкаВместеСТипом = Ложь) Экспорт
ИдентификаторЗначения = СтроковыйИдентификаторСсылкиЛкс(Значение, СсылкаВместеСТипом);
Если Истина
И ИдентификаторЗначения = Неопределено
// ускорение
И Значение <> Неопределено
И XMLТипЗнч(Значение) = Неопределено
И ТипЗнч(Значение) <> Тип("ТаблицаЗначений")
И Не ЛиКоллекцияЛкс(Значение)
Тогда
Попытка
ИдентификаторЗначения = ПоследнийФрагментЛкс(ПолучитьПолноеИмяПредопределенногоЗначения(Значение)); // имя системного перечисления
Исключение
КонецПопытки;
КонецЕсли;
Если ИдентификаторЗначения = Неопределено Тогда
Попытка
ИдентификаторЗначения = XMLСтрока(Значение);
Исключение
ИдентификаторЗначения = "" + Значение;
КонецПопытки;
КонецЕсли;
Возврат ИдентификаторЗначения;
КонецФункции
Функция РазмерЗначенияЛкс(Знач Значение) Экспорт
Если ТипЗнч(Значение) = Тип("ДвоичныеДанные") Тогда
#Если Сервер И Не Сервер Тогда
Значение = Новый ДвоичныеДанные;
#КонецЕсли
Результат = Значение.Размер();
Иначе
Если ТипЗнч(Значение) = ТипОболочкаHTMLДокументаЛкс() Тогда
Значение = Значение.ПолучитьТекст();
КонецЕсли;
Результат = СтрДлина(ЗначениеВСтрокуВнутр(Новый ХранилищеЗначения(Значение, Новый СжатиеДанных(0))));
КонецЕсли;
Возврат Результат;
КонецФункции
// Баг платформы 8.3.23 https://www.hostedredmine.com/issues/963849
Функция ТипОболочкаHTMLДокументаЛкс() Экспорт
//Результат = Тип("ОболочкаHTMLДокумента");
Результат = ЗначениеИзСтрокиВнутр("{""T"",eb8eb7e7-fc15-4bfc-90d7-64bff7b66257}");
Возврат Результат;
КонецФункции
Функция ПредставлениеДопСвойствОбъектаЛкс(Объект) Экспорт
Попытка
ДополнительныеСвойства = Объект.ДополнительныеСвойства;
Исключение
ДополнительныеСвойства = Новый Структура;
КонецПопытки;
СостояниеОбъекта = "";
Для Каждого КлючИЗначение Из ДополнительныеСвойства Цикл
Если ЛиСсылкаНаОбъектБДЛкс(КлючИЗначение.Значение) И ТранзакцияАктивна() Тогда
// На случай сломанной транзакции
ПредставлениеЗначения = СсылкаВПолныйИдентификаторЛкс(КлючИЗначение.Значение);
Иначе
ПредставлениеЗначения = "" + КлючИЗначение.Значение;
КонецЕсли;
СостояниеОбъекта = СостояниеОбъекта + Символы.ПС + КлючИЗначение.Ключ + ": " + ПредставлениеЗначения;
КонецЦикла;
Возврат СостояниеОбъекта;
КонецФункции
Функция ПрочитатьДвиженияДокументаПакетноЛкс(Ссылка, ОбъектыНаСервере = Неопределено, ТолькоКоличествоСтрок = Ложь) Экспорт
ОбъектМД = Ссылка.Метаданные();
ОбъектыМД = МетаданныеНаборовЗаписейПоРегистраторуЛкс(ОбъектМД, Истина, Истина);
Результат = Новый Соответствие;
Если ОбъектыМД.Количество() > 0 Тогда
Текст = "";
Для Каждого МетаРегистр из ОбъектыМД Цикл
Если Текст <> "" Тогда
Текст = Текст + ";" + Символы.ПС;
КонецЕсли;
ПолноеИмяМДРегистра = МетаРегистр.ПолноеИмя();
ИмяТаблицыБДРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМДРегистра);
Если ТолькоКоличествоСтрок Тогда
Текст = Текст + "ВЫБРАТЬ Количество(*)";
Иначе
Текст = Текст + "ВЫБРАТЬ Т.*";
КонецЕсли;
Если ТипТаблицыБДЛкс(ИмяТаблицыБДРегистра) = "ДвиженияССубконто" Тогда
Текст = Текст + "
|ИЗ " + ИмяТаблицыБДРегистра + "(,, Регистратор = &Ссылка) КАК Т";
Иначе
ИмяПоляОтбора = ИмяПоляОтбораПодчиненногоНабораЗаписейЛкс(ИмяТаблицыБДРегистра);
Текст = Текст + "
|ИЗ " + ИмяТаблицыБДРегистра + " КАК Т
|ГДЕ Т." + ИмяПоляОтбора + " = &Ссылка";
КонецЕсли;
КонецЦикла;
Запрос = Новый Запрос;
Запрос.Текст = Текст;
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатПакета = Запрос.ВыполнитьПакет();
ИндексВПакете = 0;
Для Каждого МетаРегистр из ОбъектыМД Цикл
ПолноеИмяМДРегистра = МетаРегистр.ПолноеИмя();
ИмяТаблицыБДРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМДРегистра);
Результат[ПолноеИмяМДРегистра] = ТаблицаСКолонкамиБезТипаNullЛкс(РезультатПакета[ИндексВПакете].Выгрузить());
Если ТолькоКоличествоСтрок Тогда
Результат[ПолноеИмяМДРегистра] = Результат[ПолноеИмяМДРегистра][0][0];
КонецЕсли;
ИндексВПакете = ИндексВПакете + 1;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяПоляОтбораПодчиненногоНабораЗаписейЛкс(Знач ИмяТаблицыБДРегистра) Экспорт
ТипТаблицы = ТипТаблицыБДЛкс(ИмяТаблицыБДРегистра);
Если ТипТаблицы = "Перерасчет" Тогда
ИмяПоля = "ОбъектПерерасчета";
Иначе
ИмяПоля = "Регистратор";
КонецЕсли;
ИмяПоля = ПеревестиСтроку(ИмяПоля);
Возврат ИмяПоля;
КонецФункции
Функция ИмяПоляЧислоСтрокЛкс() Экспорт
Возврат "ЧислоСтрок";
КонецФункции
// Позволяет перечитать объект грязным чтением, т.е. без учета блокировок. Не перечитывает свойство ВерсияДанных!
// На выходе объект имеет модифицированноть. Для удаленного объекта возвращает Неопределено.
Функция ПеречитатьОбъектЗапросомЛкс(Знач Объект) Экспорт
ОбъектМД = Объект.Метаданные();
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ " + ОбъектМД.ПолноеИмя() + " КАК Т ГДЕ Т.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
ТаблицаОбъекта = Запрос.Выполнить().Выгрузить();
Если ТаблицаОбъекта.Количество() > 0 Тогда
СтрокаДанных = ТаблицаОбъекта[0];
Для Каждого КолонкаТаблицы Из ТаблицаОбъекта.Колонки Цикл
ЗначениеРеквизита = СтрокаДанных[КолонкаТаблицы.Имя];
Если ЗначениеРеквизита = Null Тогда
// Реквизит (но не табличная часть) недоступен по признаку ЭтоГруппа. Если к нему обратиться у объекта, то будет ошибка "Ошибка установки значения свойства '…': Реквизит недоступен для группы"
Продолжить;
КонецЕсли;
Пустышка = Объект[КолонкаТаблицы.Имя]; // Проверяем корректность вычисления выражения перед его использованием в попытке
Если КолонкаТаблицы.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Попытка
Объект[КолонкаТаблицы.Имя].Загрузить(ЗначениеРеквизита);
Исключение
// Табличная часть недоступна по признаку ЭтоГруппа. Выдается ошибка "Ошибка при вызове метода контекста (Загрузить): Объект недоступен для изменения"
КонецПопытки;
Иначе
Попытка
Объект[КолонкаТаблицы.Имя] = ЗначениеРеквизита;
Исключение
// Реквизит предназначен только для чтения
КонецПопытки;
КонецЕсли;
КонецЦикла;
Иначе
Объект = Неопределено;
КонецЕсли;
Возврат Объект;
КонецФункции
// Антибаг платформы https://partners.v8.1c.ru/forum/topic/1168440
Процедура НаборЗаписейПослеЗагрузкиИзТаблицыЗначенийЛкс(Знач НаборЗаписей) Экспорт
ЭтоИмитатор = Истина
И Не ирКэш.ЛиПортативныйРежимЛкс()
И (Ложь
Или ТипЗнч(НаборЗаписей) = Тип("ОбработкаОбъект.ирИмитаторНаборЗаписей"));
Если ЭтоИмитатор Тогда
Возврат;
Иначе
#Если Сервер И Не Сервер Тогда
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
#КонецЕсли
Данные = НаборЗаписей;
ОбъектМД = НаборЗаписей.Метаданные();
КонецЕсли;
КорневойТип = ПервыйФрагментЛкс(ОбъектМД.ПолноеИмя());
Если ЛиКорневойТипРегистраБухгалтерииЛкс(КорневойТип) Тогда
Корреспонденции = Новый Массив;
Если ОбъектМД.Корреспонденция Тогда
Корреспонденции.Добавить("Дт");
Корреспонденции.Добавить("Кт");
Иначе
Корреспонденции.Добавить("");
КонецЕсли;
Для Каждого Проводка Из Данные Цикл
ОчиститьПоляРегистраБухгалтерииПоПризнакамУчетаЛкс(Проводка, ОбъектМД.Измерения, Корреспонденции, Неопределено);
ОчиститьПоляРегистраБухгалтерииПоПризнакамУчетаЛкс(Проводка, ОбъектМД.Ресурсы, Корреспонденции, 0);
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Корреспонденция Из Корреспонденции Цикл
ВидыСубконтоКУдалению = Новый Массив;
Для Каждого КлючИЗначение Из Проводка["Субконто" + Корреспонденция] Цикл
Если Проводка["Счет" + Корреспонденция].ВидыСубконто.Найти(КлючИЗначение.Ключ) = Неопределено Тогда
ВидыСубконтоКУдалению.Добавить(КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
Для Каждого ВидСубконто Из ВидыСубконтоКУдалению Цикл
Проводка["Субконто" + Корреспонденция].Удалить(ВидСубконто);
КонецЦикла;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Каждого Корреспонденция Из Корреспонденции Цикл ВидыСубконтоКУдалению = Новый Массив; Для Каждого КлючИЗначение Из Проводка["Субконто" + Корреспонденция] Цикл Если Проводка["Счет" + Корреспонденция].ВидыСубконто.Найти(КлючИЗначение.Ключ) = Неопределено Тогда ВидыСубконтоКУдалению.Добавить(КлючИЗначение.Ключ); КонецЕсли; КонецЦикла; Для Каждого ВидСубконто Из ВидыСубконтоКУдалению Цикл Проводка["Субконто" + Корреспонденция].Удалить(ВидСубконто); КонецЦикла; КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ОчиститьПоляРегистраБухгалтерииПоПризнакамУчетаЛкс(Знач Проводка, Знач КоллекцияПолей, Знач Корреспонденции, Знач ПустоеЗначение = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Проводка = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей().Добавить();
#КонецЕсли
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Поле Из КоллекцияПолей Цикл
Если Истина
И Не Поле.Балансовый
И Поле.ПризнакУчета <> Неопределено
Тогда
ИмяПризнакаУчета = Поле.ПризнакУчета.Имя;
Для Каждого Корреспонденция Из Корреспонденции Цикл
Если Не Проводка["Счет" + Корреспонденция][ИмяПризнакаУчета] Тогда
ПрисвоитьЕслиНеРавноЛкс(Проводка[Поле.Имя + Корреспонденция], ПустоеЗначение);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Каждого Поле Из КоллекцияПолей Цикл Если Истина И Не Поле.Балансовый И Поле.ПризнакУчета <> Неопределено Тогда ИмяПризнакаУчета = Поле.ПризнакУчета.Имя; Для Каждого Корреспонденция Из Корреспонденции Цикл Если Не Проводка["Счет" + Корреспонденция][ИмяПризнакаУчета] Тогда ПрисвоитьЕслиНеРавноЛкс(Проводка[Поле.Имя + Корреспонденция], ПустоеЗначение); КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Источник - http://infostart.ru/public/125988/
Функция ВыбратьПоГруппировкамЛкс(Выборка, Группировки, СИерархией = Ложь) Экспорт
МетаВыборка = Новый Соответствие;
врОбходРезультата = ОбходРезультатаЗапроса.ПоГруппировкам;
Если СИерархией Тогда
врОбходРезультата = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
КонецЕсли;
МетаВыборка.Вставить("ОбходРезультата", врОбходРезультата);
МассивГруппировок = Новый Массив;
врСтрГруппировки = Группировки;
Пока Истина Цикл
Поз = Найти( врСтрГруппировки, "," );
Если Поз = 0 Тогда
МассивГруппировок.Добавить(СокрЛП(врСтрГруппировки));
Прервать;
КонецЕсли;
МассивГруппировок.Добавить( СокрЛП( Лев(врСтрГруппировки,Поз-1) ) );
врСтрГруппировки = Сред( врСтрГруппировки, Поз+1 );
КонецЦикла;
МетаВыборка.Вставить("Группировки", МассивГруппировок);
врВыборка = Выборка;
Для пц=0 По МассивГруппировок.Количество()-2 Цикл
врВыборкаУровня = врВыборка.Выбрать(врОбходРезультата, МассивГруппировок[пц]);
МетаВыборка.Вставить("_Выборка"+Строка(пц), врВыборкаУровня);
Если не врВыборкаУровня.Следующий() Тогда
Прервать;
КонецЕсли;
врВыборка = врВыборкаУровня;
КонецЦикла;
врВыборкаУровня = врВыборка.Выбрать(врОбходРезультата, МассивГруппировок[пц]);
МетаВыборка.Вставить("Выборка", врВыборкаУровня);
МетаВыборка.Вставить("_Выборка"+Строка(пц), врВыборкаУровня);
Возврат МетаВыборка;
КонецФункции // ВыбратьПоГруппировкамЛкс
// Источник - http://infostart.ru/public/125988/
Функция СледующийПоГруппировкамЛкс(МетаВыборка, Уровень = Неопределено) Экспорт
Если Уровень = Неопределено Тогда
Уровень = МетаВыборка["Группировки"].Количество()-1;
КонецЕсли;
Если Уровень < 0 Тогда
Возврат Ложь;
КонецЕсли;
врВыборка = МетаВыборка["_Выборка"+Строка(Уровень)];
Если врВыборка.Следующий() Тогда
Возврат Истина;
КонецЕсли;
Если СледующийПоГруппировкамЛкс(МетаВыборка, Уровень-1) Тогда
МассивГруппировок = МетаВыборка["Группировки"];
врВыборкаРодитель = МетаВыборка["_Выборка"+Строка(Уровень-1)];
врВыборка = врВыборкаРодитель.Выбрать(МетаВыборка["ОбходРезультата"],МассивГруппировок[Уровень]);
МетаВыборка["_Выборка"+Строка(Уровень)] = врВыборка;
Если Уровень = МассивГруппировок.Количество()-1 Тогда
МетаВыборка["Выборка"] = врВыборка;
КонецЕсли;
Возврат СледующийПоГруппировкамЛкс(МетаВыборка, Уровень);
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции // зфСледующийПоГруппировкам
Функция ВариантыРасположенияКонфигурационногоФайлаЛкс(выхСписок = Неопределено) Экспорт
выхСписок = Новый СписокЗначений;
выхСписок.Добавить("АктивныйФайл", "Активный файл");
выхСписок.Добавить("ДляТекущегоПользователя", "Для текущего пользователя ОС");
выхСписок.Добавить("ДляТекущейВерсии", "Для текущей версии платформы");
выхСписок.Добавить("ПеренаправлениеТекущейВерсии", "Перенаправление текущей версии (conf.cfg)");
Результат = Новый Структура;
Для Каждого ЭлементСписка Из выхСписок Цикл
Результат.Вставить(ЭлементСписка.Значение, ЭлементСписка.Значение);
КонецЦикла;
Возврат Результат;
КонецФункции
// ВариантРасположенияФайлаНастроек -
// ДляТекущейВерсии
// ПеренаправлениеТекущейВерсии - использовать значение ключа ConfLocation из файла conf.cfg
// ДляТекущегоПользователя
Функция КаталогНастроекПриложения1СЛкс(ВариантРасположенияФайлаНастроек = "ПеренаправлениеТекущейВерсии", СоздатьЕслиОтсутствует = Ложь, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
Результат = ирСервер.ПолучитьКаталогНастроекПриложения1СЛкс(ВариантРасположенияФайлаНастроек, СоздатьЕслиОтсутствует);
Иначе
ВариантыРасположения = ВариантыРасположенияКонфигурационногоФайлаЛкс();
Если Ложь
Или ВариантРасположенияФайлаНастроек = ВариантыРасположения.АктивныйФайл
Или ВариантРасположенияФайлаНастроек = ВариантыРасположения.ДляТекущегоПользователя
Тогда
КаталогКонфигурацииПриложения = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс() + РазделительПутиКФайлуЛкс() + "conf";
Иначе
КаталогКонфигурацииПриложения = КаталогПрограммы() + "conf";
Если ВариантРасположенияФайлаНастроек = ВариантыРасположения.ПеренаправлениеТекущейВерсии Тогда
ФайлУказатель = Новый Файл(КаталогКонфигурацииПриложения + РазделительПутиКФайлуЛкс() + "conf.cfg");
Если ФайлУказатель.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ФайлУказатель.ПолноеИмя);
Текст = ТекстовыйДокумент.ПолучитьТекст();
НовыйКаталогКонфигурацииПриложения = ТекстМеждуМаркерамиЛкс(Текст, "ConfLocation=", Символы.ПС);
НовыйКаталог = Новый Файл(НовыйКаталогКонфигурацииПриложения);
Если НовыйКаталог.Существует() Тогда
КаталогКонфигурацииПриложения = НовыйКаталогКонфигурацииПриложения;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если СоздатьЕслиОтсутствует Тогда
Файл = Новый Файл(КаталогКонфигурацииПриложения);
Если Не Файл.Существует() Тогда
СоздатьКаталог(КаталогКонфигурацииПриложения);
КонецЕсли;
КонецЕсли;
Результат = КаталогКонфигурацииПриложения;
КонецЕсли;
Возврат Результат;
КонецФункции
// выхВариантРасположенияФайлаНастроек -
// ДляТекущейВерсии
// ПеренаправлениеТекущейВерсии - использовать значение ключа ConfLocation из файла conf.cfg
// ДляТекущегоПользователя
Функция ПолноеИмяФайлаНастройкиПриложения1СЛкс(КраткоеИмяФайла, НаСервере = Ложь, выхВариантРасположенияФайлаНастроек = Неопределено, выхДатаИзменения = Неопределено) Экспорт
Если НаСервере Тогда
Результат = ирСервер.ПолучитьПолноеИмяФайлаНастройкиПриложения1СЛкс(КраткоеИмяФайла,, выхВариантРасположенияФайлаНастроек, выхДатаИзменения);
Иначе
ВариантыРасположения = ВариантыРасположенияКонфигурационногоФайлаЛкс();
выхВариантРасположенияФайлаНастроек = ВариантыРасположения.ДляТекущегоПользователя;
Разделитель = РазделительПутиКФайлуЛкс();
КаталогКонфигурацииПриложения = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс() + Разделитель + "conf";
Результат = КаталогКонфигурацииПриложения + Разделитель + КраткоеИмяФайла;
Файл = Новый Файл(Результат);
ФайлСуществует = Файл.Существует();
Если Не ФайлСуществует Тогда
выхВариантРасположенияФайлаНастроек = ВариантыРасположения.ДляТекущейВерсии;
КаталогКонфигурацииПриложения = КаталогПрограммы() + "conf";
Результат = КаталогКонфигурацииПриложения + Разделитель + КраткоеИмяФайла;
Файл = Новый Файл(Результат);
ФайлСуществует = Файл.Существует();
Если Не ФайлСуществует Тогда
выхВариантРасположенияФайлаНастроек = ВариантыРасположения.ПеренаправлениеТекущейВерсии;
ФайлУказатель = Новый Файл(КаталогКонфигурацииПриложения + Разделитель + "conf.cfg");
Если ФайлУказатель.Существует() Тогда
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ФайлУказатель.ПолноеИмя);
Текст = ТекстовыйДокумент.ПолучитьТекст();
НовыйКаталогКонфигурацииПриложения = ТекстМеждуМаркерамиЛкс(Текст, "ConfLocation=", Символы.ПС);
НовыйКаталог = Новый Файл(НовыйКаталогКонфигурацииПриложения);
Если НовыйКаталог.Существует() Тогда
КаталогКонфигурацииПриложения = НовыйКаталогКонфигурацииПриложения;
Результат = КаталогКонфигурацииПриложения + Разделитель + КраткоеИмяФайла;
Файл = Новый Файл(Результат);
ФайлСуществует = Файл.Существует();
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не ФайлСуществует Тогда
Результат = Неопределено;
выхВариантРасположенияФайлаНастроек = Неопределено;
Иначе
выхДатаИзменения = Файл.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс();
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяФайлаАктивнойНастройкиТехноЖурналаЛкс(НаСервере = Ложь) Экспорт
Результат = ПолноеИмяФайлаНастройкиПриложения1СЛкс("logcfg.xml", НаСервере);
Возврат Результат;
КонецФункции
Функция КаталогТехножурналаЛкс(НаСервере = Ложь) Экспорт
ИмяФайлаНастроекЖурнала = ИмяФайлаАктивнойНастройкиТехноЖурналаЛкс(НаСервере);
Если ЗначениеЗаполнено(ИмяФайлаНастроекЖурнала) Тогда
ТекстХМЛ = ПрочитатьТекстИзФайлаЛкс(ИмяФайлаНастроекЖурнала, , НаСервере);
ЧтениеХМЛ = Новый ЧтениеXML;
ЧтениеХМЛ.УстановитьСтроку(ТекстХМЛ);
ПостроительДом = Новый ПостроительDOM();
Попытка
ДокументДОМ = ПостроительДом.Прочитать(ЧтениеХМЛ);
Исключение
СообщитьЛкс("Ошибка чтения настройки техножурнала: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
Если ДокументДОМ <> Неопределено Тогда
Узлы = ДокументДом.ПолучитьЭлементыПоИмени("log");
Если Узлы.Количество() > 0 Тогда
Атрибут = Узлы.Элемент(0).Атрибуты.ПолучитьИменованныйЭлемент("location");
Если Атрибут <> Неопределено Тогда
Результат = Атрибут.ТекстовоеСодержимое;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиТехножурналВключенЛкс(НаСервере = Ложь, ВыводитьСообщения = Ложь, РазрешитьПутьСКлиентаНаСервер = Ложь, ЛиПоПользователю = Ложь) Экспорт
КаталогЖурналаВзятИзНастроекЧтения = Ложь;
КаталогЖурнала = КаталогЧтенияТехножурналаЛкс(НаСервере, РазрешитьПутьСКлиентаНаСервер, ЛиПоПользователю, КаталогЖурналаВзятИзНастроекЧтения);
Если ЗначениеЗаполнено(КаталогЖурнала) Тогда
Если Не ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала, НаСервере, ВыводитьСообщения) Тогда
Возврат Истина;
Иначе
Если ВыводитьСообщения Тогда
Если КаталогЖурналаВзятИзНастроекЧтения Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Каталог техножурнала %1 недоступен. Использован каталог, заданный в настройках чтения анализа техножурнала",, КаталогЖурнала), СтатусСообщения.Внимание);
Иначе
СообщитьЛкс(СтрШаблонИменЛкс("Каталог техножурнала %1 недоступен. Использован каталог, заданный в текущей настройке техножурнала",, КаталогЖурнала), СтатусСообщения.Внимание);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иначе
Если ВыводитьСообщения Тогда
Если НаСервере Тогда
СообщитьЛкс("Каталог техножурнала сервера не удалось прочитать из текущей настройки техножурнала и не задан в настройках чтения инструмента ""Анализ техножурнала""");
Иначе
СообщитьЛкс("Каталог техножурнала клиента не удалось прочитать из текущей настройки техножурнала");
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция КаталогЧтенияТехножурналаЛкс(НаСервере = Ложь, РазрешитьПутьСКлиентаНаСервер = Ложь, ЛиПоПользователю = Ложь, выхКаталогЖурналаВзятИзНастроекЧтения = Ложь) Экспорт
КаталогЖурнала = "";
Если НаСервере И РазрешитьПутьСКлиентаНаСервер Тогда
#Если Клиент Тогда
Если ЛиПоПользователю = Истина Тогда
КаталогЖурнала = ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогТрассыПоПользователю");
Иначе
КаталогЖурнала = ВосстановитьЗначениеЛкс("ирАнализТехножурнала.КаталогЖурналаСервера");
КонецЕсли;
выхКаталогЖурналаВзятИзНастроекЧтения = Истина;
#КонецЕсли
КонецЕсли;
Если Не ЗначениеЗаполнено(КаталогЖурнала) Тогда
Если ЛиПоПользователю = Истина Тогда
КаталогЖурнала = ирСервер.КаталогТрассыПоПользователюЛкс();
Иначе
КаталогЖурнала = КаталогТехножурналаЛкс(НаСервере);
КонецЕсли;
выхКаталогЖурналаВзятИзНастроекЧтения = Ложь;
КонецЕсли;
Возврат КаталогЖурнала;
КонецФункции
Функция ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала, НаСервере = Ложь, ВыводитьСообщения = Истина) Экспорт
Если НаСервере Тогда
Результат = ирСервер.ЛиКаталогТехножурналаНедоступенЛкс(КаталогЖурнала);
Иначе
Результат = Ложь;
ФайлКаталог = Новый Файл(КаталогЖурнала);
Если Не ФайлКаталог.Существует() Тогда
Результат = Истина;
Иначе
БлокирующиеФайлы = НайтиФайлы(КаталогЖурнала, "*.*");
Счетчик = 0;
Для Каждого БлокирующийФайл Из БлокирующиеФайлы Цикл
Счетчик = Счетчик + 1;
Если Счетчик > 100 Тогда
// Ускорена проверка доступности каталога техножурнала при очень большом числе подкаталогов в нем http://www.hostedredmine.com/issues/850582
Прервать;
КонецЕсли;
Если Не БлокирующийФайл.ЭтоКаталог() Тогда
Если ВыводитьСообщения Тогда
ТекстСообщения = "В корне каталога """ + КаталогЖурнала + """ техножурнала ";
Если НаСервере Тогда
ТекстСообщения = ТекстСообщения + "сервера";
Иначе
ТекстСообщения = ТекстСообщения + "клиента";
КонецЕсли;
СообщитьЛкс(ТекстСообщения + " обнаружены блокирующие файлы. Для работы журнала их необходимо удалить.", СтатусСообщения.Внимание);
КонецЕсли;
Результат = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиКлиентЗапущенНаКомпьютереСервераЛкс() Экспорт
Результат = НРег(ирСервер.ИмяКомпьютераЛкс()) = НРег(ИмяКомпьютера());
Возврат Результат;
КонецФункции
Функция ЗаписатьТекстВФайлЛкс(ПолноеИмяФайла, Текст, Кодировка = Неопределено, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
ирСервер.ЗаписатьТекстВФайлЛкс(ПолноеИмяФайла, Текст, Кодировка);
Иначе
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(Текст);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ТекстовыйДокумент.Записать(ИмяВременногоФайла, Кодировка);
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
мПлатформа.ПереместитьФайлКакАдминистратор(ИмяВременногоФайла, ПолноеИмяФайла);
КонецЕсли;
КонецФункции
Функция ПрочитатьТекстИзФайлаЛкс(ПолноеИмяФайла, Кодировка = Неопределено, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
Результат = ирСервер.ПрочитатьТекстИзФайлаЛкс(ПолноеИмяФайла, Кодировка);
Иначе
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ПолноеИмяФайла, Кодировка);
Результат = ТекстовыйДокумент.ПолучитьТекст();
// https://www.hostedredmine.com/issues/951193
Если Не ЗначениеЗаполнено(Кодировка) И Не ЛиЕстьКонтрольныеРусскиеБуквыЛкс(Лев(Результат, 10000)) Тогда
ТекстовыйДокумент.Прочитать(ПолноеИмяФайла, КодировкаТекста.UTF8);
Результат2 = ТекстовыйДокумент.ПолучитьТекст();
Если КодСимвола(Результат2) = 65533 Тогда
// BOM
Иначе
Результат = Результат2;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиЕстьКонтрольныеРусскиеБуквыЛкс(Строка) Экспорт
КонтрольныеБуквыРусские = "ОоЕеАаИи";
Для Счетчик = 1 По СтрДлина(КонтрольныеБуквыРусские) Цикл
Буква = Сред(КонтрольныеБуквыРусские, Счетчик, 1);
Если Найти(Строка, Буква) > 0 Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция НайтиИменаФайловЛкс(Путь, Маска = Неопределено, ИскатьВПодкаталогах = Истина, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
Результат = ирСервер.НайтиИменаФайловЛкс(Путь, Маска, ИскатьВПодкаталогах);
Иначе
Файлы = НайтиФайлы(Путь, Маска, ИскатьВПодкаталогах);
Результат = Новый Массив;
Для Каждого Файл Из Файлы Цикл
Результат.Добавить(Файл.ПолноеИмя);
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// ВсеФайлыВосстановления - Массив Из Файл -
// ПолучатьДаты - Булево -
// ПолучатьРазмеры - Булево -
// Возвращаемое значение:
// ТаблицаЗначений - отсортированная по интересующей колонке
// * Файл - Файл
// * Размер - Число - байт
// * ДатаИзменения - Дата
Функция ТаблицаФайловЛкс(Знач Файлы, Знач ПолучатьДаты = Истина, Знач ПолучатьРазмеры = Ложь) Экспорт
ТаблицаФайлов = Новый ТаблицаЗначений;
ТаблицаФайлов.Колонки.Добавить("Файл"); // Файл
ТаблицаФайлов.Колонки.Добавить("Размер");
ТаблицаФайлов.Колонки.Добавить("ДатаИзменения");
Для Каждого Файл Из Файлы Цикл
Строка = ТаблицаФайлов.Добавить();
Строка.Файл = Файл;
Если ПолучатьДаты Тогда
Строка.ДатаИзменения = Файл.ПолучитьВремяИзменения();
КонецЕсли;
Если ПолучатьРазмеры Тогда
Строка.Размер = Файл.Размер();
КонецЕсли;
КонецЦикла;
Если ПолучатьДаты Тогда
ТаблицаФайлов.Сортировать("ДатаИзменения");
Иначе
ТаблицаФайлов.Сортировать("Размер");
КонецЕсли;
Возврат ТаблицаФайлов;
КонецФункции
// Параметры:
// ИзданиеПлатформы - Строка(0,П)
//
Функция КаталогПустойИнфобазыЛкс(Знач ИзданиеПлатформы = "") Экспорт
Если Не ЗначениеЗаполнено(ИзданиеПлатформы) Тогда
ИзданиеПлатформы = ирКэш.НомерИзданияПлатформыЛкс();
КонецЕсли;
КаталогПустойИнфобазы = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(, ИзданиеПлатформы) + РазделительПутиКФайлуЛкс() + "EmptyDB";
Возврат КаталогПустойИнфобазы;
КонецФункции
Функция СтрокаСоединенияПустойИнфобазыЛкс(ИзданиеПлатформы = "", Знач СоздаватьБазуВСлучаеОтсутствия = Истина, Знач СоздаватьБазуВЛюбомСлучае = Ложь) Экспорт
КаталогПустойИнфобазы = КаталогПустойИнфобазыЛкс(ИзданиеПлатформы);
ФайлПустойИнфобазы = Новый Файл(КаталогПустойИнфобазы + РазделительПутиКФайлуЛкс() + "1CV8.1CD");
Если Ложь
Или СоздаватьБазуВЛюбомСлучае
Или СоздаватьБазуВСлучаеОтсутствия И Не ФайлПустойИнфобазы.Существует()
Тогда
УдалитьФайлы(КаталогПустойИнфобазы);
СтрокаПараметров = "CREATEINFOBASE File=" + КаталогПустойИнфобазы + ";";
//СтрокаПараметров = СтрокаПараметров + " /AddInList ууууу";
ИмяФайлаЛога = ПолучитьИмяВременногоФайла();
СтрокаПараметров = СтрокаПараметров + " /out" + ИмяФайлаЛога;
СтрокаЗапуска = """" + ИмяИсполняемогоФайлаКлиентаПлатформыЛкс() + """ " + СтрокаПараметров;
РезультатКоманды = ВыполнитьКомандуОСЛкс(СтрокаЗапуска);
Если ЗначениеЗаполнено(РезультатКоманды) Тогда
СообщитьЛкс(РезультатКоманды);
КонецЕсли;
КонецЕсли;
СтрокаСоединения = "File=""" + КаталогПустойИнфобазы + """;";
Результат = СтрокаСоединения;
Возврат Результат;
КонецФункции
Функция КаталогОбщихФайловВсехВерсийПлатформыЛкс(x64 = Неопределено) Экспорт
КаталогПрограммныхФайлов = КаталогПрограммныхФайловОСЛкс(x64);
Если ирКэш.НомерИзданияПлатформыЛкс() = "82" Тогда
Результат = КаталогПрограммныхФайлов + "\1cv82\common\";
Иначе //Если ирКэш.НомерИзданияПлатформыЛкс() > "82" Тогда
Результат = КаталогПрограммныхФайлов + "\1cv8\common\";
КонецЕсли;
Результат = СтрЗаменить(Результат, "\", РазделительПутиКФайлуЛкс());
Возврат Результат;
КонецФункции
// Добавляет если нужно расширение ".exe"
Функция ИмяИсполняемогоФайлаЛкс(Знач ИмяБезРасширения)
Результат = ИмяБезРасширения;
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
Результат = Результат + ".exe";
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяИсполняемогоФайлаКлиентаПлатформыЛкс(знач Полное = Истина, знач Тонкий = Ложь, Знач КаталогПрограммы = "") Экспорт
Результат = "1cv8";
Если Тонкий Тогда
Результат = Результат + "c";
КонецЕсли;
Если ирКэш.ЭтоУчебнаяПлатформаЛкс() Тогда
Результат = Результат + "t";
КонецЕсли;
Результат = ИмяИсполняемогоФайлаЛкс(Результат);
Если Полное Тогда
Если ПустаяСтрока(КаталогПрограммы) Тогда
КаталогПрограммы = КаталогПрограммы();
КонецЕсли;
Результат = КаталогПрограммы + Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолноеИмяИсполняемогоФайлаСтартераЛкс() Экспорт
КаталогОбщихФайлов = КаталогОбщихФайловВсехВерсийПлатформыЛкс();
Результат = КаталогОбщихФайлов + ИмяИсполняемогоФайлаЛкс("1cestart");
Возврат Результат;
КонецФункции
Функция ИсполняемыйФайлАвтоСервераЛкс(СборкиПлатформы = Неопределено, Знач СообщитьОбОтсутствии = Ложь) Экспорт
Если СборкиПлатформы = Неопределено Тогда
СборкиПлатформы = ирКэш.ДоступныеСборкиПлатформыЛкс();
КонецЕсли;
#Если Сервер И Не Сервер Тогда
СборкиПлатформы = Обработки.ирУправлениеСлужбамиСервера1С.Создать().СборкиПлатформы;
#КонецЕсли
СтрокаСборки = СборкиПлатформы.Найти(Истина, "СерверАвтономный");
Если СтрокаСборки <> Неопределено Тогда
Возврат Новый Файл(СтрокаСборки.Каталог + "\bin\ibcmd.exe");
КонецЕсли;
Если СообщитьОбОтсутствии Тогда
СообщитьЛкс("На компьютере " + ИмяКомпьютера() + " не найден файл автономного сервера (ibcmd.exe). Установите 64-разрядную платформу любой версии с компонентой ""Сервер"".");
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция СоздатьФайловуюБазу1СЛкс(Знач КаталогИнфобазы = "", ИмяФайлаКонфигурации = "", УдалитьСуществующую = Ложь, Знач ПолноеИмяИсполняемогоФайла = "") Экспорт
ФайлПустойИнфобазы = Новый Файл(КаталогИнфобазы + РазделительПутиКФайлуЛкс() + "1CV8.1CD");
Если ФайлПустойИнфобазы.Существует() И УдалитьСуществующую Тогда
УдалитьФайлы(КаталогИнфобазы);
КонецЕсли;
Если Не ФайлПустойИнфобазы.Существует() Тогда
СтрокаПараметров = "CREATEINFOBASE File=""" + КаталогИнфобазы + """;";
// Антибаг платформы http://partners.v8.1c.ru/forum/thread.jsp?id=1076785#1076785
СтрокаПараметров = СтрокаПараметров + "Q=Q";
Если ЗначениеЗаполнено(ИмяФайлаКонфигурации) Тогда
СтрокаПараметров = СтрокаПараметров + " /UseTemplate """ + ИмяФайлаКонфигурации + """";
КонецЕсли;
//СтрокаПараметров = СтрокаПараметров + " /AddInList ууууу";
Если Не ЗначениеЗаполнено(ПолноеИмяИсполняемогоФайла) Тогда
ПолноеИмяИсполняемогоФайла = ИмяИсполняемогоФайлаКлиентаПлатформыЛкс();
КонецЕсли;
ЗапуститьПриложение("""" + ПолноеИмяИсполняемогоФайла + """ " + СтрокаПараметров,, Истина);
КонецЕсли;
Возврат "";
КонецФункции
// Для файловой базы при наличии прав администратора создает символьную ссылку (зеркало) файла БД и возвращет строку соединения с путем к нему.
// В остальных случаях возвращает оригинальную строку соединения этой базы.
//
// Параметры:
// СтрокаСоединенияБазы - Строка - оригнальная строка соединения; если пустая, то берется строка соединения этой базы
// выхКаталогЗеркалаБазы - Строка - только выход, можно затем использовать для удаления каталога зеркала БД
//
// Возвращаемое значение:
// Строка -
//
Функция СтрокаСоединенияБазыДляВыгрузкиЛкс(Знач СтрокаСоединенияБазы = "", выхКаталогЗеркалаБазы = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если Не ЗначениеЗаполнено(СтрокаСоединенияБазы) Тогда
СтрокаСоединенияБазы = СтрокаСоединенияИнформационнойБазы();
КонецЕсли;
Если Истина
И ирКэш.ЛиФайловаяБазаЛкс()
И мПлатформа.ЕстьАдминистративныеПраваУУчетнойЗаписиОС()
Тогда
КаталогБазы = НСтр(СтрокаСоединенияБазы, "file");
выхКаталогЗеркалаБазы = КаталогБазы + ОтносительныйПутьЗеркалаФайловойБазыЛкс();
СтрокаСоединенияБазы = СтрЗаменить(СтрокаСоединенияБазы, КаталогБазы, выхКаталогЗеркалаБазы);
//ИмяФайлаБазы = КаталогБазы + "\1Cv8.1CD"; // абсолютная
ИмяФайлаБазы = "..\1Cv8.1CD"; // относительная
ИмяФайлаЗеркалаБазы = выхКаталогЗеркалаБазы + "\1Cv8.1CD";
ФайлЗеркала = Новый Файл(ИмяФайлаЗеркалаБазы);
Если Не ФайлЗеркала.Существует() Тогда
СоздатьКаталог(выхКаталогЗеркалаБазы);
ирОбщий.ВыполнитьКомандуОСЛкс("mklink """ + ИмяФайлаЗеркалаБазы + """ """ + ИмяФайлаБазы + """",,, Истина);
КонецЕсли;
КонецЕсли;
Возврат СтрокаСоединенияБазы;
КонецФункции
Функция ОтносительныйПутьЗеркалаФайловойБазыЛкс() Экспорт
Возврат "\MirrorDB";
КонецФункции
// .
//
// Параметры:
// КомандаКонфигуратора - -
// СтрокаСоединенияБазы - Строка - пустая строка трактуется как строка соединения пустой инфобазы
// выхТекстЛога - -
// ПодавлятьДиалоги - -
// Состояние - -
// УдалитьСуществующуюПустуюИнфобазу - -
// ПолноеИмяИсполняемогоФайла - -
// ОжидатьЗавершения - -
// ИмяПользователя - -
// ПарольПользователя - -
// СообщитьСтрокуПараметров - -
// КодЯзыка - -
// СообщитьТекстЛога - -
// ФормаВладелец - -
// ОтображатьОкно - -
// ЧерезЗеркалоБазы - Булево - для файловой базы использовать временную виртуальную копию СтрокаСоединенияБазыДляВыгрузкиЛкс
//
// Возвращаемое значение:
// -
//
Функция ВыполнитьКомандуКонфигуратораЛкс(Знач КомандаКонфигуратора, Знач СтрокаСоединенияБазы = "", выхТекстЛога = "", Знач ПодавлятьДиалоги = Истина, Знач Состояние = "",
Знач УдалитьСуществующуюПустуюИнфобазу = Ложь, Знач ПолноеИмяИсполняемогоФайла = "", Знач ОжидатьЗавершения = Истина, Знач ИмяПользователя = "", Знач ПарольПользователя = "",
Знач СообщитьСтрокуПараметров = Истина, Знач КодЯзыка = "", Знач СообщитьТекстЛога = Ложь, Знач ФормаВладелец = Неопределено, Знач ОтображатьОкно = Ложь, Знач ЧерезЗеркалоБазы = Ложь) Экспорт
#Если Клиент Тогда
Если ЗначениеЗаполнено(Состояние) Тогда
СообщитьЛкс(Состояние,,, Истина);
КонецЕсли;
#КонецЕсли
Если Не ЗначениеЗаполнено(СтрокаСоединенияБазы) Тогда
КаталогПустойИнфобазы = КаталогПустойИнфобазыЛкс();
СоздатьФайловуюБазу1СЛкс(КаталогПустойИнфобазы,, УдалитьСуществующуюПустуюИнфобазу, ПолноеИмяИсполняемогоФайла);
СтрокаСоединенияБазы = "File=""" + КаталогПустойИнфобазы + """;";
КонецЕсли;
КаталогЗеркалаБазы = "";
Если ЧерезЗеркалоБазы Тогда
СтрокаСоединенияБазы = СтрокаСоединенияБазыДляВыгрузкиЛкс(СтрокаСоединенияБазы, КаталогЗеркалаБазы);
КонецЕсли;
КодВозврата = Неопределено;
ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
Если Не ЗначениеЗаполнено(ПолноеИмяИсполняемогоФайла) Тогда
ПолноеИмяИсполняемогоФайла = ИмяИсполняемогоФайлаКлиентаПлатформыЛкс();
КонецЕсли;
ДополнительныеПараметры = КомандаКонфигуратора + " /Out""" + ИмяФайлаЛога + """";
ПараметрыПакетногоЗапуска = ПараметрыЗапускаПриложения1СЛкс(ИмяПользователя, ПарольПользователя,, Истина,,,, ДополнительныеПараметры, СообщитьСтрокуПараметров,
СтрокаСоединенияБазы,,,, ЗначениеЗаполнено(ИмяПользователя), КодЯзыка);
Если ПодавлятьДиалоги Тогда
ПараметрыПакетногоЗапуска = ПараметрыПакетногоЗапуска + " /DisableStartupDialogs /DisableStartupMessages";
КонецЕсли;
Если ОтображатьОкно Тогда
ПараметрыПакетногоЗапуска = ПараметрыПакетногоЗапуска + " /Visible";
КонецЕсли;
#Если Клиент Тогда
Если Истина
И СтрокиРавныЛкс(СтрЗаменить(СтрокаСоединенияБазы, ОтносительныйПутьЗеркалаФайловойБазыЛкс() + """", """"), СтрокаСоединенияИнформационнойБазы())
И Не ЗначениеЗаполнено(ИмяПользователя)
Тогда
Если ирКэш.НомерВерсииПлатформыЛкс() > 802014 Тогда
Выполнить("ЗапуститьСистему(ПараметрыПакетногоЗапуска, ОжидатьЗавершения, КодВозврата)");
Иначе
ЗапуститьСистему(ПараметрыПакетногоЗапуска, ОжидатьЗавершения);
КодВозврата = 0;
КонецЕсли;
Иначе
#КонецЕсли
СтрокаКоманды = """" + ПолноеИмяИсполняемогоФайла + """ " + ПараметрыПакетногоЗапуска;
Если ирКэш.НомерВерсииПлатформыЛкс() > 802014 Тогда
Выполнить("ЗапуститьПриложение(СтрокаКоманды,, ОжидатьЗавершения, КодВозврата)");
Иначе
ЗапуститьПриложение(СтрокаКоманды,, ОжидатьЗавершения);
КодВозврата = 0;
КонецЕсли;
#Если Клиент Тогда
КонецЕсли;
#КонецЕсли
ФайлЛога = Новый Файл(ИмяФайлаЛога);
Если ФайлЛога.Существует() Тогда
ТекстовыйДокументЛога = Новый ТекстовыйДокумент;
ТекстовыйДокументЛога.Прочитать(ФайлЛога.ПолноеИмя);
выхТекстЛога = ТекстовыйДокументЛога.ПолучитьТекст();
Если СообщитьТекстЛога Тогда
СообщитьЛкс(выхТекстЛога);
КонецЕсли;
КонецЕсли;
//Если ЗначениеЗаполнено(КаталогЗеркалаБазы) Тогда
// УдалитьФайлы(КаталогЗеркалаБазы);
//КонецЕсли;
Возврат КодВозврата = 0;
КонецФункции
// .
// Параметры:
// СтрокаСоединенияБазы - Строка - пустая строка трактуется как строка соединения пустой инфобазы
Функция ВыполнитьКомандуАвтоСервераБазыЛкс(Знач Команда, выхТекстЛога = "", Знач Состояние = "", Знач ПолноеИмяИсполняемогоФайла = "", Знач ОжидатьЗавершения = Истина,
Знач ИмяПользователя = Неопределено, Знач ПарольПользователя = Неопределено, Знач СообщитьСтрокуПараметров = Истина, Знач СообщитьТекстЛога = Истина, Знач ФормаВладелец = Неопределено,
Знач СтрокаСоединенияБазы = "", ФормаПараметровАвтоСервера = Неопределено) Экспорт
#Если Клиент Тогда
Если ИмяПользователя = Неопределено Тогда
Если ФормаПараметровАвтоСервера = Неопределено Тогда
ФормаПараметровАвтоСервера = ирКлиент.ФормаПараметровАвтономногоСервераЛкс();
Если ФормаПараметровАвтоСервера = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
ИмяПользователя = ФормаПараметровАвтоСервера.ИмяПользователя;
ПарольПользователя = ФормаПараметровАвтоСервера.Пароль;
КонецЕсли;
Если ЗначениеЗаполнено(Состояние) Тогда
СостояниеЛкс(Состояние);
КонецЕсли;
#КонецЕсли
Если Не ЗначениеЗаполнено(ПолноеИмяИсполняемогоФайла) Тогда
ПолноеИмяИсполняемогоФайла = ИсполняемыйФайлАвтоСервераЛкс(, Истина).ПолноеИмя;
КонецЕсли;
СтрокаКоманды = """" + ПолноеИмяИсполняемогоФайла + """ " + Команда + " ";
Если ИмяПользователя = Неопределено Тогда
ИмяПользователя = ИмяПользователя();
КонецЕсли;
Если Не ЗначениеЗаполнено(СтрокаСоединенияБазы) Тогда
СтрокаСоединенияБазы = СтрокаСоединенияИнформационнойБазы();
КонецЕсли;
Если ирКэш.ЛиФайловаяБазаЛкс(СтрокаСоединенияБазы) Тогда
СтрокаКоманды = СтрокаКоманды + "--db-path=""" + НСтр(СтрокаСоединенияБазы, "file") + """";
Иначе
Если Не ПроверитьСоединениеЭтойСУБДЛкс() Тогда
Возврат Ложь;
КонецЕсли;
ПараметрыСУБД = ПараметрыСоединенияЭтойСУБДЛкс();
Если ПараметрыСУБД.ТипСУБД = "MSSQL" Тогда
ТипСУБД = "mssqlserver";
Иначе
ТипСУБД = "postgresql";
КонецЕсли;
СтрокаКоманды = СтрокаКоманды + "--db-server=" + ПараметрыСУБД.ИмяСервера + " --dbms=" + ТипСУБД + " --db-name=" + ПараметрыСУБД.ИмяБД;
Если ЗначениеЗаполнено(ПараметрыСУБД.ИмяПользователя) Тогда
СтрокаКоманды = СтрокаКоманды + " --db-user=""" + ПараметрыСУБД.ИмяПользователя + """ --db-pwd=" + ПараметрыСУБД.Пароль;
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(ИмяПользователя) Тогда
СтрокаКоманды = СтрокаКоманды + " --user=""" + ИмяПользователя + """";
Если ЗначениеЗаполнено(ПарольПользователя) Тогда
СтрокаКоманды = СтрокаКоманды + " --password=" + ПарольПользователя;
КонецЕсли;
КонецЕсли;
выхТекстЛога = ВыполнитьКомандуОСЛкс(СтрокаКоманды, ОжидатьЗавершения,,,, КодировкаТекста.UTF8);
Если ОжидатьЗавершения Тогда
Если СообщитьТекстЛога Тогда
СообщитьЛкс(выхТекстЛога);
КонецЕсли;
Иначе
#Если Клиент Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ФормаЗадания = мПлатформа.ПолучитьФорму("ФоновоеЗаданиеФормы", ФормаВладелец, Команда);
ФормаЗадания.ИдентификаторЗадания = выхТекстЛога;
ФормаЗадания.КраткоеПредставление = Команда;
ФормаЗадания.ПолноеПредставление = "ibcmd: " + Команда;
ФормаЗадания.КлючСохраненияПоложенияОкна = "ОперацияОС";
ФормаЗадания.СостояниеОкна = ВариантСостоянияОкна.Обычное;
ФормаЗадания.Открыть();
ФормаЗадания.ОбновитьСостояниеЗаданияБезПараметров();
#КонецЕсли
КонецЕсли;
Возврат Истина;
КонецФункции
Процедура ЗаполнитьСписокАдминистраторовБазыЛкс(Знач СписокАдминистраторов) Экспорт
#Если Сервер И Не Сервер Тогда
СписокАдминистраторов = Новый СписокЗначений;
#КонецЕсли
СписокАдминистраторов.Очистить();
Для Каждого Пользователь Из ПользователиИнформационнойБазы.ПолучитьПользователей() Цикл
#Если Сервер И Не Сервер Тогда
Пользователь = ПользователиИнформационнойБазы.СоздатьПользователя();
#КонецЕсли
Если ПравоДоступа("Администрирование", Метаданные, Пользователь) Тогда
СписокАдминистраторов.Добавить(Пользователь.Имя);
КонецЕсли;
КонецЦикла;
СписокАдминистраторов.СортироватьПоПредставлению();
КонецПроцедуры
// р5яф67оыйи
Функция ПараметрыЗапускаСеансаТекущиеЛкс(выхАдресОтладчика = Неопределено) Экспорт
КоманднаяСтрокаПроцесса = ирКэш.КоманднаяСтрокаТекущегоПроцессаОСЛкс();
РегВыражение = НовоеРегВыражениеЛкс();
РегВыражение.IgnoreCase = Истина;
РегВыражение.Global = Истина;
РегВыражение.Pattern = "(/DebuggerUrl\s*.+?)(?: /|$)";
Вхождения = РегВыражение.НайтиВхождения(КоманднаяСтрокаПроцесса);
Результат = "";
Если Вхождения.Количество() > 0 Тогда
выхАдресОтладчика = Вхождения[Вхождения.Количество() - 1].SubMatches(0);
Результат = Результат + выхАдресОтладчика;
КонецЕсли;
РегВыражение.Pattern = "(/Debug\s+.+?)(?: /|$)";
Вхождения = РегВыражение.НайтиВхождения(КоманднаяСтрокаПроцесса);
Если Вхождения.Количество() > 0 Тогда
СтрокаОтладчика = Вхождения[Вхождения.Количество() - 1].SubMatches(0);
Иначе
СтрокаОтладчика = "/Debug";
КонецЕсли;
Результат = Результат + " " + СтрокаОтладчика;
СохраняемыеПараметры = Новый Массив;
СохраняемыеПараметры.Добавить("TechnicalSpecialistMode");
СохраняемыеПараметры.Добавить("UseHwLicenses");
СохраняемыеПараметры.Добавить("L");
СохраняемыеПараметры.Добавить("VL");
//СохраняемыеПараметры.Добавить("C"); // Нельзя сохранять парамерт запуска, т.к. он часто разовый
СохраняемыеПараметры.Добавить("UC");
Для Каждого ИмяПараметра Из СохраняемыеПараметры Цикл
РегВыражение.Pattern = "(/" + ИмяПараметра + ".*?)(?:\s/|$)";
Вхождения = РегВыражение.НайтиВхождения(КоманднаяСтрокаПроцесса);
Если Вхождения.Количество() > 0 Тогда
ПараметрКоманднойСтроки = Вхождения[Вхождения.Количество() - 1].SubMatches(0);
Результат = Результат + " " + ПараметрКоманднойСтроки;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Создает COM объект клиента 1C и подключает его к базе по указанной строке соединения.
// Параметры:
// СтрокаСоединения - Строка
// ИмяПользователя - Строка
// ПарольПользователя - Строка
// ТипCOMОбъекта - Строка, *"Application" - "Application" или "ComConnector"
// Видимость - Булево - для Application
// ОбработатьИсключениеПодключения - Булево, *Ложь - при Истина исключение обрабатывается внутри метода и возвращается его описание в качестве результата
// ИмяСервераПроцессов - Строка - имя сервера, на котором создавать COM объект
//
// Возвращаемое значение:
// COMОбъект - клиента 1C, Строка - описание исключения
//
Функция СоздатьСеансИнфобазы1С8Лкс(Знач СтрокаСоединения = "", Знач ИмяПользователя = "", Знач ПарольПользователя = "",
Знач ТипCOMКласса = "Application", Знач Видимость = Ложь, Знач ОбработатьИсключениеПодключения = Ложь, ОписаниеОшибки = "", ИмяСервераПроцессов = "", КодРазрешения = "") Экспорт
ДопСтрокаСоединения = "";
Если ЗначениеЗаполнено(ИмяПользователя) Тогда
ДопСтрокаСоединения = ДопСтрокаСоединения + "Usr=""" + ИмяПользователя + """;" + "Pwd=""" + ПарольПользователя + """;";
КонецЕсли;
Если ЗначениеЗаполнено(КодРазрешения) Тогда
ДопСтрокаСоединения = ДопСтрокаСоединения + "UC=""" + КодРазрешения + """;";
КонецЕсли;
#Если Клиент Тогда
СостояниеЛкс("Подключение к базе через COM…");
#КонецЕсли
Соединение = СоздатьCOMОбъект1СЛкс(ТипCOMКласса, ИмяСервераПроцессов);
//! Соединение = Новый COMОбъект("V83.Application");
Если Не ЗначениеЗаполнено(СтрокаСоединения) Тогда
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
КонецЕсли;
ПолнаяСтрокаСоединения = СтрокаСоединения + ДопСтрокаСоединения;
Попытка
РезультатСоединения = Соединение.Connect(ПолнаяСтрокаСоединения);
Исключение
Если СтрНайтиЛкс(СтрокаСоединения, "File=",,,, Ложь) > 0 Тогда
СообщитьЛкс("Если не найдена лицензия, то проверьте файл nethasp.ini и для отладки проблемы запускайте вручную любую файловую базу");
КонецЕсли;
СообщитьЛкс("Если не соответствие версий клиента и сервера, то для регистрации правильной версии откройте инструмент ""Управление COM классами 1С""");
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
Если ОбработатьИсключениеПодключения Тогда
ОписаниеОшибки = ОписаниеОшибки();
Возврат ОписаниеОшибки;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если Найти(ТипCOMКласса, "Application") > 0 Тогда
#Если Клиент Тогда
СостояниеЛкс("Ожидание инициализации сеанса…");
Для Счетчик = 1 По 10 Цикл
ОбработкаПрерыванияПользователя();
Попытка
Соединение.Visible = Видимость;
Прервать;
Исключение
// Тонкий клиент еще не готов
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
ПаузаЛкс(1);
КонецЦикла;
СостояниеЛкс("");
Результат = Соединение;
#КонецЕсли
ИначеЕсли СтрНайтиЛкс(ТипCOMКласса, "ComConnector",,,, Ложь) > 0 Тогда
Результат = РезультатСоединения;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СоздатьCOMОбъект1СЛкс(Знач ТипCOMКласса = "ComConnector", Знач ИмяСервераПроцессов = "") Экспорт
ИмяCOMКласса = "v" + ирКэш.НомерИзданияПлатформыЛкс();
Если Найти(ТипCOMКласса, ".") = 0 Тогда
ИмяCOMКласса = ИмяCOMКласса + ".";
КонецЕсли;
ИмяCOMКласса = ИмяCOMКласса + ТипCOMКласса;
Попытка
Соединение = Новый COMОбъект(ИмяCOMКласса, ИмяСервераПроцессов);
//! Соединение = Новый COMОбъект("V83.ComConnector");
Исключение
Если СтрокиРавныЛкс(ТипCOMКласса, "ComConnector") Тогда
СообщитьЛкс("Убедитесь что зарегистрирован COM класс COMConnector нужной разрядности и версии платформы");
КонецЕсли;
#Если Клиент Тогда
ирКлиент.ОткрытьФормуЛкс("Обработка.ирУправлениеCOMКлассами1С.Форма");
#КонецЕсли
ВызватьИсключение "Ошибка создания COM объекта " + ИмяCOMКласса + ": " + ОписаниеОшибки();
КонецПопытки;
Возврат Соединение;
КонецФункции
// Выполняет ожидание появления сеанса и только потом возвращает
Функция ЗапуститьСеансПодПользователемЛкс(ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, ТипCOMОбъекта = "", РежимЗапуска = "Авто", КодРазрешения = "",
СообщитьКоманднуюСтроку = Ложь, ОткрытьПортативныеИнструменты = Истина, ОчисткаКэшаКлиентСерверныхВызовов = Истина, ПрименитьТекущиеПараметрыЗапуска = Истина, ДополнительныеПараметры = "",
РежимИнтерфейсаТакси = Ложь, Элевация = Ложь, РазделениеДанных = "", ОтключитьАутентификациюОС = Ложь, КодЯзыка = "", ПараметрЗапуска = "") Экспорт
Если ЗначениеЗаполнено(ТипCOMОбъекта) Тогда
Соединение = СоздатьСеансИнфобазы1С8Лкс(, ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, ТипCOMОбъекта, Истина,,,, КодРазрешения);
Иначе
#Если Клиент Тогда
//Если ирКэш.НомерВерсииПлатформыЛкс() = 802015 Тогда
// Предупреждение("В релиза 8.2.15 функция недоступна", 20); // Антибаг платформы 8.2.15
// Возврат;
//КонецЕсли;
Если РежимЗапуска = "Авто" Тогда
// Антибаг платформы. При передачи этого режима в явном виде в некоторых случаях пароль в командной строке игнорируется
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователяИнфобазы);
Если ПользовательИБ.РежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение Тогда
КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий";
ИначеЕсли ПользовательИБ.РежимЗапуска = РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение Тогда
КонечныйРежимЗапуска = "ОбычноеПриложение";
Иначе //Авто
Если Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение Тогда
КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий";
Иначе
КонечныйРежимЗапуска = "ОбычноеПриложение";
КонецЕсли;
КонецЕсли;
Иначе
КонечныйРежимЗапуска = РежимЗапуска;
КонецЕсли;
ПараметрыЗапуска = ПараметрыЗапускаПриложения1СЛкс(ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, КодРазрешения, Ложь, КонечныйРежимЗапуска,
ПрименитьТекущиеПараметрыЗапуска, ОчисткаКэшаКлиентСерверныхВызовов, ДополнительныеПараметры, СообщитьКоманднуюСтроку,, ОткрытьПортативныеИнструменты, РежимИнтерфейсаТакси,
РазделениеДанных, ОтключитьАутентификациюОС, КодЯзыка, ПараметрЗапуска);
ТекущаяДата = ирСервер.ТекущаяДатаЛкс();
Если Ложь
Или Элевация
Или КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий"
Тогда
ИмяИсполняемогоФайла = ИмяИсполняемогоФайлаКлиентаПлатформыЛкс(, КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий");
СтрокаЗапуска = """" + ИмяИсполняемогоФайла + """ " + ПараметрыЗапуска;
ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(СтрокаЗапуска,,, Ложь, Элевация);
Иначе
ЗапуститьСистему(ПараметрыЗапуска);
КонецЕсли;
СостояниеЛкс("Ожидание запуска сеанса…");
Успех = Ложь;
ДатаПоследнегоВопроса = ирСервер.ТекущаяДатаЛкс();
Пока Не Успех Цикл
ОбработкаПрерыванияПользователя();
Если ирСервер.ТекущаяДатаЛкс() - ДатаПоследнегоВопроса >= 5 Тогда
Ответ = Вопрос("Продолжить ожидание сеанса (5 сек)?", РежимДиалогаВопрос.ДаНет, 20,,, КодВозвратаДиалога.Нет);
Если Ответ <> КодВозвратаДиалога.Да Тогда
Прервать;
КонецЕсли;
ДатаПоследнегоВопроса = ирСервер.ТекущаяДатаЛкс();
КонецЕсли;
Сеансы = ПолучитьСеансыИнформационнойБазы(); // Иногда выполняется долго
Успех = Ложь;
Для Каждого Сеанс Из Сеансы Цикл
Если Истина
И Сеанс.НачалоСеанса >= ТекущаяДата
И НРег(Сеанс.ИмяКомпьютера) = НРег(ИмяКомпьютера())
И Сеанс.Пользователь <> Неопределено
И НРег(Сеанс.Пользователь.Имя) = НРег(ИмяПользователяИнфобазы)
Тогда
Успех = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
СостояниеЛкс("");
#Иначе
ВызватьИсключение "Запуск приложения допускается только на клиенте";
#КонецЕсли
КонецЕсли;
Возврат Соединение;
КонецФункции
Процедура ПерезапуститьСеансОтИмениАдминистратораОСЛкс(ФормаДляОткрытияВНовомСеансе = Неопределено) Экспорт
ПараметрДляОткрытияФормы = ПараметрЗапускаДляОткрытияФормыЛкс(ФормаДляОткрытияВНовомСеансе);
Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда
РежимЗапуска = "УправляемоеПриложение";
Иначе
РежимЗапуска = "ОбычноеПриложение";
КонецЕсли;
ЗапуститьСеансПодПользователемЛкс(ИмяПользователя(),,, РежимЗапуска,,,,,,,, Истина,,,, ПараметрДляОткрытияФормы);
КонецПроцедуры
Функция ПараметрЗапускаДляОткрытияФормыЛкс(Знач ФормаДляОткрытияВНовомСеансе) Экспорт
Результат = "ОткрытьФормуИР." + ПолноеИмяФормыЛкс(ФормаДляОткрытияВНовомСеансе);
Возврат Результат;
КонецФункции
// Параметры:
// XML -
// Тип -
// ИспользоватьXDTO -
// СообщатьОбОшибках -
//
Функция ОбъектИзСтрокиXMLЛкс(Знач ФайлИлиТекст = "", Знач Тип = "", Знач ИспользоватьXDTO = Истина, Знач СообщатьОбОшибках = Истина) Экспорт
Если Ложь
Или ТипЗнч(ФайлИлиТекст) = Тип("Файл")
Или ЗначениеЗаполнено(ФайлИлиТекст)
Тогда
Чтение = Новый ЧтениеXML;
Если ТипЗнч(ФайлИлиТекст) = Тип("Файл") Тогда
Чтение.ОткрытьФайл(ФайлИлиТекст.ПолноеИмя);
Иначе
Чтение.УстановитьСтроку(ФайлИлиТекст);
КонецЕсли;
Попытка
Если ИспользоватьXDTO Тогда
Результат = СериализаторXDTO.ПрочитатьXML(Чтение);
Иначе
Результат = ПрочитатьXML(Чтение);
КонецЕсли;
Исключение
Если СообщатьОбОшибках Тогда
СообщитьЛкс(ОписаниеОшибки(), СтатусСообщения.Важное);
КонецЕсли;
Чтение.Закрыть();
КонецПопытки;
// Антибаг платформы 8.2-8.3.6 СериализаторXDTO некорректно восстанавливает пустую табличную часть поверх непустой https://partners.v8.1c.ru/forum/t/1329468/m/1329468
Попытка
Пустышка = Результат.Модифицированность();
МетаТЧи = Результат.Метаданные().ТабличныеЧасти;
Исключение
МетаТЧи = Новый Массив;
КонецПопытки;
Для Каждого МетаТЧ Из МетаТЧи Цикл
ТЧ = Результат[МетаТЧ.Имя];
Если ТЧ.Количество() = 0 Тогда
Попытка
ТЧ.Вставить(0);
Исключение
// Недоступна по разделению группа/элемент с неадекватной ошибкой https://partners.v8.1c.ru/forum/t/1374212/m/1374212
Продолжить;
КонецПопытки;
ТЧ.Удалить(0);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Результат = Неопределено Тогда
Если ЗначениеЗаполнено(Тип) Тогда
Результат = Новый (Тип);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ВосстановитьНастройкуКомпоновкиИзСтрокиXMLЛкс(Знач XML = "", Знач СообщатьОбОшибках = Истина) Экспорт
Результат = ОбъектИзСтрокиXMLЛкс(XML, Тип("НастройкиКомпоновкиДанных"), , СообщатьОбОшибках);
Возврат Результат;
КонецФункции
// Продублирована в ирПортативныйСервер
// Параметры:
// Объект -
// ИспользоватьXDTO -
//
Функция ОбъектВСтрокуXMLЛкс(Знач Объект, Знач ИспользоватьXDTO = Истина, ИмяФайла = "", ВызыватьИсключение = Истина, Поток = Неопределено, Знач Сериализатор = Неопределено) Экспорт
Если Сериализатор = Неопределено Тогда
Сериализатор = СериализаторXDTO;
КонецЕсли;
ЭтоВременныйПоток = Поток = Неопределено;
Если ЭтоВременныйПоток Тогда
Поток = Новый ЗаписьXML;
Если ЗначениеЗаполнено(ИмяФайла) Тогда
Попытка
Поток.ОткрытьФайл(ИмяФайла);
Исключение
ВызватьИсключение ОписаниеОшибки(); // Чтобы в диалоге "Вычислить выражение" полное описание показывалось
КонецПопытки;
Иначе
Поток.УстановитьСтроку();
КонецЕсли;
КонецЕсли;
Результат = Неопределено;
ТипОбъекта = ТипЗнч(Объект);
ЭтоИмитатор = ЛиТипИмитатораОбъектаЛкс(ТипОбъекта);
Если ЭтоИмитатор Тогда
#Если Сервер И Не Сервер Тогда
Объект = Обработки.ирИмитаторСсылочныйОбъект.Создать();
#КонецЕсли
Результат = Объект.ДанныеВСтрокуXMLЧерезXDTO(ИспользоватьXDTO, ВызыватьИсключение, Сериализатор);
Поток.ЗаписатьБезОбработки(Результат); // Криво
Иначе
Попытка
Если ИспользоватьXDTO Тогда
Если Истина
И ТипЗнч(Объект) <> Тип("ОбъектXDTO")
И ТипЗнч(Объект) <> Тип("ЗначениеXDTO")
Тогда
Сериализатор.ЗаписатьXML(Поток, Объект);
Иначе
ФабрикаXDTO.ЗаписатьXML(Поток, Объект);
КонецЕсли;
Иначе
ЗаписатьXML(Поток, Объект);
КонецЕсли;
Исключение
Если ЭтоВременныйПоток Тогда
Поток.Закрыть();
КонецЕсли;
Если ВызыватьИсключение Тогда
ВызватьИсключение;
КонецЕсли;
Поток = Неопределено;
КонецПопытки;
Если Поток <> Неопределено Тогда
Если ЭтоВременныйПоток Тогда
Результат = Поток.Закрыть();
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Не выбрасывает исключения сериализации
Функция ОбъектВСтрокуДляСравненияВнутрЛкс(Знач Объект) Экспорт
РежимXML = Ложь;
Если ЛиТабличнаяЧастьЛкс(Объект, Истина) Тогда
//! Объект = 0 // ТабличнаяЧасть
Объект = Объект.Выгрузить();
ИначеЕсли ТипЗнч(Объект) = Тип("ТаблицаЗначений") Тогда
// сериализация через ЗначениеВСтрокуВнутр будет содержать внутренние номер строк и первого свободного номера
РежимXML = Истина;
КонецЕсли;
Если Не РежимXML Тогда
Результат = ЗначениеВСтрокуВнутр(Объект);
РазмерЗначения = СтрДлина(Результат);
Если РазмерЗначения = 42 И Найти(Результат, "{""#"",") = 1 Тогда
РежимXML = Истина;
КонецЕсли;
КонецЕсли;
Если РежимXML Тогда
Результат = ОбъектВСтрокуXMLЛкс(Объект,,, Ложь);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОбъектИзСтрокиJSONЛкс(Знач СтрокаJSON, Знач ПрочитатьВСоответствие = Ложь, Знач ПолноеЧтение = Истина) Экспорт
Результат = Неопределено;
ЧтениеJSON = МойЧтениеJSON();
#Если Сервер И Не Сервер Тогда
ЧтениеJSON = Новый ЧтениеJSON;
#КонецЕсли
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
// Метод ПрочитатьJSON появился в 8.3
Выполнить("Результат = ПрочитатьJSON(ЧтениеJSON, ПрочитатьВСоответствие)");
Если ПолноеЧтение Тогда
Попытка
ДостигнутКонец = Не ЧтениеJSON.Прочитать();
Исключение
ДостигнутКонец = Ложь;
КонецПопытки;
Если Не ДостигнутКонец Тогда
ВызватьИсключение СтрШаблонЛкс("Строка JSON не корректна в позиции %1:%2", ЧтениеJSON.ТекущаяСтрока, ЧтениеJSON.ТекущаяПозиция);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиТаблицаСериализуемаЛкс(Знач ТаблицаЗначений) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ТаблицаСериализуема = Истина;
ВсеРедактируемыеТипы = ОписаниеТиповВсеРедактируемыеТипыЛкс();
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
ТипыКолонки = Колонка.ТипЗначения.Типы();
ТаблицаСериализуема = Ложь;
Если ТипыКолонки.Количество() > 0 Тогда
ТаблицаСериализуема = Истина;
Для Каждого Тип Из ТипыКолонки Цикл
Если Не ВсеРедактируемыеТипы.СодержитТип(Тип) Тогда
ТаблицаСериализуема = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Не ТаблицаСериализуема Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ТаблицаСериализуема;
КонецФункции
Функция ТаблицаИзДереваСвойствоЗначениеАтрибутыЛкс(Знач СтрокиДерева) Экспорт
#Если Сервер И Не Сервер Тогда
СтрокиДерева = Новый ДеревоЗначений;
СтрокиДерева = СтрокиДерева.Строки;
#КонецЕсли
Результат = Новый ТаблицаЗначений;
Для Каждого СтрокаДерева Из СтрокиДерева Цикл
СтрокаРезультата = Результат.Добавить();
Для Каждого Атрибут Из СтрокаДерева.Атрибуты Цикл
ИмяСвойства = "Атрибут_" + ИдентификаторИзПредставленияЛкс(Лев(Атрибут.Представление, 100));
Если Результат.Колонки.Найти(ИмяСвойства) = Неопределено Тогда
Результат.Колонки.Добавить(ИмяСвойства);
КонецЕсли;
СтрокаРезультата[ИмяСвойства] = Атрибут.Значение;
КонецЦикла;
Для Каждого СтрокаСвойства Из СтрокаДерева.Строки Цикл
ИмяСвойства = ИдентификаторИзПредставленияЛкс(СтрокаСвойства.Свойство);
Если Результат.Колонки.Найти(ИмяСвойства) = Неопределено Тогда
Результат.Колонки.Добавить(ИмяСвойства);
КонецЕсли;
СтрокаРезультата[ИмяСвойства] = СтрокаСвойства.Значение;
Если СтрокаСвойства.Атрибуты.Количество() > 0 Тогда
ИмяСвойства = ИмяСвойства + "_Атрибуты";
Если Результат.Колонки.Найти(ИмяСвойства) = Неопределено Тогда
Результат.Колонки.Добавить(ИмяСвойства);
КонецЕсли;
СтрокаРезультата[ИмяСвойства] = СтрокаСвойства.Атрибуты;
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Удаляем пустые колонки
//Для Индекс = 1 - Результат.Колонки.Количество() По 0 Цикл // Обратный обход
// Колонка = Результат.Колонки[-Индекс];
// Если Результат.НайтиСтроки(Новый Структура(Колонка.Имя, "")).Количество() = Результат.Количество() Тогда
// Результат.Колонки.Удалить(Колонка);
// КонецЕсли;
//КонецЦикла;
Результат = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(Результат);
Возврат Результат;
КонецФункции
Функция ОбъектXDTOИзСтрокиXMLЛкс(ФайлИлиТекст, СТипами = Ложь) Экспорт
Чтение = Новый ЧтениеXML;
Если ТипЗнч(ФайлИлиТекст) = Тип("Файл") Тогда
Чтение.ОткрытьФайл(ФайлИлиТекст.ПолноеИмя);
Иначе
Чтение.УстановитьСтроку(ФайлИлиТекст);
КонецЕсли;
Если СТипами Тогда
XMLТип = СериализаторXDTO.ПолучитьXMLТип(Чтение);
Если XMLТип <> Неопределено Тогда
ТипОбъекта = ФабрикаXDTO.Тип(XMLТип.URIПространстваИмен, XMLТип.ИмяТипа);
КонецЕсли;
КонецЕсли;
Результат = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипОбъекта);
Возврат Результат;
КонецФункции
Функция ОбъектВСтрокуJSONЛкс(Объект, ДелатьОтступ = Ложь) Экспорт
ЗаписьЖСОН = МойЗаписьJSON(ДелатьОтступ);
//ирОбщий83.ЗаписатьЖСОНЛкс(ЗаписьЖСОН, Объект); // Только для режима совместимости 8.3.6
Выполнить("ЗаписатьJSON(ЗаписьЖСОН, Объект)"); // для платформы 8.3.6
Результат = ЗаписьЖСОН.Закрыть();
Возврат Результат;
КонецФункции
Функция ФорматироватьТекстJSONЛкс(СтрокаЖСОН) Экспорт
Если Не ЗначениеЗаполнено(СтрокаЖСОН) Тогда
Возврат СтрокаЖСОН;
КонецЕсли;
Попытка
СтруктураИзСтроки = ОбъектИзСтрокиJSONЛкс(СтрокаЖСОН);
Исключение
СтруктураИзСтроки = ОбъектИзСтрокиJSONЛкс(СтрокаЖСОН, Истина);
КонецПопытки;
Результат = ОбъектВСтрокуJSONЛкс(СтруктураИзСтроки, Истина);
Возврат Результат;
КонецФункции
Функция ФорматироватьТекстXMLЛкс(СтрокаXML) Экспорт
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(Новый ПараметрыЗаписиXML(, , Истина, Истина));
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, ЗаписьXML);
Результат = ЗаписьXML.Закрыть();
Возврат Результат;
КонецФункции
Функция ПроверитьЦиклическиеСсылкиВстроенногоЯзыкаЛкс(Значение, Описание = "<Значение>", ВыводитьСообщение = Ложь) Экспорт
Если ирКэш.НомерВерсииПлатформыЛкс() < 803010 Тогда
Если ВыводитьСообщение Тогда
СообщитьЛкс("Проверка циклических ссылок доступна только на платформе 8.3.10 и выше");
КонецЕсли;
Возврат Новый ТаблицаЗначений;
КонецЕсли;
Результат = Новый ТаблицаЗначений;
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
СтруктураТипа = мПлатформа.СтруктураТипаИзКонкретногоТипа(ТипЗнч(Значение));
ОбщийТип = ПервыйФрагментЛкс(СтруктураТипа.ИмяОбщегоТипа);
Попытка
КоличествоЭлементов = Значение.Количество();
Исключение
КоличествоЭлементов = 1;
КонецПопытки;
Если Ложь
Или ОбщийТип = "ВнешняяОбработкаОбъект"
Или ОбщийТип = "ОбработкаОбъект"
Или ОбщийТип = "ВнешняяОтчетОбъект"
Или ОбщийТип = "ОтчетОбъект"
Или КоличествоЭлементов > 1000
Или (Истина
И ТипЗнч(Значение) = Тип("ДеревоЗначений")
И Значение.Строки.Количество() > 1000)
Тогда
// Довольно долго для больших коллекций https://www.hostedredmine.com/issues/950717
Иначе
Попытка
Результат = Вычислить("ПроверитьЦиклическиеСсылкиВстроенногоЯзыка(Значение, Описание)");
Исключение
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
Если ТипЗнч(Результат) = Тип("ТаблицаЗначений") Тогда
// Антибаг платформы https://partners.v8.1c.ru/forum/t/1573860/m/1573860
Маркер = СтрШаблонЛкс("<%1>.%2", ПеревестиСтроку("Значение"), ПеревестиСтроку("КонтекстноеМеню"));
Для ИндексСтроки = 1 - Результат.Количество() По 0 Цикл // Обратный обход
Строка = Результат[-ИндексСтроки];
ЭлементыЦиклическихСсылок = Строка.ЭлементыЦиклическихСсылок;
Для ИндексЭлемента = 1 - ЭлементыЦиклическихСсылок.Количество() По 0 Цикл // Обратный обход
Элемент = ЭлементыЦиклическихСсылок[-ИндексЭлемента];
Если Найти(Элемент, Маркер) > 0 Тогда
ЭлементыЦиклическихСсылок.Удалить(-ИндексЭлемента);
КонецЕсли;
КонецЦикла;
Если ЭлементыЦиклическихСсылок.Количество() = 0 Тогда
Результат.Удалить(-ИндексСтроки);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЗаписатьОбъектДляОтладкиЛкс(Объект, АдресРезультата = Неопределено) Экспорт
Если ТранзакцияАктивна() Тогда
ирСервер.СтрокаСоединенияСервераЛкс(); // Проверка на автоостановку фоновых заданий отладчиком http://www.hostedredmine.com/issues/851201
лАдресРезультата = ПоместитьВоВременноеХранилище(Null, Новый УникальныйИдентификатор);
СтрокаХМЛ = ОбъектВСтрокуXMLЛкс(Объект);
Параметры = Новый Массив();
Параметры.Добавить(СтрокаХМЛ);
Параметры.Добавить(лАдресРезультата);
#Если Сервер И Не Сервер Тогда
ирОбщий.ЗаписатьОбъектДляОтладкиЛкс();
#КонецЕсли
ДобавитьТекущемуПользователюРолиИРЛкс();
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ирОбщий.ЗаписатьОбъектДляОтладкиЛкс", Параметры,, "Запись объекта для отладки (ИР)");
ФоновоеЗадание.ОжидатьЗавершения(20); // https://github.com/tormozit/RDT1C/issues/686
Результат = ПолучитьИзВременногоХранилища(лАдресРезультата);
Иначе
Если ТипЗнч(Объект) = Тип("Строка") Тогда
Объект = ОбъектИзСтрокиXMLЛкс(Объект);
КонецЕсли;
Если ТипЗнч(Объект) = Тип("Структура") Тогда
Результат = ИмяНастройкиХраненияОбъектаОтложеннойОтладкиЛкс();
СохранитьЗначениеЛкс(Результат, Объект);
Иначе
ЗаписатьОбъектЛкс(Объект,,,, Ложь);
Результат = Объект.Ссылка;
КонецЕсли;
Если АдресРезультата <> Неопределено Тогда
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяНастройкиХраненияОбъектаОтложеннойОтладкиЛкс() Экспорт
Возврат "Объект для отладки";
КонецФункции
Функция РасшифровкаИерархическогоЛогическогоВыраженияЛкс(Знач Выражение) Экспорт
Результат = Новый Массив;
Анализатор = НовыйАнализаторКодаЛкс(0);
Анализатор.УстановитьТекст("И " + Выражение);
Анализатор.ФорматироватьТекстВстроенногоЯзыка();
Текст = Анализатор.ПолеТекста;
Для сч = 1 По Текст.КоличествоСтрок() Цикл
ГлавнаяСтрока = Текст.ПолучитьСтроку(сч);
ГруппаУсловия = Новый Массив;
Вхождения = НайтиРегВыражениеЛкс(ГлавнаяСтрока, "^\s*(И|Или)\s+([^\n]*)");
Если Вхождения.Количество() = 0 Тогда
Если Не ЛиВнутриКомментарияЛкс(ГлавнаяСтрока) Тогда
ГруппаУсловия.Добавить(ГлавнаяСтрока);
КонецЕсли;
Продолжить;
КонецЕсли;
НепечатноеНачало = НепечатноеНачалоСтрокиЛкс(ГлавнаяСтрока);
ГлавныйОператор = Вхождения[0].Группа0;
ГлавнаяСтрока = Вхождения[0].Группа1;
ГруппаУсловия.Добавить(ГлавнаяСтрока);
Для СчВложенный = сч + 1 По Текст.КоличествоСтрок() Цикл
ВложеннаяСтрока = Текст.ПолучитьСтроку(СчВложенный);
Если ЛиВнутриКомментарияЛкс(ВложеннаяСтрока) Тогда
Продолжить;
КонецЕсли;
НепечатноеВложенное = НепечатноеНачалоСтрокиЛкс(ВложеннаяСтрока);
Если Ложь
Или НепечатноеВложенное = НепечатноеНачало
Или СтрДлина(НепечатноеВложенное) < СтрДлина(НепечатноеНачало)
Тогда
Прервать;
КонецЕсли;
ГруппаУсловия.Добавить(ВложеннаяСтрока);
КонецЦикла;
ТекстГруппы = СтрСоединитьЛкс(ГруппаУсловия, " ");
ТекстГруппыБезЛитералов = Анализатор.ЗалитьКомментарииИСтроковыеЛитералы(ТекстГруппы,, Истина, Ложь, Ложь, Ложь);
Для ц=1 По СтрЧислоВхождений(ТекстГруппыБезЛитералов, ")") - СтрЧислоВхождений(ТекстГруппыБезЛитералов, "(") Цикл
ТекстГруппы = СтрокаБезПоследнегоФрагментаЛкс(ТекстГруппы, ")");
КонецЦикла;
НоваяСтрока = """" + НепечатноеНачало + "["" + ?(Вычислить(" + ТекстВВыражениеВстроенногоЯзыкаЛкс(ТекстГруппы) + "),""+"",""-"") + ""] " + ГлавныйОператор + " " + Сред(ТекстВВыражениеВстроенногоЯзыкаЛкс(ГлавнаяСтрока), 2);
Результат.Добавить(НоваяСтрока);
КонецЦикла;
Результат = СтрСоединитьЛкс(Результат, Символы.ПС);
Возврат Результат;
КонецФункции
//
// Параметры:
// КоллекцияСтрок - Структура, СписокЗначений, ТаблицаЗначений, КоллекцияСтрокДереваЗначений, ТабличнаяЧасть, НаборЗаписей
Функция АвтоУникальноеИмяВКоллекцииЛкс(Знач КоллекцияСтрок, знач БазовоеИмяИлиСтрока, Знач ИмяКлючевойКолонки = "Имя", Знач ДолжноБытьИдентификатором = Истина,
Знач ЗаменаПустойСтроки = "_", Знач ДопустимаяДлинаИдентификатораЕслиНеЗаданаВКолонке = 50, Знач КлючеваяКолонкаВНижнемРегистре = Ложь) Экспорт
ТекущийИндекс = 0;
Если ТипЗнч(БазовоеИмяИлиСтрока) = Тип("Строка") Или БазовоеИмяИлиСтрока = Неопределено Тогда
БазовоеИмя = БазовоеИмяИлиСтрока;
Иначе
ИсключаемаяСтрока = БазовоеИмяИлиСтрока;
БазовоеИмя = БазовоеИмяИлиСтрока[ИмяКлючевойКолонки];
//ТекущийИндекс = 1;
ПоследнийСимвол = Прав(БазовоеИмя, 1);
Если ЛиЦифраЛкс(ПоследнийСимвол) И ПоследнийСимвол <> "0" Тогда
БазовоеИмя = СтрокаБезКонцаЛкс(БазовоеИмя, 1);
ТекущийИндекс = Число(ПоследнийСимвол);
КонецЕсли;
КонецЕсли;
Колонки = Неопределено;
Если ТипЗнч(КоллекцияСтрок) = Тип("Структура") Тогда
//
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("Соответствие") Тогда
//
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("СписокЗначений") Тогда
//
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("ДанныеФормыКоллекция") Тогда
//
#Если Не ТонкийКлиент И Не ВебКлиент Тогда
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("ТаблицаЗначений") Тогда
Колонки = КоллекцияСтрок.Колонки;
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("КоллекцияСтрокДереваЗначений") Тогда
Если КоллекцияСтрок.Количество() > 0 Тогда
Колонки = КоллекцияСтрок[0].Владелец().Колонки;
КонецЕсли;
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("КоллекцияКолонокТаблицыЗначений") Тогда
//
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("КоллекцияКолонокДереваЗначений") Тогда
//
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("НаборыДанныхСхемыКомпоновкиДанных") Тогда
//
ИначеЕсли ЛиТабличнаяЧастьЛкс(КоллекцияСтрок) Тогда // В этой функции вызывается ПеревестиСтроку()! Поэтому ранее бесконечная рекурсия возникала, когда условие находилось выше https://www.hostedredmine.com/issues/932471
//! КоллекцияСтрок = 0; // ТабличнаяЧасть
Колонки = КоллекцияСтрок.ВыгрузитьКолонки().Колонки;
#КонецЕсли
Иначе
ВызватьИсключение "Неподдерживаемый тип (" + ТипЗнч(КоллекцияСтрок) + ") параметра КоллекцияСтрок";
КонецЕсли;
Если ДолжноБытьИдентификатором Тогда
ДопустимаяДлинаИдентификатора = 0;
Если Колонки <> Неопределено Тогда
ДопустимаяДлинаИдентификатора = Колонки[ИмяКлючевойКолонки].ТипЗначения.КвалификаторыСтроки.Длина;
Если Колонки.Найти("Н" + ИмяКлючевойКолонки) <> Неопределено Тогда
ИмяКлючевойКолонки = "Н" + ИмяКлючевойКолонки;
КлючеваяКолонкаВНижнемРегистре = Истина;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ДопустимаяДлинаИдентификатора) Тогда
ДопустимаяДлинаИдентификатора = ДопустимаяДлинаИдентификатораЕслиНеЗаданаВКолонке;
КонецЕсли;
БазовоеИмя = ИдентификаторИзПредставленияЛкс(БазовоеИмя, ЗаменаПустойСтроки);
Если ДопустимаяДлинаИдентификатора > 0 Тогда
БазовоеИмя = Лев(БазовоеИмя, ДопустимаяДлинаИдентификатора);
КонецЕсли;
Иначе
Если ПустаяСтрока(БазовоеИмя) Тогда
БазовоеИмя = ЗаменаПустойСтроки;
КонецЕсли;
КонецЕсли;
Пока Истина Цикл
ТекущийПсевдоним = БазовоеИмя + Формат(ТекущийИндекс, "ЧГ=");
Если Ложь
Или ТипЗнч(КоллекцияСтрок) = Тип("Структура")
Или ТипЗнч(КоллекцияСтрок) = Тип("Соответствие")
Тогда
СтрокиОдноименных = ОтобратьКоллекциюЛкс(КоллекцияСтрок, "Э.Ключ = П1",, ТекущийПсевдоним);
ИначеЕсли ТипЗнч(КоллекцияСтрок) = Тип("СписокЗначений") Тогда
СтрокиОдноименных = ОтобратьКоллекциюЛкс(КоллекцияСтрок, "Э.Представление = П1",, ТекущийПсевдоним);
#Если Не ТонкийКлиент И Не ВебКлиент Тогда
ИначеЕсли Ложь
Или ТипЗнч(КоллекцияСтрок) = Тип("КоллекцияКолонокТаблицыЗначений")
Или ТипЗнч(КоллекцияСтрок) = Тип("КоллекцияКолонокДереваЗначений")
Или ТипЗнч(КоллекцияСтрок) = Тип("НаборыДанныхСхемыКомпоновкиДанных")
Тогда
СтрокиОдноименных = ОтобратьКоллекциюЛкс(КоллекцияСтрок, "Э.Имя = П1",, ТекущийПсевдоним);
#КонецЕсли
Иначе
//! КоллекцияСтрок = 0; // ТаблицаЗначений
ПроверочныйПсевдоним = ТекущийПсевдоним;
Если КлючеваяКолонкаВНижнемРегистре Тогда
ПроверочныйПсевдоним = НРег(ПроверочныйПсевдоним);
КонецЕсли;
СтрокиОдноименных = КоллекцияСтрок.НайтиСтроки(Новый Структура(ИмяКлючевойКолонки, ПроверочныйПсевдоним));
КонецЕсли;
Если Ложь
Или СтрокиОдноименных.Количество() = 0
Или (Истина
И СтрокиОдноименных.Количество() = 1
И ИсключаемаяСтрока <> Неопределено
И СтрокиРавныЛкс(ТекущийПсевдоним, ИсключаемаяСтрока[ИмяКлючевойКолонки])
)
Тогда
Прервать;
КонецЕсли;
ТекущийИндекс = ТекущийИндекс + 1;
КонецЦикла;
Возврат ТекущийПсевдоним;
КонецФункции
// Сравнение - Строка, ВидСравнения - "Авто" - для автоматического выбора, по умолчанию Равно или ВСписке
//
// Параметры:
// ЭлементОтбора - <тип> -
// Сравнение - <тип>, "" -
// Значение - <тип> -
// ЗначениеПо - <тип> -
// Использование - <тип>, Истина -
// ПриводитьТипДляНеопределено - <тип>, Истина -
//
// Возвращаемое значение:
//
Функция УстановитьЭлементОтбораЛкс(Знач ЭлементОтбора, Знач Сравнение = "", Знач Значение, Знач ЗначениеПо = Неопределено, Знач Использование = Истина,
Знач ПриводитьТипДляНеопределено = Истина) Экспорт
Если ТипЗнч(Значение) = Тип("ФиксированныйМассив") Тогда
Значение = Новый Массив(Значение);
КонецЕсли;
Если ТипЗнч(Значение) = Тип("Массив") Тогда
СписокЗначений = Новый СписокЗначений;
СписокЗначений.ЗагрузитьЗначения(Значение);
Значение = СписокЗначений;
ИначеЕсли Истина
И ПриводитьТипДляНеопределено
И Значение = Неопределено
Тогда
Значение = ЭлементОтбора.ТипЗначения.ПривестиЗначение(Значение);
КонецЕсли;
// Вид сравнения
Если СтрокиРавныЛкс(Сравнение, "Авто") Тогда
Сравнение = ОпределитьВидСравненияПоЗначениюЛкс(Значение);
ИначеЕсли ТипЗнч(Сравнение) = Тип("ВидСравнения") Тогда
ИначеЕсли Истина
И Сравнение <> Неопределено
И Сравнение <> ""
Тогда // Добавлено 25.03.2012
ВызватьИсключение "Неверный тип сравнения """ + ТипЗнч(Сравнение) + """";
Иначе
Если ТипЗнч(Значение) = Тип("СписокЗначений") Тогда
Сравнение = ВидСравнения.ВСписке;
Иначе
Сравнение = ВидСравнения.Равно;
КонецЕсли;
КонецЕсли;
// Еще надо сделать автоопределение Содержит, как у компоновки
ЭлементОтбора.ВидСравнения = Сравнение;
Попытка
Если ЗначениеПо <> Неопределено Тогда
ЭлементОтбора.ЗначениеС = Значение;
ЭлементОтбора.ЗначениеПО = ЗначениеПо;
Иначе
ЭлементОтбора.Значение = Значение;
КонецЕсли;
Исключение
ВызватьИсключение "Ошибка установки значения типа """ + ТипЗнч(Значение) + """ элементу отбора """ + ЭлементОтбора.Имя + """: " + ОписаниеОшибки();
КонецПопытки;
Попытка
ЭлементОтбора.Использование = Использование;
Исключение
// Сюда попадаем для элемента отбора набора записей с регистратором
КонецПопытки;
КонецФункции
// Установить отбор по структуре
//
// Параметры:
// Отбор - <тип> -
// СтруктураОтбора - <тип> -
// Сравнение - <тип>, "Авто" -
// ДобавлятьСсылкуВПутьКДанным - <тип>, Ложь -
// СброситьПередУстановкой - <тип>, Истина -
//
// Возвращаемое значение:
//
Функция УстановитьОтборПоСтруктуреЛкс(Знач Отбор, Знач СтруктураОтбора, Знач Сравнение = "Авто", Знач ДобавлятьСсылкуВПутьКДанным = Ложь,
Знач СброситьПередУстановкой = Истина) Экспорт
Если СброситьПередУстановкой Тогда
Отбор.Сбросить();
КонецЕсли;
Для Каждого КлючИЗначение Из СтруктураОтбора Цикл
ПутьКДанным = КлючИЗначение.Ключ;
Если ДобавлятьСсылкуВПутьКДанным Тогда
ПутьКДанным = "Ссылка." + ПутьКДанным;
КонецЕсли;
НайтиДобавитьЭлементОтбораЛкс(Отбор, ПутьКДанным, Сравнение, КлючИЗначение.Значение, , , КлючИЗначение.Ключ);
КонецЦикла;
КонецФункции
Процедура УстановитьОтборПоПодстрокеЛкс(ЭлементОтбора, Знач Подстрока = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ЭлементОтбора = Новый ПостроительЗапроса;
ЭлементОтбора = ЭлементОтбора.Отбор.Добавить();
#КонецЕсли
ЭлементОтбора.ВидСравнения = ВидСравнения.Содержит;
Если Подстрока <> Неопределено Тогда
ЭлементОтбора.Значение = Подстрока;
КонецЕсли;
ЭлементОтбора.Использование = ЗначениеЗаполнено(ЭлементОтбора.Значение);
КонецПроцедуры
Процедура ПриИзмененииПоляВводаОтбораСодержитЛкс(Знач ЭтаФорма, Знач ПолеВвода) Экспорт
ПутьКЭлементуОтбора = СтрокаБезПоследнегоФрагментаЛкс(СтрЗаменить(ПолеВвода.Данные, ".Отбор.", ".ОтборСтрок."), ".Значение");
ЭлементОтбора = Вычислить("ЭтаФорма." + ПутьКЭлементуОтбора);
УстановитьОтборПоПодстрокеЛкс(ЭлементОтбора);
Если ЭлементОтбора.Значение = "" Тогда
ПолеВвода.Значение = ЭлементОтбора.Значение; // Рассинхронизация при очистке случается, если поле напрямую связано с элементом отбора
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьНаборЗаписейПоОтборуЛкс(Знач НаборЗаписей) Экспорт
Если ТипЗнч(НаборЗаписей) = Тип("Структура") Тогда
СтрокиНабора = НаборЗаписей.Данные;
НаборЗаписей = НаборЗаписей.Методы;
Иначе
НаборЗаписей = НаборЗаписей;
СтрокиНабора = НаборЗаписей;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
СтрокиНабора = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
#КонецЕсли
СтруктураЗначенийОтбора = Новый Структура;
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
Если ЭлементОтбора.Использование Тогда
СтруктураЗначенийОтбора.Вставить(ЭлементОтбора.Имя, ЭлементОтбора.Значение);
КонецЕсли;
КонецЦикла;
Для Каждого СтрокаНабора Из СтрокиНабора Цикл
ЗаполнитьЗначенияСвойств(СтрокаНабора, СтруктураЗначенийОтбора);
КонецЦикла;
КонецПроцедуры
// Параметры:
// Объект - Ссылочный объект или запись регистра
// Отбор - Отбор, ОтборКомпоновкиДанных
//
Функция УстановитьЗначенияРеквизитовПоОтборуЛкс(Объект, Отбор) Экспорт
Если ТипЗнч(Отбор) = Тип("Отбор") Тогда
#Если Сервер И Не Сервер Тогда
Отбор = Новый ПостроительЗапроса;
Отбор = Отбор.Отбор;
#КонецЕсли
Для Каждого ЭлементОтбора Из Отбор Цикл
Если Ложь
Или Не ЭлементОтбора.Использование
Или ЭлементОтбора.ВидСравнения <> ВидСравнения.Равно
Тогда
Продолжить;
КонецЕсли;
ИмяРеквизита = ЭлементОтбора.Имя;
ЗначениеОтбора = ЭлементОтбора.Значение;
Попытка
Объект[ИмяРеквизита] = ЗначениеОтбора;
Исключение
// Сюда попадаем например для ЭтоГруппа
КонецПопытки;
КонецЦикла;
Иначе
#Если Сервер И Не Сервер Тогда
Отбор = Новый НастройкиКомпоновкиДанных;
Отбор = Отбор.Отбор;
#КонецЕсли
Для Каждого ЭлементОтбора Из Отбор.Элементы Цикл
Если Ложь
Или Не ЭлементОтбора.Использование
Или ЭлементОтбора.ВидСравнения <> ВидСравненияКомпоновкиДанных.Равно
Тогда
Продолжить;
КонецЕсли;
ИмяРеквизита = "" + ЭлементОтбора.ЛевоеЗначение;
Если Найти(ИмяРеквизита, ".") > 0 Тогда
Продолжить;
КонецЕсли;
ЗначениеОтбора = ЭлементОтбора.ПравоеЗначение;
Попытка
Объект[ИмяРеквизита] = ЗначениеОтбора;
Исключение
// Сюда попадаем например для ЭтоГруппа
КонецПопытки;
КонецЦикла;
КонецЕсли;
КонецФункции
// Определить вид сравнения по значению
//
// Параметры:
// Значение - <тип> -
// РежимКомпоновки - <тип>, Ложь -
// ДоступныеВидыСравнения - <тип>, Неопределено -
//
// Возвращаемое значение:
//
Функция ОпределитьВидСравненияПоЗначениюЛкс(Знач Значение, Знач РежимКомпоновки = Ложь, Знач ДоступныеВидыСравнения = Неопределено) Экспорт
ТипЗначения = ТипЗнч(Значение);
Если РежимКомпоновки Тогда
КоллекцияВидовСравнения = ВидСравненияКомпоновкиДанных;
Иначе
КоллекцияВидовСравнения = ВидСравнения;
КонецЕсли;
Если ТипЗначения = Тип("СписокЗначений") Тогда
Результат = КоллекцияВидовСравнения.ВСписке;
ИначеЕсли Истина
И ТипЗначения = Тип("Строка")
И ДоступныеВидыСравнения <> Неопределено
И ДоступныеВидыСравнения.НайтиПоЗначению(КоллекцияВидовСравнения.Содержит) <> Неопределено
Тогда
Результат = КоллекцияВидовСравнения.Содержит;
Иначе
Результат = КоллекцияВидовСравнения.Равно;
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗначения);
Если ОбъектМД <> Неопределено Тогда
ТипТаблицы = ТипТаблицыБДЛкс(ОбъектМД.ПолноеИмя());
Если ТипТаблицы = "Справочник" Тогда
Если ОбъектМД.ВидИерархии = Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда
Если Значение.ЭтоГруппа Тогда
Результат = КоллекцияВидовСравнения.ВИерархии;
КонецЕсли;
Иначе // иерархия элементов
Результат = КоллекцияВидовСравнения.ВИерархии;
КонецЕсли;
ИначеЕсли ТипТаблицы = "ПланВидовХарактеристик" Тогда
Если Значение.ЭтоГруппа Тогда
Результат = КоллекцияВидовСравнения.ВИерархии;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// .
// Параметры:
// ОтборИлиОбъект - ПостроительЗапроса, Отбор -
// ПутьКДанным - Строка -
// Сравнение - Строка, ВидСравнения - "Авто" - для автоматического выбора, по умолчанию Равно или ВСписке
// Значение - Произвольный -
// ЗначениеПо - Произвольный -
// Использование - Булево -
// Имя - Строка -
// Представление - Строка -
//
// Возвращаемое значение:
// ЭлементОтбора
Функция НайтиДобавитьЭлементОтбораЛкс(Знач ОтборИлиОбъект, Знач ПутьКДанным = "", Знач Сравнение = "", Знач Значение = Неопределено, Знач ЗначениеПо = Неопределено,
Знач Использование = Истина, Знач Имя = "", Знач Представление = "") Экспорт
Если ТипЗнч(ОтборИлиОбъект) = Тип("Отбор") Тогда
Отбор = ОтборИлиОбъект;
Иначе
Отбор = ОтборИлиОбъект.Отбор;
КонецЕсли;
// Ищем или добавляем новый элемент отбора
ЭлементОтбора = Неопределено;
//Если Имя <> Неопределено Тогда
// ЭлементОтбора= Отбор.Найти(Имя);
//КонецЕсли;
Если Имя <> Неопределено Тогда
Для Каждого ЭлОтбора Из Отбор Цикл
Если Ложь
Или ЭлОтбора.Имя = Имя
Или ЭлОтбора.Представление = Имя
Тогда
ЭлементОтбора = ЭлОтбора;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЭлементОтбора = Неопределено Тогда
Попытка
ЭлементОтбора = Отбор.Добавить(ПутьКДанным, Имя, Представление);
Исключение
ВызватьИсключение "Ошибка добавления элемента отбора """ + ПутьКДанным + """ построителя запроса: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
УстановитьЭлементОтбораЛкс(ЭлементОтбора, Сравнение, Значение, ЗначениеПо, Использование);
Результат = ЭлементОтбора;
Возврат Результат;
КонецФункции
Процедура ДобавитьПрефиксВсемПараметрамЗапросаЛкс(Запрос, Префикс = "Т") Экспорт
#Если Сервер И Не Сервер Тогда
Запрос = Новый Запрос;
#КонецЕсли
ТекстЗапроса = Запрос.Текст;
Параметры = Новый Структура;
СкопироватьКоллекциюЛкс(Запрос.Параметры, Параметры);
Для Каждого КлючИЗначение Из Параметры Цикл
Если Найти(КлючИЗначение.Ключ, Префикс) = 1 Тогда
ВызватьИсключение "Начало имени параметра " + КлючИЗначение.Ключ + " совпадает с префиксом " + Префикс;
КонецЕсли;
НовоеИмя = Префикс + КлючИЗначение.Ключ;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&" + КлючИЗначение.Ключ, "&" + НовоеИмя);
Запрос.УстановитьПараметр(НовоеИмя, КлючИЗначение.Значение);
КонецЦикла;
Запрос.Текст = ТекстЗапроса;
КонецПроцедуры
// ТаблицаПараметров - ТаблицаЗначений, ТабличнаяЧасть
Функция НайтиДобавитьПараметрСсылкуВТаблицуЛкс(ТаблицаПараметров, ИмяКолонкиИмени = "Имя", ИмяКолонкиЗначения = "Значение", ЗначениеПараметра,
ИмяПараметра = Неопределено, ОбновитьКопиюСвойстваВНижнемРегистре = Ложь, Знач ИскатьСУчетомИмени = Истина) Экспорт
Если ТипЗнч(ТаблицаПараметров) = Тип("ТаблицаЗначений") Тогда
МакетТаблицы = ТаблицаПараметров;
Иначе
МакетТаблицы = ТаблицаПараметров.ВыгрузитьКолонки();
КонецЕсли;
Отбор = Новый Структура(ИмяКолонкиЗначения, ЗначениеПараметра);
Если ЗначениеЗаполнено(ИмяПараметра) И ИскатьСУчетомИмени Тогда
Отбор.Вставить(ИмяКолонкиИмени, ИмяПараметра);
КонецЕсли;
Строки = ТаблицаПараметров.НайтиСтроки(Отбор);
Если Строки.Количество() > 0 Тогда
Результат = Строки[0];
Иначе
Если ТипЗнч(ЗначениеПараметра) = Тип("Строка") Тогда
ИмяПараметра = АвтоУникальноеИмяВКоллекцииЛкс(ТаблицаПараметров, "П", ИмяКолонкиИмени);
Иначе
ИмяТипа = ИмяТипаИзПолногоИмениМДЛкс(ПолучитьПолноеИмяМДТипаЛкс(ТипЗнч(ЗначениеПараметра)));
//Префикс = НРег(Лев(ОбъектМД.Имя, 1));
Префикс = "";
Если ИмяПараметра = Неопределено Тогда
ИмяПараметра = "" + РасширенноеПредставлениеЛкс(ЗначениеПараметра);
КонецЕсли;
Если Не ЗначениеЗаполнено(ИмяПараметра) Тогда
ИмяПараметра = СтрЗаменить(ИмяТипа, ".", "") + "Пустая";
КонецЕсли;
ИмяПараметра = Префикс + ИдентификаторИзПредставленияЛкс(ИмяПараметра);
ДопустимаяДлинаСтроки = МакетТаблицы.Колонки[ИмяКолонкиИмени].ТипЗначения.КвалификаторыСтроки.Длина;
Если ДопустимаяДлинаСтроки > 0 Тогда
ИмяПараметра = Лев(ИмяПараметра, ДопустимаяДлинаСтроки);
КонецЕсли;
КонецЕсли;
СтруктураСвойствПараметра = Новый Структура;
СтруктураСвойствПараметра.Вставить(ИмяКолонкиИмени, ИмяПараметра);
Счетчик = 0;
Пока ТаблицаПараметров.НайтиСтроки(СтруктураСвойствПараметра).Количество() > 0 Цикл
Счетчик = Счетчик + 1;
СтрокаНомера = "" + Счетчик;
Если ДопустимаяДлинаСтроки > 0 Тогда
лИмяПараметра = Лев(ИмяПараметра, ДопустимаяДлинаСтроки - СтрДлина(СтрокаНомера));
Иначе
лИмяПараметра = ИмяПараметра;
КонецЕсли;
СтруктураСвойствПараметра[ИмяКолонкиИмени] = лИмяПараметра + СтрокаНомера;
КонецЦикла;
СтруктураСвойствПараметра.Вставить("ЭтоВыражение", Ложь);
СтруктураСвойствПараметра.Вставить(ИмяКолонкиЗначения, ЗначениеПараметра);
СтрокаНовогоПараметра = ТаблицаПараметров.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаНовогоПараметра, СтруктураСвойствПараметра);
Если ОбновитьКопиюСвойстваВНижнемРегистре Тогда
ОбновитьКопиюСвойстваВНижнемРегистреЛкс(СтрокаНовогоПараметра, ИмяКолонкиИмени);
КонецЕсли;
Результат = СтрокаНовогоПараметра;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция НаборЗаписейИзКлючаЛкс(ПолноеИмяТаблицыИлиНаборЗаписей, Знач КлючНабора, ДобавитьИЗаполнитьСтрокуНабора = Ложь) Экспорт
Если ТипЗнч(ПолноеИмяТаблицыИлиНаборЗаписей) = Тип("Строка") Тогда
СтруктураНабораЗаписей = СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ПолноеИмяТаблицыИлиНаборЗаписей);
НаборЗаписей = СтруктураНабораЗаписей.Методы;
Иначе
НаборЗаписей = ПолноеИмяТаблицыИлиНаборЗаписей;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
#КонецЕсли
////СтруктураКлюча = ПолучитьСтруктуруКлючаТаблицыБДЛкс(ирКэш.ИмяТаблицыИзМетаданныхЛкс(НаборЗаписей.Метаданные().ПолноеИмя()), Ложь);
////Для Каждого ПолеКлюча Из СтруктураКлюча Цикл
//// ИмяПоля = ПолеКлюча.Ключ;
//// Попытка
//// ЗначениеКлюча = КлючНабора[ИмяПоля];
//// Исключение
//// // Имеет смысл для регистров сведений
//// Продолжить;
//// КонецПопытки;
//// ЭлементОтбора = НаборЗаписей.Отбор[ИмяПоля];
//// ЭлементОтбора.Значение = ЗначениеКлюча;
//// ЭлементОтбора.Использование = Истина;
////КонецЦикла;
Если ЛиКлючЗаписиРегистраЛкс(КлючНабора) Тогда
// Это нужно для обращения по имени к предопределенным свойствам ключа записи
КлючНабора = СтруктураИзКлючаЗаписиЛкс(КлючНабора, ПолноеИмяТаблицыИлиНаборЗаписей);
КонецЕсли;
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
ИмяПоля = ЭлементОтбора.Имя;
Попытка
ЗначениеКлюча = КлючНабора[ИмяПоля];
Исключение
// Имеет смысл для регистров сведений
Продолжить;
КонецПопытки;
ЭлементОтбора.Значение = ЗначениеКлюча;
ЭлементОтбора.Использование = Истина;
КонецЦикла;
Если ДобавитьИЗаполнитьСтрокуНабора Тогда
ЗаполнитьЗначенияСвойств(НаборЗаписей.Добавить(), КлючНабора);
КонецЕсли;
Возврат НаборЗаписей;
КонецФункции
// Создает копию таблицы значений с суженными типами колонок без потери данных.
//
// Параметры:
// ТаблицаДанных - ТаблицаЗначений - исходная таблица, не модифицируется
// СужатьТолькоПроизвольныеКолонки - Булево - обрабатывать только колонки с пустым (произвольным) типом
// ИмяОднойКолонки - Строка - в выходной таблице будет только одна эта колонка
// ДлинаСтроки - - Число* - используется для обрезки строк, чья длина превышает заданную
// УдалятьТолькоТипNull - Булево - удалять только тип Null, а остальные типы не трогать
// СужатьПустыеКвалификаторы - Булево - для числовых и строковых типов с пустыми квалификаторами вычислять минимальные квалификаторы
// НеСужаемыеКолонки - Массив - массив имен колонок, типы которых нельзя сужать
// ДанныеНеНужны - Ложь - можно ли возвращать таблицу без данных, если это ускорит выполнение
// ОставлятьНеопределенныеКолонки - Булево - при Истина колонки, содержащие только "Неопределено", остаются неизменнными
//
// Возвращаемое значение:
// ТаблицаЗначений - преобразованная таблица значений, в частных случаях может являться входной таблицей
//
Функция СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(Знач ТаблицаДанных, СужатьТолькоПроизвольныеКолонки = Ложь, ИмяОднойКолонки = "", Знач ДлинаСтроки = Неопределено, Знач УдалятьТолькоТипNull = Ложь,
Знач СужатьПустыеКвалификаторы = Ложь, Знач НеСужаемыеКолонки = Неопределено, Знач ДанныеНеНужны = Ложь, Знач ОставлятьНеопределенныеКолонки = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаДанных = Новый ТаблицаЗначений;
#КонецЕсли
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
АнализируемыеКолонки = Новый Массив;
ИменаНесужаемыхКолонок = Новый Структура;
Для Каждого КолонкаДанных Из ТаблицаДанных.Колонки Цикл
Если ЗначениеЗаполнено(ИмяОднойКолонки) И Не СтрокиРавныЛкс(ИмяОднойКолонки, КолонкаДанных.Имя) Тогда
Продолжить;
КонецЕсли;
КоличествоТипов = КолонкаДанных.ТипЗначения.Типы().Количество();
Если Ложь
Или (Истина
И НеСужаемыеКолонки <> Неопределено
И НеСужаемыеКолонки.Найти(КолонкаДанных.Имя) <> Неопределено)
Или (Истина
И КоличествоТипов = 1
И (Ложь
Или Не СужатьПустыеКвалификаторы
Или (Истина
И КолонкаДанных.ТипЗначения.СодержитТип(Тип("Число"))
И КолонкаДанных.ТипЗначения.КвалификаторыЧисла.Разрядность > 0)
Или (Истина
И КолонкаДанных.ТипЗначения.СодержитТип(Тип("Строка"))
И КолонкаДанных.ТипЗначения.КвалификаторыСтроки.Длина > 0)
Или (Истина
И Не КолонкаДанных.ТипЗначения.СодержитТип(Тип("Число"))
И Не КолонкаДанных.ТипЗначения.СодержитТип(Тип("Строка")))))
Или (Истина
И СужатьТолькоПроизвольныеКолонки
И КоличествоТипов > 0)
Или (Истина
И УдалятьТолькоТипNull
И (Ложь
Или КоличествоТипов = 0
Или Не КолонкаДанных.ТипЗначения.СодержитТип(Тип("Null"))))
Тогда
ИменаНесужаемыхКолонок.Вставить(КолонкаДанных.Имя);
КонецЕсли;
АнализируемыеКолонки.Добавить(КолонкаДанных);
КонецЦикла;
//СостояниеЛкс("Оптимизация типов колонок");
НовыеКолонки = Новый Структура;
ОставляемыеКолонки = "";
МетаданныеТаблицыИзменены = Ложь;
ВсеРедактируемыеТипы = ОписаниеТиповВсеРедактируемыеТипыЛкс();
#Если Сервер И Не Сервер Тогда
ВсеРедактируемыеТипы = Новый ОписаниеТипов;
#КонецЕсли
Если (АнализируемыеКолонки.Количество() - ИменаНесужаемыхКолонок.Количество()) * ТаблицаДанных.Количество() > 10000 Тогда
Индикатор = ПолучитьИндикаторПроцессаЛкс(АнализируемыеКолонки.Количество(), "Анализ колонок");
КонецЕсли;
Для Каждого КолонкаДанных Из АнализируемыеКолонки Цикл
#Если Сервер И Не Сервер Тогда
КолонкаДанных = ТаблицаДанных.Колонки.Добавить();
#КонецЕсли
Если Индикатор <> Неопределено Тогда
ОбработатьИндикаторЛкс(Индикатор);
КонецЕсли;
ИмяКолонки = КолонкаДанных.Имя;
Типы = Новый Массив;
ТаблицаКолонки = ТаблицаДанных.Скопировать(, ИмяКолонки);
ТаблицаКолонки.Свернуть(ИмяКолонки);
СтароеОписаниеТипов = КолонкаДанных.ТипЗначения;
СужатьЧисло = Ложь;
СужатьСтроку = Ложь;
МаксДлинаЧислаЦелая = 0;
МаксДлинаЧислаДробная = 0;
ЧислоМожетБытьОтрицательным = Ложь;
МаксДлинаСтроки = 0;
Если СужатьПустыеКвалификаторы Тогда
Если Истина
И СтароеОписаниеТипов.СодержитТип(Тип("Число"))
И СтароеОписаниеТипов.КвалификаторыЧисла.Разрядность = 0
Тогда
СужатьЧисло = Истина;
ИначеЕсли Истина
И СтароеОписаниеТипов.СодержитТип(Тип("Строка"))
И СтароеОписаниеТипов.КвалификаторыСтроки.Длина = 0
Тогда
СужатьСтроку = Истина;
КонецЕсли;
КонецЕсли;
ЕстьТипНеопределено = Ложь;
КоличествоТипов = КолонкаДанных.ТипЗначения.Типы().Количество();
Если ИменаНесужаемыхКолонок.Свойство(ИмяКолонки) Тогда
ПропуститьКолонку = Истина;
ИначеЕсли УдалятьТолькоТипNull Тогда
ПропуститьКолонку = ТаблицаКолонки.Найти(Null) <> Неопределено;
Иначе
ПропуститьКолонку = Ложь;
Для Каждого СтрокаДанных Из ТаблицаКолонки Цикл
ЗначениеЯчейки = СтрокаДанных[ИмяКолонки];
ТипЗначения = ТипЗнч(ЗначениеЯчейки);
Если Истина
И Не ВсеРедактируемыеТипы.СодержитТип(ТипЗначения)
И Метаданные.НайтиПоТипу(ТипЗначения) = Неопределено // Ключи записей регистров
Тогда
// Антибаг платформы 8.2-8.3
#Если Сервер И Не Сервер Тогда
_БезопасноеОписаниеТиповЛкс();
#КонецЕсли
ПропуститьКолонку = Истина;
Прервать;
КонецЕсли;
Если СужатьПустыеКвалификаторы Тогда
Если СужатьЧисло И ТипЗначения = Тип("Число") Тогда
Если ЗначениеЯчейки < 0 Тогда
ЗначениеЯчейки = -ЗначениеЯчейки;
Если Не ЧислоМожетБытьОтрицательным Тогда
ЧислоМожетБытьОтрицательным = Истина;
КонецЕсли;
КонецЕсли;
Фрагменты = СтрРазделитьЛкс(XMLСтрока(ЗначениеЯчейки));
#Если Сервер И Не Сервер Тогда
Фрагменты = Новый Массив;
#КонецЕсли
МаксДлинаЧислаЦелая = Макс(МаксДлинаЧислаЦелая, СтрДлина(Фрагменты[0]));
Если Фрагменты.Количество() > 1 Тогда
МаксДлинаЧислаДробная = Макс(МаксДлинаЧислаДробная, СтрДлина(Фрагменты[1]));
КонецЕсли;
ИначеЕсли СужатьСтроку И ТипЗначения = Тип("Строка") Тогда
МаксДлинаСтроки = Макс(МаксДлинаСтроки, СтрДлина(ЗначениеЯчейки));
КонецЕсли;
КонецЕсли;
Если ТипЗначения = Тип("Неопределено") Тогда
ЕстьТипНеопределено = Истина;
ИначеЕсли Типы.Найти(ТипЗначения) = Неопределено Тогда
Типы.Добавить(ТипЗначения);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ПропуститьКолонку Тогда
ОставляемыеКолонки = ОставляемыеКолонки + "," + КолонкаДанных.Имя;
Продолжить;
КонецЕсли;
Если УдалятьТолькоТипNull Тогда
Типы = КолонкаДанных.ТипЗначения.Типы();
Типы.Удалить(Типы.Найти(Тип("Null")));
Иначе
Если Типы.Количество() = 0 Тогда
Типы = КолонкаДанных.ТипЗначения.Типы();
Если Типы.Количество() = 0 И Не ОставлятьНеопределенныеКолонки Тогда
Типы.Добавить(Тип("Булево"));
Типы.Добавить(Тип("Число")); // https://www.hostedredmine.com/issues/961925
////Типы.Добавить(Тип("Null")); // Если будет вместе с одним типом, то в итоге получится простой тип
КонецЕсли;
// Чтобы от супертипов через точку не было много соединений, оставляем только 2 типа
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Пока Типы.Количество() > 2 Цикл
Типы.Удалить(0);
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Пока Типы.Количество() > 2 Цикл Типы.Удалить(0); КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Типы.Количество() = 1 И ЕстьТипНеопределено Тогда
Типы.Добавить(Тип("Null")); // Иначе будут потеряны значения Неопределено
КонецЕсли;
Если Типы.Количество() <> СтароеОписаниеТипов.Типы().Количество() Тогда
МетаданныеТаблицыИзменены = Истина;
КонецЕсли;
Если МаксДлинаЧислаЦелая > 0 Тогда
МетаданныеТаблицыИзменены = Истина;
КвалификаторыЧисла = Новый КвалификаторыЧисла(МаксДлинаЧислаЦелая + МаксДлинаЧислаДробная, МаксДлинаЧислаДробная, ?(ЧислоМожетБытьОтрицательным, ДопустимыйЗнак.Любой, ДопустимыйЗнак.Неотрицательный));
Иначе
КвалификаторыЧисла = СтароеОписаниеТипов.КвалификаторыЧисла;
КонецЕсли;
Если МаксДлинаСтроки > 0 Тогда
МетаданныеТаблицыИзменены = Истина;
КвалификаторыСтроки = Новый КвалификаторыСтроки(МаксДлинаСтроки);
Иначе
КвалификаторыСтроки = СтароеОписаниеТипов.КвалификаторыСтроки;
КонецЕсли;
Если Истина
И ДлинаСтроки <> Неопределено
И (Ложь
Или КвалификаторыСтроки.Длина = 0
Или КвалификаторыСтроки.Длина > ДлинаСтроки)
Тогда
КвалификаторыСтроки = Новый КвалификаторыСтроки(ДлинаСтроки);
КонецЕсли;
НовоеОписаниеТипов = Новый ОписаниеТипов(Типы, , , КвалификаторыЧисла, КвалификаторыСтроки, СтароеОписаниеТипов.КвалификаторыДаты);
НовыеКолонки.Вставить(ИмяКолонки, НовоеОписаниеТипов);
КонецЦикла;
Если Индикатор <> Неопределено Тогда
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
Если МетаданныеТаблицыИзменены Тогда
Если ОставляемыеКолонки <> "" Тогда
Если ДанныеНеНужны Тогда
ТипизированнаяТаблица = ТаблицаДанных.СкопироватьКолонки(ОставляемыеКолонки);
Иначе
ТипизированнаяТаблица = ТаблицаДанных.Скопировать(, ОставляемыеКолонки);
КонецЕсли;
Иначе
ТипизированнаяТаблица = Новый ТаблицаЗначений;
КонецЕсли;
Если Не ДанныеНеНужны И ТипизированнаяТаблица.Количество() = 0 Тогда
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Счетчик = 1 По ТаблицаДанных.Количество() Цикл
ТипизированнаяТаблица.Добавить();
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Счетчик = 1 По ТаблицаДанных.Количество() Цикл ТипизированнаяТаблица.Добавить(); КонецЦикла;
КонецЕсли;
КонецЕсли;
Для Каждого КлючИЗначение Из НовыеКолонки Цикл
ОригинальнаяКолонка = ТаблицаДанных.Колонки[КлючИЗначение.Ключ];
НоваяКолонка = ТипизированнаяТаблица.Колонки.Добавить(КлючИЗначение.Ключ, КлючИЗначение.Значение, ОригинальнаяКолонка.Заголовок, ОригинальнаяКолонка.Ширина);
Если Не ДанныеНеНужны Тогда
ТипизированнаяТаблица.ЗагрузитьКолонку(ТаблицаДанных.ВыгрузитьКолонку(КлючИЗначение.Ключ), КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
Если ТаблицаДанных.Колонки.Количество() = ТипизированнаяТаблица.Колонки.Количество() Тогда // Защита от ситуации урезания состава колонок
Для Каждого КлючИЗначение Из НовыеКолонки Цикл
ОригинальнаяКолонка = ТаблицаДанных.Колонки[КлючИЗначение.Ключ];
НоваяКолонка = ТипизированнаяТаблица.Колонки[КлючИЗначение.Ключ];
ТипизированнаяТаблица.Колонки.Сдвинуть(НоваяКолонка, ТаблицаДанных.Колонки.Индекс(ОригинальнаяКолонка) - ТипизированнаяТаблица.Колонки.Индекс(НоваяКолонка));
КонецЦикла;
КонецЕсли;
Иначе
ТипизированнаяТаблица = ТаблицаДанных;
КонецЕсли;
Результат = ТипизированнаяТаблица;
Возврат Результат;
КонецФункции
Процедура ИзменитьТипКолонкиТаблицыЗначенийЛкс(Знач ТаблицаЗначений, Знач ИмяКолонки, Знач НовыйТипКолонки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
Если НовыйТипКолонки = Неопределено Тогда
НовыйТипКолонки = Новый ОписаниеТипов;
КонецЕсли;
ИмяВременнойКолонки = НовоеУникальноеИмяЛкс();
МассивДанныхКолонки = ТаблицаЗначений.ВыгрузитьКолонку(ИмяКолонки);
ТаблицаЗначений.Колонки.Добавить(ИмяВременнойКолонки, НовыйТипКолонки);
ТаблицаЗначений.ЗагрузитьКолонку(МассивДанныхКолонки, ИмяВременнойКолонки);
ТаблицаЗначений.Колонки.Удалить(ИмяКолонки);
ТаблицаЗначений.Колонки[ИмяВременнойКолонки].Имя = ИмяКолонки;
КонецПроцедуры
// ************************
// WMI
Функция СтруктураИзЗначенияWMIЛкс(ЗначениеWMI) Экспорт
Результат = Новый Структура;
Для каждого СвойствоWMI из ЗначениеWMI Цикл
Если ТипЗнч(СвойствоWMI.Value) = Тип("COMSafeArray") Тогда
ЗначениеСвойства = СвойствоWMI.Value.Выгрузить();// возможно массив надо будет переделать
Иначе
ЗначениеСвойства = СвойствоWMI.Value;
//ИмяТипа = ИмяТипаИзКвалификаторовWMIЛкс(СвойствоWMI);
//Если СтрокиРавныЛкс(ИмяТипа, "Дата") Тогда
Если СвойствоWMI.CIMTYPE = 101 Тогда //datetime
ЗначениеСвойства = СтрокаДатыWMIВДатуЛкс(ЗначениеСвойства);
КонецЕсли;
КонецЕсли;
Результат.Вставить(СвойствоWMI.Name, ЗначениеСвойства);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ИмяТипаИзКвалификаторовWMIЛкс(Свойство) Экспорт
ИмяТипа = "";
Попытка
Квалификаторы = Свойство.Qualifiers_;
Исключение
// Нет у системных свойств
Квалификаторы = Новый Массив();
КонецПопытки;
Для Каждого Квалификатор Из Квалификаторы Цикл
Если СтрокиРавныЛкс("CIMTYPE", Квалификатор.Name) Тогда
ИмяТипа = Нрег(Квалификатор.Value);
Прервать;
КонецЕсли;
КонецЦикла;
Если Ложь
Или Найти(ИмяТипа, "int") > 0
Тогда
ИмяТипа = "Число";
ИначеЕсли Ложь
Или Найти(ИмяТипа, "date") > 0
Или Найти(ИмяТипа, "time") > 0
Тогда
ИмяТипа = "Дата";
ИначеЕсли Ложь
Или Найти(ИмяТипа, "string") > 0
Или Найти(ИмяТипа, "char") > 0
Тогда
ИмяТипа = "Строка";
ИначеЕсли ТипЗнч(ИмяТипа) = Тип("COMОбъект") Тогда
ИмяТипа = ИмяТипа + " {WbemScripting.SwbemLocator}";
КонецЕсли;
Возврат ИмяТипа;
КонецФункции
Функция ПолучитьОписаниеЭлементаWMIЛкс(ЭлементКоллекции, ИмяСвойства = "Description") Экспорт
ОписаниеЭлемента = "";
Квалификаторы = ЭлементКоллекции.qualifiers_;
Попытка
КвалификаторОписание = Квалификаторы.item(ИмяСвойства);
Исключение
КвалификаторОписание = Неопределено;
КонецПопытки;
Если КвалификаторОписание <> Неопределено Тогда
ОписаниеЭлемента = КвалификаторОписание.Value;
КонецЕсли;
Возврат ОписаниеЭлемента;
КонецФункции
Функция ДокументацияСвойстваWMIЛкс(ИмяКласса, ИмяСвойства, СлужбаWMI = Неопределено) Экспорт
Если СлужбаWMI = Неопределено Тогда
СлужбаWMI = ирКэш.ПолучитьCOMОбъектWMIЛкс();
КонецЕсли;
wbemFlagUseAmendedQualifiers = 131072; //&H20000
ОписанияСвойств = СлужбаWMI.Get(ИмяКласса, wbemFlagUseAmendedQualifiers).Properties_;
Попытка
ОписаниеСвойства = ОписанияСвойств.item(ИмяСвойства);
Исключение
Возврат "";
КонецПопытки;
ТекстОписания = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеСвойства);
ТипЗначений = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеСвойства, "CIMTYPE");
Если ТипЗначений <> Неопределено Тогда
ТекстОписания = ТекстОписания + "
|Type: " + ТипЗначений;
КонецЕсли;
ЕдиницаИзмерения = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеСвойства, "Units");
Если ЗначениеЗаполнено(ЕдиницаИзмерения) Тогда
ТекстОписания = ТекстОписания + "
|Unit: " + ЕдиницаИзмерения;
КонецЕсли;
Возврат ТекстОписания;
КонецФункции
Функция ДокументацияМетодаWMIЛкс(ИмяКласса, ИмяМетода, СлужбаWMI = Неопределено) Экспорт
Если СлужбаWMI = Неопределено Тогда
СлужбаWMI = ирКэш.ПолучитьCOMОбъектWMIЛкс();
КонецЕсли;
wbemFlagUseAmendedQualifiers = 131072; //&H20000
ОписанияМетодов = СлужбаWMI.Get(ИмяКласса, wbemFlagUseAmendedQualifiers).Methods_;
Попытка
ОписаниеМетода = ОписанияМетодов.item(ИмяМетода);
Исключение
Возврат "";
КонецПопытки;
ТекстОписания = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеМетода);
ТипЗначений = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеМетода, "CIMTYPE");
Если ТипЗначений <> Неопределено Тогда
ТекстОписания = ТекстОписания + "
|Type: " + ТипЗначений;
КонецЕсли;
ЕдиницаИзмерения = ПолучитьОписаниеЭлементаWMIЛкс(ОписаниеМетода, "Units");
Если ЗначениеЗаполнено(ЕдиницаИзмерения) Тогда
ТекстОписания = ТекстОписания + "
|Unit: " + ЕдиницаИзмерения;
КонецЕсли;
Возврат ТекстОписания;
КонецФункции
// Параметры:
// СтрокаДаты - Строка(0,П)
//
Функция СтрокаДатыWMIВДатуЛкс(Знач СтрокаДаты = "") Экспорт
Если Не ЗначениеЗаполнено(СтрокаДаты) Тогда
Возврат Дата(1,1,1);
Иначе
Строка = Лев(СтрокаДаты, 4) + Сред(СтрокаДаты, 5, 2) + Сред(СтрокаДаты, 7, 2)
+ Сред (СтрокаДаты, 9, 2) + Сред(СтрокаДаты, 11, 2) + Сред(СтрокаДаты, 13, 2);
Попытка
Результат = Дата(Строка);
Исключение
СообщитьЛкс("Ошибка преобразования даты WMI из строки """ + СтрокаДаты + """: " + ОписаниеОшибки());
Возврат Дата(1,1,1);
КонецПопытки;
Результат = Результат + Вычислить("0." + Сред(СтрокаДаты, 16, 6));
КонецЕсли;
Возврат Результат;
КонецФункции
// WMI
// *************************
// ************************
// ADO
Функция ПолучитьКолонкиRecordsetADOЛкс(РезультатТаблица, РезультатRecordset, Типизировать1С = Неопределено) Экспорт
Если РезультатТаблица = Неопределено Тогда
РезультатТаблица = Новый ТаблицаЗначений;
КонецЕсли;
мПлатформа = ирКэш.Получить();
FieldКолонка = Новый Соответствие;
Для каждого Field Из РезультатRecordset.Fields Цикл
Если ПустаяСтрока(Field.Name) Тогда
ИмяКолонки = ":?";
Для о=1 По СтрДлина(Field.Name)-1 Цикл
ИмяКолонки = ИмяКолонки + "?";
КонецЦикла;
Иначе
ИмяКолонки = Field.Name;
КонецЕсли;
Если Не ЛиИмяПеременнойЛкс(ИмяКолонки) Тогда
ИмяКолонки = ИдентификаторИзПредставленияЛкс(ИмяКолонки);
КонецЕсли;
// контроль полей - двойников по именам
НомерДвойника=0;
Пока РезультатТаблица.Колонки.Найти(ИмяКолонки + Формат(НомерДвойника,"ЧГ=0")) <> Неопределено Цикл
НомерДвойника = НомерДвойника + 1;
КонецЦикла;
ИмяКолонки = ИмяКолонки + Формат(НомерДвойника, "ЧГ=0");
Если Типизировать1С = Истина Тогда
Тип1С = FieldADO_ПолучитьТип1CЛкс(Field);
Иначе
Тип1С = Неопределено;
КонецЕсли;
//Если Тип1С=Неопределено Тогда
// Колонка = РезультатТаблица.Колонки.Добавить(ИмяКолонки,,"["+Name+"]");
//Иначе
Колонка = РезультатТаблица.Колонки.Добавить(ИмяКолонки,Тип1С);
//КонецЕсли;
FieldКолонка.Вставить(Field, Колонка);
КонецЦикла;
Возврат FieldКолонка;
КонецФункции
// Выгружает результат запроса ADO (объект 'ADODB.Recordset') в таблицу значений с выводом прогресса состояния выгрузки
Функция ПреобразоватьРезультатADOВТаблицуЗначенийЛкс(РезультатRecordset, Типизировать1С = Ложь, БинарныеВСтроку = Ложь, RecordsAffected = 0,
ИгнорироватьНеподдерживаемыеТипы = Ложь, ЗагружатьЭлементов = Неопределено, СмещениеГода = 0) Экспорт
РезультатТаблица = Новый ТаблицаЗначений;
Если РезультатRecordset = Неопределено Тогда
Возврат РезультатТаблица;
КонецЕсли;
Если ЗначениеЗаполнено(ЗагружатьЭлементов) Тогда
КоличествоЭлементов = Мин(ЗагружатьЭлементов, РезультатRecordset.RecordCount);
Иначе
КоличествоЭлементов = РезультатRecordset.RecordCount;
КонецЕсли;
Если РезультатRecordset.State = 0 Тогда
// Выполнена команда
РезультатТаблица.Колонки.Добавить("ExecutionInfo",, "Информация о выполнении:");
Стр = РезультатТаблица.Добавить();
Стр.ExecutionInfo = "Число записей, обработанных запросом: " + RecordsAffected;
Иначе
FieldКолонка = ПолучитьКолонкиRecordsetADOЛкс(РезультатТаблица, РезультатRecordset, Типизировать1С);
// Открыта выборка
ТипCOMSafeArray = Тип("COMSafeArray");
adBinaryType = intTypeADOЛкс("adBinary");
adVarBinaryType = intTypeADOЛкс("adVarBinary");
adLongVarBinaryType = intTypeADOЛкс("adLongVarBinary");
Счетчик = 0;
Индикатор = ПолучитьИндикаторПроцессаЛкс(КоличествоЭлементов, "Загрузка результата");
Если Не РезультатRecordset.EOF И Не РезультатRecordset.BOF Тогда
РезультатRecordset.MoveFirst();
КонецЕсли;
Если Не РезультатRecordset.EOF Тогда
ТипыПолей = Новый Массив;
Для Индекс = 0 По РезультатТаблица.Колонки.Количество() - 1 Цикл
ТипыПолей.Добавить(РезультатRecordset.Fields.Item(Индекс).Type);
КонецЦикла;
МассивСтрок = РезультатRecordset.GetRows(КоличествоЭлементов).Unload();
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Если _РежимОтладки Тогда // ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для каждого МассивСтроки Из МассивСтрок Цикл
СтрокаРезультата = РезультатТаблица.Добавить();
Для Индекс = 0 По РезультатТаблица.Колонки.Количество() - 1 Цикл
ЗначениеПоля = МассивСтроки[Индекс];
Если Истина
И БинарныеВСтроку = Истина
И (Ложь
Или ТипЗнч(ЗначениеПоля) = Тип("Массив") // массив появляется после применения Unload()
Или (Истина
И ТипЗнч(ЗначениеПоля) = ТипCOMSafeArray
И (Ложь
Или ТипыПолей[0] = adBinaryType
Или ТипыПолей[0] = adVarBinaryType
//ИЛИ ТипыПолей[0] = adLongVarBinaryType
)))
Тогда
// преобразование COMSafeArray в строку HEX
ЗначениеПоля = МассивЧиселВHEXЛкс(ЗначениеПоля);
ИначеЕсли СмещениеГода <> 0 И ТипЗнч(ЗначениеПоля) = Тип("Дата") Тогда
ЗначениеПоля = ДобавитьМесяц(ЗначениеПоля, - СмещениеГода * 12);
Иначе
// преобразование типа неявное
КонецЕсли;
СтрокаРезультата[Индекс] = ЗначениеПоля;
КонецЦикла;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для каждого МассивСтроки Из МассивСтрок Цикл СтрокаРезультата = РезультатТаблица.Добавить(); Для Индекс = 0 По РезультатТаблица.Колонки.Количество() - 1 Цикл ЗначениеПоля = МассивСтроки[Индекс]; Если Истина И БинарныеВСтроку = Истина И (Ложь Или ТипЗнч(ЗначениеПоля) = Тип("Массив") Или (Истина И ТипЗнч(ЗначениеПоля) = ТипCOMSafeArray И (Ложь Или ТипыПолей[0] = adBinaryType Или ТипыПолей[0] = adVarBinaryType ))) Тогда ЗначениеПоля = МассивЧиселВHEXЛкс(ЗначениеПоля); ИначеЕсли СмещениеГода <> 0 И ТипЗнч(ЗначениеПоля) = Тип("Дата") Тогда ЗначениеПоля = ДобавитьМесяц(ЗначениеПоля, - СмещениеГода * 12); Иначе КонецЕсли; СтрокаРезультата[Индекс] = ЗначениеПоля; КонецЦикла; КонецЦикла;
КонецЕсли;
КонецЕсли;
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
//! РезультатТаблица = Новый ТаблицаЗначений; // Чтобы проверка модуля не считала колонки известными
Возврат РезультатТаблица;
КонецФункции
Функция РезультатЗапросаADOВТаблицуЗначенийОбщийЛкс(РезультатRecordset, Типизировать1С = Истина, БинарныеВСтроку = Ложь, ЗагружатьЭлементов = 0, СмещениеГода = 0, РазрешитьGameWithFire = Истина,
Знач ADOUtils = Неопределено, МодальныйРежим = Ложь) Экспорт
ТаблицаИзADO = Неопределено;
Если РазрешитьGameWithFire Тогда
Если ADOUtils = Неопределено Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ADOUtils = мПлатформа.ПолучитьADOUtils(, СмещениеГода, Истина, БинарныеВСтроку);
КонецЕсли;
Если ADOUtils <> Неопределено Тогда
Попытка
ТаблицаИзADO = ADOUtils.ADORecordsetToValueTable(РезультатRecordset);
Исключение
Если ADOUtils.ГодСмещения > 0 Тогда
ADOUtils.ГодСмещения = 0;
ТаблицаИзADO = ADOUtils.ADORecordsetToValueTable(РезультатRecordset);
СообщитьЛкс("ADOUtils смещение года было отключено из-за наличия несовместимых дат");
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
Иначе
//ОписаниеОшибки = "Не удалось подключить ВК GameWithFire.dll! Выгрузка из ADO будет выполняться программой на встроенном языке.";
//СообщитьСУчетомМодальностиЛкс(ОписаниеОшибки, МодальныйРежим, СтатусСообщения.Внимание);
КонецЕсли;
КонецЕсли;
Если ТаблицаИзADO = Неопределено Тогда
ТаблицаИзADO = ПреобразоватьРезультатADOВТаблицуЗначенийЛкс(РезультатRecordset, Типизировать1С, БинарныеВСтроку,,, ЗагружатьЭлементов, СмещениеГода);
КонецЕсли;
Возврат ТаблицаИзADO;
КонецФункции
// *** УСТАНОВКА ПАРАМЕТРОВ ЗАПРОСА ADO ***
// подбирает описание типа 1С, соответствующее типу ADO
Функция ПреобразоватьТипADO_Тип1СЛкс(Type,Size,Precision0,NumericScale0, Справочно = Ложь) Экспорт
Тип1С = Неопределено;
Если Precision0 > 0 И NumericScale0 >= 0 Тогда
Если Precision0 < NumericScale0 Тогда
// кривой вариант настроек типа ADO (может иногда возвращаться провайдерами данных)
Precision = Precision0 + NumericScale0;
Иначе
Precision = Precision0;
КонецЕсли;
UseМаксЧисло = (Precision > 32);
Иначе
// совсем кривой вариант
UseМаксЧисло = Истина;
КонецЕсли;
NumericScale = ?(NumericScale0 < 0, 0, NumericScale0);
NumericScaleM = ?(NumericScale > 10, 10, NumericScale);
Если Type = intTypeADOЛкс("adEmpty") Тогда
ИначеЕсли Type = intTypeADOЛкс("adSmallInt")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 0, ДопустимыйЗнак.Любой));
ИначеЕсли Type = intTypeADOЛкс("adInteger") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Любой));
ИначеЕсли Type = intTypeADOЛкс("adSingle") Тогда
Если UseМаксЧисло Тогда
// взвешанно-максимальный числовой тип
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(32, NumericScaleM, ДопустимыйЗнак.Любой));
Иначе
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adDouble") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Precision+NumericScale, NumericScale, ДопустимыйЗнак.Любой));
Если UseМаксЧисло Тогда
// взвешанно-максимальный числовой тип
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(32, NumericScaleM, ДопустимыйЗнак.Любой));
Иначе
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adCurrency")Тогда
Если UseМаксЧисло Тогда
// взвешанно-максимальный числовой тип
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(32, NumericScaleM, ДопустимыйЗнак.Любой));
Иначе
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adDate") Тогда
Тип1С = Новый ОписаниеТипов("Дата", , Новый КвалификаторыДаты(ЧастиДаты.Дата));
ИначеЕсли Type = intTypeADOЛкс("adBSTR") Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(Size, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adIDispatch")Тогда
ИначеЕсли Type = intTypeADOЛкс("adError") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Precision, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adBoolean") Тогда
Тип1С = Новый ОписаниеТипов("Булево");
ИначеЕсли Type = intTypeADOЛкс("adVariant") Тогда
ИначеЕсли Type = intTypeADOЛкс("adIUnknown")Тогда
ИначеЕсли Type = intTypeADOЛкс("adDecimal") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
ИначеЕсли Type = intTypeADOЛкс("adTinyInt") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(3, 0, ДопустимыйЗнак.Любой));
ИначеЕсли Type = intTypeADOЛкс("adUnsignedTinyInt")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(3, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adUnsignedSmallInt")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adUnsignedInt")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adBigInt") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(20, 0, ДопустимыйЗнак.Любой));
ИначеЕсли Type = intTypeADOЛкс("adUnsignedBigInt")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(20, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adFileTime")Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Precision, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adGUID") Тогда
Если Справочно Тогда
Тип1С = Новый ОписаниеТипов("УникальныйИдентификатор");
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adBinary") Тогда
Если Справочно Тогда
Тип1С = Новый ОписаниеТипов("Двоичныеданные");
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adChar") Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(Size, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adWChar") Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(Size, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adNumeric") Тогда
Если UseМаксЧисло Тогда
// взвешанно-максимальный числовой тип
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(32, NumericScaleM, ДопустимыйЗнак.Любой));
Иначе
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adUserDefined")Тогда
ИначеЕсли Type = intTypeADOЛкс("adDBDate") Тогда
Тип1С = Новый ОписаниеТипов("Дата", , Новый КвалификаторыДаты(ЧастиДаты.Дата));
ИначеЕсли Type = intTypeADOЛкс("adDBTime") Тогда
Тип1С = Новый ОписаниеТипов("Дата", , Новый КвалификаторыДаты(ЧастиДаты.Время));
ИначеЕсли Type = intTypeADOЛкс("adDBTimeStamp")Тогда
Тип1С = Новый ОписаниеТипов("Дата", , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя));
ИначеЕсли Type = intTypeADOЛкс("adChapter") Тогда
Тип1С = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(Precision, 0, ДопустимыйЗнак.Неотрицательный));
ИначеЕсли Type = intTypeADOЛкс("adPropVariant")Тогда
ИначеЕсли Type = intTypeADOЛкс("adVarNumeric")Тогда
Если UseМаксЧисло Тогда
// взвешанно-максимальный числовой тип
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(32, NumericScaleM, ДопустимыйЗнак.Любой));
Иначе
Тип1С = Новый ОписаниеТипов("Число",Новый КвалификаторыЧисла(Precision, NumericScale, ДопустимыйЗнак.Любой));
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adVarChar") Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(Size, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adLongVarChar")Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adVarWChar")Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(Size, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adLongVarWChar")Тогда
Тип1С = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(0, ДопустимаяДлина.Переменная));
ИначеЕсли Type = intTypeADOЛкс("adVarBinary")Тогда
Если Справочно Тогда
Тип1С = Новый ОписаниеТипов("Двоичныеданные");
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("adLongVarBinary")Тогда
Если Справочно Тогда
Тип1С = Новый ОписаниеТипов("Двоичныеданные");
КонецЕсли;
ИначеЕсли Type = intTypeADOЛкс("AdArray") Тогда
Иначе // Тип1С = Неопределено;
КонецЕсли;
Возврат Тип1С;
КонецФункции // ПреобразоватьТипADO_Тип1СЛкс()
// возвращает описание типа 1С, соответствующее типу объекта ADODB.Field
// значение Неопределено соответствует значению произвольного типа 1С
Функция FieldADO_ПолучитьТип1CЛкс(FieldADOЛкс, Справочно = Ложь) Экспорт
Попытка
Type = FieldADOЛкс.Type;
DefinedSize = FieldADOЛкс.DefinedSize;
Precision = FieldADOЛкс.Precision;
NumericScale = FieldADOЛкс.NumericScale;
Исключение
Возврат Неопределено;
КонецПопытки;
Возврат ПреобразоватьТипADO_Тип1СЛкс(Type,DefinedSize,Precision,NumericScale, Справочно);
КонецФункции
// возвращает описание типа 1С, соответствующее типу объекта ADODB.Parameter
// значение Неопределено соответствует значению произвольного типа 1С
Функция ParameterADO_ПолучитьТип1CЛкс(ParameterADOЛкс) Экспорт
Попытка
Type = ParameterADOЛкс.Type;
Size = ParameterADOЛкс.Size;
Precision = ParameterADOЛкс.Precision;
NumericScale = ParameterADOЛкс.NumericScale;
Исключение
Возврат Неопределено;
КонецПопытки;
Возврат ПреобразоватьТипADO_Тип1СЛкс(Type,Size,Precision,NumericScale);
КонецФункции
// возвращает структуру с полями объекта ADODB.Field
Функция FieldADOЛкс(стрName,стрType,чисDefinedSize,чисPrecision,чисNumericScale,Value=Неопределено) Экспорт
ПолеADO = Новый Структура("Name,Type,DefinedSize,Precision,NumericScale,Value");
ТипЧисло = Тип("Число");
Если стрName <> Неопределено Тогда
ПолеADO.Вставить("Name",СокрЛП(стрName));
КонецЕсли;
Если стрType <> Неопределено Тогда
Если ТипЗнч(стрType) = ТипЧисло Тогда
// дополнительный контроль числа на допустимое значение
ПолеADO.Вставить("Type",intTypeADOЛкс(strTypeADOЛкс(стрType)));
Иначе
ПолеADO.Вставить("Type",intTypeADOЛкс(стрType));
КонецЕсли;
КонецЕсли;
Если чисDefinedSize <> Неопределено Тогда
Если ТипЗнч(чисDefinedSize)=ТипЧисло Тогда
ПолеADO.Вставить("DefinedSize",Цел(чисDefinedSize));
Иначе
ПолеADO.Вставить("DefinedSize",0);
КонецЕсли;
КонецЕсли;
Если чисPrecision <> Неопределено Тогда
Если ТипЗнч(чисPrecision)=ТипЧисло Тогда
ПолеADO.Вставить("Precision",Цел(чисPrecision));
Иначе
ПолеADO.Вставить("Precision",0);
КонецЕсли;
КонецЕсли;
Если чисNumericScale <> Неопределено Тогда
Если ТипЗнч(чисNumericScale)=ТипЧисло Тогда
ПолеADO.Вставить("NumericScale",Цел(чисNumericScale));
Иначе
ПолеADO.Вставить("NumericScale",0);
КонецЕсли;
КонецЕсли;
Если Value <> Неопределено Тогда
ПолеADO.Вставить("Value",Value);
КонецЕсли;
Возврат ПолеADO;
КонецФункции
// возвращает структуру с полями объекта ADODB.Parameter
Функция ParameterADOЛкс(стрName,стрDirection,стрType,чисSize,чисNumericScale,чисPrecision,чисAttributes=0,Value=Неопределено) Экспорт
ПараметрADO = Новый Структура("Name,Direction,Type,Size,NumericScale,Precision,Attributes,Value");
ТипЧисло = Тип("Число");
Если стрName <> Неопределено Тогда
ПараметрADO.Вставить("Name",СокрЛП(стрName));
КонецЕсли;
Если чисAttributes <> Неопределено Тогда
Если ТипЗнч(чисAttributes)=ТипЧисло И чисAttributes > 0 Тогда
ПараметрADO.Вставить("Attributes",Цел(чисAttributes));
КонецЕсли;
КонецЕсли;
Если стрDirection <> Неопределено Тогда
Если ТипЗнч(стрDirection) = ТипЧисло Тогда
// дополнительный контроль числа на допустимое значение
ПараметрADO.Вставить("Direction",intDirectionParADOЛкс(strDirectionParADOЛкс(стрDirection)));
Иначе
ПараметрADO.Вставить("Direction",intDirectionParADOЛкс(стрDirection));
КонецЕсли;
КонецЕсли;
Если стрType <> Неопределено Тогда
Если ТипЗнч(стрType) = ТипЧисло Тогда
// дополнительный контроль числа на допустимое значение
ПараметрADO.Вставить("Type",intTypeADOЛкс(strTypeADOЛкс(стрType)));
Иначе
ПараметрADO.Вставить("Type",intTypeADOЛкс(стрType));
КонецЕсли;
КонецЕсли;
Если чисSize <> Неопределено Тогда
Если ТипЗнч(чисSize)=ТипЧисло Тогда
ПараметрADO.Вставить("Size",Цел(чисSize));
Иначе
ПараметрADO.Вставить("Size",0);
КонецЕсли;
КонецЕсли;
Если чисNumericScale <> Неопределено Тогда
Если ТипЗнч(чисNumericScale)=ТипЧисло Тогда
ПараметрADO.Вставить("NumericScale",Цел(чисNumericScale));
Иначе
ПараметрADO.Вставить("NumericScale",0);
КонецЕсли;
КонецЕсли;
Если чисPrecision <> Неопределено Тогда
Если ТипЗнч(чисPrecision)=ТипЧисло Тогда
ПараметрADO.Вставить("Precision",Цел(чисPrecision));
Иначе
ПараметрADO.Вставить("Precision",0);
КонецЕсли;
КонецЕсли;
Если Value <> Неопределено Тогда
ПараметрADO.Вставить("Value",Value);
КонецЕсли;
Возврат ПараметрADO;
КонецФункции
Функция DigitDECtoHEXЛкс(ЦыфраD)
Если ЦыфраD=0 Тогда
Возврат "0";
ИначеЕсли ЦыфраD>=1 И ЦыфраD<=9 Тогда
Возврат ""+ЦыфраD;
ИначеЕсли ЦыфраD=10 Тогда
Возврат "A";
ИначеЕсли ЦыфраD=11 Тогда
Возврат "B";
ИначеЕсли ЦыфраD=12 Тогда
Возврат "C";
ИначеЕсли ЦыфраD=13 Тогда
Возврат "D";
ИначеЕсли ЦыфраD=14 Тогда
Возврат "E";
ИначеЕсли ЦыфраD=15 Тогда
Возврат "F";
Иначе
Возврат "?";
КонецЕсли;
КонецФункции
Функция DigitHEXtoDECЛкс(ЦыфраH)
Если ЦыфраH="0" ИЛИ ЦыфраH="1" ИЛИ ЦыфраH="2" ИЛИ ЦыфраH="3" ИЛИ ЦыфраH="4" ИЛИ ЦыфраH="5" ИЛИ ЦыфраH="6" ИЛИ ЦыфраH="7" ИЛИ ЦыфраH="8" ИЛИ ЦыфраH="9" Тогда
Возврат Цел(ЦыфраH);
ИначеЕсли ЦыфраH="a" ИЛИ ЦыфраH="A" Тогда
Возврат 10;
ИначеЕсли ЦыфраH="b" ИЛИ ЦыфраH="B" Тогда
Возврат 11;
ИначеЕсли ЦыфраH="c" ИЛИ ЦыфраH="C" Тогда
Возврат 12;
ИначеЕсли ЦыфраH="d" ИЛИ ЦыфраH="D" Тогда
Возврат 13;
ИначеЕсли ЦыфраH="e" ИЛИ ЦыфраH="E" Тогда
Возврат 14;
ИначеЕсли ЦыфраH="f" ИЛИ ЦыфраH="F" Тогда
Возврат 15;
Иначе
Возврат -1;
КонецЕсли;
КонецФункции
Функция СтрокаHEXtoINTЛкс(Знач СтрокаH) Экспорт
ПрефиксH = Лев(СтрокаH,2);
Если Ложь
Или ПрефиксH="0x"
Или ПрефиксH="0X"
Или ПрефиксH="0х"
Или ПрефиксH="0Х"
Тогда
СтрокаH = Сред(СтрокаH, 3);
КонецЕсли;
Если ПустаяСтрока(СтрокаH) Тогда
Возврат 0;
КонецЕсли;
ДлинаH = СтрДлина(СтрокаH);
ЧислоD = 0;
Для Позиция = 1 По ДлинаH Цикл
ЦыфраH = Сред(СтрокаH, Позиция, 1);
ЦифраD = DigitHEXtoDECЛкс(ЦыфраH);
Если ЦифраD < 0 Тогда
Возврат -1; // нарушение формата 16-тиричного числа
КонецЕсли;
ЧислоD = 16*ЧислоD + ЦифраD;
КонецЦикла;
Возврат ЧислоD;
КонецФункции
// преобразует 16-тиричную строку в COMSafeArray
Функция СтрокаHEXtoCOMSafeArrayЛкс(Знач СтрокаH) Экспорт
ПрефиксH = Лев(СтрокаH,2);
Если Ложь
Или ПрефиксH="0x"
ИЛИ ПрефиксH="0X"
ИЛИ ПрефиксH="0х"
ИЛИ ПрефиксH="0Х"
Тогда
СтрокаH=Сред(СтрокаH,3);
КонецЕсли;
Байты =СтрДлина(СтрокаH);
Байты = 2*Окр(Байты/2,0,1);
ArrayДанные = Новый Массив;
Поза=1;
Для о=1 По Байты Цикл
ДваБайт = Сред(СтрокаH,Поза,2);
ЗначInt = СтрокаHEXtoINTЛкс(ДваБайт);
Если ЗначInt<0 Тогда
Возврат Неопределено;
КонецЕсли;
ArrayДанные.Добавить(ЗначInt);
Поза=Поза+2;
КонецЦикла;
Array = Новый COMSafeArray(ArrayДанные,"VT_UI1",Байты/2);
Возврат Array;
КонецФункции
// преобразует объект УникальныйИдентификатор в COMSafeArray
Функция GUIDToCOMSafeArrayЛкс(GUID) Экспорт
ГУИД = СтрЗаменить(GUID,"-",Символы.ПС);
Если СтрЧислоСтрок(ГУИД)<>5 Тогда
// нарушена каноническая структура строки ГУИД: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12)
Возврат Неопределено;
КонецЕсли;
// Соответствие байтов в поле BINARY(16) с частями ГУИД: 4,5,3,2,1 - проверено для 1с-8.1.14
СтрокаH = СтрПолучитьСтроку(ГУИД,4) + СтрПолучитьСтроку(ГУИД,5)+ СтрПолучитьСтроку(ГУИД,3)+ СтрПолучитьСтроку(ГУИД,2)+ СтрПолучитьСтроку(ГУИД,1);
Возврат СтрокаHEXtoCOMSafeArrayЛкс(СтрокаH);
КонецФункции
// преобразует значение уникального идентификатора ссылки в COMSafeArray
Функция СсылкаToCOMSafeArrayЛкс(Ссылка) Экспорт
Попытка
ГУИД = СокрЛП(Ссылка.УникальныйИдентификатор());
Исключение
// переданное значение не ссылка
Возврат Неопределено;
КонецПопытки;
Возврат GUIDToCOMSafeArrayЛкс(ГУИД);
КонецФункции
// преобразование значения COMSafeArray, содержащие 2-байтовые целые в шестнадцатиричную строку
Функция BinaryCOMSafeArrayToHEXЛкс(Array) Экспорт
СтрHEX="";
Если ТипЗнч(Array)<>Тип("COMSafeArray") Тогда
Возврат "?COMSafeArray?";
КонецЕсли;
Возврат МассивЧиселВHEXЛкс(Array.Выгрузить());
КонецФункции
// .
//
// Параметры:
// Массив - Массив, COMSafeArray - содержащий 2-х байтовые целые
//
// Возвращаемое значение:
// Строка - шестнадцатиричные символы
//
Функция МассивЧиселВHEXЛкс(Знач Массив) Экспорт
Если ТипЗнч(Массив) = Тип("COMSafeArray") Тогда
Массив = Массив.Выгрузить();
КонецЕсли;
Результат = "";
МаксЭлементов = 1000;
Счетчик = 0;
Для каждого Слово Из Массив Цикл
Если ТипЗнч(Слово)=Тип("Число") Тогда
Слово=Цел(Слово);
Если (Слово<0)ИЛИ(Слово>255) Тогда
Результат=Результат+"??";
Иначе
Байт1=Слово%16;
Байт2=Цел(Слово/16);
Результат=Результат+DigitDECtoHEXЛкс(Байт2)+DigitDECtoHEXЛкс(Байт1);
КонецЕсли;
Иначе
Результат=Результат+"??";
КонецЕсли;
Счетчик = Счетчик + 1;
Если МаксЭлементов = Счетчик Тогда
Результат = Результат + "...";
Прервать;
КонецЕсли;
КонецЦикла;
Возврат "0x"+Результат;
КонецФункции
// возвращает свойства параметра ADO из переданной структуры
// с автоматическим подбором значений свойств по значению 1С (если свойство неопределено)
Процедура ParameterADOСвойстваЛкс(стТипADO,Значение1С,ЗначениеADO,Direction,Type,Precision,NumericScale,Size,Attributes,ADOUtils=Неопределено)
Перем ТипЗначения1С;
Если ТипЗнч(стТипADO)=Тип("Структура") Тогда
стТипADO.Свойство("Direction",Direction);
стТипADO.Свойство("Type",Type);
стТипADO.Свойство("Precision",Precision);
стТипADO.Свойство("NumericScale",NumericScale);
стТипADO.Свойство("Size",Size);
стТипADO.Свойство("Attributes",Attributes);
стТипADO.Свойство("ТипЗначения1С",ТипЗначения1С);
КонецЕсли;
Если Истина
И ТипЗнч(ТипЗначения1С) = Тип("ОписаниеТипов")
И ТипЗначения1С.Типы().Количество() > 0
И НЕ ТипЗначения1С.СодержитТип(ТипЗнч(Значение1С))
Тогда
// приведем значение 1С к указанному типу (актуально для значений Null, возвращаемых запросами 1С)
Значение1С = ТипЗначения1С.ПривестиЗначение(Значение1С);
КонецЕсли;
Если Direction=Неопределено Тогда
Direction=1; // 1 - входящий(Default) ... или 0 - неизвестно ???
КонецЕсли;
Тип1С = ТипЗнч(Значение1С);
Попытка
Ссылка = Значение1С.Ссылка;
Исключение
Ссылка = Неопределено;
Попытка
// перечисления стоят особняком среди "ссылочных" типов
МетаДата = Значение1С.Метаданные();
Если Метаданные.Перечисления.Содержит(МетаДата) Тогда
Ссылка = Значение1С;
КонецЕсли;
Исключение
КонецПопытки;
КонецПопытки;
Если Type=Неопределено Тогда
// попытаемся подобрать по типу 1С
Если Тип1С=Тип("Число") Тогда
//Type = 4; // adSingle
//Type = 5; // adDouble
//Type = 14; // adDecimal
//Type = 131; // adNumeric
//Type = 139; // adVarNumeric
Если Цел(Значение1С)=Значение1С Тогда
Если ?(Значение1С<0,-1,1)*Значение1С <= 2147483647 Тогда // 2^32-1
Type = intTypeADOЛкс("adInteger"); // 3
Иначе
Type = intTypeADOЛкс("adBigInt"); // 20
КонецЕсли;
Иначе
Type = 14; // adDecimal
КонецЕсли;
ИначеЕсли Тип1С=Тип("Строка") Тогда
//Type = 129; // adChar
//Type = 130; // adWChar
//Type = 200; // adVarChar
//Type = 201; // adLongVarChar
//Type = 202; // adVarWChar
//Type = 203; // adLongVarWChar
Если СтрДлина(Значение1С)<=4000 Тогда
Type = intTypeADOЛкс("adVarChar"); // 200
Иначе
Type = intTypeADOЛкс("adLongVarChar"); // 201
КонецЕсли;
ИначеЕсли Тип1С=Тип("Дата") Тогда
//Type = 134; // adDBTime
Если НачалоДня(Значение1С) = Значение1С Тогда
Type = intTypeADOЛкс("adDBDate"); // 133
Иначе
Type = intTypeADOЛкс("adDBTimeStamp"); // 135
КонецЕсли;
ИначеЕсли Тип1С=Тип("Булево") Тогда
Type = intTypeADOЛкс("adBoolean"); // 11
ИначеЕсли Тип1С=Тип("УникальныйИдентификатор") Тогда
Type = intTypeADOЛкс("adBinary"); // 128
Size = 16;
Иначе
Если Ссылка <> Неопределено Тогда
// ссылочный тип - преобразуем в COMSafeArray
Type = intTypeADOЛкс("adBinary"); // 128
Size = 16;
Иначе
Type = intTypeADOЛкс("adEmpty"); // 0? (Default)
КонецЕсли;
КонецЕсли;
КонецЕсли;
// ADOUtils.V8DateToDBDate( Дата ) // с учетом YearOffset
// ADOUtils.BooleanParameter( Значение ) // COMSafeArray(1)
// ADOUtils.TypeParameter( Значение ) // COMSafeArray(1) *_TYPE
// ADOUtils.TableNumberParameter( Значение ) // COMSafeArray(4) *_RTRef
// ADOUtils.DataVersionParameter( Значение ) // COMSafeArray(8) _Version
// ADOUtils.RRefParameter( Значение ) // COMSafeArray(16) *IDRRef
Если Ложь
Или Type = intTypeADOЛкс("adBinary") // 128
Или Type = intTypeADOЛкс("adVarBinary")
Тогда // 204
//Если ADOUtils = Неопределено Тогда
// ADOUtils = ПолучитьADOUtils();
// Если ADOUtils = Неопределено Тогда
// ADOUtils = Null; // для избежания повторных инициализаций
// КонецЕсли;
//КонецЕсли;
Если Ссылка <> Неопределено Тогда
// ссылочный тип - преобразуем в COMSafeArray(16)
ЗначениеADO = СсылкаToCOMSafeArrayЛкс(Ссылка);
//Если ADOUtils = Неопределено ИЛИ ADOUtils = Null Тогда
// ЗначениеADO = СсылкаToCOMSafeArrayЛкс(Ссылка);
//Иначе
// ЗначениеADO = ADOUtils.RRefParameter(Ссылка);
//КонецЕсли;
ИначеЕсли Тип1С=Тип("УникальныйИдентификатор") Тогда
// ГУИД - преобразуем в COMSafeArray(16)
ЗначениеADO = GUIDToCOMSafeArrayЛкс(Значение1С);
ИначеЕсли Тип1С=Тип("Булево") Тогда
// Булево - преобразуем в COMSafeArray(1)
ЗначениеADO = СтрокаHEXtoCOMSafeArrayЛкс(?(Значение1С,"0x01","0x00"));
//Если ADOUtils = Неопределено ИЛИ ADOUtils = Null Тогда
// ЗначениеADO = СтрокаHEXtoCOMSafeArrayЛкс(?(Значение1С,"0x01","0x00"));
//Иначе
// ЗначениеADO = ADOUtils.BooleanParameter(Значение1С);
//КонецЕсли;
Иначе
КонецЕсли;
КонецЕсли;
Если Precision=Неопределено Тогда
Если Ложь
Или Type = intTypeADOЛкс("adDecimal") // 14
ИЛИ Type = intTypeADOЛкс("adNumeric") // 131
ИЛИ Type = intTypeADOЛкс("adVarNumeric") // 139
Тогда
Precision = СтрДлина(СтрЗаменить(Строка(Значение1С)," ",""));
КонецЕсли;
КонецЕсли;
Если NumericScale=Неопределено Тогда
Если Ложь
Или Type = intTypeADOЛкс("adDecimal") // 14
ИЛИ Type = intTypeADOЛкс("adNumeric") // 131
ИЛИ Type = intTypeADOЛкс("adVarNumeric") // 139
Тогда
NumericScale = СтрДлина(Строка(Значение1С-Цел(Значение1С)));
КонецЕсли;
КонецЕсли;
Если Size=Неопределено Тогда
Если Ложь
Или Type = intTypeADOЛкс("adChar") // 129
ИЛИ Type = intTypeADOЛкс("adWChar") // 130
ИЛИ Type = intTypeADOЛкс("adVarChar") // 200
//ИЛИ Type = intTypeADOЛкс("adLongVarChar") // 201
ИЛИ Type = intTypeADOЛкс("adVarWChar") // 202
//ИЛИ Type = intTypeADOЛкс("adLongVarWChar") // 203
Тогда
Size = СтрДлина(Значение1С);
Size = Макс(1, Size); // Иначе потом при Append() возникает ошибка (ADODB.Parameters): Неправильно определен объект Parameter. Предоставлены несогласованные или неполные сведения.
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// создает массив объектов ADODB.Parameter по списку параметров ADO и по списку типов ADO
Функция ParametersArrayПолучитьЛкс(стПараметры,стПарТипADO, ADOUtils = Неопределено) Экспорт
ParametersArray = Новый Массив;
ТипаМассив = Тип("Массив");
ТипаСоответствие = Тип("Соответствие");
cтПараметрыТип = ТипЗнч(стПараметры);
cтПарТипADOТип = ТипЗнч(стПарТипADO);
Если стПараметры = Неопределено Тогда
Возврат ParametersArray;
ИначеЕсли cтПараметрыТип = ТипаМассив ИЛИ cтПараметрыТип = ТипаСоответствие Тогда
Если стПарТипADO <> Неопределено И cтПарТипADOТип <> cтПараметрыТип Тогда
ВызватьИсключение(
"Тип значения списка типов параметров ADO ('"+cтПарТипADOТип+"') не равен
|типу значения списка параметров запроса ('"+cтПараметрыТип+"') !");
КонецЕсли;
Иначе
ВызватьИсключение(
"Не предусмотренный тип значения списка параметров запроса ('"+cтПараметрыТип+"') !");
КонецЕсли;
ОбъектЗапрос = Новый COMОбъект("ADODB.Command");
Индекс = 0;
Для каждого Параметр Из стПараметры Цикл
Если cтПараметрыТип = ТипаМассив Тогда
ПараметрИмя = Неопределено;
Значение1С = Параметр;
ИначеЕсли cтПараметрыТип = ТипаСоответствие Тогда
ПараметрИмя = СокрЛП(Параметр.Ключ);
Значение1С = Параметр.Значение;
Иначе
Продолжить;
КонецЕсли;
Индекс = Индекс + 1;
стТипADO=Неопределено;
Если cтПарТипADOТип=ТипаМассив Тогда
Если Индекс<=стПарТипADO.Количество()-1 Тогда
стТипADO = стПарТипADO.Получить(Индекс);
КонецЕсли;
ИначеЕсли cтПарТипADOТип = ТипаСоответствие Тогда
стТипADO = стПарТипADO.Получить(Параметр.Ключ);
КонецЕсли;
ЗначениеADO = Неопределено;
Attributes = Неопределено;
Direction = Неопределено;
Type = Неопределено;
Precision = Неопределено;
NumericScale = Неопределено;
Size = Неопределено; // прочитаем свойства параметра ADO по полученной структуре типа и значению 1С
ParameterADOСвойстваЛкс(стТипADO,Значение1С,ЗначениеADO,Direction,Type,Precision,NumericScale,Size,Attributes,ADOUtils);
// создадим параметр ADO и заполним его свойства
Parameter = ОбъектЗапрос.CreateParameter();
Если НЕ ПустаяСтрока(Type) Тогда
Parameter.Type=Type;
КонецЕсли;
Если НЕ ПустаяСтрока(Direction) Тогда
Parameter.Direction=Direction;
КонецЕсли;
Если НЕ ПустаяСтрока(Size) Тогда
Parameter.Size=Size;
КонецЕсли;
Если НЕ ПустаяСтрока(Attributes) Тогда
Parameter.Attributes=Attributes;
КонецЕсли;
Если НЕ ПустаяСтрока(ПараметрИмя) Тогда
Parameter.Name = ПараметрИмя;
КонецЕсли;
Если ЗначениеADO = Неопределено Тогда
Parameter.Value=Значение1С; // преобразование не явное
Иначе
Parameter.Value=ЗначениеADO;
КонецЕсли;
// добавим в массив
ParametersArray.Добавить(Parameter);
КонецЦикла;
Возврат ParametersArray;
КонецФункции
// добавляет и устанавливает объект ADODB.Parameter в коллекцию параметров
// если не заданы свойства параметра ADO, делается попытка их подбора по типу значения 1С
Функция ADODBCommand_УстановитьПараметрПо1СЛкс(ОбъектЗапрос, Инициализация, Индекс, Name, стТипADO, Значение1С, ADOUtils, ЕррорИнфо) Экспорт
ЗначениеADO=Неопределено;
Attributes=Неопределено;
Direction=Неопределено;
Type=Неопределено;
Precision=Неопределено;
NumericScale=Неопределено;
Size=Неопределено; // прочитаем свойства параметра ADO из переданной структуры по значению 1С
ParameterADOСвойстваЛкс(стТипADO, Значение1С, ЗначениеADO, Direction, Type, Precision, NumericScale, Size, Attributes, ADOUtils);
ЕррорИнфо="";
Попытка
Если ОбъектЗапрос.Prepared = Ложь ИЛИ Инициализация <> Ложь Тогда
// инициализация параметров запроса
Добавить = Ложь;
Если Name = Неопределено Тогда
// по переданному индексу параметра
Parameter = ОбъектЗапрос.CreateParameter();
Добавить = Истина; // создаем без имени
Иначе
// по переданному имени параметра
Попытка
// если уже есть параметр с именем - используем его
Parameter = ОбъектЗапрос.Parameters.Item(Name);
Исключение
Parameter = Неопределено;
КонецПопытки;
Если Parameter = Неопределено Тогда
// если нет - создаем с указанным именем
Parameter = ОбъектЗапрос.CreateParameter();
Parameter.Name = Name;
Добавить = Истина;
КонецЕсли;
КонецЕсли;
Если НЕ ПустаяСтрока(Type) Тогда
Parameter.Type=Type;
КонецЕсли;
Если НЕ ПустаяСтрока(Direction) Тогда
Parameter.Direction=Direction;
КонецЕсли;
Если НЕ ПустаяСтрока(Size) Тогда
Parameter.Size=Size;
КонецЕсли;
Если НЕ ПустаяСтрока(Attributes) И Attributes <> 0 Тогда
Parameter.Attributes=Attributes;
КонецЕсли;
Если Добавить = Истина Тогда
ОбъектЗапрос.Parameters.Append(Parameter);
КонецЕсли;
Иначе
// установка параметра предварительно подготовленного параметризованного запроса
Если Name = Неопределено Тогда
// по переданному индексу параметра
Parameter = ОбъектЗапрос.Parameters.Item(Индекс);
Иначе
// по переданному имени параметра
Parameter = ОбъектЗапрос.Parameters.Item(Name);
КонецЕсли;
КонецЕсли;
Если ЗначениеADO = Неопределено Тогда
Parameter.Value=Значение1С; // преобразование не явное
Иначе
Parameter.Value=ЗначениеADO;
КонецЕсли;
Исключение
ЕррорИнфо=ОписаниеОшибки();
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
// ^^^ УСТАНОВКА ПАРАМЕТРОВ ЗАПРОСА ADO ^^^
// *** ПЕРЕЧИСЛЕНИЯ ADO ***
// возвращает строковое представление типа параметра ADO(свойства Direction) по его числовому значению
Функция strDirectionParADOЛкс(intTypeADOЛкс) Экспорт
intType = Цел(intTypeADOЛкс);
Если intType = 0 Тогда Возврат "adParamUnknown"; // Direction unknown
ИначеЕсли intType = 1 Тогда Возврат "adParamInput"; // Input parameter (Default)
ИначеЕсли intType = 2 Тогда Возврат "adParamOutput"; // Output parameter
ИначеЕсли intType = 3 Тогда Возврат "adParamInputOutput"; // Input and output parameter
ИначеЕсли intType = 4 Тогда Возврат "adParamReturnValue"; // Return value
Иначе Возврат "adParamInput"; // как 1
КонецЕсли;
КонецФункции
// возвращает числовое значения типа параметра ADO(свойства Direction) по его числовому представлению
Функция intDirectionParADOЛкс(strTypeADOЛкс) Экспорт
strType = НРег(strTypeADOЛкс);
Если strType = Нрег("adParamUnknown") Тогда Возврат 0; // Direction unknown
ИначеЕсли strType = Нрег("adParamInput") Тогда Возврат 1; // Input parameter (Default)
ИначеЕсли strType = Нрег("adParamOutput") Тогда Возврат 2; // Output parameter
ИначеЕсли strType = Нрег("adParamInputOutput") Тогда Возврат 3; // Input and output parameter
ИначеЕсли strType = Нрег("adParamReturnValue") Тогда Возврат 4; // Return value
Иначе Возврат 1; // adParamInput
КонецЕсли;
КонецФункции
// возвращает строковое представление типа значения ADO по его числовому значению
Функция strTypeADOЛкс(intTypeADOЛкс) Экспорт
intType = Цел(intTypeADOЛкс);
Если intType = 0 Тогда Возврат "adEmpty"; // no value
ИначеЕсли intType = 2 Тогда Возврат "adSmallInt"; // 2-byte signed integer
ИначеЕсли intType = 3 Тогда Возврат "adInteger"; // 4-byte signed integer
ИначеЕсли intType = 4 Тогда Возврат "adSingle"; // single-precision floating-point value
ИначеЕсли intType = 5 Тогда Возврат "adDouble"; // double-precision floating-point value
ИначеЕсли intType = 6 Тогда Возврат "adCurrency"; // currency value
ИначеЕсли intType = 7 Тогда Возврат "adDate"; // number of days since December 30, 1899 + the fraction of a day
ИначеЕсли intType = 8 Тогда Возврат "adBSTR"; // null-terminated character string
ИначеЕсли intType = 9 Тогда Возврат "adIDispatch"; // pointer to an IDispatch interface on a COM object(currently not supported by ADO)
ИначеЕсли intType = 10 Тогда Возврат "adError"; // 32-bit error code
ИначеЕсли intType = 11 Тогда Возврат "adBoolean"; // boolean value
ИначеЕсли intType = 12 Тогда Возврат "adVariant"; // automation Variant(currently not supported by ADO)
ИначеЕсли intType = 13 Тогда Возврат "adIUnknown"; // pointer to an IUnknown interface on a COM object(currently not supported by ADO)
ИначеЕсли intType = 14 Тогда Возврат "adDecimal"; // exact numeric value with a fixed precision and scale
ИначеЕсли intType = 16 Тогда Возврат "adTinyInt"; // 1-byte signed integer
ИначеЕсли intType = 17 Тогда Возврат "adUnsignedTinyInt"; // 1-byte unsigned integer
ИначеЕсли intType = 18 Тогда Возврат "adUnsignedSmallInt"; // 2-byte unsigned integer
ИначеЕсли intType = 19 Тогда Возврат "adUnsignedInt"; // 4-byte unsigned integer
ИначеЕсли intType = 20 Тогда Возврат "adBigInt"; // 8-byte signed integer
ИначеЕсли intType = 21 Тогда Возврат "adUnsignedBigInt"; // 8-byte unsigned integer
ИначеЕсли intType = 64 Тогда Возврат "adFileTime"; // number of 100-nanosecond intervals since January 1,1601
ИначеЕсли intType = 72 Тогда Возврат "adGUID"; // globally unique identifier (GUID)
ИначеЕсли intType = 128 Тогда Возврат "adBinary"; // binary value
ИначеЕсли intType = 129 Тогда Возврат "adChar"; // string value
ИначеЕсли intType = 130 Тогда Возврат "adWChar"; // null-terminated Unicode character string
ИначеЕсли intType = 131 Тогда Возврат "adNumeric"; // exact numeric value with a fixed precision and scale
ИначеЕсли intType = 132 Тогда Возврат "adUserDefined"; // user-defined variable
ИначеЕсли intType = 133 Тогда Возврат "adDBDate"; // date value (yyyymmdd)
ИначеЕсли intType = 134 Тогда Возврат "adDBTime"; // time value (hhmmss)
ИначеЕсли intType = 135 Тогда Возврат "adDBTimeStamp"; // date/time stamp (yyyymmddhhmmss plus a fraction in billionths)
ИначеЕсли intType = 136 Тогда Возврат "adChapter"; // 4-byte chapter value that identifies rows in a child rowset
ИначеЕсли intType = 138 Тогда Возврат "adPropVariant"; // automation PROPVARIANT
ИначеЕсли intType = 139 Тогда Возврат "adVarNumeric"; // numeric value(Parameter object only)
ИначеЕсли intType = 200 Тогда Возврат "adVarChar"; // string value (Parameter object only)
ИначеЕсли intType = 201 Тогда Возврат "adLongVarChar"; // long string value
ИначеЕсли intType = 202 Тогда Возврат "adVarWChar"; // null-terminated Unicode character string
ИначеЕсли intType = 203 Тогда Возврат "adLongVarWChar"; // long null-terminated Unicode string value
ИначеЕсли intType = 204 Тогда Возврат "adVarBinary"; // binary value (Parameter object only)
ИначеЕсли intType = 205 Тогда Возврат "adLongVarBinary"; // long binary value
ИначеЕсли intType = 8192 Тогда Возврат "AdArray"; // 0x2000, flag value combined with another data type constant, indicates an array of that other data type
Иначе Возврат "adEmpty"; // как 0
КонецЕсли;
КонецФункции
// возвращает числовое значение типа значения ADO по его строковому представлению
Функция intTypeADOЛкс(strTypeADOЛкс) Экспорт
strType = НРег(strTypeADOЛкс);
Если strType = НРег("adEmpty") Тогда Возврат 0; // no value
ИначеЕсли strType = НРег("adSmallInt") Тогда Возврат 2; // 2-byte signed integer
ИначеЕсли strType = НРег("adInteger") Тогда Возврат 3; // 4-byte signed integer
ИначеЕсли strType = НРег("adSingle") Тогда Возврат 4; // single-precision floating-point value
ИначеЕсли strType = НРег("adDouble") Тогда Возврат 5; // double-precision floating-point value
ИначеЕсли strType = НРег("adCurrency") Тогда Возврат 6; // currency value
ИначеЕсли strType = НРег("adDate") Тогда Возврат 7; // number of days since December 30, 1899 + the fraction of a day
ИначеЕсли strType = НРег("adBSTR") Тогда Возврат 8; // null-terminated character string
ИначеЕсли strType = НРег("adIDispatch") Тогда Возврат 9; // pointer to an IDispatch interface on a COM object(currently not supported by ADO)
ИначеЕсли strType = НРег("adError") Тогда Возврат 10; // 32-bit error code
ИначеЕсли strType = НРег("adBoolean") Тогда Возврат 11; // boolean value
ИначеЕсли strType = НРег("adVariant") Тогда Возврат 12; // automation Variant(currently not supported by ADO)
ИначеЕсли strType = НРег("adIUnknown") Тогда Возврат 13; // pointer to an IUnknown interface on a COM object(currently not supported by ADO)
ИначеЕсли strType = НРег("adDecimal") Тогда Возврат 14; // exact numeric value with a fixed precision and scale
ИначеЕсли strType = НРег("adTinyInt") Тогда Возврат 16; // 1-byte signed integer
ИначеЕсли strType = НРег("adUnsignedTinyInt") Тогда Возврат 17; // 1-byte unsigned integer
ИначеЕсли strType = НРег("adUnsignedSmallInt") Тогда Возврат 18;// 2-byte unsigned integer
ИначеЕсли strType = НРег("adUnsignedInt") Тогда Возврат 19; // 4-byte unsigned integer
ИначеЕсли strType = НРег("adBigInt") Тогда Возврат 20; // 8-byte signed integer
ИначеЕсли strType = НРег("adUnsignedBigInt") Тогда Возврат 21; // 8-byte unsigned integer
ИначеЕсли strType = НРег("adFileTime") Тогда Возврат 64; // number of 100-nanosecond intervals since January 1,1601
ИначеЕсли strType = НРег("adGUID") Тогда Возврат 72; // globally unique identifier (GUID)
ИначеЕсли strType = НРег("adBinary") Тогда Возврат 128; // binary value
ИначеЕсли strType = НРег("adChar") Тогда Возврат 129; // string value
ИначеЕсли strType = НРег("adWChar") Тогда Возврат 130; // null-terminated Unicode character string
ИначеЕсли strType = НРег("adNumeric") Тогда Возврат 131; // exact numeric value with a fixed precision and scale
ИначеЕсли strType = НРег("adUserDefined") Тогда Возврат 132; // user-defined variable
ИначеЕсли strType = НРег("adDBDate") Тогда Возврат 133; // date value (yyyymmdd)
ИначеЕсли strType = НРег("adDBTime") Тогда Возврат 134; // time value (hhmmss)
ИначеЕсли strType = НРег("adDBTimeStamp") Тогда Возврат 135; // date/time stamp (yyyymmddhhmmss plus a fraction in billionths)
ИначеЕсли strType = НРег("adChapter") Тогда Возврат 136; // 4-byte chapter value that identifies rows in a child rowset
ИначеЕсли strType = НРег("adPropVariant") Тогда Возврат 138; // automation PROPVARIANT
ИначеЕсли strType = НРег("adVarNumeric") Тогда Возврат 139; // numeric value(Parameter object only)
ИначеЕсли strType = НРег("adVarChar") Тогда Возврат 200; // string value (Parameter object only)
ИначеЕсли strType = НРег("adLongVarChar") Тогда Возврат 201; // long string value
ИначеЕсли strType = НРег("adVarWChar") Тогда Возврат 202; // null-terminated Unicode character string
ИначеЕсли strType = НРег("adLongVarWChar") Тогда Возврат 203; // long null-terminated Unicode string value
ИначеЕсли strType = НРег("adVarBinary") Тогда Возврат 204; // binary value (Parameter object only)
ИначеЕсли strType = НРег("adLongVarBinary") Тогда Возврат 205; // long binary value
ИначеЕсли strType = НРег("AdArray") Тогда Возврат 8192; // 0x2000, flag value combined with another data type constant, indicates an array of that other data type
Иначе Возврат 0; // adEmpty
КонецЕсли;
КонецФункции
// возвращает числовое значение типа курсора по его строковому представлению
Функция strCursorTypeЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = -1 Тогда Возврат "adOpenUnspecified"; // Does not specify the type of cursor
ИначеЕсли intV = 0 Тогда Возврат "adOpenForwardOnly"; // Default. Uses a forward-only cursor. Like a static cursor, except... (Default)
ИначеЕсли intV = 1 Тогда Возврат "adOpenKeyset"; // Uses a keyset cursor. Like a dynamic cursor, except...
ИначеЕсли intV = 2 Тогда Возврат "adOpenDynamic"; // Uses a dynamic cursor
ИначеЕсли intV = 3 Тогда Возврат "adOpenStatic"; // Uses a static cursor
Иначе Возврат "adOpenForwardOnly"; // как 0
КонецЕсли;
КонецФункции
// возвращает строковое представление типа курсора по его числовому значению
Функция intCursorTypeЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adOpenUnspecified") Тогда Возврат -1; // Does not specify the type of cursor
ИначеЕсли strV = Нрег("adOpenForwardOnly") Тогда Возврат 0; // Default. Uses a forward-only cursor. Like a static cursor, except... (Default
ИначеЕсли strV = Нрег("adOpenKeyset") Тогда Возврат 1; // Uses a keyset cursor. Like a dynamic cursor, except...
ИначеЕсли strV = Нрег("adOpenDynamic") Тогда Возврат 2; // Uses a dynamic cursor
ИначеЕсли strV = Нрег("adOpenStatic") Тогда Возврат 3; // Uses a static cursor
Иначе Возврат 0; // adOpenForwardOnly
КонецЕсли;
КонецФункции
// возвращает числовое значение местоположения курсора по его строковому представлению
Функция strCursorLocationЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = 1 Тогда Возврат "adUseNone"; // Does not use cursor services
ИначеЕсли intV = 2 Тогда Возврат "adUseServer"; // Uses a server-side cursor (Default)
ИначеЕсли intV = 3 Тогда Возврат "adParamOutput"; // Uses a client-side cursor supplied by a local cursor library
Иначе Возврат "adUseServer"; // как 2
КонецЕсли;
КонецФункции
// возвращает строковое представление местоположения курсора по его числовому значению
Функция intCursorLocationЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adUseNone") Тогда Возврат 1; // Does not use cursor services
ИначеЕсли strV = Нрег("adUseServer") Тогда Возврат 2; // Uses a server-side cursor (Default)
ИначеЕсли strV = Нрег("adParamOutput") Тогда Возврат 3; // Uses a client-side cursor supplied by a local cursor library
Иначе Возврат 2; // adUseServer
КонецЕсли;
КонецФункции
// возвращает числовое значение типа блокировки данных по его строковому представлению
Функция strLockTypeЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = -1 Тогда Возврат "adLockUnspecified"; // Unspecified type of lock. Clones inherits lock type from the original Recordset
ИначеЕсли intV = 1 Тогда Возврат "adLockReadOnly"; // Read-only records
ИначеЕсли intV = 2 Тогда Возврат "adLockPessimistic"; // Pessimistic locking, record by record. The provider lock records immediately after editing
ИначеЕсли intV = 3 Тогда Возврат "adLockOptimistic"; // Optimistic locking, record by record. The provider lock records only when calling update
ИначеЕсли intV = 4 Тогда Возврат "adLockBatchOptimistic"; // Optimistic batch updates. Required for batch update mode
Иначе Возврат "adLockUnspecified"; // как -1
КонецЕсли;
КонецФункции
// возвращает строковое представление типа блокировки данных по его числовому значению
Функция intLockTypeЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adLockUnspecified") Тогда Возврат -1; // Unspecified type of lock
ИначеЕсли strV = Нрег("adLockReadOnly") Тогда Возврат 1; // Read-only records
ИначеЕсли strV = Нрег("adLockPessimistic") Тогда Возврат 2; // Pessimistic locking, record by record. The provider lock records immediately after editing
ИначеЕсли strV = Нрег("adLockOptimistic") Тогда Возврат 3; // Optimistic locking, record by record. The provider lock records only when calling update
ИначеЕсли strV = Нрег("adLockBatchOptimistic") Тогда Возврат 4; // Optimistic batch updates. Required for batch update mode
Иначе Возврат -1; // adLockUnspecified
КонецЕсли;
КонецФункции
// возвращает числовое значение опции MarshalOptions по его строковому представлению
Функция strMarshalOptionsЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = 0 Тогда Возврат "adMarshalAll"; // Returns all rows (Default)
ИначеЕсли intV = 1 Тогда Возврат "adMarshalModifiedOnly"; // Returns only modified rows
Иначе Возврат "adMarshalAll"; // как 0
КонецЕсли;
КонецФункции
// возвращает строковое представление опции MarshalOptions по его числовому значению
Функция intMarshalOptionsЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adMarshalAll") Тогда Возврат 0; // Returns all rows (Default)
ИначеЕсли strV = Нрег("adMarshalModifiedOnly") Тогда Возврат 1; // Returns only modified rows
Иначе Возврат 0; // adMarshalAll
КонецЕсли;
КонецФункции
// возвращает строковое представление типа команды ADO по его числовому значению
Функция strCommandTypeADOЛкс(intTypeADOЛкс) Экспорт
Если ТипЗнч(intTypeADOЛкс) = Тип("Число") Тогда
intType = Цел(intTypeADOЛкс);
Иначе
intType = 0;
КонецЕсли;
Если intType = -1 Тогда Возврат "adCmdUnspecified"; // Unspecified type of command
ИначеЕсли intType = 1 Тогда Возврат "adCmdText"; // строка оператора T-SQL
ИначеЕсли intType = 2 Тогда Возврат "adCmdTable"; // имя таблицы для выборки строк
ИначеЕсли intType = 4 Тогда Возврат "adCmdStoredProc"; // имя хранимой процедуры
ИначеЕсли intType = 8 Тогда Возврат "adCmdUnknown"; // неизвестно, проверять провайдером (Default)
ИначеЕсли intType = 256 Тогда Возврат "adCmdFile"; // имя файла of a persistently stored Recordset (with Recordset.Open or Requery only)
ИначеЕсли intType = 512 Тогда Возврат "adCmdTableDirect"; // имя таблицы whose columns are all returned (with Recordset.Open or Requery only)
Иначе Возврат "adCmdUnknown"; // как 8
КонецЕсли;
КонецФункции
// возвращает числовое значение типа команды ADO по его строковому представлению
Функция intCommandTypeADOЛкс(strTypeADOЛкс) Экспорт
strType = Нрег(strTypeADOЛкс);
Если strType = Нрег("adCmdUnspecified") Тогда Возврат -1; // Unspecified type of command
ИначеЕсли strType = Нрег("adCmdText") Тогда Возврат 1; // строка оператора T-SQL
ИначеЕсли strType = Нрег("adCmdTable") Тогда Возврат 2; // имя таблицы для выборки строк
ИначеЕсли strType = Нрег("adCmdStoredProc") Тогда Возврат 4; // имя хранимой процедуры
ИначеЕсли strType = Нрег("adCmdUnknown") Тогда Возврат 8; // неизвестно, проверять провайдером (Default)
ИначеЕсли strType = Нрег("adCmdFile") Тогда Возврат 256; // имя файла of a persistently stored Recordset (with Recordset.Open or Requery only)
ИначеЕсли strType = Нрег("adCmdTableDirect") Тогда Возврат 512; // имя таблицы whose columns are all returned (with Recordset.Open or Requery only)
Иначе Возврат 8; // adCmdUnknown
КонецЕсли;
КонецФункции
// возвращает строковое представление типа команды ADO по его числовому значению
Функция strExecuteOptionЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = -1 Тогда Возврат "adOptionUnspecified"; // Unspecified command
ИначеЕсли intV = 16 Тогда Возврат "adAsyncExecute"; // The command should execute asynchronously
ИначеЕсли intV = 32 Тогда Возврат "adAsyncFetch"; // The remaining rows after specified in the CacheSize should be retrieved asynchronously
ИначеЕсли intV = 64 Тогда Возврат "adAsyncFetchNonBlocking"; // The main thread never blocks while retrieving.
ИначеЕсли intV = 128 Тогда Возврат "adExecuteNoRecords"; // Discard, not return retrieved rows (with Command or Connection.Execute only)
ИначеЕсли intV = 256 Тогда Возврат "adExecuteStream"; // The results of a command execution is a stream (with Connection.Execute only)
ИначеЕсли intV = 512 Тогда Возврат "adExecuteRecord"; // Return a single row as a Record object
Иначе Возврат "adOptionUnspecified"; // как -1
КонецЕсли;
КонецФункции
// возвращает числовое значение типа команды ADO по его строковому представлению
Функция intExecuteOptionЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adOptionUnspecified") Тогда Возврат -1; // Unspecified command
ИначеЕсли strV = Нрег("adAsyncExecute") Тогда Возврат 16; // The command should execute asynchronously
ИначеЕсли strV = Нрег("adAsyncFetch") Тогда Возврат 32; // The remaining rows after specified in the CacheSize should be retrieved asynchronously
ИначеЕсли strV = Нрег("adAsyncFetchNonBlocking") Тогда Возврат 64; // The main thread never blocks while retrieving
ИначеЕсли strV = Нрег("adExecuteNoRecords") Тогда Возврат 128; // Discard, not return retrieved rows (with Command or Connection.Execute only)
ИначеЕсли strV = Нрег("adExecuteStream") Тогда Возврат 256; // The results of a command execution is a stream (with Connection.Execute only)
ИначеЕсли strV = Нрег("adExecuteRecord") Тогда Возврат 512; // Return a single row as a Record object
Иначе Возврат -1; // adOptionUnspecified
КонецЕсли;
КонецФункции
// возвращает строковое представление опции аттрибутов параметра ADO по числовому значению опции
Функция strParameterADOAttributesЛкс(intValue) Экспорт
Если ТипЗнч(intValue) = Тип("Число") Тогда
intV = Цел(intValue);
Иначе
intV = 0;
КонецЕсли;
Если intV = 16 Тогда Возврат "adParamSigned"; // The parameter will accept signed values.
ИначеЕсли intV = 64 Тогда Возврат "adParamNullAble"; // The parameter will accept null values.
ИначеЕсли intV = 128 Тогда Возврат "adParamLong"; // The parameter will accept long binary data.
Иначе Возврат "adParamSigned"; // как 16
КонецЕсли;
КонецФункции
// возвращает числовое значение опции аттрибутов параметра ADO по строковому представлению опции
Функция intParameterADOAttributesЛкс(strValue) Экспорт
strV = Нрег(strValue);
Если strV = Нрег("adParamSigned") Тогда Возврат 16; // The parameter will accept signed values.
ИначеЕсли strV = Нрег("adParamNullAble") Тогда Возврат 64; // The parameter will accept null values.
ИначеЕсли strV = Нрег("adParamLong") Тогда Возврат 128; // The parameter will accept long binary data.
Иначе Возврат 16; // adParamSigned
КонецЕсли;
КонецФункции
// ^^^ ПЕРЕЧИСЛЕНИЯ ADO ^^^
// ADO
// ************************
// В платформе все корневые элементы древовидных структур содержат в свойстве Родитель Неопределено.
// Поэтому возникает неудобство при работе с этим свойством, заключающееся в необходимости часто проверять его значение на Неопределено.
//
// Параметры:
// СтрокаДерева - СтрокаДереваЗначений, ДанныеФормыЭлементДерева, ЭлементОтбора - элемент любого иерархического объекта, имеющий родителя
// Дерево - ДеревоЗначений, ДанныеФормыДерево, ОтборКомпоновкиДанных - иерархический объект, которому принадлежит элемент, для дерева значений не нужно передавать
//
// Возвращаемое значение:
// СтрокаДереваЗначений, ДанныеФормыЭлементДерева, ЭлементОтбора, ДеревоЗначений, ДанныеФормыДерево, ОтборКомпоновкиДанных
//
Функция РодительСтрокиДереваЛкс(Знач СтрокаДерева, Знач Дерево = Неопределено) Экспорт
Если ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева") Тогда
Родитель = СтрокаДерева.ПолучитьРодителя();
Иначе
Родитель = СтрокаДерева.Родитель;
КонецЕсли;
Если Родитель = Неопределено Тогда
Если Дерево = Неопределено Тогда
Родитель = СтрокаДерева.Владелец();
Иначе
Родитель = Дерево;
КонецЕсли;
КонецЕсли;
Возврат Родитель;
КонецФункции
// Результат - Неопределено, "*", Число
Функция КоличествоЭлементовКоллекцииЛкс(Значение) Экспорт
Если Истина
И ирКэш.ЛиФайловаяБазаЛкс()
И (Ложь
// Антибаг платформы 8.3.14+ https://www.hostedredmine.com/issues/957985
Или ирКэш.НомерРежимаСовместимостиЛкс() >= 803014 И ТипЗнч(Значение) = Тип("МенеджерКопийБазыДанных")
Или ирКэш.НомерВерсииПлатформыЛкс() >= 803023 И ТипЗнч(Значение) = Тип("МенеджерТабличныхПространствБазыДанных"))
Тогда
Возврат 0;
КонецЕсли;
Если Не ЛиКоллекцияЛкс(Значение) Тогда
КоличествоЭлементов = Неопределено;
Иначе
КоличествоЭлементов = "*";
Если ТипЗнч(Значение) = Тип("COMSafeArray") Тогда
КоличествоЭлементов = Значение.GetLength();
ИначеЕсли ТипЗнч(Значение) = Тип("COMОбъект") Тогда
Попытка
КоличествоЭлементов = Значение.Count;
Исключение
КонецПопытки;
КонецЕсли;
Если КоличествоЭлементов = "*" Тогда
Попытка
КоличествоЭлементов = Значение.Количество();
Исключение
КонецПопытки;
КонецЕсли;
КонецЕсли;
Возврат КоличествоЭлементов;
КонецФункции
Функция ЛиКоллекцияЛкс(Знач Значение) Экспорт
РежимОтладки = Ложь;
Если РежимОтладки Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
#Если Не ТонкийКлиент И Не ВебКлиент Тогда
// Антибаг платформы 8.2.15 (исправлено в 8.2.16) http://partners.v8.1c.ru/forum/thread.jsp?id=1017316#1017316
Если Значение = ПараметрыСеанса Тогда
Возврат Истина;
КонецЕсли;
#КонецЕсли
// Для ускорения
Если Значение = Неопределено Или Значение = Null Тогда
Возврат Ложь;
КонецЕсли;
ХмлТип = XMLТипЗнч(Значение);
Если ХмлТип <> Неопределено Тогда
ИмяТипа = ХмлТип.ИмяТипа;
Если Ложь
Или Найти(ИмяТипа, "Ref.") > 0
Или ИмяТипа = "decimal"
Или ИмяТипа = "boolean"
Или ИмяТипа = "dateTime"
Или ИмяТипа = "string"
Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Попытка
Для Каждого _Элемент Из Значение Цикл
Прервать;
КонецЦикла;
ЭтоКоллекция = Истина;
Исключение
ЭтоКоллекция = Ложь;
КонецПопытки;
Возврат ЭтоКоллекция;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если Значение = ПараметрыСеанса Тогда Возврат Истина; КонецЕсли; Если Значение = Неопределено Или Значение = Null Тогда Возврат Ложь; КонецЕсли; ХмлТип = XMLТипЗнч(Значение); Если ХмлТип <> Неопределено Тогда ИмяТипа = ХмлТип.ИмяТипа; Если Ложь Или Найти(ИмяТипа, "Ref.") > 0 Или ИмяТипа = "decimal" Или ИмяТипа = "boolean" Или ИмяТипа = "dateTime" Или ИмяТипа = "string" Тогда Возврат Ложь; КонецЕсли; КонецЕсли; Попытка Для Каждого _Элемент Из Значение Цикл Прервать; КонецЦикла; ЭтоКоллекция = Истина; Исключение ЭтоКоллекция = Ложь; КонецПопытки; Возврат ЭтоКоллекция;
КонецЕсли;
КонецФункции
Функция СоздатьОбъектПоИмениМетаданныхЛкс(ПолноеИмяМД) Экспорт
Фрагменты = СтрРазделитьЛкс(ПолноеИмяМД);
ТипМетаданных = Фрагменты[0];
ИмяОбъекта = Фрагменты[1];
Если Не ирКэш.ЛиПортативныйРежимЛкс() Тогда
// При обращении к функциям перевода будет бесконечная рекурсия
Символ = Лев(ТипМетаданных, 1);
Если ЛиРусскаяБукваЛкс(Символ) Тогда
Подтип = "Объект";
Иначе
Подтип = "Object";
КонецЕсли;
ТипОбъекта = Тип(ТипМетаданных + Подтип + "." + ИмяОбъекта);
Иначе
КэшТиповВнешнихМетаданных = ирПортативный.мКэшТиповВнешнихМетаданных;
ВнешнийОбъект = КэшТиповВнешнихМетаданных[ПолноеИмяМД];
Если ВнешнийОбъект <> Неопределено Тогда
ТипОбъекта = ТипЗнч(ВнешнийОбъект);
КонецЕсли;
КонецЕсли;
Если ТипОбъекта <> Неопределено Тогда
Результат = Новый (ТипОбъекта);
Иначе
Менеджер = ирПортативный.ПолучитьМенеджерТипаМетаданныхЛкс(ТипМетаданных);
ПолноеИмяФайла = ирПортативный.ПолноеИмяФайлаПортативногоОбъектаМетаданныхЛкс(ИмяОбъекта, ТипМетаданных);
Попытка
Результат = Менеджер.Создать(ПолноеИмяФайла, Ложь);
//// Антибаг платформы 8.3 https://partners.v8.1c.ru/forum/t/1442085/m/1442085
//Если ИмяОбъекта = "ирКлсПолеТекстаПрограммы" Тогда
// Пустышка = Результат.ПолучитьФорму();
//КонецЕсли;
Исключение
// Это очень помогает при ошибках функций режима отладки
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
Если Истина
И КэшТиповВнешнихМетаданных <> Неопределено
// Такой прием ко всем нельзя применять, т.к. при получении формы у разных экземпляров будет возвращаться всегда форма первого экземпляра, если она открыта
И (Ложь
Или ИмяОбъекта = "ирКлсПолеТекстаПрограммы"
Или ИмяОбъекта = "ирПлатформа")
Тогда
КэшТиповВнешнихМетаданных[ПолноеИмяМД] = Результат;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьПолноеИмяМДТипаЛкс(Тип) Экспорт
ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип);
Если ОбъектМетаданных <> Неопределено Тогда
Результат = ОбъектМетаданных.ПолноеИмя();
Если ЛиТипСсылкиТочкиМаршрутаЛкс(Тип) Тогда
Результат = Результат + "." + ПеревестиСтроку("Точки");
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОптимальныйПотоковыйПисательЛкс() Экспорт
Если ирКэш.НомерВерсииПлатформыЛкс() >= 803006 Тогда
ПотоковыйПисатель = МойЗаписьJSON();
Иначе
ПотоковыйПисатель = Новый ЗаписьXML;
КонецЕсли;
Возврат ПотоковыйПисатель;
КонецФункции
Функция МойЗаписьJSON(ДелатьОтступ = Истина) Экспорт
Результат = Новый("ЗаписьJSON");
Если ДелатьОтступ Тогда
//ПараметрыЗаписи = ирОбщий83.ПараметрыЗаписиЖСОНЛкс(); // Только для режима совместимости 8.3.6
ПараметрыЗаписи = Вычислить("Новый ПараметрыЗаписиJSON(, Символы.Таб)"); // для платформы 8.3.6
КонецЕсли;
Результат.УстановитьСтроку(ПараметрыЗаписи);
Возврат Результат;
КонецФункции
Функция ОптимальныйПотоковыйЧитательЛкс() Экспорт
Если ирКэш.ДоступноЖСОНЛкс() Тогда
ПотоковыйЧитатель = МойЧтениеJSON();
Иначе
ПотоковыйЧитатель = Новый ЧтениеXML;
КонецЕсли;
Возврат ПотоковыйЧитатель;
КонецФункции
Функция МойЧтениеJSON() Экспорт
Возврат Новый ("ЧтениеJSON");
КонецФункции
Функция ЛиТекстJSONЛкс(Знач Текст) Экспорт
ПервыйСимвол = Лев(СокрЛ(Текст), 1);
Если ПервыйСимвол <> "{" И ПервыйСимвол <> "[" Тогда
Результат = Ложь;
Иначе
Попытка
ОбъектИзСтрокиJSONЛкс(Текст, Истина);
Результат = Истина;
Исключение
Результат = Ложь;
КонецПопытки;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЛиТекстHTMLЛкс(Знач Текст) Экспорт
Текст = СокрЛП(Текст);
Результат = Истина
И СтрНачинаетсяСЛкс(Текст, "";
Возврат Результат;
КонецФункции
Функция ЛиТекстXMLЛкс(Знач Текст) Экспорт
Текст = СокрЛП(Текст);
ЧислоОткрывающих = СтрЧислоВхождений(Текст, "<");
ЧислоЗакрывающих = СтрЧислоВхождений(Текст, ">");
Результат = Истина
И СтрНачинаетсяСЛкс(Текст, "<")
И Прав(Текст, 1) = ">"
И ЧислоОткрывающих = ЧислоЗакрывающих
И ЧислоОткрывающих > 0;
Возврат Результат;
КонецФункции
Функция ЛиТекстЯзыкаЗапросовЛкс(Знач Текст) Экспорт
мПлатформа = ирКэш.Получить();
Результат = НайтиРегВыражениеЛкс(Текст, мПлатформа.шПустоеНачалоСтроки + "(?:ВЫБРАТЬ|SELECT)(?:$|\s)",, Ложь).Количество() > 0;
Возврат Результат;
КонецФункции
Функция ЛиТекстВстроенногоЯзыкаЛкс(Знач Текст) Экспорт
мПлатформа = ирКэш.Получить();
Результат = НайтиРегВыражениеЛкс(Текст, "[^" + мПлатформа.шБуква + "](?:КонецЕсли|КонецЦикла|КонецПопытки|КонецФункции|КонецПроцедуры)[^" + мПлатформа.шБуква + "]",, Ложь).Количество() > 0;
Возврат Результат;
КонецФункции
Функция ТекстHTMLВТекстXMLЛкс(Знач ТекстХМЛ) Экспорт
ПостроительDOM = Новый ПостроительDOM();
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.УстановитьСтроку(ТекстХМЛ);
ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("html");
Для Каждого Атрибут Из ДокументHTML.ПолучитьЭлементыПоИмени("html")[0].Атрибуты Цикл
Если Атрибут.ЛокальноеИмя = "xmlns" Тогда
Продолжить;
КонецЕсли;
ИмяПрост = ПоследнийФрагментЛкс(Атрибут.ЛокальноеИмя, ":");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен(ИмяПрост, Атрибут.Значение);
КонецЦикла;
ЗаписьDOM = Новый ЗаписьDOM;
ЭлементЗаголовка = ДокументHTML.ПолучитьЭлементыПоИмени("head");
Если ЭлементЗаголовка.Количество() > 0 Тогда
ЗаписьDOM.Записать(ЭлементЗаголовка[0], ЗаписьXML);
КонецЕсли;
ЗаписьDOM.Записать(ДокументHTML.Тело, ЗаписьXML);
ЗаписьXML.ЗаписатьКонецЭлемента();
ТекстХМЛ = ЗаписьXML.Закрыть();
Возврат ТекстХМЛ;
КонецФункции
Функция ДеревоЗначенийИзМассиваСтруктурЛкс(МассивСтруктур, Дерево = Неопределено) Экспорт
Если Дерево = Неопределено Тогда
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Свойство");
Дерево.Колонки.Добавить("Значение");
КонецЕсли;
Если Ложь
Или ТипЗнч(МассивСтруктур) = Тип("Структура")
Или ТипЗнч(МассивСтруктур) = Тип("Соответствие")
Тогда
ЭлементСтруктурыВДеревоЗначений(Дерево, МассивСтруктур);
ИначеЕсли ТипЗнч(МассивСтруктур) = Тип("Массив") Тогда
МассивВДеревоСвойств(Дерево, МассивСтруктур, "");
КонецЕсли;
Возврат Дерево;
КонецФункции
Процедура ЭлементСтруктурыВДеревоЗначений(Дерево, Структура)
#Если Сервер И Не Сервер Тогда
Дерево = Новый ДеревоЗначений;
#КонецЕсли
Для Каждого ЭлСтруктуры Из Структура Цикл
СтрокаДерева = Дерево.Строки.Добавить();
СтрокаДерева.Свойство = ЭлСтруктуры.Ключ;
Если Ложь
Или ТипЗнч(ЭлСтруктуры.Значение) = Тип("Структура")
Или ТипЗнч(ЭлСтруктуры.Значение) = Тип("Соответствие")
Тогда
ЭлементСтруктурыВДеревоЗначений(СтрокаДерева, ЭлСтруктуры.Значение);
ИначеЕсли ТипЗнч(ЭлСтруктуры.Значение) = Тип("Массив") Тогда
СтрокаДерева.Значение = "[Массив-" + XMLСтрока(ЭлСтруктуры.Значение.Количество()) + "]";
МассивВДеревоСвойств(СтрокаДерева, ЭлСтруктуры.Значение, ЭлСтруктуры.Ключ);
Иначе
СтрокаДерева.Значение = ЭлСтруктуры.Значение;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура МассивВДеревоСвойств(Дерево, Массив, ИмяСвойства)
#Если Сервер И Не Сервер Тогда
Дерево = Новый ДеревоЗначений;
#КонецЕсли
Для Каждого СтрМассива Из Массив Цикл
СтрокаДерева = Дерево.Строки.Добавить();
СтрокаДерева.Свойство = "[Элемент " + ИмяСвойства + "]";
Если Ложь
Или ТипЗнч(СтрМассива) = Тип("Структура")
Или ТипЗнч(СтрМассива) = Тип("Соответствие")
Тогда
ЭлементСтруктурыВДеревоЗначений(СтрокаДерева, СтрМассива);
ИначеЕсли ТипЗнч(СтрМассива) = Тип("Массив") Тогда
СтрокаДерева.Значение = "[Массив-" + XMLСтрока(СтрМассива.Количество()) + "]";
МассивВДеревоСвойств(СтрокаДерева, СтрМассива, ИмяСвойства);
Иначе
СтрокаДерева.Значение = СтрМассива;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
//.
// Параметры:
// Форма - РасширениеФормыОбработки -
Процедура ГотовитьТаблицуСобытийРедактораЛкс(Знач Форма, Знач События = Неопределено) Экспорт
Если События = Неопределено Тогда
События = Форма.События;
КонецЕсли;
МассивИменСобытий = Новый Массив;
Для Каждого Макет Из Форма.Метаданные().Макеты Цикл
Если СтрНачинаетсяСЛкс(Макет.Имя, "Алгоритм") Тогда
МассивИменСобытий.Добавить(Макет.Имя);
КонецЕсли;
КонецЦикла;
События.Колонки.Добавить("Параметры");
События.Колонки.Добавить("АлгоритмОбъект");
Для Каждого ИмяСобытия Из МассивИменСобытий Цикл
СтрокаСобытия = События.Добавить();
СтрокаСобытия.ИмяСобытия = ИмяСобытия;
СтрокаСобытия.СинонимСобытия = Форма.Метаданные().Макеты[ИмяСобытия].Представление();
СтрокаСобытия.Параметры = ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(Форма.ПолучитьМакет(ИмяСобытия),,,, Истина);
СтрокаСобытия.Параметры.Колонки.Добавить("ТаблицаТипов");
КонецЦикла;
КонецПроцедуры
//.
// Параметры:
// СобытияХранимые - ТаблицаЗначений
// СобытияВФорме - ТаблицаЗначений
Процедура ПрочитатьХранимыеСобытияЛкс(Знач СобытияХранимые, Знач СобытияВФорме) Экспорт
Для Каждого СтрокаСобытия Из СобытияХранимые Цикл
Если ЗначениеЗаполнено(СтрокаСобытия.Алгоритм) Тогда
СтрокаСобытияФормы = СобытияВФорме.Найти(СтрокаСобытия.ИмяСобытия);
Если СтрокаСобытияФормы <> Неопределено Тогда
СтрокаСобытияФормы.Алгоритм = СтрокаСобытия.Алгоритм;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ОбработатьСобытиеЛкс(ТаблицаСобытий, ИмяСобытия, выхОписаниеОшибки, НаСервере = Ложь, П0 = null, П1 = null, П2 = null, П3 = null, П4 = null, П5 = null, П6 = null, П7 = null) Экспорт
Если НаСервере Тогда
Результат = ирСервер.ОбработатьСобытиеЛкс(ТаблицаСобытий, ИмяСобытия, выхОписаниеОшибки, П0, П1, П2, П3, П4, П5, П6, П7);
Возврат Результат;
Иначе
СтрокаСобытия = ТаблицаСобытий.Найти(ИмяСобытия, "ИмяСобытия");
СтрокаXMLАлгоритма = СтрокаСобытия.Алгоритм;
ОбработчикЗадан = ЗначениеЗаполнено(СтрокаXMLАлгоритма);
Если Не ОбработчикЗадан Тогда
Возврат Истина;
КонецЕсли;
Если ТаблицаСобытий.Колонки.Найти("АлгоритмОбъект") = Неопределено Тогда
ТаблицаСобытий.Колонки.Добавить("АлгоритмОбъект");
КонецЕсли;
АлгоритмОбъект = СтрокаСобытия.АлгоритмОбъект;
Если АлгоритмОбъект = Неопределено Тогда
Попытка
АлгоритмОбъект = ДесериализоватьАлгоритмОбъектЛкс(СтрокаXMLАлгоритма);
Исключение
ВызватьИсключение "Ошибка десериализации алгоритма для события " + ИмяСобытия + ": " + ОписаниеОшибки();
КонецПопытки;
АлгоритмОбъект.Наименование = ИмяСобытия;
ВнутренниеПараметры = АлгоритмОбъект.Параметры.Выгрузить();
АлгоритмОбъект.Параметры.Загрузить(СтрокаСобытия.Параметры);
ЗагрузитьВТаблицуЗначенийЛкс(ВнутренниеПараметры, АлгоритмОбъект.Параметры);
СтрокаСобытия.АлгоритмОбъект = АлгоритмОбъект;
КонецЕсли;
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Попытка
Результат = мПлатформа.ВыполнитьМетодАлгоритма(АлгоритмОбъект, 0, П0, П1, П2, П3, П4, П5, П6, П7);
Исключение
//выхОписаниеОшибки = ПолучитьПричинуОшибки(ОписаниеОшибки());
выхОписаниеОшибки = ОписаниеОшибки();
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецЕсли;
КонецФункции
// Для защиты от несериализуемых типов
Функция КопияТаблицыСобытийДляСервераЛкс(СобытияОбработкиОбъектов) Экспорт
#Если Сервер И Не Сервер Тогда
СобытияОбработкиОбъектов = Новый ТаблицаЗначений;
#КонецЕсли
КопияСобытияОбработкиОбъектов = СобытияОбработкиОбъектов.Скопировать();
КопияСобытияОбработкиОбъектов.ЗаполнитьЗначения(, "АлгоритмОбъект");
Для Каждого СтрокаСобытия Из КопияСобытияОбработкиОбъектов Цикл
СтрокаСобытия.Параметры.ЗаполнитьЗначения(, "ТаблицаТипов");
КонецЦикла;
Возврат КопияСобытияОбработкиОбъектов;
КонецФункции
Функция ДесериализоватьАлгоритмОбъектЛкс(Знач СтрокаXMLАлгоритма) Экспорт
АлгоритмОбъект = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирИмитаторАлгоритмОбъект");
#Если Сервер И Не Сервер Тогда
АлгоритмОбъект = Обработки.ирИмитаторАлгоритмОбъект.Создать();
#КонецЕсли
СтруктураАлгоритма = ОбъектИзСтрокиXMLЛкс(СтрокаXMLАлгоритма); // см. ирКлиент.РедактироватьАлгоритмЧерезСтруктуруЛкс.СтруктураАлгоритма
АлгоритмОбъект.ТекстАлгоритма = СтруктураАлгоритма.ТекстАлгоритма;
ЗагрузитьВТаблицуЗначенийЛкс(СтруктураАлгоритма.ВнутренниеПараметры, АлгоритмОбъект.Параметры, Новый Структура("Вход", Истина));
Возврат АлгоритмОбъект;
КонецФункции
Функция КонсольКомпоновки_ПередВыполнениемЛкс(Знач ТаблицаСобытий, Знач ИмяСобытия, выхОписаниеОшибки, Знач НаСервере = Ложь, ВременнаяСхемаКомпоновки, ВременныеНастройкиКомпоновки,
СтруктураВнешниеНаборыДанных, МенеджерВременныхТаблиц = Неопределено) Экспорт
Если НаСервере Тогда
ТаблицаСобытий = КопияТаблицыСобытийДляСервераЛкс(ТаблицаСобытий);
ВременнаяСхемаКомпоновки = ПоместитьВоВременноеХранилище(ВременнаяСхемаКомпоновки);
ВременныеНастройкиКомпоновки = ПоместитьВоВременноеХранилище(ВременныеНастройкиКомпоновки);
Результат = ирСервер.КонсольКомпоновки_ПередВыполнениемЛкс(ТаблицаСобытий, ИмяСобытия, выхОписаниеОшибки, ВременнаяСхемаКомпоновки, ВременныеНастройкиКомпоновки, СтруктураВнешниеНаборыДанных);
ВременнаяСхемаКомпоновки = ПолучитьИзВременногоХранилища(ВременнаяСхемаКомпоновки);
ВременныеНастройкиКомпоновки = ПолучитьИзВременногоХранилища(ВременныеНастройкиКомпоновки);
Возврат Результат;
Иначе
ИспользоватьВременноеХранилище = ТипЗнч(ВременнаяСхемаКомпоновки) = Тип("Строка");
Если ИспользоватьВременноеХранилище Тогда
ВременнаяСхемаКомпоновки = ПолучитьИзВременногоХранилища(ВременнаяСхемаКомпоновки);
ВременныеНастройкиКомпоновки = ПолучитьИзВременногоХранилища(ВременныеНастройкиКомпоновки);
КонецЕсли;
Результат = ОбработатьСобытиеЛкс(ТаблицаСобытий, ИмяСобытия, выхОписаниеОшибки,, ВременнаяСхемаКомпоновки, ВременныеНастройкиКомпоновки, СтруктураВнешниеНаборыДанных, МенеджерВременныхТаблиц);
ВременнаяСхемаКомпоновкиЛ = ПоместитьВоВременноеХранилище(ВременнаяСхемаКомпоновки);
Если ИспользоватьВременноеХранилище Тогда
ВременнаяСхемаКомпоновки = ПоместитьВоВременноеХранилище(ВременнаяСхемаКомпоновки);
ВременныеНастройкиКомпоновки = ПоместитьВоВременноеХранилище(ВременныеНастройкиКомпоновки);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// мВнешниеНаборыДанных - Структура, Неопределено - не очищается
Функция ДополнитьСтруктуруВнешнихНаборовДанныхПустышкамиЛкс(СхемаКомпоновкиДанных, ВнешниеНаборыДанных = Неопределено) Экспорт
Если ВнешниеНаборыДанных = Неопределено Тогда
ВнешниеНаборыДанных = Новый Структура();
КонецЕсли;
// Создадим пустышки внешних наборов данных, если они не переданы
ОбъектТаблица = 0;
Для Каждого НаборДанных Из СхемаКомпоновкиДанных.НаборыДанных Цикл
Если ТипЗнч(НаборДанных) = Тип("НаборДанныхОбъектСхемыКомпоновкиДанных") Тогда
Если НаборДанных.ИмяОбъекта = "" Тогда
Продолжить;
КонецЕсли;
Если Не ВнешниеНаборыДанных.Свойство(НаборДанных.ИмяОбъекта, ОбъектТаблица) Тогда
ОбъектТаблица = Новый ТаблицаЗначений;
КонецЕсли;
Попытка
КолонкиОбъектаТаблицы = ОбъектТаблица.Колонки;
Исключение
//! ОбъектТаблица = 0 // ТабличнаяЧасть
// Тогда это табличная часть, но возможно и тут будет исключение
КолонкиОбъектаТаблицы = ОбъектТаблица.ВыгрузитьКолонки().Колонки;
КонецПопытки;
Если КолонкиОбъектаТаблицы.Количество() > 0 Тогда
Продолжить;
КонецЕсли;
Для Каждого Поле Из НаборДанных.Поля Цикл
Если ТипЗнч(Поле) = Тип("ПолеНабораДанныхСхемыКомпоновкиДанных") Тогда
Если КолонкиОбъектаТаблицы.Найти(Поле.Поле) = Неопределено Тогда
КолонкиОбъектаТаблицы.Добавить(Поле.Поле, Поле.ТипЗначения);
КонецЕсли;
КонецЕсли;
КонецЦикла;
ВнешниеНаборыДанных.Вставить(НаборДанных.ИмяОбъекта, ОбъектТаблица);
ИначеЕсли ТипЗнч(НаборДанных) = Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных") Тогда
ДополнитьСтруктуруВнешнихНаборовДанныхПустышкамиЛкс(Новый Структура("НаборыДанных", НаборДанных.Элементы), ВнешниеНаборыДанных);
КонецЕсли;
КонецЦикла;
Возврат ВнешниеНаборыДанных;
КонецФункции
Процедура ПроверитьСхемуКомпоновкиЛкс(Знач ПроверочнаяСхема, Знач НастройкаКомпоновки, Знач ПроверятьДоступностьПолей = Истина, Знач ВнешниеФункцииРазрешены = Истина, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
ирСервер.ПроверитьСхемуКомпоновкиЛкс(ОбъектВСтрокуXMLЛкс(ПроверочнаяСхема), ОбъектВСтрокуXMLЛкс(НастройкаКомпоновки), ПроверятьДоступностьПолей, ВнешниеФункцииРазрешены);
Иначе
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// От(ПроверочнаяСхема, НастройкаКомпоновки);
ВнешниеНаборыДанных = ДополнитьСтруктуруВнешнихНаборовДанныхПустышкамиЛкс(ПроверочнаяСхема);
МакетКомпоновки = КомпоновщикМакета.Выполнить(ПроверочнаяСхема, НастройкаКомпоновки,,,, ПроверятьДоступностьПолей); // Здесь будет возникать ошибка
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных,, ВнешниеФункцииРазрешены);
КонецЕсли;
КонецПроцедуры
// Осуществляет вывод результата компоновки в коллекцию значений. По умолчанию в качестве коллекции используется новая таблица значений.
// Параметры:
// СхемаКомпоновки - СхемаКомпоновкиДанных
// НастройкаКомпоновки - НастройкиКомпоновкиДанных
// КоллекцияЗначений - ДеревоЗначений, Массив, СписокЗначений, ТаблицаЗначений - Если не указана, создается ТаблицаЗначений
// ВнешниеНаборыДанных - Структура
// ТолькоСоздатьКолонки - Булево
// СхемаКолонок - Структура - Если Неопределено, то не возвращается
// МаксимальноеЧислоСтрокРезультата - Число(15,2) - Для предотвращения получения слишком большого результата. Если порог превышен, то результат = Неопределено.
// ОтключитьОбщиеИтоги - Булево
// РежимОтладки - Булево
//
Функция СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(Знач СхемаКомпоновки, Знач НастройкаКомпоновки, КоллекцияЗначений = Неопределено, Знач ВнешниеНаборыДанных = Неопределено,
Знач ТолькоСоздатьКолонки = Ложь, СхемаКолонок = Неопределено, Знач МаксимальноеЧислоСтрокРезультата = 0, Знач ОтключитьОбщиеИтоги = Истина, Знач РежимОтладки = Ложь,
Знач ПроверятьДоступностьПолей = Ложь, Знач СузитьТипы = Ложь, Знач ЗаменаТочкиВИменахКолонок = "", Знач ВыбратьВсеДоступныеПоля = Ложь, Знач НаСервере = Ложь) Экспорт
МакетКомпоновки = СобратьМакетКомпоновкиЛкс(СхемаКомпоновки, НастройкаКомпоновки, ВнешниеНаборыДанных, ОтключитьОбщиеИтоги, РежимОтладки, ПроверятьДоступностьПолей, ВыбратьВсеДоступныеПоля);
Если РежимОтладки = Истина Тогда
Возврат Неопределено;
КонецЕсли;
Попытка
Результат = СкомпоноватьВКоллекциюЗначенийПоМакетуЛкс(МакетКомпоновки, КоллекцияЗначений, ВнешниеНаборыДанных, ТолькоСоздатьКолонки, СхемаКолонок, МаксимальноеЧислоСтрокРезультата,
СузитьТипы, ЗаменаТочкиВИменахКолонок, НаСервере);
Исключение
ОбработатьОшибкиКомпоновкиПлатформыЛкс(ИнформацияОбОшибке(), МакетКомпоновки, НастройкаКомпоновки);
ВызватьИсключение;
КонецПопытки;
Возврат Результат;
КонецФункции
// Антибаг платформы https://www.hostedredmine.com/issues/965039
Процедура ОбработатьОшибкиКомпоновкиПлатформыЛкс(Знач ИнформацияОбОшибке, Знач МакетКомпоновки, Знач НастройкаКомпоновки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
МакетКомпоновки = Новый МакетКомпоновкиДанных;
#КонецЕсли
ОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке.Причина);
Если Ложь
Или Найти(ОписаниеОшибки, "Ошибка в выражении") > 0
Или Найти(ОписаниеОшибки, "Error in expression") > 0
Тогда
Для Каждого НаборМакета Из МакетКомпоновки.НаборыДанных Цикл
Если ЗначениеЗаполнено(НаборМакета.Отбор) Тогда
Для Каждого ЭлементОтбора Из НастройкаКомпоновки.Отбор.Элементы Цикл
Если Истина
И ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ЭлементОтбора.Использование
И ЭлементОтбора.ВидСравнения <> ВидСравненияКомпоновкиДанных.Равно
И ЭлементОтбора.ВидСравнения <> ВидСравненияКомпоновкиДанных.НеРавно
И ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("Строка")
И Найти(ЭлементОтбора.ПравоеЗначение, """") > 0
Тогда
ВызватьИсключение "Невозможно выполнить компоновку из-за ошибки обработки платформой символа ""двойная кавычка"" в значении отбора с видом ""Содержит"" https://www.hostedredmine.com/issues/965037 :
|" + ОписаниеОшибки;
КонецЕсли;
КонецЦикла;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// В режиме совместимости 8.3.5- работает некорректно - переставляет колонки местами
Функция ОтобратьТаблицуЗначенийКомпоновкойЛкс(Знач ТаблицаЗначений, Знач НастройкаКомпоновки, Знач РежимОтладки = Ложь, СкопироватьИВосстановитьНастройки = Ложь,
Знач ТаблицаБезДанныхСУзкимиТипами = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
Если Не ирКэш.ДоступноКомпоновкаТаблицыЗначенийКлс() Тогда
ВызватьИсключение "Недоступно в режиме совместимости 8.3.5-";
КонецЕсли;
НаборыДанных = Неопределено;
СхемаКомпоновки = СоздатьСхемуПоТаблицеЗначенийЛкс(ТаблицаЗначений, НаборыДанных, ТаблицаБезДанныхСУзкимиТипами);
Если СкопироватьИВосстановитьНастройки Тогда
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки));
Компоновщик.ЗагрузитьНастройки(СкопироватьНастройкиКомпоновкиЛкс(НастройкаКомпоновки,, Истина));
КомпоновщикНастроекВосстановитьЛкс(Компоновщик);
НастройкаКомпоновки = Компоновщик.Настройки;
КонецЕсли;
ТаблицаОтобранное = ТаблицаЗначений.СкопироватьКолонки();
СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(СхемаКомпоновки, НастройкаКомпоновки, ТаблицаОтобранное, НаборыДанных,,,,, РежимОтладки,,,, Истина);
Возврат ТаблицаОтобранное;
КонецФункции
// Выбирает в массив данные элементов коллекции произвольным условием. https://infostart.ru/1c/articles/1887014/
// Не следует использовать эту функцию для долгих (тяжелых) условий!
// Параметры:
// Коллекция - Коллекция - произвольная коллекция
// Условие - Строка, Структура - Если тип "Строка", то логическое выражение на встроенном языке, где параметр "Э" дает доступ к элементу коллекции, а параметры "П" - к параметрам условия.
// Если тип "Структура", то ключ задает имя свойства, а значение его отбор на равенство
// ПутьКСвойству - Строка - путь к свойству, значение которого нужно извлечь из элемента коллекции и добавить в массив результата;
// допускается начинать и не начинать путь со ссылки на элемент коллекции ("Э.")
// если нужно выгрузить сами элементы, то "" или "Э"; например "ЭлементУправления.ЦветТекста"
// П1 - Произвольное - параметр "П1" для использования в текстовом условии
// П2 - Произвольное - параметр "П2" для использования в текстовом условии
// П3 - Произвольное - параметр "П3" для использования в текстовом условии
// При малом числе элементов заметно медленнее чем статический код. При 100 элементах сопоставима по скорости с ним. При большем числе элементов даже быстрее него.
// Пример: ОтобратьКоллекциюЛкс(Коллекция, "Э<>1 И Э<>П1",, Среднее)
// Возвращаемое значение:
// Массив - элементов коллекции или значений их свойства
Функция ОтобратьКоллекциюЛкс(Знач Коллекция, Знач Условие, Знач ПутьКСвойству = "", Знач П1 = 0, Знач П2 = 0, Знач П3 = 0) Экспорт
Если ТипЗнч(Условие) <> Тип("Строка") Тогда
Если Не ЗначениеЗаполнено(ПутьКСвойству) Тогда
ПутьКСвойству = "Э";
КонецЕсли;
Результат = ВыгрузитьСвойствоЛкс(Коллекция, ПутьКСвойству, Условие);
Возврат Результат;
КонецЕсли;
Результат = Новый Массив;
Если ПутьКСвойству <> "Э" И Не СтрНачинаетсяСЛкс(ПутьКСвойству, "Э.") Тогда
ПутьКСвойству = "Э" + ?(ЗначениеЗаполнено(ПутьКСвойству), "." + ПутьКСвойству, "");
КонецЕсли;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Э Из Коллекция Цикл
//Если Э <> 0 Тогда // Для сравнения скорости со статическим кодом
Если Вычислить(Условие) Тогда
Результат.Добавить(Вычислить(ПутьКСвойству));
КонецЕсли;
КонецЦикла;
Иначе
Попытка
// Этот вариант кода использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах.
Выполнить("// ДинамическийКод
|Для Каждого Э Из Коллекция Цикл
| Если " + Условие + " Тогда
| Результат.Добавить(" + ПутьКСвойству + ");
| КонецЕсли;
|КонецЦикла;");
Исключение
Ошибка = ОбработатьИсключениеВДинамическомКодеЛкс(ИнформацияОбОшибке());
Если ЗначениеЗаполнено(Ошибка) Тогда
ВызватьИсключение Ошибка;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
КонецЕсли;
Возврат Результат;
КонецФункции
// Возвращает массив значений элементов коллекции.
//
// Параметры:
// Коллекция - Коллекция - произвольная коллекция
// ПутьКСвойству - Строка - путь к свойству; если не заполнено, то берется Ключ/Представление/Имя, например "ЭлементУправления.ЦветТекста"
// если нужно извлекать сами элементы, то "Э";
// СтруктураОтбора - Структура - ключ задает имя свойства, а значение его отбор на равенство
// ТипЭлемента - Тип - если заполнено, то обрабатывать только элементы такого типа
//
// Возвращаемое значение:
// Массив - элементов коллекции или значений их свойства
Функция ВыгрузитьСвойствоЛкс(Знач Коллекция, Знач ПутьКСвойству = "", СтруктураОтбора = Неопределено, Знач ТипЭлемента = Неопределено) Экспорт
ДоступенИндексСвойств = Найти(ПутьКСвойству, ".") = 0;
Если Не ЗначениеЗаполнено(ПутьКСвойству) Тогда
Если Ложь
Или ТипЗнч(Коллекция) = Тип("Соответствие")
Или ТипЗнч(Коллекция) = Тип("Структура")
Или ТипЗнч(Коллекция) = Тип("ФиксированноеСоответствие")
Или ТипЗнч(Коллекция) = Тип("ФиксированнаяСтруктура")
Тогда
ПутьКСвойству = "Ключ";
ИначеЕсли ТипЗнч(Коллекция) = Тип("СписокЗначений") Тогда
ПутьКСвойству = "Представление";
Иначе
ПутьКСвойству = "Имя";
КонецЕсли;
КонецЕсли;
Результат = Новый Массив;
СтрокаСвойств = "";
ЕстьОтборСтруктурой = СтруктураОтбора <> Неопределено;
ЕстьОтборТипом = ТипЭлемента <> Неопределено;
Для каждого Э Из Коллекция Цикл
Если Ложь
Или ЕстьОтборСтруктурой И Не СравнитьЗначенияСвойствЛкс(Э, СтруктураОтбора, СтрокаСвойств)
Или ЕстьОтборТипом И ТипЗнч(Э) <> ТипЭлемента
Тогда
Продолжить;
КонецЕсли;
Если ПутьКСвойству = "Э" Тогда
ЗначениеСвойства = Э;
ИначеЕсли ДоступенИндексСвойств Тогда
ЗначениеСвойства = Э[ПутьКСвойству];
Иначе
Попытка
ЗначениеСвойства = Вычислить("Э." + ПутьКСвойству);
Исключение
// Антибаг платформы. Чтобы в описание ошибки попал указательн а строку кода
Ошибка = ОписаниеОшибки();
ВызватьИсключение Ошибка;
КонецПопытки;
КонецЕсли;
Результат.Добавить(ЗначениеСвойства);
КонецЦикла;
Возврат Результат;
КонецФункции
// Устанавливает свойство у элементов коллекции.
//
// Параметры:
// Коллекция - Произвольный - любая индексированная коллекция
// ПутьКСвойству - Строка - путь к свойству, значение которого нужно установить, например "ЭлементУправления.ЦветТекста"
// ЗначениеСвойства - Произвольный.
// ИменаЭлементов - Массив - индексы элементов
// - Строка - имена элементов, разделенные запятыми
//
Процедура УстановитьСвойствоВКоллекцииЛкс(Коллекция, ПутьКСвойству, ЗначениеСвойства = Неопределено, ИменаЭлементов = Неопределено) Экспорт
ДоступенИндексСвойств = Найти(ПутьКСвойству, ".") > 0;
Попытка
Если ИменаЭлементов <> Неопределено Тогда
Если ТипЗнч(ИменаЭлементов) = Тип("Строка") Тогда
МассивИндексов = СтрРазделитьЛкс(ИменаЭлементов, ",", Истина);
Иначе
МассивИндексов = ИменаЭлементов;
КонецЕсли;
Для Каждого ИмяЭлемента Из МассивИндексов Цикл
ЭлементКоллекции = Коллекция[ИмяЭлемента];
Если ДоступенИндексСвойств Тогда
ЭлементКоллекции[ПутьКСвойству] = ЗначениеСвойства;
Иначе
Выполнить("// ДинамическийКод
|ЭлементКоллекции." + ПутьКСвойству + " = ЗначениеСвойства");
КонецЕсли;
КонецЦикла;
Иначе
Для Каждого ЭлементКоллекции Из Коллекция Цикл
Если ДоступенИндексСвойств Тогда
ЭлементКоллекции[ПутьКСвойству] = ЗначениеСвойства;
Иначе
Выполнить("// ДинамическийКод
|ЭлементКоллекции." + ПутьКСвойству + " = ЗначениеСвойства");
КонецЕсли;
КонецЦикла;
КонецЕсли;
Исключение
Ошибка = ОбработатьИсключениеВДинамическомКодеЛкс(ИнформацияОбОшибке());
Если ЗначениеЗаполнено(Ошибка) Тогда
ВызватьИсключение Ошибка;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
КонецПроцедуры
// Обход ошибки платформы в обычном клиентском приложении https://www.hostedredmine.com/issues/965445
// Позволяет перевыбросить исключение так, чтобы конфигуратор позволял быстрый переход к ближайшей строке статического кода из ошибки в динамическом коде.
// Динамический код должен начинаться с "// ДинамическийКод"
Функция ОбработатьИсключениеВДинамическомКодеЛкс(ИнформацияОбОшибке) Экспорт
#Если Сервер И Не Сервер Тогда
ИнформацияОбОшибке = ИнформацияОбОшибке();
#КонецЕсли
Результат = Неопределено;
Если Ложь
Или ИнформацияОбОшибке.Причина = Неопределено
Или Найти(ИнформацияОбОшибке.Описание, "Ошибка компиляции") > 0
Тогда
Ошибка = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
Позиция = Найти(Ошибка, "// ДинамическийКод");
Если Позиция > 0 Тогда
Результат = Лев(Ошибка, Позиция - 1);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИмяФиктивногоПоляСхемыКомпоновкиЛкс() Экспорт
Возврат "_ФиктивноеПоле";
КонецФункции
// Собирает макет компоновки из схемы и настроек.
// Параметры:
// СхемаКомпоновки - СхемаКомпоновкиДанных
// НастройкаКомпоновки - НастройкиКомпоновкиДанных
// ВнешниеНаборыДанных - Структура
// ОтключитьОбщиеИтоги - ? -
// РежимОтладки - ? -
// ПроверятьДоступностьПолей - ? -
// ВыбратьВсеДоступныеПоля - ? -
// МакетКомпоновки - МакетКомпоновкиДанных -
// ТипВыхода - Строка - Служебный параметр для перехода после вызова метода
Функция СобратьМакетКомпоновкиЛкс(СхемаКомпоновки, НастройкаКомпоновки, ВнешниеНаборыДанных = Неопределено, ОтключитьОбщиеИтоги = Ложь, РежимОтладки = Ложь,
ПроверятьДоступностьПолей = Истина, ВыбратьВсеДоступныеПоля = Ложь, ЗаполнятьРасшифровки = Истина, ДанныеРасшифровки = Неопределено, СвойМакетОформления = Неопределено,
ТипГенератора = Неопределено, ДобавитьРасшифровкиДляПолейИтогов = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
Если НастройкаКомпоновки.Структура.Количество() = 0 Тогда
//ЭлементСтруктуры = НастройкаКомпоновки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
//ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(НастройкаКомпоновки.Структура);
КонецЕсли;
Если ВыбратьВсеДоступныеПоля Тогда
ДобавитьВсеДоступныеПоляКомпоновкиВВыбранныеЛкс(СхемаКомпоновки, НастройкаКомпоновки);
КонецЕсли;
Если ОтключитьОбщиеИтоги Тогда
НастройкаКомпоновки.ПараметрыВывода.УстановитьЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ВертикальноеРасположениеОбщихИтогов"), РасположениеИтоговКомпоновкиДанных.Нет);
КонецЕсли;
Если ТипГенератора = Неопределено Тогда
ТипГенератора = Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений");
КонецЕсли;
Если Истина
И ТипГенератора = Тип("ГенераторМакетаКомпоновкиДанных")
И ДобавитьРасшифровкиДляПолейИтогов
Тогда
// Платформа для полей итогов почему то не добавляет значения в расшифровку по умолчанию. Исправим это.
// !!! Формат, заданный в макете, перезапишет формат, заданный в условном оформлении.
Для Каждого ПолеИтога Из СхемаКомпоновки.ПоляИтога Цикл
Если СхемаКомпоновки.Макеты.Найти(ПолеИтога.ПутьКДанным) <> Неопределено Тогда
Продолжить;
КонецЕсли;
ОписаниеМакета = СхемаКомпоновки.Макеты.Добавить();
ОписаниеМакета.Имя = ПолеИтога.ПутьКДанным;
МакетОбласти = Новый МакетОбластиКомпоновкиДанных;
СтрокаТаблицыОбласти = МакетОбласти.Добавить(Тип("СтрокаТаблицыОбластиКомпоновкиДанных"));
ЯчейкаОбласти = СтрокаТаблицыОбласти.Ячейки.Добавить();
ПолеОбласти = ЯчейкаОбласти.Элементы.Добавить(Тип("ПолеОбластиКомпоновкиДанных"));
ПолеОбласти.Значение = Новый ПараметрКомпоновкиДанных("п");
ЯчейкаОбласти.Оформление.УстановитьЗначениеПараметра("Расшифровка", Новый ПараметрКомпоновкиДанных("р"));
ОписаниеМакета.Макет = МакетОбласти;
ПараметрВыражение = ОписаниеМакета.Параметры.Добавить(Тип("ПараметрОбластиВыражениеКомпоновкиДанных"));
ПараметрВыражение.Выражение = ПолеИтога.ПутьКДанным;
ПараметрВыражение.Имя = "п";
ПараметрРасшифровки = ОписаниеМакета.Параметры.Добавить(Тип("ПараметрОбластиРасшифровкаКомпоновкиДанных"));
ВыражениеПоля = ПараметрРасшифровки.ВыраженияПолей.Добавить();
ВыражениеПоля.Поле = ПолеИтога.ПутьКДанным;
ВыражениеПоля.Выражение = ПолеИтога.ПутьКДанным;
ПараметрРасшифровки.Имя = "р";
МакетПоля = СхемаКомпоновки.МакетыПолей.Добавить();
МакетПоля.Поле = ПолеИтога.ПутьКДанным;
МакетПоля.Макет = ОписаниеМакета.Имя;
КонецЦикла;
КонецЕсли;
Если РежимОтладки = Истина Тогда
ОтладитьЛкс(СхемаКомпоновки, Ложь, НастройкаКомпоновки, ВнешниеНаборыДанных);
//Возврат Неопределено;
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Если ЗаполнятьРасшифровки Тогда
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкаКомпоновки, ДанныеРасшифровки, СвойМакетОформления, ТипГенератора, ПроверятьДоступностьПолей);
Иначе
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкаКомпоновки, , СвойМакетОформления, ТипГенератора, ПроверятьДоступностьПолей);
КонецЕсли;
Возврат МакетКомпоновки;
КонецФункции
// Осуществляет вывод результата компоновки в коллекцию значений. По умолчанию в качестве коллекции используется новая таблица значений.
// Параметры:
// МакетКомпоновки - МакетКомпоновкиДанных -
// КоллекцияЗначений - ДеревоЗначений, Массив, СписокЗначений, ТаблицаЗначений - Если не указана, создается ТаблицаЗначений
// ВнешниеНаборыДанных - Структура -
// ТолькоСоздатьКолонки - Булево -
// СхемаКолонок - Структура - Если Неопределено, то не возвращается
// МаксимальноеЧислоСтрокРезультата - Число(15,2) - Для предотвращения получения слишком большого результата. Если порог превышен, то результат = Неопределено.
// СузитьТипы - Булево -
// ЗаменаТочкиВИменахКолонок - Строка -
// КоллекцияРезультата - ? -
// ТипВыхода - Строка - Служебный параметр для перехода после вызова метода
Функция СкомпоноватьВКоллекциюЗначенийПоМакетуЛкс(МакетКомпоновки, КоллекцияЗначений = Неопределено, ВнешниеНаборыДанных = Неопределено, ТолькоСоздатьКолонки = Ложь, СхемаКолонок = Неопределено,
МаксимальноеЧислоСтрокРезультата = 0, СузитьТипы = Ложь, Знач ЗаменаТочкиВИменахКолонок = "", Знач НаСервере = Ложь) Экспорт
Если НаСервере Тогда
АдресМакетКомпоновки = ПоместитьВоВременноеХранилище(МакетКомпоновки);
Результат = ирСервер.СкомпоноватьВКоллекциюЗначенийПоМакетуЛкс(АдресМакетКомпоновки, КоллекцияЗначений, ВнешниеНаборыДанных, ТолькоСоздатьКолонки, СхемаКолонок, МаксимальноеЧислоСтрокРезультата,
СузитьТипы, ЗаменаТочкиВИменахКолонок);
Возврат Результат;
КонецЕсли;
Если Ложь
Или КоллекцияЗначений = Неопределено
Или ТипЗнч(КоллекцияЗначений) = Тип("СписокЗначений")
Или ТипЗнч(КоллекцияЗначений) = Тип("Массив")
Тогда
КоллекцияРезультата = Новый ТаблицаЗначений;
Иначе
КоллекцияРезультата = КоллекцияЗначений;
КонецЕсли;
Если ирКэш.НомерРежимаСовместимостиЛкс() < 803001 Тогда
// https://www.hostedredmine.com/issues/930812
КоллекцияРезультата.Колонки.Очистить();
КонецЕсли;
#Если Сервер И Не Сервер Тогда
МакетКомпоновки = Новый МакетКомпоновкиДанных;
#КонецЕсли
Если МаксимальноеЧислоСтрокРезультата > 0 Тогда
// Здесь тратится дополнительное ощутимое время на предварительный запрос.
ГрубоеКоличествоСтрокРезультата = КоличествоСтрокВРезультатеКомпоновкиЛкс(МакетКомпоновки);
Если ГрубоеКоличествоСтрокРезультата > МаксимальноеЧислоСтрокРезультата Тогда
СообщитьЛкс("Настройки компоновки приводят к слишком большой выборке данных. Попробуйте задать более сильные ограничения.");
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
//Антибаг платформы 8.1.14. Удаляем дубли ячеек по именам колонок в макете.
//ИсследоватьЛкс(МакетКомпоновки, Ложь);
ОписанияМакетовОбластей = МакетКомпоновки.Макеты;
Если ОписанияМакетовОбластей.Количество() > 0 Тогда
ЯчейкиЗаголовка = ОписанияМакетовОбластей[0].Макет.Ячейки;
КоличествоЯчеек = ЯчейкиЗаголовка.Количество();
СтруктураКолонок = Новый Структура;
ИндексЯчейки = 0;
Пока ИндексЯчейки < КоличествоЯчеек Цикл
ЯчейкаКолонки = ЯчейкиЗаголовка[ИндексЯчейки];
ИмяКолонки = ЯчейкаКолонки.Имя;
//ИмяКолонки = ИдентификаторИзПредставленияЛкс(ЯчейкаКолонки.Имя); // От этого варианта отказались из-за портативности
ИмяКолонки = СтрЗаменить(ИмяКолонки, ".", "_");
ИмяКолонки = СтрЗаменить(ИмяКолонки, "]", "");
ИмяКолонки = СтрЗаменить(ИмяКолонки, "[", "");
ИмяКолонки = СтрЗаменить(ИмяКолонки, " ", "_");
ЯчейкаКолонки.Имя = ИмяКолонки;
Если Ложь
Или Не ЗначениеЗаполнено(ИмяКолонки)
Или СтруктураКолонок.Свойство(ИмяКолонки)
Тогда
Для ИндексМакета = 1 По ОписанияМакетовОбластей.Количество() - 1 Цикл
МакетСтроки = ОписанияМакетовОбластей[ИндексМакета];
МакетСтроки.Макет.Ячейки.Удалить(ИндексЯчейки);
КонецЦикла;
ЯчейкиЗаголовка.Удалить(ИндексЯчейки);
КоличествоЯчеек = КоличествоЯчеек - 1;
Иначе
ИндексЯчейки = ИндексЯчейки + 1;
СтруктураКолонок.Вставить(ИмяКолонки);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Ложь
Или СхемаКолонок <> Неопределено
Или ЗначениеЗаполнено(ЗаменаТочкиВИменахКолонок)
Тогда
СхемаКолонок = СхемаКолонокМакетаКомпоновкиЛкс(МакетКомпоновки, СхемаКолонок);
КонецЕсли;
Если ТолькоСоздатьКолонки Тогда
КоллекцияЗначений.Колонки.Очистить();
ЯчейкиЗаголовка = МакетКомпоновки.Макеты[0].Макет.Ячейки;
Для Каждого Ячейка Из ЯчейкиЗаголовка Цикл
//КолонкаКоллекции = КоллекцияЗначений.Колонки.Найти(Ячейка.Имя);
//Если КолонкаКоллекции = Неопределено Тогда
КоллекцияЗначений.Колонки.Добавить(Ячейка.Имя, Ячейка.ТипЗначения, Ячейка.Заголовок,);
//КонецЕсли;
КонецЦикла;
Иначе
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, , Истина);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(КоллекцияРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецЕсли;
//ИсследоватьЛкс(КоллекцияРезультата);
Если ТипЗнч(КоллекцияЗначений) = Тип("СписокЗначений") Тогда
Есть0 = КоллекцияРезультата.Колонки.Количество() > 0;
Есть1 = КоллекцияРезультата.Колонки.Количество() > 1;
Для Каждого СтрокаРезультата Из КоллекцияРезультата Цикл
НовыйЭлемент = КоллекцияЗначений.Добавить();
Если Есть0 Тогда
НовыйЭлемент.Значение = СтрокаРезультата[0];
КонецЕсли;
Если Есть1 Тогда
НовыйЭлемент.Представление = СтрокаРезультата[1];
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(КоллекцияЗначений) = Тип("Массив") Тогда
Если КоллекцияРезультата.Колонки.Количество() > 0 Тогда
Для Каждого СтрокаРезультата Из КоллекцияРезультата Цикл
КоллекцияЗначений.Добавить(СтрокаРезультата[0]);
КонецЦикла;
КонецЕсли;
Иначе
КоллекцияЗначений = КоллекцияРезультата;
Если ЗначениеЗаполнено(ЗаменаТочкиВИменахКолонок) Тогда
Для Каждого Колонка Из КоллекцияЗначений.Колонки Цикл
Колонка.Имя = СтрЗаменить(СхемаКолонок[Колонка.Имя], ".", ЗаменаТочкиВИменахКолонок);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат КоллекцияЗначений;
КонецФункции
//.
// Параметры:
// МакетКомпоновки - МакетКомпоновкиДанных -
// СхемаКолонок - Структура, Неопределено -
// Возвращаемое значение:
// Структура -
Функция СхемаКолонокМакетаКомпоновкиЛкс(МакетКомпоновки, СхемаКолонок = Неопределено) Экспорт
// Схема колонок строится негарантировано, т.к. платформа не предоставляет нужных данных
Если СхемаКолонок = Неопределено Тогда
СхемаКолонок = Новый Структура;
КонецЕсли;
СхемаКолонок.Очистить();
ОписанияМакетовОбластей = МакетКомпоновки.Макеты;
Если ОписанияМакетовОбластей.Количество() > 0 Тогда
ЯчейкиЗаголовка = ОписанияМакетовОбластей[0].Макет.Ячейки;
КоличествоЯчеекЗаголовка = ЯчейкиЗаголовка.Количество();
Для Индекс = 0 По КоличествоЯчеекЗаголовка - 1 Цикл
Для Каждого ОписаниеМакетаОбласти Из ОписанияМакетовОбластей Цикл
ЯчейкаМакетаОбласти = ОписаниеМакетаОбласти.Макет.Ячейки[Индекс];
Если ТипЗнч(ЯчейкаМакетаОбласти) <> Тип("ЯчейкаМакетаКоллекцииЗначенийОбластиКомпоновкиДанных") Тогда
Продолжить;
КонецЕсли;
ПараметрЯчейки = ЯчейкаМакетаОбласти.Значение; // Ошибочное описание типа в платформе
Если ПараметрЯчейки = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяКолонки = ЯчейкиЗаголовка[Индекс].Имя;
Выражение = ОписаниеМакетаОбласти.Параметры["" + ПараметрЯчейки].Выражение;
ПозицияТочки = Найти(Выражение, ".");
Если Ложь
Или ПозицияТочки = 0
Или Найти(Выражение, " ") > 0
Или Найти(Выражение, "(") > 0
Тогда
ПутьКДанным = ИмяКолонки;
//Продолжить;
Иначе
ПутьКДанным = Сред(Выражение, ПозицияТочки + 1);
КонецЕсли;
СхемаКолонок.Вставить(ИмяКолонки, ПутьКДанным);
Прервать;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат СхемаКолонок;
КонецФункции
Функция СкомпоноватьВТабличныйДокументЛкс(СхемаКомпоновки, НастройкаКомпоновки, Знач ТабличныйДокумент = Неопределено, ВнешниеНаборыДанных = Неопределено,
ДанныеРасшифровки = Неопределено, АвтофиксацияШапки = Истина, ПроверятьДоступностьПолей = Ложь, ВстроитьЗначенияПолейВРасшифровки = Ложь, ДобавитьРасшифровкиДляПолейИтогов = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
Если НастройкаКомпоновки.Структура.Количество() = 0 Тогда
НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(НастройкаКомпоновки.Структура);
КонецЕсли;
Если ДанныеРасшифровки = Неопределено Тогда
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = СобратьМакетКомпоновкиЛкс(СхемаКомпоновки, НастройкаКомпоновки, ВнешниеНаборыДанных,,, ПроверятьДоступностьПолей,,, ДанныеРасшифровки,, Тип("ГенераторМакетаКомпоновкиДанных"),
ДобавитьРасшифровкиДляПолейИтогов);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
Попытка
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
Исключение
ОбработатьОшибкиКомпоновкиПлатформыЛкс(ИнформацияОбОшибке(), МакетКомпоновки, НастройкаКомпоновки);
ВызватьИсключение;
КонецПопытки;
Если ТабличныйДокумент = Неопределено Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
КонецЕсли;
ВывестиРезультатКомпоновкиСАвтофиксациейСтрокЛкс(ТабличныйДокумент, ПроцессорКомпоновки, ДанныеРасшифровки,,, АвтофиксацияШапки);
Если ВстроитьЗначенияПолейВРасшифровки Тогда
Для НомерСтроки = 1 По ТабличныйДокумент.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл
Ячейка = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки);
ИдентификаторРасшифровки = Ячейка.Расшифровка;
Если ТипЗнч(ИдентификаторРасшифровки) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
ЗначенияПолей = ДанныеРасшифровки.Элементы[ИдентификаторРасшифровки].ПолучитьПоля();
Если Истина
И ЗначенияПолей.Количество() > 0
И ТипЗнч(ЗначенияПолей[0].Значение) <> Тип("Строка")
Тогда
Ячейка.Расшифровка = ЗначенияПолей[0].Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Возврат ТабличныйДокумент;
КонецФункции
Функция СмещенныйЦветЛкс(Знач Цвет, Знач СмещениеКрасный = -20, Знач СмещениеЗеленый = 0, Знач СмещениеСиний = -20, Знач ЦветСтиля = Неопределено) Экспорт
Если Цвет.Вид = ВидЦвета.АвтоЦвет Тогда
Если ЦветСтиля = Неопределено Тогда
ЦветСтиля = ЦветаСтиля.ЦветФонаПоля;
КонецЕсли;
Цвет = ЦветСтиля;
КонецЕсли;
АбсолютныйЦвет = ирКэш.АбсолютныйЦветЛкс(ЗначениеВСтрокуВнутр(Цвет));
#Если Сервер И Не Сервер Тогда
АбсолютныйЦвет = Новый Цвет;
#КонецЕсли
СмещенныйЦвет = Новый Цвет(
Макс(0, Мин(255, АбсолютныйЦвет.Красный + СмещениеКрасный)),
Макс(0, Мин(255, АбсолютныйЦвет.Зеленый + СмещениеЗеленый)),
Макс(0, Мин(255, АбсолютныйЦвет.Синий + СмещениеСиний)));
Возврат СмещенныйЦвет;
КонецФункции
Функция ПредставлениеСочетанияКлавишЛкс(Знач СочетаниеКлавиш, Знач ПредставлениеПустого = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
СочетаниеКлавиш = Новый СочетаниеКлавиш;
#КонецЕсли
Представление = "";
Если СочетаниеКлавиш.Alt Тогда
Представление = Представление + "Alt+";
КонецЕсли;
Если СочетаниеКлавиш.Ctrl Тогда
Представление = Представление + "Ctrl+";
КонецЕсли;
Если СочетаниеКлавиш.Shift Тогда
Представление = Представление + "Shift+";
КонецЕсли;
ПредставлениеКлавиши = "" + СочетаниеКлавиш.Клавиша;
Если Не ЗначениеЗаполнено(ПредставлениеКлавиши) Тогда
// Например системная кнопка "Удалить текущий элемент (Alt+Shift+Del)" статического списка
Строка = ОбъектВСтрокуXMLЛкс(СочетаниеКлавиш, Истина);
ОбъектXDTO = ОбъектXDTOИзСтрокиXMLЛкс(Строка);
ПредставлениеКлавиши = ОбъектXDTO.Key;
Иначе
Если Истина
И СочетаниеКлавиш.Клавиша = Клавиша.Нет
И ПредставлениеПустого <> Неопределено
Тогда
ПредставлениеКлавиши = ПредставлениеПустого;
КонецЕсли;
КонецЕсли;
Представление = Представление + ПредставлениеКлавиши;
Возврат Представление;
КонецФункции
//.
// Параметры:
// ДляВсехПользователей - Булево -
// Возвращаемое значение:
// Строка - если пустая, то для текущего пользователя
Функция ИмяПользователяДляХраненияНастроек(Знач ДляВсехПользователей = Ложь, Знач ИмяПользователя = "") Экспорт
Если Истина
И ДляВсехПользователей
И (Ложь
Или ирКэш.НомерВерсииПлатформыЛкс() < 803001
Или ПривилегированныйРежим()
Или ПравоДоступа("АдминистрированиеДанных", Метаданные))
Тогда
ИмяПользователя = ирКэш.ИмяПродукта();
Иначе
//ИмяПользователя = Неопределено; // Такое значение вызывает ошибки у нестандартных хранилищ
Если ПустаяСтрока(ИмяПользователя) Тогда
ИмяПользователя = ИмяПользователя();
Если ПустаяСтрока(ИмяПользователя) Тогда
ИмяПользователя = "<пустой>";
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат ИмяПользователя;
КонецФункции
#КонецЕсли
// Функция - Восстановить значение лкс
//
// Параметры:
// КлючНастроек - -
// ДляВсехПользователей - -
// ХранитьНаКлиенте - Булево - при "Истина" в толстом клиенте хранить настройку на текущем компьютере, иначе - в БД
//
// Возвращаемое значение:
// -
//
Функция ВосстановитьЗначениеЛкс(КлючНастроек, ДляВсехПользователей = Ложь, Знач ХранитьНаКомпьютере = Ложь) Экспорт
#Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда
Возврат ВосстановитьЗначениеЛкс(КлючНастроек);
#Иначе
Если ХранитьНаКомпьютере Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
НастройкиКомпьютера = мПлатформа.НастройкиКомпьютера();
Результат = НастройкиКомпьютера[КлючНастроек];
Иначе
УстановитьПривилегированныйРежим(Истина);
ИмяПользователя = ИмяПользователяДляХраненияНастроек(ДляВсехПользователей, ИмяПользователя);
Результат = ХранилищеОбщихНастроек.Загрузить(ирКэш.ИмяПродукта(), КлючНастроек,, ИмяПользователя);
#Если Клиент Тогда
Если Результат = Неопределено Тогда
// Импорт из старого хранилища настроек
Результат = ВосстановитьЗначение(КлючНастроек);
Если Результат <> Неопределено Тогда
СохранитьЗначениеЛкс(КлючНастроек, Результат);
СохранитьЗначение(КлючНастроек, Неопределено);
КонецЕсли;
КонецЕсли;
#КонецЕсли
КонецЕсли;
Возврат Результат;
#КонецЕсли
КонецФункции
// Функция - Сохранить значение лкс
//
// Параметры:
// КлючНастроек - -
// Значение - -
// ДляВсехПользователей - -
// ХранитьНаКомпьютере - - ХранитьНаКлиенте - Булево - при "Истина" в толстом клиенте хранить настройку на текущем компьютере, иначе - в БД
// ИмяПользователя - Строка - если пустая, то для текущего пользователя
//
Функция СохранитьЗначениеЛкс(КлючНастроек, Значение, ДляВсехПользователей = Ложь, Знач ХранитьНаКомпьютере = Ложь, Знач ИмяПользователя = "") Экспорт
#Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда
ирСервер.СохранитьЗначениеЛкс(КлючНастроек, Значение);
#Иначе
Если ХранитьНаКомпьютере Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
НастройкиКомпьютера = мПлатформа.НастройкиКомпьютера();
НастройкиКомпьютера.Вставить(КлючНастроек, Значение);
мПлатформа.СохранитьНастройкиКомпьтера();
Иначе
УстановитьПривилегированныйРежим(Истина);
ИмяПользователя = ИмяПользователяДляХраненияНастроек(ДляВсехПользователей, ИмяПользователя);
ХранилищеОбщихНастроек.Сохранить(ирКэш.ИмяПродукта(), КлючНастроек, Значение,, ИмяПользователя);
КонецЕсли;
#КонецЕсли
Возврат Неопределено; // нужно для вызова из точки останова
КонецФункции
Функция УдалитьХранимуюНастройкуЛкс(КлючНастроек, ДляВсехПользователей = Ложь) Экспорт
#Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда
ирСервер.УдалитьХранимуюНастройкуЛкс(КлючНастроек);
#Иначе
Если ДляВсехПользователей И ПравоДоступа("АдминистрированиеДанных", Метаданные) Тогда
ИмяПользователя = ирКэш.ИмяПродукта();
Иначе
//ИмяПользователя = Неопределено; // Такое значение вызывает ошибки у нестандартных хранилищ
ИмяПользователя = ИмяПользователя();
КонецЕсли;
ХранилищеОбщихНастроек.Удалить(ирКэш.ИмяПродукта(), КлючНастроек, ИмяПользователя);
#КонецЕсли
КонецФункции
Функция ДобавитьИндексВТаблицуЛкс(ТаблицаЗначений, Знач СтрокаИлиСтруктура) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
Если ТипЗнч(СтрокаИлиСтруктура) = Тип("Структура") Тогда
// Из-за негарантированного порядка элементов можно получать разные имена одного по содержанию индекса. Поэтому могут создаваться дубли индексов
СтрокаИндекса = "";
Разделитель = ", ";
Для Каждого КлючИЗначение Из СтрокаИлиСтруктура Цикл
СтрокаИндекса = СтрокаИндекса + Разделитель + КлючИЗначение.Ключ;
КонецЦикла;
СтрокаИндекса = Сред(СтрокаИндекса, СтрДлина(Разделитель) + 1);
Иначе
СтрокаИндекса = СтрокаИлиСтруктура;
КонецЕсли;
НСтрокаИндекса = НРег(СтрокаИндекса);
НовыйИндекс = Неопределено;
Для Каждого Индекс Из ТаблицаЗначений.Индексы Цикл
Если НРег(Индекс) = НСтрокаИндекса Тогда
НовыйИндекс = Индекс;
Прервать;
КонецЕсли;
КонецЦикла;
Если НовыйИндекс = Неопределено Тогда
НовыйИндекс = ТаблицаЗначений.Индексы.Добавить(СтрокаИндекса);
Если "" + НовыйИндекс <> СтрокаИндекса Тогда
ВызватьИсключение "Поля в составе индекса должны быть разделены запятой и пробелом";
КонецЕсли;
КонецЕсли;
Возврат НовыйИндекс;
КонецФункции
Процедура ОбновитьКопиюСвойстваВНижнемРегистреЛкс(Объект, ИмяСвойства = "Имя") Экспорт
Объект["Н" + ИмяСвойства] = НРег(Объект[ИмяСвойства]);
КонецПроцедуры
// Процедура - Обновить копию колонки в нижнем регистре лкс
//
// Параметры:
// Таблица - -
// ИмяКолонки - -
// НИмяКолонки - -
// ТолькоНовую - Булево -
// ТолькоПустые - Булево - заполнять только пустые значения копии колонки, для ускорения
//
Процедура ОбновитьКопиюКолонкиВНижнемРегистреЛкс(Знач Таблица, Знач ИмяКолонки = "Имя", НИмяКолонки = Неопределено, Знач ТолькоНовую = Ложь, Знач ТолькоПустые = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
//! НИмяКолонки = 0 // - нужно для работы подсказки по втором параметре
Если НИмяКолонки = Неопределено Тогда
НИмяКолонки = "Н" + ИмяКолонки;
КонецЕсли;
Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда
Если Таблица.Колонки.Найти(НИмяКолонки) = Неопределено Тогда
Таблица.Колонки.Добавить(НИмяКолонки, Новый ОписаниеТипов("Строка"));
Таблица.Индексы.Добавить(НИмяКолонки);
ИначеЕсли ТолькоНовую Тогда
Возврат;
КонецЕсли;
КонецЕсли;
Если Не ТолькоНовую И ТолькоПустые Тогда
Таблица = Таблица.НайтиСтроки(Новый Структура(НИмяКолонки, ""));
КонецЕсли;
// В одно строку для ускорения
Для Каждого Строка Из Таблица Цикл Строка[НИмяКолонки] = НРег(Строка[ИмяКолонки]) КонецЦикла;
КонецПроцедуры
Функция ТекущаяДатаЛкс(НаСервере = Ложь, КэшироватьРазницуКлиентСервера = Ложь) Экспорт
Если НаСервере Тогда
Если КэшироватьРазницуКлиентСервера Тогда
Результат = ТекущаяДата() - ирКэш.РазницаВремениКлиентСерверЛкс();
Иначе
Результат = ирСервер.ТекущаяДатаЛкс();
КонецЕсли;
Иначе
Результат = ТекущаяДата();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ДатаОбновленияКэшаМодулейЛкс(Знач ПапкаКэша = "") Экспорт
мПлатформа = ирКэш.Получить();
Если Не ЗначениеЗаполнено(ПапкаКэша) Тогда
ПапкаКэша = мПлатформа.ПапкаКэшаМодулей.ПолноеИмя;
КонецЕсли;
КонтрольныйФайл = Новый Файл(ПапкаКэша + "\" + мПлатформа.ИмяКонтрольногоФайлаКэшаМодулей());
ПапкаКэша = Новый Файл(ПапкаКэша);
Попытка
ДатаОбновленияКэша = КонтрольныйФайл.ПолучитьВремяИзменения();
Исключение
Если ПапкаКэша.Существует() Тогда
ДатаОбновленияКэша = Дата(1,1,1);
Иначе
ДатаОбновленияКэша = Неопределено;
КонецЕсли;
КонецПопытки;
Возврат ДатаОбновленияКэша;
КонецФункции
Функция РазницаВремениКлиентСерверЛкс() Экспорт
Возврат ТекущаяДатаЛкс() - ТекущаяДатаЛкс(Истина);
КонецФункции
Функция СтрокиРавныЛкс(Знач Строка1, Знач Строка2, СУчетомРегистра = Ложь, БезПравыхНепечатныхСимволов = Ложь) Экспорт
Если Ложь
//Или ирКэш.РежимОтладкиЛкс() // Закомментировано для ускорения
Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Если Не СУчетомРегистра Тогда
Строка1 = НРег(Строка1);
Строка2 = НРег(Строка2);
КонецЕсли;
Если БезПравыхНепечатныхСимволов Тогда
Строка1 = СокрП(Строка1);
Строка2 = СокрП(Строка2);
КонецЕсли;
Возврат Строка1 = Строка2;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если Не СУчетомРегистра Тогда Строка1 = НРег(Строка1); Строка2 = НРег(Строка2); КонецЕсли; Если БезПравыхНепечатныхСимволов Тогда Строка1 = СокрП(Строка1); Строка2 = СокрП(Строка2); КонецЕсли; Возврат Строка1 = Строка2;
КонецЕсли;
КонецФункции
// Вставляет параметры в строку, учитывая, что в параметрах могут использоваться подстановочные слова %1, %2 и т.д.
Функция ПодставитьПараметрыСПроцентомЛкс(Знач СтрокаПодстановки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено)
Результат = "";
Позиция = СтрНайтиЛкс(СтрокаПодстановки, "%");
Пока Позиция > 0 Цикл
Результат = Результат + Лев(СтрокаПодстановки, Позиция - 1);
СимволПослеПроцента = Сред(СтрокаПодстановки, Позиция + 1, 1);
ПодставляемыйПараметр = Неопределено;
Если СимволПослеПроцента = "1" Тогда
ПодставляемыйПараметр = Параметр1;
ИначеЕсли СимволПослеПроцента = "2" Тогда
ПодставляемыйПараметр = Параметр2;
ИначеЕсли СимволПослеПроцента = "3" Тогда
ПодставляемыйПараметр = Параметр3;
ИначеЕсли СимволПослеПроцента = "4" Тогда
ПодставляемыйПараметр = Параметр4;
ИначеЕсли СимволПослеПроцента = "5" Тогда
ПодставляемыйПараметр = Параметр5;
ИначеЕсли СимволПослеПроцента = "6" Тогда
ПодставляемыйПараметр = Параметр6;
КонецЕсли;
Если ПодставляемыйПараметр = Неопределено Тогда
Результат = Результат + "%";
СтрокаПодстановки = Сред(СтрокаПодстановки, Позиция + 1);
Иначе
Результат = Результат + ПодставляемыйПараметр;
СтрокаПодстановки = Сред(СтрокаПодстановки, Позиция + 2);
КонецЕсли;
Позиция = СтрНайтиЛкс(СтрокаПодстановки, "%");
КонецЦикла;
Результат = Результат + СтрокаПодстановки;
Возврат Результат;
КонецФункции
// Подставляет параметры в строку. Максимально возможное число параметров - 6.
// Параметры в строке задаются как %<НомерПараметра>. Нумерация параметров начинается с единицы.
//
// Параметры:
// ШаблонСтроки - Строка - шаблон строки с параметрами (вхождениями вида "%<НомерПараметра>",
// например "%1 пошел в %2");
// Параметр - Строка - значение подставляемого параметра.
//
// Возвращаемое значение:
// Строка - текстовая строка с подставленными параметрами.
//
// Пример:
// СтрШаблонЛкс(НСтр("ru='%1 пошел в %2'"), "Вася", "Зоопарк") = "Вася пошел в Зоопарк".
//
Функция СтрШаблонЛкс(Знач ШаблонСтроки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено) Экспорт
ЕстьПараметрыСПроцентом = СтрНайтиЛкс(Параметр1, "%")
Или СтрНайтиЛкс(Параметр2, "%")
Или СтрНайтиЛкс(Параметр3, "%")
Или СтрНайтиЛкс(Параметр4, "%")
Или СтрНайтиЛкс(Параметр5, "%")
Или СтрНайтиЛкс(Параметр6, "%");
Если ЕстьПараметрыСПроцентом Тогда
Возврат ПодставитьПараметрыСПроцентомЛкс(ШаблонСтроки, Параметр1, Параметр2, Параметр3, Параметр4, Параметр5, Параметр6);
КонецЕсли;
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%1", Параметр1);
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%2", Параметр2);
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%3", Параметр3);
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%4", Параметр4);
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%5", Параметр5);
ШаблонСтроки = СтрЗаменить(ШаблонСтроки, "%6", Параметр6);
Возврат ШаблонСтроки;
КонецФункции
// Подставляет именованные параметры в строку. Максимально возможное число параметров - 6.
// Располагать поглощаемые имена следует после поглощающих, например "ЧислоБольшое, Число".
//
// Параметры:
// ШаблонСтроки - Строка - шаблон строки с параметрами (вхождениями вида "%<имя параметра>")
// Имя - Строка - имя подставляемого параметра, может начинаться с цифры
// Значение - Произвольное - значение подставляемого параметра, оно автоматчиески обрамляется кавычками, если Истина
// И не является числом или датой
// И пустое или содержит пробел или имя начинается с заглавной буквы или не буквы, кроме "0"
//
// Возвращаемое значение:
// Строка - текстовая строка с подставленными параметрами.
//
// Пример:
// СтрШаблонИменЛкс("У номенклатуры ""%Ном"" нет остатка на складке ""%Склад""", "Ном", "Ручка шариковая", "Склад", "Москва")
// = "У номенклатуры "Ручка шариковая" нет остатка на складке "Москва""
// СтрШаблонИменЛкс("У номенклатуры ""%1"" нет остатка на складке ""%2""", 1, "Ручка шариковая", 2, "Москва")
// = "У номенклатуры "Ручка шариковая" нет остатка на складке "Москва""
//
Функция СтрШаблонИменЛкс(Знач ШаблонСтроки,
Знач Имя1 = "1", Знач Значение1, Знач Имя2 = "", Знач Значение2 = Неопределено, Знач Имя3 = "", Знач Значение3 = Неопределено,
Знач Имя4 = "", Знач Значение4 = Неопределено, Знач Имя5 = "", Знач Значение5 = Неопределено, Знач Имя6 = "", Знач Значение6 = Неопределено) Экспорт
Если ЗначениеЗаполнено(Имя1) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя1, ПредставлениеДляПодстановки(Значение1)) КонецЕсли;
Если ЗначениеЗаполнено(Имя2) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя2, ПредставлениеДляПодстановки(Значение2)) КонецЕсли;
Если ЗначениеЗаполнено(Имя3) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя3, ПредставлениеДляПодстановки(Значение3)) КонецЕсли;
Если ЗначениеЗаполнено(Имя4) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя4, ПредставлениеДляПодстановки(Значение4)) КонецЕсли;
Если ЗначениеЗаполнено(Имя5) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя5, ПредставлениеДляПодстановки(Значение5)) КонецЕсли;
Если ЗначениеЗаполнено(Имя6) Тогда ШаблонСтроки = СтрЗаменитьЛкс(ШаблонСтроки, "%" + Имя6, ПредставлениеДляПодстановки(Значение6)) КонецЕсли;
Возврат ШаблонСтроки;
КонецФункции
Функция ПредставлениеДляПодстановки(Знач Значение)
Если ТипЗнч(Значение) = Тип("Число") Тогда
#Если ВебКлиент Тогда
Результат = "" + Значение;
#Иначе
Результат = XMLСтрока(Значение);
#КонецЕсли
Иначе
Результат = "" + Значение;
Если Истина
И ТипЗнч(Значение) <> Тип("Дата")
И Лев(Результат, 1) <> """"
И (Ложь
Или (Истина
// Первый символ - заглавная буква или не буква, кроме "0"
И Лев(Результат, 1) <> "0"
И Лев(Результат, 1) = ВРег(Лев(Результат, 1)))
Или ПустаяСтрока(Результат)
Или Найти(Результат, " ") > 0)
Тогда
Результат = """" + Результат + """";
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция собирает строку из элементов массива с разделителем.
// Параметры:
// МассивИлиСписок - -
// Разделитель - -
// КоличествоЭлементов - Число - если отрицательное, то вычитается из полного количества
// НачальныйНомер - Число - с какого элемента начинать сборку
// Шаблон - Строка - подставлять в шаблон элемент массива и собирать результаты
// ИмяСвойства - Строка - какое свойство взять от каждого элемента; по умолчанию берется сам элемент
// Возвращаемое значение:
// Строка - .
Функция СтрСоединитьЛкс(Знач МассивИлиСписок, Знач Разделитель = ", ", Знач КоличествоЭлементов = 0, Знач НачальныйНомер = 1, Знач Шаблон = "", Знач ИмяСвойства = "") Экспорт
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Если ТипЗнч(МассивИлиСписок) = Тип("СписокЗначений") И ПустаяСтрока(ИмяСвойства) Тогда
МассивИлиСписок = МассивИлиСписок.ВыгрузитьЗначения();
КонецЕсли;
// Этот способ медленнее!
//Если Истина
// И ЛиДоступенМодуль83()
// И КоличествоЭлементов = 0
// И НачальныйНомер = 1
// И Шаблон = ""
//Тогда
// Возврат ирОбщий83.СтрСоединитьЛкс(МассивИлиСписок, Разделитель);
//КонецЕсли;
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
Пустая = Истина;
Если КоличествоЭлементов < 0 Тогда
КоличествоЭлементов = МассивИлиСписок.Количество() + КоличествоЭлементов;
КонецЕсли;
ЛиШаблон = ЗначениеЗаполнено(Шаблон);
Счетчик = 0;
Для Каждого Элемент Из МассивИлиСписок Цикл
Счетчик = Счетчик + 1;
Если Счетчик < НачальныйНомер Тогда
Продолжить;
КонецЕсли;
Если Не Пустая Тогда
ЗаписьXML.ЗаписатьБезОбработки(Разделитель);
Иначе
Пустая = Ложь;
КонецЕсли;
Если ЗначениеЗаполнено(ИмяСвойства) Тогда
Элемент = Элемент[ИмяСвойства];
КонецЕсли;
Если ЛиШаблон Тогда
Элемент = СтрШаблонЛкс(Шаблон, Элемент);
КонецЕсли;
ЗаписьXML.ЗаписатьБезОбработки("" + Элемент);
Если КоличествоЭлементов = Счетчик Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Результат = ЗаписьXML.Закрыть();
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Если ТипЗнч(МассивИлиСписок) = Тип("СписокЗначений") И ПустаяСтрока(ИмяСвойства) Тогда МассивИлиСписок = МассивИлиСписок.ВыгрузитьЗначения(); КонецЕсли; ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.УстановитьСтроку(); Пустая = Истина; Если КоличествоЭлементов < 0 Тогда КоличествоЭлементов = МассивИлиСписок.Количество() + КоличествоЭлементов; КонецЕсли; ЛиШаблон = ЗначениеЗаполнено(Шаблон); Счетчик = 0; Для Каждого Элемент Из МассивИлиСписок Цикл Счетчик = Счетчик + 1; Если Счетчик < НачальныйНомер Тогда Продолжить; КонецЕсли; Если Не Пустая Тогда ЗаписьXML.ЗаписатьБезОбработки(Разделитель); Иначе Пустая = Ложь; КонецЕсли; Если ЗначениеЗаполнено(ИмяСвойства) Тогда Элемент = Элемент[ИмяСвойства]; КонецЕсли; Если ЛиШаблон Тогда Элемент = СтрШаблонЛкс(Шаблон, Элемент); КонецЕсли; ЗаписьXML.ЗаписатьБезОбработки("" + Элемент); Если КоличествоЭлементов = Счетчик Тогда Прервать; КонецЕсли; КонецЦикла; Результат = ЗаписьXML.Закрыть();
КонецЕсли;
Возврат Результат;
КонецФункции
// .
// Параметры:
// Текст - Строка -
// РазрешитьПотерюКомментариев - Булево - если Истина, то быстрее
//
// Возвращаемое значение:
// Строка -
//
Функция ТекстИзВстроенногоЯзыкаЛкс(Знач Текст, Знач РазрешитьПотерюКомментариев = Истина) Экспорт
Если Не Лев(Текст, 1) = """" Тогда
Возврат Неопределено;
КонецЕсли;
Если Ложь
Или Прав(Текст, 1) <> """"
Или СтрДлина(Текст) = 1
Тогда
Текст = СокрП(Текст) + """";
КонецЕсли;
Если Найти(Текст, Символы.ПС) = 0 Тогда
// быстро и безопасно, но без поддержки многострочного литерала
Текст = СтрЗаменить(Текст, """""", """");
Если Лев(Текст, 1) = """" Тогда
Текст = Сред(Текст, 2);
КонецЕсли;
Если Прав(Текст, 1) = """" Тогда
Текст = Лев(Текст, СтрДлина(Текст) - 1);
КонецЕсли;
Иначе
Если Найти(Текст, "#") > 0 Или Не РазрешитьПотерюКомментариев Тогда
мПлатформа = ирКэш.Получить();
Текст = мПлатформа.ЗамаскироватьДирективыПрепроцессора(Текст);
КонецЕсли;
Попытка
Текст = Вычислить(Текст);
Исключение
Текст = Неопределено;
КонецПопытки;
КонецЕсли;
Возврат Текст;
КонецФункции
Функция ТекстВВыражениеВстроенногоЯзыкаЛкс(Знач Текст, Знач ДобавлятьПалки = Истина, Знач РазмаскироватьДирективыПрепроцессора = Истина) Экспорт
Если ДобавлятьПалки Тогда
Текст = СтрЗаменить(Текст, Символы.ПС, Символы.ПС + "|");
КонецЕсли;
Текст = """" + СтрЗаменить(Текст, """", """""") + """";
Если РазмаскироватьДирективыПрепроцессора И Найти(Текст, "#") > 0 Тогда
мПлатформа = ирКэш.Получить();
Текст = мПлатформа.РазмаскироватьДирективыПрепроцессора(Текст);
КонецЕсли;
Возврат Текст;
КонецФункции
Функция УдалитьВнешниеСкобкиВыраженияЛкс(Знач ОпределениеПоля, Знач ОткрывающаяСкобка = "(", Знач ЗакрывающаяСкобка = ")", Знач ВсеУровни = Истина) Экспорт
ДлинаОткрытия = СтрДлина(ОткрывающаяСкобка);
ДлинаЗакрытия = СтрДлина(ЗакрывающаяСкобка);
Пока Истина
И Лев(ОпределениеПоля, ДлинаОткрытия) = ОткрывающаяСкобка
И Прав(ОпределениеПоля, ДлинаЗакрытия) = ЗакрывающаяСкобка
Цикл
ОпределениеПоля = Сред(ОпределениеПоля, 1 + ДлинаОткрытия, СтрДлина(ОпределениеПоля) - ДлинаОткрытия - ДлинаЗакрытия);
Если Не ВсеУровни Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ОпределениеПоля;
КонецФункции
// Поиск числа в строке
//
// Параметры:
// ИсходнаяСтрока - Строка, строка в которой ищется число
// ПозицияЧисла - Число, позиция начала числа
// КоличествоСимволов - Число, количество символов числа
//
// Возвращаемое значение:
// Булево - Истина, число найдено
//
Функция НайтиЧислоВСтрокеЛкс(ИсходнаяСтрока, выхПозицияЧисла = 0, выхКоличествоСимволов = 0) Экспорт
выхПозицияЧисла = 0;
выхКоличествоСимволов = 0;
ДлинаСтроки = СтрДлина(ИсходнаяСтрока);
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
// 300000 повторов при заполнении общей таблицы полей в структуре хранения БД
Для Сч = 1 По ДлинаСтроки Цикл
ТекущийСимвол = КодСимвола(Сред(ИсходнаяСтрока, Сч, 1));
Если 48 <= ТекущийСимвол И ТекущийСимвол <= 57 Тогда
Если выхПозицияЧисла = 0 Тогда
выхПозицияЧисла = Сч;
выхКоличествоСимволов = 1;
Иначе
выхКоличествоСимволов = выхКоличествоСимволов + 1;
КонецЕсли;
Иначе
Если выхПозицияЧисла <> 0 Тогда
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Сч = 1 По ДлинаСтроки Цикл ТекущийСимвол = КодСимвола(Сред(ИсходнаяСтрока, Сч, 1)); Если 48 <= ТекущийСимвол И ТекущийСимвол <= 57 Тогда Если выхПозицияЧисла = 0 Тогда выхПозицияЧисла = Сч; выхКоличествоСимволов = 1; Иначе выхКоличествоСимволов = выхКоличествоСимволов + 1; КонецЕсли; Иначе Если выхПозицияЧисла <> 0 Тогда Прервать; КонецЕсли; КонецЕсли; КонецЦикла;
КонецЕсли;
Возврат выхПозицияЧисла > 0;
КонецФункции
Функция ЭтоКорректныйСимволИмениПеременнойЛкс(Символ, Вычислитель = Неопределено) Экспорт
Если Вычислитель = Неопределено Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Вычислитель = ирКэш.ВычислительРегВыраженийЛкс();
Вычислитель.Pattern = "[" + мПлатформа.шБуква + "\d]";
КонецЕсли;
Результат = Вычислитель.Проверить(Символ);
//Код = КодСимвола(Символ, 1);
//Результат = (Код <= 57 И Код >= 48) ИЛИ (Код <= 90 И Код >= 65) ИЛИ (Код <= 122 И Код >= 97) ИЛИ (Код <= 1103 И Код >= 1040) ИЛИ Код = 95;
Возврат Результат;
КонецФункции
Функция ОписаниеОСЛкс() Экспорт
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
ПространствоИмен = ирКэш.ПолучитьCOMОбъектWMIЛкс();
ВыборкаОС = ПространствоИмен.ExecQuery("Select * from Win32_OperatingSystem");
Для Каждого ОперационнаяСистема Из ВыборкаОС Цикл
Прервать;
КонецЦикла;
Результат = ОперационнаяСистема.Caption;
Результат = Результат + " " + ОперационнаяСистема.OSArchitecture;
Если ОперационнаяСистема.Locale = "0419" Тогда
ОписаниеЯзыка = "Русский";
Иначе
ОписаниеЯзыка = "НеРусский-" + ОперационнаяСистема.Locale;
КонецЕсли;
Результат = Результат + " " + ОписаниеЯзыка;
Иначе
СистемнаяИнфо = Новый СистемнаяИнформация;
Результат = "" + СистемнаяИнфо.ТипПлатформы;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПроверитьКодЯзыкаОСЛкс() Экспорт
ПространствоИмен1 = ирКэш.ПолучитьCOMОбъектWMIЛкс();
ВыборкаОС = ПространствоИмен1.ExecQuery("Select * from Win32_OperatingSystem");
Для Каждого ОперационнаяСистема Из ВыборкаОС Цикл
Прервать;
КонецЦикла;
Если ОперационнаяСистема.Locale <> "0419" Тогда
ВызватьИсключение "Russian system locale (0419) in OS required for this function";
КонецЕсли;
КонецФункции
Функция ЛиСовместимыйЯзыкСистемыЛкс() Экспорт
ТекущийЯзыкСистемы = НРег(ПервыйФрагментЛкс(ТекущийЯзыкСистемы(), "_"));
ЛиСовместимыйЯзыкСистемы = Ложь
Или ТекущийЯзыкСистемы = "ru"
Или ТекущийЯзыкСистемы = "en";
Возврат ЛиСовместимыйЯзыкСистемы;
КонецФункции
Процедура ОчиститьКаталогТехножурналаЛкс(КаталогЖурнала, НаСервере = Ложь, ВыводитьПредупрежденияИСообщения = Истина) Экспорт
#Если Клиент Тогда
Если ВыводитьПредупрежденияИСообщения Тогда
Ответ = КодВозвратаДиалога.ОК;
Если НаСервере Тогда
ОбщийРазмер = ирСервер.ВычислитьРазмерКаталогаЛкс(КаталогЖурнала);
Иначе
ОбщийРазмер = ВычислитьРазмерКаталогаЛкс(КаталогЖурнала);
КонецЕсли;
Если ОбщийРазмер > 0 Тогда
Ответ = Вопрос(СтрШаблонИменЛкс("Действительно удалить рекурсивно все файлы (%1МБ) в каталоге журнала?",, Цел(ОбщийРазмер/1000000)), РежимДиалогаВопрос.ОКОтмена);
КонецЕсли;
Если Ответ <> КодВозвратаДиалога.ОК Тогда
Возврат;
КонецЕсли;
КонецЕсли;
Если НаСервере Тогда
ирСервер.ОчиститьКаталогТехножурналаЛкс(КаталогЖурнала, ВыводитьПредупрежденияИСообщения);
Возврат;
КонецЕсли;
#КонецЕсли
ФайлыЖурнала = НайтиФайлы(КаталогЖурнала, "*.*", Истина);
Если ФайлыЖурнала.Количество() > 0 Тогда
СчетчикНеудаленных = 0;
Для Каждого ФайлЖурнала Из ФайлыЖурнала Цикл
Попытка
УдалитьФайлы(ФайлЖурнала.ПолноеИмя);
Исключение
СчетчикНеудаленных = СчетчикНеудаленных + 1;
КонецПопытки;
КонецЦикла;
Если ВыводитьПредупрежденияИСообщения Тогда
Если СчетчикНеудаленных > 0 Тогда
СообщитьЛкс(СтрШаблонИменЛкс("%1 файлов техножурнала удалить не удалось",, СчетчикНеудаленных));
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры // ОчиститьКаталогТехножурналаЛкс()
Функция ВычислитьРазмерКаталогаЛкс(Каталог, ВключаяПодкаталоги = Истина) Экспорт
Файлы = НайтиФайлы(Каталог, "*.*", ВключаяПодкаталоги);
ОбщийРазмер = 0;
Для Каждого Файл Из Файлы Цикл
// Долго
//Если Файл.ЭтоКаталог() Тогда
// Продолжить;
//КонецЕсли;
Попытка
РазмерФайла = Файл.Размер();
Исключение
// Это каталог или нет доступа к файлу
РазмерФайла = 0;
КонецПопытки;
ОбщийРазмер = ОбщийРазмер + РазмерФайла;
КонецЦикла;
Возврат ОбщийРазмер;
КонецФункции
// Выполняет копирование файлов рекурсивно
Процедура СкопироватьФайлыЛкс(КаталогИсточник, КаталогПриемник) Экспорт
Файлы = НайтиФайлы(КаталогИсточник, "*.*");
Разделитель = РазделительПутиКФайлуЛкс();
Для Каждого Файл Из Файлы Цикл
ФайлПриемник = Новый Файл(КаталогПриемник + Разделитель + Файл.Имя);
Если Файл.ЭтоКаталог() Тогда
СоздатьКаталог(ФайлПриемник.ПолноеИмя);
СкопироватьФайлыЛкс(Файл.ПолноеИмя, ФайлПриемник.ПолноеИмя);
Продолжить;
КонецЕсли;
КопироватьФайл(Файл.ПолноеИмя, ФайлПриемник.ПолноеИмя);
КонецЦикла;
КонецПроцедуры
// Аналог платформенной функции ПолучитьРазделительПути() 8.3.3+
Функция РазделительПутиКФайлуЛкс() Экспорт
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
Разделитель = "\";
Иначе
Разделитель = "/";
КонецЕсли;
Возврат Разделитель;
КонецФункции
Функция ЗначениеПеременнойОкруженияЛкс(СтрокаПеременныхОкружения, Знач ИмяПеременной, Знач ПраваяГраница = Неопределено) Экспорт
Ответ = "";
Если Не ЗначениеЗаполнено(СтрокаПеременныхОкружения) Или Не ЗначениеЗаполнено(ИмяПеременной) Тогда
Возврат Ответ;
КонецЕсли;
Если Не СтрКончаетсяНаЛкс(ИмяПеременной, "=") Тогда
ИмяПеременной = ИмяПеременной + "=";
КонецЕсли;
МассивПеременных = СтрРазделитьЛкс(СтрокаПеременныхОкружения, Символы.ПС, Ложь);
Для Каждого СтрокаПеременной Из МассивПеременных Цикл
Если СтрНачинаетсяСЛкс(СтрокаПеременной, ИмяПеременной) Тогда
Ответ = Сред(СтрокаПеременной, СтрДлина(ИмяПеременной) + 1);
Прервать;
КонецЕсли;
КонецЦикла;
Если ПустаяСтрока(Ответ) Или ПраваяГраница = Неопределено Тогда
Возврат Ответ;
КонецЕсли;
Позиция = Найти(Ответ, ПраваяГраница);
Ответ = Лев(Ответ, Позиция - 1);
Возврат Ответ;
КонецФункции
Процедура УстановитьПометкиРодителейЛкс(Знач Родитель, Знач ИмяДанныхФлажка = "Пометка", НезависимыйРодитель = Ложь) Экспорт
Если Родитель = Неопределено Тогда
Возврат;
КонецЕсли;
ТекСостояние = Родитель[ИмяДанныхФлажка];
НайденыВключенные = Ложь;
НайденыВыключенные = Ложь;
Для каждого Строка из Родитель.Строки Цикл
ЗначениеФлажка = Строка[ИмяДанныхФлажка];
Если ЗначениеФлажка = 0 Тогда
НайденыВыключенные = Истина;
ИначеЕсли ЗначениеФлажка = 1 Тогда
НайденыВключенные = Истина;
ИначеЕсли ЗначениеФлажка = 2 Тогда
НайденыВключенные = Истина;
НайденыВыключенные = Истина;
Прервать;
КонецЕсли;
Если НайденыВключенные И НайденыВыключенные Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Если НезависимыйРодитель Тогда
Если НайденыВключенные Тогда
Включить = 2;
КонецЕсли;
Иначе
Если НайденыВключенные И НайденыВыключенные Тогда
Включить = 2;
ИначеЕсли НайденыВключенные И Не НайденыВыключенные Тогда
Включить = 1;
ИначеЕсли Не НайденыВключенные И НайденыВыключенные Тогда
Включить = 0;
ИначеЕсли Не НайденыВключенные И Не НайденыВыключенные Тогда
Включить = 2;
КонецЕсли;
КонецЕсли;
Если Включить = ТекСостояние Тогда
Возврат;
Иначе
Если Родитель[ИмяДанныхФлажка] <> 1 Или Не НезависимыйРодитель Тогда
Родитель[ИмяДанныхФлажка] = Включить;
УстановитьПометкиРодителейЛкс(Родитель.Родитель, ИмяДанныхФлажка);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура УстановитьПометкиПодчиненныхЛкс(Знач ТекСтрока, Знач ИмяДанныхФлажка = "Пометка") Экспорт
ТекСостояние = ТекСтрока[ИмяДанныхФлажка];
Подчиненные = ТекСтрока.Строки;
Если ТекСостояние = 2 Тогда
ТекСтрока[ИмяДанныхФлажка] = 0;
КонецЕсли;
Если Подчиненные.Количество() > 0 Тогда
Для каждого Строка из Подчиненные Цикл
Строка[ИмяДанныхФлажка] = ТекСостояние;
УстановитьПометкиПодчиненныхЛкс(Строка, ИмяДанныхФлажка);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция ЛиСпискиПодсистемПересекаютсяЛкс(ФильтрПодсистем, СписокПодсистем) Экспорт
Если ТипЗнч(ФильтрПодсистем) = Тип("Строка") Тогда
СписокФильтра = Новый СписокЗначений;
СписокФильтра.Добавить(ФильтрПодсистем);
КонецЕсли;
Если Ложь
Или СписокФильтра.Количество() = 0
Или СписокФильтра[0] = ""
Тогда
Возврат Истина;
КонецЕсли;
Для Каждого Подсистема Из СписокПодсистем Цикл
Если ТипЗнч(Подсистема) = Тип("ОбъектМетаданных") Тогда
ИмяПодсистемы = Подсистема.ПолноеИмя();
Иначе
ИмяПодсистемы = Подсистема.Значение;
КонецЕсли;
Если СписокФильтра.НайтиПоЗначению(ИмяПодсистемы) <> Неопределено Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
// Разбирает строку на две части: до подстроки разделителя и после
//
// Параметры:
// Стр - разбираемая строка
// Разделитель - подстрока-разделитель
// Режим - 0 - разделитель в возвращаемые подстроки не включается
// 1 - разделитель включается в левую подстроку
// 2 - разделитель включается в правую подстроку
//
// Возвращаемое значение:
// Правая часть строки - до символа-разделителя
//
Функция ОтделитьРазделителемЛкс(Знач Стр, Знач Разделитель = ".", Режим = 0) Экспорт
ПраваяЧасть = "";
ПозРазделителя = Найти(Стр, Разделитель);
ДлинаРазделителя = СтрДлина(Разделитель);
Если ПозРазделителя > 0 Тогда
ПраваяЧасть = Сред(Стр, ПозРазделителя + ?(Режим=2, 0, ДлинаРазделителя));
Стр = СокрЛП(Лев(Стр, ПозРазделителя - ?(Режим=1, -ДлинаРазделителя+1, 1)));
КонецЕсли;
Возврат(ПраваяЧасть);
КонецФункции // вОтделитьРазделителем()
// Проверяет попадание даты внутрь интервала всключая границы
Функция ЛиДатаВИнтервалеСГраницамиЛкс(ПроверяемаяДата, НачалоПериода, КонецПериода) Экспорт
ЛиДатаВНеИнтервале = Ложь
Или (Истина
И ЗначениеЗаполнено(НачалоПериода)
И ПроверяемаяДата < НачалоПериода)
Или (Истина
И ЗначениеЗаполнено(КонецПериода)
И ПроверяемаяДата > КонецПериода);
Возврат Не ЛиДатаВНеИнтервале;
КонецФункции
// Проверяет попадание даты внутрь интервала исключая границы
Функция ЛиДатаВИнтервалеБезГраницЛкс(ПроверяемаяДата, НачалоПериода, КонецПериода) Экспорт
ПустаяДата = Дата("00010101");
ЛиДатаВНеИнтервале = Ложь
Или (Истина
И НачалоПериода <> ПустаяДата
И ПроверяемаяДата <= НачалоПериода)
Или (Истина
И КонецПериода <> ПустаяДата
И ПроверяемаяДата >= КонецПериода);
Возврат Не ЛиДатаВНеИнтервале;
КонецФункции
Функция ЛиСобытиеОшибкиФоновогоЗаданияЛкс(ИмяСобытияЖурнала) Экспорт
Результат = Ложь
Или ИмяСобытияЖурнала = "_$Job$_.Fail"
Или ИмяСобытияЖурнала = "_$Job$_.Error";
Возврат Результат;
КонецФункции
Функция ЛиСобытиеУспехаФоновогоЗаданияЛкс(ИмяСобытияЖурнала) Экспорт
Результат = Ложь
Или ИмяСобытияЖурнала = "_$Job$_.Finish"
Или ИмяСобытияЖурнала = "_$Job$_.Succeed";
Возврат Результат;
КонецФункции
Функция ЛиКаталогДоступенЛкс(Каталог, ВыводитьСообщения = Истина) Экспорт
ПроверочныйФайл = Новый Файл(Каталог);
Попытка
ЭтоКаталог = ПроверочныйФайл.ЭтоКаталог();
Исключение
Если ВыводитьСообщения Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Указанный путь %1 не доступен: " + ОписаниеОшибки(),, Каталог));
КонецЕсли;
Возврат Ложь;
КонецПопытки;
Если Не ЭтоКаталог Тогда
Если ВыводитьСообщения Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Указанный путь %1 не является каталогом",, Каталог));
КонецЕсли;
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
// http://www.hostedredmine.com/issues/882395
// Параметры:
// Статус - СтатусСообщения
// ПоказатьОповещениеВУП - Булево - показать оповещение в управляемом приложении - полезно при отказе от открытия формы
// ВывестиОперативноВУП - Булево - сообщение в управляемом приложении будет сначала отображено в спец. окне для отображения в реальном времени. Может приводить к исчезновению сообщений сразу
// после закрытия формы и к открытию в отдельном окне https://www.hostedredmine.com/issues/960907
Процедура СообщитьЛкс(Знач ТекстСообщения, Знач Статус = Неопределено, Знач ТолькоВоВременноеОкно = Ложь, Знач ПоказатьОповещениеВУП = Ложь, Знач ВывестиОперативноВУП = Истина) Экспорт
Если Не ЗначениеЗаполнено(ТекстСообщения) Тогда
Возврат;
КонецЕсли;
ВывестиСообщениеВСпецОкно = Ложь;
#Если Не ВебКлиент И Не ТонкийКлиент Тогда
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если АктивноеОкно() = Неопределено И ирКэш.ОткрытыеФормыПодсистемыЛкс().Количество() = 0 Тогда
// Когда нет активного окна, сообщения выводятся в никуда. Поэтому откроем свое окно.
ОткрытьФорму("Обработка.ирПлатформа.Форма.ВременноеОкноСообщенийУпр",,,,,,, РежимОткрытияОкнаФормы.Независимый);
КонецЕсли;
#КонецЕсли
МодальныеГруппы = МодальныеГруппыЛкс();
Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда
Если ПоказатьОповещениеВУП Тогда
#Если Клиент Тогда
ПоказатьОповещениеПользователя(,, ТекстСообщения);
#КонецЕсли
КонецЕсли;
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
ВывестиСообщениеВСпецОкно = ВывестиОперативноВУП;
Иначе
// https://www.hostedredmine.com/issues/927508
КонецЕсли;
Иначе
ВывестиСообщениеВСпецОкно = МодальныеГруппы.Количество() > 0;
КонецЕсли;
Если ВывестиСообщениеВСпецОкно Тогда
ПрефиксВажности = "";
Если Статус = СтатусСообщения.Внимание Тогда
ПрефиксВажности = "! ";
ИначеЕсли Статус = СтатусСообщения.Важное Тогда
ПрефиксВажности = "!! ";
ИначеЕсли Статус = СтатусСообщения.ОченьВажное Тогда
ПрефиксВажности = "!!! ";
КонецЕсли;
МодальнаяГруппа = МодальныеГруппы.Количество();
#Если ТолстыйКлиентУправляемоеПриложение Тогда
АктивноеОтдельноеОкноОС = АктивноеОтдельноеОкноОСЛкс();
Если АктивноеОтдельноеОкноОС <> Неопределено Тогда
// Без этого сообщение попадет в никуда https://www.hostedredmine.com/issues/947572
МодальнаяГруппа = Макс(1, МодальнаяГруппа);
КонецЕсли;
#КонецЕсли
Форма = ирКэш.ОкноСообщенийЛкс(МодальнаяГруппа);
Форма.ВывестиСообщениеЛкс(ПрефиксВажности + ТекстСообщения);
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если АктивноеОтдельноеОкноОС <> Неопределено И АктивноеОтдельноеОкноОСЛкс() = Неопределено Тогда
АктивноеОтдельноеОкноОС.Активизировать();
КонецЕсли;
#КонецЕсли
КонецЕсли;
#КонецЕсли
Если Не ТолькоВоВременноеОкно Тогда
Сообщить(ТекстСообщения, Статус);
КонецЕсли;
КонецПроцедуры
Функция МодальныеГруппыЛкс() Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
МодальныеГруппы = мПлатформа.МодальныеГруппы;
Возврат МодальныеГруппы;
КонецФункции
Функция ЛиЕстьМодальныеГруппыЛкс() Экспорт
Результат = МодальныеГруппыЛкс().Количество() > 0;
Возврат Результат;
КонецФункции
Функция АктивноеОтдельноеОкноОСЛкс()
Результат = Неопределено;
#Если ТолстыйКлиентУправляемоеПриложение Тогда
АктивноеОкно = АктивноеОкно();
Если АктивноеОкно <> Неопределено И АктивноеОкно.Содержимое.Количество() = 0 Тогда
Результат = АктивноеОкно;
КонецЕсли;
#КонецЕсли
Возврат Результат;
КонецФункции
Процедура СостояниеЛкс(Знач СтрокаСостояния = "", РазрешитьПрерывание = Ложь, ЭтоСостояниеИндикатора = Ложь) Экспорт
Если Не ЭтоСостояниеИндикатора Тогда
ирПлатформа = ирКэш.Получить();
ТаблицаИндикаторов = ирПлатформа.мИндикаторы;
Если ТаблицаИндикаторов.Количество() > 0 Тогда
ОбновитьТекстСостоянияВсехИндикаторовЛкс(ТаблицаИндикаторов);
Индикатор = ТаблицаИндикаторов[ТаблицаИндикаторов.Количество() - 1];
Если ЗначениеЗаполнено(СтрокаСостояния) Тогда
СтрокаСостояния = Символы.ПС + СтрокаСостояния;
КонецЕсли;
СтрокаСостояния = Индикатор.ТекстСостояния + ". " + СтрокаСостояния;
КонецЕсли;
КонецЕсли;
Если РазрешитьПрерывание Тогда
Если ирКэш.НомерВерсииПлатформыЛкс() >= 803018 Тогда
// Работает надежнее https://www.hostedredmine.com/issues/959037
СтрокаСостояния = СтрокаСостояния + ". Прервать Ctrl+Alt+E";
Иначе
СтрокаСостояния = СтрокаСостояния + ". Прервать Ctrl+Break";
КонецЕсли;
КонецЕсли;
#Если Клиент Тогда
ИспользуемПояснение = Ложь;
Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда
Если Не ЗначениеЗаполнено(СтрокаСостояния) Тогда
Возврат;
КонецЕсли;
Если ирКэш.НомерВерсииПлатформыЛкс() >= 803017 Тогда
// http://www.hostedredmine.com/issues/875446
ИспользуемПояснение = Истина;
КонецЕсли;
КонецЕсли;
Если ИспользуемПояснение Тогда
Состояние(,, СтрокаСостояния);
Иначе
СтрокаСостояния = СтрЗаменить(СтрокаСостояния, Символы.ПС, "");
Состояние(СтрокаСостояния);
КонецЕсли;
#КонецЕсли
КонецПроцедуры
Функция ОбновитьТекстСостоянияВсехИндикаторовЛкс(Знач МассивИндикаторов)
ТекстСостояния = "";
Для Каждого лИндикатор Из МассивИндикаторов Цикл
Если ТекстСостояния <> "" Тогда
ТекстСостояния = ТекстСостояния + ".>> ";
КонецЕсли;
ТекстСостояния = ТекстСостояния + ПолучитьТекстСостоянияИндикатораЛкс(лИндикатор);
КонецЦикла;
лИндикатор.ТекстСостояния = ТекстСостояния;
Возврат лИндикатор;
КонецФункции
Функция ПолучитьТекстСостоянияИндикатораЛкс(Индикатор) Экспорт
Счетчик = Индикатор.Счетчик;
Если Истина
И Индикатор.ЛиВыводитьВремя
И Счетчик > 1
И Счетчик <= Индикатор.КоличествоПроходов
Тогда
ТекущаяДата = ТекущаяДата();
ПрошлоВремени = ТекущаяДата - Индикатор.ДатаНачалаПроцесса;
Осталось = ПрошлоВремени * (Индикатор.КоличествоПроходов / Счетчик - 1);
Если ПрошлоВремени > 0 Тогда
ЧислоВСекунду = Счетчик / ПрошлоВремени;
Иначе
ЧислоВСекунду = 0;
КонецЕсли;
ДопТекст = "";
Если ЧислоВСекунду >= 0.1 Тогда
Если ЧислоВСекунду > 1000 Тогда
ТекстЧислоВСекунду = Формат(ЧислоВСекунду/1000, "ЧЦ=3; ЧДЦ=1; ЧРД=.; ЧН=; ЧГ=") + "к";
Иначе
Если ЧислоВСекунду > 10 Тогда
ЧислоДесятичных = 0;
Иначе
ЧислоДесятичных = 1;
КонецЕсли;
ТекстЧислоВСекунду = Формат(ЧислоВСекунду, СтрШаблонЛкс("ЧЦ=3; ЧДЦ=%1; ЧРД=.; ЧН=; ЧГ=", ЧислоДесятичных));
КонецЕсли;
ДопТекст = ДопТекст + ", " + ТекстЧислоВСекунду + "/" + НСтр("ru = 'с'; en = 's'");
КонецЕсли;
ТекстОсталось = "";
ОсталосьДней = Цел(Осталось / (24*60*60));
Если ОсталосьДней > 0 Тогда
ТекстОсталось = ТекстОсталось + ОсталосьДней + НСтр("ru = 'д'; en = 'd'");
КонецЕсли;
ТекстОсталось = ТекстОсталось + формат(Дата(1,1,1) + Осталось, "ДЛФ=T");
Если ЗначениеЗаполнено(ТекстОсталось) Тогда
ДопТекст = ДопТекст + ", ~" + ТекстОсталось;
КонецЕсли;
Иначе
ДопТекст = "";
КонецЕсли;
Если Индикатор.КоличествоПроходов = 1 Тогда
ТекстСостояния = Индикатор.ПредставлениеПроцесса;
ИначеЕсли Индикатор.КоличествоПроходов > 0 Тогда
ТекстСостояния = Индикатор.ПредставлениеПроцесса + ": "
+ Формат(Счетчик / Индикатор.КоличествоПроходов * 100, "ЧЦ=3; ЧДЦ=0; ЧН=") + "%" + ДопТекст;
Иначе
ТекстСостояния = Индикатор.ПредставлениеПроцесса + ": " + Счетчик + " ";
КонецЕсли;
Возврат ТекстСостояния;
КонецФункции
Функция ФильтрДляВыбораФайлаЛкс(Знач СписокРасширений, ОписаниеФормата = "", РазрешитьВсеФайлы = Истина) Экспорт
ТребоватьТипЛкс(СписокРасширений, "СписокРасширений", Тип("Строка"), Тип("СписокЗначений"));
Если ТипЗнч(СписокРасширений) = Тип("Строка") Тогда
МассивРасширений = СтрРазделитьЛкс(СписокРасширений, ",", Истина);
СписокРасширений = Новый СписокЗначений;
СписокРасширений.ЗагрузитьЗначения(МассивРасширений);
КонецЕсли;
Результат = "";
ВсеПоддерживаемые1 = "";
Для Каждого ЭлементСписка Из СписокРасширений Цикл
Расширение = ЭлементСписка.Значение;
Если ЗначениеЗаполнено(ЭлементСписка.Представление) Тогда
ОписаниеФорматаЦикл = ЭлементСписка.Представление;
Иначе
ОписаниеФорматаЦикл = ОписаниеФормата;
КонецЕсли;
Если Результат <> "" Тогда
Результат = Результат + "|";
ВсеПоддерживаемые1 = ВсеПоддерживаемые1 + ";";
КонецЕсли;
ВсеПоддерживаемые1 = ВсеПоддерживаемые1 + "*." + Расширение;
ОписаниеРасширения = "(*." + Расширение + ")|*." + Расширение;
Если ЗначениеЗаполнено(ОписаниеФорматаЦикл) Тогда
ОписаниеРасширения = ОписаниеФорматаЦикл + " " + ОписаниеРасширения;
КонецЕсли;
Результат = Результат + ОписаниеРасширения;
КонецЦикла;
Если СписокРасширений.Количество() > 1 Тогда
ОписаниеРасширения = "Все поддерживаемые (" + ВсеПоддерживаемые1 + ")|" + ВсеПоддерживаемые1;
Результат = ОписаниеРасширения + "|" + Результат;
КонецЕсли;
Если РазрешитьВсеФайлы Тогда
Результат = Результат + "|Все файлы (*.*)|*.*";
КонецЕсли;
Возврат Результат;
КонецФункции
// Копирует все элементы переданного массива, структуры, соответствия, списка значений или коллекции объектов метаданных
// в однотипную коллекцию приемник (для метаданных в массив). Если коллекция приемник не указана, она будет создана.
// Фиксированные коллекции превращаются в нефиксированные.
//
// Параметры:
// КоллекцияИсточник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных - коллекция источник;
// КоллекцияПриемник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных, Неопределено - коллекция приемник.
//
// Возвращаемое значение:
// Произвольный - коллекция приемник.
//
Функция СкопироватьКоллекциюЛкс(КоллекцияИсточник, КоллекцияПриемник = Неопределено, Знач ВыводитьСообщения = Истина) Экспорт
Если КоллекцияИсточник = КоллекцияПриемник И КоллекцияИсточник <> Неопределено Тогда
ВызватьИсключение "Нельзя загружать коллекцию в саму себя";
КонецЕсли;
ТипКоллекции = ТипЗнч(КоллекцияИсточник);
Если Ложь
Или ТипКоллекции = Тип("Структура")
Или ТипКоллекции = Тип("ФиксированнаяСтруктура")
Тогда
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый Структура;
КонецЕсли;
Для Каждого Элемент Из КоллекцияИсточник Цикл
КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
ИначеЕсли Ложь
Или ТипКоллекции = Тип("Массив")
Или ТипКоллекции = Тип("ФиксированныйМассив")
#Если Не ТонкийКлиент И Не ВебКлиент Тогда
Или ТипКоллекции = Тип("КоллекцияОбъектовМетаданных")
#КонецЕсли
Тогда
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый Массив;
КонецЕсли;
Для Каждого Элемент Из КоллекцияИсточник Цикл
КоллекцияПриемник.Добавить(Элемент);
КонецЦикла;
ИначеЕсли Ложь
Или ТипКоллекции = Тип("Соответствие")
Или ТипКоллекции = Тип("ФиксированноеСоответствие")
Тогда
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый Соответствие;
КонецЕсли;
Для Каждого Элемент Из КоллекцияИсточник Цикл
КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение);
КонецЦикла;
ИначеЕсли ТипКоллекции = Тип("СписокЗначений") Тогда
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = Новый СписокЗначений;
КонецЕсли;
Для Каждого Элемент Из КоллекцияИсточник Цикл
ЗаполнитьЗначенияСвойств(КоллекцияПриемник.Добавить(), Элемент);
КонецЦикла;
#Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда
ИначеЕсли ТипКоллекции = Тип("ТаблицаЗначений") Тогда
//! КоллекцияИсточник = 0 // ТаблицаЗначений
Если КоллекцияПриемник = Неопределено Тогда
КоллекцияПриемник = КоллекцияИсточник.СкопироватьКолонки();
КонецЕсли;
ЗагрузитьВТаблицуЗначенийЛкс(КоллекцияИсточник, КоллекцияПриемник);
#КонецЕсли
Иначе
Если ВыводитьСообщения Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Неверный тип универсальной коллекции для копирования %1",, ТипКоллекции));
КонецЕсли;
КоллекцияПриемник = Неопределено;
КонецЕсли;
Возврат КоллекцияПриемник; // см. КоллекцияИсточник
КонецФункции
//.
// Параметры:
// Структура - Структура -
// Возвращаемое значение:
// Структура -
Функция СкопироватьСтруктуруБезЗначенийЛкс(Знач Структура) Экспорт
НоваяСтруктура = Новый Структура;
Для Каждого КлючИЗначение Из Структура Цикл
НоваяСтруктура.Вставить(КлючИЗначение.Ключ);
КонецЦикла;
Возврат НоваяСтруктура;
КонецФункции
//.
// Параметры:
// Отбор - Отбор, ОтборКомпоновкиДанных, ПользовательскиеНастройкиКомпоновкиДанных -
// Возвращаемое значение:
// Булево -
Функция ЛиОтборУстановленЛкс(Отбор) Экспорт
Если ТипЗнч(Отбор) = Тип("ПользовательскиеНастройкиКомпоновкиДанных") Тогда
Для Каждого Элемент Из Отбор.Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ОтборКомпоновкиДанных") Тогда
Если ЛиОтборУстановленЛкс(Элемент) Тогда
Возврат Истина;
КонецЕсли;
ИначеЕсли ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если Элемент.Использование Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Иначе
Если ТипЗнч(Отбор) = Тип("Отбор") Тогда
ЭлементыОтбора = Отбор;
Иначе
ЭлементыОтбора = Отбор.Элементы;
КонецЕсли;
Для Каждого ЭлементОтбора Из ЭлементыОтбора Цикл
Если ЭлементОтбора.Использование Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ЛиЗначениеПроходитЭлементОтбораЛкс(Знач ЭлементОтбора, Знач Значение) Экспорт
#Если Сервер И Не Сервер Тогда
ЭлементОтбора = Новый НастройкиКомпоновкиДанных;
ЭлементОтбора = ЭлементОтбора.Отбор.Элементы.Добавить();
#КонецЕсли
Если ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно Тогда
Результат = Значение = ЭлементОтбора.ПравоеЗначение;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеРавно Тогда
Результат = Значение <> ЭлементОтбора.ПравоеЗначение;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке Тогда
Результат = ЭлементОтбора.ПравоеЗначение.НайтиПоЗначению(Значение) <> Неопределено;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит Тогда
Результат = Найти(Значение, ЭлементОтбора.ПравоеЗначение) > 0;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке Тогда
Результат = ЭлементОтбора.ПравоеЗначение.НайтиПоЗначению(Значение) = Неопределено;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НачинаетсяС Тогда
Результат = Найти(Значение, ЭлементОтбора.ПравоеЗначение) = 1;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеНачинаетсяС Тогда
Результат = Найти(Значение, ЭлементОтбора.ПравоеЗначение) <> 1;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено Тогда
Результат = ЗначениеЗаполнено(Значение)
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено Тогда
Результат = Не ЗначениеЗаполнено(Значение);
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Больше Тогда
Результат = Значение > ЭлементОтбора.ПравоеЗначение;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.БольшеИлиРавно Тогда
Результат = Значение >= ЭлементОтбора.ПравоеЗначение;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Меньше Тогда
Результат = Значение < ЭлементОтбора.ПравоеЗначение;
ИначеЕсли ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.МеньшеИлиРавно Тогда
Результат = Значение <= ЭлементОтбора.ПравоеЗначение;
Иначе
ВызватьИсключение "Не поддерживаемый вид сравнения - " + ЭлементОтбора.ВидСравнения;
КонецЕсли;
Возврат Результат;
КонецФункции
#Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда
Функция ТекстПоискаСсылкиВXMLЛкс(Знач ИскомаяСсылка, Знач СТипом = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
ИскомаяСсылка = Справочники.Валюты.ПустаяСсылка();
#КонецЕсли
ИмяЗначения = XMLСтрока(ИскомаяСсылка);
Если СТипом Тогда
ТипХМЛ = XMLТипЗнч(ИскомаяСсылка);
//":DocumentRef.АвансовыйОтчет">9f5569b9-006b-11de-8f5c-0015e9f0f8a8<"
ТекстСсылки = ТипХМЛ.ИмяТипа + """>" + ИмяЗначения + "<";
Иначе
//"9f5569b9-006b-11de-8f5c-0015e9f0f8a8"
ТекстСсылки = "" + ИмяЗначения + "";
КонецЕсли;
Возврат ТекстСсылки;
КонецФункции
Функция НайтиВложенныеСсылкиЛкс(Знач ХранилищеГдеИскать, Знач ТекстыСсылок) Экспорт
Если ТекстыСсылок.Количество() = 0 Тогда
Возврат Ложь;
КонецЕсли;
Если ТипЗнч(ХранилищеГдеИскать) = Тип("ХранилищеЗначения") Тогда
ХранилищеГдеИскать = ХранилищеГдеИскать.Получить();
КонецЕсли;
Если ТипЗнч(ХранилищеГдеИскать) <> Тип("Строка") Тогда
ХранилищеГдеИскать = ОбъектВСтрокуXMLЛкс(ХранилищеГдеИскать,,, Ложь);
Если Не ЗначениеЗаполнено(ХранилищеГдеИскать) Тогда
//Продолжить;
КонецЕсли;
КонецЕсли;
ВсеСсылкиНайдены = Истина;
Для Каждого ТекстСсылки Из ТекстыСсылок Цикл
Если Найти(ХранилищеГдеИскать, ТекстСсылки) = 0 Тогда
ВсеСсылкиНайдены = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ВсеСсылкиНайдены;
КонецФункции
////////////////////////////////////
// Задания форм
Функция НайтиПоСсылкамЛкс(СсылкиНа, ИскатьВложенныеДоЧислаСтрок = 0, МоментНачала = Неопределено, АдресРезультата = Неопределено, ЭтаФорма = Неопределено, Кнопка = Неопределено,
ОбработчикЗавершения = Неопределено, РазрешитьАсинхронно = Ложь, Перезапустить = Ложь, БлокируемыеЭлементыФормы = Неопределено) Экспорт
Если Ложь
Или Кнопка = Неопределено
Или ЭтаФорма = Неопределено
Или РазрешитьАсинхронно = Ложь
Или Не ЛиАсинхронностьДоступнаЛкс()
Тогда
СостояниеЛкс("Поиск ссылок…");
ЗамерПоиска = Неопределено;
ТаблицаСсылок = ирСервер.НайтиПоСсылкамЛкс(СсылкиНа, ИскатьВложенныеДоЧислаСтрок,, ЗамерПоиска);
СостояниеЛкс("");
Результат = Новый Структура;
Результат.Вставить("ТаблицаСсылок", ТаблицаСсылок);
Результат.Вставить("МоментНачала", МоментНачала);
Результат.Вставить("ЗамерПоиска", ЗамерПоиска);
Результат.Вставить("СсылкиНа", СсылкиНа);
Если ЭтаФорма <> Неопределено Тогда
Выполнить("ЭтаФорма." + ОбработчикЗавершения + "(, Результат)");
Результат = Неопределено;
Иначе
Если ЗначениеЗаполнено(АдресРезультата) Тогда
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецЕсли;
КонецЕсли;
Иначе
#Если Клиент Тогда
АдресРезультата = ирКлиент.НовыйАдресРезультатаФоновогоЗаданияФормыЛкс(ЭтаФорма);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(СсылкиНа);
ПараметрыЗадания.Добавить(ИскатьВложенныеДоЧислаСтрок);
ПараметрыЗадания.Добавить(МоментНачала);
ПараметрыЗадания.Добавить(АдресРезультата);
Для Счетчик = 1 По 6 Цикл
ПараметрыЗадания.Добавить(Неопределено); // Необязательные параметры
КонецЦикла;
Представление = "Ссылки на " + РасширенноеПредставлениеЛкс(СсылкиНа);
ОписаниеЗадания = ирКлиент.ОписаниеФоновогоЗаданияФормыЛкс("СсылкиНа", "ирОбщий.НайтиПоСсылкамЛкс", ПараметрыЗадания, Представление, Кнопка, ОбработчикЗавершения, АдресРезультата,, БлокируемыеЭлементыФормы);
ирКлиент.ЗапуститьИлиОтменитьФоновоеЗаданиеФормыЛкс(ЭтаФорма, ОписаниеЗадания, Перезапустить);
#КонецЕсли
КонецЕсли;
Возврат Результат;
КонецФункции
// .
// Параметры:
// ДеревоИлиТаблицаМетаданных - -
// ИмяКлючевойКолонки - Строка - содержит имя таблицы
// ИмяКолонкиКоличества - -
// ЛиТаблицыИзменений - -
// СтруктураОтбора - -
// ТолькоРазрешенные - -
// Конфигурация - COMОбъект, ОбъектМетаданныхКонфигурация, Неопределено - Если передать Метаданные, то будут использованы только локальные таблицы
// ЭтаФорма - -
// Кнопка - -
// ОбработчикЗавершения - -
// РазрешитьАсинхронно - -
// Перезапустить - -
//
// Возвращаемое значение:
// -
//
Функция ВычислитьКоличествоСтрокТаблицВДеревеМетаданныхЛкс(ДеревоИлиТаблицаМетаданных = Неопределено, ИмяКлючевойКолонки = "ПолноеИмяОбъекта", ИмяКолонкиКоличества = "КоличествоСтрок",
ЛиТаблицыИзменений = Ложь, СтруктураОтбора = Неопределено, ТолькоРазрешенные = Ложь, Конфигурация = Неопределено, ЭтаФорма = Неопределено, Кнопка = Неопределено, ОбработчикЗавершения = "",
Знач РазрешитьАсинхронно = Истина, Знач Перезапустить = Ложь) Экспорт
БазыДанных = Новый Структура;
БазыДанных.Вставить("ЭтаБД", Новый Массив);
Если Истина
И ирКэш.ДоступноВнешниеИсточникДанныхЛкс()
И Не ЛиТаблицыИзменений
И СтруктураОтбора = Неопределено
И Конфигурация = Неопределено
Тогда
Для Каждого ВнешнийИсточникДанных Из Метаданные.ВнешниеИсточникиДанных Цикл
БазыДанных.Вставить(ВнешнийИсточникДанных.Имя, Новый Массив);
КонецЦикла;
КонецЕсли;
КлючамиЗаданыИменаТаблиц = Истина; // Иначе ключами заданы имена метаданных
Если ТипЗнч(Конфигурация) = Тип("COMОбъект") Тогда
#Если Сервер И Не Сервер Тогда
ДеревоИлиТаблицаМетаданных = Обработки.ирКлсПолеТекстаПрограммы.Создать().ДоступныеТаблицы;
#КонецЕсли
БазыДанных["ЭтаБД"] = ДеревоИлиТаблицаМетаданных.ВыгрузитьКолонку("ПолноеИмя");
РазрешитьАсинхронно = Ложь;
ИначеЕсли ТипЗнч(ДеревоИлиТаблицаМетаданных) = Тип("ДеревоЗначений") Тогда
#Если Сервер И Не Сервер Тогда
ДеревоИлиТаблицаМетаданных = Новый ДеревоЗначений;
#КонецЕсли
ЕстьКолонкаЕстьДоступ = ДеревоИлиТаблицаМетаданных.Колонки.Найти("ЕстьДоступ") <> Неопределено;
Для Каждого СтрокаДерева1 Из ДеревоИлиТаблицаМетаданных.Строки Цикл
Для Каждого СтрокаДерева2 Из СтрокаДерева1.Строки Цикл
КорневойТип = ПервыйФрагментЛкс(СтрокаДерева2[ИмяКлючевойКолонки]);
Если Ложь
//Или КорневойТип = "ВнешнийИсточникДанных"
Или КорневойТип = "РегламентноеЗадание"
Или КорневойТип = "ОбщаяФорма"
Или КорневойТип = "Интерфейс"
Или КорневойТип = "Отчет"
Или КорневойТип = "Обработка"
Или КорневойТип = "КритерийОтбора"
Или (ЕстьКолонкаЕстьДоступ И СтрокаДерева2.ЕстьДоступ = Ложь)
Тогда
Продолжить;
КонецЕсли;
ИмяТаблицы = СтрокаДерева2[ИмяКлючевойКолонки];
Если Не ЗначениеЗаполнено(ИмяТаблицы) Тогда
// Например нет доступа к таблице
Продолжить;
КонецЕсли;
Если Не ЕстьКолонкаЕстьДоступ Тогда
ОписаниеТаблицы = ОписаниеТаблицыБДЛкс(ИмяТаблицы);
Если ОписаниеТаблицы.ЕстьДоступ = Ложь Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
//ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы);
//Если ОбъектМД = Неопределено Тогда
// Продолжить;
//КонецЕсли;
Если КорневойТип = "ВнешнийИсточникДанных" Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ИмяТаблицы);
Если ОбъектМД = Неопределено Тогда
Продолжить;
КонецЕсли;
МассивКлючей = БазыДанных[ОбъектМД.Родитель().Имя];
Иначе
МассивКлючей = БазыДанных.ЭтаБД;
КонецЕсли;
МассивКлючей.Добавить(ИмяТаблицы);
Для Каждого СтрокаДерева3 Из СтрокаДерева2.Строки Цикл
Если ЕстьКолонкаЕстьДоступ И СтрокаДерева3.ЕстьДоступ = Ложь Тогда
Продолжить;
КонецЕсли;
ИмяДочернейТаблицы = СтрокаДерева3[ИмяКлючевойКолонки];
Если Не ЕстьКолонкаЕстьДоступ Тогда
ОписаниеТаблицы = ОписаниеТаблицыБДЛкс(ИмяДочернейТаблицы);
Если ОписаниеТаблицы.ЕстьДоступ = Ложь Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
МассивКлючей.Добавить(ИмяДочернейТаблицы);
КонецЦикла;
КонецЦикла;
КонецЦикла;
КлючамиЗаданыИменаТаблиц = Ложь;
Иначе
ТаблицаВсехТаблицБД = ирКэш.ТаблицаВсехТаблицБДЛкс();
#Если Сервер И Не Сервер Тогда
ТаблицаВсехТаблицБД = Новый ТаблицаЗначений;
ДеревоИлиТаблицаМетаданных = Обработки.ирКлсПолеТекстаПрограммы.Создать().ДоступныеТаблицы.Выгрузить();
//! ДеревоИлиТаблицаМетаданных.Колонки.Добавить("ТипТаблицы");
#КонецЕсли
Для Каждого КлючИЗначение Из БазыДанных Цикл
Если КлючИЗначение.Ключ = "ЭтаБД" Тогда
ИмяСхемы = "";
Иначе
ИмяСхемы = КлючИЗначение.Ключ;
КонецЕсли;
Если ИмяКлючевойКолонки = "ПолноеИмяКолонки" Тогда // Грязно
ЛокальныеКолонки = Новый Массив;
Для Каждого СтрокаКолонкиБД Из ДеревоИлиТаблицаМетаданных Цикл
Если Ложь
Или СтрокаКолонкиБД.ТипТаблицы = "Внешняя"
Тогда
Продолжить;
КонецЕсли;
ЛокальныеКолонки.Добавить(СтрокаКолонкиБД[ИмяКлючевойКолонки]);
КонецЦикла;
БазыДанных[КлючИЗначение.Ключ] = ЛокальныеКолонки;
Иначе
ЛокальныеТаблицы = ТаблицаВсехТаблицБД.Скопировать(Новый Структура("Схема", ИмяСхемы), "ПолноеИмя, Тип, ЕстьДоступ");
НачальноеКоличество = ЛокальныеТаблицы.Количество();
Для СчетчикЛокальныеТаблицы = 1 По НачальноеКоличество Цикл
ОписаниеТаблицы = ЛокальныеТаблицы[НачальноеКоличество - СчетчикЛокальныеТаблицы];
Если Ложь
Или ОписаниеТаблицы.Тип = "ВиртуальнаяТаблица"
Или ОписаниеТаблицы.Тип = "КритерийОтбора"
Или ОписаниеТаблицы.ЕстьДоступ = Ложь
Тогда
ЛокальныеТаблицы.Удалить(ОписаниеТаблицы);
КонецЕсли;
КонецЦикла;
БазыДанных[КлючИЗначение.Ключ] = ЛокальныеТаблицы.ВыгрузитьКолонку("ПолноеИмя"); // Опасно
КонецЕсли;
КонецЦикла;
КонецЕсли;
ЕстьНепустыеЗапросы = Ложь;
Для Каждого КлючИЗначение Из БазыДанных Цикл
ТекстПакета = Новый ЗаписьXML;
ТекстПакета.УстановитьСтроку();
ЛиТекстПакетаПустой = Истина;
ТекстЗапроса = Неопределено;
СчетчикТаблиц = 0;
Для Каждого ПолноеИмяМД Из КлючИЗначение.Значение Цикл
Если ИмяКлючевойКолонки = "ПолноеИмяКолонки" Тогда // Грязно
СтруктураОтбораЛ = Новый Структура;
СтруктураОтбораЛ.Вставить("ИмяПоля", ПоследнийФрагментЛкс(ПолноеИмяМД));
СтруктураОтбораЛ.Вставить("ИмяПараметра", "ЗначениеОтбора");
СтруктураОтбораЛ.Вставить("ВидСравнения", СтруктураОтбора.ВидСравнения);
ПолноеИмяМД = СтрокаБезПоследнегоФрагментаЛкс(ПолноеИмяМД);
Иначе
СтруктураОтбораЛ = СтруктураОтбора;
КонецЕсли;
ТекстЧастиОбъединения = ПолучитьТекстЗапросаСтатистикиПоТаблицеЛкс(ПолноеИмяМД, ИмяКлючевойКолонки, ИмяКолонкиКоличества, ЛиТаблицыИзменений, СтруктураОтбораЛ, ТолькоРазрешенные,
КлючамиЗаданыИменаТаблиц);
Если ТекстЧастиОбъединения = Неопределено Тогда
Продолжить;
КонецЕсли;
Если ТекстЗапроса <> Неопределено Тогда
ТекстЗапроса.ЗаписатьБезОбработки("
|UNION ALL");
Иначе
ТекстЗапроса = Новый ЗаписьXML;
ТекстЗапроса.УстановитьСтроку();
КонецЕсли;
ТекстЗапроса.ЗаписатьБезОбработки(ТекстЧастиОбъединения);
СчетчикТаблиц = СчетчикТаблиц + 1;
Если СчетчикТаблиц = 255 Тогда
СчетчикТаблиц = 0;
Если Не ЛиТекстПакетаПустой Тогда
ТекстПакета.ЗаписатьБезОбработки("
|;");
Иначе
ЛиТекстПакетаПустой = Ложь;
КонецЕсли;
ТекстПакета.ЗаписатьБезОбработки(ТекстЗапроса.Закрыть());
ТекстЗапроса = Неопределено;
КонецЕсли;
КонецЦикла;
Если ТекстЗапроса <> Неопределено Тогда
Если Не ЛиТекстПакетаПустой Тогда
ТекстПакета.ЗаписатьБезОбработки("
|;");
КонецЕсли;
ТекстПакета.ЗаписатьБезОбработки(ТекстЗапроса.Закрыть());
КонецЕсли;
БазыДанных[КлючИЗначение.Ключ] = ТекстПакета.Закрыть(); // Опасно
Если Не ЛиТекстПакетаПустой Тогда
ЕстьНепустыеЗапросы = Истина;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ЕстьНепустыеЗапросы) Тогда
Если Ложь
Или РазрешитьАсинхронно = Ложь
Или ЭтаФорма = Неопределено
Или Не ЛиАсинхронностьДоступнаЛкс()
Тогда
Результат = ВыполнитьЗапросСтатистикиПоТаблицамЛкс(БазыДанных, СтруктураОтбора, ИмяКолонкиКоличества, Конфигурация, РазрешитьАсинхронно = Ложь);
Если ЭтаФорма <> Неопределено Тогда
Выполнить("ЭтаФорма." + ОбработчикЗавершения + "(, Результат)");
Результат = Неопределено;
КонецЕсли;
Иначе
#Если Клиент Тогда
АдресРезультата = ирКлиент.НовыйАдресРезультатаФоновогоЗаданияФормыЛкс(ЭтаФорма);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(БазыДанных);
ПараметрыЗадания.Добавить(СтруктураОтбора);
ПараметрыЗадания.Добавить(ИмяКолонкиКоличества);
ПараметрыЗадания.Добавить(АдресРезультата);
Представление = "Сбор статистики таблиц";
#Если Сервер И Не Сервер Тогда
ирСервер.ВыполнитьЗапросСтатистикиПоТаблицамЛкс();
#КонецЕсли
ОписаниеЗадания = ирКлиент.ОписаниеФоновогоЗаданияФормыЛкс("Выгрузка", "ирСервер.ВыполнитьЗапросСтатистикиПоТаблицамЛкс", ПараметрыЗадания, Представление, Кнопка, ОбработчикЗавершения,
АдресРезультата);
ирКлиент.ЗапуститьИлиОтменитьФоновоеЗаданиеФормыЛкс(ЭтаФорма, ОписаниеЗадания, Перезапустить);
#КонецЕсли
КонецЕсли;
Иначе
Результат = Новый Массив();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ВыполнитьЗапросСтатистикиПоТаблицамЛкс(Знач БазыДанных, Знач СтруктураОтбора = Неопределено, Знач ИмяКолонкиКоличества = "КоличествоСтрок", Знач Конфигурация = Неопределено,
Знач РазрешитьЗаполнятьКоличествоВКэше = Неопределено) Экспорт
КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов");
#Если Сервер И Не Сервер Тогда
БазыДанных = Новый Структура;
КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать();
#КонецЕсли
#Если Клиент Тогда
СостояниеЛкс("Сбор статистики таблиц…");
#КонецЕсли
Если РазрешитьЗаполнятьКоличествоВКэше = Неопределено Тогда
РазрешитьЗаполнятьКоличествоВКэше = Не ирКэш.ЭтоФоновоеЗаданиеЛкс();
КонецЕсли;
Результат = Новый Массив();
Для Каждого КлючИЗначение Из БазыДанных Цикл
Если Не ЗначениеЗаполнено(КлючИЗначение.Значение) Тогда
Продолжить;
КонецЕсли;
Если ТипЗнч(Конфигурация) = Тип("COMОбъект") Тогда
Запрос = Новый COMОбъект("ADODB.Command");
Запрос.ActiveConnection = Конфигурация;
Запрос.CommandText = СтрЗаменить(КлючИЗначение.Значение, """", "'");
Попытка
РезультатЗапроса = Запрос.Execute();
Исключение
ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
Продолжить;
КонецПопытки;
Пока Истина Цикл
Результат.Добавить(РезультатЗапросаADOВТаблицуЗначенийОбщийЛкс(РезультатЗапроса));
лРезультат = РезультатЗапроса.NextRecordset();
Если лРезультат = Неопределено Тогда
Прервать;
КонецЕсли;
РезультатЗапроса = лРезультат;
КонецЦикла;
Иначе
Запрос = Новый Запрос;
Если СтруктураОтбора <> Неопределено Тогда
СкопироватьКоллекциюЛкс(СтруктураОтбора, Запрос.Параметры);
КонецЕсли;
Запрос.Текст = КлючИЗначение.Значение;
Попытка
РезультатПакета = Запрос.ВыполнитьПакет();
Исключение
Если КлючИЗначение.Ключ = "ЭтаБД" Тогда
ВызватьИсключение;
КонецЕсли;
ОписаниеОшибки = ОписаниеОшибки(); // Для отладки
// Это внешняя БД
Продолжить;
КонецПопытки;
Для Каждого РезультатЗапроса Из РезультатПакета Цикл
Результат.Добавить(РезультатЗапроса.Выгрузить());
КонецЦикла;
Если Истина
И РазрешитьЗаполнятьКоличествоВКэше // при не выполнении - экономия 25мс на КА1
И СтруктураОтбора = Неопределено
И КлючИЗначение.Ключ = "ЭтаБД"
Тогда
ЗаполнитьКоличестваСтрокВТаблицеВсехТаблицЛкс(Результат, ИмяКолонкиКоличества);
КонецЕсли;
КонецЕсли;
КонецЦикла;
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
Возврат Результат;
КонецФункции
Процедура ЗаполнитьКоличестваСтрокВТаблицеВсехТаблицЛкс(Знач РезультатыЗапросов, Знач ИмяКолонкиКоличества = "КоличествоСтрок") Экспорт
СписокТаблиц = ирКэш.ТаблицаВсехТаблицБДЛкс();
Для Каждого ТаблицаРезультата Из РезультатыЗапросов Цикл
Для Каждого СтрокаРезультата Из ТаблицаРезультата Цикл
ОписаниеТаблицы = СписокТаблиц.Найти(НРег(СтрокаРезультата.ИмяТаблицы), "НПолноеИмя"); // ирОбщий.ОписаниеТаблицыБДЛкс()
ОписаниеТаблицы.КоличествоСтрок = СтрокаРезультата[ИмяКолонкиКоличества];
КонецЦикла;
КонецЦикла;
Если ИмяКолонкиКоличества = "КоличествоСтрок" Тогда
ОписаниеТаблицы = ОписаниеТаблицыБДЛкс("Константы");
Если ОписаниеТаблицы <> Неопределено Тогда
ОписаниеТаблицы.КоличествоСтрок = 1; // Мультиметка0012741388 По этому признаку мы проверяем, что статистика уже собрана
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ВыполнитьЗапросЛкс(ТекстЗапроса, Параметры = Неопределено, МоментНачала = Неопределено, ЭтаФорма = Неопределено, Кнопка = Неопределено, ОбработчикЗавершения = Неопределено,
РазрешитьАсинхронно = Истина, Перезапустить = Ложь, БлокируемыеЭлементыФормы = Неопределено) Экспорт
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ТекстЗапроса);
ПараметрыЗадания.Добавить(Параметры);
Если Ложь
Или ЭтаФорма = Неопределено
Или РазрешитьАсинхронно = Ложь
Или Не ЛиАсинхронностьДоступнаЛкс()
Тогда
#Если Клиент Тогда
СостояниеЛкс("Выполнение запроса…");
#КонецЕсли
Запрос = Новый Запрос(ТекстЗапроса);
Если Параметры <> Неопределено Тогда
СкопироватьКоллекциюЛкс(Параметры, Запрос.Параметры);
КонецЕсли;
РезультатПакета = Запрос.ВыполнитьПакет();
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
РезультатЗадания = Новый Структура;
РезультатЗадания.Вставить("МоментНачала", МоментНачала);
РезультатЗадания.Вставить("ТаблицаРезультата", РезультатПакета[РезультатПакета.ВГраница()].Выгрузить());
Если ЭтаФорма <> Неопределено И ЗначениеЗаполнено(ОбработчикЗавершения) Тогда
Выполнить("ЭтаФорма." + ОбработчикЗавершения + "(, РезультатЗадания)");
РезультатЗадания = Неопределено;
КонецЕсли;
Иначе
#Если Клиент Тогда
МоментНачала = ТекущаяДата();
АдресРезультата = ирКлиент.НовыйАдресРезультатаФоновогоЗаданияФормыЛкс(ЭтаФорма);
ПараметрыЗадания.Добавить(АдресРезультата);
ПараметрыЗадания.Добавить(МоментНачала);
Для Счетчик = 1 По 1 Цикл
ПараметрыЗадания.Добавить(Неопределено); // Необязательные параметры
КонецЦикла;
Представление = "Выполнение запроса";
#Если Сервер И Не Сервер Тогда
ирСервер.ВыполнитьЗапросЛкс();
#КонецЕсли
ОписаниеЗадания = ирКлиент.ОписаниеФоновогоЗаданияФормыЛкс("ВыполнениеЗапроса", "ирСервер.ВыполнитьЗапросЛкс", ПараметрыЗадания, Представление, Кнопка, ОбработчикЗавершения, АдресРезультата,,
БлокируемыеЭлементыФормы);
РезультатЗадания = ирКлиент.ЗапуститьИлиОтменитьФоновоеЗаданиеФормыЛкс(ЭтаФорма, ОписаниеЗадания, Перезапустить);
#КонецЕсли
КонецЕсли;
Возврат РезультатЗадания;
КонецФункции
Функция УправлениеИтогамиРегистров_ВыполнитьКомандуЛкс(Знач ОбщиеПараметрыОбработки, Знач МоментНачала, Знач РегистрыДляОбработки, Знач Команда, Знач ПериодИтогов, Знач АдресРезультата = Неопределено,
ЭтаФорма = Неопределено, Кнопка = Неопределено, ОбработчикЗавершения = "", БлокируемыеЭлементы = Неопределено) Экспорт
Если Ложь
Или ЭтаФорма = Неопределено
Или Не ЛиАсинхронностьДоступнаЛкс()
Тогда
Если ЭтаФорма <> Неопределено Тогда
Обработка = ЭтаФорма.ЭтотОбъект;
Иначе
ПоместитьПереданныйКэшВоВременноеХранищеЛкс(ОбщиеПараметрыОбработки);
Обработка = Обработки.ирУправлениеИтогамиРегистров.Создать();
ЗагрузитьРеквизитыОбработкиЛкс(Обработка, ОбщиеПараметрыОбработки);
КонецЕсли;
Обработка.ВыполнитьКомандуПользователя(РегистрыДляОбработки, Команда, ПериодИтогов);
Результат = Новый Структура();
Результат.Вставить("МоментНачала", МоментНачала);
Результат.Вставить("Команда", Команда);
Результат.Вставить("РегистрыДляОбработки", РегистрыДляОбработки);
Если ЭтаФорма <> Неопределено Тогда
Выполнить("ЭтаФорма." + ОбработчикЗавершения + "(, Результат)");
Результат = Неопределено;
Иначе
Если ЗначениеЗаполнено(АдресРезультата) Тогда
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецЕсли;
КонецЕсли;
Иначе
#Если Клиент Тогда
Представление = Команда;
ИмяЗадания = "ОбработкаРегистров";
АдресРезультата = ирКлиент.НовыйАдресРезультатаФоновогоЗаданияФормыЛкс(ЭтаФорма);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ОбщиеПараметрыОбработки);
ПараметрыЗадания.Добавить(МоментНачала);
ПараметрыЗадания.Добавить(РегистрыДляОбработки);
ПараметрыЗадания.Добавить(Команда);
ПараметрыЗадания.Добавить(ПериодИтогов);
ПараметрыЗадания.Добавить(АдресРезультата);
Для Счетчик = 1 По 4 Цикл
ПараметрыЗадания.Добавить(Неопределено); // Необязательные параметры
КонецЦикла;
//ДобавитьПереданныйКэшВСтруктуруЛкс(ОбщиеПараметрыОбработки);
ОписаниеЗадания = ирКлиент.ОписаниеФоновогоЗаданияФормыЛкс(ИмяЗадания, "ирОбщий.УправлениеИтогамиРегистров_ВыполнитьКомандуЛкс", ПараметрыЗадания, Представление, Кнопка, ОбработчикЗавершения, АдресРезультата,,
БлокируемыеЭлементы);
ирКлиент.ЗапуститьИлиОтменитьФоновоеЗаданиеФормыЛкс(ЭтаФорма, ОписаниеЗадания);
Результат = Неопределено;
#КонецЕсли
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Выполнить задание формы лкс
//
// Параметры:
// ИмяМетодаОбработки - -
// ПараметрыЗадания - -
// ЭтаФормаИлиОбработка - -
// ИмяЗадания - -
// ПредставлениеЗадания - -
// Кнопка - -
// ОбработчикЗавершения - -
// РазрешитьАсинхронно - Булево, "ВЭтомСеансе" - при Истина выполняем фоново и не ждем завершения, при Ложь выполняем фоново и ждем завершения, при "ВЭтомСеансе" выполняем в текущем сеансе
// БлокируемыеЭлементыФормы - Массив - этим элементам формы включается ТолькоПросмотр либо отключается Доступность на время операции
// ПередаватьКэш - -
// Перезапустить - -
// Многопоточное - -
// ПрефиксыОповещений - -
//
// Возвращаемое значение:
// -
//
Функция ВыполнитьЗаданиеФормыЛкс(Знач ИмяМетодаОбработки, Знач ПараметрыЗадания = Неопределено, Знач ЭтаФормаИлиОбработка = Неопределено, Знач ИмяЗадания = "", Знач ПредставлениеЗадания = "",
Знач Кнопка = Неопределено, Знач ОбработчикЗавершения = Неопределено, РазрешитьАсинхронно = Истина, БлокируемыеЭлементыФормы = Неопределено, ПередаватьКэш = Ложь, Перезапустить = Ложь,
Знач Многопоточное = Ложь, Знач ПрефиксыОповещений = Неопределено, Знач ПоддерживаетПрерывание = Ложь) Экспорт // Мультиметка49144183
Если ПараметрыЗадания = Неопределено Тогда
ПараметрыЗадания = Новый Структура;
КонецЕсли;
ИмяСвойстваРеквизитыДляСервера = "_РеквизитыДляСервера";
ИмяСвойстваАдресРезультата = "_АдресРезультата";
ИмяСвойстваПолноеИмяОбработки = "_ПолноеИмяОбработки";
ИмяСвойстваКэш = "_Кэш";
ИмяСвойстваНачалоЗадания = "_НачалоЗадания";
НачалоЗадания = ТекущаяДата();
ВыполнятьНаСервере = Неопределено;
Если ПараметрыЗадания.Свойство("ВыполнятьНаСервере") Тогда
//! ПараметрыЗадания.Вставить("ВыполнятьНаСервере")
ВыполнятьНаСервере = ПараметрыЗадания.ВыполнятьНаСервере;
Иначе
Попытка
ВыполнятьНаСервере = ЭтаФормаИлиОбработка.ВыполнятьНаСервере;
Исключение
КонецПопытки;
КонецЕсли;
ТипФорма = Неопределено;
#Если Клиент Тогда
ТипФорма = Тип("Форма");
#КонецЕсли
Если Ложь
Или РазрешитьАсинхронно = "ВЭтомСеансе"
Или ВыполнятьНаСервере = Ложь
Или Не ЛиАсинхронностьДоступнаЛкс()
Или ТипЗнч(ЭтаФормаИлиОбработка) <> ТипФорма
Тогда
ПараметрыЗадания.Вставить("ЭтаФорма", ЭтаФормаИлиОбработка);
Если ЭтаФормаИлиОбработка <> Неопределено Тогда
Обработка = ЭтаФормаИлиОбработка;
Иначе
Если ПараметрыЗадания.Свойство(ИмяСвойстваКэш) Тогда
ирКэш.ПараметрыСеансаЛкс().ПереданныйКэш = ПоместитьВоВременноеХранилище(ПараметрыЗадания[ИмяСвойстваКэш], Новый УникальныйИдентификатор);
КонецЕсли;
ПолноеИмяОбработки = ПараметрыЗадания[ИмяСвойстваПолноеИмяОбработки];
РеквизитыОбработки = ПараметрыЗадания[ИмяСвойстваРеквизитыДляСервера];
Обработка = СоздатьОбъектПоИмениМетаданныхЛкс(ПолноеИмяОбработки);
Если РеквизитыОбработки <> Неопределено Тогда
ЗагрузитьРеквизитыОбработкиЛкс(Обработка, РеквизитыОбработки);
КонецЕсли;
НачалоЗадания = ПараметрыЗадания[ИмяСвойстваНачалоЗадания];
КонецЕсли;
Результат = Вычислить("Обработка." + ИмяМетодаОбработки + "(ПараметрыЗадания)");
Если ТипЗнч(Результат) = Тип("Структура") Тогда
Результат.Вставить("НачалоЗадания", НачалоЗадания);
КонецЕсли;
Если ТипЗнч(ЭтаФормаИлиОбработка) = ТипФорма Тогда
Выполнить("ЭтаФормаИлиОбработка." + ОбработчикЗавершения + "(, Результат)");
//Результат = Неопределено; // Если раскомментировать, то сломается ирПоискДублейИЗаменаСсылок.Форма.АвтозаменаЭлементов()
ИначеЕсли ЭтаФормаИлиОбработка = Неопределено Тогда
АдресРезультата = ПараметрыЗадания[ИмяСвойстваАдресРезультата];
Если ЗначениеЗаполнено(АдресРезультата) Тогда
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецЕсли;
КонецЕсли;
Иначе
#Если Клиент Тогда
//Если МетодРеализованЛкс(ЭтаФорма, "РеквизитыОбработки") Тогда
РеквизитыДляСервера = ЭтаФормаИлиОбработка.РеквизитыДляСервера(ПараметрыЗадания);
//КонецЕсли;
Если РазрешитьАсинхронно = Ложь Тогда
Кнопка = Неопределено;
КонецЕсли;
СлужебныеИменаСвойств = Новый Массив;
СлужебныеИменаСвойств.Добавить(ИмяСвойстваРеквизитыДляСервера);
СлужебныеИменаСвойств.Добавить(ИмяСвойстваАдресРезультата);
СлужебныеИменаСвойств.Добавить(ИмяСвойстваПолноеИмяОбработки);
СлужебныеИменаСвойств.Добавить(ИмяСвойстваНачалоЗадания);
СлужебныеИменаСвойств.Добавить(ИмяСвойстваКэш);
Для Каждого СлужебноеИмя Из СлужебныеИменаСвойств Цикл
Если ПараметрыЗадания.Свойство(СлужебноеИмя) Тогда
ВызватьИсключение "В параметрах задания присутствует запрещенное свойство """ + СлужебноеИмя + """";
КонецЕсли;
КонецЦикла;
Если ПередаватьКэш Тогда
ТаблицаВсехТаблицБД = ТаблицаВсехТаблицБДБезОжиданияЛкс();
Если ТаблицаВсехТаблицБД <> Неопределено Тогда
ПараметрыЗадания.Вставить(ИмяСвойстваКэш, Новый Структура("ТаблицаВсехТаблицБД", ТаблицаВсехТаблицБД));
КонецЕсли;
КонецЕсли;
АдресРезультата = ирКлиент.НовыйАдресРезультатаФоновогоЗаданияФормыЛкс(ЭтаФормаИлиОбработка);
ПолноеИмяОбъекта = ЭтаФормаИлиОбработка.Метаданные().ПолноеИмя();
ПараметрыЗадания.Вставить(ИмяСвойстваРеквизитыДляСервера, РеквизитыДляСервера);
ПараметрыЗадания.Вставить(ИмяСвойстваАдресРезультата, АдресРезультата);
ПараметрыЗадания.Вставить(ИмяСвойстваПолноеИмяОбработки, ПолноеИмяОбъекта);
ПараметрыЗадания.Вставить(ИмяСвойстваНачалоЗадания, НачалоЗадания);
#Если Сервер И Не Сервер Тогда
ирОбщий.ВыполнитьЗаданиеФормыЛкс();
#КонецЕсли
ПолноеИмяЭтогоМетода = "ирОбщий.ВыполнитьЗаданиеФормыЛкс";
ПараметрыФоновогоЗадания = Новый Массив;
ПараметрыФоновогоЗадания.Добавить(ИмяМетодаОбработки);
ПараметрыФоновогоЗадания.Добавить(ПараметрыЗадания);
// Мультиметка49144183
Для Счетчик = 1 По 12 Цикл
ПараметрыФоновогоЗадания.Добавить(Неопределено); // Необязательные параметры
КонецЦикла;
Если Не ЗначениеЗаполнено(ИмяЗадания) Тогда
ИмяЗадания = ИмяМетодаОбработки;
КонецЕсли;
ОписаниеЗадания = ирКлиент.ОписаниеФоновогоЗаданияФормыЛкс(ИмяЗадания, ПолноеИмяЭтогоМетода, ПараметрыФоновогоЗадания, ПредставлениеЗадания, Кнопка, ОбработчикЗавершения, АдресРезультата,,
БлокируемыеЭлементыФормы, Многопоточное, ПрефиксыОповещений, ПоддерживаетПрерывание);
ОшибкаСериализации = Ложь;
Результат = ирКлиент.ЗапуститьИлиОтменитьФоновоеЗаданиеФормыЛкс(ЭтаФормаИлиОбработка, ОписаниеЗадания, Перезапустить, ОшибкаСериализации);
Если ОшибкаСериализации Тогда
Результат = ВыполнитьЗаданиеФормыЛкс(ИмяМетодаОбработки, ПараметрыЗадания, ЭтаФормаИлиОбработка,,,, ОбработчикЗавершения, "ВЭтомСеансе");
КонецЕсли;
#КонецЕсли
КонецЕсли;
Возврат Результат;
КонецФункции
Функция РеквизитыОбработкиЛкс(Обработка, ДляСериализации = Истина, ИгнорироватьЗапрещенныеТипы = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Обработка = Обработки.ирАнализЖурналаРегистрации.Создать();
#КонецЕсли
Результат = Новый Структура;
Для Каждого МетаРеквизит Из Обработка.Метаданные().Реквизиты Цикл
ЗначениеРеквизита = Обработка[МетаРеквизит.Имя];
Если ДляСериализации Тогда
Если Ложь
Или ТипЗнч(ЗначениеРеквизита) = Тип("КомпоновщикНастроекКомпоновкиДанных")
Тогда
Если Не ИгнорироватьЗапрещенныеТипы Тогда
ВызватьИсключение "Запрещенный тип """ + ТипЗнч(ЗначениеРеквизита) + """ реквизита """ + МетаРеквизит.Имя + """ для сериализации";
Иначе
Продолжить;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Результат.Вставить(МетаРеквизит.Имя, ЗначениеРеквизита);
КонецЦикла;
Возврат Результат;
КонецФункции
Процедура ЗагрузитьРеквизитыОбработкиЛкс(Обработка, Реквизиты)
#Если Сервер И Не Сервер Тогда
Обработка = Отчеты.ирАнализПравДоступа.Создать();
#КонецЕсли
ЗаполнитьЗначенияСвойств(Обработка, Реквизиты);
Для Каждого МетаТЧ Из Обработка.Метаданные().ТабличныеЧасти Цикл
Если Реквизиты.Свойство(МетаТЧ.Имя) Тогда
Обработка[МетаТЧ.Имя].Загрузить(Реквизиты[МетаТЧ.Имя]);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
/////////////////////////////////////
// Функция - Колонки таблицы БДСПроверками лкс
//
// Параметры:
// ПолноеИмяТаблицы - Строка -
// ИменаКолонок - Массив, Строка - белый список имен колонок
//
// Возвращаемое значение:
// -
//
Функция КолонкиТаблицыБДСПроверкамиЛкс(Знач ПолноеИмяТаблицы, Знач ИменаКолонок = Неопределено) Экспорт
Если ТипЗнч(ИменаКолонок) = Тип("Строка") И ЗначениеЗаполнено(ИменаКолонок) Тогда
ИменаКолонок = СтрРазделитьЛкс(ИменаКолонок);
КонецЕсли;
КолонкиСПроверками = Новый Структура;
Для Каждого ПолеТаблицы Из ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицы) Цикл
ИмяКолонки = ПолеТаблицы.Имя;
Если Ложь
Или ПолеТаблицы.Метаданные = Неопределено
Или (Истина
И ТипЗнч(ИменаКолонок) = Тип("Массив")
И ИменаКолонок.Найти(ИмяКолонки) = Неопределено)
Тогда
Продолжить;
КонецЕсли;
МетаданныеКолонки = ПолеТаблицы.Метаданные;
КолонкаСПроверками = Новый Структура("Имя, СвязиПараметровВыбора, ПараметрыВыбора");
КолонкаСПроверками.Имя = ИмяКолонки;
Попытка
ЗаполнитьЗначенияСвойств(КолонкаСПроверками, МетаданныеКолонки, "СвязиПараметровВыбора, ПараметрыВыбора");
Исключение
// Например последовательность
Продолжить;
КонецПопытки;
КолонкиСПроверками.Вставить(ИмяКолонки, КолонкаСПроверками);
КонецЦикла;
Возврат КолонкиСПроверками;
КонецФункции
//.
// Параметры:
// ТаблицаДляЗагрузки - ТаблицаЗначений -
// КолонкиСПроверками - Структура - :
// * <Ключ> - Структура -
// КолонкиСНарушениями - Структура -
// ТабличноеПоле - Неопределено -
// выхПропускатьНесогласованные - Булево -
// выхПоляСУсловиями - ТаблицаЗначений - :
// * ИмяКолонки - Строка -
// * ИмяКолонкиРезультата - Строка -
// * ВыражениеЗапроса - Строка -
// ЛиТЧ - Булево -
// Возвращаемое значение:
// Булево - Истина, если нарушений нет
Функция ПроверитьТаблицуЗначенийНаСогласованностьЛкс(Знач ТаблицаДляЗагрузки, Знач КолонкиСПроверками, Знач КолонкиСНарушениями = Неопределено, Знач ТабличноеПоле = Неопределено,
выхПропускатьНесогласованные = Ложь, выхПоляСУсловиями = Неопределено, Знач ЛиТЧ = Ложь, Знач РеквизитыВладельца = Неопределено, Знач УдалитьФлагиНарушений = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаДляЗагрузки = Новый ТаблицаЗначений;
КолонкиСПроверками = Новый Структура;
#КонецЕсли
ПараметрыЗапроса = Новый Структура;
КомпоновщикТаблицы = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикТаблицы.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СоздатьСхемуПоТаблицеЗначенийЛкс(ТаблицаДляЗагрузки)));
СформироватьПоляЗапросаПроверкиСогласованностиЛкс(КомпоновщикТаблицы, КолонкиСПроверками, ПараметрыЗапроса, ТабличноеПоле, выхПоляСУсловиями, ЛиТЧ, РеквизитыВладельца);
выхПропускатьНесогласованные = Истина;
Если выхПоляСУсловиями.Количество() > 0 Тогда
ТекстЗапроса = "ВЫБРАТЬ * ПОМЕСТИТЬ Т ИЗ &Т КАК Т;
|ВЫБРАТЬ *,
| " + СтрСоединитьЛкс(выхПоляСУсловиями.ВыгрузитьКолонку("ВыражениеЗапроса"), "," + Символы.ПС + Символы.Таб) + "
|ИЗ Т";
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
СкопироватьКоллекциюЛкс(ПараметрыЗапроса, Запрос.Параметры);
Запрос.УстановитьПараметр("Т", ТаблицаДляЗагрузки);
Попытка
ТаблицаДляЗагрузкиНовая = Запрос.Выполнить().Выгрузить();
Исключение
// Есть запрещенные для запроса типы
ОписаниеОшибки = ОписаниеОшибки();
СообщитьЛкс("Ошибка проверки согласованности данных: " + ОписаниеОшибки);
Запрос = Неопределено;
КонецПопытки;
Если Запрос <> Неопределено Тогда
#Если Сервер И Не Сервер Тогда
ТаблицаДляЗагрузкиНовая = Новый ТаблицаЗначений;
#КонецЕсли
ИменаНовыхКолонок = СтрСоединитьЛкс(выхПоляСУсловиями.ВыгрузитьКолонку("ИмяКолонкиРезультата"));
КолонкиРезультатов = ТаблицаСКолонкамиБезТипаNullЛкс(ТаблицаДляЗагрузкиНовая, Ложь, ИменаНовыхКолонок); // Иначе Итог по колонке Булево не будет считаться
СкопироватьКолонкиКоллекцииЛкс(КолонкиРезультатов, ТаблицаДляЗагрузки,, ИменаНовыхКолонок);
БылиНеуспехи = Ложь;
Для Каждого ПолеСоСвязями Из выхПоляСУсловиями Цикл
ИмяКолонкиРезультата = ПолеСоСвязями.ИмяКолонкиРезультата;
// Опасно. Порядок строк наверное может измениться в каких то СУБД. Тогда надо добавить в исходную таблицу номер строки и сортировку по нему.
ТаблицаДляЗагрузки.ЗагрузитьКолонку(ТаблицаДляЗагрузкиНовая.ВыгрузитьКолонку(ИмяКолонкиРезультата), ИмяКолонкиРезультата);
КоличествоНеуспехов = ТаблицаДляЗагрузки.Итог(ИмяКолонкиРезультата);
Если КоличествоНеуспехов > 0 Тогда
СообщитьЛкс(СтрШаблонЛкс("В колонке ""%1"" %2 ячеек не удовлетворяют текущим связям и параметрам выбора выбора.%3 Эти ячейки будут пропущены.",
ПолеСоСвязями.ИмяКолонки, КоличествоНеуспехов, ?(ТабличноеПоле = Неопределено, "", " Если эти условия статичны, то")));
Если КолонкиСНарушениями <> Неопределено Тогда
КолонкиСНарушениями.Вставить(ПолеСоСвязями.ИмяКолонки);
КонецЕсли;
БылиНеуспехи = Истина;
УдалитьКолонку = УдалитьФлагиНарушений;
Иначе
УдалитьКолонку = Истина;
КонецЕсли;
Если УдалитьКолонку Тогда
ТаблицаДляЗагрузки.Колонки.Удалить(ИмяКолонкиРезультата);
КонецЕсли;
КонецЦикла;
Если БылиНеуспехи Тогда
#Если Клиент Тогда
Ответ = Вопрос("Обнаружены статично несогласованные данные в загружаемых строках. Хотите отменить загрузку и посмотреть запрос проверки?", РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
Если Ответ = КодВозвратаДиалога.Да Тогда
ОтладитьЛкс(Запрос);
Возврат Ложь;
КонецЕсли;
#Иначе
СообщитьЛкс("При выполнении на клиенте будет доступен просмотр запроса проверки согласованности.");
#КонецЕсли
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
// Функция - Сформировать поля запроса проверки согласованности лкс
//
// Параметры:
// ТаблицаДляЗагрузки - ТаблицаЗначений - строки не нужны, достаточно колонок
// КолонкиСПроверками - -
// ПараметрыЗапроса - -
// ТабличноеПоле - -
// ПоляСУсловиями - -
// ЛиТЧ - -
// РеквизитыВладельца - -
//
// Возвращаемое значение:
// -
//
Функция СформироватьПоляЗапросаПроверкиСогласованностиЛкс(Знач КомпоновщикТаблицы, Знач КолонкиСПроверками, ПараметрыЗапроса, Знач ТабличноеПоле = Неопределено, ПоляСУсловиями = Неопределено,
Знач ЛиТЧ = Ложь, Знач РеквизитыВладельца = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
КомпоновщикТаблицы = Новый КомпоновщикНастроекКомпоновкиДанных;
#КонецЕсли
ПоляСУсловиями = Новый ТаблицаЗначений;
ПоляСУсловиями.Колонки.Добавить("ИмяКолонки");
ПоляСУсловиями.Колонки.Добавить("ИмяКолонкиРезультата");
ПоляСУсловиями.Колонки.Добавить("ВыражениеЗапроса");
ПоляСУсловиями.Индексы.Добавить("ИмяКолонки");
Если ПараметрыЗапроса = Неопределено Тогда
ПараметрыЗапроса = Новый Структура;
КонецЕсли;
Для Каждого КлючИЗначение Из КолонкиСПроверками Цикл
КолонкаСПроверками = КлючИЗначение.Значение;
ИмяКолонкиТЗ = КолонкаСПроверками.Имя;
ТекстУспехаПоля = "";
СвязиПараметровВыбора = КолонкаСПроверками.СвязиПараметровВыбора;
ПараметрыВыбора = КолонкаСПроверками.ПараметрыВыбора;
ВыраженияУсловий = Новый Массив;
Для Каждого СвязьПараметраВыбора Из СвязиПараметровВыбора Цикл
#Если Сервер И Не Сервер Тогда
СвязьПараметраВыбора = Новый СвязьПараметраВыбора;
#КонецЕсли
Фрагменты = СтрРазделитьЛкс(СвязьПараметраВыбора.Имя, "Отбор.");
Если Фрагменты.Количество() < 2 Тогда
Продолжить;
КонецЕсли;
ИмяРеквизитаКолонки = Фрагменты[1];
//Если СвязьПараметраВыбора.ИзменениеЗначения = РежимИзмененияСвязанногоЗначения.НеИзменять Тогда
// Продолжить;
//КонецЕсли;
//Если КолонкаСПроверками.Свойство("НовоеЗначение") Тогда
// ИмяПараметра = АвтоУникальноеИмяВКоллекцииЛкс(ПараметрыЗапроса, ИдентификаторИзПредставленияЛкс(КолонкаСПроверками.НовоеЗначение));
// ПараметрыЗапроса.Вставить(ИмяПараметра, КолонкаСПроверками.НовоеЗначение);
// ПолеКомпоновки = "(ВЫРАЗИТЬ &" + ИмяПараметра + " КАК " + КолонкаСПроверками.НовоеЗначение.Метаданные().ПолноеИмя() + ")." + ИмяРеквизитаКолонки;
//Иначе
ПолеКомпоновки = Новый ПолеКомпоновкиДанных(ИмяКолонкиТЗ + "." + ИмяРеквизитаКолонки);
Если КомпоновщикТаблицы.Настройки.Отбор.ДоступныеПоляОтбора.НайтиПоле(ПолеКомпоновки) = Неопределено Тогда
Продолжить;
КонецЕсли;
//КонецЕсли;
ПутьКДанным = СвязьПараметраВыбора.ПутьКДанным;
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
// ПутьКДанным = "Элементы.Товары.ТекущиеДанные.Номенклатура"
Фрагменты = СтрРазделитьЛкс(ПутьКДанным, ТабличноеПоле.Имя + ".ТекущиеДанные.");
Если Фрагменты.Количество() > 1 Тогда
ВлияющееВыражение = "Т." + Фрагменты[1];
Иначе
ВлияющееЗначение = Вычислить("РеквизитыВладельца." + ПутьКДанным);
ИмяПараметра = АвтоУникальноеИмяВКоллекцииЛкс(ПараметрыЗапроса, ИдентификаторИзПредставленияЛкс(ВлияющееЗначение));
ПараметрыЗапроса.Вставить(ИмяПараметра, ВлияющееЗначение);
ВлияющееВыражение = "&" + ИмяПараметра;
КонецЕсли;
Иначе
Фрагменты = СтрРазделитьЛкс(ПутьКДанным);
Если ЛиТЧ Тогда
Если Фрагменты.Количество() = 1 Тогда
Если РеквизитыВладельца <> Неопределено Тогда
ВлияющееЗначение = РеквизитыВладельца[Фрагменты[0]];
ИмяПараметра = АвтоУникальноеИмяВКоллекцииЛкс(ПараметрыЗапроса, ИдентификаторИзПредставленияЛкс(ВлияющееЗначение));
ПараметрыЗапроса.Вставить(ИмяПараметра, ВлияющееЗначение);
ВлияющееВыражение = "&" + ИмяПараметра;
Иначе
ВлияющееВыражение = "Т.Ссылка." + Фрагменты[0];
КонецЕсли;
Иначе
ВлияющееВыражение = "Т." + Фрагменты[1];
КонецЕсли;
Иначе
ВлияющееВыражение = "Т." + Фрагменты[0];
КонецЕсли;
КонецЕсли;
ВыраженияУсловий.Добавить("ЕСТЬNULL(" + ВлияющееВыражение + " = Т." + ПолеКомпоновки + ", ИСТИНА)");
КонецЦикла;
Если Не КолонкаСПроверками.Свойство("НовоеЗначение") Тогда
Для Каждого ПараметрВыбора Из ПараметрыВыбора Цикл
#Если Сервер И Не Сервер Тогда
ПараметрВыбора = Новый ПараметрВыбора;
#КонецЕсли
Фрагменты = СтрРазделитьЛкс(ПараметрВыбора.Имя, "Отбор.");
Если Фрагменты.Количество() < 2 Тогда
Продолжить;
КонецЕсли;
ИмяРеквизитаКолонки = Фрагменты[1];
ПолеКомпоновки = Новый ПолеКомпоновкиДанных(ИмяКолонкиТЗ + "." + ИмяРеквизитаКолонки);
Если КомпоновщикТаблицы.Настройки.Отбор.ДоступныеПоляОтбора.НайтиПоле(ПолеКомпоновки) = Неопределено Тогда
Продолжить;
КонецЕсли;
ИмяПараметра = АвтоУникальноеИмяВКоллекцииЛкс(ПараметрыЗапроса, ИдентификаторИзПредставленияЛкс(ПараметрВыбора.Значение));
ПараметрыЗапроса.Вставить(ИмяПараметра, ПараметрВыбора.Значение);
ВыраженияУсловий.Добавить("ЕСТЬNULL(Т." + ПолеКомпоновки + " В (&" + ИмяПараметра + "), ИСТИНА)");
КонецЦикла;
КонецЕсли;
Если ВыраженияУсловий.Количество() > 0 Тогда
ПолеСУСловиями = ПоляСУсловиями.Добавить();
ПолеСУСловиями.ИмяКолонки = ИмяКолонкиТЗ;
ПолеСУСловиями.ИмяКолонкиРезультата = "Несогласовано_" + ИмяКолонкиТЗ;
//ПолеСУСловиями.ВыражениеЗапроса = "ВЫБОР КОГДА " + СтрСоединитьЛкс(ВыраженияУсловий, Символы.ПС + " И ") + " ТОГДА ЛОЖЬ ИНАЧЕ ИСТИНА КОНЕЦ КАК " + ПолеСУСловиями.ИмяКолонкиРезультата;
ПолеСУСловиями.ВыражениеЗапроса = "НЕ (" + СтрСоединитьЛкс(ВыраженияУсловий, Символы.ПС + " И ") + ") КАК " + ПолеСУСловиями.ИмяКолонкиРезультата;
КонецЕсли;
КонецЦикла;
Возврат ПараметрыЗапроса;
КонецФункции
Функция СоединениеHTTPЛкс(Знач СерверЗапроса, Знач ПортВременный = 0, Знач ПользовательЗапроса = "", Знач ПарольЗапроса = "", Знач ЛиСобственныйПрокси = Ложь, Знач ТаймаутЗапроса = 0,
Знач ЛиЗащищенноеСоединение = Ложь, Знач АутентификацияОС = Неопределено, Знач ПредставлениеСоединения = "Соединение", Знач ПроверитьНаСервере = Ложь, Знач ТаблицаСобытий = Неопределено,
Знач ЗащищенноеСоединение = Неопределено, Знач ИнтернетПрокси = Неопределено, выхОписаниеОшибки = "") Экспорт
Если Истина
И ПроверитьНаСервере
И ЗащищенноеСоединение = Неопределено
И ИнтернетПрокси = Неопределено
Тогда
ирСервер.СоединениеHTTPЛкс(СерверЗапроса, ПортВременный, ПользовательЗапроса, ПарольЗапроса, ЛиСобственныйПрокси, ТаймаутЗапроса, ЛиЗащищенноеСоединение, АутентификацияОС,
ПредставлениеСоединения, ТаблицаСобытий);
КонецЕсли;
Если Не ЗначениеЗаполнено(ПортВременный) Тогда
ПортВременный = ?(ЛиЗащищенноеСоединение, 443, 80);
КонецЕсли;
Если ИнтернетПрокси = Неопределено Тогда
ИнтернетПрокси = ИнтернетПроксиЛкс(ЛиСобственныйПрокси, ЛиЗащищенноеСоединение);
КонецЕсли;
Если ЛиЗащищенноеСоединение И ЗащищенноеСоединение = Неопределено Тогда
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Иначе
ЗащищенноеСоединение = Неопределено;
КонецЕсли;
Если ТаблицаСобытий <> Неопределено Тогда
Если Не ОбработатьСобытиеЛкс(ТаблицаСобытий, "АлгоритмПередСоединением", выхОписаниеОшибки,, ЗащищенноеСоединение, ИнтернетПрокси) Тогда
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Если АутентификацияОС <> Неопределено Тогда
Попытка
// параметр АутентификацияОС появился в 8.3.7
СоединениеHTTP = Вычислить("Новый HTTPСоединение(СерверЗапроса, ПортВременный, ПользовательЗапроса, ПарольЗапроса, ИнтернетПрокси, ТаймаутЗапроса, ЗащищенноеСоединение, АутентификацияОС)");
Исключение
выхОписаниеОшибки = ОписаниеОшибки();
Сообщить(ПредставлениеСоединения + " не установлено по причине: " + выхОписаниеОшибки);
Возврат Неопределено;
КонецПопытки;
Иначе
СоединениеHTTP = Новый HTTPСоединение(СерверЗапроса, ПортВременный, ПользовательЗапроса, ПарольЗапроса, ИнтернетПрокси, ТаймаутЗапроса, ЗащищенноеСоединение);
КонецЕсли;
Возврат СоединениеHTTP;
КонецФункции
Функция ИнтернетПроксиЛкс(ЛиСобственныйПрокси = Ложь, ЛиЗащищенноеСоединение = Ложь) Экспорт
ИнтернетПрокси = Новый ИнтернетПрокси(Не ЛиСобственныйПрокси);
Если ЛиСобственныйПрокси Тогда
СобственныеПрокси = ВосстановитьЗначениеЛкс("ИнтернетПрокси");
#Если Сервер И Не Сервер Тогда
СобственныеПрокси = Новый Структура;
#КонецЕсли
Протокол = ?(ЛиЗащищенноеСоединение, "https", "http");
Если СобственныеПрокси.Свойство(Протокол) Тогда
НастройкиПрокси = СобственныеПрокси[Протокол];
Если ЗначениеЗаполнено(НастройкиПрокси.Сервер) Тогда
ИнтернетПрокси.Установить(Протокол, НастройкиПрокси.Сервер, НастройкиПрокси.Порт, НастройкиПрокси.Пользователь, НастройкиПрокси.Пароль, НастройкиПрокси.АутентификацияОС);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат ИнтернетПрокси;
КонецФункции
Процедура ОчиститьДвиженияДокументаЛкс(Знач Ссылка, Знач ВключаяПоследовательности = Ложь, Знач ВключаяПерерасчеты = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Ссылка = Документы.АвансовыйОтчет.ПустаяСсылка();
#КонецЕсли
ОбъектыМД = МетаданныеНаборовЗаписейПоРегистраторуЛкс(Ссылка.Метаданные(), ВключаяПоследовательности, ВключаяПерерасчеты);
Для Каждого МетаРегистр из ОбъектыМД Цикл
ПолноеИмяМД = МетаРегистр.ПолноеИмя();
ИмяТаблицыБДРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД);
ИмяПоляОтбора = ИмяПоляОтбораПодчиненногоНабораЗаписейЛкс(ИмяТаблицыБДРегистра);
СтруктураНаборЗаписей = ОбъектБДПоКлючуЛкс(ПолноеИмяМД, Новый Структура(ИмяПоляОтбора, Ссылка),, Ложь);
ЗаписатьОбъектЛкс(СтруктураНаборЗаписей.Методы);
КонецЦикла;
КонецПроцедуры
// Процедура - Установить использование истории данных лкс
//
// Параметры:
// ИменаМД - Строка, Массив - если передана строка, то из нее создается массив с одним элементом
// НовоеИспользование - -
// НовоеИспользованиеПолей - -
//
Функция УстановитьИспользованиеИсторииДанныхЛкс(Знач ИменаМД, Знач НовоеИспользование = Неопределено, Знач НовоеИспользованиеПолей = Неопределено) Экспорт
Если ТипЗнч(ИменаМД) = Тип("Строка") Тогда
ИменаМД = ЗначенияВМассивЛкс(ИменаМД);
КонецЕсли;
#Если Клиент И Не Сервер Тогда
// Антибаг платформы https://www.hostedredmine.com/issues/922251
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
СообщитьЛкс("Серверный контекст не увидит изменений настроек истории данных до перезапуска сеанса из-за ошибки платформы");
Иначе
ирСервер.УстановитьИспользованиеИсторииДанныхЛкс(ИменаМД, НовоеИспользование, НовоеИспользованиеПолей);
КонецЕсли;
#КонецЕсли
ИсторияДанныхМоя = ИсторияДанныхЛкс();
#Если Сервер И Не Сервер Тогда
ИсторияДанныхМоя = ИсторияДанных;
#КонецЕсли
Результат = Новый Массив;
Для Каждого ПолноеИмяМД Из ИменаМД Цикл
ОбъектМД = Метаданные.НайтиПоПолномуИмени(ПолноеИмяМД);
НастройкиИстории = ИсторияДанныхМоя.ПолучитьНастройки(ОбъектМД);
Если НастройкиИстории = Неопределено Тогда
НастройкиИстории = Новый ("НастройкиИсторииДанных");
КонецЕсли;
Если НовоеИспользование <> Неопределено Тогда
НастройкиИстории.Использование = НовоеИспользование;
КонецЕсли;
Если НовоеИспользованиеПолей <> Неопределено Тогда
НастройкиИстории.ИспользованиеПолей = НовоеИспользованиеПолей;
КонецЕсли;
ИсторияДанныхМоя.УстановитьНастройки(ОбъектМД, НастройкиИстории);
Результат.Добавить(НастройкиИстории);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ИсторияДанныхЛкс() Экспорт
Возврат Вычислить("ИсторияДанных");
КонецФункции
Функция ЗапросВСтруктуруБезВременныхТаблицЛкс(Запрос) Экспорт
Результат = Новый Структура("Текст, Параметры");
Если Запрос <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(Результат, Запрос);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ЗапросИзСтруктурыБезВременныхТаблицЛкс(Знач Структура) Экспорт
Запрос = Новый Запрос(Структура.Текст);
СкопироватьКоллекциюЛкс(Структура.Параметры, Запрос.Параметры);
Возврат Запрос;
КонецФункции
Функция ЗапросИзСтруктурыЛкс(СтруктураЗапроса, выхИменаВременныхТаблиц = Неопределено, Знач Запрос = Неопределено) Экспорт
Если Запрос = Неопределено Тогда
Запрос = Новый Запрос;
КонецЕсли;
Запрос.Текст = СтруктураЗапроса.Текст;
Если Истина
И СтруктураЗапроса.Свойство("ВременныеТаблицы")
И СтруктураЗапроса.ВременныеТаблицы <> Неопределено
Тогда
выхИменаВременныхТаблиц = Неопределено;
Запрос.МенеджерВременныхТаблиц = ВосстановитьМенеджерВременныхТаблицЛкс(СтруктураЗапроса.ВременныеТаблицы, выхИменаВременныхТаблиц, Запрос.МенеджерВременныхТаблиц);
КонецЕсли;
// Антибаг платформы 8.2.18. Некорректная сериализация моментов времени http://partners.v8.1c.ru/forum/thread.jsp?id=1159525#1159525
//ирОбщий.СкопироватьКоллекциюЛкс(СтруктураЗапроса.Параметры, Объект.Параметры);
Для Каждого КлючИЗначение Из СтруктураЗапроса.Параметры Цикл
Запрос.Параметры.Вставить(КлючИЗначение.Ключ, ЗначениеИзСтрокиВнутрЛкс(КлючИЗначение.Значение));
КонецЦикла;
Если Запрос.Параметры.Свойство("_ОбъектыДанныхТранзакции") Тогда
ОбъектыДанных = Новый Массив;
Для Каждого СнимокОбъекта Из Запрос.Параметры._ОбъектыДанныхТранзакции Цикл
Если СнимокОбъекта = Неопределено Тогда
Продолжить;
КонецЕсли;
Попытка
Объект = ОбъектИзСнимкаЛкс(СнимокОбъекта);
Исключение
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
СообщитьЛкс("Ошибка восстановления объекта транзакции: " + ОписаниеОшибки());
Продолжить;
Иначе
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
ОбъектыДанных.Добавить(Объект);
КонецЦикла;
Запрос.Параметры.Вставить("_ОбъектыДанныхТранзакции", ОбъектыДанных);
КонецЕсли;
Возврат Запрос
КонецФункции
// .
// Параметры:
// Таблица1 - ТаблицаЗначений -
// Таблица2 - ТаблицаЗначений -
// ИсключаяБезымянные - Булево, *Истина - механизм перетаскивания зачем то добавляет свою колонку в таблицу-копию перетаскиваемых строк, а этот параметр включает их игнорирование
// Возвращаемое значение:
// Булево -
Функция ЛиКолонкиТаблицСовпадаютЛкс(Таблица1, Таблица2, ИсключаяБезымянные = Истина) Экспорт
Колонки1 = Новый СписокЗначений;
Для Каждого Колонка Из Таблица1.Колонки Цикл
Если ИсключаяБезымянные И Не ЗначениеЗаполнено(Колонка.Имя) Тогда
Продолжить;
КонецЕсли;
Колонки1.Добавить(Колонка.ТипЗначения, Колонка.Имя);
КонецЦикла;
Колонки1.СортироватьПоПредставлению();
Колонки2 = Новый СписокЗначений;
Для Каждого Колонка Из Таблица2.Колонки Цикл
Если ИсключаяБезымянные И Не ЗначениеЗаполнено(Колонка.Имя) Тогда
Продолжить;
КонецЕсли;
Колонки2.Добавить(Колонка.ТипЗначения, Колонка.Имя);
КонецЦикла;
Колонки2.СортироватьПоПредставлению();
Результат = ОбъектВСтрокуXMLЛкс(Колонки1) = ОбъектВСтрокуXMLЛкс(Колонки2);
Возврат Результат;
КонецФункции
Процедура ВычислитьВыраженияПараметровЛкс(Знач ТаблицаВычисляемыхПараметров, СтруктураПараметров, Знач МодальныйРежим = Ложь, НаСервере = Ложь) Экспорт
Если НаСервере Тогда
СтруктураПараметровXML = ОбъектВСтрокуXMLЛкс(СтруктураПараметров);
ирСервер.ВычислитьВыраженияПараметровЛкс(ТаблицаВычисляемыхПараметров, СтруктураПараметровXML);
СтруктураПараметров = ОбъектИзСтрокиXMLЛкс(СтруктураПараметровXML);
Иначе
Для каждого СтрокаПараметра Из ТаблицаВычисляемыхПараметров Цикл
Значение = Неопределено;
Если ЗначениеЗаполнено(СтрокаПараметра.Выражение) Тогда
ТекстАлгоритма = "
|Параметры = _П0;
|лПараметры = _П0; // Устаревшее
|Результат = " + СтрокаПараметра.Выражение;
Попытка
Значение = ВыполнитьАлгоритм(ТекстАлгоритма,,, СтруктураПараметров);
Исключение
СообщитьСУчетомМодальностиЛкс("Ошибка при вычислении параметра """ + СтрокаПараметра.ИмяПараметра + """"
+ Символы.ПС + ОписаниеОшибки(), МодальныйРежим, СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
СтруктураПараметров.Вставить(СтрокаПараметра.ИмяПараметра, Значение);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция КоличествоСтрокВРезультатеЗапросаЛкс(ЗапросИлиПостроитель, ЛиЗамерВремени = Ложь, МодальныйРежим = Ложь, ИмяЗапроса = "") Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если ТипЗнч(ЗапросИлиПостроитель) = Тип("ПостроительЗапроса") Тогда
Запрос = ЗапросИлиПостроитель.ПолучитьЗапрос();
Иначе
Запрос = ЗапросИлиПостроитель;
КонецЕсли;
ОригинальныйТекстЗапроса = Запрос.Текст;
// Исключаем тяжелые типы из финальной выборки
МассивИменВременныхТаблиц = Новый Массив();
ТекстПостроителя = мПлатформа.ЗамаскироватьВременныеТаблицы(Запрос, , МассивИменВременныхТаблиц);
ПостроительЗапроса = Новый ПостроительЗапроса;
Попытка
ПостроительЗапроса.Текст = ТекстПостроителя;
Исключение
ОписаниеОшибки = ОписаниеОшибки();
Возврат ОписаниеОшибки;
КонецПопытки;
ПостроительЗапроса.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
ПостроительЗапроса.ЗаполнитьНастройки();
УдаляемыеВыбранныеПоля = Новый Массив;
Для Каждого ВыбранноеПоле Из ПостроительЗапроса.ВыбранныеПоля Цикл
ДоступноеПоле = ПостроительЗапроса.ДоступныеПоля.Найти(ВыбранноеПоле.Имя);
ТипЗначенияПоля = ДоступноеПоле.ТипЗначения;
Если ЛиОписаниеТиповНеограниченнойДлиныЛкс(ТипЗначенияПоля) Тогда
УдаляемыеВыбранныеПоля.Добавить(ВыбранноеПоле);
КонецЕсли;
КонецЦикла;
Для Каждого ВыбранноеПоле Из УдаляемыеВыбранныеПоля Цикл
ПостроительЗапроса.ВыбранныеПоля.Удалить(ВыбранноеПоле);
КонецЦикла;
ПромежуточныйТекстЗапроса = ПостроительЗапроса.ПолучитьЗапрос().Текст;
ПромежуточныйТекстЗапроса = мПлатформа.РазмаскироватьВременныеТаблицы(ПромежуточныйТекстЗапроса, МассивИменВременныхТаблиц);
МассивТекстовЗапросов = РазбитьГрубоТекстПакетногоЗапросаНаЗапросыЛкс(ПромежуточныйТекстЗапроса); // разбивка производится второй раз. можно оптимизировать
ТекстПоследнегоЗапроса = МассивТекстовЗапросов[МассивТекстовЗапросов.ВГраница()];
ТекстДоПоследнегоЗапроса = "";
Для Индекс = 0 По МассивТекстовЗапросов.ВГраница() - 1 Цикл
ТекстДоПоследнегоЗапроса = ТекстДоПоследнегоЗапроса + МассивТекстовЗапросов[Индекс];
КонецЦикла;
ТекстПоследнегоЗапроса = мПлатформа.ПреобразоватьЗапросВПодзапрос(ТекстПоследнегоЗапроса, "КОЛИЧЕСТВО(*) КАК КоличествоСтрок",, Истина);
Запрос.Текст = ТекстДоПоследнегоЗапроса + ТекстПоследнегоЗапроса;
#Если Клиент Тогда
НачалоПредварительногоВыполнения = ТекущееВремяВМиллисекундахЛкс();
#КонецЕсли
Попытка
РезультатПредварительногоЗапроса = Запрос.Выполнить();
ПредварительныйЗапросБылиОшибки = Ложь;
Исключение
ПредварительныйЗапросБылиОшибки = Истина;
КоличествоСтрок = ОписаниеОшибки();
КонецПопытки;
#Если Клиент Тогда
Если Истина
И ЛиЗамерВремени
И Не ПредварительныйЗапросБылиОшибки
Тогда
СообщитьСУчетомМодальностиЛкс("Время формирования предварительного результата """ + ИмяЗапроса + """ - "
+ Строка(ТекущееВремяВМиллисекундахЛкс() - НачалоПредварительногоВыполнения) + " мс", МодальныйРежим);
КонецЕсли;
#КонецЕсли
Если Не ПредварительныйЗапросБылиОшибки Тогда
КоличествоСтрок = РезультатПредварительногоЗапроса.Выгрузить()[0].КоличествоСтрок;
КонецЕсли;
Запрос.Текст = ОригинальныйТекстЗапроса;
Возврат КоличествоСтрок;
КонецФункции
Функция КоличествоСтрокВРезультатеКомпоновкиЛкс(МакетКомпоновкиДанныхВКоллекциюЗначений, БылиОшибки = Ложь, ЛиЗамерВремени = Ложь,
МодальныйРежим = Ложь) Экспорт
КоличествоСтрокВсего = 0;
Запрос = Новый Запрос;
Для Каждого ЗначениеПараметра Из МакетКомпоновкиДанныхВКоллекциюЗначений.ЗначенияПараметров Цикл
Запрос.Параметры.Вставить(ЗначениеПараметра.Имя, ЗначениеПараметра.Значение);
КонецЦикла;
Для Каждого НаборДанных Из МакетКомпоновкиДанныхВКоллекциюЗначений.НаборыДанных Цикл
Если ТипЗнч(НаборДанных) <> Тип("НаборДанныхЗапросМакетаКомпоновкиДанных") Тогда
Продолжить;
КонецЕсли;
Запрос.Текст = НаборДанных.Запрос;
КоличествоСтрок = КоличествоСтрокВРезультатеЗапросаЛкс(Запрос, ЛиЗамерВремени, МодальныйРежим, НаборДанных.Имя);
Если ТипЗнч(КоличествоСтрок) = Тип("Число") Тогда
КоличествоСтрокВсего = КоличествоСтрокВсего + КоличествоСтрок;
Иначе
БылиОшибки = Истина;
КонецЕсли;
КонецЦикла;
Возврат КоличествоСтрокВсего;
КонецФункции
// Функция - Скомпоновать отчет в консоли лкс
//
// Параметры:
// КоллекцияВывода - ТабличныйДокумент, ПолеТабличногоДокумента, ТаблицаЗначений, ДеревоЗначений -
// МакетКомпоновки - МакетКомпоновкиДанных -
// ВнешниеНаборыДанных - Структура -
// Автофиксация - -
// МодальныйРежим - -
// ЛиОтладка - -
// АдресДанныхРасшифровки - ДанныеРасшифровкиКомпоновкиДанных -
// НаСервере - -
// выхЭлементыРезультата - -
// ВыполнятьПредварительныйЗапрос - -
// МенеджерВременныхТаблиц - -
// выхДлительность - -
// ПоляИтогаТаблицыВКоллекцию - -
//
// Возвращаемое значение:
// -
//
Функция СкомпоноватьОтчетВКонсолиЛкс(КоллекцияВывода, Знач МакетКомпоновки, ВнешниеНаборыДанных = Неопределено, Автофиксация = Истина, МодальныйРежим = Ложь, ЛиОтладка = Ложь,
АдресДанныхРасшифровки = Неопределено, НаСервере = Ложь, выхЭлементыРезультата = Неопределено, ВыполнятьПредварительныйЗапрос = Ложь, МенеджерВременныхТаблиц = Неопределено,
выхДлительность = 0, Знач ПоляИтогаТаблицыВКоллекцию = Неопределено) Экспорт
#Если Не Сервер Тогда
Если НаСервере Тогда
АдресКоллекцииВывода = ПоместитьВоВременноеХранилище(КоллекцияВывода);
АдресМакетаКомпоновки = ПоместитьВоВременноеХранилище(МакетКомпоновки);
Результат = ирСервер.СкомпоноватьОтчетВКонсолиЛкс(АдресКоллекцииВывода, АдресМакетаКомпоновки, ВнешниеНаборыДанных, Автофиксация, МодальныйРежим, ЛиОтладка, АдресДанныхРасшифровки,
ВыполнятьПредварительныйЗапрос, выхДлительность, ПоляИтогаТаблицыВКоллекцию);
КоллекцияВывода = ПолучитьИзВременногоХранилища(АдресКоллекцииВывода);
Возврат Результат;
КонецЕсли;
#КонецЕсли
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
МакетКомпоновки = Новый МакетКомпоновкиДанных;
#КонецЕсли
// Осторожная выборка
Если ВыполнятьПредварительныйЗапрос = Истина Тогда
БезопасныйПорогКоличестваСтрок = ВосстановитьЗначениеЛкс("ир_БезопасныйПорогКоличестваСтрок");
//Если ТипЗнч(КоллекцияВывода) = Тип("ТабличныйДокумент") Тогда
МакетКомпоновкиДанныхВКоллекциюЗначений = МакетКомпоновки;
//Иначе
// МакетКомпоновкиДанныхВКоллекциюЗначений = ПолучитьМакетКомпоновки("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений");
//КонецЕсли;
БылиОшибки = Ложь;
КоличествоСтрокВсего = КоличествоСтрокВРезультатеКомпоновкиЛкс(МакетКомпоновкиДанныхВКоллекциюЗначений, БылиОшибки, ЛиОтладка, МодальныйРежим);
ТекстВопроса = "Оценка общего размера результатов запросов макета составляет " + КоличествоСтрокВсего + " строк.";
Если БылиОшибки Тогда
ТекстВопроса = ТекстВопроса + "
|При расчете некоторые запросы не удалось проанализировать."
КонецЕсли;
Если Ложь
Или БезопасныйПорогКоличестваСтрок * 1000 < КоличествоСтрокВсего
Или БылиОшибки
Тогда
#Если Клиент Тогда
Ответ = Вопрос(ТекстВопроса + " Продолжить?", РежимДиалогаВопрос.ОКОтмена);
Отменить = Ответ <> КодВозвратаДиалога.ОК;
#Иначе
СообщитьЛкс(ТекстВопроса + " Отмена.");
Отменить = Истина;
#КонецЕсли
Если Отменить Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЛиОтладка Тогда
Запрос = Новый Запрос;
Для Каждого Параметр Из МакетКомпоновки.ЗначенияПараметров Цикл
ЗначениеПараметра = Параметр.Значение;
Если ТипЗнч(ЗначениеПараметра) = Тип("ВыражениеКомпоновкиДанных") Тогда
Попытка
ЗначениеПараметра = Вычислить(ЗначениеПараметра);
Исключение
ЗначениеПараметра = Неопределено;
СообщитьСУчетомМодальностиЛкс("Ошибка вычисления значения параметра """ + Параметр.Имя + """: " + ОписаниеОшибки(), МодальныйРежим, СтатусСообщения.Внимание);
КонецПопытки;
КонецЕсли;
Запрос.УстановитьПараметр(Параметр.Имя, ЗначениеПараметра);
КонецЦикла;
СтруктураНаборовДанныхЗапросовМакета = ВсеНаборыДанныхЗапросовКомпоновкиЛкс(МакетКомпоновки.НаборыДанных);
Для Каждого ЭлементНаборДанныхМакета Из СтруктураНаборовДанныхЗапросовМакета Цикл
НаборДанных = ЭлементНаборДанныхМакета.Значение.НаборДанных;
Если Не ЗначениеЗаполнено(НаборДанных.Имя) Тогда
// Служебные наборы данных пропускаем
Продолжить;
КонецЕсли;
Запрос.Текст = НаборДанных.Запрос;
ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка, "Отдельный запрос - " + НаборДанных.Имя)
КонецЦикла;
КонецЕсли;
НачалоВывода = ТекущееВремяВМиллисекундахЛкс();
Если АдресДанныхРасшифровки <> Неопределено Тогда
ДанныеРасшифровки = АдресДанныхРасшифровки;
КонецЕсли;
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
Попытка
Если ирКэш.НомерВерсииПлатформыЛкс() < 803017 Тогда
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
Иначе
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина,, МенеджерВременныхТаблиц);
КонецЕсли;
Исключение
//ОбработатьОшибкиКомпоновкиПлатформыЛкс(ИнформацияОбОшибке(), МакетКомпоновки, НастройкаКомпоновки); // TODO
ВызватьИсключение;
КонецПопытки;
Если Ложь
Или ТипЗнч(КоллекцияВывода) = Тип("ТабличныйДокумент")
#Если Клиент Тогда
Или ТипЗнч(КоллекцияВывода) = Тип("ПолеТабличногоДокумента")
#КонецЕсли
Тогда
выхЭлементыРезультата = Новый Массив;
ВывестиРезультатКомпоновкиСАвтофиксациейСтрокЛкс(КоллекцияВывода, ПроцессорКомпоновкиДанных, ДанныеРасшифровки, , , Автофиксация, выхЭлементыРезультата);
ИначеЕсли ЗначениеЗаполнено(ПоляИтогаТаблицыВКоллекцию) Тогда
ВывестиТаблицуКомпоновкиВКоллекциюЛкс(КоллекцияВывода, ПроцессорКомпоновкиДанных, ДанныеРасшифровки, ПоляИтогаТаблицыВКоллекцию);
Иначе
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
КоллекцияВывода.Колонки.Очистить();
ПроцессорВывода.УстановитьОбъект(КоллекцияВывода);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных, Истина);
КонецЕсли;
Если АдресДанныхРасшифровки <> Неопределено Тогда
АдресДанныхРасшифровки = ДанныеРасшифровки;
КонецЕсли;
выхДлительность = ТекущееВремяВМиллисекундахЛкс() - НачалоВывода;
Если ЛиОтладка Тогда
СообщитьСУчетомМодальностиЛкс("Формирование результата - " + Строка(выхДлительность) + " мс", МодальныйРежим);
КонецЕсли;
Возврат Истина;
КонецФункции
//.
// Параметры:
// КоллекцияВывода - ТаблицаЗначений, ДеревоЗначений -
// ПроцессорКомпоновкиДанных - ПроцессорКомпоновкиДанных -
// ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных -
// ПоляИтогаТаблицыВКоллекцию - Массив из Строка - имена ресурсов схемы компоновки
Процедура ВывестиТаблицуКомпоновкиВКоллекциюЛкс(Знач КоллекцияВывода, Знач ПроцессорКомпоновкиДанных, Знач ДанныеРасшифровки, Знач ПоляИтогаТаблицыВКоллекцию) Экспорт
КоллекцияВывода.Колонки.Очистить();
СтрокаРезультата = КоллекцияВывода;
СдигаемыеКолонки = Новый Массив;
БазовыеКолонкиГруппировки = Новый Массив;
Глубина = 0;
ГлубинаТекущейСтроки = 0;
ИндексКолонки = 0;
ЕстьСтроки = Ложь;
Пока Истина Цикл
ЭлементРезультата = ПроцессорКомпоновкиДанных.Следующий();
Если ЭлементРезультата = Неопределено Тогда
Прервать;
КонецЕсли;
Если ЭлементРезультата.РасположениеВложенныхЭлементов = РасположениеВложенныхЭлементовРезультатаКомпоновкиДанных.Вертикально Тогда
Если ЭлементРезультата.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.Начало Тогда
Глубина = Глубина + 1;
ИначеЕсли ЭлементРезультата.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.Конец Тогда
Глубина = Глубина - 1;
Если Истина
И ТипЗнч(СтрокаРезультата) = Тип("СтрокаДереваЗначений")
И КоллекцияВывода.Строки.Количество() > 0
Тогда
СтрокаРезультата = ирОбщий.РодительСтрокиДереваЛкс(СтрокаРезультата);
КонецЕсли;
КонецЕсли;
НачатьНовуюСтроку = БазовыеКолонкиГруппировки.Количество() > 0;
КонецЕсли;
ЗначенияПолейРасшифровки = Неопределено;
Для Каждого ЗначениеПараметра Из ЭлементРезультата.ЗначенияПараметров Цикл
Если ТипЗнч(ЗначениеПараметра.Значение) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
ЗначенияПолейРасшифровки = ДанныеРасшифровки.Элементы[ЗначениеПараметра.Значение].ПолучитьПоля();
КонецЕсли;
КонецЦикла;
Если Истина
И ЗначенияПолейРасшифровки <> Неопределено
И Не ЕстьСтроки
Тогда
БазовыеКолонкиГруппировки.Добавить(ирОбщий.ИдентификаторИзПредставленияЛкс(ЗначенияПолейРасшифровки[0].Значение));
Иначе
Если НачатьНовуюСтроку И ЭлементРезультата.РасположениеВложенныхЭлементов = РасположениеВложенныхЭлементовРезультатаКомпоновкиДанных.Горизонтально Тогда
НачатьНовуюСтроку = Ложь;
Если ТипЗнч(КоллекцияВывода) = Тип("ТаблицаЗначений") Тогда
СтрокаРезультата = КоллекцияВывода.Добавить();
Иначе
СтрокаРезультата = СтрокаРезультата.Строки.Добавить();
КонецЕсли;
ЕстьСтроки = Истина;
ГлубинаТекущейСтроки = Глубина;
ИндексБазовойКолонки = 0;
КонецЕсли;
КонецЕсли;
Если ЕстьСтроки И ЗначенияПолейРасшифровки <> Неопределено Тогда
ЭтоРесурс = Ложь;
ЗначениеПараметраЯчейки = Неопределено;
Для Каждого ЗначениеПараметра Из ЭлементРезультата.ЗначенияПараметров Цикл
Если ТипЗнч(ЗначениеПараметра.Значение) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
ЗначенияПолейРасшифровки = ДанныеРасшифровки.Элементы[ЗначениеПараметра.Значение].ПолучитьПоля();
Для Каждого ЗначениеПоля Из ЗначенияПолейРасшифровки Цикл
Если ПоляИтогаТаблицыВКоллекцию.Найти(ЗначениеПоля.Поле) <> Неопределено Тогда
ЭтоРесурс = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЭтоРесурс Тогда
Если БазовыеКолонкиГруппировки.Количество() > ИндексБазовойКолонки Тогда
БазовоеИмяКолонки = БазовыеКолонкиГруппировки[ИндексБазовойКолонки];
Иначе
БазовоеИмяКолонки = "Итоги";
КонецЕсли;
ИмяКолонки = БазовоеИмяКолонки + "_" + ЗначениеПоля.Поле;
Если КоллекцияВывода.Колонки.Найти(ИмяКолонки) = Неопределено Тогда
КоллекцияВывода.Колонки.Добавить(ИмяКолонки);
КонецЕсли;
СтрокаРезультата[ИмяКолонки] = ЗначениеПараметраЯчейки;
КонецЕсли;
Иначе
ЗначениеПараметраЯчейки = ЗначениеПараметра.Значение;
КонецЕсли;
КонецЦикла;
Если ЭтоРесурс Тогда
ИндексБазовойКолонки = ИндексБазовойКолонки + 1;
Иначе
Если КоллекцияВывода.Колонки.Найти(ЗначениеПоля.Поле) = Неопределено Тогда
СдигаемыеКолонки.Вставить(0, КоллекцияВывода.Колонки.Добавить(ЗначениеПоля.Поле));
КонецЕсли;
СтрокаРезультата[ЗначениеПоля.Поле] = ЗначениеПоля.Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Для Каждого Колонка Из СдигаемыеКолонки Цикл
КоллекцияВывода.Колонки.Сдвинуть(Колонка, -КоллекцияВывода.Колонки.Индекс(Колонка));
КонецЦикла;
КонецПроцедуры
// Получает макет компоновки данных по схеме с использованием временных таблиц.
//
// Параметры:
// Схема - СхемаКомпоновкиДанных;
// Настройки - НастройкиКомпоновкиДанных;
// *ВнешниеНаборыДанных - Структура, *Неопределено - туда добавляются временные таблицы;
// *ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных, *Неопределено;
// *ЛиОтладка - Булево, *Ложь - показывать тексты запросов и время выполнения этапов.
//
// Возвращаемое значение:
// МакетКомпоновкиДанных.
//
Функция _МакетКомпоновкиДанныхСВременнымиТаблицамиЛкс(Схема, Настройки, ВнешниеНаборыДанных = Неопределено,
ДанныеРасшифровки = Неопределено, ЛиОтладка = Ложь, СвойМакетОформления = Неопределено, ПроверятьДоступностьПолей = Ложь) Экспорт
РегВыражение = НовоеРегВыражениеЛкс();
РегВыражение.Global = Истина;
РегВыражение.MultiLine = Ложь;
РегВыражение.IgnoreCase = Истина;
// Допустим 1 уровень скобок.
шСкобки = "\([^\)\(]*?\)";
РегВыражение.Pattern = "\(ВЫБРАТЬ(?:" + шСкобки + "|[^$\(\)])*?""ВременнаяТаблица"" = ""(.*?)""\)";
Если ВнешниеНаборыДанных = Неопределено Тогда
ВнешниеНаборыДанных = Новый Структура;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
// Выполним создание всех временных таблиц. Временной таблицей считаем набор данных запрос,
// имя которого начинается с "@". Наборы данных временных таблиц удаляются из предварительной схемы.
ПредварительнаяСхема = КопияОбъектаЛкс(Схема);
НаборыДанныхСхемы = ПредварительнаяСхема.НаборыДанных;
ЕстьВременныеТаблицы = Ложь;
НачальноеКоличество = НаборыДанныхСхемы.Количество();
Для СчетчикНаборыДанныхСхемы = 1 По НачальноеКоличество Цикл
НаборДанных = НаборыДанныхСхемы[НачальноеКоличество - СчетчикНаборыДанныхСхемы];
Если Истина
И Лев(НаборДанных.Имя, 1) = "@"
И ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросСхемыКомпоновкиДанных")
Тогда
ВременнаяСхема = КопияОбъектаЛкс(Схема);
// Кривое копирование набора данных в новую схемы, где он будет один.
ВременнаяСхема.СвязиНаборовДанных.Очистить();
НаборыДанныхВременнойСхемы = ВременнаяСхема.НаборыДанных;
НаборыДанныхВременнойСхемыВГраница = НаборыДанныхВременнойСхемы.Количество() - 1;
Для СчетчикВременнойСхемы = 0 По НаборыДанныхВременнойСхемыВГраница Цикл
НаборДанныхВременнойСхемы = НаборыДанныхВременнойСхемы[НаборыДанныхВременнойСхемыВГраница - СчетчикВременнойСхемы];
Если НаборДанныхВременнойСхемы.Имя <> НаборДанных.Имя Тогда
НаборыДанныхВременнойСхемы.Удалить(НаборДанныхВременнойСхемы);
КонецЕсли;
КонецЦикла;
Для Каждого ПолеНабора Из НаборыДанныхВременнойСхемы[0].Поля Цикл
ПолеНабора.ОграничениеИспользования.Поле = Ложь;
ПолеНабора.ВыражениеПредставления = ПолеНабора.ПутьКДанным;
КонецЦикла;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ВременнаяСхема));
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
КомпоновщикНастроек.Настройки.Структура.Очистить();
КомпоновщикНастроек.Настройки.Выбор.Элементы.Очистить();
КомпоновщикНастроекВосстановитьЛкс(КомпоновщикНастроек);
ВременныеНастройки = КомпоновщикНастроек.Настройки;
// Установим использование параметров
Для Каждого ЭлементПараметра Из ВременныеНастройки.ПараметрыДанных.Элементы Цикл
ЭлементПараметра.Использование = Истина;
КонецЦикла;
// Установим структуру и выбранные поля
ЭлементСтруктуры = ВременныеНастройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
Для Каждого ДоступноеПоле Из ВременныеНастройки.ДоступныеПоляВыбора.Элементы Цикл
// Чтобы пропустить системные папки
Если Не ДоступноеПоле.Папка Тогда
НовоеВыбранноеПоле = ВременныеНастройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
НовоеВыбранноеПоле.Поле = ДоступноеПоле.Поле;
НовоеВыбранноеПоле.Использование = Истина;
КонецЕсли;
КонецЦикла;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ВременнаяСхема, ВременныеНастройки,,,, ПроверятьДоступностьПолей);
Запрос.Текст = МакетКомпоновкиДанных.НаборыДанных[0].Запрос;
Для Каждого Параметр Из МакетКомпоновкиДанных.ЗначенияПараметров Цикл
Запрос.УстановитьПараметр(Параметр.Имя, Параметр.Значение);
КонецЦикла;
Запрос.Текст = РегВыражение.Заменить(Запрос.Текст, "$1");
ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка, "Предварительный запрос - " + НаборДанных.Имя);
//// Недоступные поля набора данных цепляются в настройках при совпадении имен с выбранными полями
//// http://partners.v8.1c.ru/forum/thread.jsp?id=514094
//Для Каждого Поле Из НаборДанных.Поля Цикл
// Поле.ПутьКДанным = "_поле_" + Поле.ПутьКДанным;
//КонецЦикла;
НаборыДанныхСхемы.Удалить(НаборДанных);
ЕстьВременныеТаблицы = Истина;
КонецЕсли;
КонецЦикла;
Если Не ЕстьВременныеТаблицы Тогда
Если ЛиОтладка Тогда
ВремяНачалаКомпоновкиМакета = ТекущееВремяВМиллисекундахЛкс();
КонецЕсли;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ПредварительнаяСхема, Настройки, ДанныеРасшифровки, СвойМакетОформления,, ПроверятьДоступностьПолей);
Если ЛиОтладка Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Компоновка макета - %1мс",, ТекущееВремяВМиллисекундахЛкс() - ВремяНачалаКомпоновкиМакета));
КонецЕсли;
Иначе
// Выполним получение результата предварительного запроса
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ПредварительнаяСхема));
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
КомпоновщикНастроекВосстановитьЛкс(КомпоновщикНастроек);
ПредварительныеНастройки = КомпоновщикНастроек.Настройки;
Если ЛиОтладка Тогда
ВремяНачалаКомпоновкиМакета = ТекущееВремяВМиллисекундахЛкс();
КонецЕсли;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ПредварительнаяСхема, ПредварительныеНастройки, ДанныеРасшифровки, СвойМакетОформления,, ПроверятьДоступностьПолей);
Если ЛиОтладка Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Компоновка макета - %1мс",, ТекущееВремяВМиллисекундахЛкс() - ВремяНачалаКомпоновкиМакета));
КонецЕсли;
Для Каждого Параметр Из МакетКомпоновкиДанных.ЗначенияПараметров Цикл
Запрос.УстановитьПараметр(Параметр.Имя, Параметр.Значение);
КонецЦикла;
СтруктураНаборовДанныхЗапросовМакета = ВсеНаборыДанныхЗапросовКомпоновкиЛкс(МакетКомпоновкиДанных.НаборыДанных);
Для Каждого ЭлементНаборДанныхМакета Из СтруктураНаборовДанныхЗапросовМакета Цикл
НаборДанных = ЭлементНаборДанныхМакета.Значение.НаборДанных;
Запрос.Текст = НаборДанных.Запрос;
Запрос.Текст = РегВыражение.Заменить(Запрос.Текст, "$1");
РезультатЗапроса = ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка, "Предварительный запрос - " + НаборДанных.Имя);
ВнешниеНаборыДанных.Вставить(НаборДанных.Имя, РезультатЗапроса);
КонецЦикла;
// Получение конечного макета
Для Каждого ЭлементНаборДанных Из СтруктураНаборовДанныхЗапросовМакета Цикл
КоллекцияВладелец = ЭлементНаборДанных.Значение.КоллекцияВладелец;
НаборДанныхЗапрос = ЭлементНаборДанных.Значение.НаборДанных;
НаборДанныхОбъект = КоллекцияВладелец.Добавить(Тип("НаборДанныхОбъектМакетаКомпоновкиДанных"));
// Копируем Свойства набора данных запроса в набор данных объекта
ЗаполнитьЗначенияСвойств(НаборДанныхОбъект, НаборДанныхЗапрос);
НаборДанныхОбъект.ИмяОбъекта = НаборДанныхЗапрос.Имя;
Для Каждого ПолеНабораДанныхОригинала Из НаборДанныхЗапрос.Поля Цикл
ПолеРезультата = НаборДанныхОбъект.Поля.Добавить();
ЗаполнитьЗначенияСвойств(ПолеРезультата, ПолеНабораДанныхОригинала);
ЗаполнитьЗначенияСвойств(ПолеРезультата.Роль, ПолеНабораДанныхОригинала.Роль);
КонецЦикла;
КоллекцияВладелец.Удалить(НаборДанныхЗапрос);
КонецЦикла;
КонецЕсли;
// Баг платформы. Пустая дата превращается в Неопределено.
Для Каждого ПараметрСхемы Из ПредварительнаяСхема.Параметры Цикл
Если ПараметрСхемы.ОграничениеИспользования Тогда
Если Не ПараметрСхемы.ДоступенСписокЗначений Тогда
ЗначениеПараметра = МакетКомпоновкиДанных.ЗначенияПараметров.Найти(ПараметрСхемы.Имя);
ЗначениеПараметра.Значение = ПараметрСхемы.ТипЗначения.ПривестиЗначение(ЗначениеПараметра.Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат МакетКомпоновкиДанных;
КонецФункции
// Получает линейную структуру наборов данных запросов компоновки. Работает и со схемой и с макетом.
// Содержит рекурсивный вызов.
//
// Параметры:
// НаборыДанных - НаборыДанныхСхемыКомпоновкиДанных, НаборыДанныхМакетаКомпоновкиДанных -
// *СтруктураНаборовДанных - Структура, *Неопределено - Структура("Имя", Структура("КоллекцияВладелец, НаборДанных"))
//
// Возвращаемое значение:
// Структура.
//
Функция ВсеНаборыДанныхЗапросовКомпоновкиЛкс(Знач НаборыДанных, СтруктураНаборовДанных = Неопределено) Экспорт
Если СтруктураНаборовДанных = Неопределено Тогда
СтруктураНаборовДанных = Новый Структура;
КонецЕсли;
Для каждого НаборДанных Из НаборыДанных Цикл
Если Ложь
Или ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросМакетаКомпоновкиДанных")
Или ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросСхемыКомпоновкиДанных")
Тогда
Если Не ЗначениеЗаполнено(НаборДанных.Имя) Тогда
// Платформа генерит такие наборы для служебных целей
ИмяНабора = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", "");
Иначе
ИмяНабора = НаборДанных.Имя;
КонецЕсли;
СтруктураНаборовДанных.Вставить(ИмяНабора, Новый Структура("КоллекцияВладелец, НаборДанных", НаборыДанных, НаборДанных));
ИначеЕсли Ложь
Или ТипЗнч(НаборДанных) = Тип("НаборДанныхОбъединениеМакетаКомпоновкиДанных")
Или ТипЗнч(НаборДанных) = Тип("НаборДанныхОбъединениеСхемыКомпоновкиДанных")
Тогда
ВсеНаборыДанныхЗапросовКомпоновкиЛкс(НаборДанных.Элементы, СтруктураНаборовДанных);
КонецЕсли;
КонецЦикла;
Возврат СтруктураНаборовДанных;
КонецФункции
// Выводит результат СКД с установкой вертикальной автофиксации.
//
// Параметры:
// Таб - ТабличныеДокумент, ПолеТабличногоДокумента - куда выводим отчет;
// ПроцессорКомпоновкиДанных - ПроцессорКомпоновкиДанных;
// ЭлементыРасшифровки - ЭлементыРасшифровкиКомпоновкиДанных;
// ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных -
// МассивИгнорируемыхПолей - Массив, Неопределено - массив имен игнорируемых полей;
// РазрешитьПрерывание - Булево
// Автофиксация - Булево -
// выхЭлементыРезультата - -
//
Процедура ВывестиРезультатКомпоновкиСАвтофиксациейСтрокЛкс(Таб, ПроцессорКомпоновкиДанных, ДанныеРасшифровки = Неопределено,
Знач МассивИгнорируемыхПолей = Неопределено, РазрешитьПрерывание = Истина, Автофиксация = Истина, выхЭлементыРезультата = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
#КонецЕсли
ЭлементыРасшифровки = Неопределено;
Если ДанныеРасшифровки <> Неопределено Тогда
ЭлементыРасшифровки = ДанныеРасшифровки.Элементы;
КонецЕсли;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.ОтображатьПроцентВывода = Ложь;
ПроцессорВывода.УстановитьДокумент(Таб);
ПроцессорВывода.НачатьВывод();
ФиксацияВыполнена = Ложь;
Если МассивИгнорируемыхПолей = Неопределено Тогда
МассивИгнорируемыхПолей = Новый Массив;
КонецЕсли;
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Индикатор = ПолучитьИндикаторПроцессаЛкс(100, "Компоновка",,, РазрешитьПрерывание);
Пока Истина Цикл
//Если РазрешитьПрерывание Тогда
// #Если Клиент Тогда
// ОбработкаПрерыванияПользователя();
// #КонецЕсли
//КонецЕсли;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
ЭлементРезультатаКомпоновкиДанных = ПроцессорКомпоновкиДанных.Следующий();
Если ЭлементРезультатаКомпоновкиДанных = Неопределено Тогда
Прервать;
КонецЕсли;
Если Индикатор.Счетчик <> ЭлементРезультатаКомпоновкиДанных.ПроцентВывода Тогда
ОбработатьИндикаторЛкс(Индикатор, ЭлементРезультатаКомпоновкиДанных.ПроцентВывода);
КонецЕсли;
// Автофиксация
Если Истина
И Автофиксация
И Не ФиксацияВыполнена
И ЭлементыРасшифровки <> Неопределено
Тогда
Для Каждого ЗначениеПараметра Из ЭлементРезультатаКомпоновкиДанных.ЗначенияПараметров Цикл
Если ТипЗнч(ЗначениеПараметра.Значение) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
ЗначенияПолейРасшифровки = ЭлементыРасшифровки[ЗначениеПараметра.Значение].ПолучитьПоля();
Для Каждого ЗначениеПоляРасшифровки Из ЗначенияПолейРасшифровки Цикл
Если МассивИгнорируемыхПолей.Найти(ЗначениеПоляРасшифровки.Поле) = Неопределено Тогда
Таб.ФиксацияСверху = Таб.ВысотаТаблицы;
ФиксацияВыполнена = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ФиксацияВыполнена Тогда
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ПроцессорВывода.ВывестиЭлемент(ЭлементРезультатаКомпоновкиДанных);
Если Истина
И выхЭлементыРезультата <> Неопределено
И выхЭлементыРезультата.Количество() < 10000
Тогда
выхЭлементыРезультата.Добавить(ЭлементРезультатаКомпоновкиДанных);
КонецЕсли;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
ЭлементРезультатаКомпоновкиДанных = ПроцессорКомпоновкиДанных.Следующий(); Если ЭлементРезультатаКомпоновкиДанных = Неопределено Тогда Прервать; КонецЕсли; Если Индикатор.Счетчик <> ЭлементРезультатаКомпоновкиДанных.ПроцентВывода Тогда ОбработатьИндикаторЛкс(Индикатор, ЭлементРезультатаКомпоновкиДанных.ПроцентВывода); КонецЕсли; Если Истина И Автофиксация И Не ФиксацияВыполнена И ЭлементыРасшифровки <> Неопределено Тогда Для Каждого ЗначениеПараметра Из ЭлементРезультатаКомпоновкиДанных.ЗначенияПараметров Цикл Если ТипЗнч(ЗначениеПараметра.Значение) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда ЗначенияПолейРасшифровки = ЭлементыРасшифровки[ЗначениеПараметра.Значение].ПолучитьПоля(); Для Каждого ЗначениеПоляРасшифровки Из ЗначенияПолейРасшифровки Цикл Если МассивИгнорируемыхПолей.Найти(ЗначениеПоляРасшифровки.Поле) = Неопределено Тогда Таб.ФиксацияСверху = Таб.ВысотаТаблицы; ФиксацияВыполнена = Истина; Прервать; КонецЕсли; КонецЦикла; Если ФиксацияВыполнена Тогда Прервать; КонецЕсли; КонецЕсли; КонецЦикла; КонецЕсли; ПроцессорВывода.ВывестиЭлемент(ЭлементРезультатаКомпоновкиДанных); Если Истина И выхЭлементыРезультата <> Неопределено И выхЭлементыРезультата.Количество() < 10000 Тогда выхЭлементыРезультата.Добавить(ЭлементРезультатаКомпоновкиДанных); КонецЕсли;
КонецЕсли;
КонецЦикла;
ПроцессорВывода.ЗакончитьВывод();
КонецПроцедуры
//
// Параметры:
// Таблица - ТаблицаЗначений - может быть модифицирована здесь, поэтому нужно передавать копию, если нужна неизменность
Функция ВывестиТаблицуВТабличныйДокументИлиТаблицуЗначенийЛкс(ТаблицаЗначений, Знач Приемник = Неопределено, ДанныеРасшифровки = Неопределено, ИтогиЧисловыхКолонок = Истина,
АвтофиксацияШапки = Истина, ВстроитьЗначенияВРасшифровки = Истина, ОтображатьПустые = Ложь, ДобавлятьКолонкиИдентификаторов = Ложь, ДобавлятьКолонкиТипов = Ложь,
ДобавлятьКолонкиПредставлений = Истина, Знач ВыбранныеКолонки = Неопределено, ИмяТекущейКолонки = "", ВыводВТаблицуЗначений = Ложь, Отладка = Ложь, ДобавлятьКолонкиРазмеров = Ложь,
СузитьТипы = Ложь, Иерархия = Ложь) Экспорт
ТребоватьТипЛкс(ТаблицаЗначений,, Тип("ТаблицаЗначений"), Тип("ДеревоЗначений"));
ирПлатформа = ирКэш.Получить();
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
Если ТипЗнч(ТаблицаЗначений) = Тип("ТаблицаЗначений") Тогда
Если ДобавлятьКолонкиТипов Или ДобавлятьКолонкиИдентификаторов Тогда
//ТаблицаЗначений = ТаблицаСКолонкамиБезТипаNullЛкс(ТаблицаЗначений);
ТаблицаЗначений = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаЗначений);
КонецЕсли;
ВсеСтроки = ТаблицаЗначений;
Иначе
//! ТаблицаЗначений = 0 // ДеревоЗначений
ВсеСтроки = ВсеСтрокиДереваЗначенийЛкс(ТаблицаЗначений);
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ирПлатформа = Обработки.ирПлатформа.Создать();
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ВнешниеНаборыДанных = Новый Структура("Основной", ТаблицаЗначений);
КолонкиИдентификаторов = Новый Массив;
КолонкиТипов = Новый Массив;
КолонкиРазмеров = Новый Массив;
Если ВыбранныеКолонки = Неопределено Тогда
ВыбранныеКолонки = Новый Массив;
Для Каждого Колонка Из КолонкиИсточникаДанныхЛкс(ТаблицаЗначений) Цикл
ВыбранныеКолонки.Добавить(Колонка.Имя);
КонецЦикла;
КонецЕсли;
ИменаТипов = Новый Структура;
ПозицииКолонок = Новый Структура;
ИндексТекущейКолонки = 0;
ОформлениеКолонокИдентификаторов = НастройкаКомпоновки.УсловноеОформление.Элементы.Добавить();
ОформлениеКолонокИдентификаторов.Оформление.УстановитьЗначениеПараметра("МаксимальнаяШирина", 2);
ОформлениеКолонокИдентификаторов.Оформление.УстановитьЗначениеПараметра("Размещение", ТипРазмещенияТекстаКомпоновкиДанных.Обрезать);
Для Каждого ВыбраннаяКолонка Из ВыбранныеКолонки Цикл
Если Не ЗначениеЗаполнено(ВыбраннаяКолонка) Тогда
Продолжить;
КонецЕсли;
ИмяКолонки = СтрЗаменить(ВыбраннаяКолонка, ".", "_");
Колонка = ТаблицаЗначений.Колонки.Найти(ИмяКолонки);
Если Колонка = Неопределено Тогда
// Например "ИдентификаторСсылкиЛкс" в таблице формы
Продолжить;
КонецЕсли;
ТипЗначения = Колонка.ТипЗначения;
ТипыКолонки = ТипЗначения.Типы();
ЛиТипПростойСтроковый = ЛиОписаниеТиповПростогоСтроковогоТипаЛкс(ТипЗначения);
ПозицииКолонок.Вставить(Колонка.Имя, НастройкаКомпоновки.Выбор.Элементы.Количество());
Если ДобавлятьКолонкиПредставлений Или ЛиТипПростойСтроковый Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ВыбраннаяКолонка);
КонецЕсли;
Если Ложь
Или ОтображатьПустые
Или (Истина
И ДобавлятьКолонкиТипов
И ТипыКолонки.Количество() > 1)
Тогда
КолонкиТипов.Добавить(Колонка.Имя);
ТаблицаЗначений.Колонки.Вставить(ТаблицаЗначений.Колонки.Индекс(Колонка) + 1, ИмяКолонки + "_ИмяТипаЗначения_", Новый ОписаниеТипов("Строка"),
Колонка.Заголовок + " (тип)");
Если ДобавлятьКолонкиТипов Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяКолонки + "_ИмяТипаЗначения_");
КонецЕсли;
ИменаТиповКолонки = Новый Соответствие;
Для Каждого Тип Из ТипыКолонки Цикл
ИменаТиповКолонки.Вставить(Тип, ПредставлениеТипаЛкс(Тип, ТипЗначения, Истина));
КонецЦикла;
ИменаТипов.Вставить(Колонка.Имя, ИменаТиповКолонки);
КонецЕсли;
Если ДобавлятьКолонкиИдентификаторов Тогда
//ЕстьСсылочныйТип = ТипыКолонки.Количество() = 0;
//Если Не ЕстьСсылочныйТип Тогда
// Для Каждого Тип Из ТипыКолонки Цикл
// Если ЛиТипСсылкиБДЛкс(Тип, Ложь) Тогда
// ЕстьСсылочныйТип = Истина;
// Прервать;
// КонецЕсли;
// КонецЦикла;
//КонецЕсли;
Если Ложь
//Или ЕстьСсылочныйТип
Или Не (ЛиТипПростойСтроковый)
Тогда
Если ИндексТекущейКолонки = 0 И ЗначениеЗаполнено(ИмяТекущейКолонки) И СтрокиРавныЛкс(ВыбраннаяКолонка, ИмяТекущейКолонки) Тогда
ИндексТекущейКолонки = НастройкаКомпоновки.Выбор.Элементы.Количество();
КонецЕсли;
КолонкиИдентификаторов.Добавить(Колонка.Имя);
ИмяКолонкиИдентификатора = ИмяКолонки + "_ИдентификаторЗначения_";
Если ТаблицаЗначений.Колонки.Найти(ИмяКолонкиИдентификатора) = Неопределено Тогда
ТаблицаЗначений.Колонки.Вставить(ТаблицаЗначений.Колонки.Индекс(Колонка) + 1, ИмяКолонкиИдентификатора, Новый ОписаниеТипов("Строка"),
Колонка.Заголовок + " (идентификатор)");
КонецЕсли;
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяКолонкиИдентификатора);
Если ДобавлятьКолонкиПредставлений Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(ОформлениеКолонокИдентификаторов.Поля, ИмяКолонкиИдентификатора);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ДобавлятьКолонкиРазмеров Тогда
Если ЛиОписаниеТиповНеограниченнойДлиныЛкс(ТипЗначения) Тогда
Если ИндексТекущейКолонки = 0 И ЗначениеЗаполнено(ИмяТекущейКолонки) И СтрокиРавныЛкс(ВыбраннаяКолонка, ИмяТекущейКолонки) Тогда
ИндексТекущейКолонки = НастройкаКомпоновки.Выбор.Элементы.Количество();
КонецЕсли;
КолонкиРазмеров.Добавить(Колонка.Имя);
ТаблицаЗначений.Колонки.Вставить(ТаблицаЗначений.Колонки.Индекс(Колонка) + 1, ИмяКолонки + "_РазмерЗначения_", Новый ОписаниеТипов("Число"),
Колонка.Заголовок + " (размер)");
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяКолонки + "_РазмерЗначения_");
КонецЕсли;
КонецЕсли;
Если ОтображатьПустые Тогда
ПустыеЗначения = Новый Массив;
ПустыеЗначения.Добавить(Неопределено);
ПустыеЗначения.Добавить(0);
ПустыеЗначения.Добавить(Дата(1,1,1));
ПустыеЗначения.Добавить(Ложь);
ПустыеЗначения.Добавить("");
Для Каждого ПустоеЗначение Из ПустыеЗначения Цикл
Если Ложь
Или ТипЗначения.Типы().Количество() = 0
Или ТипЗначения.СодержитТип(ТипЗнч(ПустоеЗначение))
Тогда
ЭлементУсловногоОформления = НастройкаКомпоновки.УсловноеОформление.Элементы.Добавить();
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Текст", ирПлатформа.ПредставлениеПустогоЗначенияЛкс(ПустоеЗначение));
//ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветФонаПустогоЗначенияЛкс());
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ЭлементУсловногоОформления.Отбор, ВыбраннаяКолонка, , ВидСравненияКомпоновкиДанных.НеЗаполнено);
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ЭлементУсловногоОформления.Отбор, ВыбраннаяКолонка, ПустоеЗначение, ВидСравненияКомпоновкиДанных.Равно);
ПолеЭлементаОформления = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ПолеЭлементаОформления.Поле = Новый ПолеКомпоновкиДанных(ВыбраннаяКолонка);
КонецЕсли;
КонецЦикла;
// Отдельно для особенного Null
ПустоеЗначение = Null;
Если Истина
И ТипЗначения.Типы().Количество() > 0
И ТипЗначения.СодержитТип(ТипЗнч(ПустоеЗначение))
Тогда
ЭлементУсловногоОформления = НастройкаКомпоновки.УсловноеОформление.Элементы.Добавить();
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Текст", ирПлатформа.ПредставлениеПустогоЗначенияЛкс(ПустоеЗначение));
//ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветФонаПустогоЗначенияЛкс());
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ЭлементУсловногоОформления.Отбор, ИмяКолонки + "_ИмяТипаЗначения_", "Null", ВидСравненияКомпоновкиДанных.Равно);
ПолеЭлементаОформления = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ПолеЭлементаОформления.Поле = Новый ПолеКомпоновкиДанных(ВыбраннаяКолонка);
КонецЕсли;
Иначе
// Значение "Ложь" выводим в виде пустой строки
ПустоеЗначение = Ложь;
Если Ложь
Или ТипЗначения.Типы().Количество() = 1
Или ТипЗначения.СодержитТип(ТипЗнч(ПустоеЗначение))
Тогда
ЭлементУсловногоОформления = НастройкаКомпоновки.УсловноеОформление.Элементы.Добавить();
ЭлементУсловногоОформления.Оформление.УстановитьЗначениеПараметра("Текст", "");
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ЭлементУсловногоОформления.Отбор, ВыбраннаяКолонка, ПустоеЗначение, ВидСравненияКомпоновкиДанных.Равно);
ПолеЭлементаОформления = ЭлементУсловногоОформления.Поля.Элементы.Добавить();
ПолеЭлементаОформления.Поле = Новый ПолеКомпоновкиДанных(ВыбраннаяКолонка);
КонецЕсли;
КонецЕсли;
КонецЦикла;
ОформлениеКолонокИдентификаторов.Использование = ОформлениеКолонокИдентификаторов.Поля.Элементы.Количество() > 0;
Если Ложь
Или КолонкиТипов.Количество() > 0
Или КолонкиИдентификаторов.Количество() > 0
Или КолонкиРазмеров.Количество() > 0
Тогда
Индикатор = ПолучитьИндикаторПроцессаЛкс(ВсеСтроки.Количество(), "Заполнение доп. колонок");
Для Каждого СтрокаТаблицы Из ВсеСтроки Цикл
ОбработатьИндикаторЛкс(Индикатор); // добавляет значительную долю длительности цикла
Если ирКэш.РежимОтладкиЛкс() Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого ИмяКолонки Из КолонкиТипов Цикл
Если Ложь
Или ДобавлятьКолонкиТипов
Или СтрокаТаблицы[ИмяКолонки] = Null
Тогда
СтрокаТаблицы[ИмяКолонки + "_ИмяТипаЗначения_"] = ИменаТипов[ИмяКолонки][ТипЗнч(СтрокаТаблицы[ИмяКолонки])];
КонецЕсли;
КонецЦикла;
Если ДобавлятьКолонкиИдентификаторов Тогда
Для Каждого ИмяКолонки Из КолонкиИдентификаторов Цикл
СтрокаТаблицы[ИмяКолонки + "_ИдентификаторЗначения_"] = СтроковыйИдентификаторЗначенияЛкс(СтрокаТаблицы[ИмяКолонки]);
КонецЦикла;
КонецЕсли;
Если ДобавлятьКолонкиРазмеров Тогда
Для Каждого ИмяКолонки Из КолонкиРазмеров Цикл
СтрокаТаблицы[ИмяКолонки + "_РазмерЗначения_"] = РазмерЗначенияЛкс(СтрокаТаблицы[ИмяКолонки]);
КонецЦикла;
КонецЕсли;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для Каждого ИмяКолонки Из КолонкиТипов Цикл Если Ложь Или ДобавлятьКолонкиТипов Или СтрокаТаблицы[ИмяКолонки] = Null Тогда СтрокаТаблицы[ИмяКолонки + "_ИмяТипаЗначения_"] = ИменаТипов[ИмяКолонки][ТипЗнч(СтрокаТаблицы[ИмяКолонки])]; КонецЕсли; КонецЦикла; Если ДобавлятьКолонкиИдентификаторов Тогда Для Каждого ИмяКолонки Из КолонкиИдентификаторов Цикл СтрокаТаблицы[ИмяКолонки + "_ИдентификаторЗначения_"] = СтроковыйИдентификаторЗначенияЛкс(СтрокаТаблицы[ИмяКолонки]); КонецЦикла; КонецЕсли; Если ДобавлятьКолонкиРазмеров Тогда Для Каждого ИмяКолонки Из КолонкиРазмеров Цикл СтрокаТаблицы[ИмяКолонки + "_РазмерЗначения_"] = РазмерЗначенияЛкс(СтрокаТаблицы[ИмяКолонки]); КонецЦикла; КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ДобавлятьКолонкиИдентификаторов И ТипЗнч(ТаблицаЗначений) = Тип("ДеревоЗначений") Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяКлючаСтрокиДереваЛкс());
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяКлючаСтрокиРодителяЛкс());
КонецЕсли;
Если НастройкаКомпоновки.Структура.Количество() = 0 Тогда
НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(НастройкаКомпоновки.Структура);
КонецЕсли;
СхемаКомпоновки = СоздатьСхемуПоТаблицамЗначенийЛкс(ВнешниеНаборыДанных, , , ИтогиЧисловыхКолонок,,, Иерархия);
#Если Сервер И Не Сервер Тогда
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
#КонецЕсли
//Если Иерархия Тогда
// СвязьНаборов = СхемаКомпоновки.СвязиНаборовДанных.Добавить();
// СвязьНаборов.НаборДанныхИсточник = СхемаКомпоновки.НаборыДанных[0].Имя;
// СвязьНаборов.НаборДанныхПриемник = СхемаКомпоновки.НаборыДанных[0].Имя;
// СвязьНаборов.ВыражениеИсточник = "_ИДВетки";
// СвязьНаборов.ВыражениеПриемник = "_ИДВеткиРодителя";
// СвязьНаборов.НачальноеВыражение = "Неопределено"; // вычисляемое значение
//КонецЕсли;
Если Отладка Тогда
ОтладитьЛкс(СхемаКомпоновки, , НастройкаКомпоновки, ВнешниеНаборыДанных);
Возврат Неопределено;
КонецЕсли;
Если ВыводВТаблицуЗначений Тогда
Приемник = СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(СхемаКомпоновки, НастройкаКомпоновки, Новый(ТипЗнч(ТаблицаЗначений)), ВнешниеНаборыДанных,,,,,,, СузитьТипы);
//Приемник = ТаблицаЗначений.Скопировать(, "…");
Иначе
Приемник = СкомпоноватьВТабличныйДокументЛкс(СхемаКомпоновки, НастройкаКомпоновки, Приемник, ВнешниеНаборыДанных, ДанныеРасшифровки, АвтофиксацияШапки,, ВстроитьЗначенияВРасшифровки);
#Если Сервер И Не Сервер Тогда
Приемник = Новый ТабличныйДокумент;
#КонецЕсли
Приемник.СохранятьСвойстваОтображения = Истина;
Если ЗначениеЗаполнено(ИмяТекущейКолонки) И ВыбранныеКолонки.Найти(ИмяТекущейКолонки) <> Неопределено Тогда
Приемник.ТекущаяОбласть = Приемник.Область(2, ПозицииКолонок[ИмяТекущейКолонки] + 1);
КонецЕсли;
Для Счетчик = 1 По ВыбранныеКолонки.Количество() Цикл
ИмяКолонки = ВыбранныеКолонки[Счетчик - 1];
Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда
Продолжить;
КонецЕсли;
Колонка = ТаблицаЗначений.Колонки.Найти(ИмяКолонки);
Если Истина
И Колонка <> Неопределено
И Колонка.ТипЗначения <> Новый ОписаниеТипов("Строка")
И Колонка.ТипЗначения <> Новый ОписаниеТипов
Тогда
Приемник.Область(1, ПозицииКолонок[ИмяКолонки] + 1).Примечание.Текст = "Типы значений: " + РасширенноеПредставлениеЛкс(Колонка.ТипЗначения);
КонецЕсли;
КонецЦикла;
МаксВысотаСтроки = 100;
Если ЗначениеЗаполнено(МаксВысотаСтроки) Тогда
Приемник.Область().ВысотаСтроки = МаксВысотаСтроки;
Приемник.Область().АвтоВысотаСтроки = Истина;
КонецЕсли;
КонецЕсли;
Возврат Приемник;
КонецФункции
// Для табличного поля может вернуть полное имя МД табличной части обработки!
// Поэтому вместо это функции рекомендуется вызов ирОбщий.ОбщийТипДанныхТабличногоПоляЛкс(ТабличноеПоле,,, ИмяТаблицыБД) = "Список"
Функция ИмяТаблицыБДДинамическогоСпискаЛкс(ТабличноеПоле, выхПолноеИмяМД = "") Экспорт
Если ТипЗнч(ТабличноеПоле) = Тип("Структура") Тогда
Возврат Неопределено;
ИначеЕсли ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
//выхПолноеИмяМД = ДинамическийСписок.ОсновнаяТаблица; // На клиенте недоступно
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(ТабличноеПоле);
ПутьКДаннымСписка = ПутьКДаннымЭлементаУправляемойФормыЛкс(ТабличноеПоле,, ЭтаФорма);
СлужебныеДанные = СлужебныеДанныеФормыЛкс(ЭтаФорма);
ДинамическийСписок = Неопределено;
Если Истина
И ЗначениеЗаполнено(ПутьКДаннымСписка)
И Найти(ПутьКДаннымСписка, ".") = 0
И СлужебныеДанные <> Неопределено
И СлужебныеДанные.Свойство("ДинамическиеСписки")
Тогда
СлужебныеДанные.ДинамическиеСписки.Свойство(ПутьКДаннымСписка, ДинамическийСписок);
КонецЕсли;
//Если ТипЗнч(ДинамическийСписок) = Тип("ДинамическийСписок") Тогда
Если ДинамическийСписок <> Неопределено Тогда
ПолноеИмяТаблицы = ДинамическийСписок.ОсновнаяТаблица;
Иначе
Если ЗначениеЗаполнено(ПутьКДаннымСписка) Тогда
Попытка
ДинамическийСписок = Вычислить("ЭтаФорма." + ПутьКДаннымСписка);
Исключение
// например путь к данным пользовательских настроек компоновки ДинамическийСписок.КомпоновщикНастроек.ПользовательскиеНастройки[0].Отбор
КонецПопытки;
КонецЕсли;
ТекущаяСтрока = ТабличноеПоле.ТекущаяСтрока;
ТипЗначенияСтроки = Неопределено;
Если Ложь
Или ТекущаяСтрока = Неопределено
Или ТипЗнч(ТекущаяСтрока) = Тип("Число") // Основная таблица не указана
Тогда
Если ТипЗнч(ДинамическийСписок) = Тип("ДинамическийСписок") Тогда
КомпоновщикНастроек = ДинамическийСписок.КомпоновщикНастроек;
#Если Сервер И Не Сервер Тогда
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
#КонецЕсли
ДоступныеПоля = КомпоновщикНастроек.Настройки.Выбор.ДоступныеПоляВыбора.Элементы;
ДоступноеПолеСсылка = ДоступныеПоля.Найти("Ссылка");
Если ДоступноеПолеСсылка <> Неопределено И ДоступныеПоля.Найти("ПометкаУдаления") <> Неопределено Тогда
ТипЗначенияСтроки = ДоступноеПолеСсылка.ТипЗначения.Типы()[0];
КонецЕсли;
КонецЕсли;
Иначе
ТипЗначенияСтроки = ТипЗнч(ТекущаяСтрока);
КонецЕсли;
Если ТипЗначенияСтроки = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗначенияСтроки);
Если ОбъектМД = Неопределено Тогда
Возврат Неопределено
КонецЕсли;
ПолноеИмяТаблицы = ОбъектМД.ПолноеИмя();
КонецЕсли;
#Если Сервер Тогда
Если Не ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда
ПолноеИмяТаблицы = СокрЛП(ТекстМеждуМаркерамиЛкс(ДинамическийСписок.ТекстЗапроса, "ИЗ ", " КАК _Т", Ложь));
КонецЕсли;
#КонецЕсли
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
Иначе
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(ТабличноеПоле.Значение));
КонецЕсли;
Если ОбъектМД <> Неопределено Тогда
выхПолноеИмяМД = ОбъектМД.ПолноеИмя();
КонецЕсли;
Если ЗначениеЗаполнено(выхПолноеИмяМД) Тогда
ПолноеИмяТаблицы = ирКэш.ИмяТаблицыИзМетаданныхЛкс(выхПолноеИмяМД);
КонецЕсли;
Возврат ПолноеИмяТаблицы;
КонецФункции
Функция РазбитьГрубоТекстПакетногоЗапросаНаЗапросыЛкс(Знач ТекстПакета, Знач ПозицияКурсора = Неопределено, выхПозиции = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
МассивТекстовЗапросов = мПлатформа.РазбитьГрубоТекстПакетногоЗапросаНаЗапросы(ТекстПакета, ПозицияКурсора, выхПозиции);
Возврат МассивТекстовЗапросов;
КонецФункции
// Формирует макет компоновки и извлекает из него запрос
// Параметры:
// Схема - СхемаКомпоновкиДанных
// НастройкаКомпоновкиДанных - НастройкиКомпоновкиДанных
// ДобавлятьУпорядочивание - Булево
// ПрефиксИменПараметров - Строка, *"" - используется для переименования параметров, полезно при смешивании нескольких запросов из компоновки в один
// выхСхемаКолонок - Структура, *Неопределено - если не равно Неопределено, то возвращается структура,
// где ключи - имена колонок, а значения - полные имена полей
//
// Результат - Запрос
//
Функция ЗапросИзКомпоновкиЛкс(Знач Схема, Знач НастройкаКомпоновки, Знач ДобавлятьУпорядочивание = Ложь, ПрефиксИменПараметров = "",
ДобавитьВыбранноеПоле = "", выхСхемаКолонок = Неопределено, Автоупорядочивание = Истина, ПроверятьДоступностьПолей = Ложь, СПредставлениямиСсылок = Ложь) Экспорт
НастройкаКомпоновки = КопияОбъектаЛкс(НастройкаКомпоновки, Истина);
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных
#КонецЕсли
Если НастройкаКомпоновки.Структура.Количество() = 0 Тогда
НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(НастройкаКомпоновки.Структура);
КонецЕсли;
Если ЗначениеЗаполнено(ДобавитьВыбранноеПоле) Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ДобавитьВыбранноеПоле);
КонецЕсли;
Если НастройкаКомпоновки.Выбор.Элементы.Количество() = 0 Тогда
ДобавитьВсеДоступныеПоляКомпоновкиВВыбранныеЛкс(Схема, НастройкаКомпоновки); // Опасно
КонецЕсли;
Если Не СПредставлениямиСсылок Тогда
Для Каждого ВыбранноеПоле Из ВсеВыбранныеПоляГруппировкиКомпоновкиЛкс(НастройкаКомпоновки.Выбор, Истина) Цикл
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(НастройкаКомпоновки.Структура[0].Отбор, "" + ВыбранноеПоле.Поле); // Отбор здесь используется не для фильтрации
КонецЦикла;
НастройкаКомпоновки.Выбор.Элементы.Очистить();
КонецЕсли;
КопияПорядка = ОтобратьКоллекциюЛкс(НастройкаКомпоновки.Порядок.Элементы, "Э.Использование");
НастройкаКомпоновки.Порядок.Элементы.Очистить();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// ирОбщий.От(Схема, НастройкаКомпоновки)
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, НастройкаКомпоновки, ,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"), ПроверятьДоступностьПолей);
Если МакетКомпоновки.НаборыДанных.Количество() = 0 Тогда
// Нет прав на таблицу
Возврат Неопределено;
КонецЕсли;
СтрокаПорядка = ВыражениеПорядкаКомпоновкиНаЯзыкеЗапросовЛкс(КопияПорядка,,,, МакетКомпоновки.НаборыДанных[0].Поля);
Запрос = Новый Запрос;
Если МакетКомпоновки.НаборыДанных.Количество() > 2 Тогда
СообщитьЛкс("В макете компоновки обнаружено более одного запроса");
КонецЕсли;
ТекстЗапроса = МакетКомпоновки.НаборыДанных[0].Запрос;
Если ДобавлятьУпорядочивание Тогда
// TODO Переделать на схему запроса
Если ЗначениеЗаполнено(СтрокаПорядка) Тогда
// Порядок от группировок помещается сразу в текст запроса платформой
Если СтрНайтиЛкс(ПоследнийФрагментЛкс(ТекстЗапроса, ";"), "УПОРЯДОЧИТЬ ПО") > 0 Тогда
ТекстЗапроса = ТекстЗапроса + ",
| " + СтрокаПорядка;
Иначе
ТекстЗапроса = ТекстЗапроса + "
|//Секция_Упорядочить. Этот комментарий используется в коде
|УПОРЯДОЧИТЬ ПО
| " + СтрокаПорядка;
КонецЕсли;
КонецЕсли;
Если Ложь
Или Автоупорядочивание
//Или ЗначениеЗаполнено(СтрокаПорядка)
Тогда
ТекстЗапроса = ТекстЗапроса + "
|//Секция_Упорядочить. Этот комментарий используется в коде
|АВТОУПОРЯДОЧИВАНИЕ";
КонецЕсли;
КонецЕсли;
Запрос.Текст = ТекстЗапроса;
Для Каждого ЗначениеПараметра Из МакетКомпоновки.ЗначенияПараметров Цикл
Запрос.Параметры.Вставить(ЗначениеПараметра.Имя, ЗначениеПараметра.Значение);
КонецЦикла;
Если ПрефиксИменПараметров <> "" Тогда
ДобавитьПрефиксВсемПараметрамЗапросаЛкс(Запрос, ПрефиксИменПараметров);
КонецЕсли;
Если выхСхемаКолонок <> Неопределено Тогда
//выхСхемаКолонок = ПолучитьСхемуКолонокМакетаКомпоновкиДанныхЛкс(МакетКомпоновки);
//
НаборДанныхМакета = МакетКомпоновки.НаборыДанных[0];
Для Каждого ПолеНабора Из НаборДанныхМакета.Поля Цикл
выхСхемаКолонок.Вставить(ПолеНабора.Имя, ПолеНабора.ПутьКДанным);
КонецЦикла;
Для Каждого ВложенныйНаборДанных Из НаборДанныхМакета.ВложенныеНаборыДанных Цикл
выхСхемаКолонок.Вставить(ВложенныйНаборДанных.Имя, ВложенныйНаборДанных.ПутьКДанным);
КонецЦикла;
КонецЕсли;
Возврат Запрос;
КонецФункции
Функция ТекстОтбораЗапросаКомпоновкиЛкс(ТекстЗапросаСОтбором, ПсевдонимТаблицыПередГДЕ = "Т") Экспорт
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
РегВыражение.Multiline = Ложь;
РегВыражение.Pattern = "(?:AS|КАК)\s+" + ПсевдонимТаблицыПередГДЕ + "\s+(?:ГДЕ|WHERE)((?:.|\n|\r)+)";
Найденные = РегВыражение.НайтиВхождения(ТекстЗапросаСОтбором);
Если Найденные.Количество() > 0 Тогда
ТекстОтбора = Найденные[0].Submatches(0);
Иначе
ТекстОтбора = " ИСТИНА ";
КонецЕсли;
Возврат ТекстОтбора;
КонецФункции
Функция ЗапросОтбораПоТаблицеКлючейЛкс(Запрос, Знач СтруктураКлюча, Знач ТолькоСуммируемыеКолонки = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Запрос = Новый Запрос;
#КонецЕсли
СхемаЗапроса = Вычислить("Новый СхемаЗапроса");
#Если Сервер И Не Сервер Тогда
СхемаЗапроса = Новый СхемаЗапроса;
#КонецЕсли
СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);
ПоследнийЗапрос = СхемаЗапроса.ПакетЗапросов[СхемаЗапроса.ПакетЗапросов.Количество() - 1];
ТаблицаИсточник = ПоследнийЗапрос.Операторы[0].Источники[0].Источник;
ПсевдонимОсновнойТаблицы = ТаблицаИсточник.Псевдоним;
ЗапросВыбора = СхемаЗапроса.ПакетЗапросов.Добавить(Тип("ЗапросВыбораСхемыЗапроса"));
ЗапросВыбора.ТаблицаДляПомещения = ИмяВременнойТаблицыДляТаблицыБДЛкс(ТаблицаИсточник.ИмяТаблицы, "КлючиОтбираемыхСтрок");
ИндексЗапроса = СхемаЗапроса.ПакетЗапросов.Количество() - 1;
СхемаЗапроса.ПакетЗапросов.Сдвинуть(ИндексЗапроса, - ИндексЗапроса);
ОператорЗапроса = ЗапросВыбора.Операторы[0];
ВыбираемыеПоля = ОператорЗапроса.ВыбираемыеПоля;
ОператорЗапроса.Источники.Добавить(Тип("ОписаниеВременнойТаблицыСхемыЗапроса"), "&Ключи", "Т");
ПоляКлюча = Новый Массив;
Маркер = "_88цвап0192_";
Для Каждого ЭлементКлюча Из СтруктураКлюча Цикл
ВыбираемыеПоля.Добавить("Т." + ЭлементКлюча.Ключ);
Если ЭлементКлюча.Значение.СодержитТип(Тип("УникальныйИдентификатор")) Тогда
// Антибаг платформы https://www.hostedredmine.com/issues/966821
ВыражениеПоля = """" + Маркер + ПсевдонимОсновнойТаблицы + "." + ЭлементКлюча.Ключ + Маркер + """";
Иначе
ВыражениеПоля = ПсевдонимОсновнойТаблицы + "." + ЭлементКлюча.Ключ;
КонецЕсли;
ПоляКлюча.Добавить(ВыражениеПоля);
КонецЦикла;
СтрокаКлюча = СтрСоединитьЛкс(ПоляКлюча);
Для каждого ОператорЗапроса Из ПоследнийЗапрос.Операторы Цикл
// На низких режимах совместимости некорректно работает платформа https://www.hostedredmine.com/issues/959039
ВыражениеЗапроса = "(" + СтрокаКлюча + ") В (ВЫБРАТЬ " + СтрокаКлюча + " ИЗ " + ЗапросВыбора.ТаблицаДляПомещения + " КАК " + ПсевдонимОсновнойТаблицы + ")";
ВыражениеЗапроса = Вычислить("Новый ВыражениеСхемыЗапроса(ВыражениеЗапроса)");
#Если Сервер И Не Сервер Тогда
ВыражениеЗапроса = Новый ВыражениеСхемыЗапроса;
#КонецЕсли
ОператорЗапроса.Отбор.Очистить();
ОператорЗапроса.Отбор.Добавить(ВыражениеЗапроса); // В режиме совместимости 8.2.13 некорректно добавляется выражение
КонецЦикла;
Если ТолькоСуммируемыеКолонки Тогда
ПоследнийЗапрос.Порядок.Очистить();
Для Индекс = 1 - ПоследнийЗапрос.Колонки.Количество() По 0 Цикл // Обратный обход
Колонка = ПоследнийЗапрос.Колонки[-Индекс];
Если Ложь
И Не Колонка.ТипЗначения.СодержитТип(Тип("Число"))
И Не Колонка.ТипЗначения.СодержитТип(Тип("Булево"))
Тогда
Для каждого ОператорЗапроса Из ПоследнийЗапрос.Операторы Цикл
ОператорЗапроса.ВыбираемыеПоля.Удалить(-Индекс);
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();
Запрос.Текст = СтрЗаменить(Запрос.Текст, """" + Маркер, "");
Запрос.Текст = СтрЗаменить(Запрос.Текст, Маркер + """", "");
Возврат Запрос;
КонецФункции
Функция ОбренутьВыражениеЗапросаДляГруппировкиЛкс(Выражение, ОписаниеТипов, ДобавитьКонечноеПодчеркивание = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов = Новый ОписаниеТипов;
#КонецЕсли
Результат = Выражение;
Если ОписаниеТипов.СодержитТип(Тип("Строка")) Тогда
Если ОписаниеТипов.КвалификаторыСтроки.Длина = 0 Тогда
Результат = "ПОДСТРОКА(ВЫРАЗИТЬ(" + Результат + " КАК СТРОКА(300)), 1, 300)";
КонецЕсли;
Если ДобавитьКонечноеПодчеркивание Тогда
Результат = Результат + " + ""_"""
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает строку для установки порядка компоновки.
//
// Параметры:
// ПорядокКомпоновки - ПорядокКомпоновкиДанных, ЭлементыПорядкаКомпоновкиДанных
// ИсключаемоеПоле - Строка
// СимволЗаменыТочки - Строка
// ДиалектSQL - Строка
// ПутиКДаннымПолей - ПоляНабораДанныхЗапросаМакетаКомпоновкиДанных
//
// Возвращаемое значение:
// Строка - для установки порядка.
//
Функция ВыражениеПорядкаКомпоновкиНаЯзыкеЗапросовЛкс(Знач ПорядокКомпоновки, ИсключаемоеПоле = "", СимволЗаменыТочки = Неопределено, ДиалектSQL = "1С", ПутиКДаннымПолей = Неопределено,
УчитыватьПравыеПробелыСтрок = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый НастройкиКомпоновкиДанных;
ПорядокКомпоновки = Пустышка.Порядок;
#КонецЕсли
Это1С = СтрокиРавныЛкс(ДиалектSQL, "1С");
Если Это1С Тогда
СтрокаВозр = "Возр";
СтрокаУбыв = "Убыв";
Иначе
СтрокаВозр = "Asc";
СтрокаУбыв = "Desc";
КонецЕсли;
Если ТипЗнч(ПорядокКомпоновки) = Тип("ПорядокКомпоновкиДанных") Тогда
Если Это1С И ПутиКДаннымПолей = Неопределено Тогда
ДоступныеПоля = ПорядокКомпоновки.ДоступныеПоляПорядка;
КонецЕсли;
ПорядокКомпоновки = ПорядокКомпоновки.Элементы;
КонецЕсли;
Строка = "";
Для Каждого ЭлементПорядка Из ПорядокКомпоновки Цикл
Если Ложь
Или Не ЭлементПорядка.Использование
Или ТипЗнч(ЭлементПорядка) = Тип("АвтоЭлементПорядкаКомпоновкиДанных")
Или ИсключаемоеПоле = "" + ЭлементПорядка.Поле
Тогда
Продолжить;
КонецЕсли;
ИмяПоля = "" + ЭлементПорядка.Поле;
Если ПутиКДаннымПолей <> Неопределено Тогда
Фрагменты = ирОбщий.СтрРазделитьЛкс(ИмяПоля);
ПутьКДаннымПоля = НайтиЭлементКоллекцииЛкс(ПутиКДаннымПолей, "ПутьКДанным", Фрагменты[0]);
Если ПутьКДаннымПоля = Неопределено Тогда
// Например реквизит ТЧ
Продолжить;
КонецЕсли;
Фрагменты[0] = ПутьКДаннымПоля.Имя;
ИмяПоля = СтрСоединитьЛкс(Фрагменты, ".");
Иначе
Если СимволЗаменыТочки <> Неопределено Тогда
ИмяПоля = СтрЗаменить(ИмяПоля, ".", СимволЗаменыТочки);
КонецЕсли;
Если ДоступныеПоля <> Неопределено Тогда
ДоступноеПоле = ДоступныеПоля.НайтиПоле(ЭлементПорядка.Поле);
Если ДоступноеПоле <> Неопределено Тогда
ИмяПоля = ОбренутьВыражениеЗапросаДляГруппировкиЛкс(ИмяПоля, ДоступноеПоле.ТипЗначения, УчитыватьПравыеПробелыСтрок);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Строка = Строка + ", " + ИмяПоля + " ";
Если ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр Тогда
Строка = Строка + СтрокаВозр;
Иначе
Строка = Строка + СтрокаУбыв;
КонецЕсли;
КонецЦикла;
Возврат Сред(Строка, 3);
КонецФункции
// ТипНастроек - Число
Функция НастройкиДинамическогоСпискаЛкс(Знач ДинамическийСписок, ТипНастроек = "Результирующие") Экспорт
Если ТипЗнч(ДинамическийСписок) = Тип("ДинамическийСписок") Тогда
Если ТипНастроек = "Результирующие" Тогда
НастройкиСписка = ДинамическийСписок.КомпоновщикНастроек.ПолучитьНастройки();
ИначеЕсли ТипНастроек = "Фиксированные" Тогда
НастройкиСписка = ДинамическийСписок.КомпоновщикНастроек.ФиксированныеНастройки;
ИначеЕсли Истина
И ТипНастроек = "Пользовательские"
И ирКэш.НомерРежимаСовместимостиЛкс() > 802013 // https://www.hostedredmine.com/issues/952896
Тогда
НастройкиСписка = СтруктураПользовательскихНастроекКомпоновкиЛкс(ДинамическийСписок.КомпоновщикНастроек.ПользовательскиеНастройки);
Иначе
НастройкиСписка = ДинамическийСписок;
КонецЕсли;
Иначе
НастройкиСписка = ДинамическийСписок;
КонецЕсли;
Возврат НастройкиСписка;
КонецФункции
Функция СтруктураПользовательскихНастроекКомпоновкиЛкс(Знач ПользовательскиеНастройки) Экспорт
#Если Сервер И Не Сервер Тогда
ПользовательскиеНастройки = Новый ПользовательскиеНастройкиКомпоновкиДанных;
#КонецЕсли
НастройкиСписка = Новый Структура("Отбор, Порядок, УсловноеОформление");
Для Каждого ЭлементПользовательскихНастроек Из ПользовательскиеНастройки.Элементы Цикл
Если ТипЗнч(ЭлементПользовательскихНастроек) = Тип("ОтборКомпоновкиДанных") Тогда
НастройкиСписка.Отбор = ЭлементПользовательскихНастроек;
ИначеЕсли ТипЗнч(ЭлементПользовательскихНастроек) = Тип("ПорядокКомпоновкиДанных") Тогда
НастройкиСписка.Порядок = ЭлементПользовательскихНастроек;
ИначеЕсли ТипЗнч(ЭлементПользовательскихНастроек) = Тип("УсловноеОформлениеКомпоновкиДанных") Тогда
НастройкиСписка.УсловноеОформление = ЭлементПользовательскихНастроек;
КонецЕсли;
КонецЦикла;
Возврат НастройкиСписка;
КонецФункции
Функция ПредельноеЧислоВидимыхКолонокДинамСпискаЛкс() Экспорт
Возврат 40;
КонецФункции
Функция ИмяОтсутствияПодсистемыЛкс() Экспорт
Возврат "<Не входящие в подсистемы>";
КонецФункции
// .
// Параметры:
// ПолноеИмяПодсистемы - Строка - чистое иерархическое имя подсистемы
// ПодсистемаПеревод - -
//
// Возвращаемое значение:
// ОбъектМетаданныхПодсистема -
//
Функция ПодсистемаПоПолномуИмениЛкс(Знач ПолноеИмяПодсистемы, Знач ПодсистемаПеревод = "") Экспорт
Если Не ЗначениеЗаполнено(ПодсистемаПеревод) Тогда
ПодсистемаПеревод = ПеревестиСтроку("Подсистема");
КонецЕсли;
МДПодсистема = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПодсистемаПеревод + "." + СтрЗаменить(ПолноеИмяПодсистемы, ".", "." + ПодсистемаПеревод + "."));
Возврат МДПодсистема;
КонецФункции
// .
// Параметры:
// Подсистема - -
// ПодсистемаПеревод - -
//
// Возвращаемое значение:
// Строка - чистое иерархическое имя подсистемы
//
Функция ПолноеИмяПодсистемыЛкс(Знач Подсистема, Знач ПодсистемаПеревод = "") Экспорт
Если Не ЗначениеЗаполнено(ПодсистемаПеревод) Тогда
ПодсистемаПеревод = ПеревестиСтроку("Подсистема");
КонецЕсли;
ПолноеИмяПодсистемы = СтрЗаменить(Подсистема.ПолноеИмя(), ПодсистемаПеревод + ".", "");
Возврат ПолноеИмяПодсистемы;
КонецФункции
// .
//
// Параметры:
// СписокПодсистем - СписокЗначений - значение элемента содержит полное имя подсистемы в виде "ИмяПодсистемы1[.ИмяПодсистемы2...]"
// СтрокаДереваПодсистем - -
// ОбъектыВыбранныхПодсистем - Соответствие - дублирует возвращаемое значение
//
// Возвращаемое значение:
// Соответствие - :
// * Ключ - ОбъектМетаданных - входящий в заданные подсистемы
//
Функция ОбъектыПодсистемЛкс(Знач СписокПодсистем, СтрокаДереваПодсистем = Неопределено, ОбъектыВыбранныхПодсистем = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
СписокПодсистем = Новый СписокЗначений;
#КонецЕсли
Если ОбъектыВыбранныхПодсистем = Неопределено Тогда
ОбъектыВыбранныхПодсистем = Новый Соответствие;
КонецЕсли;
ПодсистемаПеревод = ПеревестиСтроку("Подсистема");
ИмяОтсутствияПодсистемы = ИмяОтсутствияПодсистемыЛкс();
Для Каждого ЭлементСписка Из СписокПодсистем Цикл
Если ЭлементСписка.Значение = ИмяОтсутствияПодсистемы Тогда
ВсеПодсистемы = Новый СписокЗначений;
ВсеПодсистемы.ЗагрузитьЗначения(ВыгрузитьСвойствоЛкс(ирКэш.ВсеПодсистемыЛкс()));
ОбъектыВсехПодсистем = ОбъектыПодсистемЛкс(ВсеПодсистемы);
Для Каждого СтрокаТипаМетаданных Из ирКэш.ТипыМетаОбъектов(, Ложь, Ложь) Цикл
Если СтрокаТипаМетаданных.Единственное = "Перерасчет" Тогда
Продолжить;
КонецЕсли;
Для Каждого ОбъектМД Из Метаданные[СтрокаТипаМетаданных.Множественное] Цикл
Если ОбъектыВсехПодсистем[ОбъектМД] <> Неопределено Тогда
Продолжить;
КонецЕсли;
ОбъектыВыбранныхПодсистем.Вставить(ОбъектМД, 1);
КонецЦикла;
КонецЦикла;
Иначе
ПодсистемаМД = ПодсистемаПоПолномуИмениЛкс(ЭлементСписка.Значение);
Если ПодсистемаМД <> Неопределено Тогда
Для Каждого ЭлементСостава Из ПодсистемаМД.Состав Цикл
ОбъектыВыбранныхПодсистем.Вставить(ЭлементСостава, 1);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ОбъектыВыбранныхПодсистем;
КонецФункции
// Функция - Подсистемы объекта лкс
//
// Параметры:
// ОбъектМД - ОбъектМетаданных -
//
// Возвращаемое значение:
// Массив, ОбъектМетаданныхПодсистема -
//
Функция ПодсистемыОбъектаЛкс(Знач ОбъектМД, Знач ДостаточноОдной = Ложь) Экспорт
ВсеПодсистемы = ирКэш.ВсеПодсистемыЛкс();
Результат = Новый Массив;
Для Каждого ЭлементСписка Из ВсеПодсистемы Цикл
Если ЭлементСписка.Значение.Состав.Содержит(ОбъектМД) Тогда
Результат.Добавить(ЭлементСписка.Значение);
Если ДостаточноОдной Тогда
Возврат Результат[0];
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ДостаточноОдной Тогда
Возврат Неопределено;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция НоваяТаблицаНастройкиСтандартногоХранилищаЛкс() Экспорт
ТабОписаний = Новый ТаблицаЗначений;
ТабОписаний.Колонки.Добавить("ИмяХранилища");
ТабОписаний.Колонки.Добавить("ИмяОбъекта");
ТабОписаний.Колонки.Добавить("КлючНастроек");
ТабОписаний.Колонки.Добавить("Настройка");
ТабОписаний.Колонки.Добавить("ИмяПользователя");
ТабОписаний.Колонки.Добавить("Описание");
Возврат ТабОписаний;
КонецФункции
Функция НоваяТаблицаНайденныеСсылкиЛкс() Экспорт
НайденныеСсылки = Новый ТаблицаЗначений;
НайденныеСсылки.Колонки.Добавить("Ссылка");
НайденныеСсылки.Колонки.Добавить("Данные");
НайденныеСсылки.Колонки.Добавить("Метаданные");
ПодготовитьТаблицуНайтиПоСсылкамЛкс(НайденныеСсылки);
//! НайденныеСсылки.Колонки.Добавить("ТаблицаСвязи");
Возврат НайденныеСсылки;
КонецФункции
Процедура ПодготовитьТаблицуНайтиПоСсылкамЛкс(Знач НайденныеСсылки) Экспорт
НайденныеСсылки.Колонки.Добавить("ТаблицаСвязи", Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(100)));
ирОбщий.ДобавитьИндексВТаблицуЛкс(НайденныеСсылки, "Ссылка");
ирОбщий.ДобавитьИндексВТаблицуЛкс(НайденныеСсылки, "Ссылка, Данные");
ирОбщий.ДобавитьИндексВТаблицуЛкс(НайденныеСсылки, "Данные");
КонецПроцедуры
Функция НоваяТаблицаЗначенийЛкс(ИменаКолонок) Экспорт
Результат = Новый ТаблицаЗначений;
Для Каждого ИмяКолонки Из СтрРазделитьЛкс(ИменаКолонок, ",", Истина) Цикл
Результат.Колонки.Добавить(ИмяКолонки);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция МетаданныеНаборовЗаписейПоРегистраторуЛкс(мдОбъекта, ВключаяПоследовательности = Ложь, ВключаяПерерасчеты = Ложь, Сортировать = Ложь) Экспорт
ОбъектыМД = Новый Массив();
ЗащитаОтДублей = Новый Соответствие;
Для Каждого МетаРегистр из мдОбъекта.Движения Цикл
Если ЗащитаОтДублей[МетаРегистр.Имя] <> Неопределено Тогда
// https://www.hostedredmine.com/issues/943296
Продолжить;
КонецЕсли;
ЗащитаОтДублей[МетаРегистр.Имя] = 1;
ОбъектыМД.Добавить(МетаРегистр);
Если ВключаяПерерасчеты Тогда
Если ЛиКорневойТипРегистраРасчетаЛкс(ПервыйФрагментЛкс(МетаРегистр.ПолноеИмя())) Тогда
Для Каждого ПерерасчетМД Из МетаРегистр.Перерасчеты Цикл
ОбъектыМД.Добавить(ПерерасчетМД);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ВключаяПоследовательности Тогда
Для Каждого МетаПоследовательность Из Метаданные.Последовательности Цикл
Если МетаПоследовательность.Документы.Содержит(мдОбъекта) Тогда
ОбъектыМД.Добавить(МетаПоследовательность);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Сортировать Тогда
Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(ОбъектыМД);
Для Каждого ЭлементСписка Из Список Цикл
ЭлементСписка.Представление = ЭлементСписка.Значение.Имя;
КонецЦикла;
Список.СортироватьПоПредставлению();
ОбъектыМД = Список.ВыгрузитьЗначения();
КонецЕсли;
Возврат ОбъектыМД;
КонецФункции
// Функция считывает в табличный документ данные из текстового файла
//
// Параметры:
// ТабличныйДокумент - ТабличныйДокумент, в который необходимо прочитать данные
// ИмяФайла - имя текстового файла, из которого необходимо прочитать данные
//
// Возвращаемое значение:
// Истина, если файл прочитан, Ложь - иначе
//
Функция ПрочитатьТабличныйДокументИзТекстаЛкс(Знач ТабличныйДокумент, Знач ИмяФайла, Разделитель = ",", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
#КонецЕсли
ВыбФайл = Новый Файл(ИмяФайла);
Если НЕ ВыбФайл.Существует() Тогда
СообщитьЛкс("Файл не существует!");
Возврат Ложь;
КонецЕсли;
Попытка
Текст = ПрочитатьТекстИзФайлаЛкс(ИмяФайла);
Исключение
СообщитьЛкс("Ошибка открытия файла!");
Возврат Ложь;
КонецПопытки;
ТабличныйДокумент.Очистить();
#Если Клиент Тогда
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ФормаРазбивки = мПлатформа.ПолучитьФорму("РазбивкаТекста");
ФормаРазбивки.Приемник = ТабличныйДокумент;
ФормаРазбивки.Текст = Текст;
Если ФормаРазбивки.ОткрытьМодально() = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
#Иначе
ТаблицаИзСтрокиСРазделителемЛкс(Текст, Разделитель, ОбрезатьНепечатныеСимволы, ТабличныйДокумент);
#КонецЕсли
Возврат Истина;
КонецФункции
// Функция считывает в табличный документ данные из файла в формате dBase III (*.dbf)
//
// Параметры:
// ТабличныйДокумент - ТабличныйДокумент, в который необходимо прочитать данные
// ИмяФайла - имя файла в формате TXT, из которого необходимо прочитать данные
//
// Возвращаемое значение:
// Истина, если файл прочитан, Ложь - иначе
//
Функция ПрочитатьТабличныйДокументИзDBFЛкс(Знач ТабличныйДокумент, Знач ИмяФайла) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
#КонецЕсли
ВыбФайл = Новый Файл(ИмяФайла);
Если НЕ ВыбФайл.Существует() Тогда
СообщитьЛкс("Файл не существует!");
Возврат Ложь;
КонецЕсли;
XBase = Новый XBase;
XBase.Кодировка = КодировкаXBase.OEM;
Попытка
XBase.ОткрытьФайл(ИмяФайла);
Исключение
СообщитьЛкс("Ошибка открытия файла!");
Возврат Ложь;
КонецПопытки;
ТабличныйДокумент.Очистить();
ТекущаяСтрока = 1;
ТекущаяКолонка = 0;
Для каждого Поле Из XBase.поля Цикл
ТекущаяКолонка = ТекущаяКолонка + 1;
ТабличныйДокумент.Область("R" + Формат(ТекущаяСтрока, "ЧГ=") +"C" + Формат(ТекущаяКолонка, "ЧГ=")).Текст = Поле.Имя;
КонецЦикла;
Рез = XBase.Первая();
Пока Не XBase.ВКонце() Цикл
ТекущаяСтрока = ТекущаяСтрока + 1;
ТекущаяКолонка = 0;
Для каждого Поле Из XBase.поля Цикл
ТекущаяКолонка = ТекущаяКолонка + 1;
Если Поле.Тип = "M" Тогда
Продолжить;
КонецЕсли;
ТабличныйДокумент.Область("R" + Формат(ТекущаяСтрока, "ЧГ=") +"C" + Формат(ТекущаяКолонка, "ЧГ=")).Текст = XBase.ПолучитьЗначениеПоля(ТекущаяКолонка - 1);
КонецЦикла;
XBase.Следующая();
КонецЦикла;
Возврат Истина;
КонецФункции // ()
Процедура ПрочитатьТабличныйДокументExcelЛкс(Знач ТабличныйДокумент, Знач ИмяФайла, Знач СпособЧтенияЗначений = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
#КонецЕсли
Если ирКэш.НомерВерсииПлатформыЛкс() < 803001 Тогда
ТабличныйДокумент.Прочитать(ИмяФайла);
Иначе
Если СпособЧтенияЗначений = Неопределено Тогда
#Если Клиент Тогда
ЧитатьЗначения = Вопрос("Читать содержимое ячеек как значения? Иначе оно будет прочитано как тексты.", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да;
#Иначе
ЧитатьЗначения = Истина;
#КонецЕсли
Если ЧитатьЗначения Тогда
СпособЧтенияЗначений = Вычислить("СпособЧтенияЗначенийТабличногоДокумента").Значение;
КонецЕсли;
КонецЕсли;
ТабличныйДокумент.Прочитать(ИмяФайла, СпособЧтенияЗначений);
КонецЕсли;
КонецПроцедуры
// .
// Параметры:
// ТаблицаПриемник - ТабличныйДокумент, ТаблицаЗначений, *Неопределено
//
Функция ТаблицаИзСтрокиСРазделителемЛкс(Знач Текст, Разделитель = ",", ОбрезатьНепечатныеСимволы = Ложь, Знач ИменаКолонокИзПервойСтроки = Ложь, Знач ТаблицаПриемник = Неопределено,
Знач ОписаниеТипов = Неопределено, Знач РазворачиватьКавычки = Истина) Экспорт
Если ТаблицаПриемник = Неопределено Тогда
ТаблицаПриемник = Новый ТаблицаЗначений;
КонецЕсли;
КоличествоКолонок = 0;
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(Текст);
КоличествоСтрок = ТекстовыйДокумент.КоличествоСтрок();
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Индикатор = ПолучитьИндикаторПроцессаЛкс(КоличествоСтрок, "Разбивка текста");
Для СчетчикСтроки = 1 По КоличествоСтрок Цикл
Если СчетчикСтроки % 100 = 0 Тогда
ОбработатьИндикаторЛкс(Индикатор, СчетчикСтроки);
КонецЕсли;
СтрокаТекста = ТекстовыйДокумент.ПолучитьСтроку(СчетчикСтроки);
// Можно заменить на регулярный поиск https://infostart.ru/1c/articles/2141752/
Массив = СтрРазделитьЛкс(СтрокаТекста, Разделитель, ОбрезатьНепечатныеСимволы, Истина, РазворачиватьКавычки);
Если КоличествоКолонок < Массив.Количество() Тогда
Если ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений") Тогда
Для ИндексКолонки = КоличествоКолонок По Массив.Количество() - 1 Цикл
Если ИменаКолонокИзПервойСтроки И СчетчикСтроки = 1 Тогда
ЗаголовокКолонки = Массив[ИндексКолонки];
ИмяКолонки = ИдентификаторИзПредставленияЛкс(ЗаголовокКолонки);
ИмяКолонки = АвтоУникальноеИмяВКоллекцииЛкс(ТаблицаПриемник.Колонки, ИмяКолонки);
Иначе
ИмяКолонки = "Колонка" + XMLСтрока(ИндексКолонки);
ЗаголовокКолонки = "";
КонецЕсли;
ТаблицаПриемник.Колонки.Добавить(ИмяКолонки, ОписаниеТипов, ЗаголовокКолонки);
КонецЦикла;
КонецЕсли;
КоличествоКолонок = Массив.Количество();
//ИначеЕсли КоличествоКолонок > Массив.Количество() Тогда
// СообщитьЛкс("В строке текст №" + XMLСтрока(СчетчикСтроки) + " указаны значения не для всех колонок");
КонецЕсли;
Если ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений") Тогда
Если ИменаКолонокИзПервойСтроки И СчетчикСтроки = 1 Тогда
Продолжить;
КонецЕсли;
СтрокаТаблицы = ТаблицаПриемник.Добавить();
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для ИндексКолонки = 0 По Массив.ВГраница() Цикл
СтрокаТаблицы[ИндексКолонки] = Массив[ИндексКолонки];
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для ИндексКолонки = 0 По Массив.ВГраница() Цикл СтрокаТаблицы[ИндексКолонки] = Массив[ИндексКолонки]; КонецЦикла;
КонецЕсли;
Иначе //Если ТипЗнч(ТаблицаПриемник) = Тип("ТабличныйДокумент") Тогда
#Если Сервер И Не Сервер Тогда
ТаблицаПриемник = Новый ТабличныйДокумент;
#КонецЕсли
Для ИндексКолонки = 0 По Массив.ВГраница() Цикл
ТаблицаПриемник.Область(СчетчикСтроки, ИндексКолонки + 1).Текст = Массив[ИндексКолонки];
КонецЦикла;
КонецЕсли;
КонецЦикла;
ОсвободитьИндикаторПроцессаЛкс();
#Если Сервер И Не Сервер Тогда
ТаблицаПриемник = Новый ТаблицаЗначений; // для моей подсказки
#КонецЕсли
Возврат ТаблицаПриемник;
КонецФункции
Процедура КонвертироватьСтроковуюТаблицуВТипизированнуюЛкс(ТаблицаСтроковыхЗначений, ТаблицаТипизированая, АмериканскоеПоложениеМесяца = Ложь, РазворачиватьКавычки = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаСтроковыхЗначений = Новый ТаблицаЗначений;
ТаблицаТипизированая = Новый ТаблицаЗначений;
#КонецЕсли
Для Каждого СтрокаСтроковая Из ТаблицаСтроковыхЗначений Цикл
СтрокаТипизированная = ТаблицаТипизированая.Добавить();
Для Каждого Колонка Из ТаблицаСтроковыхЗначений.Колонки Цикл
СтроковоеЗначение = СтрокаСтроковая[Колонка.Имя];
Если Истина
И РазворачиватьКавычки
И Лев(СтроковоеЗначение, 1) = """"
И Прав(СтроковоеЗначение, 1) = """"
Тогда
СтроковоеЗначение = ТекстИзВстроенногоЯзыкаЛкс(СтроковоеЗначение);
//СтроковеЗначение = СтрокаБезКонцаЛкс(Сред(СтроковеЗначение, 2), 1);
КонецЕсли;
ТипКолонки = ТипЗнч(СтрокаТипизированная[Колонка.Имя]);
Если ТипКолонки = Тип("Дата") Тогда
СтрокаТипизированная[Колонка.Имя] = СтрокаВДатуЛкс(СтроковоеЗначение,,, АмериканскоеПоложениеМесяца);
ИначеЕсли Ложь
Или ТипКолонки = Тип("Число")
Или ТипКолонки = Тип("Булево")
Тогда
СтрокаТипизированная[Колонка.Имя] = СтрокаВЧислоЛкс(СтроковоеЗначение);
Иначе
СтрокаТипизированная[Колонка.Имя] = СтроковоеЗначение;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция ОбщийТипДанныхТабличногоПоляЛкс(Знач ТабличноеПоле, ПреобразоватьТипДанныхФормыИнструмента = Ложь, выхСтруктураТипаМетаданных = Неопределено, выхПолноеИмяТаблицыБД = "",
выхДанныеТабличногоПоля = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Если ТипЗнч(ТабличноеПоле) = Тип("Структура") Тогда
Если Не ТабличноеПоле.Свойство("ОписаниеТипов") Тогда
// Имитатор табличного поля
Возврат Неопределено;
КонецЕсли;
// Имитатор таблицы управляемой формы
Если ТабличноеПоле.ОписаниеТипов <> Неопределено Тогда
ТипЗначенияТабличногоПоля = ТабличноеПоле.ОписаниеТипов.Типы()[0];
Иначе
ТипЗначенияТабличногоПоля = Тип("Неопределено");
КонецЕсли;
Иначе
выхДанныеТабличногоПоля = ДанныеЭлементаФормыЛкс(ТабличноеПоле);
Если ПреобразоватьТипДанныхФормыИнструмента Тогда
ТипЗначенияТабличногоПоля = ТипЗначенияЭлементаФормыЛкс(ТабличноеПоле).Типы()[0];
Иначе
ТипЗначенияТабличногоПоля = ТипЗнч(выхДанныеТабличногоПоля);
КонецЕсли;
КонецЕсли;
Если ТипЗначенияТабличногоПоля = Тип("ТаблицаЗначений") Тогда
ТипИсточника = "ТаблицаЗначений";
ИначеЕсли ТипЗначенияТабличногоПоля = Тип("ДеревоЗначений") Тогда
ТипИсточника = "ДеревоЗначений";
ИначеЕсли ТипЗначенияТабличногоПоля = Тип("СписокЗначений") Тогда
ТипИсточника = "СписокЗначений";
ИначеЕсли ЛиДанныеФормыСВозможностьюПоискаЛкс(ТипЗначенияТабличногоПоля) Тогда
ТипИсточника = "ТаблицаЗначений";
ИначеЕсли ТипЗначенияТабличногоПоля = Тип("ДанныеФормыДерево") Тогда
ТипИсточника = "ДеревоЗначений";
ИначеЕсли Истина
И ТипЗнч(ТабличноеПоле) = Тип("Структура")
И ТипЗначенияТабличногоПоля = Тип("Неопределено")
И Найти(ТабличноеПоле.ПутьКДанным, "-") > 0
Тогда
ТипИсточника = "ТабличнаяЧасть";
Иначе
//мПлатформа.ИнициацияОписанияМетодовИСвойств();
СтруктураТипа = мПлатформа.СтруктураТипаИзКонкретногоТипа(ТипЗначенияТабличногоПоля);
Если Ложь
Или Найти(СтруктураТипа.ИмяОбщегоТипа, "<Имя табличной части>") > 0
Или Найти(СтруктураТипа.ИмяОбщегоТипа, "ВидыСубконто") > 0
Или Найти(СтруктураТипа.ИмяОбщегоТипа, "БазовыеВидыРасчета") > 0
Или Найти(СтруктураТипа.ИмяОбщегоТипа, "ВедущиеВидыРасчета") > 0
Или Найти(СтруктураТипа.ИмяОбщегоТипа, "ВытесняющиеВидыРасчета") > 0
Тогда
ТипИсточника = "ТабличнаяЧасть";
ИначеЕсли Найти(СтруктураТипа.ИмяОбщегоТипа, "НаборЗаписей.") > 0 Тогда
ТипИсточника = "НаборЗаписей";
ИначеЕсли Найти(СтруктураТипа.ИмяОбщегоТипа, "Список.") > 0 Тогда
ТипИсточника = "Список";
ИначеЕсли СтруктураТипа.ИмяОбщегоТипа = "ДинамическийСписок" Тогда
ТипИсточника = "Список";
КонецЕсли;
Если СтруктураТипа.ИмяОбщегоТипа <> "Неопределено" Тогда
выхСтруктураТипаМетаданных = СтруктураТипа;
КонецЕсли;
выхПолноеИмяТаблицыБД = ИмяТаблицыБДДинамическогоСпискаЛкс(ТабличноеПоле);
Если Истина
И Не ЗначениеЗаполнено(ТипИсточника)
И ЗначениеЗаполнено(выхПолноеИмяТаблицыБД)
Тогда
ТипИсточника = "Список";
КонецЕсли;
КонецЕсли;
Возврат ТипИсточника;
КонецФункции
Функция ЛиДанныеФормыСВозможностьюПоискаЛкс(Знач ДанныеИлиТипТаблицы) Экспорт
Если ТипЗнч(ДанныеИлиТипТаблицы) <> Тип("Тип") Тогда
Тип = ТипЗнч(ДанныеИлиТипТаблицы);
Иначе
Тип = ДанныеИлиТипТаблицы;
КонецЕсли;
Возврат Ложь
Или Тип = Тип("СписокЗначений")
Или Тип = Тип("ДанныеФормыКоллекция")
Или Тип = Тип("ДанныеФормыСтруктураСКоллекцией");
КонецФункции
// .
// Параметры:
// ТабличноеПоле - ТабличноеПоле, ТаблицаФормы -
// ОписанияКолонок - -
// МетаданныеКолонок - КоллекцияОбъектовМетаданных, ТаблицаЗначений - для таблицы значений используются колонки Имя и Метаданные
// ДоступныеПоляВыбора - -
// ТолькоПросмотр - -
// Формат - -
//
Процедура НастроитьДобавленныеКолонкиТабличногоПоляЛкс(Знач ТабличноеПоле, ОписанияКолонок = Неопределено, МетаданныеКолонок = Неопределено, ДоступныеПоляВыбора = Неопределено,
ТолькоПросмотр = Ложь, Формат = "") Экспорт
#Если Сервер И Не Сервер Тогда
ТабличноеПоле = Новый ТабличноеПоле;
#КонецЕсли
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
Если ОписанияКолонок = Неопределено Тогда
ОписанияКолонок = ирСервер.ТаблицаДочернихРеквизитовЛкс(ТабличноеПоле);
КонецЕсли;
Иначе
//! ТабличноеПоле = 0 // ТабличноеПоле
#Если Клиент Тогда
ирКлиент.ТабличноеПолеВключитьСтаруюЦветовуюСхемуЛкс(ТабличноеПоле);
#КонецЕсли
Если ОписанияКолонок = Неопределено Тогда
ОписанияКолонок = ТабличноеПоле.Значение.Колонки; // КоллекцияКолонокТаблицыЗначений
КонецЕсли;
КонецЕсли;
КолонкиТабличногоПоля = ТабличноеПоле.Колонки;
#Если Сервер И Не Сервер Тогда
КолонкиТабличногоПоля = Новый ТаблицаЗначений;
КолонкиТабличногоПоля = КолонкиТабличногоПоля.Колонки;
#КонецЕсли
МассивКолонокДанных = МассивИзКоллекцииЛкс(КолонкиТабличногоПоля);
Для Каждого КолонкаДанных Из МассивКолонокДанных Цикл
Для Каждого КолонкаДанныхОсновная Из МассивКолонокДанных Цикл
Если "Несогласовано_" + КолонкаДанныхОсновная.Имя = КолонкаДанных.Имя Тогда
КолонкиТабличногоПоля.Сдвинуть(КолонкаДанных, КолонкиТабличногоПоля.Индекс(КолонкаДанныхОсновная) - КолонкиТабличногоПоля.Индекс(КолонкаДанных) + 1);
КонецЕсли;
КонецЦикла;
КонецЦикла;
МинимальнаяШиринаКолонки = МинимальнаяШиринаКолонкиЛкс();
Для Каждого КолонкаТаблицы Из ОписанияКолонок Цикл
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
КолонкаТП = ТабличноеПоле.ПодчиненныеЭлементы.Найти(ТабличноеПоле.Имя + КолонкаТаблицы.Имя);
Иначе
//! ТабличноеПоле = 0 // ТабличноеПоле
КолонкаТП = ТабличноеПоле.Колонки.Найти(КолонкаТаблицы.Имя);
КонецЕсли;
Если КолонкаТП = Неопределено Тогда
Продолжить;
КонецЕсли;
Если КолонкаТП.Видимость Тогда
УстановитьТекущуюКолонкуТаблицыФормыЛкс(ТабличноеПоле, КолонкаТП, Истина);
КонецЕсли;
Если ТолькоПросмотр Тогда
КолонкаТП.ТолькоПросмотр = Истина;
КонецЕсли;
Если ЗначениеЗаполнено(Формат) Тогда
КолонкаТП.Формат = Формат;
КонецЕсли;
Если ДоступныеПоляВыбора <> Неопределено Тогда
ДоступноеПоле = ДоступныеПоляВыбора.НайтиПоле(Новый ПолеКомпоновкиДанных(КолонкаТаблицы.Имя));
Если ДоступноеПоле <> Неопределено Тогда
ТекстШапки = ДоступноеПоле.Заголовок;
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
//! КолонкаТП = 0 // ПолеФормы
КолонкаТП.Заголовок = ТекстШапки;
Иначе
//! КолонкаТП = 0 // КолонкаТабличногоПоля
КолонкаТП.ТекстШапки = ТекстШапки;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле")
#КонецЕсли
Тогда
ТипЗначенияКолонки = КолонкаТаблицы.ТипЗначения;
#Если Сервер И Не Сервер Тогда
ТипЗначенияКолонки = Новый ОписаниеТипов;
#КонецЕсли
ТипЗначенияКолонки = Новый ОписаниеТипов(ТипЗначенияКолонки,, "Null");
ТипыРеквизита = ТипЗначенияКолонки.Типы();
// От вывода картинки в шапке больше вреда - в первую очередь они съедают много ширины
//Если Истина
// И ТипыРеквизита.Количество() = 1
// И ТипыРеквизита[0] <> Тип("Булево")
//Тогда
// #Если Клиент Тогда
// КолонкаТП.КартинкаШапки = ирКлиент.КартинкаТипаЛкс(ТипыРеквизита[0]); // https://t.me/DevTool1C/24810
// #КонецЕсли
//КонецЕсли;
Если ТипыРеквизита.Количество() = 1 И ТипыРеквизита[0] = Тип("Булево") Тогда
КолонкаТП.Ширина = МинимальнаяШиринаКолонки;
КолонкаТП.КартинкиСтрок = ирКэш.КартинкаПоИмениЛкс("ирСостоянияФлажка");
ИначеЕсли Истина
И ТипыРеквизита.Количество() = 1
И ТипЗначенияКолонки.СодержитТип(Тип("Число"))
И ТипЗначенияКолонки.КвалификаторыЧисла.Разрядность = 0
И КолонкаТП.Ширина = 1
Тогда
// Почему то в этом случае платформа устанавливает ширину 1
КолонкаТП.Ширина = 10;
Иначе
Если КолонкаТаблицы.Ширина > 0 Тогда
КолонкаТП.Ширина = КолонкаТаблицы.Ширина; // Почему то в редакторе таблицы значений не работала автоширина (-1)
КонецЕсли;
КолонкаТП.Ширина = Мин(КолонкаТП.Ширина, 30);
Если КолонкаТП.Ширина = 0 Тогда
КолонкаТП.Ширина = МинимальнаяШиринаКолонки; // Для 8.2 необходимо, иначе колонки будут не видны
КонецЕсли;
КонецЕсли;
Метареквизит = Неопределено;
Если МетаданныеКолонок <> Неопределено Тогда
Если ТипЗнч(МетаданныеКолонок) = Тип("КоллекцияОбъектовМетаданных") Тогда
Метареквизит = МетаданныеКолонок.Найти(КолонкаТаблицы.Имя);
Иначе // Если ТипЗнч(МетаданныеКолонок) = Тип("ТаблицаЗначений") Тогда
СтрокаПоля = МетаданныеКолонок.Найти(КолонкаТаблицы.Имя, "Имя");
Если СтрокаПоля <> Неопределено Тогда
Метареквизит = СтрокаПоля.Метаданные;
Иначе
Метареквизит = Неопределено;
КонецЕсли;
КонецЕсли;
Если Метареквизит <> Неопределено Тогда
Попытка
Подсказка = Метареквизит.Подсказка;
Исключение
// У графы журнала нет подсказки
Подсказка = Неопределено;
КонецПопытки;
Если Подсказка <> Неопределено Тогда
КолонкаТП.ПодсказкаВШапке = Подсказка;
Если Истина
И Метареквизит.Тип.СодержитТип(Тип("Строка"))
И Метареквизит.МногострочныйРежим
Тогда
КолонкаТП.ЭлементУправления.МногострочныйРежим = Метареквизит.МногострочныйРежим;
КолонкаТП.ЭлементУправления.РасширенноеРедактирование = Метареквизит.РасширенноеРедактирование;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Истина
И Метареквизит = Неопределено
И ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ТипЗначенияКолонки)
И ТипЗнч(КолонкаТП.ЭлементУправления) = Тип("ПолеВвода")
И Не КолонкаТП.ТолькоПросмотр
Тогда
КолонкаТП.ЭлементУправления.МногострочныйРежим = Истина; // Доступно только при КолонкаТП.ТолькоПросмотр=Ложь
КолонкаТП.ЭлементУправления.РасширенноеРедактирование = Истина;
КонецЕсли;
ДобавитьОписаниеТиповВПодсказкуШапкиКолонкиЛкс(КолонкаТП, ТипЗначенияКолонки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Процедура - Добавить описание типов в подсказку шапки колонки лкс
//
// Параметры:
// КолонкаТабличногоПоля - КолонкаТабличногоПоля -
// ТипЗначенияКолонки - ОписаниеТипов -
// МетаданныеКолонки - ОбъектМетаданных -
// ДобавлятьРоль - Булево -
// ИмяПоля - Строка - для ускорения
//
Процедура ДобавитьОписаниеТиповВПодсказкуШапкиКолонкиЛкс(Знач КолонкаТабличногоПоля, Знач ТипЗначенияКолонки, Знач МетаданныеКолонки = Неопределено, Знач ДобавлятьРоль = Истина, Знач ИмяПоля = "") Экспорт
Если ТипЗнч(КолонкаТабличногоПоля) = Тип("ПолеФормы") Тогда
НоваяПодсказка = КолонкаТабличногоПоля.Подсказка;
Если Не ЗначениеЗаполнено(НоваяПодсказка) Тогда
НоваяПодсказка = КолонкаТабличногоПоля.Заголовок;
КонецЕсли;
Иначе
НоваяПодсказка = КолонкаТабличногоПоля.ПодсказкаВШапке;
Если Не ЗначениеЗаполнено(НоваяПодсказка) Тогда
НоваяПодсказка = КолонкаТабличногоПоля.ТекстШапки;
КонецЕсли;
КонецЕсли;
ПодсказкаИзменена = Ложь;
МаркерТипа = Символы.ПС + "Тип: ";
Если Найти(НоваяПодсказка, МаркерТипа) = 0 Тогда
НоваяПодсказка = НоваяПодсказка + МаркерТипа + РасширенноеПредставлениеЛкс(ТипЗначенияКолонки,,,,,, 5);
ПодсказкаИзменена = Истина;
КонецЕсли;
МаркерРоли = Символы.ПС + "Роль: ";
Если ДобавлятьРоль И Найти(НоваяПодсказка, МаркерРоли) = 0 И МетаданныеКолонки <> Неопределено Тогда
Если МетаданныеКолонки = Неопределено И Не ЗначениеЗаполнено(ИмяПоля) Тогда
ИмяПоля = ПоследнийФрагментЛкс(ПутьКДаннымКолонкиТабличногоПоляЛкс(КолонкаТабличногоПоля));
КонецЕсли;
Роль = РольПоляБДЛкс(МетаданныеКолонки, ИмяПоля);
Если ЗначениеЗаполнено(Роль) Тогда
НоваяПодсказка = НоваяПодсказка + МаркерРоли + Роль;
ПодсказкаИзменена = Истина;
КонецЕсли;
КонецЕсли;
Если ПодсказкаИзменена Тогда
Если ТипЗнч(КолонкаТабличногоПоля) = Тип("ПолеФормы") Тогда
КолонкаТабличногоПоля.Подсказка = НоваяПодсказка;
Иначе
КолонкаТабличногоПоля.ПодсказкаВШапке = НоваяПодсказка;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция ЗаголовокКолонкиТаблицыФормыЛкс(Знач КолонкаТП) Экспорт
Заголовок = СтрЗаменить(КолонкаТП.Заголовок, Символы.ПС, "");
Если Истина
И Найти(Заголовок, "…") > 0
И СтрДлина(КолонкаТП.Подсказка) > СтрДлина(Заголовок)
Тогда
Заголовок = ПервыйФрагментЛкс(КолонкаТП.Подсказка, Символы.ПС);
КонецЕсли;
Возврат Заголовок;
КонецФункции
// Функция - Роль поля БД. Вызывается из очень часто из Обработка.ирКолонкиБД
//
// Параметры:
// МетаданныеКолонки - ОписаниеСтандартногоРеквизита, ОбъектМетаданных, Неопределено -
//
// Возвращаемое значение:
// Строка - роль поля
//
Функция РольПоляБДЛкс(Знач МетаданныеКолонки = Неопределено, ИмяПоля = "") Экспорт
//ПолноеИмяМД = ПолноеИмяМДПоляТаблицыЛкс(МетаданныеКолонки);
Если МетаданныеКолонки = Неопределено Тогда
Если Ложь
Или ИмяПоля = ПеревестиСтроку("ВерсияДанных")
Или ИмяПоля = ПеревестиСтроку("Предопределенный")
Или ИмяПоля = "ИдентификаторСсылкиЛкс"
Или ИмяПоля = "Представление"
Или ИмяПоля = "ЭтотУзел"
Тогда
Роль = "Стандартный";
Иначе
Роль = "";
КонецЕсли;
ИначеЕсли ТипЗнч(МетаданныеКолонки) = Тип("ОписаниеСтандартногоРеквизита") Тогда
Роль = "Стандартный";
Иначе
// Медленно. Результат НЕ зависимым от варианта встроенного языка
//ПолноеИмяМД = МетаданныеКолонки.ПолноеИмя();
//Если Истина
// И ирКэш.ДоступноОбщиеРеквизитыЛкс()
// И Метаданные.ОбщиеРеквизиты.Индекс(МетаданныеКолонки) >= 0
//Тогда
// Роль = "Общий реквизит";
//ИначеЕсли Найти(ПолноеИмяМД, "." + ПеревестиСтроку("Измерение") + ".") > 0 Тогда
// Роль = "Измерение";
//ИначеЕсли Найти(ПолноеИмяМД, "." + ПеревестиСтроку("Ресурс") + ".") > 0 Тогда
// Роль = "Ресурс";
//КонецЕсли;
//
// Быстро. Результат зависим от варианта встроенного языка
Фрагменты = СтрРазделитьЛкс(МетаданныеКолонки.ПолноеИмя());
Роль = Фрагменты[Фрагменты.Вграница() - 1];
КонецЕсли;
Возврат Роль;
КонецФункции
Функция ПорядокРолиПоляБДЛкс(Знач РолиПоля) Экспорт
Если РолиПоля = "Стандартный" Тогда
ПорядокРоли = 10;
ИначеЕсли РолиПоля = "Измерение" Тогда
ПорядокРоли = 20;
ИначеЕсли РолиПоля = "Ресурс" Тогда
ПорядокРоли = 30;
ИначеЕсли РолиПоля = "Реквизит" Тогда
ПорядокРоли = 40;
ИначеЕсли РолиПоля = "ОбщийРеквизит" Тогда
ПорядокРоли = 50;
ИначеЕсли РолиПоля = "ПризнакУчета" Тогда
ПорядокРоли = 60;
ИначеЕсли РолиПоля = "Доп. реквизит" Тогда
ПорядокРоли = 70;
ИначеЕсли ЗначениеЗаполнено(РолиПоля) Тогда
ПорядокРоли = 80;
Иначе
ПорядокРоли = 100;
КонецЕсли;
Возврат ПорядокРоли;
КонецФункции
Процедура УстановитьТекущуюКолонкуТаблицыФормыЛкс(Знач ТабличноеПоле, Знач Колонка, Знач ТолькоЕслиНеопределена = Ложь) Экспорт
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
Если Не ТолькоЕслиНеопределена Или ТабличноеПоле.ТекущийЭлемент = Неопределено Тогда
ТабличноеПоле.ТекущийЭлемент = Колонка;
КонецЕсли;
Иначе
Если Не ТолькоЕслиНеопределена Или ТабличноеПоле.ТекущаяКолонка = Неопределено Тогда
ТабличноеПоле.ТекущаяКолонка = Колонка;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Функция СостоянияКнопкиОтображатьПустыеИИдентификаторыЛкс() Экспорт
МассивСостояний = Новый Массив;
МассивСостояний.Добавить("Не отображать");
МассивСостояний.Добавить("Отображать пустые");
МассивСостояний.Добавить("Отображать пустые и идентификаторы");
Возврат МассивСостояний;
КонецФункции
// Функция - Ключ хранения настроек формы лкс
//
// Параметры:
// ЭтаФорма - Форма, УправляемаяФорма, Структура -
//
// Возвращаемое значение:
// -
//
Функция КлючХраненияНастроекФормыЛкс(Знач ЭтаФорма) Экспорт
Результат = ПолноеИмяФормыЛкс(ЭтаФорма);
// Сделать потом новый режим формирования ключа хранения и флажок в общих настройках чтобы пользователь сам его включал для использования нового ключа.
//Фрагменты = СтрРазделитьЛкс(Результат);
//Фрагменты.Удалить(2);
//Фрагменты.Удалить(0);
//Результат = СтрСоединитьЛкс(Фрагменты);
Возврат Результат;
КонецФункции
Функция КлючСохраненияСпискаПоследнихЗначенийФормыЛкс(ЭтаФорма, Знач ТабличноеПолеИлиКлюч = Неопределено, ТипКлюча = "Выбранные", Знач ДопКлючХранения = "") Экспорт
Если ТипЗнч(ТабличноеПолеИлиКлюч) = Тип("Строка") Тогда
Результат = ТабличноеПолеИлиКлюч;
Иначе
Если ТипЗнч(ЭтаФорма) = ТипУправляемаяФормаЛкс() Тогда
КлючУникальности = ЭтаФорма.мКлючУникальности;
ИначеЕсли ТипЗнч(ЭтаФорма.КлючУникальности) <> Тип("УникальныйИдентификатор") Тогда
КлючУникальности = ЭтаФорма.КлючУникальности;
КонецЕсли;
Результат = КлючХраненияНастроекФормыЛкс(ЭтаФорма) + ".";
Если Не ЭтаФорма.РежимВыбора Тогда
Если ТабличноеПолеИлиКлюч <> Неопределено Тогда
Результат = Результат + ТабличноеПолеИлиКлюч.Имя + ".";
Иначе
СообщитьЛкс("В форме не в режиме выбора при формировании ключа списка последних выбранных значений нужно указывать табличное поле");
КонецЕсли;
КонецЕсли;
Результат = Результат + Лев(ДопКлючХранения, 30);
Результат = Результат + Лев(КлючУникальности, 30);
КонецЕсли;
Результат = Результат + ".Последние" + ТипКлюча;
Возврат Результат;
КонецФункции
Процедура ЗаменитьФигурныеСкобкиЛкс(ТекстКнопки) Экспорт
ТекстКнопки = СтрЗаменить(ТекстКнопки, "{", " ");
ТекстКнопки = СтрЗаменить(ТекстКнопки, "}", " ");
КонецПроцедуры
Функция КоличествоЗапоминаемыхПоследнихВыбранныхЛкс() Экспорт
Возврат 20;
КонецФункции
Функция НачалоИмениКнопкиПодменюПоследнихВыбранныхЛкс(ТипКлюча = "Выбранные") Экспорт
Возврат "Последние" + ТипКлюча;
КонецФункции
Функция ИспользованиеДинамическогоСпискаВместоОсновнойФормыЛкс(ПолноеИмяМД) Экспорт
Возврат ВосстановитьЗначениеЛкс("ирДинамическийСписок.ВместоОсновной." + ПолноеИмяМД) <> Ложь;
КонецФункции
Функция КлючУникальностиДинамическогоСпискаЛкс(Знач ИмяТаблицы, Знач КлючУникальности = "") Экспорт
КлючУникальности = ИмяТаблицы + ";" + КлючУникальности;
Возврат КлючУникальности;
КонецФункции
Функция КлючИсторииВыбораПоляВводаЛкс(Знач ПолеВводаИлиЭлементОтбора, Знач КлючИстории, Знач ДополнительныйКлючИстории = "") Экспорт
Если ТипЗнч(КлючИстории) <> Тип("Строка") Тогда
КлючИстории = КлючХраненияНастроекФормыЛкс(КлючИстории);
КлючИстории = КлючИстории + ДополнительныйКлючИстории;
КлючИстории = КлючИстории + "." + ПолеВводаИлиЭлементОтбора.Имя;
ИначеЕсли Ложь
Или ТипЗнч(ПолеВводаИлиЭлементОтбора) = Тип("ЭлементОтбора")
Или ТипЗнч(ПолеВводаИлиЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
Тогда
КлючИстории = КлючИстории + ДополнительныйКлючИстории;
КлючИстории = КлючИсторииВыбораЗначенияОтбораЛкс(КлючИстории, ПолеВводаИлиЭлементОтбора);
КонецЕсли;
КлючИстории = КлючИстории + ".ПоследниеЗначения";
Возврат КлючИстории;
КонецФункции
Функция ПрочитатьПоследниеВыбранныеЗначенияЛкс(Знач КлючИстории) Экспорт
ПоследниеЗначенияСчитанные = ВосстановитьЗначениеЛкс(КлючИстории);
Если ТипЗнч(ПоследниеЗначенияСчитанные) = Тип("СписокЗначений") Тогда
ПоследниеЗначения = ПоследниеЗначенияСчитанные;
Иначе
ПоследниеЗначения = Новый СписокЗначений;
Если ТипЗнч(ПоследниеЗначенияСчитанные) = Тип("Массив") Тогда
// Конвертация из старого формата
Для Каждого Значение Из ПоследниеЗначенияСчитанные Цикл
ПоследниеЗначения.Добавить(ОбъектВСтрокуXMLЛкс(Значение), РасширенноеПредставлениеЛкс(Значение));
КонецЦикла;
КонецЕсли;
КонецЕсли;
СократитьСписокПоследнихВыбранныхЛкс(ПоследниеЗначения);
Возврат ПоследниеЗначения;
КонецФункции
Процедура СократитьСписокПоследнихВыбранныхЛкс(Знач ПоследниеЗначения, Знач ЗапоминатьПоследние = 0) Экспорт
Если Не ЗначениеЗаполнено(ЗапоминатьПоследние) Тогда
ЗапоминатьПоследние = КоличествоЗапоминаемыхПоследнихВыбранныхЛкс();
КонецЕсли;
Для Счетчик = ЗапоминатьПоследние По ПоследниеЗначения.Количество() - 1 Цикл
ПоследниеЗначения.Удалить(ЗапоминатьПоследние);
КонецЦикла;
КонецПроцедуры
// Процедура - Поле ввода с историей выбора начало выбора из списка лкс.
// Вызывается с сервера в динамическом списке.
//
// Параметры:
// ЭлементФормы - -
// КлючИстории - Форма, Строка -
// ДополнительныйКлючИстории - -
// ОтборВыбора - -
//
Процедура ПолеВводаСИсториейВыбора_ОбновитьСписокЛкс(Знач ЭлементФормы, Знач КлючИстории, ДополнительныйКлючИстории = "", ОтборВыбора = Неопределено) Экспорт
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(ЭлементФормы) = Тип("КолонкаТабличногоПоля")
#КонецЕсли
Тогда
ПолеВвода = ЭлементФормы.ЭлементУправления;
Иначе
ПолеВвода = ЭлементФормы;
КонецЕсли;
КлючИстории = КлючИсторииВыбораПоляВводаЛкс(ЭлементФормы, КлючИстории, ДополнительныйКлючИстории);
ПоследниеЗначения = ПрочитатьПоследниеВыбранныеЗначенияЛкс(КлючИстории);
ПолеВвода.СписокВыбора.Очистить();
ПолеВвода_ОбновитьСписокЛкс(ПолеВвода);
Если ТипЗнч(ПоследниеЗначения) = Тип("СписокЗначений") Тогда
Если ОтборВыбора <> Неопределено Тогда
ТаблицаСсылок = Новый ТаблицаЗначений;
ТаблицаСсылок.Колонки.Добавить("Ссылка");
Для Каждого ЭлементСписка Из ПоследниеЗначения Цикл
ТаблицаСсылок.Добавить().Ссылка = ОбъектИзСтрокиXMLЛкс(ЭлементСписка.Значение);
КонецЦикла;
ТаблицаСсылок = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаСсылок);
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, "Ссылка");
СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, ОтборВыбора,,,, "Ссылка");
ОтобранныеЗначения = ОтобратьТаблицуЗначенийКомпоновкойЛкс(ТаблицаСсылок, НастройкаКомпоновки,, Истина);
Для Каждого Ссылка Из ОтобранныеЗначения.ВыгрузитьКолонку("Ссылка") Цикл
ПоследниеЗначения.Добавить(ОбъектВСтрокуXMLЛкс(Ссылка));
КонецЦикла;
КонецЕсли;
ЗагрузитьИсториюВыбораВПолеВводаЛкс(ПолеВвода, ПоследниеЗначения);
КонецЕсли;
КонецПроцедуры
//.
// Параметры:
// ПолеВвода - ПолеВвода, ПолеВыбора -
// ПоследниеЗначения - СписокЗначений -
Процедура ЗагрузитьИсториюВыбораВПолеВводаЛкс(Знач ПолеВвода, Знач ПоследниеЗначения) Экспорт
Для Каждого ЭлементСписка Из ПоследниеЗначения Цикл
Значение = ЗначениеИзЭлементаИсторииВыбораЛкс(ЭлементСписка);
ПолеВвода.СписокВыбора.Добавить(Значение, ЭлементСписка.Представление);
КонецЦикла;
КонецПроцедуры
//.
// Параметры:
// ЭлементСписка - ЭлементСпискаЗначений -
// Возвращаемое значение:
// Произвольный, Строка, Неопределено -
Функция ЗначениеИзЭлементаИсторииВыбораЛкс(Знач ЭлементСписка) Экспорт
Значение = ЭлементСписка.Значение;
Если ТипЗнч(Значение) = Тип("Строка") Тогда
НовоеЗначение = ОбъектИзСтрокиXMLЛкс(Значение,,, Ложь);
Если НовоеЗначение <> Неопределено Тогда
Значение = НовоеЗначение;
КонецЕсли;
КонецЕсли;
Возврат Значение;
КонецФункции
Функция ПолеВвода_ОбновитьСписокЛкс(ПолеВвода) Экспорт
СписокВыбора = ПолеВвода.СписокВыбора;
#Если Сервер И Не Сервер Тогда
СписокВыбора = Новый СписокЗначений;
#КонецЕсли
Значение = ДанныеЭлементаФормыЛкс(ПолеВвода);
Если ТипЗнч(Значение) = Тип("Дата") Тогда
Если ТипЗнч(ПолеВвода) = Тип("ПолеВвода") Тогда
ПолеВвода.Значение = ПолеВвода.Значение + 1;
ВремяДоступно = ПолеВвода.Значение <> Значение;
ПолеВвода.Значение = Значение;
Иначе
ВремяДоступно = Истина;
КонецЕсли;
СписокВыбора.Очистить();
СписокВыбора.Добавить(ТекущаяДата(), "<текущая дата клиента>");
РазницаВремениКлиентСервер = РазницаВремениКлиентСерверЛкс();
Если Макс(РазницаВремениКлиентСервер, -РазницаВремениКлиентСервер) > 60 Тогда
СписокВыбора.Добавить(ТекущаяДатаЛкс(Истина), СтрШаблонЛкс("<текущая дата сервера %1с>", ПредставлениеРазностиЛкс(-РазницаВремениКлиентСервер)));
КонецЕсли;
// Из-за некорректной работы кнопок регулирования внутри таблицы будем добавлять все команды https://www.hostedredmine.com/issues/936754
Если ЗначениеЗаполнено(Значение) Тогда
Если ВремяДоступно Тогда
СписокВыбора.Добавить(НачалоДня(Значение), "<начало выбранной даты>");
СписокВыбора.Добавить(КонецДня(Значение), "<конец выбранной даты>");
Если Не ПолеВвода.КнопкаРегулирования Тогда
СписокВыбора.Добавить(Значение - 60, "- минтута");
СписокВыбора.Добавить(Значение + 60, "+ минута");
СписокВыбора.Добавить(Значение - 60*60, "- час");
СписокВыбора.Добавить(Значение + 60*60, "+ час");
КонецЕсли;
КонецЕсли;
Если Не ПолеВвода.КнопкаРегулирования Тогда
СписокВыбора.Добавить(Значение - 24*60*60, "- сутки");
СписокВыбора.Добавить(Значение + 24*60*60, "+ сутки");
КонецЕсли;
КонецЕсли;
ИначеЕсли ТипЗнч(Значение) = Тип("Число") Тогда
СписокВыбора.Очистить();
Если Окр(Значение) <> Значение Тогда
СписокВыбора.Добавить(Окр(Значение), "<Округлить>");
КонецЕсли;
СписокВыбора.Добавить(Значение - 10, "- 10");
СписокВыбора.Добавить(Значение + 10, "+ 10");
КонецЕсли;
КонецФункции
Функция ЛиТипЗначенияДопускаетРегулированиеВПолеВводаЛкс(Знач ТипЗначения) Экспорт
Возврат ТипЗначения = Тип("Дата") Или ТипЗначения = Тип("Число");
КонецФункции
// Положительное число выводится со знаком "+"
Функция ПредставлениеРазностиЛкс(Знач Разность) Экспорт
Возврат ?(Разность > 0, "+", "") + Разность;
КонецФункции
Функция КлючИсторииВыбораЗначенияОтбораЛкс(ПолноеИмяМД, ЭлементОтбора) Экспорт
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбора") Тогда
Результат = ПолноеИмяМД + ".Отбор." + ЭлементОтбора.Имя;
ИначеЕсли ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Результат = ПолноеИмяМД + ".Отбор." + ЭлементОтбора.ЛевоеЗначение;
ИначеЕсли ТипЗнч(ЭлементОтбора) = Тип("Строка") Тогда
Результат = ПолноеИмяМД + ".Отбор." + ЭлементОтбора;
Иначе
ВызватьИсключение "Неверный тип элемента отбора";
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СтроковыйИдентификаторСсылкиЛкс(Знач Ссылка, Знач ВместеСТипом = Ложь) Экспорт
ИдентификаторСсылки = Неопределено;
XMLТип = XMLТипЗнч(Ссылка);
Если XMLТип <> Неопределено Тогда
Если Найти(XMLТип.ИмяТипа, "Ref.") > 0 Тогда
Если Найти(XMLТип.ИмяТипа, "ExternalDataSourceTableRef.") > 0 Тогда
ИдентификаторСсылки = "{" + ТекстМеждуМаркерамиЛкс(ЗначениеВСтрокуВнутр(Ссылка), "," + Символы.ПС + "{", "}" + Символы.ПС + "}") + "}";
ИдентификаторСсылки = СтрЗаменить(ИдентификаторСсылки, Символы.ПС, "");
Иначе
ИдентификаторСсылки = XMLСтрока(Ссылка);
КонецЕсли;
ИначеЕсли XMLТип.ИмяТипа = "Type" Тогда
XMLТипТипа = XMLТип(Ссылка);
Если XMLТипТипа <> Неопределено Тогда
ИдентификаторСсылки = XMLТипТипа.ИмяТипа;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ВместеСТипом И ИдентификаторСсылки <> Неопределено Тогда
ИдентификаторСсылки = ИдентификаторСсылки + "." + XMLТип.ИмяТипа;
КонецЕсли;
Возврат ИдентификаторСсылки;
КонецФункции
Функция ИменаИспользуемыхВЗапросеВременныхТаблицЛкс(Знач ЗапросИлиМенеджерВременныхТаблиц, Знач ОбязательныеДляПроверкиИмена = """") Экспорт
Платформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
Платформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
МассивИмен = СтрРазделитьЛкс(ОбязательныеДляПроверкиИмена, ",", Истина, Ложь);
Если ТипЗнч(ЗапросИлиМенеджерВременныхТаблиц) = Тип("Запрос") Тогда
#Если Сервер И Не Сервер Тогда
ЗапросИлиМенеджерВременныхТаблиц = Новый Запрос;
#КонецЕсли
ИменаИспользуемыхВременныхТаблиц = Платформа.НайтиВозможныеИменаВременныхТаблиц(ЗапросИлиМенеджерВременныхТаблиц.Текст);
Для Каждого ИмяИспользуемойВременнойТаблицы Из ИменаИспользуемыхВременныхТаблиц Цикл
МассивИмен.Добавить(ИмяИспользуемойВременнойТаблицы);
КонецЦикла;
МенеджерВременныхТаблиц = ЗапросИлиМенеджерВременныхТаблиц.МенеджерВременныхТаблиц;
Иначе
Если Не ирКэш.ДоступноТаблицыМенеджераВременныхТаблицЛкс() И Не ЗначениеЗаполнено(ОбязательныеДляПроверкиИмена) Тогда
ВызватьИсключение "Необходимо указать имена временных таблиц";
КонецЕсли;
МенеджерВременныхТаблиц = ЗапросИлиМенеджерВременныхТаблиц;
КонецЕсли;
Если Истина
И ирКэш.ДоступноТаблицыМенеджераВременныхТаблицЛкс()
И МенеджерВременныхТаблиц <> Неопределено
Тогда
#Если Сервер И Не Сервер Тогда
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
#КонецЕсли
Для Каждого ТаблицаМенеджера Из МенеджерВременныхТаблиц.Таблицы Цикл
МассивИмен.Добавить(ТаблицаМенеджера.ПолноеИмя);
КонецЦикла;
КонецЕсли;
Возврат МассивИмен;
КонецФункции
// Процедура - Скопировать дерево лкс
//
// Параметры:
// Источник - ДеревоЗначений, СтрокаДереваЗначений -
// Приемник - ДеревоЗначений, СтрокаДереваЗначений -
// ОчиститьПередЗагрузкой - -
// ЗначенияПоУмолчанию - Структура -
// ЗаполнитьПустыеИД - -
//
Процедура СкопироватьДеревоЛкс(Источник, Приемник, ОчиститьПередЗагрузкой = Истина, ЗначенияПоУмолчанию = Неопределено, Знач ЗаполнитьПустыеИД = Ложь) Экспорт
Если ОчиститьПередЗагрузкой Тогда
Приемник.Строки.Очистить();
КонецЕсли;
Если Источник.Строки.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Если ЗначенияПоУмолчанию <> Неопределено Тогда
ИменаСвойствПоУмолчанию = ИменаСвойствСтруктурыЛкс(ЗначенияПоУмолчанию);
КонецЕсли;
Для каждого СтрокаДерева из Источник.Строки Цикл
НоваяСтрока = Приемник.Строки.Добавить();
Если ЗначенияПоУмолчанию <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(НоваяСтрока, ЗначенияПоУмолчанию, ИменаСвойствПоУмолчанию);
КонецЕсли;
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДерева);
Если ЗаполнитьПустыеИД И НоваяСтрока.ИД = Неопределено Тогда
НоваяСтрока.ИД = Новый УникальныйИдентификатор;
КонецЕсли;
СкопироватьДеревоЛкс(СтрокаДерева, НоваяСтрока, ОчиститьПередЗагрузкой = Истина, ЗначенияПоУмолчанию, ЗаполнитьПустыеИД);
КонецЦикла;
КонецПроцедуры
Функция СоздатьСамоудаляющийсяКомандныйФайлЛкс(Знач ТекстКомандногоФайла = "", Знач КраткоеИмяФайла = "") Экспорт
Если ЗначениеЗаполнено(КраткоеИмяФайла) Тогда
ПолноеИмяФайла = КаталогВременныхФайлов() + КраткоеИмяФайла + ".bat";
Иначе
ПолноеИмяФайла = ПолучитьИмяВременногоФайла("bat");
КонецЕсли;
Если СтрНачинаетсяСЛкс(ТекущийЯзыкСистемы(), "ru") Тогда
ТекстКомандногоФайла = "Chcp 866" + Символы.ПС + ТекстКомандногоФайла;
КонецЕсли;
ТекстКомандногоФайла = ТекстКомандногоФайла + "
|del """ + ПолноеИмяФайла + """
|";
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(ТекстКомандногоФайла);
ТекстовыйДокумент.Записать(ПолноеИмяФайла, КодировкаТекста.OEM);
Результат = ПолноеИмяФайла;
Возврат Результат;
КонецФункции
// Проверить уникальность строк ТЧ по колонке
//
// Параметры:
// Объект - <тип> -
// ИмяТаблицы - <тип> -
// ИмяКолонки - <тип>, "" -
//
// Возвращаемое значение:
//
Функция ПроверитьУникальностьСтрокТЧПоКолонкеЛкс(Объект, ИмяТаблицы, ИмяКолонки = "", ИгнорироватьРегистрДляПростогоСтрокогоТипа = Истина, ОтборСтрок = Неопределено,
МассивИсключений = Неопределено) Экспорт
Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда
ИмяКолонки = Объект.Метаданные().ТабличныеЧасти[ИмяТаблицы].Реквизиты[0].Имя;
КонецЕсли;
Если Истина
И МассивИсключений <> Неопределено
И ИгнорироватьРегистрДляПростогоСтрокогоТипа
Тогда
НовыйМассивИсключений = Новый Массив;
Для Каждого ИсключаемоеЗначение Из МассивИсключений Цикл
Если ТипЗнч(ИсключаемоеЗначение) = Тип("Строка") Тогда
ИсключаемоеЗначение = НРег(ИсключаемоеЗначение);
КонецЕсли;
НовыйМассивИсключений.Добавить(ИсключаемоеЗначение);
КонецЦикла;
МассивИсключений = НовыйМассивИсключений;
КонецЕсли;
Успех = Истина;
НеуникальныеЗначения = НеуникальныеЗначенияКолонкиТаблицыЛкс(Объект[ИмяТаблицы], ИмяКолонки, ИгнорироватьРегистрДляПростогоСтрокогоТипа, ОтборСтрок);
Для Каждого НеуникальноеЗначение Из НеуникальныеЗначения Цикл
Если Истина
И МассивИсключений <> Неопределено
И МассивИсключений.Найти(НеуникальноеЗначение) <> Неопределено
Тогда
Продолжить;
КонецЕсли;
СообщитьЛкс(СтрШаблонИменЛкс("Значение %1 встречается более одного раза среди активных строк в колонке %2 таблицы %3",
1, НеуникальноеЗначение, 2, ИмяКолонки, 3, ИмяТаблицы), СтатусСообщения.Внимание);
Успех = Ложь;
КонецЦикла;
Возврат Успех;
КонецФункции
// Функция - Получить процесс ОСЛкс
//
// Параметры:
// ИдентификаторПроцесса - -
// НачалоПроцесса - -
// Компьютер - -
// ВызватьИсключениеПриОшибкеПодключенияWMI - -
// ДопустимоеОтклонениеВремени - -
// МаркерВКоманднойСтроке - -
// ИмяИсполняемогоФайла - -
//
// Возвращаемое значение:
// COMОбъект - :
// * ProcessID - Число
// * ParentProcessId - Число
// * CommandLine - Строка
// * CreationDate - Строка
// * Name - Строка
//
Функция ПолучитьПроцессОСЛкс(Знач ИдентификаторПроцесса = Неопределено, Знач НачалоПроцесса = Неопределено, Знач Компьютер = Неопределено,
Знач ВызватьИсключениеПриОшибкеПодключенияWMI = Истина, Знач ДопустимоеОтклонениеВремени = 2, Знач МаркерВКоманднойСтроке = Неопределено, Знач ИмяИсполняемогоФайла = Неопределено) Экспорт
Если СтрокиРавныЛкс(ИдентификаторПроцесса, "текущий") Тогда
ИдентификаторПроцесса = ирКэш.ИдентификаторПроцессаОСЛкс();
КонецЕсли;
Попытка
WMIЛокатор = ирКэш.ПолучитьCOMОбъектWMIЛкс(Компьютер);
Исключение
Если ВызватьИсключениеПриОшибкеПодключенияWMI Тогда
ВызватьИсключение;
КонецЕсли;
ОписаниеОшибки = ОписаниеОшибки();
СообщитьЛкс(ОписаниеОшибки, СтатусСообщения.Внимание);
WMIЛокатор = Неопределено;
КонецПопытки;
Если WMIЛокатор = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
// ТекстОтбора = "1=1 AND"; Синтаксис WQL такого не допускает
ТекстОтбора = "";
Если ЗначениеЗаполнено(ИдентификаторПроцесса) Тогда
Если ТекстОтбора <> "" Тогда
ТекстОтбора = ТекстОтбора + " AND ";
КонецЕсли;
ТекстОтбора = ТекстОтбора + " ProcessID = " + XMLСтрока(ИдентификаторПроцесса);
КонецЕсли;
Если ЗначениеЗаполнено(МаркерВКоманднойСтроке) Тогда
Если ТекстОтбора <> "" Тогда
ТекстОтбора = ТекстОтбора + " AND ";
КонецЕсли;
ТекстОтбора = ТекстОтбора + " CommandLine LIKE '%" + МаркерВКоманднойСтроке + "%'";
КонецЕсли;
Если ЗначениеЗаполнено(ИмяИсполняемогоФайла) Тогда
Если ТекстОтбора <> "" Тогда
ТекстОтбора = ТекстОтбора + " AND ";
КонецЕсли;
ТекстОтбора = ТекстОтбора + " Name = '" + ИмяИсполняемогоФайла + "'";
КонецЕсли;
Если НачалоПроцесса <> Неопределено Тогда
Если ТекстОтбора <> "" Тогда
ТекстОтбора = ТекстОтбора + " AND ";
КонецЕсли;
ТекстОтбора = ТекстОтбора + " CreationDate >= " + ПолучитьЛитералДатыДляWQLЛкс(НачалоПроцесса - ДопустимоеОтклонениеВремени);
ТекстОтбора = ТекстОтбора + " AND CreationDate <= " + ПолучитьЛитералДатыДляWQLЛкс(НачалоПроцесса + 1 + ДопустимоеОтклонениеВремени);
КонецЕсли;
Результат = "Процесс ОС с отбором (" + ТекстОтбора + ") не найден";
ТекстЗапросаWQL = "Select * from Win32_Process Where " + ТекстОтбора;
ВыборкаПроцессовОС = WMIЛокатор.ExecQuery(ТекстЗапросаWQL);
Для Каждого ПроцессОС Из ВыборкаПроцессовОС Цикл
Результат = ПроцессОС;
Прервать;
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Ли процесс ОСКонфигуратора лкс
//
// Параметры:
// ПроцессОС - WMI:Win32_Process -
//
// Возвращаемое значение:
// -
//
Функция ЛиПроцессОСКонфигуратораЛкс(Знач ПроцессОС) Экспорт
Результат = Ложь
Или Найти(НРег(ПроцессОС.CommandLine), "config") > 0
Или Найти(НРег(ПроцессОС.CommandLine), "designer") > 0;
Возврат Результат;
КонецФункции
Функция ПолучитьЛитералДатыДляWQLЛкс(Знач Результат) Экспорт
Результат = Результат - СмещениеСтандартногоВремени();
Результат = "'" + Формат(Результат, "ДФ='yyyyMMdd HH:mm:ss'; ДП=") + "'";
Возврат Результат
КонецФункции
Функция ПолучитьФайлWMIЛкс(ПолноеИмяФайла, КомпьютерИлиИмя = Неопределено) Экспорт
СлужбаWMI = ирКэш.ПолучитьCOMОбъектWMIЛкс(КомпьютерИлиИмя);
ФайлыWMI = СлужбаWMI.ExecQuery("Select * from CIM_Datafile where name='" + ЗаменитьСлешиНаДвойныеЛкс(ПолноеИмяФайла) + "'");
Для каждого ФайлWMI Из ФайлыWMI цикл
КонецЦикла;
Возврат ФайлWMI;
КонецФункции
// Применяется для заполнения табличных частей с доступными сборками платформы 1С.
// Параметры:
// СборкиПлатформы - ОбработкаТабличнаяЧасть.ирУправлениеCOMКлассами1С.СборкиПлатформы, ОбработкаТабличнаяЧасть.ирУправлениеСлужбамиСервера1С.СборкиПлатформы -
// ТипыComКлассов - -
// ТабличноеПоле - см. Обработка.ирУправлениеСлужбамиСервера1С.Форма.Форма.ЭлементыФормы.СборкиПлатформы -
// ДопПапки - Массив Из Строка -
// Возвращаемое значение:
// -
Функция ЗаполнитьДоступныеСборкиПлатформыЛкс(СборкиПлатформы = Неопределено, Знач ТипыComКлассов = Неопределено, Знач ТабличноеПоле = Неопределено, Знач ДопПапки = Неопределено) Экспорт
Если СборкиПлатформы = Неопределено Тогда
СборкиПлатформы = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирУправлениеСлужбамиСервера1С");
#Если Сервер И Не Сервер Тогда
СборкиПлатформы = Обработки.ирУправлениеСлужбамиСервера1С.Создать();
#КонецЕсли
СборкиПлатформы = СборкиПлатформы.СборкиПлатформы.ВыгрузитьКолонки();
#Если Сервер И Не Сервер Тогда
СборкиПлатформы = Обработки.ирУправлениеСлужбамиСервера1С.Создать().СборкиПлатформы;
#КонецЕсли
КонецЕсли;
#Если Клиент Тогда
Если ТабличноеПоле <> Неопределено Тогда
СостояниеСтрокТП = ирКлиент.ТабличноеПолеСостояниеСтрокЛкс(ТабличноеПоле, "Каталог");
КонецЕсли;
#КонецЕсли
СборкиПлатформы.Очистить();
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
Инсталлер = Новый COMОбъект("WindowsInstaller.Installer");
Продукты = Инсталлер.Products;
Для Каждого Продукт Из Продукты Цикл
Попытка
ПубликаторПродукта = Инсталлер.ProductInfo(Продукт, "Publisher");
Исключение
Продолжить;
КонецПопытки;
Если Истина
И ПубликаторПродукта <> "1C" // латинские буквы
И ПубликаторПродукта <> "1С" // русские буквы
И ПубликаторПродукта <> "1C-Soft" // латинские буквы
И ПубликаторПродукта <> "1С-Софт" // русские буквы
И ПубликаторПродукта <> "NetHelp" // Польша
Тогда
Продолжить;
КонецЕсли;
//НаименованиеПродукта = Инсталлер.ProductInfo(Продукт, "ProductName");
КаталогВерсии = Инсталлер.ProductInfo(Продукт, "InstallLocation");
//СтрокаРелиза = Инсталлер.ProductInfo(Продукт, "VersionString");
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, КаталогВерсии, ТипыComКлассов, Истина);
КонецЦикла;
КонецЕсли;
Разделитель = РазделительПутиКФайлуЛкс();
Файлы = НайтиФайлы(ирОбщий.КаталогПрограммныхФайловОСЛкс(Ложь) + РазделительПутиКФайлуЛкс() + "1cv82", "*");
Для Каждого Файл Из Файлы Цикл
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Файл.ПолноеИмя + Разделитель, ТипыComКлассов);
КонецЦикла;
Файлы = НайтиФайлы(ирОбщий.КаталогПрограммныхФайловОСЛкс(Истина) + РазделительПутиКФайлуЛкс() + "1cv82", "*");
Для Каждого Файл Из Файлы Цикл
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Файл.ПолноеИмя + Разделитель, ТипыComКлассов);
КонецЦикла;
Файлы = НайтиФайлы(ирОбщий.КаталогПрограммныхФайловОСЛкс(Ложь) + РазделительПутиКФайлуЛкс() + "1cv8", "*");
Для Каждого Файл Из Файлы Цикл
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Файл.ПолноеИмя + Разделитель, ТипыComКлассов);
КонецЦикла;
Файлы = НайтиФайлы(ирОбщий.КаталогПрограммныхФайловОСЛкс(Истина) + РазделительПутиКФайлуЛкс() + "1cv8", "*");
Для Каждого Файл Из Файлы Цикл
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Файл.ПолноеИмя + Разделитель, ТипыComКлассов);
КонецЦикла;
Если ДопПапки <> Неопределено Тогда
Для Каждого БазоваяПапка Из ДопПапки Цикл
Файлы = НайтиФайлы(БазоваяПапка, "*");
Для Каждого Файл Из Файлы Цикл
ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Файл.ПолноеИмя + Разделитель, ТипыComКлассов);
КонецЦикла;
КонецЦикла;
КонецЕсли;
СборкиПлатформы.Сортировать("Порядок Убыв, ФайлыСуществуют Убыв, СборкаПлатформы Убыв, x64");
#Если Клиент Тогда
Если ТабличноеПоле <> Неопределено Тогда
ирКлиент.ТабличноеПолеВосстановитьСостояниеСтрокЛкс(ТабличноеПоле, СостояниеСтрокТП);
КонецЕсли;
#КонецЕсли
Возврат СборкиПлатформы;
КонецФункции
Функция ДобавитьКаталогВДоступныеСборкиПлатформыЛкс(СборкиПлатформы, Знач КаталогВерсии, Знач ТипыComКлассов, Знач ЕстьВРеестре = Ложь)
Если СборкиПлатформы.Найти(КаталогВерсии, "Каталог") <> Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Разделитель = РазделительПутиКФайлуЛкс();
СтрокаТаблицыСборок = СборкиПлатформы.Добавить();
СтрокаТаблицыСборок.Каталог = КаталогВерсии;
СтрокаТаблицыСборок.ЕстьВРеестре = ЕстьВРеестре;
ФайлПолученияВерсии = Неопределено;
Если ТипыComКлассов <> Неопределено Тогда
Для Каждого ТипКласса Из ТипыComКлассов Цикл
//Если Метаданные().ТабличныеЧасти.СборкиПлатформы.Реквизиты.Найти(ВыборкаКлассов.Имя) = Неопределено Тогда
// Продолжить;
//КонецЕсли;
ФайлКомпоненты = Новый Файл(КаталогВерсии + "bin" + Разделитель + ТипКласса.КлючевойФайл); // Быстро
СтрокаТаблицыСборок[ТипКласса.Имя] = ФайлКомпоненты.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок[ТипКласса.Имя] Тогда
ФайлПолученияВерсии = ФайлКомпоненты;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ИсполняемыйФайл = Новый Файл(СтрокаТаблицыСборок.Каталог + "bin" + Разделитель + ИмяИсполняемогоФайлаЛкс("ibcmd")); // Быстро
СтрокаТаблицыСборок.СерверАвтономный = ИсполняемыйФайл.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок.СерверАвтономный Тогда
ФайлПолученияВерсии = ИсполняемыйФайл;
КонецЕсли;
ИсполняемыйФайл = Новый Файл(СтрокаТаблицыСборок.Каталог + "bin" + Разделитель + ИмяИсполняемогоФайлаЛкс("ragent")); // Быстро
СтрокаТаблицыСборок.АгентСервера = ИсполняемыйФайл.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок.АгентСервера Тогда
ФайлПолученияВерсии = ИсполняемыйФайл;
КонецЕсли;
ИсполняемыйФайл = Новый Файл(СтрокаТаблицыСборок.Каталог + "bin" + Разделитель + ИмяИсполняемогоФайлаЛкс("ras")); // Быстро
СтрокаТаблицыСборок.СерверАдминистрирования = ИсполняемыйФайл.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок.СерверАдминистрирования Тогда
ФайлПолученияВерсии = ИсполняемыйФайл;
КонецЕсли;
ИсполняемыйФайл = Новый Файл(СтрокаТаблицыСборок.Каталог + "bin" + Разделитель + ИмяИсполняемогоФайлаЛкс("dbgs")); // Быстро
СтрокаТаблицыСборок.СерверОтладки = ИсполняемыйФайл.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок.СерверОтладки Тогда
ФайлПолученияВерсии = ИсполняемыйФайл;
КонецЕсли;
ИсполняемыйФайл = Новый Файл(СтрокаТаблицыСборок.Каталог + "bin" + Разделитель + ИмяИсполняемогоФайлаЛкс("crserver")); // Быстро
СтрокаТаблицыСборок.СерверХранилища = ИсполняемыйФайл.Существует();
Если ФайлПолученияВерсии = Неопределено И СтрокаТаблицыСборок.СерверХранилища Тогда
ФайлПолученияВерсии = ИсполняемыйФайл;
КонецЕсли;
Если ФайлПолученияВерсии <> Неопределено Тогда
ФайлПолученияВерсии = ПолучитьФайлWMIЛкс(ФайлПолученияВерсии.ПолноеИмя);
СтрокаТаблицыСборок.ФайлыСуществуют = Истина;
СтрокаТаблицыСборок.x64 = ирКэш.Это64битнаяОСЛкс() И Найти(СтрокаТаблицыСборок.Каталог, "(x86)") = 0;
СтрокаТаблицыСборок.СборкаПлатформы = ФайлПолученияВерсии.Version;
СтрокаТаблицыСборок.КлючСборки = КлючСборкиПлатформыЛкс(СтрокаТаблицыСборок);
СтрокаВерсии = ФайлПолученияВерсии.Version;
Если ЗначениеЗаполнено(СтрокаВерсии) Тогда
СтрокаТаблицыСборок.СборкаПлатформы = СтрокаВерсии;
Фрагменты = СтрРазделитьЛкс(СтрокаВерсии);
ИзданиеПлатформы = Фрагменты[0] + "." + Фрагменты[1];
СтрокаТаблицыСборок.ИзданиеПлатформы = ИзданиеПлатформы;
СтрокаТаблицыСборок.Порядок = Фрагменты[0] * 10000000 + Фрагменты[1] * 1000000 + Фрагменты[2] * 10000 + Фрагменты[3] + Число(СтрокаТаблицыСборок.x64);
КонецЕсли;
Иначе
СборкиПлатформы.Удалить(СтрокаТаблицыСборок);
Возврат Неопределено;
КонецЕсли;
СтрокаТаблицыСборок.НКаталог = НРег(СтрокаТаблицыСборок.Каталог);
Возврат СтрокаТаблицыСборок;
КонецФункции
Функция КлючСборкиПлатформыЛкс(Знач СтрокаТаблицыСборок) Экспорт
Возврат СтрокаТаблицыСборок.СборкаПлатформы + " - " + ?(СтрокаТаблицыСборок.x64, "64", "32");
КонецФункции
Функция ЗаменитьСлешиНаДвойныеЛкс(Строка) Экспорт
Результат = СтрЗаменить(Строка, "\", "\\");
Возврат Результат;
КонецФункции
// Функция - Выполнить команду ОСЛкс
//
// Параметры:
// СтрокаКоманды - Строка, Массив -
// ОжидатьЗавершения - Булево - ИмяКомпьютера - -
// _ИмяКомпьютера - -
// Элевация - -
// Состояние - -
// КодировкаРезультата - КодировкаТекста -
//
// Возвращаемое значение:
// Строка - текст вывода в синхронном режиме и файл вывода в асинхронном режиме
//
Функция ВыполнитьКомандуОСЛкс(Знач СтрокаКоманды = "", ОжидатьЗавершения = Истина, Знач _ИмяКомпьютера = "", Знач Элевация = Ложь, Знач Состояние = "", Знач КодировкаРезультата = Неопределено) Экспорт
ФайлРезультата = Новый Файл(ПолучитьИмяВременногоФайла("txt"));
Если ЗначениеЗаполнено(Состояние) Тогда
СостояниеЛкс(Состояние);
КонецЕсли;
Если ТипЗнч(СтрокаКоманды) = Тип("Массив") Тогда
СтрокаКоманды = МассивВСтрокуКомандыЛкс(СтрокаКоманды);
КонецЕсли;
ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(СтрокаКоманды, ФайлРезультата.Путь, ФайлРезультата.Имя, ОжидатьЗавершения, Элевация);
Если ОжидатьЗавершения Тогда
Если ФайлРезультата.Существует() Тогда
Если Не ЗначениеЗаполнено(КодировкаРезультата) Тогда
КодировкаРезультата = СистемнаяКодировкаТекстаОСЛкс();
КонецЕсли;
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ФайлРезультата.ПолноеИмя, КодировкаРезультата);
УдалитьФайлы(ФайлРезультата.ПолноеИмя);
Результат = СокрЛП(ТекстовыйДокумент.ПолучитьТекст());
Иначе
Результат = Неопределено;
КонецЕсли;
Иначе
Результат = ФайлРезультата;
КонецЕсли;
Если ЗначениеЗаполнено(Состояние) Тогда
СостояниеЛкс("");
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СистемнаяКодировкаТекстаОСЛкс() Экспорт
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
Кодировка = КодировкаТекста.OEM;
Иначе
Кодировка = КодировкаТекста.Системная;
КонецЕсли;
Возврат Кодировка;
КонецФункции
// .
// Параметры:
// ИмяФайлаРезультата - Краткое имя файла, в который будет выведен выходной поток, только в текущем каталоге.
// Элевация - Булево - используется только если текущая учетная запись Windows входит в группу Администраторы
//
Процедура ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(Знач СтрокаКоманды, Знач ТекущийКаталог = "", КраткоеИмяФайлаРезультата = "", ОжидатьЗавершения = Истина, Элевация = Ложь,
СообщитьКоманду = Ложь) Экспорт
Если Не ЗначениеЗаполнено(ТекущийКаталог) Тогда
ТекущийКаталог = КаталогВременныхФайлов();
КонецЕсли;
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
СтрокаКоманды =
"cd """ + ТекущийКаталог + """
|cmd.exe /c """ + СтрокаКоманды + """";
Иначе
СтрокаКоманды =
"bash -c '" + СтрокаКоманды + "'";
КонецЕсли;
Если КраткоеИмяФайлаРезультата <> "" Тогда
СтрокаКоманды = СтрокаКоманды + " > """ + ТекущийКаталог + КраткоеИмяФайлаРезультата + """";
СтрокаКоманды = СтрокаКоманды + " 2>&1"; //stderr
КонецЕсли;
Если СообщитьКоманду Тогда
СообщитьЛкс(СтрокаКоманды);
КонецЕсли;
Если ирКэш.ЛиПлатформаWindowsЛкс() Тогда
ИмяКомандногоФайла = СоздатьСамоудаляющийсяКомандныйФайлЛкс(СтрокаКоманды);
ВК = ВКОбщаяЛкс();
ВК.Run(ИмяКомандногоФайла, "", ТекущийКаталог, ОжидатьЗавершения, Элевация);
Иначе
КодВозврата = Неопределено;
ЗапуститьПриложение(СтрокаКоманды, ТекущийКаталог, ОжидатьЗавершения, КодВозврата);
КонецЕсли;
КонецПроцедуры
Функция МассивВСтрокуКомандыЛкс(КомандаЗапуска) Экспорт
Результат = Новый Массив;
НужныКавычки = Ложь;
Для Каждого Аргумент Из КомандаЗапуска Цикл
Если Результат.Количество() > 0 Тогда
Результат.Добавить(" ")
КонецЕсли;
НужныКавычки = Ложь
Или Аргумент = Неопределено
Или ПустаяСтрока(Аргумент)
Или Найти(Аргумент, " ")
Или Найти(Аргумент, Символы.Таб)
Или Найти(Аргумент, "&")
Или Найти(Аргумент, "(")
Или Найти(Аргумент, ")")
Или Найти(Аргумент, "[")
Или Найти(Аргумент, "]")
Или Найти(Аргумент, "{")
Или Найти(Аргумент, "}")
Или Найти(Аргумент, "^")
Или Найти(Аргумент, "=")
Или Найти(Аргумент, ";")
Или Найти(Аргумент, "!")
Или Найти(Аргумент, "'")
Или Найти(Аргумент, "+")
Или Найти(Аргумент, ",")
Или Найти(Аргумент, "`")
Или Найти(Аргумент, "~")
Или Найти(Аргумент, "$")
Или Найти(Аргумент, "|");
Если НужныКавычки Тогда
Результат.Добавить("""");
КонецЕсли;
Результат.Добавить(СтрЗаменить(Аргумент, """", """"""));
Если НужныКавычки Тогда
Результат.Добавить("""");
КонецЕсли;
КонецЦикла;
Возврат СтрСоединитьЛкс(Результат, "");
КонецФункции
Функция КомандаСистемыЗапускаСкриптаPowerShellЛкс(Знач ИмяФайлаСкриптаСПараметрами) Экспорт
КомандаСистемыЗапускаСкрипта = "powershell.exe -executionpolicy unrestricted -file " + ИмяФайлаСкриптаСПараметрами;
Возврат КомандаСистемыЗапускаСкрипта;
КонецФункции
Функция ЗапретитьУправляемуюБлокировку(Знач НичегоДелатьБезТранзакции = Ложь) Экспорт
Возврат Ложь
Или Метаданные.РежимУправленияБлокировкойДанных = Метаданные.СвойстваОбъектов.РежимУправленияБлокировкойДанныхПоУмолчанию.Автоматический
Или Метаданные.РежимУправленияБлокировкойДанных = Метаданные.СвойстваОбъектов.РежимУправленияБлокировкойДанныхПоУмолчанию.АвтоматическийИУправляемый
Или (Истина
И НичегоДелатьБезТранзакции
И Не ТранзакцияАктивна());
КонецФункции
Процедура ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, НичегоДелатьБезТранзакции = Ложь, НовыйРежимБлокировкиДанных = Неопределено) Экспорт
Если ЗапретитьУправляемуюБлокировку(НичегоДелатьБезТранзакции) Тогда
Возврат;
КонецЕсли;
Блокировка = Новый БлокировкаДанных;
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъектаБДЛкс(НаборЗаписей));
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют;
НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
#КонецЕсли
ПространствоБлокировок = ОбъектМД.ПолноеИмя();
КорневойТип = ПервыйФрагментЛкс(ПространствоБлокировок);
Если ТипТаблицыБДЛкс(ПространствоБлокировок) = "Перерасчет" Тогда
Возврат;
//ПространствоБлокировок = ОбъектМД.Родитель().ПолноеИмя();
КонецЕсли;
Если Ложь
Или Не ЛиКорневойТипРегистраСведенийЛкс(КорневойТип)
Или ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору
Тогда
ПространствоБлокировок = ПространствоБлокировок + ".НаборЗаписей";
КонецЕсли;
СловоПериод = "";
Если ЛиКорневойТипРегистраСведенийЛкс(КорневойТип) Тогда
СловоПериод = ПеревестиСтроку("Период");
КонецЕсли;
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
Если Истина
И ЭлементОтбора.Имя = СловоПериод
И ирКэш.НомерВерсииПлатформыЛкс() > 803001
И (Ложь
Или ОбъектМД.РазрешитьИтогиСрезПоследних
Или ОбъектМД.РазрешитьИтогиСрезПервых)
Тогда
// При итогах нельзя включать период https://www.hostedredmine.com/issues/963838
Продолжить;
КонецЕсли;
Если ЭлементОтбора.Использование Тогда
ЭлементБлокировки.УстановитьЗначение(ЭлементОтбора.Имя, ЭлементОтбора.Значение);
КонецЕсли;
КонецЦикла;
Если НовыйРежимБлокировкиДанных = Неопределено Тогда
НовыйРежимБлокировкиДанных = РежимБлокировкиДанных.Исключительный;
КонецЕсли;
ЭлементБлокировки.Режим = НовыйРежимБлокировкиДанных;
Блокировка.Заблокировать();
КонецПроцедуры
Процедура ЗаблокироватьРегистрПоМенеджеруЗаписиЛкс(МенеджерЗаписи, НичегоДелатьБезТранзакции = Ложь, Знач РежимБлокировки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
#КонецЕсли
Если ЗапретитьУправляемуюБлокировку(НичегоДелатьБезТранзакции) Тогда
Возврат;
КонецЕсли;
Блокировка = Новый БлокировкаДанных;
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(МенеджерЗаписи));
ПространствоБлокировок = ОбъектМД.ПолноеИмя();
КорневойТип = ПервыйФрагментЛкс(ПространствоБлокировок);
Если ТипТаблицыБДЛкс(ПространствоБлокировок) = "Перерасчет" Тогда
Возврат;
//ПространствоБлокировок = ОбъектМД.Родитель().ПолноеИмя();
КонецЕсли;
Если ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору Тогда
ПространствоБлокировок = ПространствоБлокировок + ".НаборЗаписей";
КонецЕсли;
НаборЗаписей = Новый (ИмяТипаИзПолногоИмениМДЛкс(ОбъектМД, "НаборЗаписей"));
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
ЭлементБлокировки.УстановитьЗначение(ЭлементОтбора.Имя, МенеджерЗаписи[ЭлементОтбора.Имя]);
КонецЦикла;
Если РежимБлокировки <> Неопределено Тогда
ЭлементБлокировки.Режим = РежимБлокировки;
КонецЕсли;
Блокировка.Заблокировать();
КонецПроцедуры
Процедура ЗаблокироватьСсылкуВТранзакцииЛкс(СсылочныйОбъект, НичегоДелатьБезТранзакции = Ложь) Экспорт
Если ЗапретитьУправляемуюБлокировку(НичегоДелатьБезТранзакции) Тогда
Возврат;
КонецЕсли;
Блокировка = Новый БлокировкаДанных;
ОбъектМД = СсылочныйОбъект.Метаданные();
ПространствоБлокировок = ОбъектМД.ПолноеИмя();
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
ЭлементБлокировки.УстановитьЗначение("Ссылка", СсылочныйОбъект.Ссылка);
Блокировка.Заблокировать();
КонецПроцедуры
Процедура ЗаблокироватьКонстантуЛкс(КонстантаМенеджерЗначения, НичегоДелатьБезТранзакции = Ложь, Знач РежимБлокировки = Неопределено) Экспорт
Если ЗапретитьУправляемуюБлокировку(НичегоДелатьБезТранзакции) Тогда
Возврат;
КонецЕсли;
Блокировка = Новый БлокировкаДанных;
ОбъектМД = Метаданные.НайтиПоТипу(ТипОбъектаБДЛкс(КонстантаМенеджерЗначения));
ПространствоБлокировок = ОбъектМД.ПолноеИмя();
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
Если РежимБлокировки <> Неопределено Тогда
ЭлементБлокировки.Режим = РежимБлокировки;
КонецЕсли;
Блокировка.Заблокировать();
КонецПроцедуры
Функция ПредставлениеПоляБДЛкс(СтрокаПоля, ЛиИменаБД = Ложь, _ЭтоТабличнаяЧасть = Ложь, ИспользоватьИмяПоляВместоПустогоПредставления = Ложь) Экспорт
ПредставлениеПоля = СтрокаПоля.ИмяПоля;
Если ПустаяСтрока(ПредставлениеПоля) Тогда
Если ЛиИменаБД Тогда
Если СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_Period") Тогда
ПредставлениеПоля = "Период";
ИначеЕсли Найти(СтрокаПоля.ИмяПоляХранения, "IDRRef") > 0 Тогда
// Антибаг платформы. У некоторых полей почему то пустое имя, а должно быть непустое. https://partners.v8.1c.ru/forum/topic/1275356#m_1275356
ПредставлениеПоля = "Ссылка";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_KeyField") Тогда
ПредставлениеПоля = "КлючСтроки";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_SliceUsing") Тогда
ПредставлениеПоля = "ВключенСрезПоследних";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_Version") Тогда
ПредставлениеПоля = "Версия";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_MessageNo") Тогда
ПредставлениеПоля = "НомерСообщения";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_RecordKey") Тогда
ПредставлениеПоля = "КлючСтроки";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_ConstID") Тогда
ПредставлениеПоля = "КлючКонстанты";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_NumberPrefix") Тогда
ПредставлениеПоля = "ПериодНомера";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_NodeTRef") Тогда
ПредставлениеПоля = "Узел_ТипСсылки";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_NodeRRef") Тогда
ПредставлениеПоля = "Узел";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_ObjectKey") Тогда
ПредставлениеПоля = "КлючОбъекта";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_UserId") Тогда
ПредставлениеПоля = "КлючПользователя";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_SettingsKey") Тогда
ПредставлениеПоля = "КлючНастроек";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_SettingsData") Тогда
ПредставлениеПоля = "Настройки";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_SettingsPresentation") Тогда
ПредставлениеПоля = "ОписаниеНастроек";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_PredefinedID") Тогда
ПредставлениеПоля = "ИмяПредопределенныхДанных";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_RecorderTRef") Тогда
ПредставлениеПоля = "Регистратор_ТипСсылки";
ИначеЕсли СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "_RecorderRRef") Тогда
ПредставлениеПоля = "Регистратор";
ИначеЕсли ЗначениеЗаполнено(СтрокаПоля.Метаданные) Тогда
ПредставлениеПоля = ПоследнийФрагментЛкс(СтрокаПоля.Метаданные);
КонецЕсли;
Иначе
Если СтрокиРавныЛкс(СтрокаПоля.ИмяПоляХранения, "NumberPrefix") Тогда
ПредставлениеПоля = "ПрефиксНомера";
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(ПредставлениеПоля) Тогда
Если ЛиИменаБД Тогда
НИмяПоляХранения = НРег(СтрокаПоля.ИмяПоляХранения);
НМаркерПоляТипаЗначения = НРег("TYPE");
НМаркерПоляТипаСсылки = НРег("TRef");
//МаркерПоляЗначенияСсылки = НРег("RRef");
Если Прав(НИмяПоляХранения, СтрДлина(НМаркерПоляТипаСсылки)) = НМаркерПоляТипаСсылки Тогда
ПредставлениеПоля = ПредставлениеПоля + "_ТипСсылки";
ИначеЕсли Прав(НИмяПоляХранения, СтрДлина(НМаркерПоляТипаЗначения)) = НМаркерПоляТипаЗначения Тогда
ПредставлениеПоля = ПредставлениеПоля + "_ТипЗначения";
//ИначеЕсли Прав(НИмяПоляХранения, СтрДлина(НМаркерПоляЗначенияСсылки)) = НМаркерПоляЗначенияСсылки Тогда
// ПредставлениеПоля = ПредставлениеПоля + "_Ссылка";
КонецЕсли;
КонецЕсли;
ИначеЕсли ИспользоватьИмяПоляВместоПустогоПредставления Тогда
ПредставлениеПоля = СтрокаПоля.ИмяПоляХранения;
КонецЕсли;
Возврат ПредставлениеПоля;
КонецФункции
Функция ПредставлениеСтруктурыЛкс(Структура) Экспорт
#Если Сервер И Не Сервер Тогда
Структура = Новый Структура;
#КонецЕсли
ПредставлениеСтруктуры = "";
Для Каждого КлючИЗначение Из Структура Цикл
Если ПредставлениеСтруктуры <> "" Тогда
ПредставлениеСтруктуры = ПредставлениеСтруктуры + ", ";
КонецЕсли;
ПредставлениеСтруктуры = ПредставлениеСтруктуры + КлючИЗначение.Ключ + " = " + КлючИЗначение.Значение;
КонецЦикла;
Возврат ПредставлениеСтруктуры;
КонецФункции
Функция ПредставлениеИндексаХраненияЛкс(СтрокаИндексаСтруктурыБД, ЛиСтруктураДанныхВИменахБД = Ложь, СтрокаТаблицыХранения, ЛиПредставлениеВИменахБД = Ложь) Экспорт
ЭтоТабличнаяЧасть = СтрокаТаблицыХранения.Назначение = "ТабличнаяЧасть";
ПредставлениеИндекса = "";
Разделитель = "";
ПредИмя = "";
_РежимОтладки = ирКэш.РежимОтладкиЛкс();
Если _РежимОтладки Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для каждого СтрокаПоля Из СтрокаИндексаСтруктурыБД.Поля Цикл
Если ЛиПредставлениеВИменахБД Тогда
ПредставлениеПоля = СтрокаПоля.ИмяПоляХранения;
Иначе
ПредставлениеПоля = ПредставлениеПоляБДЛкс(СтрокаПоля, ЛиСтруктураДанныхВИменахБД, ЭтоТабличнаяЧасть, Истина);
КонецЕсли;
Если ПредИмя = ПредставлениеПоля Тогда
Продолжить;
КонецЕсли;
ПредставлениеИндекса = ПредставлениеИндекса + Разделитель + ПредставлениеПоля;
Разделитель = ", ";
ПредИмя = ПредставлениеПоля;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Для каждого СтрокаПоля Из СтрокаИндексаСтруктурыБД.Поля Цикл Если ЛиПредставлениеВИменахБД Тогда ПредставлениеПоля = СтрокаПоля.ИмяПоляХранения; Иначе ПредставлениеПоля = ПредставлениеПоляБДЛкс(СтрокаПоля, ЛиСтруктураДанныхВИменахБД, ЭтоТабличнаяЧасть, Истина); КонецЕсли; Если ПредИмя = ПредставлениеПоля Тогда Продолжить; КонецЕсли; ПредставлениеИндекса = ПредставлениеИндекса + Разделитель + ПредставлениеПоля; Разделитель = ", "; ПредИмя = ПредставлениеПоля; КонецЦикла;
КонецЕсли;
Возврат ПредставлениеИндекса;
КонецФункции
Процедура ОбработатьВыборкуСтруктурыХраненияБДЛкс(Знач Результат, ЛиИменаБД = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Результат = Новый ТаблицаЗначений;
#КонецЕсли
Если Результат.Колонки.Найти("КраткоеИмяТаблицыХранения") <> Неопределено Тогда
// Например это схема чужой БД
//Возврат;
Иначе
//Результат.Колонки.ИмяТаблицыХранения.Имя = "ИмяТаблицыХраненияСРегистромБукв";
Результат.Колонки.Добавить("КраткоеИмяТаблицыХранения", Новый ОписаниеТипов("Строка"));
//Результат.Колонки.Добавить("ИмяТаблицыХранения", Новый ОписаниеТипов("Строка"));
КонецЕсли;
ПеревестиКолонкиСтруктурыХраненияБДТаблицыЛкс(Результат);
Для Каждого СтрокаТаблицыХранения Из Результат Цикл
// Антибаг платформы 8.2.16 У ряда назначений таблиц ИмяТаблицы пустое http://partners.v8.1c.ru/forum/thread.jsp?id=1090307#1090307
Если ПустаяСтрока(СтрокаТаблицыХранения.ИмяТаблицы) Тогда
МетаПолноеИмяТаблицы = "";
Если ЗначениеЗаполнено(СтрокаТаблицыХранения.Метаданные) Тогда
МетаПолноеИмяТаблицы = СтрокаТаблицыХранения.Метаданные;
КонецЕсли;
Если СтрокаТаблицыХранения.Назначение = "РегистрацияИзменений" Тогда
СтрокаТаблицыХранения.ИмяТаблицы = МетаПолноеИмяТаблицы + ".Изменения";
ИначеЕсли СтрокаТаблицыХранения.Назначение = "Основная" Тогда
СтрокаТаблицыХранения.ИмяТаблицы = МетаПолноеИмяТаблицы;
Иначе
Если ЗначениеЗаполнено(МетаПолноеИмяТаблицы) Тогда
МетаПолноеИмяТаблицы = МетаПолноеИмяТаблицы + "." + СтрокаТаблицыХранения.Назначение;
Иначе
МетаПолноеИмяТаблицы = СтрокаТаблицыХранения.Назначение;
КонецЕсли;
СтрокаТаблицыХранения.ИмяТаблицы = МетаПолноеИмяТаблицы;
КонецЕсли;
КонецЕсли;
//СтрокаТаблицыХранения.ИмяТаблицыХранения = НРег(ПоследнийФрагментЛкс(СтрокаТаблицыХранения.ИмяТаблицыХраненияСРегистромБукв));
// В режим ЛиИменаБД=Ложь Document209.VT2672->VT2672
Если Не ЗначениеЗаполнено(СтрокаТаблицыХранения.КраткоеИмяТаблицыХранения) Тогда
СтрокаТаблицыХранения.КраткоеИмяТаблицыХранения = НРег(ПоследнийФрагментЛкс(СтрокаТаблицыХранения.ИмяТаблицыХранения));
КонецЕсли;
КонецЦикла;
ДобавитьИндексВТаблицуЛкс(Результат, "КраткоеИмяТаблицыХранения");
КонецПроцедуры
// Процедура - Заполнить имя индекса хранения лкс
//
// Параметры:
// СтрокаИндексаХранения - СтрокаТаблицыЗначений -
// ЛиИменаБД - -
// СтрокаТаблицыХранения - -
//
Процедура ЗаполнитьИмяИндексаХраненияЛкс(Знач СтрокаИндексаХранения, Знач ЛиИменаБД, Знач СтрокаТаблицыХранения) Экспорт
Индексы = СтрокаТаблицыХранения.Индексы;
Если Индексы.Колонки.Найти("ИмяИндекса") = Неопределено Тогда
Индексы.Колонки.Добавить("ИмяИндекса", Новый ОписаниеТипов("Строка"));
ПеревестиКолонкиСтруктурыХраненияБДИндексыЛкс(Индексы);
КонецЕсли;
Если Не ЗначениеЗаполнено(СтрокаИндексаХранения.ИмяИндекса) Тогда
ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(СтрокаИндексаХранения.Поля);
ПредставлениеИндекса = ПредставлениеИндексаХраненияЛкс(СтрокаИндексаХранения, ЛиИменаБД, СтрокаТаблицыХранения);
СтрокаИндексаХранения.ИмяИндекса = "Индекс(" + ПредставлениеИндекса + ")";
КонецЕсли;
КонецПроцедуры
Процедура ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(Знач Поля) Экспорт
#Если Сервер И Не Сервер Тогда
Поля = Новый ТаблицаЗначений;
#КонецЕсли
Если Поля.Колонки.Найти("ИмяПоля") = Неопределено Тогда
Поля.Колонки[ПеревестиСтроку("ИмяПоля")].Имя = "ИмяПоля";
Поля.Колонки[ПеревестиСтроку("ИмяПоляХранения")].Имя = "ИмяПоляХранения";
Поля.Колонки[ПеревестиСтроку("Метаданные")].Имя = "Метаданные";
КонецЕсли;
КонецПроцедуры
Процедура ПеревестиКолонкиСтруктурыХраненияБДИндексыЛкс(Знач Индексы) Экспорт
#Если Сервер И Не Сервер Тогда
Индексы = Новый ТаблицаЗначений;
#КонецЕсли
Если Индексы.Колонки.Найти("Поля") = Неопределено Тогда
Индексы.Колонки[ПеревестиСтроку("ИмяИндексаХранения")].Имя = "ИмяИндексаХранения";
Индексы.Колонки[ПеревестиСтроку("Поля")].Имя = "Поля";
КонецЕсли;
КонецПроцедуры
Процедура ПеревестиКолонкиСтруктурыХраненияБДТаблицыЛкс(Знач Результат) Экспорт
#Если Сервер И Не Сервер Тогда
Результат = Новый ТаблицаЗначений;
#КонецЕсли
Если Результат.Колонки.Найти("Поля") = Неопределено Тогда
Результат.Колонки[ПеревестиСтроку("ИмяТаблицы")].Имя = "ИмяТаблицы";
Результат.Колонки[ПеревестиСтроку("ИмяТаблицыХранения")].Имя = "ИмяТаблицыХранения";
Результат.Колонки[ПеревестиСтроку("Индексы")].Имя = "Индексы";
Результат.Колонки[ПеревестиСтроку("Метаданные")].Имя = "Метаданные";
Результат.Колонки[ПеревестиСтроку("Назначение")].Имя = "Назначение";
Результат.Колонки[ПеревестиСтроку("Поля")].Имя = "Поля";
КонецЕсли;
КонецПроцедуры
Процедура ПеревестиКолонкиНайтиПоСсылкамЛкс(Знач Таблица, НуженПеревод = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
Если НуженПеревод = Неопределено Тогда
НуженПеревод = Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Английский;
КонецЕсли;
Если НуженПеревод Тогда
Попытка
Таблица.Колонки[ПеревестиСтроку("Ссылка")].Имя = "Ссылка";
Таблица.Колонки[ПеревестиСтроку("Данные")].Имя = "Данные";
Таблица.Колонки[ПеревестиСтроку("Метаданные")].Имя = "Метаданные";
Исключение
// Повторный перевод
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Процедура ПеревестиКолонкиСистемнойТаблицыЛкс(Знач Таблица, НуженПеревод = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
Таблица = Новый ТаблицаЗначений;
#КонецЕсли
Если НуженПеревод = Неопределено Тогда
НуженПеревод = Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Английский;
КонецЕсли;
Если НуженПеревод Тогда
Для Каждого Колонка Из Таблица.Колонки Цикл
Таблица.Колонки[Колонка.Имя].Имя = ПеревестиВРусский(Колонка.Имя);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция СтруктураХраненияБДЛкс(Знач ОтборПоМетаданным = Неопределено, ЛиИменаБД = Ложь, АдресЧужойСхемыБД = "") Экспорт
Если ОтборПоМетаданным = Неопределено Тогда
#Если Клиент Тогда
СостояниеЛкс("Получение структуры БД…");
#КонецЕсли
ИначеЕсли ТипЗнч(ОтборПоМетаданным) <> Тип("Массив") Тогда
Массив = Новый Массив;
Массив.Добавить(ОтборПоМетаданным);
ОтборПоМетаданным = Массив;
КонецЕсли;
Если ЗначениеЗаполнено(АдресЧужойСхемыБД) Тогда
СтруктураСхемы = ПолучитьЧужуюСхемуБДЛкс(АдресЧужойСхемыБД);
Если ЛиИменаБД Тогда
ГлавнаяТаблица = СтруктураСхемы.СУБД;
Иначе
ГлавнаяТаблица = СтруктураСхемы.SDBL;
КонецЕсли;
Если ОтборПоМетаданным <> Неопределено Тогда
Результат = ГлавнаяТаблица.СкопироватьКолонки();
Если ГлавнаяТаблица.Индексы.Количество() = 0 Тогда
ГлавнаяТаблица.Индексы.Добавить("Метаданные");
КонецЕсли;
Для Каждого ИмяМД Из ОтборПоМетаданным Цикл
Для Каждого СтрокаТаблицы Из ГлавнаяТаблица.НайтиСтроки("Метаданные", ИмяМД) Цикл
ЗаполнитьЗначенияСвойств(Результат.Добавить(), СтрокаТаблицы);
КонецЦикла;
КонецЦикла;
Иначе
Результат = ГлавнаяТаблица;
КонецЕсли;
Иначе
Результат = ПолучитьСтруктуруХраненияБазыДанных(ОтборПоМетаданным, ЛиИменаБД);
КонецЕсли;
//! Результат.Колонки.Добавить("ИмяТаблицы");
//! Результат.Колонки.Добавить("ИмяТаблицыХранения");
//! Результат.Колонки.Добавить("Метаданные");
//! Результат.Колонки.Добавить("Назначение");
//! Результат.Колонки.Добавить("Поля"); //ТаблицаЗначений
//! Результат.Колонки.Добавить("Индексы"); //ТаблицаЗначений
//! Результат.Колонки.Добавить("КраткоеИмяТаблицыХранения");
ОбработатьВыборкуСтруктурыХраненияБДЛкс(Результат, ЛиИменаБД);
Если ОтборПоМетаданным = Неопределено Тогда
#Если Клиент Тогда
СостояниеЛкс("");
#КонецЕсли
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПолучитьЧужуюСхемуБДЛкс(АдресЧужойСхемыБД) Экспорт
Если Не ЗначениеЗаполнено(АдресЧужойСхемыБД) Тогда
Возврат Неопределено;
Иначе
Результат = ПолучитьИзВременногоХранилища(АдресЧужойСхемыБД);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СтруктураХраненияБДСРазмерамиЛкс(Знач ИменаSDBL = Ложь, Знач ОтборПоМетаданным = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Обработка = мПлатформа.мСтруктураХраненияБДСРазмерами;
Если Обработка = Неопределено Тогда
Обработка = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирСтруктураХраненияБД");
мПлатформа.мСтруктураХраненияБДСРазмерами = Обработка;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
Обработка = Обработки.ирСтруктураХраненияБД.Создать();
#КонецЕсли
Если Ложь
Или Обработка.Таблицы.Количество() = 0
Или Не Обработка.ПоказыватьSDBL И ИменаSDBL
Или Обработка.ОтборПоМетаданным <> Неопределено И ОтборПоМетаданным <> Неопределено
Тогда
Обработка.ПоказыватьСУБД = Истина;
Обработка.ПоказыватьSDBL = Обработка.ПоказыватьSDBL Или ИменаSDBL;
Обработка.ПоказыватьРазмеры = Истина;
Обработка.ОтборПоМетаданным = ОтборПоМетаданным;
Обработка.ОбновитьТаблицы();
ИначеЕсли Истина
И Не Обработка.ПоказыватьРазмеры // Если закомментировать то всегда свежие размеры будут
Тогда
Обработка.ПоказыватьРазмеры = Истина;
Обработка.ВычислитьРазмерыТаблиц();
КонецЕсли;
Возврат Обработка;
КонецФункции
Функция ДочернийОбъектМДПоИмениЛкс(Знач МетаОбъект, Знач ИмяПоля, Знач ТипТаблицы = "") Экспорт
Если Не ЗначениеЗаполнено(ТипТаблицы) Тогда
ТипТаблицы = КорневойТипКонфигурацииЛкс(МетаОбъект);
КонецЕсли;
Если Ложь
Или ЛиКорневойТипСсылочногоОбъектаБДЛкс(ТипТаблицы)
Или ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы)
Тогда
#Если Сервер И Не Сервер Тогда
МетаОбъект = Метаданные.Справочники.Валюты;
#КонецЕсли
Результат = МетаОбъект.Реквизиты.Найти(ИмяПоля);
ИначеЕсли ЛиКорневойТипРегистраБДЛкс(ТипТаблицы) Тогда
#Если Сервер И Не Сервер Тогда
МетаОбъект = Метаданные.РегистрыСведений.КурсыВалют;
#КонецЕсли
Результат = МетаОбъект.Измерения.Найти(ИмяПоля);
Если Не ЛиКорневойТипПоследовательностиЛкс(ТипТаблицы) Тогда
Если Результат = Неопределено Тогда
Результат = МетаОбъект.Ресурсы.Найти(ИмяПоля);
КонецЕсли;
Если Результат = Неопределено Тогда
Результат = МетаОбъект.Реквизиты.Найти(ИмяПоля);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Результат = Неопределено И ирКэш.ДоступноОбщиеРеквизитыЛкс() Тогда
ОбщийРеквизит = Метаданные.ОбщиеРеквизиты.Найти(ИмяПоля);
Если ОбщийРеквизит <> Неопределено Тогда
Если ЛиОбщийРеквизитИспользуетсяВОбъектеМетаданныхЛкс(ОбщийРеквизит, МетаОбъект) Тогда
Результат = ОбщийРеквизит;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура ОбновитьПовторноИспользуемыеЗначенияЛкс() Экспорт
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
ирПортативный.ОбновитьПовторноИспользуемыеЗначенияЛкс();
Иначе
ОбновитьПовторноИспользуемыеЗначения();
КонецЕсли;
КонецПроцедуры
Функция ПолучитьСовместимоеЗначениеПараметраЗапросаЛкс(Знач ЗначениеПараметра, ИмяПараметра, ОписаниеТиповЭлементаУправленияПараметра = Неопределено) Экспорт
Результат = ЗначениеПараметра;
ТипЗначенияПараметра = ТипЗнч(Результат);
Если Истина
И ТипЗначенияПараметра = Тип("Массив")
И ОписаниеТиповЭлементаУправленияПараметра <> Неопределено
Тогда
СписокЗначений = Новый СписокЗначений;
ПреобразованиеУспешно = Истина;
Для Каждого ЭлементМассива Из Результат Цикл
Если ОписаниеТиповЭлементаУправленияПараметра.СодержитТип(ТипЗнч(ЭлементМассива)) Тогда
СписокЗначений.Добавить(ЭлементМассива);
Иначе
ПреобразованиеУспешно = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Если ПреобразованиеУспешно Тогда
Результат = СписокЗначений;
КонецЕсли;
Иначе
// http://www.hostedredmine.com/issues/885230
//МетаданныеТипаЗначения = Метаданные.НайтиПоТипу(ТипЗначенияПараметра);
//Если МетаданныеТипаЗначения <> Неопределено Тогда
// ТипТаблицы = ТипТаблицыБДЛкс(МетаданныеТипаЗначения.ПолноеИмя());
// Если ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда
// Результат = ЗначениеПараметра.Выгрузить();
// КонецЕсли;
//КонецЕсли;
Попытка
Результат = Результат.Выгрузить();
Исключение
КонецПопытки;
Если ОписаниеТиповЭлементаУправленияПараметра <> Неопределено Тогда
#Если Сервер И Не Сервер Тогда
ОписаниеТиповЭлементаУправленияПараметра = Новый ОписаниеТипов;
#КонецЕсли
Результат = ОписаниеТиповЭлементаУправленияПараметра.ПривестиЗначение(Результат);
КонецЕсли;
КонецЕсли;
Если Результат <> ЗначениеПараметра Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Значение параметра %1 было преобразовано %2->%3", 1, ИмяПараметра, 2, ТипЗначенияПараметра, 3, ТипЗнч(Результат)), СтатусСообщения.Внимание);
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура ПолучитьСхемуИНастройкиКомпоновкиДинамическогоСпискаЛкс(Знач ДинамическийСписок, выхНастройкаКомпоновки, выхСхема) Экспорт
ТекстЗапроса = ДинамическийСписок.ТекстЗапроса;
Если Не ЗначениеЗаполнено(ТекстЗапроса) Тогда
ТекстЗапроса = "ВЫБРАТЬ * ИЗ " + ДинамическийСписок.ОсновнаяТаблица;
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапроса);
выхНастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
ТекущаяГруппировка = выхНастройкаКомпоновки;
Для Каждого ПолеГруппировки Из ДинамическийСписок.Группировка.Элементы Цикл
Если ПолеГруппировки.Использование Тогда
ТекущаяГруппировка = НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(ТекущаяГруппировка.Структура, ПолеГруппировки.Поле);
КонецЕсли;
КонецЦикла;
НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(ТекущаяГруппировка.Структура);
Для Каждого ДоступноеПоле Из ДинамическийСписок.УсловноеОформление.ДоступныеПоляПолей.Элементы Цикл
Если ДоступноеПоле.Папка Тогда
Продолжить;
КонецЕсли;
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(выхНастройкаКомпоновки.Выбор, ДоступноеПоле.Поле);
КонецЦикла;
НастройкаXDTO = СериализаторXDTO.ЗаписатьXDTO(выхНастройкаКомпоновки);
НастройкаXDTO.Filter = СериализаторXDTO.ЗаписатьXDTO(ДинамическийСписок.Отбор);
НастройкаXDTO.DataParameters = СериализаторXDTO.ЗаписатьXDTO(ДинамическийСписок.Параметры);
НастройкаXDTO.Order = СериализаторXDTO.ЗаписатьXDTO(ДинамическийСписок.Порядок);
НастройкаXDTO.ConditionalAppearance = СериализаторXDTO.ЗаписатьXDTO(ДинамическийСписок.УсловноеОформление);
выхНастройкаКомпоновки = СериализаторXDTO.ПрочитатьXDTO(НастройкаXDTO);
выхСхема = СоздатьСхемуКомпоновкиПоЗапросуЛкс(Запрос);
КонецПроцедуры
// Создает новый экземпляр объекта и полностью замещает в нем выбранные настройки компоновки. Для дополнения оригинального объекта следует использовать СкопироватьЭлементыКомпоновкиЛкс()
Функция СкопироватьНастройкиКомпоновкиЛкс(НастройкаКомпоновкиИлиДинамическийСписокИсточник, Знач НастройкаКомпоновкиПриемник = Неопределено, КопироватьОтбор = Ложь,
КопироватьПараметрыДанных = Ложь, КопироватьПорядок = Ложь, КопироватьУсловноеОформление = Ложь, КопироватьВыбор = Ложь, КопироватьПараметрыВывода = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
НастройкаКомпоновкиИсточник = Новый НастройкиКомпоновкиДанных;
НастройкаКомпоновкиИлиДинамическийСписокИсточник = Новый НастройкиКомпоновкиДанных;
#КонецЕсли
Если ТипЗнч(НастройкаКомпоновкиИлиДинамическийСписокИсточник) = Тип("НастройкиКомпоновкиДанных") Тогда
Если КопироватьПараметрыДанных Тогда
ПараметрыДанных = НастройкаКомпоновкиИлиДинамическийСписокИсточник.ПараметрыДанных;
КонецЕсли;
Если КопироватьПараметрыВывода Тогда
ПараметрыВывода = НастройкаКомпоновкиИлиДинамическийСписокИсточник.ПараметрыВывода;
КонецЕсли;
Иначе // ДинамическийСписок
//! НастройкаКомпоновкиИлиДинамическийСписокИсточник = 0 // ДинамическийСписок
Если КопироватьПараметрыДанных Тогда
ПараметрыДанных = НастройкаКомпоновкиИлиДинамическийСписокИсточник.Параметры;
КонецЕсли;
КонецЕсли;
//! НастройкаКомпоновкиИлиДинамическийСписокИсточник = 0 // НастройкиКомпоновкиДанных
Если КопироватьВыбор Тогда
Выбор = НастройкаКомпоновкиИлиДинамическийСписокИсточник.Выбор;
КонецЕсли;
Если КопироватьОтбор Тогда
Отбор = НастройкаКомпоновкиИлиДинамическийСписокИсточник.Отбор;
КонецЕсли;
Если КопироватьПорядок Тогда
Порядок = НастройкаКомпоновкиИлиДинамическийСписокИсточник.Порядок;
КонецЕсли;
Если КопироватьУсловноеОформление Тогда
УсловноеОформление = НастройкаКомпоновкиИлиДинамическийСписокИсточник.УсловноеОформление;
КонецЕсли;
НастройкаКомпоновкиПриемник = УстановитьКомпонентыНастроекКомпоновкиЛкс(НастройкаКомпоновкиПриемник, ПараметрыДанных, Выбор, Отбор, Порядок, УсловноеОформление, ПараметрыВывода);
Возврат НастройкаКомпоновкиПриемник;
КонецФункции
// Параметры:
// НастройкаКомпоновкиПриемник - ? -
// Параметры - ? -
// Выбор - ? -
// Отбор - ? -
// Порядок - ? -
// УсловноеОформление - ? -
// Возвращаемое значение:
// НастройкиКомпоновкиДанных - новый объект настроек с установленными компонентами
Функция УстановитьКомпонентыНастроекКомпоновкиЛкс(Знач НастройкаКомпоновкиПриемник = Неопределено, Знач ПараметрыДанных = Неопределено, Знач Выбор = Неопределено, Знач Отбор = Неопределено,
Знач Порядок = Неопределено, Знач УсловноеОформление = Неопределено, ПараметрыВывода = Неопределено) Экспорт
Если НастройкаКомпоновкиПриемник = Неопределено Тогда
НастройкаКомпоновкиПриемник = Новый НастройкиКомпоновкиДанных;
КонецЕсли;
НастройкаXDTO = СериализаторXDTO.ЗаписатьXDTO(НастройкаКомпоновкиПриемник);
Если ПараметрыДанных <> Неопределено Тогда
НастройкаXDTO.DataParameters = СериализаторXDTO.ЗаписатьXDTO(ПараметрыДанных);
КонецЕсли;
Если Выбор <> Неопределено Тогда
НастройкаXDTO.selection = СериализаторXDTO.ЗаписатьXDTO(Выбор);
КонецЕсли;
Если Отбор <> Неопределено Тогда
НастройкаXDTO.Filter = СериализаторXDTO.ЗаписатьXDTO(Отбор);
КонецЕсли;
Если Порядок <> Неопределено Тогда
НастройкаXDTO.Order = СериализаторXDTO.ЗаписатьXDTO(Порядок);
КонецЕсли;
Если УсловноеОформление <> Неопределено Тогда
НастройкаXDTO.ConditionalAppearance = СериализаторXDTO.ЗаписатьXDTO(УсловноеОформление);
КонецЕсли;
Если ПараметрыВывода <> Неопределено Тогда
НастройкаXDTO.OutputParameters = СериализаторXDTO.ЗаписатьXDTO(ПараметрыВывода);
КонецЕсли;
НастройкаКомпоновкиПриемник = СериализаторXDTO.ПрочитатьXDTO(НастройкаXDTO);
Возврат НастройкаКомпоновкиПриемник;
КонецФункции
// Дополнительно к обычному восстановлению настроек обеспечивает защита от ошибки "Глобальные элементы отбора обязательно должны использовать поля"
Процедура КомпоновщикНастроекВосстановитьЛкс(Компоновщик) Экспорт
#Если Сервер И Не Сервер Тогда
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
#КонецЕсли
Компоновщик.Восстановить(); //Удаляет некорректные элементы пользовательских настроек https://www.hostedredmine.com/issues/947616
// Защита от ошибки "глобальные элементы отбора обязательно должны использовать поля"
// https://partners.v8.1c.ru/forum/topic/2028705
Для Каждого ЭлементОтбора Из Компоновщик.Настройки.Отбор.Элементы Цикл
Если Истина
И ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных")
И ТипЗнч(ЭлементОтбора.ЛевоеЗначение) <> Тип("ПолеКомпоновкиДанных")
Тогда
ЭлементОтбора.Использование = Ложь;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция РасширениеФайловДляОтладкиЛкс() Экспорт
Результат = "deb";
Возврат Результат;
КонецФункции
Функция ОтложитьУпакованныйОбъектДляОтладкиЛкс(СтруктураПараметров, выхОбъектДляОтладки = Неопределено, Знач Наименование = "", Знач ФорматВнутр = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
СтруктураПараметров = Новый Структура;
#КонецЕсли
Если Не ЗначениеЗаполнено(Наименование) Тогда
Наименование = "" + СтруктураПараметров.Объект;
КонецЕсли;
Наименование = "" + ТекущаяДата() + " " + СтруктураПараметров.ТипОперации + " " + Наименование;
Наименование = Лев(Наименование, 100);
Если ТранзакцияАктивна() Тогда
ФильтрЖурнала = Новый Структура;
События = Новый Массив;
События.Добавить("_$Data$_.Update");
События.Добавить("_$Data$_.New");
События.Добавить("_$Data$_.Delete");
События.Добавить("_$Data$_.Post");
События.Добавить("_$Data$_.Unpost");
ФильтрЖурнала.Вставить("Событие", События);
ФильтрЖурнала.Вставить("СтатусТранзакции", СтатусТранзакцииЗаписиЖурналаРегистрации.НеЗавершена);
ФильтрЖурнала.Вставить("Сеанс", НомерСеансаИнформационнойБазы());
ФильтрЖурнала.Вставить("Начало", ирКэш.ТекущийСеансЛкс().НачалоСеанса);
ТаблицаЖурнала = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(ТаблицаЖурнала, ФильтрЖурнала,,, 1);
ПеревестиКолонкиСистемнойТаблицыЛкс(ТаблицаЖурнала);
Если ТаблицаЖурнала.Количество() > 0 Тогда
ПоследняяСтрока = ТаблицаЖурнала[ТаблицаЖурнала.Количество() - 1];
ФильтрЖурнала.Вставить("Транзакция", ПоследняяСтрока.Транзакция);
ФильтрЖурнала.Вставить("Конец", ПоследняяСтрока.Дата);
ФильтрЖурнала.Удалить("СтатусТранзакции");
СтруктураПараметров.Вставить("Транзакция", ФильтрЖурнала);
КонецЕсли;
КонецЕсли;
Успех = Ложь;
ДоступноФоновоеЗадание = Не (Истина
И ТранзакцияАктивна()
И ирКэш.ЛиФайловаяБазаЛкс()
// В файловой базе даже 8.3 не получится, т.к. там не истинной параллельности
//И (Ложь
// Или РежимСовместимостиМеньше8_3_4Лкс()
// Или ирКэш.ЭтоФоновоеЗаданиеЛкс())
);
Если Истина
И Метаданные.Справочники.Найти("ирОбъектыДляОтладки") <> Неопределено
И ДоступноФоновоеЗадание
Тогда
Попытка
Если ФорматВнутр Тогда
ХранимоеЗначение = ЗначениеВСтрокуВнутр(СтруктураПараметров);
Иначе
ХранимоеЗначение = ОбъектВСтрокуXMLЛкс(СтруктураПараметров);
КонецЕсли;
СтруктураОбъекта = ОбъектБДПоКлючуЛкс(Метаданные.Справочники.ирОбъектыДляОтладки.ПолноеИмя());
ОбъектДляОтладки = СтруктураОбъекта.Данные; // СправочникОбъект.ирОбъектыДляОтладки
ОбъектДляОтладки.Наименование = Наименование;
ОбъектДляОтладки.XML = ХранимоеЗначение;
выхОбъектДляОтладки = ЗаписатьОбъектДляОтладкиЛкс(СтруктураОбъекта.Методы);
Успех = Истина;
Исключение
Результат = "Ошибка записи объекта для отладки: " + ОписаниеОшибки();
КонецПопытки;
Если Успех Тогда
Результат = "Скопируйте эту строку и используйте команду ""Открыть объект для отладки"". Данные помещены в справочник ""Объекты для отладки""."
+ " Объект """ + ОбъектДляОтладки + """(" + выхОбъектДляОтладки.УникальныйИдентификатор() + ")";
КонецЕсли;
Иначе
//выхОбъектДляОтладки = ПоместитьВоВременноеХранилище(ХранимоеЗначение, Новый УникальныйИдентификатор);
//Результат = "Данные помещены в хранилище ДО КОНЦА СЕАНСА. Скопируйте эту строку и используйте команду ""Открыть объект для отладки""."
//+ " Адрес """ + выхОбъектДляОтладки + """";
КаталогОбъектовДляОтладки = КаталогОбъектовДляОтладкиЛкс();
Успех = Ложь;
Если ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда
РасширениеФайловДляОтладки = РасширениеФайловДляОтладкиЛкс();
Наименование = ИдентификаторИзПредставленияЛкс(Наименование);
ИмяФайла = КаталогОбъектовДляОтладки + РазделительПутиКФайлуЛкс() + Наименование + "." + РасширениеФайловДляОтладки;
ФайлОбъектаДляОтладки = Новый Файл(ИмяФайла);
Попытка
Если ФорматВнутр Тогда
Успех = ЗначениеВФайл(ФайлОбъектаДляОтладки.ПолноеИмя, СтруктураПараметров);
Иначе
ОбъектВСтрокуXMLЛкс(СтруктураПараметров, , ФайлОбъектаДляОтладки.ПолноеИмя);
Успех = Истина;
КонецЕсли;
Исключение
СообщитьЛкс("Ошибка сохранения файла для отладки: " + ОписаниеОшибки());
КонецПопытки;
Если Успех Тогда
выхОбъектДляОтладки = ФайлОбъектаДляОтладки.ПолноеИмя;
Результат = "Скопируйте эту строку и используйте команду ""Открыть объект для отладки"". Данные помещены в файл."
+ " Файл """ + выхОбъектДляОтладки + """";
КонецЕсли;
Иначе
ТекстРекомендации = "Рекомендуется в общих настройках инструментов задать каталог объектов для отладки.";
СообщитьЛкс(ТекстРекомендации);
КонецЕсли;
Если Не Успех Тогда
Если ТранзакцияАктивна() И Не ДоступноФоновоеЗадание Тогда
Попытка
ОтменитьТранзакцию();
Успех = Истина;
Исключение
// Системная транзакция записи объекта
КонецПопытки;
Если Не Успех Тогда
Результат = "Невозможно отменить транзакцию записи объекта для сохранения объекта для отладки в общие настройки. " + ТекстРекомендации;
Иначе
СообщитьЛкс("Транзакция была отменена для сохранения объекта для отладки в общие настройки");
КонецЕсли;
Иначе
Успех = Истина;
КонецЕсли;
Если Успех Тогда
Успех = Ложь;
Попытка
КлючНастройки = ЗаписатьОбъектДляОтладкиЛкс(СтруктураПараметров);
Успех = Истина;
Исключение
Результат = "Ошибка записи объекта для отладки: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
Если Успех Тогда
Результат = РезультатСохраненияОбъектаОтложеннойОтладкиВНастройкуЛкс(КлючНастройки);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Истина
И СтруктураПараметров.Свойство("СериализацияФабрикой")
И СтруктураПараметров.СериализацияФабрикой = "Внутр"
Тогда
Результат = Результат + ". Применена ЗначениеВСтрокуВнутр() и получено " + СтрДлина(СтруктураПараметров.Объект) + " символов.";
КонецЕсли;
Возврат Результат;
КонецФункции
// Параметры:
// КлючНастройки - Ссылка, Строка
Функция РезультатСохраненияОбъектаОтложеннойОтладкиВНастройкуЛкс(Знач КлючНастройки = "") Экспорт
Если Не ЗначениеЗаполнено(КлючНастройки) Тогда
КлючНастройки = ИмяНастройкиХраненияОбъектаОтложеннойОтладкиЛкс();
КонецЕсли;
Результат = "Скопируйте эту строку и используйте команду ""Открыть объект для отладки"". Данные помещены в настройку """ + КлючНастройки + """."
+ " Пользователь """ + ИмяПользователя() + """";
Возврат Результат;
КонецФункции
// Получает имена создаваемых временных таблиц из текста запроса.
// Это неточный метод, основанный на регулярных выражениях.
//
// Параметры:
// ТекстПакета - Строка -
// ТолькоТребующиеУничтоженияНаВходе - Булево -
// ТекстыЗапросовПакета - Массив - для ускорения
// ВместеСУничтожениями - Булево - добавлять имена уничтожаемых временных таблиц в виде "-<ИмяУничтоженнойТаблицы>"
//
// Возвращаемое значение:
// Строка, Неопределено - .
//
Функция СоздаваемыеВременныеТаблицыПакетаЗапросовЛкс(Знач ТекстПакетаИлиМассивТекстовЗапросов, Знач ТолькоТребующиеУничтоженияНаВходе = Ложь, Знач ВместеСУничтожениями = Ложь,
Знач ВместеСДополнениями = Ложь, Знач БыстрыйАнализ = Ложь) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
Результат = мПлатформа.СоздаваемыеВременныеТаблицыПакетаЗапросов(ТекстПакетаИлиМассивТекстовЗапросов, ТолькоТребующиеУничтоженияНаВходе, ВместеСУничтожениями, ВместеСДополнениями, БыстрыйАнализ);
Возврат Результат;
КонецФункции
Функция ВосстановитьМенеджерВременныхТаблицЛкс(Знач СтруктураВременныеТаблицы, выхИменаВременныхТаблиц = "", Знач МенеджерВременныхТаблиц = Неопределено) Экспорт
Если МенеджерВременныхТаблиц = Неопределено Тогда
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
выхИменаВременныхТаблиц = "";
СостояниеЛкс("Подготовка временных таблиц");
Для Каждого КлючИЗначение Из СтруктураВременныеТаблицы Цикл
Если выхИменаВременныхТаблиц <> "" Тогда
выхИменаВременныхТаблиц = выхИменаВременныхТаблиц + ",";
КонецЕсли;
ИмяТаблицы = КлючИЗначение.Ключ;
ТаблицаЗначений = КлючИЗначение.Значение;
выхИменаВременныхТаблиц = выхИменаВременныхТаблиц + ИмяТаблицы;
Запрос.Текст = "УНИЧТОЖИТЬ " + ИмяТаблицы;
Попытка
Запрос.Выполнить();
Исключение
КонецПопытки;
СоздатьВременнуюТаблицуЗапросаИзТаблицыЗначенийЛкс(Запрос, ТаблицаЗначений, ИмяТаблицы);
КонецЦикла;
СостояниеЛкс("");
Возврат Запрос.МенеджерВременныхТаблиц;
КонецФункции
Процедура СоздатьВременнуюТаблицуЗапросаИзТаблицыЗначенийЛкс(Запрос, ТаблицаЗначений, Знач ИмяТаблицы) Экспорт
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ТаблицаЗначений = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаЗначений, Истина,,,,,,, Истина);
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
Запрос = Новый Запрос;
#КонецЕсли
ТекстВыбораПолей = "";
СуффиксВыборПодколонки = "_ВыборПодколонки" + СуффиксСлужебногоСвойстваЛкс();
СуффиксПодколонкиБезНеудобногоТипа = "_Значение" + СуффиксСлужебногоСвойстваЛкс();
СуффиксПодколонкиДляНеудобногоТипа = "_ЗначениеДляТипа" + СуффиксСлужебногоСвойстваЛкс();
ЕстьКолонкиСНеудобнымТипом = Ложь;
НеподдерживаемыеКолонки = Новый Массив;
НачальноеЧислоКолонок = ТаблицаЗначений.Колонки.Количество();
Для ИндексКолонки = 0 По НачальноеЧислоКолонок - 1 Цикл
Колонка = ТаблицаЗначений.Колонки[НачальноеЧислоКолонок - ИндексКолонки - 1]; // Состав коллекции расширяется, но нам нужно обойти только начальный состав
Если Ложь
//Или Колонка.ТипЗначения.СодержитТип(Тип("Тип"))
//Или Колонка.ТипЗначения.СодержитТип(Тип("МоментВремени"))
Или Колонка.ТипЗначения.СодержитТип(Тип("ОписаниеТипов"))
Или (Истина
И ирКэш.НомерРежимаСовместимостиЛкс() < 803012
И Колонка.ТипЗначения.СодержитТип(Тип("УникальныйИдентификатор")))
Тогда
НеподдерживаемыеКолонки.Добавить(Колонка.Имя);
ТекстВыбораПолей = ТекстВыбораПолей + ",
| НЕОПРЕДЕЛЕНО КАК " + Колонка.Имя;
Иначе
Если Колонка.ТипЗначения.Типы().Количество() = 0 Тогда
ТекстВыбораПолей = ТекстВыбораПолей + ",
| НЕОПРЕДЕЛЕНО КАК " + Колонка.Имя;
ЕстьКолонкиСНеудобнымТипом = Истина;
ИначеЕсли Ложь
Или Колонка.ТипЗначения.СодержитТип(Тип("Тип"))
Или Колонка.ТипЗначения.СодержитТип(Тип("МоментВремени"))
Или Колонка.ТипЗначения.СодержитТип(Тип("Null"))
Тогда
ЕстьКолонкиСНеудобнымТипом = Истина;
ОписаниеТиповДляНеудобногоТипа = Неопределено;
Если Колонка.ТипЗначения.СодержитТип(Тип("МоментВремени")) Тогда
ИмяНеудобногоТипа = "МоментВремени";
ИмяКолонкиЗначениеДляНеудобногоТипа = Колонка.Имя + СуффиксПодколонкиДляНеудобногоТипа;
ИмяКолонкиЗначениеДляНеудобногоТипаДата = Колонка.Имя + "_Дата" + СуффиксПодколонкиДляНеудобногоТипа;
ВыражениеНеудобногоТипа = "
| ВЫБОР КОГДА Т." + ИмяКолонкиЗначениеДляНеудобногоТипа + ".Дата <> Т." + ИмяКолонкиЗначениеДляНеудобногоТипаДата + "
| ТОГДА 1/0
| ИНАЧЕ Т." + ИмяКолонкиЗначениеДляНеудобногоТипа + ".МоментВремени
| КОНЕЦ";
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиЗначениеДляНеудобногоТипаДата, Новый ОписаниеТипов("Дата"));
Если ТаблицаЗначений.Количество() = 0 Тогда
ТипыДокументов = Новый Массив;
ТипыДокументов.Добавить(Документы.ТипВсеСсылки().Типы()[0]);
ОписаниеТиповДляНеудобногоТипа = Новый ОписаниеТипов(ТипыДокументов);
КонецЕсли;
ИначеЕсли Колонка.ТипЗначения.СодержитТип(Тип("Тип")) Тогда
ИмяНеудобногоТипа = "Тип";
ИмяКолонкиЗначениеДляНеудобногоТипа = Колонка.Имя + СуффиксПодколонкиДляНеудобногоТипа;
ВыражениеНеудобногоТипа = "ТипЗначения(Т." + ИмяКолонкиЗначениеДляНеудобногоТипа + ")";
ИначеЕсли Колонка.ТипЗначения.СодержитТип(Тип("Null")) Тогда
ИмяНеудобногоТипа = "Null";
ИмяКолонкиЗначениеДляНеудобногоТипа = Колонка.Имя + СуффиксПодколонкиДляНеудобногоТипа;
ВыражениеНеудобногоТипа = "NULL";
Иначе
ВызватьИсключение "Неподдерживаемый тип";
КонецЕсли;
ИмяКолонкиВыбораПодколонки = Колонка.Имя + СуффиксВыборПодколонки;
ИмяКолонкиБезНеудобногоТипа = Колонка.Имя + СуффиксПодколонкиБезНеудобногоТипа;
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиВыбораПодколонки, Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(Макс(10, СтрДлина(ИмяНеудобногоТипа)))));
ОписаниеТиповКолонкиБезТипов = Новый ОписаниеТипов(Колонка.ТипЗначения,, ИмяНеудобногоТипа + ", Null");
Если ОписаниеТиповКолонкиБезТипов.Типы().Количество() > 0 Тогда
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиБезНеудобногоТипа, ОписаниеТиповКолонкиБезТипов);
ВыражениеБезНеудобногоТипа = "Т." + ИмяКолонкиБезНеудобногоТипа;
Иначе
ВыражениеБезНеудобногоТипа = "НЕОПРЕДЕЛЕНО";
КонецЕсли;
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиЗначениеДляНеудобногоТипа, ОписаниеТиповДляНеудобногоТипа);
ТекстВыбораПолей = ТекстВыбораПолей + ",
| ВЫБОР КОГДА Т." + ИмяКолонкиВыбораПодколонки + " = """ + ИмяНеудобногоТипа + """
| ТОГДА " + ВыражениеНеудобногоТипа + "
| КОГДА Т." + ИмяКолонкиВыбораПодколонки + " = ""Null""
| ТОГДА NULL
| ИНАЧЕ " + ВыражениеБезНеудобногоТипа + "
| КОНЕЦ КАК " + Колонка.Имя;
Для Каждого СтрокаТаблицы Из ТаблицаЗначений Цикл
ЗначениеКолонки = СтрокаТаблицы[Колонка.Имя];
Если ТипЗнч(ЗначениеКолонки) = Тип(ИмяНеудобногоТипа) Тогда
Если ТипЗнч(ЗначениеКолонки) = Тип("МоментВремени") Тогда
СтрокаТаблицы[ИмяКолонкиЗначениеДляНеудобногоТипаДата] = ЗначениеКолонки.Дата;
ЗначениеКолонки = ЗначениеКолонки.Ссылка;
ИначеЕсли ТипЗнч(ЗначениеКолонки) = Тип("Тип") Тогда
Типы = Новый Массив;
Типы.Добавить(ЗначениеКолонки);
ОписаниеТипов = Новый ОписаниеТипов(Типы);
ЗначениеКолонки = ОписаниеТипов.ПривестиЗначение();
ИначеЕсли ТипЗнч(ЗначениеКолонки) = Тип("NULL") Тогда
ЗначениеКолонки = Неопределено;
Иначе
ВызватьИсключение "Неподдерживаемый тип";
КонецЕсли;
СтрокаТаблицы[ИмяКолонкиВыбораПодколонки] = ИмяНеудобногоТипа;
СтрокаТаблицы[ИмяКолонкиЗначениеДляНеудобногоТипа] = ЗначениеКолонки;
ИначеЕсли ЗначениеКолонки = Null Тогда
// Моноколонку с типом NULL тоже невозможно поместить во временную таблицу из таблицы-параметра
СтрокаТаблицы[ИмяКолонкиВыбораПодколонки] = "Null";
Иначе
СтрокаТаблицы[ИмяКолонкиБезНеудобногоТипа] = ЗначениеКолонки;
КонецЕсли;
КонецЦикла;
ТаблицаЗначений.Колонки.Удалить(Колонка.Имя);
Иначе
ТекстВыбораПолей = ТекстВыбораПолей + ",
| Т." + Колонка.Имя + " КАК " + Колонка.Имя;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ПоддерживаемыеКолонки = ирОбщий.СтрСоединитьЛкс(ВыгрузитьСвойствоЛкс(ТаблицаЗначений.Колонки));
Если Не ЗначениеЗаполнено(ПоддерживаемыеКолонки) Тогда
ПоддерживаемыеКолонки = "0";
КонецЕсли;
Если ЕстьКолонкиСНеудобнымТипом Тогда
ТаблицаЗначений = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаЗначений, Истина);
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ИмяСлужебнойТаблицы = "_Т" + СуффиксСлужебногоСвойстваЛкс();
ТекстЗапросаПодготовки = "
|ВЫБРАТЬ " + ПоддерживаемыеКолонки + " ПОМЕСТИТЬ " + ИмяСлужебнойТаблицы + " ИЗ &" + ИмяТаблицы + " КАК Т;
|ВЫБРАТЬ " + Сред(ТекстВыбораПолей, 2) + "
|ПОМЕСТИТЬ " + ИмяТаблицы + " ИЗ " + ИмяСлужебнойТаблицы + " КАК Т;
|УНИЧТОЖИТЬ " + ИмяСлужебнойТаблицы + "";
Иначе
ТекстЗапросаПодготовки = "
|ВЫБРАТЬ " + Сред(ТекстВыбораПолей, 2) + "
|ПОМЕСТИТЬ " + ИмяТаблицы + " ИЗ &" + ИмяТаблицы + " КАК Т";
КонецЕсли;
Если НеподдерживаемыеКолонки.Количество() > 0 Тогда
ТаблицаЗначений = ТаблицаЗначений.Скопировать(, ПоддерживаемыеКолонки);
КонецЕсли;
Запрос.Параметры.Вставить(ИмяТаблицы, ТаблицаЗначений);
Если НеподдерживаемыеКолонки.Количество() Тогда
// https://partners.v8.1c.ru/forum/t/1570237/m/1570237
СообщитьЛкс(СтрШаблонИменЛкс("Невозможно восстановить колонки таблицы %1 из-за недопустимых типов (МоментВремени, УникальныйИдентификатор, Тип, ОписаниеТипов): %2",,
ИмяТаблицы, 2, ирОбщий.СтрСоединитьЛкс(НеподдерживаемыеКолонки)), СтатусСообщения.Внимание);
КонецЕсли;
Если ЗначениеЗаполнено(ТекстЗапросаПодготовки) Тогда
Запрос.Текст = ТекстЗапросаПодготовки;
Попытка
Запрос.Выполнить();
Исключение
Причина = ОписаниеОшибки();
Если Ложь
Или СтрНайтиЛкс(Причина, "деление на ноль",,,, Ложь)
Или СтрНайтиЛкс(Причина, "division by zero",,,, Ложь)
Тогда
Причина = "Присутствует момент времени, дата в котором не совпадает с датой документа";
КонецЕсли;
СообщитьЛкс(СтрШаблонИменЛкс("Ошибка восстановления временной таблицы %1: " + Причина,, ИмяТаблицы), СтатусСообщения.Внимание);
КонецПопытки;
КонецЕсли;
Запрос.Параметры.Удалить(ИмяТаблицы);
КонецПроцедуры
// Подставляет параметры в строку. Максимально возможное число параметров - 9.
// Параметры в строке задаются как %<номер параметра>. Нумерация параметров начинается с единицы.
//
// Параметры:
// СтрокаПодстановки - Строка - шаблон строки с параметрами (вхождениями вида "%ИмяПараметра");
// Параметр - Строка - подставляемый параметр.
//
// Возвращаемое значение:
// Строка - текстовая строка с подставленными параметрами.
//
// Пример:
// ПодставитьПараметрыВСтроку(НСтр("ru='%1 пошел в %2'"), "Вася", "Зоопарк") = "Вася пошел в Зоопарк".
//
Функция ПодставитьПараметрыВСтрокуЛкс(Знач СтрокаПодстановки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено,
Знач Параметр7 = Неопределено, Знач Параметр8 = Неопределено, Знач Параметр9 = Неопределено) Экспорт
ИспользоватьАльтернативныйАлгоритм = Ложь
Или Найти(Параметр1, "%")
Или Найти(Параметр2, "%")
Или Найти(Параметр3, "%")
Или Найти(Параметр4, "%")
Или Найти(Параметр5, "%")
Или Найти(Параметр6, "%")
Или Найти(Параметр7, "%")
Или Найти(Параметр8, "%")
Или Найти(Параметр9, "%");
Если ИспользоватьАльтернативныйАлгоритм Тогда
СтрокаПодстановки = ПодставитьПараметрыВСтрокуАльтернативныйАлгоритм(СтрокаПодстановки, Параметр1,
Параметр2, Параметр3, Параметр4, Параметр5, Параметр6, Параметр7, Параметр8, Параметр9);
Иначе
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%1", Параметр1);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%2", Параметр2);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%3", Параметр3);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%4", Параметр4);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%5", Параметр5);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%6", Параметр6);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%7", Параметр7);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%8", Параметр8);
СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%9", Параметр9);
КонецЕсли;
Возврат СтрокаПодстановки;
КонецФункции
// Вставляет параметры в строку, учитывая, что в параметрах могут использоваться подстановочные слова %1, %2 и т.д.
Функция ПодставитьПараметрыВСтрокуАльтернативныйАлгоритм(Знач СтрокаПодстановки,
Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено,
Знач Параметр4 = Неопределено, Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено,
Знач Параметр7 = Неопределено, Знач Параметр8 = Неопределено, Знач Параметр9 = Неопределено)
Результат = "";
Позиция = Найти(СтрокаПодстановки, "%");
Пока Позиция > 0 Цикл
Результат = Результат + Лев(СтрокаПодстановки, Позиция - 1);
СимволПослеПроцента = Сред(СтрокаПодстановки, Позиция + 1, 1);
ПодставляемыйПараметр = "";
Если СимволПослеПроцента = "1" Тогда
ПодставляемыйПараметр = Параметр1;
ИначеЕсли СимволПослеПроцента = "2" Тогда
ПодставляемыйПараметр = Параметр2;
ИначеЕсли СимволПослеПроцента = "3" Тогда
ПодставляемыйПараметр = Параметр3;
ИначеЕсли СимволПослеПроцента = "4" Тогда
ПодставляемыйПараметр = Параметр4;
ИначеЕсли СимволПослеПроцента = "5" Тогда
ПодставляемыйПараметр = Параметр5;
ИначеЕсли СимволПослеПроцента = "6" Тогда
ПодставляемыйПараметр = Параметр6;
ИначеЕсли СимволПослеПроцента = "7" Тогда
ПодставляемыйПараметр = Параметр7
ИначеЕсли СимволПослеПроцента = "8" Тогда
ПодставляемыйПараметр = Параметр8;
ИначеЕсли СимволПослеПроцента = "9" Тогда
ПодставляемыйПараметр = Параметр9;
КонецЕсли;
Если ПодставляемыйПараметр = "" Тогда
Результат = Результат + "%";
СтрокаПодстановки = Сред(СтрокаПодстановки, Позиция + 1);
Иначе
Результат = Результат + ПодставляемыйПараметр;
СтрокаПодстановки = Сред(СтрокаПодстановки, Позиция + 2);
КонецЕсли;
Позиция = Найти(СтрокаПодстановки, "%");
КонецЦикла;
Результат = Результат + СтрокаПодстановки;
Возврат Результат;
КонецФункции
Функция КаталогОбъектовДляОтладкиЛкс(ДляСервера = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ирПортативный = Обработки.ирПортативный.Создать();
#КонецЕсли
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
КаталогОбъектовДляОтладки = ирПортативный.КаталогОбъектовДляОтладкиЛкс();
Иначе
//ИмяФайла = ПолучитьИмяВременногоФайла(РасширениеФайловДляОтладки);
КаталогОбъектовДляОтладки = ВосстановитьЗначениеЛкс("КаталогОбъектовДляОтладки");
#Если Клиент Тогда
Если Не ДляСервера И Не ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда
КаталогОбъектовДляОтладки = ирКэш.Получить().КаталогФайловогоКэша;
КонецЕсли;
#КонецЕсли
Если ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда
ИмяКаталогаБазы = ИдентификаторИзПредставленияЛкс(СтрокаСоединенияИнформационнойБазы());
КаталогОбъектовДляОтладки = КаталогОбъектовДляОтладки + "\" + ИмяКаталогаБазы + "\";
КаталогОбъектовДляОтладки = СтрЗаменить(КаталогОбъектовДляОтладки, "\", РазделительПутиКФайлуЛкс());
Каталог = Новый Файл(КаталогОбъектовДляОтладки);
Если Не Каталог.Существует() Тогда
Попытка
СоздатьКаталог(КаталогОбъектовДляОтладки);
Исключение
СообщитьЛкс("Ошибка создания каталога объектов для отладки: " + ОписаниеОшибки());
КаталогОбъектовДляОтладки = Неопределено;
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат КаталогОбъектовДляОтладки;
КонецФункции
Функция ИмяПродуктаЛкс() Экспорт
Возврат "ИнструментыРазработчикаTormozit";
КонецФункции
Функция ПреобразоватьПараметрыЗапросаДляСериализацииЛкс(Параметры) Экспорт
// Антибаг платформы 8.2.18. Некорректная сериализация моментов времени http://partners.v8.1c.ru/forum/thread.jsp?id=1159525#1159525
//СтруктураЗапроса.Параметры = КопияОбъектаЛкс(Объект.Параметры);
Структура = Новый Структура();
ОбъектыДанных = Новый Массив;
Для Каждого КлючИЗначение Из Параметры Цикл
ЗначениеПараметра = ПолучитьСовместимоеЗначениеПараметраЗапросаЛкс(КлючИЗначение.Значение, КлючИЗначение.Ключ);
Структура.Вставить(КлючИЗначение.Ключ, ЗначениеВСтрокуВнутр(ЗначениеПараметра));
Если Истина
И ТранзакцияАктивна()
И ЛиСсылкаНаОбъектБДЛкс(ЗначениеПараметра)
И ЗначениеЗаполнено(ЗначениеПараметра)
Тогда
// ЗначениеПараметра = Документы.РеализацияТоваровУслуг.ПустаяСсылка(); // назначение типа
ОбъектДанных = ЗначениеПараметра.ПолучитьОбъект();
Если ОбъектДанных <> Неопределено Тогда
ОбъектыДанных.Добавить(СнимокОбъектаЛкс(ОбъектДанных));
КонецЕсли;
Если ЛиКорневойТипДокументаЛкс(ПервыйФрагментЛкс(ЗначениеПараметра.Метаданные().ПолноеИмя())) Тогда
ТаблицыДвижений = ПрочитатьДвиженияДокументаПакетноЛкс(ЗначениеПараметра);
Для Каждого КлючИЗначение Из ТаблицыДвижений Цикл
ТаблицаНабора = КлючИЗначение.Значение;
Если ТаблицаНабора.Количество() > 10000 Тогда
Продолжить;
КонецЕсли;
ИмяТаблицыБДРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(КлючИЗначение.Ключ);
ИмяПоляОтбора = ирОбщий.ИмяПоляОтбораПодчиненногоНабораЗаписейЛкс(ИмяТаблицыБДРегистра);
//Набор = Новый (ИмяТипаИзПолногоИмениМДЛкс(КлючИЗначение.Ключ, "НаборЗаписей")); // РегистрНакопленияНаборЗаписей.ЗатратыОбороты
//Набор.Отбор[ИмяПоляОтбора].Установить(ЗначениеПараметра);
//Набор.Загрузить(ТаблицаНабора);
СтруктураНабора = ирОбщий.ОбъектБДПоКлючуЛкс(ИмяТаблицыБДРегистра,,, Ложь); // см. ирОбщий.докОбъектБДПоКлючуРегистр
СтруктураНабора.Методы.Отбор[ИмяПоляОтбора].Установить(ЗначениеПараметра);
СтруктураНабора.Методы.Загрузить(ТаблицаНабора);
ОбъектыДанных.Добавить(СнимокОбъектаЛкс(СтруктураНабора.Методы));
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ОбъектыДанных.Количество() > 0 Тогда
Структура.Вставить("_ОбъектыДанныхТранзакции", ЗначениеВСтрокуВнутр(ОбъектыДанных));
КонецЕсли;
Возврат Структура;
КонецФункции
Функция СкопироватьЗапросЛкс(ЗапросИсточник, ЗапросПриемник = Неопределено) Экспорт
Если ЗапросПриемник = Неопределено Тогда
ЗапросПриемник = Новый Запрос;
КонецЕсли;
ЗапросПриемник.Текст = ЗапросИсточник.Текст;
СкопироватьКоллекциюЛкс(ЗапросИсточник.Параметры, ЗапросПриемник.Параметры);
Возврат ЗапросПриемник;
КонецФункции
Функция ПолучитьТекстЗапросаВсехТиповСсылокЛкс(ИмяВременнойТаблицы = "ВсеТипыСсылок", Знач ОписаниеТипов = Неопределено) Экспорт
Если ОписаниеТипов = Неопределено Тогда
ОписаниеТипов = ОписаниеТиповВсеСсылкиЛкс();
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ОписаниеВсехТипов = Новый ОписаниеТипов;
#КонецЕсли
ТекстТаблицыТипов = "";
Для Каждого Тип Из ОписаниеТипов.Типы() Цикл
ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя();
НоваяСтрока = "ВЫБРАТЬ ТИП(" + ПолноеИмя + ") КАК Тип, """ + ПолноеИмя + """ КАК Имя" + Символы.ПС;
Если ТекстТаблицыТипов <> "" Тогда
ТекстТаблицыТипов = ТекстТаблицыТипов + "ОБЪЕДИНИТЬ ВСЕ " + Символы.ПС;
Иначе
Если ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
НоваяСтрока = НоваяСтрока + "ПОМЕСТИТЬ " + ИмяВременнойТаблицы + Символы.ПС;
КонецЕсли;
КонецЕсли;
ТекстТаблицыТипов = ТекстТаблицыТипов + НоваяСтрока;
КонецЦикла;
//ТекстТаблицыТипов = ТекстТаблицыТипов + " ИНДЕКСИРОВАТЬ ПО Тип"; // По такому типу поля нельзя индексировать
Возврат ТекстТаблицыТипов;
КонецФункции
Функция ТекстЗапросаДатыЗаПериодЛкс(ИмяВременнойТаблицы = "ДатыДиапазона") Экспорт
Текст = ТекстЗапросаЧислаШаблонЛкс(ИмяВременнойТаблицы, "ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, &Значение)") + " <= РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)";
Возврат Текст;
КонецФункции
Функция ТекстЗапросаЦелыеЧислаЛкс(ИмяВременнойТаблицы = "ЦелыеЧисла") Экспорт
Текст = ТекстЗапросаЧислаШаблонЛкс(ИмяВременнойТаблицы) + " <= &МаксЧисло";
Возврат Текст;
КонецФункции
Функция ТекстЗапросаЧислаШаблонЛкс(ИмяВременнойТаблицы, ВыбранноеВыражение = "&Значение")
БазовоеВыражение = "aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a";
Текст = СтрЗаменитьЛкс("ВЫБРАТЬ &Подстановка КАК Значение // Максимальное точек в диапазоне = 10000", "&Подстановка", СтрЗаменитьЛкс(ВыбранноеВыражение, "&Значение", БазовоеВыражение));
Если ЗначениеЗаполнено(ИмяВременнойТаблицы) Тогда
Текст = Текст + Символы.ПС + "ПОМЕСТИТЬ " + ИмяВременнойТаблицы;
КонецЕсли;
Текст = Текст + "
|ИЗ
| (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК aa
| СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК bb ПО ИСТИНА
| СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК cc ПО ИСТИНА
| СОЕДИНЕНИЕ (ВЫБРАТЬ 0 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 1 ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6 ОБЪЕДИНИТЬ ВЫБРАТЬ 7 ОБЪЕДИНИТЬ ВЫБРАТЬ 8 ОБЪЕДИНИТЬ ВЫБРАТЬ 9) КАК dd ПО ИСТИНА
|ГДЕ
| aa.a * 1000 + bb.a * 100 + cc.a * 10 + dd.a";
Возврат Текст;
КонецФункции
Функция ПолучитьСобственноеВнешнееСоединениеЛкс(ИнициализироватьИнтерфейсИР = Ложь, выхИнтерфейсИР = Неопределено) Экспорт
ИмяПользователяВнешнегоСоединения = "";
ПарольПользователяВнешнегоСоединения = "";
Если ПользователиИнформационнойБазы.ПолучитьПользователей().Количество() > 0 Тогда
ИмяПользователяВнешнегоСоединения = ИмяПользователя() + "_ВнешнееСоединение";
Попытка
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователяВнешнегоСоединения);
Исключение
СообщитьЛкс("Не удалось выполнить поиск служебного пользователя: " + ОписаниеОшибки());
// Разделенная база в неразделенном сеансе
Возврат Неопределено;
КонецПопытки;
Если ПользовательИБ = Неопределено Тогда
ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
ПользовательИБ.Имя = ИмяПользователяВнешнегоСоединения;
ПользовательИБ.ПолноеИмя = ИмяПользователяВнешнегоСоединения;
СообщитьЛкс(СтрШаблонИменЛкс("Создан служебный пользователь ИБ с именем %1",, ИмяПользователяВнешнегоСоединения));
КонецЕсли;
ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
ЗаполнитьЗначенияСвойств(ПользовательИБ, ТекущийПользовательИБ,, "Имя, ПолноеИмя");
ПользовательИБ.Роли.Очистить();
Для Каждого Роль Из ТекущийПользовательИБ.Роли Цикл
ПользовательИБ.Роли.Добавить(Роль);
КонецЦикла;
ПарольПользователяВнешнегоСоединения = "" + Новый УникальныйИдентификатор;
ПользовательИБ.ПоказыватьВСпискеВыбора = Ложь;
ПользовательИБ.АутентификацияОС = Ложь;
ПользовательИБ.АутентификацияСтандартная = Истина;
ПользовательИБ.Пароль = ПарольПользователяВнешнегоСоединения;
ПользовательИБ.Записать();
КонецЕсли;
Результат = ЗапуститьСеансПодПользователемЛкс(ИмяПользователяВнешнегоСоединения, ПарольПользователяВнешнегоСоединения, "ComConnector");
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
выхИнтерфейсИР = Результат.ВнешниеОбработки.Создать(ирПортативный.ИспользуемоеИмяФайла, Ложь);
Иначе
выхИнтерфейсИР = Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
// Ключи формируются только из данных расшифровки ячеек.
//
// Параметры:
// ТабличныйДокумент - - ТабличныйДокумент
// ДанныеРасшифровки - - ДанныеРасшифровкиКомпоновкиДанных
// Поля - - Строка(0,П), Массив - Если строка, то через запятую перечисленные имена полей.
// Область - ВыделенныеОбластиТабличногоДокумента, Массив, ОбластьЯчеекТабличногоДокумента - Если не указано, используются выделенные области
// выхКлючТекущейСтроки - СтрокаТаблицыЗначений - ключ выделенной области или первый ключ среди найденных
//
// Возвращаемое значение:
// - ТаблицаЗначений - таблица ключей
//
Функция ТаблицаКлючейИзТабличногоДокументаЛкс(Знач ТабличныйДокумент, Знач ДанныеРасшифровки = Неопределено, Знач Поля = "", Знач Область = Неопределено,
Знач выхКлючТекущейСтроки = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
#КонецЕсли
Если Истина
И ТипЗнч(Поля) = Тип("Строка")
И Не ПустаяСтрока(Поля)
Тогда
МассивИменПолей = СтрРазделитьЛкс(Поля, ",", Истина);
ИначеЕсли ТипЗнч(Поля) = Тип("Массив") Тогда
МассивИменПолей = Поля;
Иначе
МассивИменПолей = Новый Массив;
КонецЕсли;
ТаблицаРезультата = Неопределено;
МассивСсылок = Новый Массив;
АвтоПоля = МассивИменПолей.Количество() = 0;
Если ТипЗнч(Область) = Тип("Неопределено") Тогда
КоллекцияОбластей = ТабличныйДокумент.ВыделенныеОбласти;
ИначеЕсли ТипЗнч(Область) = Тип("Массив") Тогда
КоллекцияОбластей = Область;
ИначеЕсли ТипЗнч(Область) = Тип("ОбластьЯчеекТабличногоДокумента") Тогда
КоллекцияОбластей = Новый Массив;
КоллекцияОбластей.Добавить(Область);
Иначе
ВызватьИсключение "Некорректный тип параметра ""Область""";
КонецЕсли;
Если ТипЗнч(ДанныеРасшифровки) = Тип("ДанныеРасшифровкиКомпоновкиДанных") Тогда
ЭлементыРасшифровки = ДанныеРасшифровки.Элементы;
КонецЕсли;
НачальноеКоличество = КоллекцияОбластей.Количество();
ЛиПрервать = Ложь;
Для СчетчикВыделенныеОбласти = 1 По НачальноеКоличество Цикл
Область = КоллекцияОбластей[НачальноеКоличество - СчетчикВыделенныеОбласти];
Если ТипЗнч(Область) = Тип("РисунокТабличногоДокумента") Тогда
Продолжить;
КонецЕсли;
Если Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Колонки Тогда
Лево = Область.Лево;
Право = Область.Право;
Верх = 1;
Низ = ТабличныйДокумент.ВысотаТаблицы;
ИначеЕсли Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Строки Тогда
Лево = 1;
Право = ТабличныйДокумент.ШиринаТаблицы;
Верх = Область.Верх;
Низ = Область.Низ;
ИначеЕсли Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Прямоугольник Тогда
Лево = Область.Лево;
Право = Область.Право;
Верх = Область.Верх;
Низ = Область.Низ;
Иначе // Если Область.ТипОбласти = ТипОбластиЯчеекТабличногоДокумента.Таблица Тогда
Лево = 1;
Право = ТабличныйДокумент.ШиринаТаблицы;
Верх = 1;
Низ = ТабличныйДокумент.ВысотаТаблицы;
КонецЕсли;
Для НомерСтроки = Верх по Низ Цикл
КлючПолучен = Ложь;
СтруктураПолей = Новый Структура;
Для НомерКолонки = Лево по Право Цикл
ОбластьЯчейки = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки);
Если ОбластьЯчейки.Лево <> НомерКолонки Или ОбластьЯчейки.Верх <> НомерСтроки Тогда
// Данная ячейка принадлежит объединенным ячейкам и не является начальной ячейкой
Продолжить;
КонецЕсли;
Расшифровка = ОбластьЯчейки.Расшифровка;
Если ТипЗнч(Расшифровка) = Тип("ИдентификаторРасшифровкиКомпоновкиДанных") Тогда
Если ЭлементыРасшифровки = Неопределено Тогда
//СообщитьЛкс("В табличном документа найден идентификатор расшифровки компоновки, но не переданы данные расшифровки");
ЛиПрервать = Истина;
Прервать;
КонецЕсли;
ЭлементРасшифровкиПоля = ЭлементыРасшифровки[Расшифровка];
Если НомерСтроки = Верх Тогда
Если ТаблицаРезультата = Неопределено Тогда
ТаблицаРезультата = Новый ТаблицаЗначений;
Для Каждого ИмяПоля Из МассивИменПолей Цикл
ТаблицаРезультата.Колонки.Добавить(ИмяПоля);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КлючПолучен = ИзвлечьКлючИзЭлементаРасшифровкиКомпоновкиЛкс(ЭлементРасшифровкиПоля, МассивИменПолей, СтруктураПолей);
Если Истина
И КлючПолучен
И (Ложь
Или НомерКолонки = Право
Или Не АвтоПоля)
Тогда
Прервать;
КонецЕсли;
ИначеЕсли ЛиСсылкаНаОбъектБДЛкс(Расшифровка, Ложь) Тогда
СтруктураПолей.Вставить("Ссылка", Расшифровка);
КлючПолучен = Истина;
ИначеЕсли ТипЗнч(Расшифровка) = Тип("Структура") Тогда
СкопироватьКоллекциюЛкс(Расшифровка, СтруктураПолей);
КонецЕсли;
КонецЦикла;
Если ЛиПрервать Тогда
Прервать;
КонецЕсли;
Если КлючПолучен Тогда
Если ТаблицаРезультата = Неопределено Тогда
ТаблицаРезультата = Новый ТаблицаЗначений;
КонецЕсли;
Для Каждого КлючИЗначение Из СтруктураПолей Цикл
Если ТаблицаРезультата.Колонки.Найти(КлючИЗначение.Ключ) = Неопределено Тогда
ТаблицаРезультата.Колонки.Добавить(КлючИЗначение.Ключ);
КонецЕсли;
КонецЦикла;
Если Ложь
Или МассивИменПолей.Количество() = 0
Или ТаблицаРезультата.НайтиСтроки(СтруктураПолей).Количество() = 0
Тогда
СтрокаРезультата = ТаблицаРезультата.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаРезультата, СтруктураПолей);
Если ТабличныйДокумент.ТекущаяОбласть = Область Тогда
выхКлючТекущейСтроки = СтрокаРезультата;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ЛиПрервать Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Если ТаблицаРезультата = Неопределено Тогда
ТаблицаРезультата = Новый ТаблицаЗначений;
Иначе
Если выхКлючТекущейСтроки = Неопределено И ТаблицаРезультата.Количество() > 0 Тогда
выхКлючТекущейСтроки = ТаблицаРезультата[0];
КонецЕсли;
КонецЕсли;
Результат = ТаблицаРезультата;
Возврат Результат;
КонецФункции
// Извлекаемые значения помещаются в структуру
//
// Параметры:
// ЭлементРасшифровкиПоля - - ЭлементРасшифровкиКомпоновкиДанныхГруппировка, ЭлементРасшифровкиКомпоновкиДанныхПоля
// Поля - - Строка(0,П), Массив
// СтруктураПолей - Структура (если поля заданы), Соответствие
// выхСтруктураПолей - -
// ЛиКорневой - -
//
// Возвращаемое значение:
// - Булево - удалось ли собрать полный ключ
//
Функция ИзвлечьКлючИзЭлементаРасшифровкиКомпоновкиЛкс(Знач ЭлементРасшифровкиПоля, Знач Поля = "", выхСтруктураПолей = Неопределено, ЛиКорневой = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
Пустышка = Новый ДанныеРасшифровкиКомпоновкиДанных;
ЭлементРасшифровкиПоля = Пустышка.Элементы[0];
#КонецЕсли
Если выхСтруктураПолей = Неопределено Тогда
выхСтруктураПолей = Новый Структура;
КонецЕсли;
Если Истина
И ТипЗнч(Поля) = Тип("Строка")
И Не ПустаяСтрока(Поля)
Тогда
МассивИменПолей = СтрРазделитьЛкс(Поля, ",", Истина);
ИначеЕсли ТипЗнч(Поля) = Тип("Массив") Тогда
МассивИменПолей = Поля;
Иначе
МассивИменПолей = Новый Массив;
КонецЕсли;
Если МассивИменПолей.Количество() > 0 И выхСтруктураПолей.Количество() = МассивИменПолей.Количество() Тогда
Результат = Истина;
Иначе
Результат = Ложь;
Если ТипЗнч(ЭлементРасшифровкиПоля) = Тип("ЭлементРасшифровкиКомпоновкиДанныхПоля") Тогда
ЗначенияПолей = ЭлементРасшифровкиПоля.ПолучитьПоля();
Если ЗначенияПолей.Количество() > 0 Тогда
Если МассивИменПолей.Количество() > 0 Тогда
Для Каждого ИмяПоля Из МассивИменПолей Цикл
ЗначениеПоля = ЗначенияПолей.Найти(ИмяПоля);
ИмяСвойства = СтрЗаменить(ИмяПоля, ".", "");
Если Истина
И ЗначениеПоля <> Неопределено
И Не выхСтруктураПолей.Свойство(ИмяСвойства)
Тогда
выхСтруктураПолей.Вставить(ИмяСвойства, ЗначениеПоля.Значение);
Если выхСтруктураПолей.Количество() = МассивИменПолей.Количество() Тогда
Результат = Истина;
Прервать
КонецЕсли;
КонецЕсли;
КонецЦикла;
Иначе
Для Каждого ЗначениеПоля Из ЗначенияПолей Цикл
Ключ = "" + ЗначениеПоля.Поле;
Если ТипЗнч(выхСтруктураПолей) = Тип("Структура") Тогда
Ключ = СтрЗаменить(Ключ, ".", "_");
КонфликтноеЗначение = Неопределено;
Если Ложь
Или ЛиКорневой
Или (Истина
И выхСтруктураПолей.Свойство(Ключ, КонфликтноеЗначение)
И КонфликтноеЗначение <> ЗначениеПоля.Значение)
Тогда
Ключ = АвтоУникальноеИмяВКоллекцииЛкс(выхСтруктураПолей, Ключ, "Ключ");
КонецЕсли;
Иначе
Если Ложь
Или ЛиКорневой
Или (Истина
И ТипЗнч(выхСтруктураПолей) = Тип("Соответствие")
И выхСтруктураПолей[Ключ] <> ЗначениеПоля.Значение)
Тогда
Ключ = АвтоУникальноеИмяВКоллекцииЛкс(выхСтруктураПолей, Ключ, "Ключ", Ложь);
КонецЕсли;
КонецЕсли;
выхСтруктураПолей.Вставить(Ключ, ЗначениеПоля.Значение);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не Результат Тогда
РодительскиеЭлементыРасшифровки = ЭлементРасшифровкиПоля.ПолучитьРодителей();
Для Каждого РодительскийЭлементРасшифровки Из РодительскиеЭлементыРасшифровки Цикл
Результат = ИзвлечьКлючИзЭлементаРасшифровкиКомпоновкиЛкс(РодительскийЭлементРасшифровки, МассивИменПолей, выхСтруктураПолей, Ложь);
Если Результат И МассивИменПолей.Количество() > 0 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Если Истина
И МассивИменПолей.Количество() = 0
И РодительскиеЭлементыРасшифровки.Количество() = 0
Тогда
Результат = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция СоединениеЭтойСУБД(Знач ИмяСервера = "", Знач ИмяБД = "", Знач ИмяПользователя = "", Знач Пароль = "", Асинхронно = Ложь, Знач ТипСУБД = "") Экспорт
Если Не ЗначениеЗаполнено(ИмяСервера) Тогда
ПараметрыСоединения = ПараметрыСоединенияЭтойСУБДЛкс();
ИмяСервера = ПараметрыСоединения.ИмяСервера;
ИмяБД = ПараметрыСоединения.ИмяБД;
ИмяПользователя = ПараметрыСоединения.ИмяПользователя;
Пароль = ПараметрыСоединения.Пароль;
ТипСУБД = ПараметрыСоединения.ТипСУБД;
КонецЕсли;
КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов");
#Если Сервер И Не Сервер Тогда
КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать();
#КонецЕсли
ИсточникДанных = КонсольЗапросов.ПолучитьСтруктуруИсточникаДанныхADO(ТипСУБД);
ИсточникДанных.БазаСервер = ИмяСервера;
ИсточникДанных.БазаИмя = ИмяБД;
ИсточникДанных.АутентификацияОС = Не ЗначениеЗаполнено(ИмяПользователя);
ИсточникДанных.Пользователь = ИмяПользователя;
ИсточникДанных.Пароль = Пароль;
СоединениеADO = Неопределено;
ОшибкиПодключения = Неопределено;
РезультатПодключения = КонсольЗапросов.ConnectADO(ИсточникДанных, СоединениеADO,, ОшибкиПодключения,, Асинхронно);
//! СоединениеADO = Новый COMОбъект("ADODB.Connection")
Если Асинхронно Тогда
Возврат СоединениеADO;
КонецЕсли;
Если Не РезультатПодключения Тогда
СообщениеОбОшибке = "Ошибки подключения к СУБД:";
Для каждого ОшибкаПодключения Из ОшибкиПодключения Цикл
СообщениеОбОшибке = СообщениеОбОшибке + Символы.ПС + ОшибкаПодключения;
КонецЦикла;
СообщитьЛкс(СообщениеОбОшибке);
СоединениеADO = Неопределено;
Иначе
КлючНастроек = "" + Новый УникальныйИдентификатор;
ХранилищеОбщихНастроек.Сохранить(ирКэш.ИмяПродукта(), КлючНастроек, Неопределено);
РезультатЗапроса = ВыполнитьЗапросЭтойСУБДЛкс("SELECT 1 FROM _CommonSettings WHERE _SettingsKey = '" + КлючНастроек + "'",,,,, Ложь, СоединениеADO);
ХранилищеОбщихНастроек.Удалить(ирКэш.ИмяПродукта(), КлючНастроек, ИмяПользователя());
Если РезультатЗапроса.Количество() = 0 Тогда
Если ТранзакцияАктивна() Тогда
СообщитьЛкс("Невозможно проверить подключение к БД текущей базы 1С внутри открытой транзакции. Закройте транзакцию и повторите проверку.", СтатусСообщения.Внимание);
Иначе
СообщитьЛкс("Указаны параметры подключения к БД, не связанной с текущей базой 1С", СтатусСообщения.Внимание);
КонецЕсли;
СоединениеADO = Неопределено;
КонецЕсли;
КонецЕсли;
Возврат СоединениеADO;
КонецФункции
Функция ОбновитьМодульВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля, ТекстМодуляВКонсолиНеМенялся, ДатаИзмененияВнешнейОбработки,
ИспользоватьБыструюРаспаковку = Ложь) Экспорт
// Из-за негарантированной последовательности изменений одного файла в сетевом ресурсе, проводимых с разных компьютеров, серверное выполнение лишено смысла
//Если НаСервере Тогда
// Результат = ирСервер.ОбновитьМодульВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля, ТекстМодуляВКонсолиНеМенялся, ДатаИзмененияВнешнейОбработки);
// Возврат Результат;
//Иначе
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
ИмяФайлаВнешнейОбработки = ФайлВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки);
Если Не ЗначениеЗаполнено(ИмяФайлаВнешнейОбработки) Тогда
Возврат Ложь;
КонецЕсли;
ФайловыйКэшАлгоритмовДопускаетРедактирование = Истина;
ФайлВнешнейОбработки = Новый Файл(ИмяФайлаВнешнейОбработки);
Если ДатаИзмененияВнешнейОбработки <> Неопределено Тогда
Если Ложь
Или (Истина
И ФайлВнешнейОбработки.Существует()
И ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() > ДатаИзмененияВнешнейОбработки
И ФайловыйКэшАлгоритмовДопускаетРедактирование)
Или (Истина
И ФайлВнешнейОбработки.Существует()
И ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() = ДатаИзмененияВнешнейОбработки
И ТекстМодуляВКонсолиНеМенялся)
Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
мПлатформа.СформироватьВнешнююОбработку(ФайлВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля,,, ИспользоватьБыструюРаспаковку);
//// 19.01.2019 Для ВерсияАлгоритма в консоли кода
////ДатаИзмененияВнешнейОбработки = ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс();
//Если ЗначениеЗаполнено(ДатаИзмененияВнешнейОбработки) Тогда
// ФайлВнешнейОбработки.УстановитьВремяИзменения(ДатаИзмененияВнешнейОбработки);
//КонецЕсли;
Возврат Истина;
//КонецЕсли;
КонецФункции
// Получает идентификатор из любой строки.
// Пример "3-я Дебиторка По контрагентам с интервалами СНГ (для Руководства)" => "_3_яДебиторкаПоКонтрагентамСИнтерваламиСНГ_дляРуководства_".
// Параметры:
// Представление - Строка. -
// ЗаменаПустойСтроки - -
// ДопРазрешенныеСимволы - -
// ЗаменаСпецСимвола - Строка - если пустая, то следующий символ приводится к верхнему регистру
// ДелатьПервыйСимволВРег - Булево - если строка уже является идентификатором, то первый символ все равно нужно привести в верхний регистр
// Возвращаемое значение:
// Строка - .
Функция ИдентификаторИзПредставленияЛкс(Знач Представление = Неопределено, Знач ЗаменаПустойСтроки = "_", ДопРазрешенныеСимволы = "", Знач ЗаменаСпецСимвола = "_",
Знач ДелатьПервыйСимволВРег = Ложь) Экспорт
Если ПустаяСтрока(Представление) Тогда
Представление = ЗаменаПустойСтроки;
Иначе
Представление = "" + Представление;
КонецЕсли;
Если Не ДелатьПервыйСимволВРег И ЛиИмяПеременнойЛкс(Представление) Тогда
Возврат Представление;
КонецЕсли;
ПервыйСимвол = Сред(Представление, 1, 1);
Если ЛиЦифраЛкс(ПервыйСимвол) Тогда
// Первый символ - цифра
Представление = "_" + Представление;
КонецЕсли;
ПредыдущийСимвол = " ";
ТекущаяСтрока = "";
ШаблонСимволаИдентификатора = ШаблонСимволаИдентификатораЛкс(ДопРазрешенныеСимволы);
Для Счетчик = 1 По СтрДлина(Представление) Цикл
ТекущийСимвол = Сред(Представление, Счетчик, 1);
Если ПустаяСтрока(ПредыдущийСимвол) Тогда
// Предыдущий символ - непечатный или спецсимвол
ТекущийСимвол = ВРег(ТекущийСимвол);
КонецЕсли;
Если Найти(ШаблонСимволаИдентификатора, НРег(ТекущийСимвол)) > 0 Тогда
// Предыдущий символ - непечатный
ТекущаяСтрока = ТекущаяСтрока + ТекущийСимвол;
Иначе
Если Не ПустаяСтрока(ТекущийСимвол) Тогда
ТекущаяСтрока = ТекущаяСтрока + ЗаменаСпецСимвола;
Если ЗаменаСпецСимвола = "" Тогда
ТекущийСимвол = " ";
КонецЕсли;
КонецЕсли;
КонецЕсли;
ПредыдущийСимвол = ТекущийСимвол;
КонецЦикла;
Результат = ТекущаяСтрока;
Возврат ТекущаяСтрока;
КонецФункции
Функция ШаблонСимволаИдентификатораЛкс(Знач ДопРазрешенныеСимволы = "") Экспорт
РусскиеБуквы = РусскиеБуквыЛкс();
ШаблонСимволаИдентификатора = НРег("_0123456789" + РусскиеБуквы + "abcdefghijklmnopqrstuvwxyz" + ДопРазрешенныеСимволы); // Русский и Ангийский
Возврат ШаблонСимволаИдентификатора;
КонецФункции
Функция РусскиеБуквыЛкс() Экспорт
Возврат "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
КонецФункции
Функция ЛиРусскаяБукваЛкс(Знач Символ)
Возврат Символ <> "" И Найти(РусскиеБуквыЛкс(), НРег(Символ)) > 0;
КонецФункции
Функция ЛиБукваЛкс(Знач Символ) Экспорт
Возврат НРег(Символ) <> ВРег(Символ);
КонецФункции
Функция ЛиЦифраЛкс(Символ) Экспорт
Результат = Символ <> "" И Найти("0123456789", Символ) > 0;
//Результат = Символ >= "0" и Символ <= "9"; // Неправильно, т.к. сработает для "²", которое потом не сможет конвертироваться в число
Возврат Результат;
КонецФункции
Функция ЛиБулевыйЛитералЛкс(Знач ПрисвоенноеВыражение, выхЗначение = Неопределено) Экспорт
ПрисвоенноеВыражение = НРег(ПрисвоенноеВыражение);
Если Ложь
Или ПрисвоенноеВыражение = "истина"
Или ПрисвоенноеВыражение = "true"
Тогда
выхЗначение = Истина;
Результат = Истина;
ИначеЕсли Ложь
Или ПрисвоенноеВыражение = "ложь"
Или ПрисвоенноеВыражение = "false"
Тогда
выхЗначение = Ложь;
Результат = Истина;
Иначе
Результат = Ложь;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПроверитьКатегорииСимволаЛкс(Знач Символ, Знач МожноЦифра = Истина, Знач МожноБуква = Истина, Знач МожноПодчеркивание = Истина, Знач МожноНепечатный = Ложь) Экспорт
Если МожноЦифра И ЛиЦифраЛкс(Символ) Тогда
Возврат Истина;
КонецЕсли;
Если МожноБуква И ЛиБукваЛкс(Символ) Тогда
Возврат Истина;
КонецЕсли;
Если МожноПодчеркивание И Символ = "_" Тогда
Возврат Истина;
КонецЕсли;
Если МожноНепечатный И Символ <> "" И ПустаяСтрока(Символ) Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Функция ФайлВнешнейОбработкиДляОтладкиЛкс(Знач ИмяВнешнейОбработки) Экспорт
КаталогОбъектовДляОтладки = КаталогОбъектовДляОтладкиЛкс();
Если Не ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда
СообщитьЛкс("В общих настройках инструментов не задан ""Каталог объектов для отладки""! Сохранение внешней обработки не выполнено.", СтатусСообщения.Внимание);
Возврат "";
КонецЕсли;
ИмяФайлаВнешнейОбработки = КаталогОбъектовДляОтладки + ИмяВнешнейОбработки + ".epf";
Возврат ИмяФайлаВнешнейОбработки;
КонецФункции
//.
// Параметры:
// ИмяТипа - Строка - имя типа в единственном числе (ВнешняяОбработка/ВнешнийОтчет)
// ИмяФайла - Строка -
// Возвращаемое значение:
// ВнешняяОбработкаОбъект.<Имя внешней обработки> -
Функция МенеджерВнешнегоОбъектаЛкс(Знач ИмяФайла) Экспорт
Файл = Новый Файл(ИмяФайла);
Если СтрокиРавныЛкс(Файл.Расширение, ".erf") Тогда
МенеджерОбъектов = ВнешниеОтчеты;
Иначе
МенеджерОбъектов = ВнешниеОбработки;
КонецЕсли;
МенеджерОбъекта = МенеджерОбъектов.Создать(ИмяФайла, Ложь);
Возврат МенеджерОбъекта;
КонецФункции
// Возвращает строку недопустимых символов.
// Согласно http://en.wikipedia.org/wiki/Filename - в разделе "Reserved characters and words".
// Возвращаемое значение:
// Строка - строка недопустимых символов.
//
Функция НедопустимыеСимволыВИмениФайлаЛкс() Экспорт
НедопустимыеСимволы = """/\[]:;|=?*<>";
НедопустимыеСимволы = НедопустимыеСимволы + Символы.Таб + Символы.ПС;
Возврат НедопустимыеСимволы;
КонецФункции
// Заменяет недопустимые символы в имени файла.
//
// Параметры:
// ИмяФайла - Строка - исходное имя файла.
// НаЧтоМенять - Строка - строка, на которую необходимо заменить недопустимые символы.
//
// Возвращаемое значение:
// Строка - преобразованное имя файла.
//
Функция ЗаменитьНедопустимыеСимволыВИмениФайлаЛкс(Знач ИмяФайла, Знач НаЧтоМенять = " ", Знач ДопЗапрещенныеСимволы = "", Знач СжиматьСерии = Истина) Экспорт
Шаблон = "[" + ирОбщий.ТекстДляРегВыраженияЛкс(НедопустимыеСимволыВИмениФайлаЛкс() + ДопЗапрещенныеСимволы) + "]";
Если СжиматьСерии Тогда
Шаблон = Шаблон + "+";
КонецЕсли;
Возврат СокрЛП(ЗаменитьРегВыражениеЛкс(ИмяФайла, Шаблон, НаЧтоМенять, Ложь));
КонецФункции
Процедура ДокументDOMВФайлЛкс(Знач ДокументДом, Знач ИмяФайла) Экспорт
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайла);
ЗаписьДом = Новый ЗаписьDOM;
ЗаписьДом.Записать(ДокументДом, ЗаписьXML);
ЗаписьXML.Закрыть();
КонецПроцедуры
Функция ДокументDOMВСтрокуЛкс(Знач ДокументДом) Экспорт
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("");
ЗаписьДом = Новый ЗаписьDOM;
ЗаписьДом.Записать(ДокументДом, ЗаписьXML);
Результат = ЗаписьXML.Закрыть();
Возврат Результат;
КонецФункции
Функция ФайлВДокументDOMЛкс(Знач ИмяФайла, ИгнорироватьПробельныеСимволы = Ложь) Экспорт
ЧтениеXML = Новый ЧтениеXML;
ПараметрыЧтения = Новый ПараметрыЧтенияXML(,,,,,,,, ИгнорироватьПробельныеСимволы);
ЧтениеXML.ОткрытьФайл(ИмяФайла, ПараметрыЧтения);
ПостроительДом = Новый ПостроительDOM();
ДокументДОМ = ПостроительДом.Прочитать(ЧтениеXML);
ЧтениеXML.Закрыть();
Возврат ДокументДОМ;
КонецФункции
Функция ТекстВДокументDOMЛкс(Знач Текст, ИгнорироватьПробельныеСимволы = Ложь) Экспорт
ЧтениеXML = Новый ЧтениеXML;
ПараметрыЧтения = Новый ПараметрыЧтенияXML(,,,,,,,, ИгнорироватьПробельныеСимволы);
ЧтениеXML.УстановитьСтроку(Текст, ПараметрыЧтения);
ПостроительDOM = Новый ПостроительDOM;
ДокументДом = ПостроительDOM.Прочитать(ЧтениеXML);
Возврат ДокументДом;
КонецФункции
Функция ДокументDOMИзСтрокиВнутрЛкс(ТекстФайла, ИгнорироватьПробельныеСимволы = Истина) Экспорт
XMLСтрока = СтрокаВнутрВХМЛТелоЛкс(ТекстФайла);
ДокументDOM = ТекстВДокументDOMЛкс(XMLСтрока, ИгнорироватьПробельныеСимволы);
Возврат ДокументDOM;
КонецФункции
Функция ДобавитьМногострочнуюСтрокуВТекстЛкс(ТекстПриемник = "", Знач СтрокаДляВставки, Знач СмещениеОбычное, Знач СНовойСтроки = Ложь, Знач ОбрезатьЛевыеПустые = Ложь, Знач СмещениеДляЗвезд = Неопределено) Экспорт
Если Не ЗначениеЗаполнено(ТекстПриемник) Тогда
ТекстПриемник = "";
КонецЕсли;
ЗаписьТекста = Новый ЗаписьXML;
ЗаписьТекста.УстановитьСтроку();
Если СНовойСтроки Тогда
ЗаписьТекста.ЗаписатьБезОбработки(Символы.ПС + СмещениеОбычное);
КонецЕсли;
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(СтрокаДляВставки);
ЗаписьТекста.ЗаписатьБезОбработки(ТекстовыйДокумент.ПолучитьСтроку(1));
Для Счетчик = 2 По ТекстовыйДокумент.КоличествоСтрок() Цикл
ТекущаяСтрока = ТекстовыйДокумент.ПолучитьСтроку(Счетчик);
Если ОбрезатьЛевыеПустые Тогда
ТекущаяСтрока = СокрЛ(ТекущаяСтрока);
КонецЕсли;
Если Истина
И ЗначениеЗаполнено(СмещениеДляЗвезд)
И Лев(ТекущаяСтрока, 1) = "*"
Тогда
Если СтрНачинаетсяСЛкс(ТекущаяСтрока, "***") Тогда
СмещениеСтроки = " ";
ИначеЕсли СтрНачинаетсяСЛкс(ТекущаяСтрока, "**") Тогда
СмещениеСтроки = " ";
Иначе
СмещениеСтроки = " ";
КонецЕсли;
СмещениеСтроки = СмещениеДляЗвезд + СмещениеСтроки;
Иначе
СмещениеСтроки = СмещениеОбычное;
КонецЕсли;
ЗаписьТекста.ЗаписатьБезОбработки(Символы.ПС + СмещениеСтроки + ТекущаяСтрока);
КонецЦикла;
ТекстПриемник = ТекстПриемник + ЗаписьТекста.Закрыть();
Возврат ТекстПриемник;
КонецФункции
Функция ЭтотРасширениеКонфигурацииЛкс() Экспорт
Результат = Неопределено;
Если Не РежимСовместимостиМеньше8_3_4Лкс() Тогда
УстановитьПривилегированныйРежим(Истина);
Попытка
ЭтиРасширения = Вычислить("РасширенияКонфигурации").Получить(); // Антибаг платформы 8.3.10- исправлен в 8.3.11 https://partners.v8.1c.ru/forum/t/1607016/m/1607016
Исключение
Возврат Результат;
КонецПопытки;
ОтборРасширений = Новый Структура("Имя", ИмяПродуктаЛкс());
ЭтиРасширения = Вычислить("РасширенияКонфигурации").Получить(ОтборРасширений);
Если ЭтиРасширения.Количество() > 0 Тогда
Результат = ЭтиРасширения[0];
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция АдаптироватьРасширениеЛкс(ИмяПользователя = "", ПарольПользователя = "", ВключатьНомерСтроки = Истина) Экспорт
#Если ТонкийКлиент Или ВебКлиент Тогда
Результат = ирСервер.АдаптироватьРасширениеЛкс();
Возврат Результат;
#КонецЕсли
ПодключитьОтладкуВнешнихОбработокБСП = ХранилищеОбщихНастроек.Загрузить(, "ирАдаптацияРасширения.ПодключитьОтладкуВнешнихОбработокБСП",, ИмяПродуктаЛкс());
ПодключитьОтладкуОтчетов = Ложь; // Теперь это делается через глобальную команду
СгенерироватьРольВсеПрава = Ложь; // Давать права на верхние объекты метаданных недостаточно. Поэтому отключил пока этот флажок
НадоДобавитьВсеСсылочныеМетаданнные = Ложь;
ЭтотРасширение = ЭтотРасширениеКонфигурацииЛкс();
#Если Сервер И Не Сервер Тогда
ЭтотРасширение = РасширенияКонфигурации.Создать();
#КонецЕсли
ИмяРасширения = ЭтотРасширение.Имя;
ТекстСпискаОбъектовКонфигурации = "";
Если НадоДобавитьВсеСсылочныеМетаданнные Тогда
// Типы внешних источников пока не поддерживаются в платформе и будет ошибка при загрузке из файлов https://www.hostedredmine.com/issues/963092
ТипыСсылок = ОписаниеТиповВсеСсылкиЛкс(Ложь, Ложь).Типы();
#Если Сервер И Не Сервер Тогда
ТипыСсылок = Новый Массив;
#КонецЕсли
ТипыСсылокПлановОбмена = ПланыОбмена.ТипВсеСсылки().Типы();
// Сначала выгружаем из конфигурации все метаданные
//ТекстСпискаОбъектовКонфигурации = Метаданные.ПолноеИмя();
ДобавляемыеТипы = СкопироватьКоллекциюЛкс(ТипыСсылок);
#Если Сервер И Не Сервер Тогда
ДобавляемыеТипы = Новый Массив;
#КонецЕсли
Если СгенерироватьРольВсеПрава Тогда
ДобавляемыеТипыРегистров = Новый Массив;
ДобавляемыеТипыРегистров.Добавить("РегистрыСведений");
ДобавляемыеТипыРегистров.Добавить("РегистрыНакопления");
ДобавляемыеТипыРегистров.Добавить("РегистрыРасчета");
ДобавляемыеТипыРегистров.Добавить("РегистрыБухгалтерии");
ДобавляемыеТипыРегистров.Добавить("Последовательности");
Для Каждого ИмяКоллекцииРегистров Из ДобавляемыеТипыРегистров Цикл
Для Каждого ОбъектМД Из Метаданные[ИмяКоллекцииРегистров] Цикл
ДобавляемыеТипы.Добавить(Тип(СтрЗаменить(ОбъектМД.ПолноеИмя(), ".", "НаборЗаписей.")));
КонецЦикла;
КонецЦикла;
КонецЕсли;
Для Каждого Тип Из ДобавляемыеТипы Цикл
ОбъектМД = Метаданные.НайтиПоТипу(Тип);
ТекстСпискаОбъектовКонфигурации = ТекстСпискаОбъектовКонфигурации + Символы.ПС + ОбъектМД.ПолноеИмя();
КонецЦикла;
Для Каждого ОбъектМД Из Метаданные.ВнешниеИсточникиДанных Цикл
Если ОбъектМД.РасширениеКонфигурации() <> Неопределено Тогда
Продолжить;
КонецЕсли;
ТекстСпискаОбъектовКонфигурации = ТекстСпискаОбъектовКонфигурации + Символы.ПС + ОбъектМД.ПолноеИмя();
КонецЦикла;
КонецЕсли;
Если ПодключитьОтладкуВнешнихОбработокБСП И ирКэш.НомерВерсииБСПЛкс() >= 204 Тогда
ТекстСпискаОбъектовКонфигурации = ТекстСпискаОбъектовКонфигурации + Символы.ПС + Метаданные.ОбщиеМодули.ДополнительныеОтчетыИОбработки.ПолноеИмя(); //@skip-check unknown-method-property
КонецЕсли;
ПодключитьОтладкуОтчетов = ПодключитьОтладкуОтчетов И Метаданные.ОсновнаяФормаОтчета <> Неопределено И Метаданные.ОсновнаяФормаОтчета.РасширениеКонфигурации() = Неопределено;
Если ПодключитьОтладкуОтчетов Тогда
ТекстСпискаОбъектовКонфигурации = ТекстСпискаОбъектовКонфигурации + Символы.ПС + Метаданные.ОсновнаяФормаОтчета.ПолноеИмя();
КонецЕсли;
ТекстСпискаОбъектовКонфигурации = Сред(ТекстСпискаОбъектовКонфигурации, 2); // !
КаталогВыгрузкиКонфигурации = ПолучитьИмяВременногоФайла();
Успех = ВыгрузитьОбъектыМетаданныхЛкс(ТекстСпискаОбъектовКонфигурации, КаталогВыгрузкиКонфигурации, ИмяПользователя, ПарольПользователя);
Если Не Успех Тогда
УдалитьФайлы(КаталогВыгрузкиКонфигурации);
Возврат Ложь;
КонецЕсли;
// Выгружаем объекты из расширения
КаталогВыгрузкиРасширения = ПолучитьИмяВременногоФайла();
ИмяФайлаСпискаВыгрузкиРасширения = ПолучитьИмяВременногоФайла("txt");
ТекстЛога = "";
СоздатьКаталог(КаталогВыгрузкиРасширения);
ТекстСпискаОбъектовРасширения = "Конфигурация." + ИмяРасширения;
//Для Каждого КлючИЗначение Из ПометкиКоманд Цикл
// ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + "ОбщаяКоманда." + КлючИЗначение.Ключ;
//КонецЦикла;
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(ТекстСпискаОбъектовРасширения);
ТекстовыйДокумент.Записать(ИмяФайлаСпискаВыгрузкиРасширения);
// Пришлось отказаться от частичной загрузки из-за непонятной ошибки
// Файл - Configuration.xml: ошибка частичной загрузки - идентификатор 15dc941a-fd9f-4d00-bc7e-3ef077518def загружаемой конфигурации отличается от идентификатора b9c0a797-9739-4c3f-a665-796b3bf92d6a сохраненной конфигурации
//Успех = ВыполнитьКомандуКонфигуратораЛкс("/DumpConfigToFiles """ + КаталогВыгрузкиРасширения + """ -Extension """ + ИмяРасширения + """ -listFile """ + ИмяФайлаСпискаВыгрузкиРасширения + """ -Format Plain",
// СтрокаСоединенияИнформационнойБазы(), ТекстЛога, , "Выгрузка расширения в файлы");
Успех = ВыполнитьКомандуКонфигуратораЛкс("/DumpConfigToFiles """ + КаталогВыгрузкиРасширения + """ -Extension """ + ИмяРасширения + """ -Format Plain",
СтрокаСоединенияИнформационнойБазы(), ТекстЛога, , "Выгрузка расширения в файлы",,,, ИмяПользователя, ПарольПользователя);
Если Не Успех Тогда
УдалитьФайлы(КаталогВыгрузкиРасширения);
СообщитьЛкс(ТекстЛога);
Возврат Ложь;
КонецЕсли;
// Добавим ссылочные объекты в расширение
ИмяФайла = КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + "Configuration.xml";
ОписаниеРасширения = Новый ТекстовыйДокумент;
ОписаниеРасширения.Прочитать(ИмяФайла);
ОписаниеРасширения = ОписаниеРасширения.ПолучитьТекст();
ДокументДОМ = ФайлВДокументDOMЛкс(ИмяФайла);
УзелТиповСпискаОбъектов = ДокументДом.ПолучитьЭлементыПоИмени("ChildObjects");
УзелТиповСпискаОбъектов = УзелТиповСпискаОбъектов[0];
Если НадоДобавитьВсеСсылочныеМетаданнные Тогда
Если СгенерироватьРольВсеПрава Тогда
ТекстФайлаПрав = Новый ЗаписьXML;
ТекстФайлаПрав.УстановитьСтроку("");
// Мультиметка59234971
ТекстФайлаПрав.ЗаписатьБезОбработки("
|
| true
| true
| false");
КонецЕсли;
ДобавленныеВнешниеИсточникиДанных = Новый Соответствие;
Для Каждого Тип Из ДобавляемыеТипы Цикл
ПолноеИмяМДXML = XMLТип(Тип).ИмяТипа;
Если Ложь
Или Найти(ПолноеИмяМДXML, "RoutePointRef.") > 0
Тогда
Продолжить;
КонецЕсли;
ЭтоТаблицаВИД = Найти(ПолноеИмяМДXML, "ExternalDataSourceTableRef.") > 0;
Если ЭтоТаблицаВИД Тогда
Фрагменты = СтрРазделитьЛкс(ПолноеИмяМДXML);
Фрагменты[0] = "ExternalDataSource";
Фрагменты.Вставить(2, "Table");
МассивТаблицВИД = ДобавленныеВнешниеИсточникиДанных[Фрагменты[1]];
Если МассивТаблицВИД = Неопределено Тогда
МассивТаблицВИД = Новый Массив;
ДобавленныеВнешниеИсточникиДанных.Вставить(Фрагменты[1], МассивТаблицВИД);
КонецЕсли;
ПолноеИмяМДXML = СтрСоединитьЛкс(Фрагменты, ".");
КонецЕсли;
ПолноеИмяМДXML = СтрЗаменить(ПолноеИмяМДXML, "Ref.", ".");
ПолноеИмяМДXML = СтрЗаменить(ПолноеИмяМДXML, "RecordSet.", ".");
// Добавим в описание конфигурации (Configuration.xml)
ОбъектМД = Метаданные.НайтиПоТипу(Тип);
Если Не ЭтоТаблицаВИД Тогда
ИмяКлассаМДXML = ПервыйФрагментЛкс(ПолноеИмяМДXML);
ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя();
Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") > 0 Тогда
Продолжить;
КонецЕсли;
УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML);
УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя;
УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта);
Иначе
МассивТаблицВИД.Добавить(ОбъектМД.Имя);
ИмяКлассаМДXML = "Table";
КонецЕсли;
// Укажем принадлежность объекта в его описании
ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ПолноеИмяМДXML + ".xml");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя);
//ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя);
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "" + ИмяКлассаМДXML + ">", Ложь, Истина, Истина);
НаЧтоЗаменять =
"
| " + ПоследнийФрагментЛкс(ФайлИсточник.ИмяБезРасширения) + "
| Adopted
|
|
| " + ИмяКлассаМДXML + ">";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина);
НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
Если СгенерироватьРольВсеПрава Тогда
Если Истина
И Найти(ПолноеИмяМДXML, "Enum.") = 0
Тогда
// Даем права Просмотр и ПросмотрИстории
ТекстФайлаПрав.ЗаписатьБезОбработки("
| ");
КонецЕсли;
КонецЕсли;
КонецЦикла;
Для Каждого КлючИЗначение Из ДобавленныеВнешниеИсточникиДанных Цикл
ПолноеИмяМДXML = "ExternalDataSource." + КлючИЗначение.Ключ;
ИмяКлассаМДXML = ПервыйФрагментЛкс(ПолноеИмяМДXML);
// Добавим в описание конфигурации (Configuration.xml)
ОбъектМД = Метаданные.ВнешниеИсточникиДанных[КлючИЗначение.Ключ];
ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя();
Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") > 0 Тогда
Продолжить;
КонецЕсли;
УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML);
УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя;
УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта);
// Укажем принадлежность объекта в его описании
ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ПолноеИмяМДXML + ".xml");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя);
//ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя);
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "" + ИмяКлассаМДXML + ">", Ложь, Истина, Истина);
НаЧтоЗаменять =
"
| " + ПоследнийФрагментЛкс(ФайлИсточник.ИмяБезРасширения) + "
| Adopted
|
|
| " + ИмяКлассаМДXML + ">";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина);
НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ДокументДомВИД = ТекстВДокументDOMЛкс(ТекстФайла);
УзелТиповСпискаДочернихОбъектов = ДокументДомВИД.ПолучитьЭлементыПоИмени("ChildObjects");
УзелТиповСпискаДочернихОбъектов = УзелТиповСпискаДочернихОбъектов[0];
Для Каждого ИмяТаблицы Из КлючИЗначение.Значение Цикл
УзелОбъекта = ДокументДомВИД.СоздатьЭлемент("Table");
УзелОбъекта.ТекстовоеСодержимое = ИмяТаблицы;
УзелТиповСпискаДочернихОбъектов.ДобавитьДочерний(УзелОбъекта);
КонецЦикла;
ДокументDOMВФайлЛкс(ДокументДомВИД, ФайлПриемник.ПолноеИмя);
КонецЦикла;
Если СгенерироватьРольВсеПрава Тогда
// Добавим в описание конфигурации (Configuration.xml)
ИмяКлассаМДXML = "Role";
ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + "Роль.ирВсеПрава";
Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + "ирВсеПрава" + "<") = 0 Тогда
УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML);
УзелОбъекта.ТекстовоеСодержимое = "ирВсеПрава";
УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта);
КонецЕсли;
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + ".ирВсеПрава.xml");
ТекстФайла = "
|
|
|
| ирВсеПрава
|
|
| ru
| Все права (ИР)
|
|
| Сгенерирована инструментом ""Адаптация расширения"" для доступа на просмотр ко всем данным
|
|
|";
ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + ".ирВсеПрава.Rights.xml");
ТекстФайлаПрав.ЗаписатьБезОбработки("
|");
ТекстовыйДокумент.УстановитьТекст(ТекстФайлаПрав.Закрыть());
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
КонецЕсли;
КонецЕсли;
Если ПодключитьОтладкуВнешнихОбработокБСП И ирКэш.НомерВерсииБСПЛкс() >= 204 Тогда
ИмяОбъектаОригинала = "ДополнительныеОтчетыИОбработки";
ИмяОбъектаРасширения = "ирДополнительныеОтчетыИОбработкиБСП";
// Добавим в описание конфигурации (Configuration.xml)
ИмяКлассаМДXML = "CommonModule";
ОбъектМД = Метаданные.ОбщиеМодули[ИмяОбъектаОригинала];
ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя();
Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") = 0 Тогда
УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML);
УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя;
УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта);
// Укажем принадлежность объекта в его описании
ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".xml");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя);
//ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя);
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "" + ИмяКлассаМДXML + ">", Ложь, Истина, Истина);
НаЧтоЗаменять =
"
| " + ИмяОбъектаОригинала + "
| Adopted
|
| " + ИмяКлассаМДXML + ">";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина);
НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
КонецЕсли;
ФайлИсточник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ИмяОбъектаРасширения + ".Module.txt");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".Module.txt");
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
КонецЕсли;
Если ПодключитьОтладкуОтчетов И Метаданные.ОсновнаяФормаОтчета <> Неопределено Тогда
ИмяОбъектаОригинала = Метаданные.ОсновнаяФормаОтчета.Имя;
ИмяОбъектаРасширения = Метаданные.ОбщиеФормы.ирФормаОтчетаРасширение.Имя;
// Добавим в описание конфигурации (Configuration.xml)
ИмяКлассаМДXML = "CommonForm";
ОбъектМД = Метаданные.ОбщиеФормы[ИмяОбъектаОригинала];
ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя();
Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") = 0 Тогда
УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML);
УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя;
УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта);
// Укажем принадлежность объекта в его описании
ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".xml");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя);
//ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя);
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "" + ИмяКлассаМДXML + ">", Ложь, Истина, Истина);
НаЧтоЗаменять =
"
| " + ИмяОбъектаОригинала + "
| Adopted
| Managed
|
| " + ИмяКлассаМДXML + ">";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина);
НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
КонецЕсли;
// Модуль
ФайлИсточник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ИмяОбъектаРасширения + ".Form.Module.txt");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".Form.Module.txt");
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
// Диалог
ФайлИсточник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ИмяОбъектаРасширения + ".Form.xml");
ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".Form.xml");
ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя);
ТекстФайла = ТекстовыйДокумент.ПолучитьТекст();
ЧтоЗаменять = "";
НаЧтоЗаменять = "";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять);
ЧтоЗаменять = "";
НаЧтоЗаменять = "";
ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять, Истина);
ТекстовыйДокумент.УстановитьТекст(ТекстФайла);
ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя);
КонецЕсли;
ДокументDOMВФайлЛкс(ДокументДом, ИмяФайла);
//// Добавим типы ссылочных объектов в общие команды
//#Если Сервер И Не Сервер Тогда
// ТипыСсылок = Новый ОписаниеТипов;
//#КонецЕсли
//Для Каждого КлючИЗначение Из ПометкиКоманд Цикл
// ИмяКоманды = КлючИЗначение.Ключ;
// ИмяФайла = КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + "CommonCommand." + ИмяКоманды + ".xml";
// ДокументДОМ = ФайлВДокументDOMЛкс(ИмяФайла);
// УзелТиповПараметра = ДокументДом.ПолучитьЭлементыПоИмени("CommandParameterType");
// УзелТиповПараметра = УзелТиповПараметра[0];
// Пока УзелТиповПараметра.ДочерниеУзлы.Количество() > 0 Цикл
// УзелТиповПараметра.УдалитьДочерний(УзелТиповПараметра.ПервыйДочерний);
// КонецЦикла;
// Если КлючИЗначение.Значение Тогда
// Если ИмяКоманды = Метаданные.ОбщиеКоманды.ирРедактироватьИзмененияНаУзле.Имя Тогда
// ТипыПараметра = ТипыСсылокПлановОбмена;
// Иначе
// ТипыПараметра = ТипыСсылок;
// КонецЕсли;
// Для Каждого Тип Из ТипыПараметра Цикл
// УзелТипа = ДокументДом.СоздатьЭлемент("v8:Type"); // http://v8.1c.ru/8.1/data/core
// УзелТипа.ТекстовоеСодержимое = "cfg:" + XMLТип(Тип).ИмяТипа; // http://v8.1c.ru/8.1/data/enterprise/current-config
// УзелТиповПараметра.ДобавитьДочерний(УзелТипа);
// КонецЦикла;
// КонецЕсли;
// ДокументDOMВФайлЛкс(ДокументДом, ИмяФайла);
//КонецЦикла;
ТекстЛога = "";
// Пришлось отказаться от частичной загрузки из-за непонятной ошибки
// Файл - Configuration.xml: ошибка частичной загрузки - идентификатор 15dc941a-fd9f-4d00-bc7e-3ef077518def загружаемой конфигурации отличается от идентификатора b9c0a797-9739-4c3f-a665-796b3bf92d6a сохраненной конфигурации
//ФайлыДляЗагрузки = НайтиФайлы(КаталогВыгрузкиРасширения, "*");
//ТекстовыйДокумент.Очистить();
//Для Каждого Файл Из ФайлыДляЗагрузки Цикл
// ТекстовыйДокумент.ДобавитьСтроку(Файл.ПолноеИмя);
//КонецЦикла;
//ТекстовыйДокумент.Записать(ИмяФайлаСпискаВыгрузкиРасширения);
//Успех = ВыполнитьКомандуКонфигуратораЛкс("/LoadConfigFromFiles """ + КаталогВыгрузкиРасширения + """ -Extension """ + ИмяРасширения + """ -listFile """ + ИмяФайлаСпискаВыгрузкиРасширения + """ -Format Plain",
// СтрокаСоединенияИнформационнойБазы(), ТекстЛога,,, "Загрузка расширения из файлов");
Успех = ВыполнитьКомандуКонфигуратораЛкс("/LoadConfigFromFiles """ + КаталогВыгрузкиРасширения + """ -Extension """ + ИмяРасширения + """ -Format Plain",
СтрокаСоединенияИнформационнойБазы(), ТекстЛога, , "Загрузка расширения из файлов",,,, ИмяПользователя, ПарольПользователя);
УдалитьФайлы(КаталогВыгрузкиРасширения);
Если Не Успех Тогда
СообщитьЛкс(ТекстЛога);
Возврат Ложь;
КонецЕсли;
// Почему то без этого расширение не применялось (оставалась активной кнопка "Обновить конфигурацию БД"
//ЭтотРасширение.Записать();
КонечныйФайл = ПолучитьИмяВременногоФайла();
Успех = ВыполнитьКомандуКонфигуратораЛкс("/DumpCfg """ + КонечныйФайл + """ -Extension """ + ИмяРасширения + """", СтрокаСоединенияИнформационнойБазы(), ТекстЛога,,,,,, ИмяПользователя, ПарольПользователя);
Если Не Успех Тогда
СообщитьЛкс(ТекстЛога);
Возврат Ложь;
КонецЕсли;
ЭтотРасширение.Записать(Новый ДвоичныеДанные(КонечныйФайл));
Возврат Истина;
КонецФункции
Функция ВыгрузитьОбъектыМетаданныхЛкс(Знач ИменаОбъектов, Знач КаталогВыгрузкиКонфигурации, Знач ИмяПользователя = "", Знач ПарольПользователя = "", выхТекстЛога = "",
Знач ПодавлятьДиалоги = Истина, Знач СообщитьСтрокуПараметров = Истина) Экспорт
ИмяФайлаСпискаВыгрузкиКонфигурации = ПолучитьИмяВременногоФайла("txt");
Если ТипЗнч(ИменаОбъектов) = Тип("Массив") Тогда
ИменаОбъектов = СтрСоединитьЛкс(ИменаОбъектов, Символы.ПС);
КонецЕсли;
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.УстановитьТекст(ИменаОбъектов);
ТекстовыйДокумент.Записать(ИмяФайлаСпискаВыгрузкиКонфигурации);
СоздатьКаталог(КаталогВыгрузкиКонфигурации);
выхТекстЛога = "";
Успех = ВыполнитьКомандуКонфигуратораЛкс("/DumpConfigToFiles """ + КаталогВыгрузкиКонфигурации + """ -listFile """ + ИмяФайлаСпискаВыгрузкиКонфигурации + """ -Format Plain",
СтрокаСоединенияИнформационнойБазы(), выхТекстЛога, ПодавлятьДиалоги, "Выгрузка конфигурации в файлы",,,, ИмяПользователя, ПарольПользователя, СообщитьСтрокуПараметров,,,,, Истина);
УдалитьФайлы(ИмяФайлаСпискаВыгрузкиКонфигурации);
Если Не Успех Тогда
СообщитьЛкс(выхТекстЛога);
КонецЕсли;
Возврат Успех;
КонецФункции
Процедура ПроверитьСоздатьКаталогПередСозданиемФайлаЛкс(Знач ИмяКонфигурационногоФайла) Экспорт
Файл = Новый Файл(ИмяКонфигурационногоФайла);
ФайлКаталога = Новый Файл(Файл.Путь);
Если Не ФайлКаталога.Существует() Тогда
СоздатьКаталог(ФайлКаталога.ПолноеИмя);
КонецЕсли;
КонецПроцедуры
Функция КаталогПрограммныхФайловОСЛкс(Знач x64 = Неопределено) Экспорт
ПеременныеОкружения = ирКэш.ПеременныеОкруженияПроцессаЛкс();
Если ирКэш.Это64битнаяОСЛкс() Тогда
Если x64 = Неопределено Тогда
x64 = ирКэш.Это64битныйПроцессЛкс();
КонецЕсли;
Если x64 Тогда
ИмяПеременной = "ProgramW6432";
Иначе
ИмяПеременной = "ProgramFiles(x86)";
КонецЕсли;
Иначе
ИмяПеременной = "ProgramFiles";
КонецЕсли;
КаталогПрограммныхФайлов = ПеременныеОкружения.Item(ИмяПеременной);
Возврат КаталогПрограммныхФайлов;
КонецФункции
Функция КаталогПеремещаемыхДанныхПриложенийЛкс() Экспорт
ПеременныеОкружения = ирКэш.ПеременныеОкруженияПроцессаЛкс();
КаталогПеремещаемыхДанныхПриложений = ПеременныеОкружения.Item("Appdata");
Возврат КаталогПеремещаемыхДанныхПриложений;
КонецФункции
Функция ПараметрыСоединенияЭтойСУБДЛкс(выхИменаПараметров = "") Экспорт
выхИменаПараметров = "ИмяСервера, ИмяБД, ИмяПользователя, Пароль, НаСервере, СобиратьТрассу, ТипСУБД";
Результат = Новый Структура(выхИменаПараметров);
РезультатСохраненный = ВосстановитьЗначениеЛкс("ПараметрыСоединенияСУБД");
Если РезультатСохраненный = Неопределено Тогда
// Старый формат настроек
Результат.ИмяСервера = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяСервера");
Результат.ИмяБД = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяБД");
Результат.ИмяПользователя = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяПользователя");
Результат.СобиратьТрассу = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.СобиратьТрассу");
Результат.ТипСУБД = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ТипСУБД");
Результат.НаСервере = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.НаСервере");
Результат.Пароль = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.Пароль");
СохранитьПараметрыСоединенияСУБДЛкс(Результат);
Иначе
ЗаполнитьЗначенияСвойств(Результат, РезультатСохраненный);
КонецЕсли;
Если Результат.ТипСУБД = Неопределено Тогда
Результат.ТипСУБД = "MSSQL";
КонецЕсли;
Если Результат.Пароль <> Неопределено Тогда
Результат.Пароль = Результат.Пароль.Получить();
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// ТабличныйДокумент - ТабличныйДокумент -
// Возвращаемое значение:
// СписокЗначений -
Функция ПараметрыТабличногоДокументаЛкс(Знач ТабличныйДокумент) Экспорт
ПараметрыМакета = Новый СписокЗначений;
ПараметрыМакета.ТипЗначения = Новый ОписаниеТипов("Строка");
Текст = ОбъектВСтрокуXMLЛкс(ТабличныйДокумент);
шИмяЭлемента = "(?:detail)?parameter";
Вхождения = НайтиРегВыражениеЛкс(Текст, "<" +шИмяЭлемента+ ">(.+)" +шИмяЭлемента+ ">");
Для Каждого Вхождение Из Вхождения Цикл
Если ПараметрыМакета.НайтиПоЗначению(Вхождение.Группа0) = Неопределено Тогда
ПараметрыМакета.Добавить(Вхождение.Группа0);
КонецЕсли;
КонецЦикла;
ПараметрыМакета.СортироватьПоЗначению();
Возврат ПараметрыМакета;
КонецФункции
Процедура СохранитьПараметрыСоединенияСУБДЛкс(Результат) Экспорт
Если ТипЗнч(Результат.Пароль) = Тип("Строка") Тогда
Результат.Пароль = Новый ХранилищеЗначения(Результат.Пароль);
КонецЕсли;
СохранитьЗначениеЛкс("ПараметрыСоединенияСУБД", Результат);
КонецПроцедуры
Функция ПроверитьСоединениеЭтойСУБДЛкс(Знач ИмяСервера = "", Знач ИмяБД = "", Знач ИмяПользователя = "", Знач Пароль = "", Знач НаСервере = Неопределено, ЗапрашиватьПараметрыПодключения = Истина,
Асинхронно = Ложь, выхСоединение = Неопределено, Знач ТипСУБД = "MSSQL") Экспорт
Если ПроверитьПлатформаНеWindowsЛкс(, "Прямой запрос к СУБД") Тогда
Возврат Ложь;
КонецЕсли;
КоличествоПопыток = 1;
НачальнаяПопытка = 1;
Если ЗапрашиватьПараметрыПодключения Тогда
КоличествоПопыток = 2;
Если Не ЗначениеЗаполнено(ИмяСервера) Тогда
ПараметрыСоединения = ПараметрыСоединенияЭтойСУБДЛкс();
Если Не ЗначениеЗаполнено(ПараметрыСоединения.ИмяСервера) Тогда
НачальнаяПопытка = 2;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Для НомерПопытки = НачальнаяПопытка По КоличествоПопыток Цикл
Если НомерПопытки = 2 Тогда
#Если Клиент Тогда
ФормаПодключения = ирКлиент.ОткрытьФормуСоединенияСУБДЛкс(Истина);
Если ФормаПодключения = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
Если НаСервере = Неопределено Тогда
НаСервере = ФормаПодключения.НаСервере;
КонецЕсли;
#Иначе
СообщитьЛкс("Необходимо с клиента выполнить проверку установки соединения с СУБД");
Возврат Ложь;
#КонецЕсли
Иначе
Если НаСервере = Неопределено Тогда
Если ПараметрыСоединения = Неопределено Тогда
ПараметрыСоединения = ПараметрыСоединенияЭтойСУБДЛкс();
КонецЕсли;
НаСервере = ПараметрыСоединения.НаСервере;
КонецЕсли;
КонецЕсли;
Если НомерПопытки = 2 И Не ЗначениеЗаполнено(ИмяСервера) Тогда
ЛиСоединениеУстановлено = Ложь;
ИначеЕсли НаСервере = Истина Тогда
ЛиСоединениеУстановлено = ирСервер.ПроверитьСоединениеЭтойСУБДЛкс(ИмяСервера, ИмяБД, ИмяПользователя, Пароль, Асинхронно, ТипСУБД);
Если ЛиСоединениеУстановлено Тогда
выхСоединение = "Готов";
КонецЕсли;
Иначе
выхСоединение = СоединениеЭтойСУБД(ИмяСервера, ИмяБД, ИмяПользователя, Пароль, Асинхронно, ТипСУБД);
ЛиСоединениеУстановлено = выхСоединение <> Неопределено;
КонецЕсли;
Если ЛиСоединениеУстановлено Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ЛиСоединениеУстановлено;
КонецФункции
Функция ВыполнитьЗапросЭтойСУБДЛкс(Знач ТекстЗапроса, Знач РежимОтладки = Ложь, Знач ПредставлениеЗапроса = "", Знач СмещениеГода = 2000, Знач ИспользованиеGWF = Истина,
Знач НаСервере = Неопределено, СоединениеADO = Неопределено, БинарныеВСтроку = Истина, Знач ИспользоватьRecordset = Истина, Знач МаксСекунд = 300) Экспорт
ТребоватьТипЛкс(ТекстЗапроса, "ТекстЗапроса", Тип("Строка"));
#Если Клиент Тогда
Если РежимОтладки Тогда
ирКлиент.ОткрытьЗапросСУБДЛкс(ТекстЗапроса, ПредставлениеЗапроса);
Возврат Неопределено;
КонецЕсли;
Если Истина
И СоединениеADO = Неопределено
И НаСервере = Неопределено
Тогда
НаСервере = ПараметрыСоединенияЭтойСУБДЛкс().НаСервере;
КонецЕсли;
#КонецЕсли
Если НаСервере = Истина Тогда
Таблица = ирСервер.ВыполнитьЗапросЭтойСУБДЛкс(ТекстЗапроса, СмещениеГода, ИспользованиеGWF);
Иначе
Если СоединениеADO = Неопределено Тогда
Попытка
СоединениеADO = ирКэш.СоединениеЭтойСУБД();
Исключение
СоединениеADO = СоединениеЭтойСУБД();
КонецПопытки;
Если СоединениеADO = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Если ИспользоватьRecordset Тогда
СоединениеADO.CommandTimeout = МаксСекунд;
РезультатЗапроса = Новый COMОбъект("ADODB.Recordset");
adOpenStatic = 3;
adLockOptimistic = 3;
adCmdText = 1;
РезультатЗапроса.Open(ТекстЗапроса, СоединениеADO, adOpenStatic, adLockOptimistic, adCmdText);
Иначе
КомандаADO = Новый COMОбъект("ADODB.Command");
КомандаADO.CommandTimeout = МаксСекунд;
КомандаADO.CommandText = ТекстЗапроса;
КомандаADO.CommandType = 1;
КомандаADO.ActiveConnection = СоединениеADO;
РезультатЗапроса = КомандаADO.Execute();
Если СоединениеADO.Properties("Multiple Results").Value <> 0 Тогда
// Получаем последний результат пакетной команды
Пока Истина Цикл
лРезультат = РезультатЗапроса.NextRecordset();
Если лРезультат = Неопределено Тогда
Прервать;
КонецЕсли;
РезультатЗапроса = лРезультат;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если РезультатЗапроса.State = 1 Тогда
Таблица = РезультатЗапросаADOВТаблицуЗначенийОбщийЛкс(РезультатЗапроса, , БинарныеВСтроку, , СмещениеГода, ИспользованиеGWF);
КонецЕсли;
КонецЕсли;
Возврат Таблица;
КонецФункции
// Функция - Выполнить запрос и найти текст СУБДЛкс
//
// Параметры:
// Запрос - -
// ДолженСодержатьТекст - -
// ЗапроситьИдентификаторСоединенияБД - Булево - принудительно запросить актуальный идентификатор соединения БД, можно передавать Ложь если соединение БД удерживается снаружи
//
// Возвращаемое значение:
// -
//
Функция ВыполнитьЗапросИНайтиТекстСУБДЛкс(Знач Запрос, Знач ДолженСодержатьТекст = "", Знач ЗапроситьИдентификаторСоединенияБД = Истина) Экспорт
АнализТехножурнала = ирКэш.АнализТехножурналаЛкс();
#Если Сервер И Не Сервер Тогда
Запрос = Новый Запрос;
АнализТехножурнала = Обработки.ирАнализТехножурнала.Создать();
#КонецЕсли
АнализТехножурнала.ОчиститьТаблицуЖурнала();
АнализТехножурнала.НачатьТрассу(,,, Истина, ЗапроситьИдентификаторСоединенияБД);
Запрос.Выполнить();
АнализТехножурнала.КончитьТрассу();
АнализТехножурнала.ЗагрузитьТрассуСУБД();
ОтборЖурнала = Новый Структура;
ОтборЖурнала.Вставить("ТипПроцессаОС", "sqlservr");
Найденные = АнализТехножурнала.ТаблицаЖурнала.НайтиСтроки(ОтборЖурнала);
ТекстСУБД = "";
Для Каждого НайденныйЗапрос Из Найденные Цикл
Если Ложь
Или Не ЗначениеЗаполнено(ДолженСодержатьТекст)
Или СтрНайтиЛкс(НайденныйЗапрос.ТекстСУБД, ДолженСодержатьТекст,,,, Ложь) > 0
Тогда
ТекстСУБД = НайденныйЗапрос.ТекстСУБД;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ЗначениеЗаполнено(ТекстСУБД) Тогда
ВызватьИсключение "Не найден сформированный платформой запрос СУБД";
КонецЕсли;
Возврат ТекстСУБД;
КонецФункции
//Функция получает на вход текст html, из которого создает COM объект HtmlFile
//Параметры
// ТекстHtml - Строка. Текст в формате HTML
// ПереопределятьБазу - используется только при УстановитьБазу = Истина
//Возвращаемое значение
//COM объект с типом HtmlFile
Функция ПолучитьHtmlFileИзТекстаHtmlЛкс(ТекстHtml = "", Результат = Неопределено) Экспорт
Если Результат = Неопределено Тогда
Результат = Новый COMОбъект("HtmlFile");
КонецЕсли;
Результат.open("text/html");
Результат.write(ТекстHtml);
Результат.close();
Возврат Результат;
КонецФункции
Функция ПолучитьHtmlТекстВыделенияЛкс(ДокументHtml) Экспорт
Результат = "";
Если ДокументHtml.getSelection() <> Неопределено Тогда
Выделение = ДокументHtml.getSelection();
Если Выделение.rangeCount > 0 Тогда
ЭлементDiv = ДокументHtml.createElement("div");
Для Счетчик = 0 по Выделение.rangeCount - 1 Цикл
ЭлементDiv.appendChild(Выделение.getRangeAt(Счетчик).cloneContents());
КонецЦикла;
Результат = ЭлементDiv.innerHTML;
КонецЕсли;
ИначеЕсли ДокументHtml.selection <> Неопределено Тогда
//Если ДокументHtml.selection.type = "Text" Тогда
// Результат = ДокументHtml.selection.createRange().htmlText;
//КонецЕсли;
Результат = ДокументHtml.selection.CreateRange().htmlText;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ОбработатьПорциюСтрокТаблицыЛкс(АдресТаблицыЗначений, НачальныйНомерСтроки, РазмерПорции, МодальныйРежим = Ложь, ПропускатьОшибки = Ложь, ТекстАлгоритма, ПараметраАлгоритмы = Неопределено, ПерейтиНаСервер = Ложь) Экспорт
Если ПерейтиНаСервер Тогда
ирСервер.ОбработатьПорциюСтрокТаблицыЛкс(АдресТаблицыЗначений, НачальныйНомерСтроки, РазмерПорции, МодальныйРежим, ПропускатьОшибки, ТекстАлгоритма, ПараметраАлгоритмы);
Возврат Неопределено;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ТаблицаЗначений = Новый ТаблицаЗначений;
#КонецЕсли
ТаблицаЗначений = ПолучитьИзВременногоХранилища(АдресТаблицыЗначений);
КоличествоСтрокТаблицы = ТаблицаЗначений.Количество();
Для НомерСтроки = НачальныйНомерСтроки По Мин(НачальныйНомерСтроки + РазмерПорции - 1, ТаблицаЗначений.Количество()) Цикл
СтрокаТаблицы = ТаблицаЗначений[НомерСтроки - 1];
Попытка
ВыполнитьАлгоритм(ТекстАлгоритма,,, ПараметраАлгоритмы, СтрокаТаблицы, НомерСтроки = 1, НомерСтроки = КоличествоСтрокТаблицы);
Исключение
Если Не ПропускатьОшибки Тогда
ВызватьИсключение
КонецЕсли;
СообщитьСУчетомМодальностиЛкс("Строка результата №" + НомерСтроки + ": " + ОписаниеОшибки(), МодальныйРежим);
КонецПопытки;
КонецЦикла;
КонецФункции
Процедура ПаузаЛкс(ЧислоСекунд) Экспорт
ПаузаМиллисекундЛкс(ЧислоСекунд*1000);
КонецПроцедуры
Процедура ПаузаМиллисекундЛкс(Число) Экспорт
Если Истина
И ирКэш.НомерВерсииПлатформыЛкс() >= 803025
И ирКэш.ЭтоФоновоеЗаданиеЛкс()
Тогда
Выполнить("ВызватьПаузу(Число)");
Возврат;
КонецЕсли;
Попытка
ВК = ВКОбщаяЛкс();
ВК.Sleep(Число);
Исключение
// Антибаг платформы 8.3 https://www.hostedredmine.com/issues/889213
ОписаниеОшибки = ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Функция ФоновыеЗаданияПотоковЛкс() Экспорт
Отбор = Новый Структура;
Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
#Если Сервер И Не Сервер Тогда
ирОбщий.ОбработатьПорциюОбъектовЛкс();
#КонецЕсли
Отбор.Вставить("ИмяМетода", "ирОбщий.ОбработатьПорциюОбъектовЛкс");
Найденные = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
Возврат Найденные;
КонецФункции
// Используется иногда долгая функция ПолучитьСеансыИнформационнойБазы()
Функция СеансКонфигуратора() Экспорт
Сеансы = ПолучитьСеансыИнформационнойБазы(); // Иногда выполняется долго
Для Каждого Сеанс Из Сеансы Цикл
Если СтрокиРавныЛкс(Сеанс.ИмяПриложения, "Designer") Тогда
Возврат Сеанс;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция ПростойРезультатЗапросаЛкс(ТекстЗапроса, АдресХранилища = Неопределено) Экспорт
Если ЗначениеЗаполнено(ТекстЗапроса) Тогда
ЗапросКоличестваСтрок = Новый Запрос(ТекстЗапроса);
Результат = ЗапросКоличестваСтрок.Выполнить().Выгрузить()[0][0];
Иначе
Результат = 0;
КонецЕсли;
Если ЗначениеЗаполнено(АдресХранилища) Тогда
ПоместитьВоВременноеХранилище(Результат, АдресХранилища);
КонецЕсли;
Возврат Результат;
КонецФункции
Функция КоличествоСтрокВТаблицеМДЛкс(ПолноеИмяМД, АдресВременногоХранилища = "") Экспорт
Если Не ЗначениеЗаполнено(ПолноеИмяМД) Тогда
Возврат "";
КонецЕсли;
ПолноеИмяТаблицы = ирКэш.ИмяТаблицыИзМетаданныхЛкс(ПолноеИмяМД,,, Истина);
Если Не ЗначениеЗаполнено(ПолноеИмяТаблицы) Тогда
Возврат Неопределено;
КонецЕсли;
КоличествоСтрок = КоличествоСтрокВТаблицеБДЛкс(ПолноеИмяТаблицы);
Если ЗначениеЗаполнено(АдресВременногоХранилища) Тогда
ПоместитьВоВременноеХранилище(КоличествоСтрок, АдресВременногоХранилища);
КонецЕсли;
Возврат КоличествоСтрок;
КонецФункции
// Функция - Количество строк в таблице БДЛкс
//
// Параметры:
// ПолноеИмяТаблицыИлиЗапрос - Текст, Запрос - имя таблицы или запрос
// Отбор - Отбор - Используется только когда передано имя таблицы
//
// Возвращаемое значение:
// - Запрос
//
Функция КоличествоСтрокВТаблицеБДЛкс(Знач ПолноеИмяТаблицыИлиЗапрос, Знач Отбор = Неопределено) Экспорт
Если ТипЗнч(ПолноеИмяТаблицыИлиЗапрос) = Тип("Строка") Тогда
ПолноеИмяТаблицы = ПолноеИмяТаблицыИлиЗапрос;
Если Отбор = Неопределено Тогда
ЗапросКоличестваСтрок = Новый Запрос("ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ " + ПолноеИмяТаблицы);
КоличествоСтрок = ЗапросКоличестваСтрок.Выполнить().Выгрузить()[0][0];
Иначе
ИмяСлужебногоПоля = "СлужебноеПоле" + СуффиксСлужебногоСвойстваЛкс();
ТекстЗапроса = "ВЫБРАТЬ Т.*, 0 КАК " + ИмяСлужебногоПоля + " ИЗ " + ПолноеИмяТаблицы + " КАК Т";
СхемаКомпоновки = СоздатьСхемуКомпоновкиПоЗапросуЛкс(ТекстЗапроса);
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, Отбор);
//СкопироватьПорядокЛюбойЛкс(НастройкаКомпоновки.Порядок, НастройкиСписка.Порядок);
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ИмяСлужебногоПоля);
Запрос = ЗапросИзКомпоновкиЛкс(СхемаКомпоновки, НастройкаКомпоновки,,,,, Ложь);
#Если Сервер И Не Сервер Тогда
Запрос = Новый Запрос;
#КонецЕсли
Запрос.Текст = СтрЗаменитьЛкс(Запрос.Текст, "0 КАК " + ИмяСлужебногоПоля, "РАЗРЕШЕННЫЕ КОЛИЧЕСТВО(*) КАК КоличествоСтрок");
КоличествоСтрок = Запрос.Выполнить().Выгрузить()[0][0];
КонецЕсли;
Иначе
Запрос = ПолноеИмяТаблицыИлиЗапрос;
КоличествоСтрок = КоличествоСтрокВРезультатеЗапросаЛкс(Запрос);
КонецЕсли;
Возврат КоличествоСтрок;
КонецФункции
Процедура ВыделитьПервыеСтрокиДинамическогоСпискаЛкс(Знач ТабличноеПоле, Знач Количество, Знач НастройкиСписка = Неопределено) Экспорт
Если ТипЗнч(ТабличноеПоле.ТекущаяСтрока) = Тип("Число") Тогда
СообщитьЛкс("Для этого типа таблицы не поддерживается");
Возврат;
КонецЕсли;
ДинамическийСписок = ДанныеЭлементаФормыЛкс(ТабличноеПоле);
ПолноеИмяТаблицы = ИмяТаблицыБДДинамическогоСпискаЛкс(ТабличноеПоле);
СхемаКомпоновки = СоздатьСхемуКомпоновкиТаблицыБДЛкс(ПолноеИмяТаблицы,,,,,,, Количество);
НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных;
Если НастройкиСписка = Неопределено Тогда
НастройкиСписка = НастройкиДинамическогоСпискаЛкс(ДинамическийСписок);
КонецЕсли;
СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, НастройкиСписка.Отбор);
Если Не ЛиКорневойТипПеречисленияЛкс(ПервыйФрагментЛкс(ПолноеИмяТаблицы)) Тогда
СкопироватьПорядокЛюбойЛкс(НастройкаКомпоновки.Порядок, НастройкиСписка.Порядок);
КонецЕсли;
СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяТаблицы,, Ложь);
Для Каждого ЭлементСписка Из СтруктураКлюча Цикл
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ЭлементСписка.Представление);
КонецЦикла;
КлючиСтрок = СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(СхемаКомпоновки, НастройкаКомпоновки);
ВыделенныеСтроки = ТабличноеПоле.ВыделенныеСтроки;
Индикатор = ПолучитьИндикаторПроцессаЛкс(КлючиСтрок.Количество(), "Выделение");
Для Каждого КлючСтроки Из КлючиСтрок Цикл
ОбработатьИндикаторЛкс(Индикатор);
ВыделенныеСтроки.Добавить(КлючСтрокиТаблицыБДИзСтрокиТаблицыЗначенийЛкс(ПолноеИмяТаблицы, КлючСтроки));
КонецЦикла;
ОсвободитьИндикаторПроцессаЛкс();
Если КлючиСтрок.Количество() <> Количество Тогда
СообщитьЛкс(СтрШаблонИменЛкс("Выделены все отобранные элементы, но меньшим количеством %1",, КлючиСтрок.Количество()));
КонецЕсли;
#Если Клиент Тогда
Если ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле") Тогда
ТабличноеПоле.ОбновитьСтроки();
КонецЕсли;
#КонецЕсли
КонецПроцедуры
// Если в текущей строке не достаточно полей для заполнения ключа записи регистра, то всегда возвращается набор записей, не смотря на параметр ДляРегистровСоздатьНаборЗаписей.
// Параметры:
// СтруктураКлюча - Структура - для ускорения в циклах;
// ОбъектМД - ОбъектМетаданных - для ускорения в циклах;
Функция КлючСтрокиТаблицыБДИзСтрокиТаблицыЗначенийЛкс(Знач ПолноеИмяТаблицы, Знач ТекущаяСтрока, ДляНабораЗаписейРегистраСведений = Ложь, выхСтруктураЛокальногоКлючаСтроки = Неопределено,
ОбъектыНаСервере = Неопределено, СтруктураКлюча = Неопределено, ОбъектМД = Неопределено) Экспорт
ИмяПоляСсылка = ПеревестиСтроку("Ссылка");
ИмяПоляНомерСтроки = ПеревестиСтроку("НомерСтроки");
ИмяПоляПериод = ПеревестиСтроку("Период");
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
Если СтруктураКлюча = Неопределено Тогда
СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяТаблицы,,, ДляНабораЗаписейРегистраСведений);
Иначе
СтруктураКлюча = СкопироватьКоллекциюЛкс(СтруктураКлюча);
КонецЕсли;
#Если Сервер И Не Сервер Тогда
СтруктураКлюча = Новый Структура;
#КонецЕсли
Если СтруктураКлюча.Свойство(ИмяПоляНомерСтроки) Тогда
выхСтруктураЛокальногоКлючаСтроки = Новый Структура(ИмяПоляНомерСтроки);
ИначеЕсли СтруктураКлюча.Свойство(ИмяПоляПериод) Тогда
выхСтруктураЛокальногоКлючаСтроки = Новый Структура(ИмяПоляПериод);
Иначе
выхСтруктураЛокальногоКлючаСтроки = Неопределено;
КонецЕсли;
Если выхСтруктураЛокальногоКлючаСтроки <> Неопределено Тогда
ЗаполнитьЗначенияСвойств(выхСтруктураЛокальногоКлючаСтроки, ТекущаяСтрока);
КонецЕсли;
Если ОбъектМД = Неопределено Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.ВнешниеИсточникиДанных.ВнешнийИсточникДанных1.Таблицы.Таблица1;
#КонецЕсли
КонецЕсли;
Если Ложь
Или ЛиМетаданныеСсылочногоОбъектаЛкс(ОбъектМД)
Или ЛиКорневойТипЖурналаДокументовЛкс(ТипТаблицы)
Или ТипТаблицы = "Точки"
Тогда
Если ЛиТипСсылкиБДЛкс(ТипЗнч(ТекущаяСтрока), Ложь) Тогда
КлючОбъекта = ТекущаяСтрока;
Иначе
КлючОбъекта = ТекущаяСтрока[ИмяПоляСсылка];
КонецЕсли;
//ПолноеИмяТаблицы = Метаданные.НайтиПоТипу(ТипЗнч(КлючОбъекта)).ПолноеИмя(); // Описать зачем TODO
ИначеЕсли ЛиМетаданныеРегистраЛкс(ОбъектМД, Ложь) Тогда
Если Не ДляНабораЗаписейРегистраСведений Тогда
НайденыВсеПоляКлючаЗаписи = Истина;
Для Каждого КлючИЗначение Из СтруктураКлюча Цикл
Попытка
Пустышка = ТекущаяСтрока[КлючИЗначение.Ключ];
Исключение
НайденыВсеПоляКлючаЗаписи = Ложь;
Прервать;
КонецПопытки;
КонецЦикла;
КонецЕсли;
ЗаполнитьЗначенияСвойств(СтруктураКлюча, ТекущаяСтрока);
Если Ложь
Или ДляНабораЗаписейРегистраСведений
Или Не НайденыВсеПоляКлючаЗаписи
Тогда
//КлючОбъекта = ПолучитьНаборЗаписейПоКлючуЛкс(ПолноеИмяТаблицы, ТекущаяСтрока);
УдаляемыеКлючи = ОтобратьКоллекциюЛкс(СтруктураКлюча, "ТипЗнч(Э.Значение) = П1", "Э.Ключ", Тип("ОписаниеТипов"));
Для Каждого УдаляемыйКлюч Из УдаляемыеКлючи Цикл
СтруктураКлюча.Удалить(УдаляемыйКлюч);
КонецЦикла;
КлючОбъекта = ОбъектБДПоКлючуЛкс(ПолноеИмяТаблицы, СтруктураКлюча,, Ложь, ОбъектыНаСервере);
Иначе
Если ОбъектМД = Неопределено Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
КонецЕсли;
МенеджерРегистра = Новый (ИмяТипаИзПолногоИмениМДЛкс(ОбъектМД.ПолноеИмя(), "Менеджер"));
КлючОбъекта = МенеджерРегистра.СоздатьКлючЗаписи(СтруктураКлюча);
КонецЕсли;
ИначеЕсли ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда
ЗаполнитьЗначенияСвойств(СтруктураКлюча, ТекущаяСтрока);
// Мультиметка92305488234
КлючОбъекта = Новый Структура("ПолноеИмяТаблицы, Структура", ПолноеИмяТаблицы, СтруктураКлюча);
ИначеЕсли ЛиКорневойТипПоследовательностиЛкс(ТипТаблицы) Тогда
ЗаполнитьЗначенияСвойств(СтруктураКлюча, ТекущаяСтрока);
// Мультиметка92305488234
КлючОбъекта = Новый Структура("ПолноеИмяТаблицы, Структура", ПолноеИмяТаблицы, СтруктураКлюча);
Иначе
КлючОбъекта = Неопределено;
КонецЕсли;
Возврат КлючОбъекта;
КонецФункции
Функция КлючОбъектаКонстантыЛкс(Знач ИмяКонстанты, Знач РазрешитьОпасныеОперации = Истина) Экспорт
Если ирКэш.НомерВерсииПлатформыЛкс() >= 803013 Тогда
КлючОбъекта = Новый ("КонстантаКлючЗначения." + ИмяКонстанты);
ИначеЕсли РазрешитьОпасныеОперации Тогда
КлючОбъекта = Новый ("КонстантаМенеджерЗначения." + ИмяКонстанты); // Инициализация модуля. Есть риск ошибок компиляции на клиенте
КонецЕсли;
Возврат КлючОбъекта;
КонецФункции
Функция СообщенияПользователюОтФоновогоЗаданияЛкс(Знач ФоновоеЗадание, УдалятьПолученные = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
ФоновоеЗадание = ФоновыеЗадания.Выполнить();
#КонецЕсли
СообщенияПользователю = ФоновоеЗадание.ПолучитьСообщенияПользователю(УдалятьПолученные);
// Антибаг платформы 8.2.14
Если СообщенияПользователю = Неопределено Тогда
СообщенияПользователю = Новый Массив;
КонецЕсли;
Возврат СообщенияПользователю;
КонецФункции
Функция СоединитьСообщенияПользователюЛкс(Знач СообщенияОбъекта) Экспорт
СообщенияОбработки = Новый ЗаписьXML;
СообщенияОбработки.УстановитьСтроку("");
Для Каждого СообщениеОбъекта Из СообщенияОбъекта Цикл
#Если Сервер И Не Сервер Тогда
СообщениеОбъекта = Новый СообщениеПользователю;
#КонецЕсли
СообщенияОбработки.ЗаписатьБезОбработки(СообщениеОбъекта.Текст + Символы.ПС);
КонецЦикла;
ТекстСообщений = СообщенияОбработки.Закрыть();
Возврат ТекстСообщений;
КонецФункции
Функция ОжидатьЗавершенияФоновойОперацииЛкс(ФоновоеЗадание, ЭтаФорма = Неопределено, ПодключитьОбработчикОтменыЗадания = Истина, ФормаЗадания = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору();
#КонецЕсли
ИдентификаторФоновогоЗадания = ФоновоеЗадание.УникальныйИдентификатор;
#Если Клиент Тогда
Если ПодключитьОбработчикОтменыЗадания Тогда
#Если Сервер И Не Сервер Тогда
ОтменитьФоновоеЗаданиеОтложенноЛкс();
#КонецЕсли
ирКлиент.ПодключитьОбработчикОжиданияСПараметрамиЛкс("ОтменитьФоновоеЗаданиеОтложенноЛкс", Новый Структура("ИдентификаторФоновогоЗадания", ИдентификаторФоновогоЗадания));
КонецЕсли;
СостояниеЛкс("Выполняем фоновое задание", Истина);
#КонецЕсли
Если ЭтаФорма <> Неопределено Тогда
ПрефиксКлючаПотока = ПрефиксКлючаПотокаЛкс(ЭтаФорма);
КонецЕсли;
ПериодОбновленияФормы = 2;
МоментОбновления = ТекущаяДата() - ПериодОбновленияФормы;
ЭтоПерваяПроверка = Истина;
Пока Истина Цикл
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторФоновогоЗадания);
Если ТекущаяДата() - МоментОбновления >= ПериодОбновленияФормы Тогда
ОбработатьСообщенияФоновогоЗаданияЛкс(ФоновоеЗадание, ФормаЗадания, ПрефиксКлючаПотока, Ложь);
Если ФормаЗадания <> Неопределено Тогда
ФормаЗадания.ОбновитьСостояниеЗадания(ФоновоеЗадание);
КонецЕсли;
МоментОбновления = ТекущаяДата();
КонецЕсли;
Если ФоновоеЗадание.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
Прервать;
КонецЕсли;
Длительность = ?(ЭтоПерваяПроверка, 50, 100);
ПаузаМиллисекундЛкс(Длительность);
ЭтоПерваяПроверка = Ложь;
КонецЦикла;
#Если Клиент Тогда
ирКлиент.ОтлючитьОбработчикОжиданияСПараметрамиЛкс();
#КонецЕсли
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.ЗавершеноАварийно Тогда
ИнформацияОбОшибке = ФоновоеЗадание.ИнформацияОбОшибке;
ТекстСообщения = "Фоновое задание завершено аварийно! Описание ошибки получить не удалось";
#Если Клиент Тогда
Если ИнформацияОбОшибке <> Неопределено Тогда
ПоказатьИнформациюОбОшибке(ИнформацияОбОшибке);
Иначе
СообщитьЛкс(ТекстСообщения, СтатусСообщения.Внимание);
КонецЕсли;
#Иначе
Если ИнформацияОбОшибке <> Неопределено Тогда
ВызватьИсключение ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке);
Иначе
ВызватьИсключение ТекстСообщения;
КонецЕсли;
#КонецЕсли
Результат = Ложь;
Иначе
Результат = Истина;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Обработать сообщения фонового задания лкс
//
// Параметры:
// ФоновоеЗадание - -
//
// Возвращаемое значение:
// - Булево - был ли изменен текст состояния
//
Функция ОбработатьСообщенияФоновогоЗаданияЛкс(Знач ФоновоеЗадание, ФормаЗадания = Неопределено, ПрефиксКлючаПотока = "", АсинхронныйРежим = Истина) Экспорт
#Если Сервер И Не Сервер Тогда
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору();
#КонецЕсли
Результат = Ложь;
СообщенияПользователю = СообщенияПользователюОтФоновогоЗаданияЛкс(ФоновоеЗадание, Истина);
Если СообщенияПользователю <> Неопределено Тогда
ТекстСостояния = "";
МаркерПотока = "#Поток ";
РазделительМаркера = ": ";
Для Каждого СообщениеПользователю Из СообщенияПользователю Цикл
#Если Сервер И Не Сервер Тогда
СообщениеПользователю = Новый СообщениеПользователю;
#КонецЕсли
ТекстСообщения = СообщениеПользователю.Текст;
НомерПотока = Неопределено;
Если СтрНачинаетсяСЛкс(ТекстСообщения, МаркерПотока) Тогда
НомерПотока = ТекстМеждуМаркерамиЛкс(ТекстСообщения, МаркерПотока, РазделительМаркера, Ложь,, Истина);
ТекстСообщения = Сред(ТекстСообщения, Найти(ТекстСообщения, РазделительМаркера) + СтрДлина(РазделительМаркера));
КонецЕсли;
МассивИндикаторов = Неопределено;
Если СтрНачинаетсяСЛкс(ТекстСообщения, "#Индикатор-") Тогда
МассивИндикаторов = ЗначениеИзСтрокиВнутрЛкс(ТекстМеждуМаркерамиЛкс(СообщениеПользователю.Текст, "#Индикатор-"));
КонецЕсли;
Если МассивИндикаторов = Неопределено Тогда
Если ФормаЗадания <> Неопределено Тогда
#Если Клиент Тогда
ТекстовыйДокумент = ФормаЗадания.ЭлементыФормы.ПолеТекста;
ТекстовыйДокумент.ДобавитьСтроку(СообщениеПользователю.Текст);
ПолеТекста = ирКлиент.ОболочкаПоляТекстаЛкс(ТекстовыйДокумент);
#Если Сервер И Не Сервер Тогда
ПолеТекста = Обработки.ирОболочкаПолеТекста.Создать();
#КонецЕсли
ПолеТекста.ПоказатьПоследнююСтроку();
#КонецЕсли
Иначе
СообщитьЛкс(СообщениеПользователю.Текст,, Истина);
СообщениеПользователю.Сообщить();
КонецЕсли;
Иначе
Индикатор = ОбновитьТекстСостоянияВсехИндикаторовЛкс(МассивИндикаторов);
Если НомерПотока = Неопределено Тогда
ТекстСостояния = Индикатор.ТекстСостояния;
ИначеЕсли ФормаЗадания <> Неопределено Тогда
СтрокаПотока = ФормаЗадания.Потоки.Найти(НомерПотока, "НомерПотока");
Если СтрокаПотока = Неопределено Тогда
СтрокаПотока = ФормаЗадания.Потоки.Добавить();
СтрокаПотока.НомерПотока = НомерПотока;
КонецЕсли;
СтрокаПотока.Состояние = Индикатор.ТекстСостояния;
КонецЕсли;
КонецЕсли;
КонецЦикла;
#Если Сервер И Не Сервер Тогда
ОбработатьПорциюОбъектовЛкс()
#КонецЕсли
Если ЗначениеЗаполнено(ТекстСостояния) Тогда
Если АсинхронныйРежим И ФормаЗадания <> Неопределено Тогда
ФормаЗадания.Заголовок = ТекстСостояния;
//ФормаЗадания.Обновить(); // Не дает эффекта в синхронном режиме
Иначе
СостояниеЛкс(ТекстСостояния, Истина);
КонецЕсли;
Результат = Истина;
КонецЕсли;
КонецЕсли;
Если Истина
И ФормаЗадания <> Неопределено
И ФормаЗадания.Потоки.Количество() > 0
Тогда
ФоновыеПотоки = ФоновыеЗаданияПотоковЛкс();
НачальноеКоличество = ФормаЗадания.Потоки.Количество();
Для Счетчик = 1 По НачальноеКоличество Цикл
СтрокаПотока = ФормаЗадания.Потоки[НачальноеКоличество - Счетчик];
ФоновоеЗаданиеПотокаАктивно = Ложь;
Для Каждого ФоновыйПоток Из ФоновыеПотоки Цикл
#Если Сервер И Не Сервер Тогда
ФоновыйПоток = ФоновыеЗадания.Выполнить();
#КонецЕсли
Если ФоновыйПоток.Ключ = ПрефиксКлючаПотока + "." + СтрокаПотока.НомерПотока Тогда
ФоновоеЗаданиеПотокаАктивно = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ФоновоеЗаданиеПотокаАктивно Тогда
ФормаЗадания.Потоки.Удалить(СтрокаПотока);
КонецЕсли;
КонецЦикла;
ФормаЗадания.Обновить();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПредставлениеПериодаЛкс(НачалоПериода, КонецПериода) Экспорт
ПредставлениеОтбора = "";
Если ЗначениеЗаполнено(НачалоПериода) Тогда
ПредставлениеОтбора = ПредставлениеОтбора + " с " + НачалоПериода;
КонецЕсли;
Если ЗначениеЗаполнено(КонецПериода) Тогда
Если Формат(НачалоПериода, "ДФ=dd.MM.yyyy") = Формат(КонецПериода, "ДФ=dd.MM.yyyy") Тогда
Строка = Формат(КонецПериода, "ДЛФ=T");
Иначе
Строка = "" + КонецПериода;
КонецЕсли;
ПредставлениеОтбора = ПредставлениеОтбора + " по " + Строка;
КонецЕсли;
Возврат ПредставлениеОтбора;
КонецФункции
Функция СтруктураХраненияТаблицыБДЛкс(Знач ПолноеИмяТаблицыБД, Знач ТипТаблицы = "", ОбъектМД = Неопределено, выхИмяОстаток = "", Знач ЛиИменаБазыДанных = Истина) Экспорт
Если Не ЗначениеЗаполнено(ТипТаблицы) Тогда
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицыБД);
КонецЕсли;
Если ОбъектМД = Неопределено Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД, Истина);
КонецЕсли;
ФильтрМетаданных = Новый Массив;
Если ОбъектМД = Неопределено Тогда
// Константы
// Так будет всегда пустой результат
Иначе
РодительМД = ОбъектМД.Родитель();
Если Истина
И ТипТаблицы <> "Перерасчет"
И ТипТаблицы <> "Внешняя"
И ТипЗнч(РодительМД) <> Тип("ОбъектМетаданныхКонфигурация")
Тогда
ОбъектМДФильтра = РодительМД;
Иначе
ОбъектМДФильтра = ОбъектМД;
КонецЕсли;
ФильтрМетаданных.Добавить(ОбъектМДФильтра);
КонецЕсли;
//Если ТипТаблицы = "ДвиженияССубконто" Тогда
// ПолноеИмяТаблицыБД = Лев(ПолноеИмяТаблицыБД, СтрДлина(ПолноеИмяТаблицыБД) - СТрДлина(".ДвиженияССубконто"));
//КонецЕсли;
Если Ложь // Все таки отключил
И Метаданные.Справочники.Количество() < 300 // Заполняем весь кэш сразу, если уложимся за секунду
И ирКэш.НомерВерсииПлатформыЛкс() >= 803016
Тогда
СтруктураХраненияБД = ирКэш.СтруктураХраненияБДЛкс(ЛиИменаБазыДанных); // 0.5сек в моей базе, 2.5сек в рабочей базе
ДобавитьИндексВТаблицуЛкс(СтруктураХраненияБД, "ИмяТаблицы");
Иначе
// https://partners.v8.1c.ru/forum/topic/1751092
// https://bugboard.v8.1c.ru/error/000046221.html
// В этих версиях платформы будут компилироваться модули менеджеров. Поэтому получаем структуру хранения узко
СтруктураХраненияБД = ПолучитьСтруктуруХраненияБазыДанных(ФильтрМетаданных, ЛиИменаБазыДанных); // В цикле по всем из редактора объекта - 4сек в моей базе
ПеревестиКолонкиСтруктурыХраненияБДТаблицыЛкс(СтруктураХраненияБД);
КонецЕсли;
СтрокиСтруктурыТаблицы = СтруктураХраненияБД.НайтиСтроки(Новый Структура("ИмяТаблицы", ПолноеИмяТаблицыБД));
Если Истина
И СтрокиСтруктурыТаблицы.Количество() = 0
И ТипТаблицы = "ВиртуальнаяТаблица"
Тогда
Если ПоследнийФрагментЛкс(ПолноеИмяТаблицыБД) = "Субконто" Тогда
// 8.3.20- https://www.hostedredmine.com/issues/992432
Назначение = "ЗначенияСубконто";
Иначе
Назначение = "Основная";
КонецЕсли;
СтрокиСтруктурыТаблицы = СтруктураХраненияБД.НайтиСтроки(Новый Структура("Назначение", Назначение));
выхИмяОстаток = ПеревестиСтроку("Остаток");
КонецЕсли;
Возврат СтрокиСтруктурыТаблицы;
КонецФункции
Функция СтруктураХраненияОсновнойТаблицыМДЛкс(Знач ПолноеИмяМД) Экспорт
//СтруктураХраненияПолей = ирКэш.СтруктураХраненияБДЛкс().НайтиСтроки(Новый Структура("Назначение, Метаданные", "Основная", ПолноеИмяМД))[0].Поля;
ФильтрМетаданных = Новый Массив;
ФильтрМетаданных.Добавить(ПолноеИмяМД);
СтруктураХраненияТаблиц = ПолучитьСтруктуруХраненияБазыДанных(ФильтрМетаданных);
ПеревестиКолонкиСтруктурыХраненияБДТаблицыЛкс(СтруктураХраненияТаблиц);
Назначение = НазначениеОсновнойТаблицыХраненияМДЛкс(ПолноеИмяМД);
СтруктураХраненияТаблицы = СтруктураХраненияТаблиц.НайтиСтроки(Новый Структура("Назначение, Метаданные", Назначение, ПолноеИмяМД))[0];
ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(СтруктураХраненияТаблицы.Поля);
Возврат СтруктураХраненияТаблицы;
КонецФункции
Функция НазначениеОсновнойТаблицыХраненияМДЛкс(Знач ПолноеИмяМД) Экспорт
СловоКонстанта = ПеревестиСтроку("Константа");
Если СтрНачинаетсяСЛкс(ПолноеИмяМД, СловоКонстанта) Тогда
Назначение = СловоКонстанта;
Иначе
Назначение = ПеревестиСтроку("Основная");
КонецЕсли;
Возврат Назначение;
КонецФункции
Функция ОсновнойПорядокТаблицыБДЛкс(Знач ПолноеИмяТаблицы, Знач СтрокаПорядка = "", Знач НастройкаПорядка = Неопределено, Знач СтруктураХраненияТаблицы = Неопределено,
Знач СортироватьДатыПоУбыванию = Ложь) Экспорт
Построитель = Новый ПостроительЗапроса("ВЫБРАТЬ * ИЗ " + ПолноеИмяТаблицы + " КАК Т");
ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы);
Если СтруктураХраненияТаблицы = Неопределено Тогда
ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы);
Если Ложь
Или ОбъектМД = Неопределено
Или ТипТаблицы = "Внешняя"
Или ТипТаблицы = "Изменения"
Или ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы)
Тогда
Возврат Построитель;
КонецЕсли;
СтруктураХраненияТаблицы = СтруктураХраненияОсновнойТаблицыМДЛкс(ОбъектМД.ПолноеИмя());
КонецЕсли;
выхСортировкаПоДате = Ложь;
Построитель.ЗаполнитьНастройки();
ПорядокТаблицы = Построитель.Порядок;
Если ЛиКорневойТипПоследовательностиЛкс(ТипТаблицы) Тогда
СтрокаИндекса = СтруктураХраненияТаблицы.Индексы.Найти("ByDims", "ИмяИндексаХранения");
Если СтрокаИндекса <> Неопределено Тогда
СтрокаПорядка = СтрСоединитьЛкс(СтрокаИндекса.Поля.ВыгрузитьКолонку("ИмяПоля"));
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(СтрокаПорядка) Тогда
ПредопределенныеПоля = Новый Массив();
Если ТипТаблицы = "ПланСчетов" Тогда
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Код"));
КонецЕсли;
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Наименование"));
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Дата"));
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Период"));
ПредопределенныеПоля.Добавить("ДатаИзменения");
ПредопределенныеПоля.Добавить("ДатаСоздания");
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Номер"));
ПредопределенныеПоля.Добавить(ПеревестиСтроку("Код"));
ПеревестиКолонкиСтруктурыХраненияБДИндексыЛкс(СтруктураХраненияТаблицы.Индексы);
Для Каждого ПредопределенноеПоле Из ПредопределенныеПоля Цикл
Если НастройкаПорядка <> Неопределено Тогда
ЭлементПорядка = НастройкаПорядка.Найти(ПредопределенноеПоле);
Если ЭлементПорядка = Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Для Каждого ИндексТаблицыБД Из СтруктураХраненияТаблицы.Индексы Цикл
ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(ИндексТаблицыБД.Поля);
Если ИндексТаблицыБД.Поля[0].ИмяПоля = ПредопределенноеПоле Тогда
Если ЭлементПорядка <> Неопределено Тогда
ЭлементПорядка.Доступность = Истина;
КонецЕсли;
СтрокаПорядка = ПредопределенноеПоле;
Прервать;
КонецЕсли;
КонецЦикла;
Если Истина
И ЗначениеЗаполнено(СтрокаПорядка)
И (НастройкаПорядка = Неопределено Или ЭлементПорядка.Доступность)
Тогда
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЗначениеЗаполнено(СтрокаПорядка) Тогда
ПорядокТаблицы.Установить(СтрокаПорядка);
Если СортироватьДатыПоУбыванию Тогда
ЭлементПорядкаТипаДата = ЭлементПорядкаТипаДатаЛкс(ПолноеИмяТаблицы, ПорядокТаблицы);
Если ЭлементПорядкаТипаДата <> Неопределено Тогда
ЭлементПорядкаТипаДата.Направление = НаправлениеСортировки.Убыв;
КонецЕсли;
КонецЕсли;
КонецЕсли;
//Возврат ПорядокТаблицы; // Так возвращается пустой порядок всегда
Возврат Построитель;
КонецФункции
Функция ЭлементПорядкаТипаДатаЛкс(Знач ПолноеИмяТаблицы, Знач ПорядокТаблицы) Экспорт
#Если Сервер И Не Сервер Тогда
ПорядокТаблицы = Новый ПостроительЗапроса;
ПорядокТаблицы = ПорядокТаблицы.Порядок;
#КонецЕсли
Если Истина
И ПорядокТаблицы.Количество() > 0
И ирКэш.ПоляТаблицыБДЛкс(ПолноеИмяТаблицы).Найти(ПорядокТаблицы[0].Имя, "Имя").ТипЗначения.СодержитТип(Тип("Дата"))
Тогда
ЭлементПорядкаТипаДата = ПорядокТаблицы[0];
КонецЕсли;
Возврат ЭлементПорядкаТипаДата;
КонецФункции
Процедура ПоместитьПереданныйКэшВоВременноеХранищеЛкс(Знач ОбщиеПараметрыОбработки)
#Если Сервер И Не Сервер Тогда
ОбщиеПараметрыОбработки = Новый Структура;
#КонецЕсли
Если ОбщиеПараметрыОбработки.Свойство("_Кэш") Тогда
ирКэш.ПараметрыСеансаЛкс().ПереданныйКэш = ПоместитьВоВременноеХранилище(ОбщиеПараметрыОбработки._Кэш, Новый УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьПереданныйКэшВСтруктуруЛкс(Знач Структура)
#Если Сервер И Не Сервер Тогда
Структура = Новый Структура;
#КонецЕсли
ТаблицаВсехТаблицБД = ТаблицаВсехТаблицБДБезОжиданияЛкс();
Если ТаблицаВсехТаблицБД <> Неопределено Тогда
Структура.Вставить("_Кэш", Новый Структура("ТаблицаВсехТаблицБД", ТаблицаВсехТаблицБД));
КонецЕсли;
КонецПроцедуры
Функция НайтиПутьКДаннымПоляТаблицыФормыЛкс(Знач СтрокаИлиКоллекция, Знач ИмяПоля, выхЗначениеПоля = Неопределено) Экспорт
Если ТипЗнч(СтрокаИлиКоллекция) = Тип("ТаблицаФормы") Тогда
СтрокаИлиКоллекция = ДанныеЭлементаФормыЛкс(СтрокаИлиКоллекция);
КонецЕсли;
ДлинаСтроки = СтрДлина(ИмяПоля);
ПутьКДанным = "";
РежимКоллекции = ЛиДанныеФормыСВозможностьюПоискаЛкс(СтрокаИлиКоллекция);
Пока ДлинаСтроки > 0 Цикл
ПроверяемоеИмя = Прав(ИмяПоля, ДлинаСтроки);
ДлинаСтроки = ДлинаСтроки - 1;
Если РежимКоллекции Тогда
Попытка
СтрокаИлиКоллекция.НайтиСтроки(Новый Структура(ПроверяемоеИмя));
ПутьКДанным = ПроверяемоеИмя;
Прервать;
Исключение
Продолжить;
КонецПопытки;
Иначе
Попытка
выхЗначениеПоля = СтрокаИлиКоллекция[ПроверяемоеИмя]; // СправочникСсылка
ПутьКДанным = ПроверяемоеИмя;
Прервать;
Исключение
Продолжить;
КонецПопытки;
КонецЕсли;
КонецЦикла;
Если Не ЗначениеЗаполнено(ПутьКДанным) Тогда
ДлинаИмениДочернегоРеквизита = 0;
Пока Не ЗначениеЗаполнено(ПутьКДанным) И ДлинаИмениДочернегоРеквизита < СтрДлина(ИмяПоля) Цикл
ДлинаИмениДочернегоРеквизита = ДлинаИмениДочернегоРеквизита + 1;
Если "_" <> Сред(ИмяПоля, СтрДлина(ИмяПоля) - ДлинаИмениДочернегоРеквизита + 1, 1) Тогда
Продолжить;
КонецЕсли;
ИмяРеквизита = Лев(ИмяПоля, СтрДлина(ИмяПоля) - ДлинаИмениДочернегоРеквизита);
ИмяДочернегоРеквизита = Прав(ИмяПоля, ДлинаИмениДочернегоРеквизита - 1);
ПутьКДанным = НайтиПутьКДаннымПоляТаблицыФормыЛкс(СтрокаИлиКоллекция, ИмяРеквизита, выхЗначениеПоля);
Если Метаданные.ВариантВстроенногоЯзыка = Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский Тогда
ИмяДочернегоРеквизита = ПеревестиВРусский(ИмяДочернегоРеквизита); // http://www.hostedredmine.com/issues/880938
КонецЕсли;
Если ЗначениеЗаполнено(ПутьКДанным) И выхЗначениеПоля <> Неопределено Тогда
ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(выхЗначениеПоля.Метаданные().ПолноеИмя());
Если ПоляТаблицыБД.Найти(ИмяДочернегоРеквизита, "Имя") = Неопределено Тогда
ПутьКДанным = Неопределено;
Иначе
ПутьКДанным = ПутьКДанным + "." + ИмяДочернегоРеквизита;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат ПутьКДанным;
КонецФункции
// Для управляемой формы возвращает путь относительно родителя и может вернуть ложный путь
Функция ПутьКДаннымКолонкиТабличногоПоляЛкс(Знач ТабличноеПоле, Колонка = Неопределено) Экспорт
#Если Сервер И Не Сервер Тогда
ТабличноеПоле = Новый ТабличноеПоле;
#КонецЕсли
Если Колонка = Неопределено Тогда
#Если Клиент Тогда
Колонка = ирКлиент.ТабличноеПолеТекущаяКолонкаЛкс(ТабличноеПоле);
#КонецЕсли
КонецЕсли;
Если Ложь
Или ТипЗнч(Колонка) = Тип("ПолеФормы")
Или ТипЗнч(Колонка) = Тип("Структура") // пользовательская колонка из СтруктураФормы
Тогда
ПутьКДанным = ПутьКДаннымЭлементаУправляемойФормыЛкс(Колонка, Истина);
Если Не ЗначениеЗаполнено(ПутьКДанным) Тогда
ПутьКДанным = Колонка.Имя;
Если Найти(ПутьКДанным, ТабличноеПоле.Имя) = 1 Тогда
ДанныеТаблицы = ДанныеЭлементаФормыЛкс(ТабличноеПоле);
ПутьКДанным = Сред(ПутьКДанным, СтрДлина(ТабличноеПоле.Имя) + 1);
КонецЕсли;
СтрокаИлиКоллекция = Неопределено;
Если ТабличноеПоле.ТекущиеДанные = Неопределено Тогда
Если ЛиДанныеФормыСВозможностьюПоискаЛкс(ДанныеТаблицы) Тогда
СтрокаИлиКоллекция = ДанныеТаблицы;
КонецЕсли;
Иначе
СтрокаИлиКоллекция = ТабличноеПоле.ТекущиеДанные;
КонецЕсли;
Если СтрокаИлиКоллекция <> Неопределено Тогда
ПутьКДанным = НайтиПутьКДаннымПоляТаблицыФормыЛкс(СтрокаИлиКоллекция, ПутьКДанным);
КонецЕсли;
КонецЕсли;
ИначеЕсли ТипЗнч(Колонка) = Тип("ГруппаФормы") Тогда
ПутьКДанным = "";
ИначеЕсли Колонка <> Неопределено Тогда
//! Колонка = 0 // КолонкаТабличногоПоля
ПутьКДанным = Колонка.Данные;
Если Не ЗначениеЗаполнено(ПутьКДанным) Тогда
ПутьКДанным = Колонка.ДанныеФлажка;
КонецЕсли;
Если Не ЗначениеЗаполнено(ПутьКДанным) Тогда
Если Ложь
Или ТипЗнч(ТабличноеПоле.Значение) = Тип("ТаблицаЗначений")
Или ТипЗнч(ТабличноеПоле.Значение) = Тип("ДеревоЗначений")
Тогда
//! Колонка = 0 // РасширениеКолонкиТабличногоПоляДереваЗначений
ПутьКДанным = Колонка.ДанныеКартинки;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(ПутьКДанным) Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(ТабличноеПоле.Значение));
Если Истина
И ОбъектМД <> Неопределено
И ЛиКорневойТипПеречисленияЛкс(ПервыйФрагментЛкс(ОбъектМД.ПолноеИмя()))
Тогда
ПутьКДанным = "Ссылка";
КонецЕсли;
КонецЕсли;
Если ТипЗнч(ТабличноеПоле.Значение) = Тип("НастройкиКомпоновкиДанных") Тогда
// Здесь ПутьКДанным = "СтруктураОтчета" - виртуальное имя
ПутьКДанным = "";
ИначеЕсли Ложь
Или ПутьКДанным = "ПравоеЗначениеДляКраткогоОтображенияЭлемента"
Тогда
ПутьКДанным = "ПравоеЗначение";
ИначеЕсли Ложь
Или ПутьКДанным = "ВидыСравненияДляКраткогоОтображенияЭлемента"
Тогда
ПутьКДанным = "ВидСравнения";
ИначеЕсли Ложь
Или ПутьКДанным = "ЛевоеЗначениеДляКраткогоОтображенияЭлемента"
Тогда
ПутьКДанным = "ЛевоеЗначение";
КонецЕсли;
КонецЕсли;
Возврат ПутьКДанным;
КонецФункции
Функция ИтогКолонкиТабличногоПоляЛкс(Знач КопияТаблицы, Знач ИмяКолонки, Знач КолонкиКоллекции = Неопределено) Экспорт
СуммаКолонки = Неопределено;
ИмяНомерСтроки = ирОбщий.ПеревестиСтроку("НомерСтроки");
Если Истина
И ЗначениеЗаполнено(ИмяКолонки)
И ИмяКолонки <> ИмяНомерСтроки
//И КоллекцияСтрок.Количество() > 0
И КопияТаблицы.Количество() > 0
Тогда
Если КолонкиКоллекции = Неопределено Тогда
КолонкиКоллекции = КопияТаблицы.Колонки;
КонецЕсли;
ТипЗначения = КолонкиКоллекции.Найти(ИмяКолонки).ТипЗначения;
Если Ложь
Или ТипЗначения.СодержитТип(Тип("Число"))
Или ТипЗначения = Новый ОписаниеТипов("Булево")
Тогда
СуммаКолонки = КопияТаблицы.Итог(ИмяКолонки);
ИначеЕсли Истина
И ТипЗначения = Новый ОписаниеТипов("Булево, Null")
И ТипЗнч(КопияТаблицы) = Тип("ТаблицаЗначений")
//И Не ЭтоКоллекцияСМетаданными
И КопияТаблицы.Количество() < 10000 // Сужение типа - долгая операция
Тогда
//Если ТипЗнч(КопияТаблицы) <> Тип("ТаблицаЗначений") Тогда
// КопияТаблицы = ТаблицаИлиДеревоЗначенийИзТаблицыФормыСКоллекциейЛкс(ТабличноеПоле,,,,,, ЭтаФорма);
//КонецЕсли;
// Если у колонки составной тип, то Итог() не будет считать булевы значения
КопияКолонки = ТаблицаСКолонкамиБезТипаNullЛкс(КопияТаблицы,, ИмяКолонки);
СуммаКолонки = КопияКолонки.Итог(ИмяКолонки);
КонецЕсли;
КонецЕсли;
Возврат СуммаКолонки;
КонецФункции
// .
// Параметры:
// Коллекция - Коллекция -
// ИменаСвойств - Строка - имена числовых свойств через запятую (максимум 5 шт), по которым искать лучшее значение, для массива чисел не используется
// Максимум - Булево - лучшим считать максимальное значение, иначе - минимальное
// СтруктураОтбора - Структура - отбор для коллекции с методом НайтиСтроки()
// Возвращаемое значение:
// Произвольнй - для случая одного свойства, лучший элемент коллекции
// Структура - для случая нескольких свойств, ключом является имя свойства, значением - лучший элемент для этого свойства
Функция ЛучшиеЭлементыКоллекцииЛкс(Знач Коллекция, Знач ИменаСвойств = "", Знач Максимум = Истина, Знач СтруктураОтбора = Неопределено) Экспорт
// Способ через построитель - долгий 2мс
Если СтруктураОтбора <> Неопределено Тогда
Коллекция = Коллекция.НайтиСтроки(СтруктураОтбора);
КонецЕсли;
НачальноеЗначение = ?(Максимум, -1, 1) * 99999999999;
Если ПустаяСтрока(ИменаСвойств) Тогда
ЛучшиеЭлементы = НачальноеЗначение;
Иначе
ЛучшиеЗначения = Новый Структура(ИменаСвойств, НачальноеЗначение, НачальноеЗначение, НачальноеЗначение, НачальноеЗначение, НачальноеЗначение);
ЛучшиеЭлементы = Новый Структура(ИменаСвойств, Неопределено, Неопределено, Неопределено, Неопределено, Неопределено);
КонецЕсли;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Каждого Строка Из Коллекция Цикл
Если ПустаяСтрока(ИменаСвойств) Тогда
Если Ложь
Или Максимум И ЛучшиеЭлементы < Строка
Или Не Максимум И ЛучшиеЭлементы > Строка
Тогда
ЛучшиеЭлементы = Строка;
КонецЕсли;
Иначе
Для Каждого КлючИЗначение Из ЛучшиеЭлементы Цикл
Если Ложь
Или Максимум И ЛучшиеЗначения[КлючИЗначение.Ключ] < Строка[КлючИЗначение.Ключ]
Или Не Максимум И ЛучшиеЗначения[КлючИЗначение.Ключ] > Строка[КлючИЗначение.Ключ]
Тогда
ЛучшиеЗначения[КлючИЗначение.Ключ] = Строка[КлючИЗначение.Ключ];
ЛучшиеЭлементы[КлючИЗначение.Ключ] = Строка;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Каждого Строка Из Коллекция Цикл Если ПустаяСтрока(ИменаСвойств) Тогда Если Ложь Или Максимум И ЛучшиеЭлементы < Строка Или Не Максимум И ЛучшиеЭлементы > Строка Тогда ЛучшиеЭлементы = Строка; КонецЕсли; Иначе Для Каждого КлючИЗначение Из ЛучшиеЭлементы Цикл Если Ложь Или Максимум И ЛучшиеЗначения[КлючИЗначение.Ключ] < Строка[КлючИЗначение.Ключ] Или Не Максимум И ЛучшиеЗначения[КлючИЗначение.Ключ] > Строка[КлючИЗначение.Ключ] Тогда ЛучшиеЗначения[КлючИЗначение.Ключ] = Строка[КлючИЗначение.Ключ]; ЛучшиеЭлементы[КлючИЗначение.Ключ] = Строка; КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла;
КонецЕсли;
Если Истина
И ЗначениеЗаполнено(ИменаСвойств)
И ЛучшиеЭлементы.Количество() = 1
Тогда
ЛучшиеЭлементы = ЛучшиеЭлементы[ИменаСвойств];
КонецЕсли;
Возврат ЛучшиеЭлементы;
КонецФункции
// Функция - Прочитать результат фонового задания лкс
//
// Параметры:
// АдресРезультата - -
// ФормаРезультата - см. Обработка.ирПлатформа.Форма.РезультатФоновогоЗадания - с ее идентификатором создавался адрес временного хранилища
//
// Возвращаемое значение:
// -
//
Функция ПрочитатьРезультатФоновогоЗаданияЛкс(Знач АдресРезультата, Знач ФормаРезультата = Неопределено) Экспорт
Результат = ПолучитьИзВременногоХранилища(АдресРезультата);
Если Результат = Null И ФормаРезультата <> Неопределено Тогда
// Антибаг платформы https://www.hostedredmine.com/issues/884756
Если ТипЗнч(ФормаРезультата) = ТипУправляемаяФормаЛкс() Тогда
ФормаРезультата.ОбновитьВременноеХранилище(АдресРезультата); // Тяжелая операция
Результат = ПолучитьИзВременногоХранилища(АдресРезультата);
КонецЕсли;
Если Результат = Null Тогда
СообщитьЛкс("Не удалось получить результат фонового задания. Возможные причины: https://www.hostedredmine.com/issues/884756, https://bugboard.v8.1c.ru/error/000133136, https://bugboard.v8.1c.ru/error/000158034 ."
+ " Асинхронность отключена до конца сеанса.", СтатусСообщения.Внимание);
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
мПлатформа.АсинхронностьЗапрещена = Истина;
КонецЕсли;
КонецЕсли;
УдалитьИзВременногоХранилища(АдресРезультата);
Возврат Результат
КонецФункции
Функция СтрокаТабличнойКоллекцииПоКлючуЛкс(Знач ТабличнаяКоллекция, Знач КлючТекущейСтроки) Экспорт
Если ТипЗнч(КлючТекущейСтроки) = Тип("Структура") Тогда
#Если Сервер И Не Сервер Тогда
КлючТекущейСтроки = Новый Структура;
#КонецЕсли
НайденныеСтроки = Новый Массив;
Если ТипЗнч(ТабличнаяКоллекция) = Тип("ДеревоЗначений") Тогда
НайденныеСтроки = ТабличнаяКоллекция.Строки.НайтиСтроки(КлючТекущейСтроки, Истина);
Иначе
//! ТабличнаяКоллекция = 0 // ТаблицаЗначений
ИмяНомерСтроки = ПеревестиСтроку("НомерСтроки");
Если Истина
И КлючТекущейСтроки.Количество() = 1
И КлючТекущейСтроки.Свойство(ИмяНомерСтроки)
И ТабличнаяКоллекция.Колонки.Найти(ИмяНомерСтроки) = Неопределено
Тогда
НомерСтроки = КлючТекущейСтроки[ИмяНомерСтроки];
Если Истина
И ТипЗнч(НомерСтроки) = Тип("Число")
И ТабличнаяКоллекция.Количество() >= НомерСтроки
Тогда
НайденныеСтроки.Добавить(ТабличнаяКоллекция[НомерСтроки - 1]);
КонецЕсли;
Иначе
НайденныеСтроки = ТабличнаяКоллекция.НайтиСтроки(КлючТекущейСтроки);
КонецЕсли;
КонецЕсли;
Если НайденныеСтроки.Количество() > 0 Тогда
Строка = НайденныеСтроки[0];
КонецЕсли;
Иначе
Если ТабличнаяКоллекция.Количество() > КлючТекущейСтроки Тогда
Строка = ТабличнаяКоллекция[КлючТекущейСтроки];
КонецЕсли;
КонецЕсли;
Возврат Строка;
КонецФункции
// Только 8.3+
Функция ТаблицаДанныхВыбораМенеджераЛкс(Знач ОбъектМД, Знач Параметры, Знач СхемаКомпоновки, Знач ОтображаемоеЧислоРезультатов = 50, Знач Компоновщик = Неопределено,
РежимПоискаПоСловам = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Параметры = Новый Структура;
ОбъектМД = Метаданные.Справочники.Валюты;
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
#КонецЕсли
РежимПоискаПоСловам = ирКэш.КоличествоСтрокВТаблицеБДЛкс(ОбъектМД.ПолноеИмя()) < 500000; // Такой порог вроде бы обеспечивает предельное время 1 сек https://www.hostedredmine.com/issues/963529
НастройкаКомпоновки = СхемаКомпоновки.НастройкиПоУмолчанию;
ИмяСсылка = ПеревестиСтроку("Ссылка");
ИмяЭтоГруппа = ПеревестиСтроку("ЭтоГруппа");
Если Параметры.Отбор <> Неопределено Тогда
Для Каждого КлючИЗначение Из Параметры.Отбор Цикл
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(НастройкаКомпоновки.Отбор, КлючИЗначение.Ключ, КлючИЗначение.Значение);
КонецЦикла;
//ОбработкаУстановкиОтбораВыбора(ОбъектМД, НастройкаКомпоновки, Параметры);
Если Параметры.Отбор.Количество() > 0 Тогда
// Нужно чтобы отключить элементы отбора несуществующих полей
Если Компоновщик = Неопределено Тогда
Компоновщик = Новый КомпоновщикНастроекКомпоновкиДанных;
Компоновщик.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки));
КонецЕсли;
Компоновщик.ЗагрузитьНастройки(НастройкаКомпоновки);
Компоновщик.Восстановить();
НастройкаКомпоновки = Компоновщик.Настройки;
КонецЕсли;
КонецЕсли;
Попытка
ЧислоПоиска = Число(Параметры.СтрокаПоиска);
Исключение
ЧислоПоиска = Неопределено;
КонецПопытки;
ГруппаИли = НастройкаКомпоновки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИли.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
ТекстСортировки = новый Массив;
Если Параметры.Свойство("СтрокаПоиска") И ЗначениеЗаполнено(Параметры.СтрокаПоиска) Тогда
СловаПоиска = РазделитьСтрокуПоискаНаСловаПоискаЛкс(НРег(Параметры.СтрокаПоиска));
ПоляТаблицы = ирКэш.ПоляТаблицыБДЛкс(ОбъектМД.ПолноеИмя(), Истина);
Для Каждого ПолеПоискаПоСтроке Из ОбъектМД.ВводПоСтроке Цикл
ДоступноеПоле = ПоляТаблицы.Найти(ПолеПоискаПоСтроке.Имя, "Имя");
Если ДоступноеПоле.ТипЗначения.СодержитТип(Тип("Строка")) Тогда
Если РежимПоискаПоСловам Тогда
ГруппаИ = ГруппаИли.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Для Каждого СловоПоиска Из СловаПоиска Цикл
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ГруппаИ, ПолеПоискаПоСтроке.Имя, СловоПоиска, ВидСравненияКомпоновкиДанных.Содержит,, Ложь);
КонецЦикла;
Иначе
ЗначениеОтбора = Параметры.СтрокаПоиска + "%";
ЗначениеОтбора = СтрЗаменить(ЗначениеОтбора, "/", "//"); // Спецсимвол по умолчанию
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ГруппаИли, ПолеПоискаПоСтроке.Имя, ЗначениеОтбора, ВидСравненияКомпоновкиДанных.Подобно,, Ложь);
КонецЕсли;
ТекстСортировки.Добавить(ПолеПоискаПоСтроке.Имя + " = &СтрокаПоиска УБЫВ");
ИначеЕсли ЧислоПоиска <> Неопределено Тогда
НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ГруппаИли, ПолеПоискаПоСтроке.Имя, ЧислоПоиска, ВидСравненияКомпоновкиДанных.Равно,, Ложь);
ТекстСортировки.Добавить(ПолеПоискаПоСтроке.Имя + " = &ЧислоПоиска УБЫВ");
КонецЕсли;
КонецЦикла;
Для Каждого ПолеПоискаПоСтроке Из ОбъектМД.ВводПоСтроке Цикл
ДоступноеПоле = ПоляТаблицы.Найти(ПолеПоискаПоСтроке.Имя, "Имя");
Если ДоступноеПоле.ТипЗначения.СодержитТип(Тип("Строка")) Тогда
ТекстСортировки.Добавить(ПолеПоискаПоСтроке.Имя + " ПОДОБНО &СтрокаПоиска + ""%"" УБЫВ");
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если НастройкаКомпоновки.Выбор.Элементы.Количество() = 0 Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, "Ссылка");
КонецЕсли;
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, "ПометкаУдаления");
Для Каждого ПолеПоискаПоСтроке Из ОбъектМД.ВводПоСтроке Цикл
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ПолеПоискаПоСтроке.Имя);
КонецЦикла;
Если ЛиМетаданныеОбъектаСГруппамиЛкс(ОбъектМД) Тогда
НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, "ЭтоГруппа");
КонецЕсли;
СхемаКолонок = Новый Структура;
Запрос = ЗапросИзКомпоновкиЛкс(СхемаКомпоновки, НастройкаКомпоновки,,,, СхемаКолонок);
#Если Сервер И Не Сервер Тогда
Запрос = Новый Запрос;
#КонецЕсли
Если ТекстСортировки.Количество() > 0 Тогда
Запрос.УстановитьПараметр("СтрокаПоиска", Параметры.СтрокаПоиска);
Запрос.УстановитьПараметр("ЧислоПоиска", ЧислоПоиска);
КонецЕсли;
ТекстСортировки.Добавить("Ссылка");
ТекстСортировки = СтрСоединитьЛкс(ТекстСортировки, "," + Символы.ПС + Символы.Таб);
Запрос.Текст = Запрос.Текст + "
|УПОРЯДОЧИТЬ ПО
| " + ТекстСортировки + "
|АВТОУПОРЯДОЧИВАНИЕ";
ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
Для Каждого КлючИЗначение Из СхемаКолонок Цикл
ТаблицаРезультата.Колонки[КлючИЗначение.Ключ].Имя = СтрЗаменить(КлючИЗначение.Значение, ".", "");
КонецЦикла;
// Формируем представления ссылок по полям ввода по строке с учетом поглощения
ТаблицаРезультата.Колонки.Добавить("Представление");
//ИмяПоляПорядка1 = "Важность" + СуффиксСлужебногоСвойстваЛкс();
//ТаблицаРезультата.Колонки.Добавить(ИмяПоляПорядка1, Новый ОписаниеТипов("Число"));
//ИмяПоляПорядка2 = "ОсновнойПорядок" + СуффиксСлужебногоСвойстваЛкс();
//ТаблицаРезультата.Колонки.Добавить(ИмяПоляПорядка2);
//Если ТаблицаРезультата.Количество() > МаксЧислоВариантов Тогда
// СтрокаРезультата = ТаблицаРезультата.Добавить();
// СтрокаРезультата[ИмяПоляПорядка1] = 2;
// СтрокаРезультата.Представление = СтрШаблонЛкс("<Результатов больше %1>", МаксЧислоВариантов);
//КонецЕсли;
Если Истина
И ТаблицаРезультата.Количество() > 0
И Параметры.Свойство("СтрокаПоиска")
И ЗначениеЗаполнено(Параметры.СтрокаПоиска)
Тогда
ЕстьРавенствоПервойСтроки = Ложь;
ЕстьРавенствоПоследнейСтроки = Ложь;
ПоследнийИндекс = Мин(ОтображаемоеЧислоРезультатов, ТаблицаРезультата.Количество()) - 1;
Для Каждого ПолеПоискаПоСтроке Из ОбъектМД.ВводПоСтроке Цикл
Если СтрокиРавныЛкс(ТаблицаРезультата[0][ПолеПоискаПоСтроке.Имя], Параметры.СтрокаПоиска) Тогда
ЕстьРавенствоПервойСтроки = Истина;
КонецЕсли;
Если СтрокиРавныЛкс(ТаблицаРезультата[ПоследнийИндекс][ПолеПоискаПоСтроке.Имя], Параметры.СтрокаПоиска) Тогда
ЕстьРавенствоПоследнейСтроки = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЕстьРавенствоПервойСтроки И Не ЕстьРавенствоПоследнейСтроки Тогда
Пока ТаблицаРезультата.Количество() > ОтображаемоеЧислоРезультатов Цикл
ТаблицаРезультата.Удалить(ОтображаемоеЧислоРезультатов);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если ТаблицаРезультата.Количество() <= ОтображаемоеЧислоРезультатов Тогда
Для Каждого СтрокаРезультата Из ТаблицаРезультата Цикл
//СтрокаРезультата[ИмяПоляПорядка2] = ТаблицаРезультата.Индекс(СтрокаРезультата);
ПолноеПредставление = Новый Массив;
ПолноеПредставление.Добавить("" + СтрокаРезультата[ИмяСсылка]);
Для Каждого ПолеПоискаПоСтроке Из ОбъектМД.ВводПоСтроке Цикл
ЗначениеРеквизита = СтрокаРезультата[ПолеПоискаПоСтроке.Имя];
//Если ЗначениеЗаполнено(Параметры.СтрокаПоиска) И СтрНачинаетсяСЛкс(ЗначениеРеквизита, СловаПоиска[0]) Тогда
// СтрокаРезультата[ИмяПоляПорядка1] = 1;
//КонецЕсли;
НадоДобавлять = Истина;
УдалитьЭлементы = Новый Массив;
Для Каждого Представление Из ПолноеПредставление Цикл
Если СтрНайтиЛкс(ЗначениеРеквизита, Представление,,,, Ложь) Тогда
УдалитьЭлементы.Добавить(Представление);
ИначеЕсли СтрНайтиЛкс(Представление, ЗначениеРеквизита,,,, Ложь) Тогда
НадоДобавлять = Ложь;
КонецЕсли;
КонецЦикла;
Для Каждого УдалитьЭлемент Из УдалитьЭлементы Цикл
ПолноеПредставление.Удалить(ПолноеПредставление.Найти(УдалитьЭлемент));
КонецЦикла;
Если НадоДобавлять Тогда
ПолноеПредставление.Добавить(ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
ПолноеПредставление = СтрСоединитьЛкс(ПолноеПредставление, " | ");
Если ЛиМетаданныеОбъектаСГруппамиЛкс(ОбъектМД) И СтрокаРезультата[ИмяЭтоГруппа] Тогда
ПолноеПредставление = ПолноеПредставление + " [Группа]";
КонецЕсли;
СтрокаРезультата.Представление = ПолноеПредставление;
КонецЦикла;
//ТаблицаРезультата.Сортировать(ИмяПоляПорядка1 + " Убыв, " + ИмяПоляПорядка2);
КонецЕсли;
Возврат ТаблицаРезультата;
КонецФункции
Процедура СсылочныйМенеджерОбработкаПолученияДанныхВыбораЛкс(Знач МенеджерТипа, ДанныеВыбора, Знач Параметры, СтандартнаяОбработка) Экспорт
#Если Сервер И Не Сервер Тогда
МенеджерТипа = Справочники.Валюты;
#КонецЕсли
ДанныеВыбора = Новый СписокЗначений;
Если Истина
И ирКэш.НомерВерсииПлатформыЛкс() > 803001 // https://www.hostedredmine.com/issues/962080
//И Параметры.Отбор.Количество() > 0
Тогда
СтандартнаяОбработка = Ложь;
ТипСсылки = ТипЗнч(МенеджерТипа.ПустаяСсылка());
ОбъектМД = Метаданные.НайтиПоТипу(ТипСсылки);
РазмерСпискаПлатформы = 50;
СхемаКомпоновки = СоздатьСхемуКомпоновкиПоОбъектуМДЛкс(ОбъектМД,,,,,,, РазмерСпискаПлатформы + 1);
Компоновщик = ирКэш.КомпоновщикТаблицыМетаданныхЛкс(ОбъектМД.ПолноеИмя());
РежимПоискаПоСловам = Ложь;
ТаблицаРезультата = ТаблицаДанныхВыбораМенеджераЛкс(ОбъектМД, Параметры, СхемаКомпоновки, РазмерСпискаПлатформы, Компоновщик, РежимПоискаПоСловам);
Если РежимПоискаПоСловам Тогда
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
#Если Сервер И Не Сервер Тогда
РегВыражение = Обработки.ирОболочкаРегВыражение.Создать();
#КонецЕсли
РегВыражение.Global = Истина;
СловаПоиска = РазделитьСтрокуПоискаНаСловаПоискаЛкс(НРег(Параметры.СтрокаПоиска));
РегВыражение.Pattern = РегВыражениеСтрокиПоискаЛкс(СловаПоиска, Ложь);
ШаблонРазметкиВхождений = ШаблонРазметкиВхожденийЛкс();
КонецЕсли;
ИмяСсылка = ПеревестиСтроку("Ссылка");
ИмяПометкаУдаления = ПеревестиСтроку("ПометкаУдаления");
Для Каждого СтрокаРезультата Из ТаблицаРезультата Цикл
ОформленнаяСтрока = СтрокаРезультата.Представление;
Если РежимПоискаПоСловам И ЗначениеЗаполнено(Параметры.СтрокаПоиска) Тогда
//ОформленнаяСтрока = СтрНайтиИВыделитьОформлением(ОформленнаяСтрока, Параметры.СтрокаПоиска);
ОформленнаяСтрока = РегВыражение.Заменить(ОформленнаяСтрока, ШаблонРазметкиВхождений);
КонецЕсли;
ДанныеВыбора.Добавить(СтрокаРезультата[ИмяСсылка], ОформленнаяСтрока, СтрокаРезультата[ИмяПометкаУдаления]);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Функция - Ли корневой тип метаданных лкс
//
// Параметры:
// ЗначениеСвойства - -
// ИмяСвойства - Строка - Единственное, Множественное
//
// Возвращаемое значение:
// Булево -
//
Функция ЛиКорневойТипМетаданныхЛкс(Знач ЗначениеСвойства, Знач ИмяСвойства = "Единственное") Экспорт
Результат = ирКэш.ТипыМетаОбъектов(, Ложь, Ложь).Найти(НРег(ЗначениеСвойства), "Н" + ИмяСвойства) <> Неопределено;
Возврат Результат;
КонецФункции
// Функция - Ли корневой общий тип метаданных лкс
//
// Параметры:
// ИмяОбщегоТипа - Строка - например, ОбъектМетаданныхОбщаяФорма
//
// Возвращаемое значение:
// Булево -
//
Функция ЛиКорневойОбщийТипМетаданныхЛкс(Знач ИмяОбщегоТипа) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
#КонецЕсли
мПлатформа.ИнициацияОписанияМетодовИСвойств();
СтрокаТипаКоллекции = мПлатформа.ТаблицаОбщихТипов.НайтиСтроки(Новый Структура("ЯзыкПрограммы, ТипЭлементаКоллекции", 0, ИмяОбщегоТипа));
СтрокаТипаКоллекции = СтрокаТипаКоллекции[0];
Найденные = мПлатформа.ТаблицаКонтекстов.НайтиСтроки(Новый Структура("ЯзыкПрограммы, ТипЗначения, ТипСлова", 0, СтрокаТипаКоллекции.Слово, "Свойство"));
Результат = Истина;
Для Каждого СтрокаКонтекста Из Найденные Цикл
Если СтрокаКонтекста.ТипКонтекста <> "ОбъектМетаданныхКонфигурация" Тогда
Результат = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// .
// Параметры:
// ТипОбъектовРезультата - Строка, "" - имя типа объектов метаданных, которые нужно находить
// ИскомыйОбъектМД - ОбъектМетаданных, Неопределено - если указан, то ищутся объекты, ссылающиеся на него, а параметр ТипОбъектовРезультата игнорируется
// Результат - - на выходе - таблица значений результатов поиска
// мКолонкиРасширенногоПредставления - -
// СтруктураТипа - -
// ЛиЦелевойТипКорневой - -
// ПолноеИмяРодителя - -
// ЗащитаРекурсия - -
// СвойстваРекурсия - -
//
// Возвращаемое значение:
// Булево - были ли подходящие коллекции
//
Функция НайтиОбъектыМетаданныхРекурсивноЛкс(ТипОбъектовРезультата = Неопределено, Знач ИскомыйОбъектМД = Неопределено, Результат = Неопределено, Знач КолонкиРасширенногоПредставления = Неопределено,
СтруктураТипа = Неопределено, Знач ЛиЦелевойТипКорневой = Неопределено, Знач ПолноеИмяРодителя = Неопределено, Знач ЗащитаРекурсия = Неопределено, Знач СвойстваРекурсия = Неопределено) Экспорт
мПлатформа = ирКэш.Получить();
#Если Сервер И Не Сервер Тогда
мПлатформа = Обработки.ирПлатформа.Создать();
Результат = Новый ТаблицаЗначений;
#КонецЕсли
Если Результат = Неопределено Тогда
ИнтерфейснаяПанель = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирИнтерфейснаяПанель");
Результат = ИнтерфейснаяПанель.СсылкиНаОбъект.ВыгрузитьКолонки();
КонецЕсли;
Если СтруктураТипа = Неопределено Тогда
СтруктураТипа = мПлатформа.СтруктураТипаИзЗначения(Метаданные);
Если ТипОбъектовРезультата <> Неопределено Тогда
ЛиЦелевойТипКорневой = ЛиКорневойОбщийТипМетаданныхЛкс(ТипОбъектовРезультата);
Иначе
ЛиЦелевойТипКорневой = Ложь;
КонецЕсли;
Результат.Очистить();
КонецЕсли;
ТаблицаОбщихТипов = мПлатформа.ТаблицаОбщихТипов;
Если ЗащитаРекурсия = Неопределено Тогда
ЗащитаРекурсия = Новый Соответствие;
КонецЕсли;
Если СвойстваРекурсия = Неопределено Тогда
СвойстваРекурсия = Новый Соответствие;
КонецЕсли;
Свойства = СвойстваРекурсия[СтруктураТипа.ИмяОбщегоТипа];
Если Свойства = Неопределено Тогда
//СвойстваВсе = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипа,,,, Ложь,, "Свойство");
ПараметрыЗаполнения = мПлатформа.НовыеПараметрыЗаполненияСлов("Свойство",,,,, Ложь);
СвойстваВсе = мПлатформа.ТаблицаСловИзСтруктурыТипа(СтруктураТипа, ПараметрыЗаполнения);
Свойства = Новый Структура;
Для Каждого Свойство Из СвойстваВсе Цикл
Если ИскомыйОбъектМД = Неопределено И Свойство.Слово = "Состав" Тогда
Продолжить;
КонецЕсли;
Если ИскомыйОбъектМД <> Неопределено И Свойство.ТипЗначения = "ОписаниеТипов" Тогда
Свойства.Вставить(Свойство.Слово, "Тип");
Иначе
СтрокаТипаЗначения = ТаблицаОбщихТипов.НайтиСтроки(Новый Структура("ЯзыкПрограммы, Слово", 0, Свойство.ТипЗначения));
Если СтрокаТипаЗначения.Количество() > 0 Тогда
Свойства.Вставить(Свойство.Слово, СтрокаТипаЗначения[0].ТипЭлементаКоллекции);
КонецЕсли;
КонецЕсли;
КонецЦикла;
СвойстваРекурсия[СтруктураТипа.ИмяОбщегоТипа] = Свойства;
КонецЕсли;
Если ПолноеИмяРодителя = Неопределено Тогда
ИндикаторСвойств = ПолучитьИндикаторПроцессаЛкс(Свойства.Количество());
КонецЕсли;
ЛиБылиПодходящиеКоллекции = Ложь;
Для Каждого Свойство Из Свойства Цикл
Если ИндикаторСвойств <> Неопределено Тогда
ОбработатьИндикаторЛкс(ИндикаторСвойств);
КонецЕсли;
ТипЭлементаКоллекции = Свойство.Значение;
ИмяСвойства = Свойство.Ключ;
Если Ложь
Или Не ЗначениеЗаполнено(ТипЭлементаКоллекции)
Или ИскомыйОбъектМД = Неопределено И Найти(ТипЭлементаКоллекции, ",") > 0
Тогда
Продолжить;
КонецЕсли;
Если ТипОбъектовРезультата = Неопределено Или ТипЭлементаКоллекции = ТипОбъектовРезультата Тогда
ЛиБылиПодходящиеКоллекции = Истина;
КонецЕсли;
ВременныеМетаданные = СтруктураТипа.Метаданные;
Если ВременныеМетаданные = Неопределено Тогда
ВременныеМетаданные = Метаданные;
КонецЕсли;
КоллекцияВСвойстве = Неопределено;
Попытка
КоллекцияВСвойстве = ВременныеМетаданные[ИмяСвойства];
Исключение
Продолжить;
КонецПопытки;
Если КоллекцияВСвойстве = Неопределено Тогда
Продолжить;
КонецЕсли;
ОписаниеТиповИзСвойства = Неопределено;
Если Истина
И ТипЗнч(КоллекцияВСвойстве) = Тип("ОписаниеТипов")
И ИскомыйОбъектМД <> Неопределено
//И ЛиМетаданныеСсылочногоОбъектаЛкс(ИскомыйОбъектМД) // долго TODO закэшировать
Тогда
ОписаниеТиповИзСвойства = КоллекцияВСвойстве;
КоллекцияВСвойстве = КоллекцияВСвойстве.Типы();
ТипЭлементаКоллекции = "";
КонецЕсли;
ИндикаторКоллекции = Неопределено;
Если ПолноеИмяРодителя = Неопределено Тогда
ИндикаторКоллекции = ПолучитьИндикаторПроцессаЛкс(КоллекцияВСвойстве.Количество(), ИмяСвойства);
КонецЕсли;
СтруктураТипаОбъекта = Неопределено;
Для Каждого ОбъектМД Из КоллекцияВСвойстве Цикл
Если ТипЗнч(ОбъектМД) = Тип("Тип") Тогда
ОбъектМД = Метаданные.НайтиПоТипу(ОбъектМД);
Если ОбъектМД = Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ОбъектМД = Метаданные.Справочники.ирАлгоритмы;
#КонецЕсли
Если ИндикаторКоллекции <> Неопределено Тогда
ОбработатьИндикаторЛкс(ИндикаторКоллекции);
КонецЕсли;
ПолноеИмяМД = "";
Попытка
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
Исключение
// Пакет XDTO
// Описание стандартного реквизита
Попытка
ИмяОбъекта = ОбъектМД.Имя;
Исключение
ИмяОбъекта = "";
КонецПопытки;
Если ЗначениеЗаполнено(ИмяОбъекта) Тогда
ПолноеИмяМД = ПолноеИмяРодителя + "." + ПоследнийФрагментЛкс(ТипЭлементаКоллекции, " ") + "." + ОбъектМД.Имя;
КонецЕсли;
КонецПопытки;
Если ИскомыйОбъектМД = ОбъектМД И ЗначениеЗаполнено(ПолноеИмяРодителя) Тогда
РодительМД = СтруктураТипа.Метаданные;
СтрокаНайденного = Результат.Добавить();
СтрокаНайденного.ПолноеИмя = ПолноеИмяРодителя;
Если ТипЗнч(РодительМД) = Тип("ОбъектМетаданных") Тогда
//! РодительМД = 0 // ОбъектМетаданныхРеквизит
РодительРодителя = РодительМД.Родитель();
Если РодительРодителя <> Неопределено Тогда
СтрокаНайденного.ПолноеИмяРодителя = РодительРодителя.ПолноеИмя();
КонецЕсли;
Иначе
СтрокаНайденного.ПолноеИмяРодителя = ПервыеФрагментыЛкс(ПолноеИмяМД);
КонецЕсли;
СтрокаНайденного.ИмяСвойства = ИмяСвойства;
СтрокаНайденного.ИмяНабораТипов = ирОбщий.ИмяНабораТиповИзОписанияТиповЛкс(ОписаниеТиповИзСвойства);
Попытка
РасширениеКонфигурации = РодительМД.РасширениеКонфигурации();
Исключение
РасширениеКонфигурации = Неопределено;
КонецПопытки;
СтрокаНайденного.РасширениеКонфигурации = РасширениеКонфигурации;
//Прервать;
КонецЕсли;
Если Не ЗначениеЗаполнено(ТипЭлементаКоллекции) Или Найти(ТипЭлементаКоллекции, ",") > 0 Тогда
Продолжить;
КонецЕсли;
Если ТипЭлементаКоллекции = ТипОбъектовРезультата Тогда
СтрокаНайденного = Результат.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаНайденного, ОбъектМД);
Для Каждого ИмяКолонкиРезультата Из КолонкиРасширенногоПредставления Цикл
Попытка
ЗначениеСвойства = ОбъектМД[ИмяКолонкиРезультата];
Исключение
// Измерение последовательности
Продолжить;
КонецПопытки;
СтрокаНайденного[ИмяКолонкиРезультата] = РасширенноеПредставлениеЛкс(ЗначениеСвойства,,,,,,, Истина);
КонецЦикла;
СтрокаНайденного.ПолноеИмя = ПолноеИмяМД;
СтрокаНайденного.ПолноеИмяРодителя = ПолноеИмяРодителя;
Попытка
РасширениеКонфигурации = ОбъектМД.РасширениеКонфигурации();
Исключение
РасширениеКонфигурации = Неопределено;
КонецПопытки;
СтрокаНайденного.РасширениеКонфигурации = РасширениеКонфигурации;
КонецЕсли;
Если ЗначениеЗаполнено(ПолноеИмяМД) Тогда
Если ЗащитаРекурсия[ПолноеИмяМД] = 1 Тогда
Продолжить;
КонецЕсли;
ЗащитаРекурсия[ПолноеИмяМД] = 1;
КонецЕсли;
Если СтруктураТипаОбъекта = Неопределено Тогда
СтруктураТипаОбъекта = мПлатформа.НоваяСтруктураТипа();
СтруктураТипаОбъекта.ИмяОбщегоТипа = ТипЭлементаКоллекции;
КонецЕсли;
СтруктураТипаОбъекта.Метаданные = ОбъектМД;
Если Не ЛиЦелевойТипКорневой Тогда
ЛиБылиПодходящиеКоллекцииСнизу = НайтиОбъектыМетаданныхРекурсивноЛкс(ТипОбъектовРезультата, ИскомыйОбъектМД, Результат, КолонкиРасширенногоПредставления, СтруктураТипаОбъекта,
ЛиЦелевойТипКорневой, ПолноеИмяМД, ЗащитаРекурсия, СвойстваРекурсия);
Если ЛиБылиПодходящиеКоллекцииСнизу Тогда
ЛиБылиПодходящиеКоллекции = Истина;
КонецЕсли;
Если Не ЛиБылиПодходящиеКоллекции Тогда
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ИндикаторКоллекции <> Неопределено Тогда
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
КонецЦикла;
Если ИндикаторСвойств <> Неопределено Тогда
ОсвободитьИндикаторПроцессаЛкс();
КонецЕсли;
Возврат ЛиБылиПодходящиеКоллекции;
КонецФункции
Процедура ДобавитьТекущемуПользователюРолиИРЛкс() Экспорт
Если ирКэш.ЛиПортативныйРежимЛкс() Тогда
Возврат;
КонецЕсли;
ТекущийПользовательЗапуска = ПользователиИнформационнойБазы.ТекущийПользователь();
Если СтрКончаетсяНаЛкс(ТекущийПользовательЗапуска.ПолноеИмя, МаркерВременныхРолейЛкс()) Тогда
Возврат;
КонецЕсли;
Если ирКэш.НомерВерсииБСПЛкс() >= 300 И Метаданные.Справочники.Найти("ПрофилиГруппДоступа") <> Неопределено Тогда
ирСервер.ДобавитьТекущемуПользователюБСПРолиИРЛкс();
КонецЕсли;
ТекущийПользовательБД = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя());
Если Ложь
Или ТекущийПользовательБД.Роли.Содержит(Метаданные.Роли.ирРазработчик)
Или Не ЗначениеЗаполнено(ИмяПользователя())
Или Не ПравоДоступа("Администрирование", Метаданные)
Тогда
Возврат;
КонецЕсли;
ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирРазработчик);
ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирПользователь);
Если Метаданные.Роли.Найти("ирВсеПрава") <> Неопределено Тогда
ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирВсеПрава); //@skip-check unknown-method-property
КонецЕсли;
Текст = "Восстановлены роли ИР текущего пользователя.";
Если ирКэш.НомерВерсииБСПЛкс() >= 300 Тогда
Текст = Текст + " Рекомендуется установить расширение https://devtool1c.ucoz.ru/load/osnovnye/zashhita_rolej_rasshirenij_bsp_3_1_0/1-1-0-25";
КонецЕсли;
ирОбщий.СообщитьЛкс(Текст);
ЗаписьЖурналаРегистрации("ИР.Перезапуск", УровеньЖурналаРегистрации.Предупреждение,,, Текст);
ТекущийПользовательБД.Записать();
#Если Клиент Тогда
ирКлиент.ОповеститьОЗаписиОбъектаЛкс(Тип("ПользовательИнформационнойБазы"));
#КонецЕсли
КонецПроцедуры
Функция МаркерВременныхРолейЛкс() Экспорт
Результат = " (временные роли ИР)";
Возврат Результат;
КонецФункции
Процедура ЗаполнитьКолонкуПорядкаТаблицыЛкс(Знач ТаблицаЗначений, Знач ИмяКолонкиПорядка = "Порядок") Экспорт
#Если Сервер И Не Сервер Тогда
ВсеВидыПравДоступа = Новый ТаблицаЗначений;
#КонецЕсли
Если ТаблицаЗначений.Колонки.Найти(ИмяКолонкиПорядка) = Неопределено Тогда
ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиПорядка);
КонецЕсли;
Счетчик = 1;
Для Каждого Строка Из ТаблицаЗначений Цикл
Строка[ИмяКолонкиПорядка] = Счетчик;
Счетчик = Счетчик + 1;
КонецЦикла;
КонецПроцедуры
// .
//
// Параметры:
// ИмяМодуля - Строка -
// НомерСтрокиМодуля - Число -
// ИмяМетода - Строка -
// СмещениеСтрокиМетода - -
// ТекстСтроки - -
// НомерКолонки - -
// ИмяПараметра - -
// Расширенная - Булево - если Ложь, то используется самый компактный стандартный формат ссылки, например {Обработка.ирКлсПолеТекстаПрограммы.МодульОбъекта(5362,5)}
//
// Возвращаемое значение:
// Строка - Пример: {ОбщийМодуль.ирОбщий.Модуль(29754:СсылкаСтрокиМодуляЛкс.ИмяМодуля,1)}: Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда
//
Функция СсылкаСтрокиМодуляЛкс(Знач ИмяМодуля, Знач НомерСтрокиМодуля = 0, Знач ИмяМетода = "", Знач СмещениеСтрокиМетода = 0, Знач ТекстСтроки = "", Знач НомерКолонки = 0, Знач ИмяПараметра = "",
Знач Расширенная = Истина, Знач Команда = "") Экспорт
Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда
ИмяМодуля = СтрокаБезПоследнегоФрагментаЛкс(ИмяМодуля);
ИначеЕсли СтрНачинаетсяСЛкс(ИмяМодуля, "Конфигурация.") Тогда
ИмяМодуля = СтрокаБезПервогоФрагментаЛкс(ИмяМодуля);
КонецЕсли;
//Если ЗначениеЗаполнено(ИмяРасширения) Тогда
// ИмяМодуля = ИмяРасширения + " " + ИмяМодуля;
//КонецЕсли;
Результат = Новый Массив;
Если НомерСтрокиМодуля = Неопределено Тогда
НомерСтрокиМодуля = 0;
КонецЕсли;
КоординатыВМодуле = XMLСтрока(НомерСтрокиМодуля);
Если ЗначениеЗаполнено(НомерКолонки) Тогда
КоординатыВМодуле = КоординатыВМодуле + "," + XMLСтрока(НомерКолонки);
КонецЕсли;
Результат.Добавить(КоординатыВМодуле);
Если Расширенная Тогда
Если ЗначениеЗаполнено(ИмяМетода) Или ЗначениеЗаполнено(СмещениеСтрокиМетода) Тогда
КоординатыМетода = XMLСтрока(ИмяМетода);
Если ЗначениеЗаполнено(ИмяПараметра) Тогда
КоординатыМетода = КоординатыМетода + "." + XMLСтрока(ИмяПараметра);
КонецЕсли;
Если ЗначениеЗаполнено(СмещениеСтрокиМетода) Тогда
КоординатыМетода = КоординатыМетода + "," + XMLСтрока(СмещениеСтрокиМетода);
КонецЕсли;
Результат.Добавить(КоординатыМетода);
КонецЕсли;
Если Не СтрНачинаетсяСЛкс(ИмяМодуля, "Ф::") Тогда
ИмяМодуля = СтрЗаменить(ИмяМодуля, "\", " ");
КонецЕсли;
КонецЕсли;
Результат = СтрСоединитьЛкс(Результат, ":");
Если Расширенная Тогда
Если ЗначениеЗаполнено(Команда) Тогда
Результат = Результат + "!" + Команда;
КонецЕсли;
КонецЕсли;
Результат = "{" + ИмяМодуля + "(" + Результат + ")}";
Если Расширенная И ЗначениеЗаполнено(ТекстСтроки) Тогда
Результат = Результат + ": " + ирОбщий.ПредставлениеЗначенияСОграничениемДлиныЛкс(ТекстСтроки);
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// СсылкаСтрокиМодуля - Строка - Пример: {ОбщийМодуль.ирОбщий.Модуль(29754:СсылкаСтрокиМодуляЛкс.ИмяМодуля,1)}: Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда
Функция СтруктураСсылкиСтрокиМодуляЛкс(Знач СсылкаСтрокиМодуля, Знач НормализоватьИмяМодуля = Истина) Экспорт
ШаблонСсылки = ШаблонСсылкиСтрокиМодуляЛкс();
Вхождения = НайтиРегВыражениеЛкс(СсылкаСтрокиМодуля, ШаблонСсылки);
Если Вхождения.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;
МаркерТекста = "}: ";
ПозицияТекста = Найти(СсылкаСтрокиМодуля, МаркерТекста);
Если ПозицияТекста > 0 Тогда
Текст = Сред(СсылкаСтрокиМодуля, ПозицияТекста + СтрДлина(МаркерТекста));
КонецЕсли;
Вхождение = Вхождения[0];
Расширение = СокрЛП(Вхождение.Группы[1]);
Модуль = Вхождение.Группы[2];
Фрагменты1 = СтрРазделитьЛкс(Модуль);
Фрагменты2 = СтрРазделитьЛкс(Модуль, "::");
Если Фрагменты2.Количество() > 2 Тогда
Файл = Новый Файл(Фрагменты2[1]);
ИмяФайла = Файл.ПолноеИмя;
Если СтрокиРавныЛкс(Файл.Расширение, ".erf") Тогда
ТипОбъекта = "ВнешнийОтчет";
Иначе
ТипОбъекта = "ВнешняяОбработка";
КонецЕсли;
Фрагменты1[0] = Файл.ПолноеИмя;
Фрагменты1.Вставить(0, ТипОбъекта);
Внутренняя = ТипОбъекта + "." + Фрагменты2[2];
КонецЕсли;
Если Фрагменты1.Количество() > 1 Тогда
Объект = Фрагменты1[1];
КонецЕсли;
Форма = "";
Если Фрагменты1.Количество() > 3 Тогда
Форма = Фрагменты1[3];
ИначеЕсли СтрокиРавныЛкс(Фрагменты1[0], "ОбщаяФорма") Тогда
Форма = Фрагменты1[1];
КонецЕсли;
Если ЗначениеЗаполнено(Форма) И НормализоватьИмяМодуля Тогда
Модуль = Модуль + ".Модуль";
КонецЕсли;
НомерСтроки = Число(Вхождение.Группы[4]);
Если Вхождение.Группы[5] <> Неопределено Тогда
НомерКолонки = Число(Вхождение.Группы[5]);
Иначе
НомерКолонки = 1;
КонецЕсли;
Если Вхождение.Группы[7] <> Неопределено Тогда
СмещениеСтрокиМетода = Число(Вхождение.Группы[7]);
Иначе
СмещениеСтрокиМетода = 0;
КонецЕсли;
ПриоритетМетода = Вхождение.Группы[6] <> Неопределено;
Если НомерСтроки = 0 Тогда
ПриоритетМетода = Истина;
НомерСтроки = 1;
КонецЕсли;
Метод = Вхождение.Группы[6];
ФрагментыМетода = СтрРазделитьЛкс(Метод);
Если ФрагментыМетода.Количество() > 1 Тогда
Метод = ФрагментыМетода[0];
ПараметрМетода = ФрагментыМетода[1];
КонецЕсли;
ТипМодуля = ПоследнийФрагментЛкс(Модуль);
Если ЗначениеЗаполнено(Расширение) Тогда
Модуль = Расширение + " " + Модуль;
КонецЕсли;
Команда = Вхождение.Группы[8];
СтруктураСсылкиСтрокиМодуля = Новый Структура;
СтруктураСсылкиСтрокиМодуля.Вставить("Модуль", Модуль);
СтруктураСсылкиСтрокиМодуля.Вставить("Внутренняя", Внутренняя); // Для внешней обработки
СтруктураСсылкиСтрокиМодуля.Вставить("Файл", ИмяФайла);
СтруктураСсылкиСтрокиМодуля.Вставить("ТипОбъекта", ТипОбъекта);
СтруктураСсылкиСтрокиМодуля.Вставить("ТипМодуля", ТипМодуля);
СтруктураСсылкиСтрокиМодуля.Вставить("Расширение", Расширение);
СтруктураСсылкиСтрокиМодуля.Вставить("Объект", Объект);
СтруктураСсылкиСтрокиМодуля.Вставить("Форма", Форма);
СтруктураСсылкиСтрокиМодуля.Вставить("НомерСтроки", НомерСтроки);
СтруктураСсылкиСтрокиМодуля.Вставить("НомерКолонки", НомерКолонки);
СтруктураСсылкиСтрокиМодуля.Вставить("Метод", Метод);
СтруктураСсылкиСтрокиМодуля.Вставить("ПараметрМетода", ПараметрМетода);
СтруктураСсылкиСтрокиМодуля.Вставить("СмещениеСтрокиМетода", СмещениеСтрокиМетода);
СтруктураСсылкиСтрокиМодуля.Вставить("Текст", Текст);
СтруктураСсылкиСтрокиМодуля.Вставить("Команда", Команда);
СтруктураСсылкиСтрокиМодуля.Вставить("ТекстСсылки", Вхождение.ТекстВхождения);
Возврат СтруктураСсылкиСтрокиМодуля;
КонецФункции
Функция ШаблонСсылкиСтрокиМодуляЛкс() Экспорт
ШаблонСсылки = "(\{([a-zа-яё0-9_ ]+ )?(([a-zа-яё0-9_]+::.+?::)?(?:[a-zа-яё0-9_]+\.)*(?:Форма|Form|Модуль[a-zа-яё0-9_]*|[a-zа-яё0-9_]*Module))\((\d+)(?:,(\d+))?(?:\:?([a-zа-яё0-9_<>\.]*)(?:,\s*(-?\d+))?)?"
+ "(?:!([a-zа-яё0-9_\.:]+))?\)\})";
Возврат ШаблонСсылки;
КонецФункции
// Пример C:\TerminalDisk\ОтважныйБобр.epf -> file://C:/TerminalDisk/ОтважныйБобр.epf
// Параметры:
// ИмяФайла - Строка -
// Возвращаемое значение:
// Строка -
Функция СсылкаФайлаЛкс(Знач ИмяФайла) Экспорт
ИмяФайла = "file://" + СтрЗаменить(ИмяФайла, "\", "/");
Возврат ИмяФайла;
КонецФункции
// .
// Параметры:
// ИменаЗначений - Строка - имена значений через ", ", например "Стул, Стол"
//
// Возвращаемое значение:
// ФиксированнаяСтруктура - Ключ=Значение
//
Функция НовоеПеречислениеЛкс(Знач ИменаЗначений) Экспорт
//Параметры = СтрРазделить(ИменаЗначений, ", ", Ложь); // Нет в 8.2
Параметры = СтрРазделитьЛкс(ИменаЗначений, ", ");
Параметры.Вставить(0, ИменаЗначений);
Возврат Новый ("ФиксированнаяСтруктура", Параметры);
КонецФункции
Функция РежимОтладкиСервераИзКоманднойСтрокиЛкс(Знач СтрокаЗапускаПроцесса = "") Экспорт
Если Не ЗначениеЗаполнено(СтрокаЗапускаПроцесса) Тогда
ирСервер.ПолучитьПараметрыПроцессаАгентаСервера(, СтрокаЗапускаПроцесса);
КонецЕсли;
Вхождения = НайтиРегВыражениеЛкс(СтрокаЗапускаПроцесса, "[-/]debug(?:\s+-(http)|$)");
Если Вхождения.Количество() > 0 Тогда
Если Вхождения[0].Группы[0] <> Неопределено Тогда
РежимОтладки = "http";
Иначе
РежимОтладки = "tcp";
КонецЕсли;
Иначе
РежимОтладки = "нет";
КонецЕсли;
Возврат РежимОтладки;
КонецФункции
// Конвертировать слова в корни. От 100мс на слово. Нужен доступ к https://sinonim.org
// Параметры:
// Текст - Строка - слова разделенные пробелом, слова еще принудительно разбиваются на слова по заглавным буквам вызовом ПредставлениеИзИдентификатораЛкс
// выхКорни - Массив - выходной массив корней
// Возвращаемое значение:
// Строка, Неопределено - корни разделенные пробелом
Функция КорниСловЛкс(Знач Текст, Знач ОтрезатьМягкийЗнак = Истина, выхКорни = Неопределено, выхОшибка = "") Экспорт
Текст = НРег(ПредставлениеИзИдентификатораЛкс(Текст));
ИнтернетПрокси = Новый ИнтернетПрокси(ИСТИНА); // 20мс
мПлатформа = ирКэш.Получить();
СерверЗапроса = "sinonim.org";
ПортВременный = 443;
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
СоединениеHTTP = Новый HTTPСоединение(СерверЗапроса, ПортВременный,,, ИнтернетПрокси, 1, ЗащищенноеСоединение);
ЗапросHTTP = Новый HTTPЗапрос("/mo/" + Текст);
Попытка
ОтветHTTP = СоединениеHTTP.ВызватьHTTPМетод("GET", ЗапросHTTP);
Исключение
выхОшибка = ОписаниеОшибки();
Возврат Текст;
КонецПопытки;
КодСостояния = ОтветHTTP.КодСостояния;
ТелоОтветаСтрока = ОтветHTTP.ПолучитьТелоКакСтроку();
ТелоОтветаСтрока = СтрЗаменить(ТелоОтветаСтрока, "́", ""); // Удаляем маркеры ударения
ТелоОтветаСтрока = ирОбщий.ПервыйФрагментЛкс(ТелоОтветаСтрока, "Случайные слова");
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
РегВыражение.Global = Истина;
РегВыражение.IgnoreCase = Истина;
// Альтернативный шаблон: ">([" + мПлатформа.шБуква + "]+) - корень,"
РегВыражение.Pattern = "class=""m_m1""[^>]*>([" + мПлатформа.шБуква + "]+)";
Вхождения = РегВыражение.НайтиВхождения(ТелоОтветаСтрока);
выхКорни = Новый Массив;
Для Каждого ВхожденияЭлемент Из Вхождения Цикл
Корень = ВхожденияЭлемент.SubMatches(0);
Если ОтрезатьМягкийЗнак И Прав(Корень, 1) = "ь" Тогда
Корень = СтрокаБезКонцаЛкс(Корень);
КонецЕсли;
выхКорни.Добавить(Корень);
КонецЦикла;
Возврат СтрСоединитьЛкс(выхКорни, " ");
КонецФункции
Функция ИмяТипаИзИмениПеременнойЛкс(Знач ИмяПеременной) Экспорт
ИмяТипа = Неопределено;
ИмяПеременнойНрег = НРег(ИмяПеременной);
ПервоеСлово = ирОбщий.ПервыйФрагментЛкс(ирОбщий.ПредставлениеИзИдентификатораЛкс(ИмяПеременнойНрег), " ");
Если Ложь
Или ПервоеСлово = "высота"
Или ПервоеСлово = "доля"
Или ПервоеСлово = "длина"
Или ПервоеСлово = "длительность"
Или ПервоеСлово = "глубина"
Или ПервоеСлово = "итог"
Или ПервоеСлово = "количество"
Или ПервоеСлово = "коэффициент"
Или ПервоеСлово = "кратность"
Или ПервоеСлово = "курс"
Или ПервоеСлово = "надбавка"
Или ПервоеСлово = "наценка"
Или ПервоеСлово = "премия"
Или ПервоеСлово = "процент"
Или ПервоеСлово = "разница"
Или ПервоеСлово = "разность"
Или ПервоеСлово = "скидка"
Или ПервоеСлово = "сумма"
Или ПервоеСлово = "число"
Или ПервоеСлово = "ширина"
Или ПервоеСлово = "штраф"
Тогда
ИмяТипа = "Число";
ИначеЕсли Ложь
Или ИмяПеременнойНрег = "доступность"
Или ИмяПеременнойНрег = "видимость"
Или ИмяПеременнойНрег = "толькопросмотр"
Или ИмяПеременнойНрег = "успех"
Или ИмяПеременнойНрег = "отказ"
Или ИмяПеременнойНрег = "стандартнаяобработка"
Тогда
ИмяТипа = "Булево";
Иначе
КонецСлова = Прав(ПервоеСлово, 3);
Если Ложь
Или ПервоеСлово = "ать" и ПервоеСлово <> "печать"
Или ПервоеСлово = "еть"
Или ПервоеСлово = "ить"
Или ПервоеСлово = "оть"
Тогда
ИмяТипа = "Булево";
КонецЕсли;
КонецЕсли;
Возврат ИмяТипа;
КонецФункции
////////////////////////////////////////////////
// Многопоточность
// Вызывающие модули:
// ОбработкаОбъект.ирПодборИОбработкаОбъектов
Функция НоваяСтруктураМногопоточнойОбработкиЛкс(Знач ИмяОбработчикаОбъекта, Знач МодульОбработчика, Знач ИмяОбработчикаРезультатаОбъекта, Знач КоличествоОбъектовВПорции,
Знач КоличествоПотоков, Знач ОбщиеПараметрыОбработкиОдногоОбъекта = Неопределено, Знач ВыводитьСообщения = Истина) Экспорт
ПотокиОбработки = Новый ТаблицаЗначений;
ПотокиОбработки.Колонки.Добавить("АдресРезультата");
ПотокиОбработки.Колонки.Добавить("СтрокиРезультатовОбъектов");
ПотокиОбработки.Колонки.Добавить("УникальныйИдентификатор");
ДоступностьМногопоточности = Истина
И ирКэш.ЭтоФоновоеЗаданиеЛкс()
И Не ирКэш.ЛиФайловаяБазаЛкс()
И Не ирКэш.ЛиПортативныйРежимЛкс();
Для Счетчик = 1 По Макс(1, КоличествоПотоков) Цикл
Если Счетчик > 1 И Не ДоступностьМногопоточности Тогда
Прервать;
КонецЕсли;
ПотокиОбработки.Добавить();
КонецЦикла;
Если ОбщиеПараметрыОбработкиОдногоОбъекта = Неопределено Тогда
ОбщиеПараметрыОбработкиОдногоОбъекта = Новый Структура();
Для Каждого МетаРеквизит Из МодульОбработчика.Метаданные().Реквизиты Цикл
ЗначениеРеквизита = МодульОбработчика[МетаРеквизит.Имя];
Если Ложь
Или ТипЗнч(ЗначениеРеквизита) = Тип("Строка")
Или ТипЗнч(ЗначениеРеквизита) = Тип("Булево")
Или ТипЗнч(ЗначениеРеквизита) = Тип("Дата")
Или ТипЗнч(ЗначениеРеквизита) = Тип("Число")
Тогда
ОбщиеПараметрыОбработкиОдногоОбъекта.Вставить(МетаРеквизит.Имя, ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Статистика = Новый ТаблицаЗначений;
Статистика.Колонки.Добавить("Длительность");
СтруктураПотоков = Новый Структура;
СтруктураПотоков.Вставить("ПорцияОбъектов", Неопределено);
СтруктураПотоков.Вставить("ПотокиОбработки", ПотокиОбработки);
СтруктураПотоков.Вставить("Статистика", Статистика);
СтруктураПотоков.Вставить("ФактическоеКоличествоПотоков", ПотокиОбработки.Количество());
СтруктураПотоков.Вставить("КоличествоОбъектовВПорции", КоличествоОбъектовВПорции);
СтруктураПотоков.Вставить("МодульОбработчика", МодульОбработчика);
СтруктураПотоков.Вставить("ОбщиеПараметрыОбработкиОдногоОбъекта", ОбщиеПараметрыОбработкиОдногоОбъекта);
СтруктураПотоков.Вставить("ИмяОбработчикаРезультатаОбъекта", ИмяОбработчикаРезультатаОбъекта);
СтруктураПотоков.Вставить("ИмяОбработчикаОбъекта", ИмяОбработчикаОбъекта);
СтруктураПотоков.Вставить("ВыводитьСообщения", ВыводитьСообщения);
Возврат СтруктураПотоков;
КонецФункции
// Добавить объект в очередь многопоточной обработки
//
// Параметры:
// СтруктураПотоков - -
// ПараметрыОбработкиОбъекта - Структура - передавайте сюда защищенные экземпляры (копии) коллекций, чтобы при возвращении результата порции они остались неизменными
// СтрокиРезультатовОбъекта - -
// ПринудительноВОсновномПотоке - -
//
Процедура ДобавитьОбъектВОчередьМногопоточнойОбработкиЛкс(СтруктураПотоков, ПараметрыОбработкиОбъекта, СтрокиРезультатовОбъекта = Неопределено, ПринудительноВОсновномПотоке = Ложь) Экспорт
МодульОбработчика = СтруктураПотоков.МодульОбработчика;
Если Ложь
Или СтруктураПотоков.ФактическоеКоличествоПотоков = 1
Или ПринудительноВОсновномПотоке
Тогда
РезультатОбработки = Вычислить("МодульОбработчика." + СтруктураПотоков.ИмяОбработчикаОбъекта + "(ПараметрыОбработкиОбъекта)");
Выполнить("МодульОбработчика." + СтруктураПотоков.ИмяОбработчикаРезультатаОбъекта + "(РезультатОбработки, СтрокиРезультатовОбъекта)");
Возврат;
КонецЕсли;
ПорцияОбъектов = СтруктураПотоков.ПорцияОбъектов;
Если ПорцияОбъектов = Неопределено Тогда
ПорцияОбъектов = Новый Структура("ПараметрыОбработкиОбъектов, СтрокиРезультатовОбъектов", Новый Массив, Новый Массив);
СтруктураПотоков.ПорцияОбъектов = ПорцияОбъектов;
КонецЕсли;
ПорцияОбъектов.ПараметрыОбработкиОбъектов.Добавить(ПараметрыОбработкиОбъекта);
ПорцияОбъектов.СтрокиРезультатовОбъектов.Добавить(СтрокиРезультатовОбъекта);
Если ПорцияОбъектов.ПараметрыОбработкиОбъектов.Количество() < СтруктураПотоков.КоличествоОбъектовВПорции Тогда
Возврат;
КонецЕсли;
ЗапуститьПотокОбработкиПорцииЛкс(СтруктураПотоков);
КонецПроцедуры
Процедура ОжидатьЗавершенияВсехПотоковОбработкиЛкс(СтруктураПотоков) Экспорт
Если СтруктураПотоков.ПорцияОбъектов <> Неопределено Тогда
ЗапуститьПотокОбработкиПорцииЛкс(СтруктураПотоков);
КонецЕсли;
Пока ОбновитьПотокиОбработкиОбъектовЛкс(СтруктураПотоков, Ложь).Количество() < СтруктураПотоков.ПотокиОбработки.Количество() Цикл
ПаузаМиллисекундЛкс(100);
КонецЦикла;
Если СтруктураПотоков.ВыводитьСообщения И СтруктураПотоков.ПотокиОбработки.Количество() > 1 Тогда
СообщитьСтатистикуПорцийСРекомендациями(СтруктураПотоков, Истина);
КонецЕсли;
КонецПроцедуры
Процедура СообщитьСтатистикуПорцийСРекомендациями(Знач СтруктураПотоков, ВыводитьСтатистикуОбязательно = Ложь)
Статистика = СтруктураПотоков.Статистика;
Если Статистика.Количество() = 0 Тогда
// Все потоки завершились неуспешно
СуммарнаяДлительность = 0;
СредняяДлительностьПорции = 0;
Иначе
СуммарнаяДлительность = Статистика.Итог("Длительность");
СредняяДлительностьПорции = Окр(СуммарнаяДлительность / Статистика.Количество(), 1);
КонецЕсли;
ТекстСообщения = СтрШаблонИменЛкс("Обработано %1 порций в %2 потоков. Средняя длительность порции - %3с",
1, Статистика.Количество(), 2, СтруктураПотоков.ФактическоеКоличествоПотоков, 3, СредняяДлительностьПорции);
Если СтруктураПотоков.КоличествоОбъектовВПорции > 1 И СредняяДлительностьПорции > 5 Тогда
ТекстСообщения = ТекстСообщения + ". Рекомендуется уменьшить количество объектов в порции.";
ИначеЕсли СуммарнаяДлительность > 1 И СредняяДлительностьПорции < 1 Тогда
ТекстСообщения = ТекстСообщения + ". Рекомендуется увеличить количество объектов в порции.";
ИначеЕсли СуммарнаяДлительность = 0 Или Не ВыводитьСтатистикуОбязательно Тогда
Возврат;
КонецЕсли;
СообщитьЛкс(ТекстСообщения);
КонецПроцедуры
Процедура ЗапуститьПотокОбработкиПорцииЛкс(Знач СтруктураПотоков)
//ФоновыеЗадания.ОжидатьЗавершенияВыполнения() // Не позволяет ждать одного из
Пока Истина Цикл
НомераСвободныхПотоков = ОбновитьПотокиОбработкиОбъектовЛкс(СтруктураПотоков);
Если НомераСвободныхПотоков.Количество() > 0 Тогда
Прервать;
КонецЕсли;
ПаузаМиллисекундЛкс(50);
КонецЦикла;
ПорцияОбъектов = СтруктураПотоков.ПорцияОбъектов;
НомерСвободногоПотока = НомераСвободныхПотоков[0];
ПотокиОбработки = СтруктураПотоков.ПотокиОбработки;
ПотокиОбработки[НомерСвободногоПотока].СтрокиРезультатовОбъектов = ПорцияОбъектов.СтрокиРезультатовОбъектов;
АдресРезультата = ПоместитьВоВременноеХранилище(Null);
ПараметрыЗадания = Новый Массив(5);
ПолноеИмяМодуля = СтруктураПотоков.МодульОбработчика.Метаданные().ПолноеИмя();
ПараметрыЗадания[0] = ПолноеИмяМодуля;
ПараметрыЗадания[1] = СтруктураПотоков.ИмяОбработчикаОбъекта;
ПараметрыЗадания[2] = СтруктураПотоков.ОбщиеПараметрыОбработкиОдногоОбъекта;
ПараметрыЗадания[3] = ПорцияОбъектов.ПараметрыОбработкиОбъектов;
ПараметрыЗадания[4] = АдресРезультата;
//ДобавитьПереданныйКэшВСтруктуруЛкс(СтруктураПотоков.ОбщиеПараметрыОбработкиОдногоОбъекта);
#Если Сервер И Не Сервер Тогда
ирОбщий.ОбработатьПорциюОбъектовЛкс();
#КонецЕсли
ДобавитьТекущемуПользователюРолиИРЛкс();
ПрефиксКлючаПотока = ПрефиксКлючаПотокаЛкс(СтруктураПотоков.МодульОбработчика);
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ирОбщий.ОбработатьПорциюОбъектовЛкс", ПараметрыЗадания, ПрефиксКлючаПотока + "." + НомерСвободногоПотока, "Поток обработки объектов " + НомерСвободногоПотока);
ПотокиОбработки[НомерСвободногоПотока].АдресРезультата = АдресРезультата;
ПотокиОбработки[НомерСвободногоПотока].УникальныйИдентификатор = ФоновоеЗадание.УникальныйИдентификатор;
СтруктураПотоков.ПорцияОбъектов = Неопределено;
КонецПроцедуры
Функция ПрефиксКлючаПотокаЛкс(Знач ОбработкаОбъект) Экспорт
Возврат ОбработкаОбъект.Метаданные().ПолноеИмя() + ".";
КонецФункции
Процедура ОбработатьПорциюОбъектовЛкс(ПолноеИмяМД, ИмяОбработчикаОбъекта, ОбщиеПараметрыОбработки, ПараметрыМетода, АдресРезультата) Экспорт
ПоместитьПереданныйКэшВоВременноеХранищеЛкс(ОбщиеПараметрыОбработки);
Обработка = СоздатьОбъектПоИмениМетаданныхЛкс(ПолноеИмяМД);
#Если Сервер И Не Сервер Тогда
Обработка = Обработки.ирПодборИОбработкаОбъектов.Создать()
#КонецЕсли
ЗагрузитьРеквизитыОбработкиЛкс(Обработка, ОбщиеПараметрыОбработки);
РезультатПорции = Новый Массив;
Для Каждого ПараметрыВызова Из ПараметрыМетода Цикл
РезультатПорции.Добавить(Вычислить("Обработка." + ИмяОбработчикаОбъекта + "(ПараметрыВызова)"));
КонецЦикла;
ПоместитьВоВременноеХранилище(РезультатПорции, АдресРезультата);
КонецПроцедуры
Функция ОбновитьПотокиОбработкиОбъектовЛкс(СтруктураПотоков, ОбновлятьДоПервогоСвободного = Истина)
ПотокиОбработки = СтруктураПотоков.ПотокиОбработки;
Статистика = СтруктураПотоков.Статистика;
НомераСвободныхПотоков = Новый Массив;
МодульОбработчика = СтруктураПотоков.МодульОбработчика;
Для Каждого ПотокОбработки Из СтруктураПотоков.ПотокиОбработки Цикл
Если ЗначениеЗаполнено(ПотокОбработки.УникальныйИдентификатор) Тогда
ФоновоеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ПотокОбработки.УникальныйИдентификатор);
Если СтруктураПотоков.ВыводитьСообщения Тогда
СообщенияПользователю = СообщенияПользователюОтФоновогоЗаданияЛкс(ФоновоеЗадание, Истина);
Для Каждого СообщениеПользователю Из СообщенияПользователю Цикл
#Если Сервер И Не Сервер Тогда
СообщениеПользователю = Новый СообщениеПользователю;
#КонецЕсли
СообщениеПользователю.Текст = "#Поток " + ПоследнийФрагментЛкс(ФоновоеЗадание.Ключ) + ": " + СообщениеПользователю.Текст;
//СообщитьЛкс(СообщениеПользователю.Текст,, Истина); // Теперь это всегда только на сервере
СообщениеПользователю.Сообщить();
КонецЦикла;
КонецЕсли;
Если ФоновоеЗадание.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
РезультатПорции = ПолучитьИзВременногоХранилища(ПотокОбработки.АдресРезультата);
Если Статистика <> Неопределено Тогда
СтрокаСтатистики = Статистика.Добавить();
СтрокаСтатистики.Длительность = ФоновоеЗадание.Конец - ФоновоеЗадание.Начало;
Если Статистика.Количество() = 4 Тогда
СообщитьСтатистикуПорцийСРекомендациями(СтруктураПотоков);
КонецЕсли;
КонецЕсли;
Иначе
РезультатОбработки = "Фоновое задание отменено";
Если ФоновоеЗадание.Состояние = СостояниеФоновогоЗадания.ЗавершеноАварийно Тогда
РезультатОбработки = ПодробноеПредставлениеОшибкиЛкс(ФоновоеЗадание.ИнформацияОбОшибке);
КонецЕсли;
ВызватьИсключение РезультатОбработки;
//РезультатПорции = Новый Массив;
//ТекстСообщений = СоединитьСообщенияПользователюЛкс(СообщенияПользователю);
//Для Счетчик = 1 По ПотокОбработки.СтрокиРезультатовОбъектов.Количество() Цикл
// РезультатПорции.Добавить(Новый Структура("Результат, ТекстСообщений", РезультатОбработки, ТекстСообщений));
//КонецЦикла;
КонецЕсли;
Для ИндексОбъектаПорции = 0 По ПотокОбработки.СтрокиРезультатовОбъектов.ВГраница() Цикл
РезультатОбработки = РезультатПорции[ИндексОбъектаПорции];
СтрокиРезультатов = ПотокОбработки.СтрокиРезультатовОбъектов[ИндексОбъектаПорции];
Выполнить("МодульОбработчика." + СтруктураПотоков.ИмяОбработчикаРезультатаОбъекта + "(РезультатОбработки, СтрокиРезультатов)");
ПотокОбработки.СтрокиРезультатовОбъектов[ИндексОбъектаПорции] = СтрокиРезультатов;
КонецЦикла;
ПотокОбработки.УникальныйИдентификатор = Неопределено;
КонецЕсли;
КонецЕсли;
Если ПотокОбработки.УникальныйИдентификатор = Неопределено Тогда
НомерСвободногоПотока = СтруктураПотоков.ПотокиОбработки.Индекс(ПотокОбработки);
НомераСвободныхПотоков.Добавить(НомерСвободногоПотока);
КонецЕсли;
КонецЦикла;
Возврат НомераСвободныхПотоков;
КонецФункции
////////////////////////////////////////////////
#КонецЕсли
// Получает первый фрагмент, отделяемый разделителем от строки.
// Написана для оптимизации по скорости.
//
// Параметры:
// Строка - Строка - которую разбиваем;
// *Разделитель - Строка, "." - символ-разделитель;
// *ЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево, *Истина.
//
// Возвращаемое значение:
// Строка, Неопределено - первый фрагмент строки
//
Функция ПервыйФрагментЛкс(Знач Строка, Знач Разделитель = ".", Знач ЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина) Экспорт
Если Ложь Тогда
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Позиция = Найти(Строка, Разделитель);
Если Позиция > 0 Тогда
Возврат Лев(Строка, Позиция - 1);
Иначе
Если ЛиИспользоватьГраницуЕслиМаркерНеНайден Тогда
Возврат Строка;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Позиция = Найти(Строка, Разделитель); Если Позиция > 0 Тогда Возврат Лев(Строка, Позиция - 1); Иначе Если ЛиИспользоватьГраницуЕслиМаркерНеНайден Тогда Возврат Строка; Иначе Возврат Неопределено; КонецЕсли; КонецЕсли;
КонецЕсли;
КонецФункции
Функция ПервыеФрагментыЛкс(Знач Строка, Знач Разделитель = ".", Знач ЧислоФрагментов = 2) Экспорт
Фрагменты = СтрРазделитьЛкс(Строка, Разделитель);
Пока Фрагменты.Количество() > ЧислоФрагментов Цикл
Фрагменты.Удалить(Фрагменты.ВГраница());
КонецЦикла;
Результат = СтрСоединитьЛкс(Фрагменты, Разделитель);
Возврат Результат;
КонецФункции
Функция ДлинаОтступаЛкс(Знач СтрокаТекста, Знач ЗаменятьТабуляции = Истина) Экспорт
Если ЗаменятьТабуляции Тогда
СтрокаТекста = СтрЗаменить(СтрокаТекста, Символы.Таб, 4);
КонецЕсли;
Возврат СтрДлина(СтрокаТекста) - СтрДлина(СокрЛ(СтрокаТекста));
КонецФункции
Функция НепечатноеНачалоСтрокиЛкс(Знач Текст) Экспорт
Возврат Лев(Текст, СтрДлина(Текст) - СтрДлина(СокрЛ(Текст)));
КонецФункции
Функция СтрКончаетсяНаЛкс(Знач ПерваяСтрока, Знач ВтораяСтрока, Знач СУчетомРегистра = Ложь) Экспорт
КонецСтроки = Прав(ПерваяСтрока, СтрДлина(ВтораяСтрока));
Если СУчетомРегистра Тогда
Результат = КонецСтроки = ВтораяСтрока;
Иначе
Результат = НРег(КонецСтроки) = НРег(ВтораяСтрока);
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает последний фрагмент, отделяемый разделителем от строки.
// Для для длинных строк медленно! Для них рекомендуется использовать регулярные выражения.
//
// Параметры:
// Строка - Строка - в которой ищем;
// Маркер - Строка - отсекающий маркер;
// ЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево - разрешение использования границ строки
// в случае, если маркер не найден.
//
// Возвращаемое значение:
// Неопределено - маркер не найден;
// - Число - позиция маркера.
//
Функция ПоследнийФрагментЛкс(Знач Строка, Знач Маркер = ".", Знач ЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина) Экспорт
//Если ЛиДоступенМодуль83() Тогда
// Позиция = СтрНайтиЛкс(Строка, Маркер, Истина);
// Возврат Сред(Строка, Позиция + СтрДлина(Маркер));
//КонецЕсли;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Подстрока = Строка;
МаркерНайден = Ложь;
Пока Маркер <> "" Цикл
Позиция = Найти(Подстрока, Маркер);
Если Позиция = 0 Тогда
Прервать;
КонецЕсли;
МаркерНайден = Истина;
Подстрока = Сред(Подстрока, Позиция + СтрДлина(Маркер));
КонецЦикла;
Если Истина
И Не МаркерНайден
И ЛиИспользоватьГраницуЕслиМаркерНеНайден
Тогда
Возврат "" + Строка;
ИначеЕсли МаркерНайден Тогда
Возврат Подстрока;
Иначе
Возврат "";
КонецЕсли;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Подстрока = Строка; МаркерНайден = Ложь; Пока Маркер <> "" Цикл Позиция = Найти(Подстрока, Маркер); Если Позиция = 0 Тогда Прервать; КонецЕсли; МаркерНайден = Истина; Подстрока = Сред(Подстрока, Позиция + СтрДлина(Маркер)); КонецЦикла; Если Истина И Не МаркерНайден И ЛиИспользоватьГраницуЕслиМаркерНеНайден Тогда Возврат "" + Строка; ИначеЕсли МаркерНайден Тогда Возврат Подстрока; Иначе Возврат ""; КонецЕсли;
КонецЕсли;
КонецФункции
// Конструктор массива через значения элементов.
//
// Параметры:
// п1 - Произвольный - элементы массива, Null - считается отсутствием значения (заполнение массива прерывается).
//
// Возвращаемое значение:
// Массив - полученный массив.
//
Функция ЗначенияВМассивЛкс(
п1, п2 = Null, п3 = Null, п4 = Null, п5 = Null,
п6 = Null, п7 = Null, п8 = Null, п9 = Null, п10= Null,
п11= Null, п12= Null, п13= Null, п14= Null, п15= Null,
п16= Null, п17= Null, п18= Null, п19= Null, п20= Null
) Экспорт
М = Новый Массив();
Если п1 = Null Тогда Возврат М; Иначе М.Добавить(п1 ); КонецЕсли;
Если п2 = Null Тогда Возврат М; Иначе М.Добавить(п2 ); КонецЕсли;
Если п3 = Null Тогда Возврат М; Иначе М.Добавить(п3 ); КонецЕсли;
Если п4 = Null Тогда Возврат М; Иначе М.Добавить(п4 ); КонецЕсли;
Если п5 = Null Тогда Возврат М; Иначе М.Добавить(п5 ); КонецЕсли;
Если п6 = Null Тогда Возврат М; Иначе М.Добавить(п6 ); КонецЕсли;
Если п7 = Null Тогда Возврат М; Иначе М.Добавить(п7 ); КонецЕсли;
Если п8 = Null Тогда Возврат М; Иначе М.Добавить(п8 ); КонецЕсли;
Если п9 = Null Тогда Возврат М; Иначе М.Добавить(п9 ); КонецЕсли;
Если п10= Null Тогда Возврат М; Иначе М.Добавить(п10); КонецЕсли;
//Если п11= Null Тогда Возврат М; Иначе М.Добавить(п11); КонецЕсли;
//Если п12= Null Тогда Возврат М; Иначе М.Добавить(п12); КонецЕсли;
//Если п13= Null Тогда Возврат М; Иначе М.Добавить(п13); КонецЕсли;
//Если п14= Null Тогда Возврат М; Иначе М.Добавить(п14); КонецЕсли;
//Если п15= Null Тогда Возврат М; Иначе М.Добавить(п15); КонецЕсли;
//Если п16= Null Тогда Возврат М; Иначе М.Добавить(п16); КонецЕсли;
//Если п17= Null Тогда Возврат М; Иначе М.Добавить(п17); КонецЕсли;
//Если п18= Null Тогда Возврат М; Иначе М.Добавить(п18); КонецЕсли;
//Если п19= Null Тогда Возврат М; Иначе М.Добавить(п19); КонецЕсли;
//Если п20= Null Тогда Возврат М; Иначе М.Добавить(п20); КонецЕсли;
//! М.Добавить(п1);
Возврат М;
КонецФункции
Функция ЛиВСпискеЛкс(Знач ПроверяемоеЗначение, Знач Значение1 = Null, Знач Значение2 = Null, Знач Значение3 = Null) Экспорт
Если Значение1 <> Null И ПроверяемоеЗначение = Значение1 Тогда
Возврат Истина;
КонецЕсли;
Если Значение2 <> Null И ПроверяемоеЗначение = Значение2 Тогда
Возврат Истина;
КонецЕсли;
Если Значение3 <> Null И ПроверяемоеЗначение = Значение3 Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
// Удаляет первое вхождение значения из массива.
//
// Параметры:
// Массив - Массив - массив, из которого необходимо удалить значение;
// Значение - Массив - удаляемое значение из массива.
//
Процедура УдалитьЗначениеИзМассиваЛкс(Массив, Значение) Экспорт
Индекс = Массив.Найти(Значение);
Если Индекс <> Неопределено Тогда
Массив.Удалить(Индекс);
КонецЕсли;
КонецПроцедуры
// Конструктор структуры через пары Имя-Значение.
//
// Параметры:
// Имя1 - Строка - "" считается отсутствием элемента (заполнение структуры прерывается)
// Знач1 - Произвольный - значение элемента структуры
//
// Возвращаемое значение:
// Структура - полученная структура.
//
Функция СтруктураЗначенийЛкс(Имя1, Знач1, Имя2, Знач2, Имя3 = "", Знач3 = Null, Имя4 = "", Знач4 = Null, Имя5 = "", Знач5 = Null, Имя6 = "", Знач6 = Null, Имя7 = "", Знач7 = Null,
Имя8 = "", Знач8 = Null, Имя9 = "", Знач9 = Null, Имя10 = "", Знач10 = Null) Экспорт
М = Новый Структура();
М.Вставить(Имя1, Знач1);
М.Вставить(Имя2, Знач2);
Если Имя3 = "" Тогда Возврат М; Иначе М.Вставить(Имя3, Знач3); КонецЕсли;
Если Имя4 = "" Тогда Возврат М; Иначе М.Вставить(Имя4, Знач4); КонецЕсли;
Если Имя5 = "" Тогда Возврат М; Иначе М.Вставить(Имя5, Знач5); КонецЕсли;
Если Имя6 = "" Тогда Возврат М; Иначе М.Вставить(Имя6, Знач6); КонецЕсли;
Если Имя7 = "" Тогда Возврат М; Иначе М.Вставить(Имя7, Знач7); КонецЕсли;
Если Имя8 = "" Тогда Возврат М; Иначе М.Вставить(Имя8, Знач8); КонецЕсли;
Если Имя9 = "" Тогда Возврат М; Иначе М.Вставить(Имя9, Знач9); КонецЕсли;
Если Имя10 = "" Тогда Возврат М; Иначе М.Вставить(Имя10, Знач10); КонецЕсли;
Возврат М;
КонецФункции
Функция ИменительныйПадежПериодаЛкс(Знач ЛюбойПадеж) Экспорт
ЛюбойПадеж = Нрег(ЛюбойПадеж);
Если ЛюбойПадеж = "года" Тогда
Результат = "год";
ИначеЕсли ЛюбойПадеж = "полугодия" Тогда
Результат = "полугодие";
ИначеЕсли ЛюбойПадеж = "квартала" Тогда
Результат = "квартал";
ИначеЕсли ЛюбойПадеж = "месяца" Тогда
Результат = "месяц";
ИначеЕсли ЛюбойПадеж = "декады" Тогда
Результат = "декада";
ИначеЕсли ЛюбойПадеж = "недели" Тогда
Результат = "неделя";
ИначеЕсли ЛюбойПадеж = "дня" Тогда
Результат = "день";
ИначеЕсли ЛюбойПадеж = "часа" Тогда
Результат = "час";
ИначеЕсли ЛюбойПадеж = "минуты" Тогда
Результат = "минута";
ИначеЕсли ЛюбойПадеж = "секунды" Тогда
Результат = "секунда";
Иначе
ВызватьИсключение "Период не опознан """ + ЛюбойПадеж + """";
КонецЕсли;
Возврат Результат;
КонецФункции
Процедура ДобавитьЕслиНужноПравыйСлешВФайловыйПутьЛкс(КаталогИсполняемыхФайлов) Экспорт
Если Прав(КаталогИсполняемыхФайлов, 1) <> "\" Тогда
КаталогИсполняемыхФайлов = КаталогИсполняемыхФайлов + "\";
КонецЕсли;
КонецПроцедуры
// Проверяет правильность заполнения реквизитов объекта
// Параметры:
// Объект -
// ОбязательныеПоля - Строка(0,П), Массив
// Отказ - Булево
// Заголовок - Строка(0,П)
//
// Возвращаемое значение: Булево - истина, если проверка пройдена успешно
Функция ПроверитьЗаполнениеРеквизитовОбъектаЛкс(Знач Объект, Знач ОбязательныеПоля = "", Отказ = Ложь) Экспорт
Результат = Истина;
Попытка
ОбменДаннымиЗагрузка = Объект.ОбменДанными.Загрузка;
Исключение
ОбменДаннымиЗагрузка = Ложь;
КонецПопытки;
Если ОбменДаннымиЗагрузка Тогда
Возврат Результат;
КонецЕсли;
Если ТипЗнч(ОбязательныеПоля) = Тип("Строка") Тогда
МассивПолей = СтрРазделитьЛкс(ОбязательныеПоля, ",", Истина);
ОбязательныеПоля = Новый Соответствие;
Для каждого Значение Из МассивПолей Цикл
ОбязательныеПоля[Значение] = "";
КонецЦикла;
//ОбязательныеПоля = Новый Структура(ОбязательныеПоля);
КонецЕсли;
РеквизитыМД = Объект.Метаданные().Реквизиты;
Для каждого КлючЗначение Из ОбязательныеПоля Цикл
ПутьКДанным = КлючЗначение.Ключ;
Значение = Вычислить("Объект." + ПутьКДанным);
Если Не ЗначениеЗаполнено(Значение) Тогда // надо ругаться
Если Не ЗначениеЗаполнено(КлючЗначение.Значение) Тогда
Фрагменты = СтрРазделитьЛкс(ПутьКДанным);
ИндексСтрокиТЧ = Неопределено;
Если Фрагменты.Количество() > 1 Тогда
ИндексСтрокиТЧ = ТекстМеждуМаркерамиЛкс(Фрагменты[0], "[", "]", Ложь);
Если ИндексСтрокиТЧ <> Неопределено Тогда
ИндексСтрокиТЧ = Число(ИндексСтрокиТЧ);
//ИмяТЧ = ПолучитьПервыйФрагментИис(Фрагменты[0], "[");
КонецЕсли;
КонецЕсли;
//ПредставлениеРеквизита = РеквизитыМД[КлючЗначение.Ключ].Представление();
ПредставлениеРеквизита = СокрЛП(Фрагменты[Фрагменты.ВГраница()]);
СтрокаСообщения = "Не заполнено значение реквизита """ + ПредставлениеРеквизита + """";
Если ИндексСтрокиТЧ <> Неопределено Тогда
СтрокаСообщения = СтрокаСообщения + " в строке №" + Формат(ИндексСтрокиТЧ + 1, "ЧГ=") + " таблицы """ + СокрЛП(ПервыйФрагментЛкс(Фрагменты[0], "[")) + """";
КонецЕсли;
Иначе
СтрокаСообщения = КлючЗначение.Значение;
КонецЕсли;
Отказ = Истина;
СообщитьЛкс(СтрокаСообщения, СтатусСообщения.Внимание);
Результат = Ложь;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Ли описания типов пересекаются лкс
//
// Параметры:
// ОписаниеТипов1 - КолонкаТаблицыЗначений, КолонкаДереваЗначений, КолонкаРезультатаЗапроса, ДоступноеПолеКомпоновкиДанных, ДоступноеПолеОтбораКомпоновкиДанных -
// ОписаниеТипов2 - КолонкаТаблицыЗначений, КолонкаДереваЗначений, КолонкаРезультатаЗапроса, ДоступноеПолеКомпоновкиДанных, ДоступноеПолеОтбораКомпоновкиДанных -
// ИсключаяПримитивныеТипы - -
//
// Возвращаемое значение:
// Булево
//
Функция ЛиОписанияТиповПересекаютсяЛкс(Знач ОписаниеТипов1, Знач ОписаниеТипов2, Знач ИсключаяПримитивныеТипы = Ложь) Экспорт
Если Ложь
Или ТипЗнч(ОписаниеТипов1) = Тип("КолонкаТаблицыЗначений")
Или ТипЗнч(ОписаниеТипов1) = Тип("КолонкаДереваЗначений")
Или ТипЗнч(ОписаниеТипов1) = Тип("КолонкаРезультатаЗапроса")
Или ТипЗнч(ОписаниеТипов1) = Тип("ДоступноеПолеКомпоновкиДанных")
Или ТипЗнч(ОписаниеТипов1) = Тип("ДоступноеПолеОтбораКомпоновкиДанных")
Тогда
ОписаниеТипов1 = ОписаниеТипов1.ТипЗначения;
КонецЕсли;
Если Ложь
Или ТипЗнч(ОписаниеТипов2) = Тип("КолонкаТаблицыЗначений")
Или ТипЗнч(ОписаниеТипов2) = Тип("КолонкаДереваЗначений")
Или ТипЗнч(ОписаниеТипов2) = Тип("КолонкаРезультатаЗапроса")
Или ТипЗнч(ОписаниеТипов2) = Тип("ДоступноеПолеКомпоновкиДанных")
Или ТипЗнч(ОписаниеТипов2) = Тип("ДоступноеПолеОтбораКомпоновкиДанных")
Тогда
ОписаниеТипов2 = ОписаниеТипов2.ТипЗначения;
КонецЕсли;
#Если Сервер И Не Сервер Тогда
ОписаниеТипов1 = Новый ОписаниеТипов;
ОписаниеТипов2 = Новый ОписаниеТипов;
#КонецЕсли
Результат = Ложь;
Типы1 = ОписаниеТипов1.Типы();
Если Истина
И Типы1.Количество() = 0
И ОписаниеТипов2.Типы().Количество() = 0
Тогда
Результат = Истина;
Иначе
Для Каждого Тип Из Типы1 Цикл
// Мультиметка7334148
Если Истина
И ИсключаяПримитивныеТипы
И (Ложь
Или Тип = Тип("Булево")
Или Тип = Тип("Строка")
Или Тип = Тип("Число")
Или Тип = Тип("Дата"))
Тогда
Продолжить;
КонецЕсли;
Если ОписаниеТипов2.СодержитТип(Тип) Тогда
Результат = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Результат;
КонецФункции
//
// Параметры:
// ВариантКвалификаторов - Число - 0 - пересекать, 1 - брать от ОписаниеТипов1, 2 - брать от ОписаниеТипов2
Функция ПересечьОписанияТиповЛкс(ОписаниеТипов1, ОписаниеТипов2, ИсключаяПримитивныеТипы = Ложь, ВариантКвалификаторов = 0) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов1 = Новый ОписаниеТипов;
ОписаниеТипов2 = Новый ОписаниеТипов;
#КонецЕсли
Если ВариантКвалификаторов = 1 Тогда
КвалификаторыЧисла = ОписаниеТипов1.КвалификаторыЧисла;
КвалификаторыСтроки = ОписаниеТипов1.КвалификаторыСтроки;
КвалификаторыДаты = ОписаниеТипов1.КвалификаторыДаты;
Иначе
КвалификаторыЧисла = ОписаниеТипов2.КвалификаторыЧисла;
КвалификаторыСтроки = ОписаниеТипов2.КвалификаторыСтроки;
КвалификаторыДаты = ОписаниеТипов2.КвалификаторыДаты;
Если ВариантКвалификаторов = 0 Тогда
Если КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Переменная И ОписаниеТипов1.КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Переменная Тогда
ДопустимаяДлинаНовая = ДопустимаяДлина.Переменная;
Иначе
ДопустимаяДлинаНовая = ДопустимаяДлина.Фиксированная;
КонецЕсли;
КвалификаторыСтроки = Новый КвалификаторыСтроки(
Мин(КвалификаторыСтроки.Длина, ОписаниеТипов1.КвалификаторыСтроки.Длина),
ДопустимаяДлинаНовая);
КвалификаторыЧисла = Новый КвалификаторыЧисла(
Мин(КвалификаторыЧисла.Разрядность, ОписаниеТипов1.КвалификаторыЧисла.Разрядность),
Мин(КвалификаторыЧисла.РазрядностьДробнойЧасти, ОписаниеТипов1.КвалификаторыЧисла.РазрядностьДробнойЧасти),
?(КвалификаторыЧисла.ДопустимыйЗнак = ДопустимыйЗнак.Неотрицательный, КвалификаторыЧисла.ДопустимыйЗнак, ОписаниеТипов1.КвалификаторыЧисла.ДопустимыйЗнак));
Если КвалификаторыДаты.ЧастиДаты = ЧастиДаты.ДатаВремя Тогда
ЧастиДатыНовая = ОписаниеТипов1.КвалификаторыДаты.ЧастиДаты;
ИначеЕсли КвалификаторыДаты.ЧастиДаты <> ОписаниеТипов1.КвалификаторыДаты.ЧастиДаты И ОписаниеТипов1.КвалификаторыДаты.ЧастиДаты <> ЧастиДаты.ДатаВремя Тогда
ЧастиДатыНовая = ЧастиДаты.ДатаВремя;
Иначе
ЧастиДатыНовая = КвалификаторыДаты.ЧастиДаты;
КонецЕсли;
КвалификаторыДаты = Новый КвалификаторыДаты(ЧастиДатыНовая);
КонецЕсли;
КонецЕсли;
МассивОбщихТипов = Новый Массив;
Если ОписаниеТипов1.Типы().Количество() = 0 Тогда
МассивОбщихТипов = ОписаниеТипов2.Типы();
ИначеЕсли ОписаниеТипов2.Типы().Количество() = 0 Тогда
МассивОбщихТипов = ОписаниеТипов1.Типы();
Иначе
Для Каждого Тип Из ОписаниеТипов1.Типы() Цикл
// Мультиметка7334148
Если Истина
И ИсключаяПримитивныеТипы
И (Ложь
Или Тип = Тип("Булево")
Или Тип = Тип("Строка")
Или Тип = Тип("Число")
Или Тип = Тип("Дата"))
Тогда
Продолжить;
КонецЕсли;
Если ОписаниеТипов2.СодержитТип(Тип) Тогда
МассивОбщихТипов.Добавить(Тип);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Результат = Новый ОписаниеТипов(МассивОбщихТипов,,, КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты);
Возврат Результат;
КонецФункции
Функция ОбъединитьОписанияТиповЛкс(ОписаниеТипов1, ОписаниеТипов2) Экспорт
#Если Сервер И Не Сервер Тогда
ОписаниеТипов1 = Новый ОписаниеТипов;
ОписаниеТипов2 = Новый ОписаниеТипов;
#КонецЕсли
КвалификаторыСтроки = ОписаниеТипов2.КвалификаторыСтроки;
Если КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Переменная Или ОписаниеТипов1.КвалификаторыСтроки.ДопустимаяДлина = ДопустимаяДлина.Переменная Тогда
ДопустимаяДлинаНовая = ДопустимаяДлина.Переменная;
Иначе
ДопустимаяДлинаНовая = ДопустимаяДлина.Фиксированная;
КонецЕсли;
КвалификаторыСтроки = Новый КвалификаторыСтроки(
Макс(КвалификаторыСтроки.Длина, ОписаниеТипов1.КвалификаторыСтроки.Длина),
ДопустимаяДлинаНовая);
КвалификаторыЧисла = ОписаниеТипов2.КвалификаторыЧисла;
КвалификаторыЧисла = Новый КвалификаторыЧисла(
Макс(КвалификаторыЧисла.Разрядность, ОписаниеТипов1.КвалификаторыЧисла.Разрядность),
Макс(КвалификаторыЧисла.РазрядностьДробнойЧасти, ОписаниеТипов1.КвалификаторыЧисла.РазрядностьДробнойЧасти),
?(КвалификаторыЧисла.ДопустимыйЗнак = ДопустимыйЗнак.Любой, КвалификаторыЧисла.ДопустимыйЗнак, ОписаниеТипов1.КвалификаторыЧисла.ДопустимыйЗнак));
КвалификаторыДаты = ОписаниеТипов2.КвалификаторыДаты;
Если КвалификаторыДаты.ЧастиДаты = ОписаниеТипов1.КвалификаторыДаты.ЧастиДаты Тогда
ЧастиДатыНовая = КвалификаторыДаты.ЧастиДаты;
Иначе
ЧастиДатыНовая = ЧастиДаты.ДатаВремя;
КонецЕсли;
КвалификаторыДаты = Новый КвалификаторыДаты(ЧастиДатыНовая);
МассивОбщихТипов = ОписаниеТипов1.Типы();
Для Каждого Тип Из ОписаниеТипов2.Типы() Цикл
МассивОбщихТипов.Добавить(Тип);
КонецЦикла;
Результат = Новый ОписаниеТипов(МассивОбщихТипов,,, КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты);
Возврат Результат;
КонецФункции
// Проверяет, отвечает ли строка правилам формирования имен переменных встроенного языка.
//
// Параметры:
// Строка - Строка.
//
// Возвращаемое значение:
// Булево.
//
Функция ЛиИмяПеременнойЛкс(Строка) Экспорт
Если Ложь
Или ПустаяСтрока(Строка)
//Или Найти(Строка, ".") > 0 // Долго
Тогда
Возврат Ложь;
КонецЕсли;
Если ЛиДоступенМодуль83() Тогда
ДопустимыеСимволы = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZабвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
Если Найти(ДопустимыеСимволы, Лев(Строка, 1)) = 0 Тогда
Возврат Ложь;
КонецЕсли;
Возврат ирОбщий83.СтрРазделитьЛкс(Строка, ДопустимыеСимволы + "0123456789", Ложь).Количество() = 0;
КонецЕсли;
Пустышка = Новый Структура;
Попытка
Пустышка.Вставить(Строка);
Возврат Истина;
Исключение
Возврат Ложь; // На большой глубине стека выброс исключения дает заметное замедление
КонецПопытки;
КонецФункции
// Пространство имен текущей конфигурации.
// Возвращаемое значение:
//
Функция ПространствоИменТекущейКонфигурацииЛкс() Экспорт
Возврат "http://v8.1c.ru/8.1/data/enterprise/current-config";
КонецФункции
Функция ЗначениеСвойстваПолучитьБезопасноЛкс(ЭлементФормы, Знач ИмяСвойстваЗаголовка) Экспорт
СтруктураЗначений = Новый Структура(ИмяСвойстваЗаголовка);
ЗаполнитьЗначенияСвойств(СтруктураЗначений, ЭлементФормы);
ЗаголовокЭлемента = СтруктураЗначений[ИмяСвойстваЗаголовка];
Возврат ЗаголовокЭлемента;
КонецФункции
Функция ПолноеИмяФормыЛкс(ЭтаФорма) Экспорт
Если ТипЗнч(ЭтаФорма) = ТипУправляемаяФормаЛкс() Тогда
//! ЭтаФорма = 0; // УправляемаяФорма
Результат = ЭтаФорма.ИмяФормы;
Иначе
Результат = СлужебныеДанныеФормыЛкс(ЭтаФорма).ИмяФормы;
КонецЕсли;
Возврат Результат;
КонецФункции
// Идентификатор экземпляра формы
Функция ИдентификаторФормыЛкс(ЭтаФорма) Экспорт
Если ТипЗнч(ЭтаФорма) = ТипУправляемаяФормаЛкс() Тогда
Результат = ЭтаФорма.УникальныйИдентификатор;
Иначе
Результат = СлужебныеДанныеФормыЛкс(ЭтаФорма).УникальныйИдентификатор;
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Служебные данные формы лкс
//
// Параметры:
// ЭтаФорма - Форма, УправляемаяФорма, Структура -
//
// Возвращаемое значение:
// Структура
//
Функция СлужебныеДанныеФормыЛкс(ЭтаФорма) Экспорт
Результат = Неопределено;
#Если Клиент Тогда
Если ТипЗнч(ЭтаФорма) = Тип("Форма") Тогда
Результат = ЭтаФорма.Панель.Страницы[0].Значение;
Если Результат = Неопределено Тогда
Результат = Новый Структура();
Результат.Вставить("Тип", ТипЗнч(ЭтаФорма));
ЭтаФорма.Панель.Страницы[0].Значение = Результат;
КонецЕсли;
Если Не Результат.Свойство("ИмяФормы") Тогда
// мелкая форма без вызова "Обработка.ирАнализТехножурнала.Форма.СхемаБД"
Результат.Вставить("ИмяФормы");
КонецЕсли;
Иначе
#КонецЕсли
Если ТипЗнч(ЭтаФорма) = Тип("Структура") Тогда
Результат = ЭтаФорма;
Иначе
Попытка
Результат = ЭтаФорма.мСлужебныеДанные; // см. ОбработкаОбъект.ирПлатформа.ИмитаторУправляемойФормыИзДокументаДОМ()
Исключение
#Если Клиент Тогда
Попытка
Результат = ЭтаФорма.КлючУникальности;
Исключение
// Файловый сервер
Возврат Неопределено;
КонецПопытки;
Если ТипЗнч(Результат) <> Тип("Структура") Тогда
//! ЭтаФорма = 0 // Форма
Если Не ЭтаФорма.Открыта() Тогда
// Только для пассивных форм!
Результат = Новый Структура;
Результат.Вставить("Тип", ТипЗнч(ЭтаФорма));
ЭтаФорма.КлючУникальности = Результат;
Иначе
Результат = Неопределено;
КонецЕсли;
КонецЕсли;
#КонецЕсли
КонецПопытки;
КонецЕсли;
#Если Клиент Тогда
КонецЕсли;
#КонецЕсли
// Обычная форма
//! Результат.Вставить("ИмяФормы", "");
//! Результат.Вставить("МенеджерСохраненияНастроек", ирКлиент.НовыйМенеджерСохраненияНастроекФормыЛкс());
//! Результат.Вставить("КомандныеПанелиКнопок", Новый Соответствие);
//! Результат.Вставить("КнопкиВсехДействийКомандныхПанелей", Новый Соответствие);
//! Результат.Вставить("НеготовыеСтраницы", Новый Соответствие);
Возврат Результат;
КонецФункции
Функция ПроверитьПлатформаНеWindowsЛкс(выхОтказ = Неопределено, Знач НазваниеФункции = "", ДляРегВыражений = Ложь) Экспорт
Если Ложь
Или (Истина
И Не ДляРегВыражений
И Не ирКэш.ЛиПлатформаWindowsЛкс()
Или (Истина
И ДляРегВыражений
И Не ирКэш.ДоступноРегВыраженияЛкс()))
Тогда
выхОтказ = Истина;
Если ЗначениеЗаполнено(НазваниеФункции) Тогда
НазваниеФункции = ТекстВВыражениеВстроенногоЯзыкаЛкс(НазваниеФункции);
КонецЕсли;
СообщитьЛкс(СтрШаблонИменЛкс("Функция %1 поддерживается только в ОС Windows",, НазваниеФункции), СтатусСообщения.Внимание,, Истина);
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Процедура ОчиститьПодчиненныеЭлементыФормыЛкс(Знач Родитель, КоличествоНеудаляемых = 1) Экспорт
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(Родитель) = Тип("Панель")
#КонецЕсли
Тогда
Родитель.Страницы.Очистить();
ИначеЕсли Ложь
#Если Клиент Тогда
Или ТипЗнч(Родитель) = Тип("ТабличноеПоле")
#КонецЕсли
Тогда
Родитель.Колонки.Очистить();
Иначе
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(Родитель); // ФормаКлиентскогоПриложения
ПодчиненныеЭлементы = Родитель.ПодчиненныеЭлементы;
НачальноеКоличество = ПодчиненныеЭлементы.Количество();
Для Счетчик = 1 По НачальноеКоличество Цикл
ПодчиненныйЭлемент = ПодчиненныеЭлементы[НачальноеКоличество - Счетчик];
Если ПодчиненныеЭлементы.Количество() > КоличествоНеудаляемых Тогда
ЭтаФорма.Элементы.Удалить(ПодчиненныйЭлемент);
Иначе
// Статистически добавленные нельзя удалять
ПодчиненныйЭлемент.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура СоздатьКолонкиТабличногоПоляЛкс(ТабличноеПоле) Экспорт
Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда
ОчиститьПодчиненныеЭлементыФормыЛкс(ТабличноеПоле, 0);
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(ТабличноеПоле); // ФормаКлиентскогоПриложения
ПутьКДанным = ПутьКДаннымЭлементаУправляемойФормыЛкс(ТабличноеПоле);
РеквизитыТаблицы = ЭтаФорма.ПолучитьРеквизиты(ПутьКДанным);
Для Каждого РеквизитТаблицы Из РеквизитыТаблицы Цикл
ПолеФормы = ЭтаФорма.Элементы.Добавить(ТабличноеПоле.Имя + РеквизитТаблицы.Имя, Тип("ПолеФормы"), ТабличноеПоле);
ПолеФормы.Вид = ВидПоляФормы.ПолеВвода;
Попытка
ПолеФормы.ПутьКДанным = ПутьКДанным + "." + РеквизитТаблицы.Имя;
Исключение
// При РеквизитТаблицы.Имя = "КоличествоСтрок"
КонецПопытки;
КонецЦикла;
Иначе
ТабличноеПоле.СоздатьКолонки();
КонецЕсли;
КонецПроцедуры
Функция ТипЗначенияЭлементаФормыЛкс(ЭлементФормы, ВызыватьИсключение = Истина) Экспорт
Попытка
ТипЗначения = ЭлементФормы.ТипЗначения;
Исключение
// Упр
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(ЭлементФормы);
СлужебныеДанные = СлужебныеДанныеФормыЛкс(ЭтаФорма);
Попытка
ТипЗначения = СлужебныеДанные.ТипыЗначений[ЭлементФормы.Имя];
Исключение
Если ВызыватьИсключение Тогда
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
КонецПопытки;
Возврат ТипЗначения;
КонецФункции
// Чтобы функция всегда возвращала правильное значение в управляемой форме, должен быть
// выполнен общий обработчик формы ПриСозданииНаСервере.
//
// Параметры:
// Элемент - -
// выхПутьКДанным - -
// ЭтаФорма - Форма, ФормаКлиентскогоПриложения -
// ВзятьОтобранное - Булево, Неопределено - для компонуемого табличного поля взять отобранное, при "Неопределено" структура отбора просмотра игнорируется
//
// Возвращаемое значение:
// ДанныеФормыКоллекция, ТаблицаЗначений, ДеревоЗначений, ТабличнаяЧасть -
//
Функция ДанныеЭлементаФормыЛкс(Знач Элемент, выхПутьКДанным = "", ЭтаФорма = Неопределено, ВзятьОтобранное = Ложь) Экспорт
#Если Клиент Тогда
Если Истина
И ЭтаФорма <> Неопределено
И ТипЗнч(Элемент) = Тип("ТабличноеПоле")
И ВзятьОтобранное <> Неопределено
Тогда
КомпоновкаТП = ирКлиент.КомпоновкаТабличногоПоляЛкс(ЭтаФорма, Элемент);
Если КомпоновкаТП <> Неопределено Тогда
Если ВзятьОтобранное И КомпоновкаТП.ИспользоватьОтбор Тогда
Возврат КомпоновкаТП.ТаблицаОтобранное;
Иначе
Возврат КомпоновкаТП.ТаблицаЗначений;
КонецЕсли;
КонецЕсли;
КонецЕсли;
#КонецЕсли
Попытка
// Обычная форма или имитатор управляемой
Данные = Элемент.Значение;
выхПутьКДанным = Неопределено;
Попытка
выхПутьКДанным = Элемент.Данные;
Исключение
// Колонка табличного поля
Попытка
выхПутьКДанным = Элемент.ПутьКДанным; // имитатор
Исключение
КонецПопытки;
КонецПопытки;
Возврат Данные;
Исключение
КонецПопытки;
Если Ложь
#Если Клиент Тогда
Или ТипЗнч(Элемент) = Тип("ПолеТабличногоДокумента")
#КонецЕсли
Тогда
Данные = Элемент;
Иначе
Если ЭтаФорма = Неопределено Тогда
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(Элемент, ТипУправляемаяФормаЛкс()); // Переменная "ЭтаФорма" используется в Вычислить ниже
КонецЕсли;
выхПутьКДанным = ПутьКДаннымЭлементаУправляемойФормыЛкс(Элемент, , ЭтаФорма);
ИмяОбъекта = "";
Если Не ЗначениеЗаполнено(выхПутьКДанным) Или Найти(выхПутьКДанным, "-") > 0 Тогда
//! ЭтаФорма = 0 // ФормаКлиентскогоПриложения
ИмяОбъекта = ПервыйФрагментЛкс(выхПутьКДанным);
ЛокальныйПутьКДанным = Элемент.Имя;
Если ЛокальныйПутьКДанным = "КомпоновщикНастроекПользовательскиеНастройкиЭлемент0Отбор" Тогда
// Стандартная форма "Настройки списка"
ЛокальныйПутьКДанным = "КомпоновщикНастроек.ПользовательскиеНастройки.Элементы[0]";
ИначеЕсли СтрКончаетсяНаЛкс(ЛокальныйПутьКДанным, "ФиксированныеНастройкиОтбор") Тогда
ЛокальныйПутьКДанным = "КомпоновщикНастроек.ФиксированныеНастройки.Отбор";
ИначеЕсли Истина
И Найти(ЛокальныйПутьКДанным, "Отбор") > 0
И ТипЗнч(Элемент) = Тип("ТаблицаФормы")
И ЭтаФорма.Элементы.Найти(ЛокальныйПутьКДанным + "ПравоеЗначение") <> Неопределено
Тогда
ЛокальныйПутьКДанным = "КомпоновщикНастроек.Настройки.Отбор";
КонецЕсли;
выхПутьКДанным = ЛокальныйПутьКДанным;
КонецЕсли;
выхПутьКДанным = СтрЗаменить(выхПутьКДанным, ".ПользовательскиеНастройки[0].Отбор", ".ПользовательскиеНастройки.Элементы[0]"); // грязно
Попытка
Данные = Вычислить("ЭтаФорма." + выхПутьКДанным);
Исключение
Данные = Неопределено;
КонецПопытки;
Если Данные = Неопределено Тогда
Если ЗначениеЗаполнено(ИмяОбъекта) Тогда
КандидатыИмен = ЗначенияВМассивЛкс(ИмяОбъекта);
Иначе
КандидатыИмен = КандидатыИменОбъектныхРеквизитовФормыЛкс(ЭтаФорма);
КонецЕсли;
мПлатформа = ирКэш.Получить();
Для Каждого ИмяОбъекта Из КандидатыИмен Цикл
Попытка
ДанныеОбъекта = Вычислить("ЭтаФорма." + ИмяОбъекта);
Исключение
Продолжить;
КонецПопытки;
Если мПлатформа.мМассивТиповСМетаданными.Найти(ТипЗнч(ДанныеОбъекта)) = Неопределено Тогда
Продолжить;
КонецЕсли;
выхПутьКДанным = ИмяОбъекта + "." + ЛокальныйПутьКДанным;
Попытка
Данные = Вычислить("ЭтаФорма." + выхПутьКДанным);
Прервать;
Исключение
КонецПопытки;
КонецЦикла;
Если Данные = Неопределено Тогда
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для Счетчик = 1 По СтрДлина(Элемент.Имя) Цикл
выхПутьКДанным = Лев(Элемент.Имя, Счетчик) + "." + Сред(Элемент.Имя, Счетчик + 1);
Попытка
Данные = Вычислить("ЭтаФорма." + выхПутьКДанным);
Прервать;
Исключение
КонецПопытки;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для Счетчик = 1 По СтрДлина(Элемент.Имя) Цикл выхПутьКДанным = Лев(Элемент.Имя, Счетчик) + "." + Сред(Элемент.Имя, Счетчик + 1); Попытка Данные = Вычислить("ЭтаФорма." + выхПутьКДанным); Прервать; Исключение КонецПопытки; КонецЦикла;
КонецЕсли;
КонецЕсли;
Если Истина
И ТипЗнч(Элемент) = Тип("ТаблицаФормы")
И Данные <> Неопределено
И ТипЗнч(Данные) <> Тип("ДинамическийСписок")
И ТипЗнч(Данные) <> Тип("ОтборКомпоновкиДанных")
И Элемент.ТекущаяСтрока <> Неопределено
И Данные.НайтиПоИдентификатору(Элемент.ТекущаяСтрока) = Неопределено
Тогда
//https://www.hostedredmine.com/issues/948431
Данные = Неопределено;
КонецЕсли;
Если Данные = Неопределено Тогда
выхПутьКДанным = Неопределено;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Данные;
КонецФункции
// Возвращаемое значение:
// Массив -
Функция ЧастыеИменаРеквизитовОбъектаВФормеЛкс() Экспорт
ЧастыеИменаОбъектов = Новый Массив;
ЧастыеИменаОбъектов.Добавить("Объект");
ЧастыеИменаОбъектов.Добавить("Список");
ЧастыеИменаОбъектов.Добавить("Задача");
ЧастыеИменаОбъектов.Добавить("Запись");
ЧастыеИменаОбъектов.Добавить("Документ");
ЧастыеИменаОбъектов.Добавить("НаборКонстант");
ЧастыеИменаОбъектов.Добавить("Обработка");
ЧастыеИменаОбъектов.Добавить("Отчет");
Возврат ЧастыеИменаОбъектов;
КонецФункции
//.
// Параметры:
// Форма - УправляемаяФорма -
// Возвращаемое значение:
// Массив[Строка] -
Функция КандидатыИменОбъектныхРеквизитовФормыЛкс(Знач Форма) Экспорт
СлужебныеДанные = СлужебныеДанныеФормыЛкс(Форма);
Если Истина
И ТипЗнч(СлужебныеДанные) = Тип("Структура")
И СлужебныеДанные.Свойство("Реквизиты")
И СлужебныеДанные.Реквизиты <> Неопределено
Тогда
Результат = СлужебныеДанные.Реквизиты.ВыгрузитьКолонку("Имя");
Иначе
Результат = ЧастыеИменаРеквизитовОбъектаВФормеЛкс();
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ИдентификаторСтрокиТабличногоПоляЛкс(Знач НоваяСтрока) Экспорт
Если Ложь
Или ТипЗнч(НоваяСтрока) = Тип("ДанныеФормыЭлементКоллекции")
Или ТипЗнч(НоваяСтрока) = Тип("ДанныеФормыЭлементДерева")
Тогда
НоваяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецЕсли;
Возврат НоваяСтрока;
КонецФункции
// Функция - Найти элемент коллекции лкс
//
// Параметры:
// Коллекция - Структура, ТаблицаЗначений, любая коллекция -
// Свойство - Строка - если не указано, то поиск будет по типу
// Значение - -
// ТипЭлемента - Тип -
//
// Возвращаемое значение:
// Произвольный
//
Функция НайтиЭлементКоллекцииЛкс(Знач Коллекция, Знач Свойство = "", Знач Значение = Неопределено, Знач ТипЭлемента = Неопределено, Знач СУчетомРегистра = Истина) Экспорт
Структура = Новый Структура(Свойство);
Если Не СУчетомРегистра Тогда
НЗначение = НРег(Значение);
КонецЕсли;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Для каждого Элемент Из Коллекция Цикл
Если Истина
И ТипЭлемента <> Неопределено
И ТипЗнч(Элемент) <> ТипЭлемента
Тогда
Продолжить;
КонецЕсли;
ЗаполнитьЗначенияСвойств(Структура, Элемент, Свойство);
Если Ложь
Или Не ЗначениеЗаполнено(Свойство)
Или СУчетомРегистра И Структура[Свойство] = Значение
Или Не СУчетомРегистра И НРег(Структура[Свойство]) = НЗначение
Тогда
Результат = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
Для каждого Элемент Из Коллекция Цикл Если Истина И ТипЭлемента <> Неопределено И ТипЗнч(Элемент) <> ТипЭлемента Тогда Продолжить; КонецЕсли; ЗаполнитьЗначенияСвойств(Структура, Элемент, Свойство); Если Ложь Или Не ЗначениеЗаполнено(Свойство) Или СУчетомРегистра И Структура[Свойство] = Значение Или Не СУчетомРегистра И НРег(Структура[Свойство]) = НЗначение Тогда Результат = Элемент; Прервать; КонецЕсли; КонецЦикла;
КонецЕсли;
Возврат Результат; // Неопределено, см. Коллекция[0]
КонецФункции
Функция ЗначенияСвойстваКоллекцииЛкс(Знач Коллекция, Знач Свойство = "Имя", Знач ТипЭлемента = Неопределено) Экспорт
Результат = Новый Массив;
Для каждого Элемент Из Коллекция Цикл
Если Истина
И ТипЭлемента <> Неопределено
И ТипЗнч(Элемент) <> ТипЭлемента
Тогда
Продолжить;
КонецЕсли;
Результат.Добавить(Элемент[Свойство]);
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Стр заменить лкс
//
// Параметры:
// ГдеЗаменять - -
// ЧтоЗаменять - -
// НаЧтоЗаменять - -
// ОставитьЧтоЗаменятьСлева - -
// ВыброситьИсключениеПриОтсутствии - -
// УчитыватьРегистр - Булево - при Истина работает медленно https://partners.v8.1c.ru/forum/t/2132299/m/2132299
//
// Возвращаемое значение:
// -
//
Функция СтрЗаменитьЛкс(Знач ГдеЗаменять, Знач ЧтоЗаменять, Знач НаЧтоЗаменять, Знач ОставитьЧтоЗаменятьСлева = Ложь, Знач ВыброситьИсключениеПриОтсутствии = Истина,
Знач УчитыватьРегистр = Истина) Экспорт
Результат = ГдеЗаменять;
Если ЧтоЗаменять = НаЧтоЗаменять Тогда
Возврат Результат;
КонецЕсли;
Если Не УчитыватьРегистр Тогда
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ТекстНРег = НРег(Результат);
Пока Истина Цикл
ПозицияОбращения = Найти(ТекстНРег, НРег(ЧтоЗаменять));
Если ПозицияОбращения = 0 Тогда
ЗаписьXML.ЗаписатьБезОбработки(Результат);
Прервать;
КонецЕсли;
ЗаписьXML.ЗаписатьБезОбработки(Лев(Результат, ПозицияОбращения - 1));
ЗаписьXML.ЗаписатьБезОбработки(НаЧтоЗаменять);
Результат = Сред(Результат, ПозицияОбращения + СтрДлина(ЧтоЗаменять));
ТекстНРег = Сред(ТекстНРег, ПозицияОбращения + СтрДлина(ЧтоЗаменять));
КонецЦикла;
Результат = ЗаписьXML.Закрыть();
Иначе
Если ОставитьЧтоЗаменятьСлева Тогда
НаЧтоЗаменять = ЧтоЗаменять + НаЧтоЗаменять;
КонецЕсли;
Результат = СтрЗаменить(Результат, ЧтоЗаменять, НаЧтоЗаменять);
КонецЕсли;
Если ВыброситьИсключениеПриОтсутствии И Результат = ГдеЗаменять Тогда
ВызватьИсключение "Шаблонная строка """ + ЧтоЗаменять + """ не найдена в тексте";
КонецЕсли;
Возврат Результат;
КонецФункции
// Функция - Стр найти лкс
//
// Параметры:
// Строка - -
// ПодстрокаПоиска - -
// НаправлениеПоискаСКонца - -
// НачальнаяПозиция - -
// НомерВхождения - -
// УчитыватьРегистр - -
//
// Возвращаемое значение:
// Число - Позиция первого знака найденной подстроки. Нумерация символов в строке начинается с 1. Если строка не содержит указанной подстроки, то возвращается 0.
//
Функция СтрНайтиЛкс(Знач Строка, Знач ПодстрокаПоиска, Знач НаправлениеПоискаСКонца = Ложь, Знач НачальнаяПозиция = Неопределено, Знач НомерВхождения = 1, Знач УчитыватьРегистр = Истина) Экспорт
Если Не УчитыватьРегистр Тогда
Строка = НРег(Строка);
ПодстрокаПоиска = НРег(ПодстрокаПоиска);
КонецЕсли;
Если Не НаправлениеПоискаСКонца И НачальнаяПозиция = Неопределено И НомерВхождения = 1 Тогда
Возврат Найти(Строка, ПодстрокаПоиска);
КонецЕсли;
Если ЛиДоступенМодуль83() Тогда
Возврат ирОбщий83.СтрНайтиЛкс(Строка, ПодстрокаПоиска, ?(НаправлениеПоискаСКонца, ПредопределенноеЗначение("НаправлениеПоиска.СКонца"), ПредопределенноеЗначение("НаправлениеПоиска.СНачала")),
НачальнаяПозиция, НомерВхождения);
КонецЕсли;
ТекущаяПозиция = 0;
ЗнакНаправленияДвижения = 0;
ДлинаСтрПоиска = СтрДлина(ПодстрокаПоиска);
Попытка
Если НачальнаяПозиция <> Неопределено Тогда
НачальнаяПозиция = Число(НачальнаяПозиция);
Если НачальнаяПозиция <= 0 ИЛИ НачальнаяПозиция > СтрДлина(Строка) Тогда // Платформенный вариант для пустого текста не выбрасывает исключение, а этот выбросит
ВызватьИсключение ("");
КонецЕсли;
КонецЕсли;
Исключение
ВызватьИсключение("Недопустимое значение параметра (параметр номер '4')");
КонецПопытки;
Если НаправлениеПоискаСКонца Тогда
НачальнаяПозиция = ?(НачальнаяПозиция <> Неопределено, НачальнаяПозиция, СтрДлина(Строка));
ЗнакНаправленияДвижения = -1;
Иначе
НачальнаяПозиция = ?(НачальнаяПозиция <> Неопределено, НачальнаяПозиция, 1);
ЗнакНаправленияДвижения = 1;
КонецЕсли;
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
Пока Истина
И НомерВхождения <> 0
И (Ложь
Или (Истина
И Не НаправлениеПоискаСКонца
И НачальнаяПозиция <= СтрДлина(Строка))
Или (Истина
И НаправлениеПоискаСКонца
И НачальнаяПозиция >= 0))
Цикл
Позиция = Найти(Сред(Строка, НачальнаяПозиция, ДлинаСтрПоиска), ПодстрокаПоиска);
Если Позиция Тогда
ТекущаяПозиция = НачальнаяПозиция;
НачальнаяПозиция = ТекущаяПозиция + ДлинаСтрПоиска * ЗнакНаправленияДвижения;
НомерВхождения = НомерВхождения - 1;
Иначе
НачальнаяПозиция = НачальнаяПозиция + 1 * ЗнакНаправленияДвижения;
КонецЕсли;
КонецЦикла;
Иначе
// Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
Пока Истина И НомерВхождения <> 0 И (Ложь Или (Истина И Не НаправлениеПоискаСКонца И НачальнаяПозиция <= СтрДлина(Строка)) Или (Истина И НаправлениеПоискаСКонца И НачальнаяПозиция >= 0)) Цикл Позиция = Найти(Сред(Строка, НачальнаяПозиция, ДлинаСтрПоиска), ПодстрокаПоиска); Если Позиция Тогда ТекущаяПозиция = НачальнаяПозиция; НачальнаяПозиция = ТекущаяПозиция + ДлинаСтрПоиска * ЗнакНаправленияДвижения; НомерВхождения = НомерВхождения - 1; Иначе НачальнаяПозиция = НачальнаяПозиция + 1 * ЗнакНаправленияДвижения; КонецЕсли; КонецЦикла;
КонецЕсли;
Если НомерВхождения Тогда
ТекущаяПозиция = 0;
КонецЕсли;
Возврат ТекущаяПозиция;
КонецФункции
Функция ЛиДоступенМодуль83() Экспорт
#Если Клиент Тогда
Попытка
Возврат ирПлатформа.ЛиРежимСовместимости83 И ирОбщий83 <> Неопределено;
Исключение
// Попытка для ускорения
Возврат Ложь;
КонецПопытки;
#Иначе
//Возврат = ирКэш.НомерРежимаСовместимостиЛкс() >= 803006; // Будет бесконечная при инициации ирПлатформа
Возврат Ложь;
#КонецЕсли
КонецФункции
// Функция - Стр начинается с лкс
//
// Параметры:
// ГдеИщем - -
// ЧтоИщем - -
// УчитыватьРегистр - Булево -
//
// Возвращаемое значение:
// -
//
Функция СтрНачинаетсяСЛкс(ГдеИщем, ЧтоИщем, УчитыватьРегистр = Ложь) Экспорт
Возврат Ложь
Или (Истина
И УчитыватьРегистр
И Лев(ГдеИщем, СтрДлина(ЧтоИщем)) = ЧтоИщем)
Или (Истина
И Не УчитыватьРегистр
И Лев(НРег(ГдеИщем), СтрДлина(ЧтоИщем)) = НРег(ЧтоИщем));
КонецФункции
// Функция разбивает строку разделителем. Сильно отличается от системной функции СтрРазделить()!
// Старые имена - РазбитьСтрокуРазделителем, ПолучитьМассивИзСтрокиСРазделителем
//
// Параметры:
// Стр - Строка - которую разбиваем
// Разделитель - Строка - последовательность символов, трактуемая как разделитель
// ОбрезатьНепечатныеСимволы - Булево - делать СокрЛП
// ОставлятьПустуюСтроку - Булево - если передана пустая строка, то добавлять ее в массив
// УчитыватьКавычки - Булево - если да, то разделители внутри кавычек игнорируются, а сами крание кавычки фрагментов удаляются
// ПропускатьПустые - Булево - если да, то пропускать пустые фрагменты
//
// Возвращаемое значение:
// Массив - фрагментов.
//
Функция СтрРазделитьЛкс(Знач Стр, Знач Разделитель = ".", Знач ОбрезатьНепечатныеСимволы = Ложь, Знач ОставлятьПустуюСтроку = Истина, Знач УчитыватьКавычки = Ложь, Знач ПропускатьПустые = Ложь,
Знач ТолькоПервыйРазделитель = Ложь, Знач УчитыватьРегистр = Истина) Экспорт
_РежимОтладки = Ложь;
Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1)
// Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах.
МассивСтрок = Новый Массив;
Если Истина
И Не ОставлятьПустуюСтроку
И ПустаяСтрока(Стр)
Тогда
Возврат МассивСтрок;
КонецЕсли;
НужнаПостобработка = Ложь
Или ПропускатьПустые
Или УчитыватьКавычки И Найти(Стр, """") > 0;
Если Истина
И СтрДлина(Разделитель) = 1
И Не ОбрезатьНепечатныеСимволы
И Не ТолькоПервыйРазделитель
И УчитыватьРегистр
И ЛиДоступенМодуль83()
Тогда
МассивСтрок = ирОбщий83.СтрРазделитьЛкс(Стр, Разделитель, Не ПропускатьПустые);
ИначеЕсли Разделитель = " " Тогда
Стр = СокрЛП(Стр);
Пока 1=1 Цикл
Поз = Найти(Стр, Разделитель);
Если Поз=0 Тогда
МассивСтрок.Добавить(Стр);
Прервать;
КонецЕсли;
МассивСтрок.Добавить(Лев(Стр, Поз-1));
Стр = СокрЛ(Сред(Стр, Поз));
Если ТолькоПервыйРазделитель Тогда
МассивСтрок.Добавить(Стр);
Прервать;
КонецЕсли;
КонецЦикла;
Иначе
ОбрезатьНепечатныеСимволыСразу = ОбрезатьНепечатныеСимволы И Не НужнаПостобработка;
ДлинаРазделителя = СтрДлина(Разделитель);
Пока 1=1 Цикл
Поз = Найти(Стр, Разделитель);
Если Поз=0 Тогда
Фрагмент = Стр;
Если ОбрезатьНепечатныеСимволыСразу Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Прервать;
КонецЕсли;
Фрагмент = Лев(Стр, Поз-1);
Если ОбрезатьНепечатныеСимволыСразу Тогда
Фрагмент = СокрЛП(Фрагмент);
КонецЕсли;
МассивСтрок.Добавить(Фрагмент);
Стр = Сред(Стр, Поз+ДлинаРазделителя);
Если ТолькоПервыйРазделитель Тогда
МассивСтрок.Добавить(Стр);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если НужнаПостобработка Тогда
СтроковыйЛитерал = Неопределено;
Для Индекс = 1 - МассивСтрок.Количество() По 0 Цикл // Обратный обход
ТекстЯчейки = МассивСтрок[-Индекс];
Если СтроковыйЛитерал = Неопределено И Прав(СтрЗаменить(ТекстЯчейки, """""", ""), 1) = """" Тогда
СтроковыйЛитерал = ТекстЯчейки;
ИначеЕсли СтроковыйЛитерал <> Неопределено Тогда
СтроковыйЛитерал = ТекстЯчейки + Разделитель + СтроковыйЛитерал;
КонецЕсли;
Если Истина
И СтроковыйЛитерал <> Неопределено
И Лев(СтрЗаменить(СтроковыйЛитерал, """""", ""), 1) = """"
Тогда
ТекстЯчейки = ТекстИзВстроенногоЯзыкаЛкс(СтроковыйЛитерал);
СтроковыйЛитерал = Неопределено;
ИначеЕсли Не ОбрезатьНепечатныеСимволы Тогда
Продолжить;
КонецЕсли;
Если Ложь
Или СтроковыйЛитерал <> Неопределено
Или ПропускатьПустые И ПустаяСтрока(ТекстЯчейки)
Тогда
МассивСтрок.Удалить(-Индекс);
Иначе
Если ОбрезатьНепечатныеСимволы Тогда
ТекстЯчейки = СокрЛП(ТекстЯчейки);
КонецЕсли;
МассивСтрок[-Индекс] = ТекстЯчейки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Иначе
// Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика"
МассивСтрок = Новый Массив; Если Истина И Не ОставлятьПустуюСтроку И ПустаяСтрока(Стр) Тогда Возврат МассивСтрок; КонецЕсли; НужнаПостобработка = Ложь Или ПропускатьПустые Или УчитыватьКавычки И Найти(Стр, """") > 0; Если Истина И СтрДлина(Разделитель) = 1 И Не ОбрезатьНепечатныеСимволы И Не ТолькоПервыйРазделитель И УчитыватьРегистр И ЛиДоступенМодуль83() Тогда МассивСтрок = ирОбщий83.СтрРазделитьЛкс(Стр, Разделитель, Не ПропускатьПустые); ИначеЕсли Разделитель = " " Тогда Стр = СокрЛП(Стр); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; МассивСтрок.Добавить(Лев(Стр, Поз-1)); Стр = СокрЛ(Сред(Стр, Поз)); Если ТолькоПервыйРазделитель Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; КонецЦикла; Иначе ОбрезатьНепечатныеСимволыСразу = ОбрезатьНепечатныеСимволы И Не НужнаПостобработка; ДлинаРазделителя = СтрДлина(Разделитель); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда Фрагмент = Стр; Если ОбрезатьНепечатныеСимволыСразу Тогда Фрагмент = СокрЛП(Фрагмент); КонецЕсли; МассивСтрок.Добавить(Фрагмент); Прервать; КонецЕсли; Фрагмент = Лев(Стр, Поз-1); Если ОбрезатьНепечатныеСимволыСразу Тогда Фрагмент = СокрЛП(Фрагмент); КонецЕсли; МассивСтрок.Добавить(Фрагмент); Стр = Сред(Стр, Поз+ДлинаРазделителя); Если ТолькоПервыйРазделитель Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; КонецЦикла; КонецЕсли; Если НужнаПостобработка Тогда СтроковыйЛитерал = Неопределено; Для Индекс = 1 - МассивСтрок.Количество() По 0 Цикл ТекстЯчейки = МассивСтрок[-Индекс]; Если СтроковыйЛитерал = Неопределено И Прав(СтрЗаменить(ТекстЯчейки, """""", ""), 1) = """" Тогда СтроковыйЛитерал = ТекстЯчейки; ИначеЕсли СтроковыйЛитерал <> Неопределено Тогда СтроковыйЛитерал = ТекстЯчейки + Разделитель + СтроковыйЛитерал; КонецЕсли; Если Истина И СтроковыйЛитерал <> Неопределено И Лев(СтрЗаменить(СтроковыйЛитерал, """""", ""), 1) = """" Тогда ТекстЯчейки = ТекстИзВстроенногоЯзыкаЛкс(СтроковыйЛитерал); СтроковыйЛитерал = Неопределено; ИначеЕсли Не ОбрезатьНепечатныеСимволы Тогда Продолжить; КонецЕсли; Если Ложь Или СтроковыйЛитерал <> Неопределено Или ПропускатьПустые И ПустаяСтрока(ТекстЯчейки) Тогда МассивСтрок.Удалить(-Индекс); Иначе Если ОбрезатьНепечатныеСимволы Тогда ТекстЯчейки = СокрЛП(ТекстЯчейки); КонецЕсли; МассивСтрок[-Индекс] = ТекстЯчейки; КонецЕсли; КонецЦикла; КонецЕсли;
КонецЕсли;
Возврат МассивСтрок;
КонецФункции
// Функция платформы СтрЧислоСтрок() не учитывает последнюю пустую строку https://partners.v8.1c.ru/forum/topic/472085 .
// А эта функция учитывает все строки.
Функция СтрЧислоСтрокЛкс(Знач Текст) Экспорт
Возврат СтрЧислоСтрок(Текст + "й");
КонецФункции
// Получает подстроку заключенную между первым вхождением начального маркера и первым вхождением
// в правой части конечного маркера. Сами маркеры не включаются в результат. Опционально - если
// маркер не найден, то границей считается граница строки.
//
// Параметры:
// Текст - Строка - в которой ищем;
// НачальныйМаркер - Строка, *Неопределено - начальный маркер подстроки;
// КонечныйМаркер - Строка, *Неопределено - конечный маркер подстроки;
// БратьГраницуЕслиНачальныйМаркерНеНайден - Булево, *Истина - разрешение использования границ строки в случае, если маркер не найден;
// ВключатьМаркеры - Булево, *Ложь - включение маркеров в результат
// ВыброситьИсключениеЕслиНеНайдено - Булево -
// БратьГраницуЕслиКонечныйМаркерНеНайден - Булево, Неопределено - по умолчанию совпадает с БратьГраницуЕслиНачальныйМаркерНеНайден
//
// Возвращаемое значение:
// Неопределено - обязательные условия не выполнены;
// Строка - найденная подстрока.
//
Функция ТекстМеждуМаркерамиЛкс(Текст, НачальныйМаркер = Неопределено, КонечныйМаркер = Неопределено, БратьГраницуЕслиНачальныйМаркерНеНайден = Истина, ВключатьМаркеры = Ложь,
ВыброситьИсключениеЕслиНеНайдено = Ложь, Знач БратьГраницуЕслиКонечныйМаркерНеНайден = Неопределено) Экспорт
ПозицияНачальногоМаркера = Найти(Текст, НачальныйМаркер);
Если Истина
И ПозицияНачальногоМаркера = 0
И БратьГраницуЕслиНачальныйМаркерНеНайден = Ложь
Тогда
Если ВыброситьИсключениеЕслиНеНайдено Тогда
ВызватьИсключение "Не найдено вхождение начального маркера";
Иначе
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Если Ложь
ИЛИ НачальныйМаркер = Неопределено
ИЛИ ПозицияНачальногоМаркера = 0
Тогда
ПозицияНачальногоМаркера = - СтрДлина(НачальныйМаркер);
КонецЕсли;
Стр = Сред(Текст, ПозицияНачальногоМаркера + СтрДлина(НачальныйМаркер));
ПозицияКонечногоМаркера = Найти(Стр, КонечныйМаркер);
Если БратьГраницуЕслиКонечныйМаркерНеНайден = Неопределено Тогда
БратьГраницуЕслиКонечныйМаркерНеНайден = БратьГраницуЕслиНачальныйМаркерНеНайден;
КонецЕсли;
Если Истина
И ПозицияКонечногоМаркера = 0
И БратьГраницуЕслиКонечныйМаркерНеНайден = Ложь
Тогда
Если ВыброситьИсключениеЕслиНеНайдено Тогда
ВызватьИсключение "Не найдено вхождение конечного маркера";
Иначе
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
Если Ложь
ИЛИ КонечныйМаркер = Неопределено
ИЛИ ПозицияКонечногоМаркера = 0
Тогда
ПозицияКонечногоМаркера = СтрДлина(Стр) + 1;
КонецЕсли;
Результат = Лев(Стр, ПозицияКонечногоМаркера - 1);
Если ВключатьМаркеры Тогда
Если НачальныйМаркер <> Неопределено Тогда
Результат = НачальныйМаркер + Результат;
КонецЕсли;
Если КонечныйМаркер <> Неопределено Тогда
Результат = Результат + КонечныйМаркер;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ПервыеНепечатныеСимволыПервойНепустойСтрокиЛкс(Текст) Экспорт
РегВыражение = ирКэш.ВычислительРегВыраженийЛкс();
РегВыражение.Global = Ложь;
РегВыражение.Pattern = "\S";
Результат = РегВыражение.НайтиВхождения(Текст);
Если Результат.Количество() > 0 Тогда
ТекстСмещения = Лев(Текст, Результат[0].FirstIndex);
ТекстСмещения = ПоследнийФрагментЛкс(ТекстСмещения, Символы.ПС);
Иначе
ТекстСмещения = "";
КонецЕсли;
Возврат ТекстСмещения;
КонецФункции
Функция ЛиВнутриТекстовогоЛитералаЛкс(Знач Текст) Экспорт
Возврат (?(Лев(СокрЛ(Текст), 1) = "|", 1, 0) + СтрЧислоВхождений(Текст, """")) % 2 = 1;
КонецФункции
Функция ЛиВнутриНепервойСтрокиТекстовогоЛитералаЛкс(Знач Текст) Экспорт
Возврат Истина
И Лев(СокрЛ(Текст), 1) = "|"
И СтрЧислоВхождений(Текст, """") % 2 = 0;
КонецФункции
Функция ЛиВнутриКомментарияЛкс(Знач Текст) Экспорт
СтрокаДоКомментария = ирОбщий.ПервыйФрагментЛкс(Текст, "//", Ложь);
Результат = Истина
И СтрокаДоКомментария <> Неопределено
И Не ЛиВнутриТекстовогоЛитералаЛкс(СтрокаДоКомментария);
Возврат Результат;
КонецФункции
Функция ЛиВнутриПрепроцессораЛкс(Знач Текст) Экспорт
Возврат Лев(СокрЛ(Текст), 1) = "#";
КонецФункции
// Дополняет массив МассивПриемник значениями из массива МассивИсточник.
//
// Параметры:
// МассивПриемник - Массив - массив, в который необходимо добавить значения.
// МассивИсточник - Массив - массив значений для заполнения.
// ТолькоУникальныеЗначения - Булево - если истина, то в массив будут включены только уникальные значения.
//
Процедура ДополнитьМассивЛкс(МассивПриемник, МассивИсточник, ТолькоУникальныеЗначения = Ложь) Экспорт
Если ТолькоУникальныеЗначения Тогда
УникальныеЗначения = СоответствиеИзМассиваЛкс(МассивПриемник);
КонецЕсли;
Для Каждого Значение Из МассивИсточник Цикл
Если ТолькоУникальныеЗначения Тогда
Если УникальныеЗначения[Значение] <> Неопределено Тогда
Продолжить;
КонецЕсли;
УникальныеЗначения.Вставить(Значение, Истина);
КонецЕсли;
МассивПриемник.Добавить(Значение);
КонецЦикла;
КонецПроцедуры
Функция СоответствиеИзМассиваЛкс(Знач Массив) Экспорт
УникальныеЗначения = Новый Соответствие;
Для Каждого Значение Из Массив Цикл
УникальныеЗначения.Вставить(Значение, Истина);
КонецЦикла;
Возврат УникальныеЗначения;
КонецФункции
Функция СоответствиеВМассивЛкс(Знач Соответствие, ПомещатьКлючи = Истина, ПомещатьЗначения = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
Соответствие = Новый Соответствие;
#КонецЕсли
Результат = Новый Массив;
Для Каждого КлючИЗначение Из Соответствие Цикл
Если ПомещатьКлючи Тогда
Результат.Добавить(КлючИЗначение.Ключ);
КонецЕсли;
Если ПомещатьЗначения Тогда
Результат.Добавить(КлючИЗначение.Значение);
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Возвращет массив без повторяющихся элементов.
//
// Параметры:
// Массив - Массив - массив произвольных значений.
//
// Возвращаемое значение:
// Массив - новая коллекция уникальных элементов.
//
Функция СвернутьМассивЛкс(Знач Массив) Экспорт
Результат = Новый Массив;
ДополнитьМассивЛкс(Результат, Массив, Истина);
Возврат Результат;
КонецФункции
// Функция - Пересечь массивы лкс
//
// Параметры:
// Массив1 - -
// Массив2 - -
// выхПрисутствующиеТолько1 - Массив, Неопределено - если передан массив, то он будет очищен и заполнен элементами, которые отсутствуют во втором массиве
//
// Возвращаемое значение:
// -
//
Функция ПересечьМассивыЛкс(Знач Массив1, Знач Массив2, выхПрисутствующиеТолькоВ1 = Неопределено) Экспорт
Элементы2 = СоответствиеИзМассиваЛкс(Массив2);
Результат = Новый Массив;
Если выхПрисутствующиеТолькоВ1 <> Неопределено Тогда
выхПрисутствующиеТолькоВ1.Очистить();
КонецЕсли;
Для Каждого Элемент1 Из Массив1 Цикл
Если Элементы2[Элемент1] = Неопределено Тогда
Если выхПрисутствующиеТолькоВ1 <> Неопределено Тогда
выхПрисутствующиеТолькоВ1.Добавить(Элемент1);
КонецЕсли;
Продолжить;
КонецЕсли;
Результат.Добавить(Элемент1);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция МассивИзКоллекцииЛкс(Знач Коллекция) Экспорт
Результат = Новый Массив;
Для Каждого Элемент Из Коллекция Цикл
Результат.Добавить(Элемент);
КонецЦикла;
Возврат Результат;
КонецФункции
Функция СоответствиеИзПредставленийСпискаЗначенийЛкс(Знач СписокЗначений) Экспорт
#Если Сервер И Не Сервер Тогда
СписокЗначений = Новый СписокЗначений;
#КонецЕсли
УникальныеЗначения = Новый Соответствие;
Для Каждого КлючИЗначение Из СписокЗначений Цикл
УникальныеЗначения.Вставить(КлючИЗначение.Представление, КлючИЗначение.Значение);
КонецЦикла;
Возврат УникальныеЗначения;
КонецФункции
// Дополняет список СписокПриемник значениями из массива СписокИсточник.
//
// Параметры:
// СписокПриемник - СписокЗначений - куда необходимо добавить элементы;
// СписокИсточник - СписокЗначений - элементы, которые надо добавить;
// ТолькоУникальныеПредставления - Булево - если истина, то в приемник будут включены только уникальные представления.
//
Процедура ДополнитьСписокЗначенийЛкс(СписокПриемник, СписокИсточник, ТолькоУникальныеПредставления = Ложь) Экспорт
#Если Сервер И Не Сервер Тогда
СписокИсточник = Новый СписокЗначений;
СписокПриемник = Новый СписокЗначений;
#КонецЕсли
Если ТолькоУникальныеПредставления Тогда
УникальныеЗначения = СоответствиеИзПредставленийСпискаЗначенийЛкс(СписокПриемник);
КонецЕсли;
Для Каждого ЭлементСписка Из СписокИсточник Цикл
Если ТолькоУникальныеПредставления Тогда
Если УникальныеЗначения[ЭлементСписка.Представление] <> Неопределено Тогда
Продолжить;
КонецЕсли;
УникальныеЗначения.Вставить(ЭлементСписка.Представление, Истина);
КонецЕсли;
СписокПриемник.Добавить(ЭлементСписка.Значение, ЭлементСписка.Представление, ЭлементСписка.Пометка, ЭлементСписка.Картинка);
КонецЦикла;
КонецПроцедуры
// Возвращет список значений без повторяющихся представлений.
//
// Параметры:
// СписокВход - СписокЗначений - список произвольных значений с представлениями.
//
// Возвращаемое значение:
// СписокЗначений - новая коллекция уникальных представлений.
//
Функция СвернутьСписокЗначенийПоПредставлениюЛкс(СписокВход) Экспорт
Результат = Новый СписокЗначений;
ДополнитьСписокЗначенийЛкс(Результат, СписокВход, Истина);
Возврат Результат;
КонецФункции
Функция ПроверитьЧтоСеансТолстогоКлиентаЛкс(НавигационнаяСсылка = "") Экспорт
Доступно = Ложь;
Если ирКэш.ЛиСеансТолстогоКлиентаЛкс() Тогда
Доступно = Истина;
#Если Клиент Тогда
ИначеЕсли ирКэш.ЛиСеансТонкогоКлиентаЛкс() Тогда
ОткрытьФорму("Обработка.ирПортативный.Форма.ЗапускСеансаУправляемая", Новый Структура("НавигационнаяСсылка", НавигационнаяСсылка));
#КонецЕсли
Иначе
СообщитьЛкс("Функция доступна только в толстом клиенте",,, Истина);
КонецЕсли;
Возврат Доступно;
КонецФункции
// Встроенный язык не поддерживает функциональную адресацию ячеек памяти в левом операнде присвоения. Например
// ПриложениеОбъект.Value("RunForever") = Истина
Процедура УстановитьЗначениеПоФункциональнойСсылкеЛкс(Объект, Значение, ИмяФункции, ПараметрФункции) Экспорт
СкриптМенеджер = ирКэш.СкриптМенеджерЛкс();
Скрипт = "
|Function SetFuncValue(Object, Parameter, Value)
|Object." + ИмяФункции + "(Parameter) = Value
|End Function
|";
СкриптМенеджер.Language = "vbscript";
СкриптМенеджер.AddCode(Скрипт);
СкриптМенеджер.Run("SetFuncValue", Объект, ПараметрФункции, Значение);
КонецПроцедуры
Функция МинимальнаяШиринаКолонкиЛкс() Экспорт
Возврат 5; // Начиная с 5 гарантируется возможность увеличения ширины перетаскиванием даже при очень большом числе колонок
КонецФункции
// Возвращает значение свойства структуры.
//
// Параметры:
// Структура - Структура, ФиксированнаяСтруктура, ДанныеФормыСтруктура, ДанныеФормыЭлементКоллекции, ДанныеФормыЭлементДерева - объект, из которого необходимо прочитать значение ключа.
// Ключ - Строка - имя свойства структуры, для которого необходимо прочитать значение.
// ЗначениеПоУмолчанию - Произвольный - необязательный. Возвращается когда в структуре нет значения по указанному ключу.
// Для скорости рекомендуется передавать только быстро вычисляемые значения (например примитивные типы),
// а инициализацию более тяжелых значений выполнять после проверки полученного значения (только если это требуется).
//
// Возвращаемое значение:
// Произвольный - значение свойства структуры. ЗначениеПоУмолчанию если в структуре нет указанного свойства.
//
Функция СвойствоСтруктурыЛкс(Знач Структура, Знач Ключ, Знач ЗначениеПоУмолчанию = Неопределено) Экспорт
Перем Результат;
Если Структура = Неопределено Тогда
Возврат ЗначениеПоУмолчанию;
КонецЕсли;
Если Структура.Свойство(Ключ, Результат) Тогда
Возврат Результат;
Иначе
Возврат ЗначениеПоУмолчанию;
КонецЕсли;
КонецФункции
// Тяжелый метод. Попытка-Исключение в 5-10 раз быстрее на малой глубине стека.
Функция ЕстьСвойствоОбъектаЛкс(Объект, Свойство) Экспорт
УникальноеЗначение = "м86ыщшру5аа7шлв9823454";
Структура = Новый Структура(Свойство, УникальноеЗначение);
ЗаполнитьЗначенияСвойств(Структура, Объект);
Результат = Структура[Свойство] <> УникальноеЗначение;
Возврат Результат;
КонецФункции
Функция РасширениеКонфигурацииОбъектаМДЛкс(ОбъектМД) Экспорт
Результат = Неопределено;
Если ирКэш.НомерВерсииПлатформыЛкс() > 803007 Тогда
Результат = ОбъектМД.РасширениеКонфигурации();
КонецЕсли;
Возврат Результат;
КонецФункции
//.
// Параметры:
// МетаданныеРодителя - ? -
// Возвращаемое значение:
// ТаблицаЗначений -
Функция ЛиФормаИлиИмитаторЛкс(Знач МетаданныеРодителя, Знач ПроверятьОбычную = Истина) Экспорт
ТипУправляемаяФорма = ТипУправляемаяФормаЛкс();
Результат = Ложь
#Если Клиент Тогда
Или ПроверятьОбычную И ТипЗнч(МетаданныеРодителя) = Тип("Структура") И СвойствоСтруктурыЛкс(МетаданныеРодителя, "Тип") = Тип("Форма")
Или ПроверятьОбычную И ТипЗнч(МетаданныеРодителя) = Тип("Форма")
#КонецЕсли
Или ТипЗнч(МетаданныеРодителя) = Тип("Структура") И СвойствоСтруктурыЛкс(МетаданныеРодителя, "Тип") = ТипУправляемаяФорма
Или ТипЗнч(МетаданныеРодителя) = ТипУправляемаяФорма;
Возврат Результат;
КонецФункции
Функция ЛиИмяТипаФормыЛкс(Знач ИмяОбщегоТипа, Знач ПроверятьОбычную = Ложь, Знач ПроверятьУправляемую = Истина) Экспорт
ЛиУправляемая = СтрНачинаетсяСЛкс(ИмяОбщегоТипа, "РасширениеФормыКлиент");
Возврат Ложь
Или (Истина
И ПроверятьУправляемую
И (Ложь
Или ЛиУправляемая
Или ИмяОбщегоТипа = "ФормаКлиентскогоПриложения"
//Или ИмяОбщегоТипа = "УправляемаяФорма"
))
Или (Истина
И ПроверятьОбычную
И (Ложь
Или ИмяОбщегоТипа = "Форма"
Или Не ЛиУправляемая И СтрНачинаетсяСЛкс(ИмяОбщегоТипа, "РасширениеФормы")))
;
КонецФункции
Функция ЛиИмяТипаВнешнегоОбъектаМетаданныхЛкс(Знач ИмяОбщегоТипа) Экспорт
Результат = Ложь
Или ИмяОбщегоТипа = "ВнешняяОбработкаОбъект.<Имя внешней обработки>"
Или ИмяОбщегоТипа = "ВнешнийОтчетОбъект.<Имя внешнего отчета>";
Возврат Результат;
КонецФункции
Функция ТипУправляемаяФормаЛкс() Экспорт
Возврат Тип("УправляемаяФорма");
//! Возврат Тип("ФормаКлиентскогоПриложения");
КонецФункции
Функция ЛиАсинхронностьДоступнаЛкс() Экспорт
#Если Клиент Тогда
Возврат Истина
И Не ирКэш.Получить().АсинхронностьЗапрещена
И ирКэш.НомерВерсииПлатформыЛкс() <> 803009 // https://www.hostedredmine.com/issues/936748
И (Не ирКэш.ЛиФайловаяБазаЛкс() Или ирКэш.НомерРежимаСовместимостиЛкс() >= 803001)
И Не ирКэш.ЛиПортативныйРежимЛкс()
#Если Клиент И Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда
И Не МонопольныйРежим()
// https://www.hostedredmine.com/issues/925027
И Не СтрКончаетсяНаЛкс(ПользователиИнформационнойБазы.ТекущийПользователь().ПолноеИмя, МаркерВременныхРолейЛкс())
#КонецЕсли
;
#Иначе
Возврат Ложь;
#КонецЕсли
КонецФункции
///////////////////////////////////////////////////
// Управляемые формы
// Ищет элемент нужного типа, начиная с указанного, шагая по родителям.
//
// Параметры:
// Элемент - ЭлементФормы - произвольный элемент формы, с которого начинаем поиск
// ТипРодителя - Тип, *Неопределено - тип искомого элемента, при Неопределено используется ТипУправляемаяФормаЛкс(), при "все" тип не проверяется
// Свойство - Строка - проверять свойство
// ЗначениеСвойства - Произвольный - проверять значение свойства
//
// Возвращаемое значение:
// УправляемаяФорма, ТаблицаФормы, ГруппаФормы -
//
Функция РодительЭлементаУправляемойФормыЛкс(Знач Элемент, ТипРодителя = Неопределено, Знач Свойство = "", Знач ЗначениеСвойства = Неопределено, Знач СамыйВерхний = Ложь) Экспорт
ТипУправляемаяФорма = ТипУправляемаяФормаЛкс();
Если ТипРодителя = Неопределено Тогда
ТипРодителя = ТипУправляемаяФорма;
КонецЕсли;
Результат = Неопределено;
Пока Истина Цикл
Если Истина
И (Ложь
Или ТипРодителя = "все"
Или ТипЗнч(Элемент) = ТипРодителя)
И (Ложь
Или Не ЗначениеЗаполнено(Свойство)
Или Элемент[Свойство] = ЗначениеСвойства)
Тогда
Результат = Элемент;
Если Не СамыйВерхний Тогда
Прервать;
КонецЕсли;
КонецЕсли;
Если ТипЗнч(Элемент) = ТипУправляемаяФорма Тогда
Прервать;
КонецЕсли;
Попытка
Элемент = Элемент.Родитель;
Исключение
// Ошибка платформы http://www.hostedredmine.com/issues/880476
Родитель = Неопределено;
Прервать;
КонецПопытки;
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Все подчиненные элементы формы лкс
//
// Параметры:
// ГруппаФормы - ФормаКлиентскогоПриложения, ГруппаФормы -
// ВключаяГруппы - Булево -
// Результат - - служебный параметр для рекурсии
//
// Возвращаемое значение:
// Массив -
//
Функция ВсеПодчиненныеЭлементыФормыЛкс(Знач ГруппаФормы, Знач ВключаяГруппы = Ложь, Знач Результат = Неопределено) Экспорт
Если Результат = Неопределено Тогда
Результат = Новый Массив;
КонецЕсли;
Для Каждого Подчиненный Из ГруппаФормы.ПодчиненныеЭлементы Цикл
Если ТипЗнч(Подчиненный) = Тип("ГруппаФормы") Тогда
ВсеПодчиненныеЭлементыФормыЛкс(Подчиненный, ВключаяГруппы, Результат);
Если Не ВключаяГруппы Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
Результат.Добавить(Подчиненный);
КонецЦикла;
Возврат Результат;
КонецФункции
// Путь - можно передавать как полный путь к реквизиту, так и путь к родительскому реквизиту
//
// Параметры:
// ЭтаФорма - <тип> -
// Путь - <тип>, "" -
// ИмяРеквизита - <тип>, "" -
//
// Возвращаемое значение:
//
Функция ПолучитьРеквизитФормыЛкс(ЭтаФорма, Знач Путь = "", Знач ИмяРеквизита = "") Экспорт
Если Не ЗначениеЗаполнено(ИмяРеквизита) Тогда
Фрагменты = СтрРазделитьЛкс(Путь);
ИмяРеквизита = Фрагменты[Фрагменты.Количество() - 1];
Фрагменты.Удалить(Фрагменты.Количество() - 1);
Путь = СтрСоединитьЛкс(Фрагменты, ".");
КонецЕсли;
Результат = Неопределено;
РеквизитыФормы = ЭтаФорма.ПолучитьРеквизиты(Путь);
Для Каждого РеквизитФормы Из РеквизитыФормы Цикл
Если НРег(РеквизитФормы.Имя) = Нрег(ИмяРеквизита) Тогда
Результат = РеквизитФормы;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Получить тип реквизита формы
//
// Параметры:
// ЭтаФорма - <тип> -
// Путь - <тип>, "" -
// ИмяРеквизита - <тип> -
//
// Возвращаемое значение:
//
Функция ПолучитьТипРеквизитаФормыЛкс(ЭтаФорма, Путь = "", ИмяРеквизита = "") Экспорт
РеквизитФормы = ПолучитьРеквизитФормыЛкс(ЭтаФорма, Путь, ИмяРеквизита);
Результат = РеквизитФормы.ТипЗначения.Типы()[0];
Возврат Результат;
КонецФункции
// Получить путь к данным элемента управляемой формы. Чтобы функция возвращала правильное значение, в форме должен быть
// выполнен общий обработчик УправляемаяФорма_ПриСозданииЛкс.
//
// Параметры:
// ЭлементФормы - Структура, ЭлементФормы -
// ОтносительноРодителя - -
// ЭтаФорма - -
//
// Возвращаемое значение:
// Строка -
//
Функция ПутьКДаннымЭлементаУправляемойФормыЛкс(Знач ЭлементФормы, ОтносительноРодителя = Ложь, Знач ЭтаФорма = Неопределено) Экспорт
Если ЭтаФорма = Неопределено Тогда
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(ЭлементФормы, ТипУправляемаяФормаЛкс());
КонецЕсли;
ПутьКДаннымПоля = "";
#Если Не ТонкийКлиент И Не ВебКлиент Тогда
Если ЭлементФормы <> ЭтаФорма Тогда
СлужебныеДанные = СлужебныеДанныеФормыЛкс(ЭтаФорма);
//СообщитьЛкс(Поле.Имя); // Для отладки http://www.hostedredmine.com/issues/850205, http://www.hostedredmine.com/issues/850204
Если СлужебныеДанные <> Неопределено Тогда
Если СлужебныеДанные.Свойство("Элементы") Тогда
Если СлужебныеДанные.Элементы.Свойство(ЭлементФормы.Имя) Тогда
ПутьКДаннымПоля = СлужебныеДанные.Элементы[ЭлементФормы.Имя].ПутьКДанным;
КонецЕсли;
ИначеЕсли Истина
И СлужебныеДанные.Свойство("ПутиКДанным")
И Не СлужебныеДанные.ПутиКДанным.Свойство(ЭлементФормы.Имя, ПутьКДаннымПоля)
Тогда
ПутьКДаннымПоля = "";
КонецЕсли;
КонецЕсли;
Если ОтносительноРодителя Тогда
ПутьКДаннымПоля = ПоследнийФрагментЛкс(ПутьКДаннымПоля, "." + ПеревестиСтроку("ТекущиеДанные") + ".", Ложь);
Если Не ЗначениеЗаполнено(ПутьКДаннымПоля) Тогда
ПутьКДаннымПоля = ПоследнийФрагментЛкс(ПутьКДаннымПоля);
КонецЕсли;
КонецЕсли;
КонецЕсли;
#КонецЕсли
Если ТипЗнч(ЭлементФормы) = Тип("Структура") Тогда
ПутьКДаннымПоля = СвойствоСтруктурыЛкс(ЭлементФормы, "ПутьКДанным");
КонецЕсли;
Если Не ЗначениеЗаполнено(ПутьКДаннымПоля) Тогда
// Криво, но для управляемой формы на клиенте других способов нет
Попытка
Пустышка = ЭтаФорма[ЭлементФормы.Имя];
ПутьКДаннымПоля = ЭлементФормы.Имя;
Исключение
КонецПопытки;
КонецЕсли;
Возврат ПутьКДаннымПоля;
КонецФункции
Процедура СкопироватьКнопкиКоманднойПанелиУправляемойФормыЛкс(Знач КоманднаяПанельИсточник, Знач КоманднаяПанельПриемник, Знач ПрефиксИмени) Экспорт
ЭтаФорма = РодительЭлементаУправляемойФормыЛкс(КоманднаяПанельИсточник);
ЭлементыФормы = ЭтаФорма.Элементы;
Для Каждого КнопкаОбразец Из КоманднаяПанельИсточник.ПодчиненныеЭлементы Цикл
Если Ложь
Или ТипЗнч(КнопкаОбразец) = Тип("ГруппаФормы")
Или Не ЗначениеЗаполнено(КнопкаОбразец.ИмяКоманды)
Тогда
// Это - системная команда
Продолжить;
КонецЕсли;
ИмяНовойКнопки = ПрефиксИмени + КнопкаОбразец.Имя;
НоваяКнопка = ЭлементыФормы.Добавить(ИмяНовойКнопки, ТипЗнч(КнопкаОбразец), КоманднаяПанельПриемник);
ЗаполнитьЗначенияСвойств(НоваяКнопка, КнопкаОбразец,, "Имя");
КонецЦикла;
КонецПроцедуры
//.
// Параметры:
// НачальнаяСтрока - ДанныеФормыДерево -
// КлючиУровней - Массив -
// ИмяКлючевойКолонки - Строка - если пустое, то будет использован индекс элементов дерева
// Возвращаемое значение:
// ДанныеФормыЭлементДерева -
Функция НайтиСтрокуДереваФормыПоАдресуЛкс(НачальнаяСтрока, КлючиУровней, Знач ИмяКлючевойКолонки = "Ссылка") Экспорт
ТекущаяСтрока = НачальнаяСтрока;
Уровень = 0;
Для Уровень = 0 По КлючиУровней.Количество() - 1 Цикл
ЭлементыДерева = ТекущаяСтрока.ПолучитьЭлементы();
ЗначениеКлюча = КлючиУровней[Уровень];
Если Не ЗначениеЗаполнено(ИмяКлючевойКолонки) Тогда
НайденнаяСтрока = Неопределено;
Если ЭлементыДерева.Количество() > ЗначениеКлюча Тогда
НайденнаяСтрока = ЭлементыДерева[ЗначениеКлюча];
КонецЕсли;
Иначе
НайденнаяСтрока = НайтиЭлементКоллекцииЛкс(ЭлементыДерева, ИмяКлючевойКолонки, ЗначениеКлюча);
КонецЕсли;
Если НайденнаяСтрока <> Неопределено Тогда
ТекущаяСтрока = НайденнаяСтрока;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ТекущаяСтрока;
КонецФункции
#Если Сервер И Не Сервер Тогда
ирПортативный = Обработки.ирПортативный.Создать();
#КонецЕсли