//////////////////////////////////////////////////////////////////////////////// // Подсистема "Инструменты разработчика Tormozit" // Авторское право (с) 2007-2023, Старых С.А. // Лицензия 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) Экспорт УстановитьПривилегированныйРежимЛкс(); #Если Сервер И Не Клиент Тогда РежимОперации = 2; #КонецЕсли МассивИмен = СтрРазделитьЛкс(СтрокаИменПараметров, ",", Истина); Если МассивИмен.Количество() > 0 Тогда Если МассивИмен[0] = "" Тогда МассивИмен.Удалить(0); КонецЕсли; КонецЕсли; ЧислоПараметров = 9; ПереданныеПараметры = Новый СписокЗначений; Для Счетчик = 1 По ЧислоПараметров Цикл ИмяПараметра = "П" + Счетчик; ЗначениеПараметра = Вычислить(ИмяПараметра); Если Ложь Или ЗначениеПараметра <> Null // Опасный трюк в интерактивном режиме. Отрезает параметры, переданные, но имеющие значение Null. Или РежимОперации = 2 Тогда ПсевдонимПараметра = ИмяПараметра; Если МассивИмен.Количество() > Счетчик - 1 Тогда ПсевдонимПараметра = МассивИмен[Счетчик - 1]; КонецЕсли; ПереданныеПараметры.Добавить(ЗначениеПараметра, ПсевдонимПараметра); КонецЕсли; КонецЦикла; Если РежимОперации < 2 Тогда #Если Клиент Тогда ФормаОтладки = ирКлиент.ПолучитьФормуЛкс("Обработка.ирКонсольКода.Форма", , , Новый УникальныйИдентификатор); ФормаОтладки.мРежимРедактора = Истина; ФормаОтладки.мСписокВнешнихПараметров = ПереданныеПараметры; ФормаОтладки.ПараметрТекст = ТекстПрограммы; Если РежимОперации = 0 Тогда ФормаОтладки.Открыть(); Возврат Неопределено; КонецЕсли; ПолученныеПараметры = ФормаОтладки.ОткрытьМодально(); Если ПолученныеПараметры = Неопределено Тогда Возврат Неопределено; КонецЕсли; #КонецЕсли Иначе ТекстПрограммы = ТекстПрограммы + ";"; Для Индекс = 0 По ПереданныеПараметры.Количество() - 1 Цикл ВнешнийПараметр = ПереданныеПараметры[Индекс]; ТекстПрограммы = ВнешнийПараметр.Представление + "=" + "_АлгоритмОбъект[" + Индекс + "].Значение;" + Символы.ПС + ТекстПрограммы; ТекстПрограммы = ТекстПрограммы + Символы.ПС + "_АлгоритмОбъект[" + Индекс + "].Значение = " + ВнешнийПараметр.Представление + ";"; КонецЦикла; ВыполнитьАлгоритм(ТекстПрограммы, ПереданныеПараметры); ПолученныеПараметры = ПереданныеПараметры; КонецЕсли; ОписаниеОшибок = ""; НовоеЗначение = Неопределено; Для Счетчик = 1 По ЧислоПараметров Цикл ИмяПараметра = "П" + Счетчик; НовоеЗначение = Неопределено; Если ПолученныеПараметры.Количество() > Счетчик - 1 Тогда НовоеЗначение = ПолученныеПараметры[Счетчик - 1].Значение; КонецЕсли; Если Вычислить(ИмяПараметра) <> НовоеЗначение Тогда Попытка Выполнить(ИмяПараметра + " = НовоеЗначение"); Исключение ПсевдонимПараметра = ИмяПараметра; Если МассивИмен.Количество() > Счетчик - 1 Тогда ПсевдонимПараметра = МассивИмен[Счетчик - 1]; КонецЕсли; ОписаниеОшибки = "Ошибка возвращения параметра " + ПсевдонимПараметра + ": " + ОписаниеОшибки(); ОписаниеОшибок = ОписаниеОшибок + ОписаниеОшибки; СообщитьЛкс(ОписаниеОшибки); КонецПопытки; КонецЕсли; КонецЦикла; Возврат ОписаниеОшибок; КонецФункции // Подготавливает выражение встроенного языка для помещения всех переменных в структуру с целью ее дальнейшего вычисления в отладчике "Вычислить(Пер())". // Длина выражения в отладчике имеет ограничение 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 - допустимое количество строк для каждой временной таблицы запроса // для отложенной отладки, больше этого количества строки не сохраняются, о чем сообщается в результате; // Наименование - Строка, * - наименование сохраняемого объекта отложенной отладки; // МенеджерВременныхТаблиц - МенеджерВременныхТаблиц, * - менеджер временных таблиц для компоновки данных; // // Возвращаемое значение: // Неопределено. // Функция ОтладитьЛкс(Знач Объект, Модально = Ложь, Знач Объект2 = Неопределено, Знач ВнешниеНаборыДанных = Неопределено, ОтложенноеВыполнение = Ложь, ПорогОбрезкиВременнойТаблицы = 500000, выхОбъектДляОтладки = Неопределено, Наименование = "", Знач МенеджерВременныхТаблиц = Неопределено, Знач ФорматВнутр = Истина) Экспорт УстановитьПривилегированныйРежимЛкс(); #Если Не Клиент Тогда ОтложенноеВыполнение = Истина; #КонецЕсли Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() И ирКэш.ЛиПортативныйРежимЛкс() Тогда ОтложенноеВыполнение = Истина; КонецЕсли; ТребоватьТипЛкс(Модально, "Модально", Тип("Булево")); ТребоватьТипЛкс(ОтложенноеВыполнение, "ОтложенноеВыполнение", Тип("Булево")); ТребоватьТипЛкс(ВнешниеНаборыДанных, "ВнешниеНаборыДанных", Тип("Неопределено"), Тип("Структура")); ТребоватьТипЛкс(Объект2, "Объект2", Тип("Неопределено"), Тип("Строка"), Тип("НастройкиКомпоновкиДанных"), Тип("HTTPЗапрос")); Если ТипЗнч(Объект) = Тип("МенеджерВременныхТаблиц") Тогда МенеджерВременныхТаблиц = Объект; Объект = Новый Запрос; Объект.Текст = "ВЫБРАТЬ 1"; Объект.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц; КонецЕсли; Если Не ОтложенноеВыполнение Тогда ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Объект)); #Если Клиент Тогда Если Ложь Или ТипЗнч(Объект) = Тип("Запрос") Или ТипЗнч(Объект) = Тип("COMОбъект") Тогда КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов"); #Если Сервер И Не Сервер Тогда КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать(); #КонецЕсли Результат = КонсольЗапросов.ОткрытьДляОтладки(Объект, , , Модально, Объект2); ИначеЕсли ТипЗнч(Объект) = Тип("ПостроительЗапроса") Тогда КонсольЗапросов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольЗапросов"); #Если Сервер И Не Сервер Тогда КонсольЗапросов = Обработки.ирКонсольЗапросов.Создать(); #КонецЕсли Результат = КонсольЗапросов.ОткрытьДляОтладки(Объект.ПолучитьЗапрос(), , , Модально); ИначеЕсли ТипЗнч(Объект) = Тип("ПостроительОтчета") Тогда КонсольПостроителейОтчетов = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольПостроителейОтчетов"); #Если Сервер И Не Сервер Тогда КонсольПостроителейОтчетов = Обработки.ирКонсольПостроителейОтчетов.Создать(); #КонецЕсли Результат = КонсольПостроителейОтчетов.ОткрытьДляОтладки(Объект, Модально); ИначеЕсли Ложь Или ТипЗнч(Объект) = Тип("СхемаКомпоновкиДанных") Или ТипЗнч(Объект) = Тип("МакетКомпоновкиДанных") Тогда КонсольКомпоновкиДанных = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольКомпоновокДанных"); #Если Сервер И Не Сервер Тогда КонсольКомпоновкиДанных = Обработки.ирКонсольКомпоновокДанных.Создать(); #КонецЕсли Результат = КонсольКомпоновкиДанных.ОткрытьДляОтладки(Объект, Объект2, ВнешниеНаборыДанных, Модально,,, МенеджерВременныхТаблиц); ИначеЕсли Истина И ОбъектМД <> Неопределено И Метаданные.Отчеты.Индекс(ОбъектМД) <> -1 Тогда КонсольКомпоновкиДанных = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирКонсольКомпоновокДанных"); #Если Сервер И Не Сервер Тогда КонсольКомпоновкиДанных = Обработки.ирКонсольКомпоновокДанных.Создать(); Объект = КонсольКомпоновкиДанных; #КонецЕсли Если Объект.СхемаКомпоновкиДанных = Неопределено Тогда Возврат "У отчета не установлена схема компоновки данных"; КонецЕсли; Результат = КонсольКомпоновкиДанных.ОткрытьДляОтладки(Объект.СхемаКомпоновкиДанных, Объект.КомпоновщикНастроек.ПолучитьНастройки(), ВнешниеНаборыДанных, Модально,,, МенеджерВременныхТаблиц); ИначеЕсли Истина И ОбъектМД <> Неопределено И Метаданные.РегистрыСведений.Индекс(ОбъектМД) <> -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Лкс(Объект)); КонецЕсли; //Иначе // Большого смысла пока не увидел, т.к. обратное преобразование не оформлено отдельной функцией // Результат = СтруктураОбъектаДляОтладкиЛкс(Объект); КонецЕсли; Если Результат = Неопределено Тогда Результат = ЗначениеВСтрокуВнутр(Объект); КонецЕсли; Возврат Результат; КонецФункции Функция ОбъектИзСнимкаЛкс(Знач Снимок, Знач ВВидеСтруктуры = Ложь) Экспорт Если ТипЗнч(Снимок) = Тип("Структура") Тогда СтруктураОбъекта = ОбъектБДПоКлючуЛкс(Снимок.ПолноеИмяМД,,, Ложь,,,,, Ложь); ИмитаторОбъекта = СтруктураОбъекта.Методы; Если ЛиТипИмитатораОбъектаЛкс(ТипЗнч(ИмитаторОбъекта)) Тогда #Если Сервер И Не Сервер Тогда ИмитаторОбъекта = Обработки.ирИмитаторСсылочныйОбъект.Создать(); #КонецЕсли ИмитаторОбъекта.ЗагрузитьСнимок(Снимок.Снимок); Иначе ИмитаторОбъекта = ОбъектИзСтроки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 Тогда Пока Истина И ИнформацияОбОшибке.Причина <> Неопределено И (Ложь Или ЗначениеЗаполнено(ИнформацияОбОшибке.Причина.ИмяМодуля) Или ИнформацияОбОшибке.Причина.Причина <> Неопределено) Цикл ИнформацияОбОшибке = ИнформацияОбОшибке.Причина; КонецЦикла; ТекстовыйДокумент.УдалитьСтроку(НомерПоследнейСтроки); Результат = ТекстовыйДокумент.ПолучитьТекст() + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке); КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ЗагрузитьЗначениеИзФайлаЛкс(Знач ПолноеИмяФайла, Знач Сжатие = Ложь) Экспорт Файл = Новый Файл(ПолноеИмяФайла); Если СтрокиРавныЛкс(Файл.Расширение, ".zip") Тогда Сжатие = Истина; КонецЕсли; Если Сжатие Тогда ВременныйКаталог = ПолучитьИмяВременногоФайла(); СоздатьКаталог(ВременныйКаталог); Попытка ЗипЧтение = Новый ЧтениеZipФайла(ПолноеИмяФайла); Исключение ОписаниеОшибки = ОписаниеОшибки(); ЗипЧтение = Неопределено; КонецПопытки; Если ЗипЧтение <> Неопределено Тогда ЗипЧтение.ИзвлечьВсе(ВременныйКаталог); ПолноеИмяФайла = ВременныйКаталог + РазделительПутиКФайлуЛкс() + ЗипЧтение.Элементы[0].Имя; КонецЕсли; КонецЕсли; ЧтениеХМЛ = Новый ЧтениеXML; ЧтениеХМЛ.ОткрытьФайл(ПолноеИмяФайла); Попытка //Результат = ЗначениеИзФайла(ВыборФайла.ПолноеИмяФайла); Результат = СериализаторXDTO.ПрочитатьXML(ЧтениеХМЛ); Исключение СообщитьЛкс(ОписаниеОшибки()); Результат = Неопределено; КонецПопытки; ЧтениеХМЛ.Закрыть(); Если Сжатие Тогда УдалитьФайлы(ВременныйКаталог, "*"); КонецЕсли; Если ТипЗнч(Результат) = Тип("Структура") И Результат.Свойство("ВложенноеНесериализуемоеЗначение") Тогда Результат = Результат.ВложенноеНесериализуемоеЗначение.Получить(); КонецЕсли; Возврат Результат; КонецФункции Функция СохранитьЗначениеВФайлЛкс(Знач Значение, Знач ПолноеИмяФайла, Сжатие = Ложь, УровеньСжатия = Неопределено) Экспорт ЗаписьХМЛ = Новый ЗаписьXML; ЗаписьХМЛ.ОткрытьФайл(ПолноеИмяФайла); Результат = Истина; Попытка //ЗначениеВФайл(ПолноеИмяФайла, Значение); СериализаторXDTO.Записать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" + ТекстВВыражениеВстроенногоЯзыкаЛкс(СтрокаСоединения); Если ЗначениеЗаполнено(ИмяВСпискеБазПользователя) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /IBName" + ТекстВВыражениеВстроенногоЯзыкаЛкс(ИмяВСпискеБазПользователя); КонецЕсли; Если ЗначениеЗаполнено(ДополнительныеПараметры) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " " + ДополнительныеПараметры; КонецЕсли; Если ЗначениеЗаполнено(ИмяПользователяИнфобазы) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /N""" + ИмяПользователяИнфобазы + """"; КонецЕсли; Если ОтключитьАутентификациюОС Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /WA-"; КонецЕсли; Если ЗначениеЗаполнено(ПарольПользователяИнфобазы) Тогда СтрокаПараметраПароля = "/P""" + ПарольПользователяИнфобазы + """"; СтрокаЗаменыПароля = "/P""" + "***" + """"; ПараметрыЗапуска = ПараметрыЗапуска + " " + СтрокаПараметраПароля; КонецЕсли; Если ЗначениеЗаполнено(ПараметрЗапуска) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /C""" + ПараметрЗапуска + """"; КонецЕсли; ПараметрыЗапуска = ПараметрыЗапуска + " /UC""" + КодРазрешения + """"; Если Не РежимКонфигуратора Тогда Если ПрименитьТекущиеПараметрыЗапуска Тогда ПараметрыЗапускаДляОтладки = ПараметрыЗапускаСеансаТекущиеЛкс(); ПараметрыЗапуска = ПараметрыЗапуска + " " + ПараметрыЗапускаДляОтладки; КонецЕсли; Если ОчисткаКэшаКлиентСерверныхВызовов Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /ClearCache"; КонецЕсли; Если РежимИнтерфейсаТакси Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /iTaxi"; КонецЕсли; Если ОткрытьПортативныеИнструменты И ирКэш.ЛиПортативныйРежимЛкс() Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /Execute""" + ирПортативный.ИспользуемоеИмяФайла + """"; КонецЕсли; Если СтрокиРавныЛкс(РежимЗапуска, "Авто") Тогда // Из-за этого иногда долго стартует почему то ПараметрыЗапуска = ПараметрыЗапуска + " /AppAutoCheckMode"; // Автоматический выбор типа приложения для запуска ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "ОбычноеПриложение") Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /RunModeOrdinaryApplication"; ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "УправляемоеПриложениеТолстый") Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /RunModeManagedApplication"; ИначеЕсли СтрокиРавныЛкс(РежимЗапуска, "УправляемоеПриложениеТонкий") Тогда //ПараметрыЗапуска = ПараметрыЗапуска + "/IBConnectionString" + ТекстВВыражениеВстроенногоЯзыкаЛкс(СтрокаСоединения); КонецЕсли; Если ЗначениеЗаполнено(РазделениеДанных) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /Z""" + РазделениеДанных + """"; КонецЕсли; КонецЕсли; Если ЗначениеЗаполнено(КодЯзыка) Тогда ПараметрыЗапуска = ПараметрыЗапуска + " /L""" + КодЯзыка + """"; КонецЕсли; Если СообщитьСтрокуПараметров Тогда СообщитьЛкс(СтрЗаменить(ПараметрыЗапуска, СтрокаПараметраПароля, СтрокаЗаменыПароля)); КонецЕсли; Возврат ПараметрыЗапуска; КонецФункции Функция СоздатьСсылочныйОбъектПоМетаданнымЛкс(ОбъектИлиИмяМД, ЭтоГруппаДляНового = Ложь, ИдентификаторСсылки = Неопределено, ЗаполнитьНовый = Истина) Экспорт УстановитьПривилегированныйРежим(Истина); Менеджер = ПолучитьМенеджерЛкс(ОбъектИлиИмяМД); Если ТипЗнч(ОбъектИлиИмяМД) = Тип("ОбъектМетаданных") Тогда ОбъектМД = ОбъектИлиИмяМД; Иначе ОбъектМД = ПолучитьМетаданныеЛкс(ОбъектИлиИмяМД); КонецЕсли; ПолноеИмяМД = ОбъектМД.ПолноеИмя(); ИмяТипаМетаданного = ПеревестиВРусский(ПервыйФрагментЛкс(ПолноеИмяМД)); Попытка Если ИмяТипаМетаданного = "Справочник" Или ИмяТипаМетаданного = "ПланВидовХарактеристик" Тогда Если ЭтоГруппаДляНового Тогда Объект = Менеджер.СоздатьГруппу(); Иначе Объект = Менеджер.СоздатьЭлемент(); КонецЕсли; ИначеЕсли ИмяТипаМетаданного = "Документ" Тогда Объект = Менеджер.СоздатьДокумент(); ИначеЕсли ИмяТипаМетаданного = "Задача" Тогда Объект = Менеджер.СоздатьЗадачу(); ИначеЕсли ИмяТипаМетаданного = "БизнесПроцесс" Тогда Объект = Менеджер.СоздатьБизнесПроцесс(); ИначеЕсли ИмяТипаМетаданного = "ПланОбмена" Тогда Объект = Менеджер.СоздатьУзел(); ИначеЕсли ИмяТипаМетаданного = "ПланВидовРасчета" Тогда Объект = Менеджер.СоздатьВидРасчета(); ИначеЕсли ИмяТипаМетаданного = "ПланСчетов" Тогда Объект = Менеджер.СоздатьСчет(); ИначеЕсли ИмяТипаМетаданного = "ВнешнийИсточникДанных" Тогда Объект = Менеджер.СоздатьОбъект(); Иначе ВызватьИсключение "Неизвестный тип метаданных """ + ИмяТипаМетаданного + """"; КонецЕсли; Исключение ПроверитьОшибкуПодписокНаКлиентеЛкс(ОписаниеОшибки()); ВызватьИсключение; КонецПопытки; Если ИдентификаторСсылки = Неопределено Тогда ИдентификаторСсылки = Новый УникальныйИдентификатор(); КонецЕсли; Объект.УстановитьСсылкуНового(Менеджер.ПолучитьСсылку(ИдентификаторСсылки)); Если ЗаполнитьНовый Тогда Объект.Заполнить(Неопределено); КонецЕсли; Возврат Объект; КонецФункции Процедура ПроверитьОшибкуПодписокНаКлиентеЛкс(ОписаниеОшибки) #Если Клиент Тогда Если Найти(ОписаниеОшибки, "Обработчик события не найден") > 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 И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип) Тогда Возврат (ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные); Иначе Если Истина И Не ДляТабличнойЧастиПроверятьРодителя И Фрагменты.Количество() > 2 Тогда Возврат Ложь; КонецЕсли; Если ЛиКорневойТипСсылкиЛкс(КорневойТип, ИсключаяСсылкиМетаданных) Тогда Возврат Истина; Иначе Возврат Ложь; КонецЕсли; КонецЕсли; КонецФункции Функция ЛиМетаданныеРегистраЛкс(Знач ОбъектМД, СчитатьПоследовательностьРегистром = Истина) Экспорт Если ОбъектМД = Неопределено Тогда Возврат Ложь; КонецЕсли; #Если Сервер И Не Сервер Тогда ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют; #КонецЕсли Фрагменты = СтрРазделитьЛкс(ОбъектМД.ПолноеИмя()); КорневойТип = Фрагменты[0]; Если ЛиКорневойТипРегистраБДЛкс(КорневойТип, СчитатьПоследовательностьРегистром) Тогда Возврат Истина; ИначеЕсли Истина И Фрагменты.Количество() = 4 И ЛиКорневойТипВнешнегоИсточникаДанныхЛкс(КорневойТип) Тогда Возврат (ОбъектМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.НеобъектныеДанные); Иначе Возврат Ложь; КонецЕсли; КонецФункции Функция ЛиМетаданныеНезависимогоРегистраЛкс(Знач ОбъектМД) Экспорт Если ОбъектМД = Неопределено Тогда Возврат Ложь; КонецЕсли; #Если Сервер И Не Сервер Тогда ОбъектМД = Метаданные.РегистрыСведений.КурсыВалют; #КонецЕсли Фрагменты = СтрРазделитьЛкс(ОбъектМД.ПолноеИмя()); КорневойТип = Фрагменты[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 Тогда Возврат ПолучитьМетаданныеЛкс(ТипОбъекта); Иначе Возврат Неопределено; КонецЕсли; КонецФункции // ПолучитьМетаданныеСпискаЛкс() // Определяет корневой тип конфигурации по описанию типов, типу, метаданным, ссылке или объекту. // Для описания типов берется первый тип массива типов. // // Параметры: // пОбъект - Произвольный - для чего получаем метаданные; // *пЛиТолькоДляКорневого - Булево, *Ложь - возвращать только для объекта корневого типа. // // Возвращаемое значение: // - Строка - имя типа корневого объекта метаданных; // Неопределено - не удалось получить имя типа. // Функция КорневойТипКонфигурацииЛкс(пОбъект, пЛиТолькоДляКорневого = Ложь) Экспорт Если ТипЗнч(пОбъект) = Тип("ОбъектМетаданных") Тогда МетаданныеТипа = пОбъект; Иначе МетаданныеТипа = ПолучитьМетаданныеЛкс(пОбъект); КонецЕсли; Результат = Неопределено; Если МетаданныеТипа <> Неопределено Тогда ПолноеИмя = МетаданныеТипа.ПолноеИмя(); Если пЛиТолькоДляКорневого Тогда МассивФрагментов = СтрРазделитьЛкс(ПолноеИмя); Если МассивФрагментов.Количество() = 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 // ОбъектМетаданныхРеквизит Колонки.Добавить(Реквизит.Имя, Реквизит.Тип, Реквизит.Представление()); ИначеЕсли ТипЗнч(Реквизит) = Тип("ПолеНастройки") Тогда Колонки.Добавить(Реквизит.Имя, Реквизит.ТипЗначения, Реквизит.Представление); Иначе ВызватьИсключение "Неизвестный тип описания реквизита """ + ТипЗнч(Реквизит) + """"; КонецЕсли; КонецЦикла; Если ТипЗнч(Коллекция) = Тип("Структура") Тогда Для Каждого Колонка Из Колонки Цикл Коллекция.Вставить(Колонка.Имя, Колонка.ТипЗначения.ПривестиЗначение(Неопределено)); КонецЦикла; КонецЕсли; Возврат КоллекцияПриемник; КонецФункции Функция СписокБазПользователяОСЛкс(Знач ПолноеИмяФайла = Неопределено, ВычислятьРазмерыКаталогов = Ложь, ВычислятьПоследнегоПользователя = Ложь, ТаблицаПриемник = Неопределено) Экспорт мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли Если ТаблицаПриемник = Неопределено Тогда Результат = мПлатформа.СписокБазПользователя.ВыгрузитьКолонки(); Иначе Результат = ТаблицаПриемник; КонецЕсли; Если ПолноеИмяФайла = Неопределено Тогда лПолноеИмяФайла = ИмяФайлаОбщегоСпискаИнфобазВсехПользователейОСЛкс(); Если ЗначениеЗаполнено(лПолноеИмяФайла) Тогда СписокБазПользователяОСЛкс(лПолноеИмяФайла,,, Результат); КонецЕсли; лПолноеИмяФайла = ИмяФайлаОбщегоСпискаИнфобазТекущегоПользователяОСЛкс(); Если ЗначениеЗаполнено(лПолноеИмяФайла) Тогда СписокБазПользователяОСЛкс(лПолноеИмяФайла,,, Результат); КонецЕсли; ПолноеИмяФайла = ИмяФайлаСпискаИнфобазПользователяОСЛкс(); КонецЕсли; Если ЛиИдентификацияБазыВСпискеПоНаименованиюЛкс() Тогда КолонкаConnect = Неопределено; Иначе КолонкаConnect = Результат.Колонки.Connect; КонецЕсли; Файл = Новый Файл(ПолноеИмяФайла); ДобавленныеСтроки = Новый Массив; Если Файл.Существует() Тогда ЧтениеФайла = Новый ЧтениеТекста; Попытка ЧтениеФайла.Открыть(ПолноеИмяФайла, КодировкаТекста.UTF8); СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку(); Исключение // Файл существует, но недоступен http://www.hostedredmine.com/issues/882846 ОписаниеОшибки = ОписаниеОшибки(); // Для отладки СтрокаИзФайла = Неопределено; КонецПопытки; Пока СтрокаИзФайла <> Неопределено Цикл Если СтрДлина(СокрЛП(СтрокаИзФайла)) Тогда ТекущаяСтрока = СокрЛП(СтрокаИзФайла); Если Лев(ТекущаяСтрока, 1) = "[" Тогда НовоеНаименование = Сред(ТекущаяСтрока, 2, СтрДлина(ТекущаяСтрока) - 2); // Убираем квадратные скобки вначале и вконце Если КолонкаConnect = Неопределено Тогда НоваяСтрока = Результат.Найти(НРег(НовоеНаименование), "КлючСтроки"); Если НоваяСтрока <> Неопределено Тогда НоваяСтрока = Неопределено; СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку(); Продолжить; КонецЕсли; КонецЕсли; НоваяСтрока = Результат.Добавить(); НоваяСтрока.ФайлСписка = ПолноеИмяФайла; НоваяСтрока.Наименование = НовоеНаименование; ДобавленныеСтроки.Добавить(НоваяСтрока); КонецЕсли; ИмяКолонки = ПервыйФрагментЛкс(ТекущаяСтрока, "=", Ложь); Если НоваяСтрока <> Неопределено И ЗначениеЗаполнено(ИмяКолонки) Тогда Колонка = Результат.Колонки.Найти(ИмяКолонки); Если Колонка <> Неопределено Тогда ПредставлениеЗначения = Сред(ТекущаяСтрока, СтрДлина(ИмяКолонки + "=") + 1); ЗначениеПараметра = Колонка.ТипЗначения.ПривестиЗначение(ПредставлениеЗначения); НоваяСтрока[Колонка.Имя] = ЗначениеПараметра; Если Колонка = КолонкаConnect Тогда СуществующаяСтрока = Результат.Найти(НРег(ЗначениеПараметра), "КлючСтроки"); Если СуществующаяСтрока <> Неопределено Тогда Результат.Удалить(НоваяСтрока); ДобавленныеСтроки.Удалить(ДобавленныеСтроки.ВГраница()); НоваяСтрока = Неопределено; СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку(); Продолжить; КонецЕсли; КонецЕсли; Иначе Пустышка = 0; // Для отладки КонецЕсли; КонецЕсли; КонецЕсли; СтрокаИзФайла = ЧтениеФайла.ПрочитатьСтроку(); КонецЦикла; КонецЕсли; Разделитель = РазделительПутиКФайлуЛкс(); #Если Сервер И Не Сервер Тогда ДобавленныеСтроки = Результат; #КонецЕсли Для Каждого СтрокаТЧ Из ДобавленныеСтроки Цикл ИзданиеПлатформы = СтрЗаменить(Лев(СтрокаТЧ.Version, 3), ".", ""); СтрокаТЧ.КаталогКэша = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(, ИзданиеПлатформы) + Разделитель + СтрокаТЧ.ID; СтрокаТЧ.КаталогНастроек = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(Ложь, ИзданиеПлатформы) + Разделитель + СтрокаТЧ.ID; Если ЛиИдентификацияБазыВСпискеПоНаименованиюЛкс() Тогда СтрокаТЧ.КлючСтроки = НРег(СтрокаТЧ.Наименование); Иначе СтрокаТЧ.КлючСтроки = НРег(СтрокаТЧ.Connect); КонецЕсли; СтрокаТЧ.НСтрокаСоединения = НРег(СтрокаТЧ.Connect); СтрокаСоединенияКластера = НСтр(СтрокаТЧ.Connect, "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 Тогда ЗаполнитьЭлементыКомпоновкиЛкс(ЭлементПриемник.ЗначенияВложенныхПараметров, ЭлементИсточник.ЗначенияВложенныхПараметров, ПриемникЗначения); КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры // Копирует объект Отбор в другой объект Отбор. // Если нужно, в приемнике создаются отсутствующие элементы отбора. // // Параметры: // пОтборПриемник - Отбор - куда копируем; // пОтборИсточник - Отбор, Структура - откуда копируем; // пСоздаватьОтсутствующие - Булево, *Ложь - признак создания отсутствующих элементов отбора в приемнике. // Процедура СкопироватьОтборПостроителяЛкс(ОтборПриемник, ОтборИсточник, СоздаватьОтсутствующие = Истина, ТолькоИспользуемые = Ложь, ОчищатьПриемник = Ложь) Экспорт #Если Сервер И Не Сервер Тогда Пустышка = Новый ПостроительЗапроса; ОтборПриемник = Пустышка.Отбор; #КонецЕсли Если ОчищатьПриемник Тогда ОтборПриемник.Сбросить(); КонецЕсли; //Если пСоздаватьОтсутствующие Тогда // ДоступныеПоля = пОтборПриемник.ПолучитьДоступныеПоля(); //КонецЕсли; Для Каждого ЭлементОтбораИсточника Из ОтборИсточник Цикл Если Истина И ТолькоИспользуемые И Не ЭлементОтбораИсточника.Использование Тогда Продолжить; КонецЕсли; Если ТипЗнч(ЭлементОтбораИсточника) = Тип("КлючИЗначение") Тогда ЭлементОтбораИсточника = ЭлементОтбораИсточника.Значение; КонецЕсли; //Если ЭлементОтбораИсточника.Имя = "" Тогда // СообщитьЛкс("Невозможно определить элемент отбора приемника при копировании отбора.", // СтатусСообщения.Внимание); // Продолжить; //КонецЕсли; ЭлементОтбораПриемника = ОтборПриемник.Найти(ЭлементОтбораИсточника.Имя); Если ЭлементОтбораПриемника = Неопределено Тогда Если Истина И СоздаватьОтсутствующие //И НайтиПолеНастройкиПоПутиКДаннымЛкс(ДоступныеПоля, ЭлементОтбораИсточника.ПутьКДанным) <> Неопределено Тогда Попытка ЭлементОтбораПриемника = ОтборПриемник.Добавить(ЭлементОтбораИсточника.ПутьКДанным, ЭлементОтбораИсточника.Имя); Исключение Продолжить; КонецПопытки; Иначе Продолжить; КонецЕсли; КонецЕсли; СкопироватьЭлементОтбораЛкс(ЭлементОтбораПриемника, ЭлементОтбораИсточника); КонецЦикла; КонецПроцедуры // Получает инвертированный вид сравнения. // // Параметры: // ВидСравнения - ВидСравнения. // // Возвращаемое значение: // ВидСравнения; // Функция ИнвертированныйВидСравненияЛкс(ВидСравненияП) Экспорт МассивИнвертируемыхТиповСравнения = Новый Массив; МассивИнвертируемыхТиповСравнения.Добавить("ВИерархии"); МассивИнвертируемыхТиповСравнения.Добавить("ВСписке"); МассивИнвертируемыхТиповСравнения.Добавить("Равно"); МассивИнвертируемыхТиповСравнения.Добавить("Содержит"); МассивИнвертируемыхТиповСравнения.Добавить("ВСпискеПоИерархии"); Для Каждого ТипСравнения Из МассивИнвертируемыхТиповСравнения Цикл ПрямойТипСравнения = Вычислить("ВидСравнения." + ТипСравнения); Если ПрямойТипСравнения = ВидСравненияП Тогда Возврат Вычислить("ВидСравнения.Не" + ТипСравнения); КонецЕсли; ОбратныйТипСравнения = Вычислить("ВидСравнения.Не" + ТипСравнения); Если ОбратныйТипСравнения = ВидСравненияП Тогда Возврат Вычислить("ВидСравнения." + ТипСравнения); КонецЕсли; КонецЦикла; Возврат ВидСравненияП; КонецФункции // Копирует один порядок в другой. Приемник перед копированием очищается. // // Параметры: // пПорядокПриемник - Порядок - куда копируем; // пПорядокИсточник - Порядок - откуда копируем. // Процедура СкопироватьПорядокПостроителяЛкс(пПорядокПриемник, пПорядокИсточник) Экспорт пПорядокПриемник.Очистить(); Для Каждого ЭлементПорядка Из пПорядокИсточник Цикл пПорядокПриемник.Добавить(ЭлементПорядка.ПутьКДанным, ЭлементПорядка.Имя, , ЭлементПорядка.Направление); КонецЦикла; КонецПроцедуры // СкопироватьПорядокЛкс() // Трансформирует порядок в порядок компоновки. // // Параметры: // ПорядокКомпоновки - ПорядокКомпоновкиДанных; // Порядок - Порядок. // Процедура ТрансформироватьПорядокВПорядокКомпоновкиЛкс(ПорядокКомпоновки, Порядок) Экспорт ЭлементыКомпоновки = ПорядокКомпоновки.Элементы; ЭлементыКомпоновки.Очистить(); Для Каждого Элемент Из Порядок Цикл ЭлементКомпоновки = ЭлементыКомпоновки.Добавить(Тип("ЭлементПорядкаКомпоновкиДанных")); ЭлементКомпоновки.Использование = Истина; ЭлементКомпоновки.Поле = Новый ПолеКомпоновкиДанных(Элемент.ПутьКДанным); Если Элемент.Направление = НаправлениеСортировки.Возр Тогда ЭлементКомпоновки.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр; Иначе//Если Элемент.Направление = НаправлениеСортировки.Убыв Тогда ЭлементКомпоновки.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Убыв; КонецЕсли; КонецЦикла; КонецПроцедуры Процедура СкопироватьПорядокЛюбойЛкс(ПорядокПриемник, ПорядокИсточник, ТолькоИспользуемые = Ложь, ПроверятьДоступность = Ложь, ОчищатьПриемник = Истина) Экспорт Если Истина И ТипЗнч(ПорядокИсточник) = Тип("Порядок") И ТипЗнч(ПорядокПриемник) = Тип("Порядок") Тогда СкопироватьПорядокПостроителяЛкс(ПорядокПриемник, ПорядокИсточник); ИначеЕсли Истина И ТипЗнч(ПорядокИсточник) = Тип("ПорядокКомпоновкиДанных") И ТипЗнч(ПорядокПриемник) = Тип("ПорядокКомпоновкиДанных") Тогда СкопироватьЭлементыКомпоновкиЛкс(ПорядокПриемник, ПорядокИсточник, ОчищатьПриемник); ИначеЕсли Истина И ТипЗнч(ПорядокИсточник) = Тип("Порядок") И ТипЗнч(ПорядокПриемник) = Тип("ПорядокКомпоновкиДанных") Тогда ТрансформироватьПорядокВПорядокКомпоновкиЛкс(ПорядокПриемник, ПорядокИсточник); Иначе ВызватьИсключение "Неверные типы параметров"; КонецЕсли; КонецПроцедуры Функция ПостроительЗапросаКТабличномуДокументуЛкс(Знач ТабличныйДокументИлиОбласть) Экспорт #Если Сервер И Не Сервер Тогда ТабличныйДокументИлиОбласть = Новый ТабличныйДокумент; #КонецЕсли Если ТипЗнч(ТабличныйДокументИлиОбласть) = Тип("ТабличныйДокумент") Тогда Область = ТабличныйДокументИлиОбласть.Область(); Иначе Область = ТабличныйДокументИлиОбласть; КонецЕсли; Построитель = Новый ПостроительЗапроса; Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Область); Построитель.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять; Построитель.ЗаполнитьНастройки(); Возврат Построитель; КонецФункции // Возвращает текущее время в миллисекундах. // // Параметры: // Нет. // // Возвращаемое значение: // Число. // Функция ТекущееВремяВМиллисекундахЛкс() Экспорт Попытка // Для ускорения //Пустышка = Метаданные.ОпределяемыеТипы; // Проверка 8.3 Результат = Вычислить("ТекущаяУниверсальнаяДатаВМиллисекундах()"); Исключение мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли Результат = мПлатформа.ПолучитьТекущееВремяВМиллисекундах(); КонецПопытки; Возврат Результат; КонецФункции // Выполняет запрос. Опционально сообщает его текст и время выполнения. // Удобно для оптимизации. // // Параметры: // Запрос - Запрос; // *ЛиОтладка - Булево, *Ложь - показывать тексты запросов и время выполнения. // *Заголовок - Строка, *"" - название запроса. // // Возвращаемое значение: // РезультатЗапроса. // Функция ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка = Ложь, Знач Заголовок = "") Экспорт Если ЛиОтладка Тогда ВремяНачала = ТекущееВремяВМиллисекундахЛкс(); КонецЕсли; Результат = Запрос.Выполнить(); Если ЛиОтладка Тогда Заголовок = Заголовок + " - " + Строка(ТекущееВремяВМиллисекундахЛкс() - ВремяНачала) + " мс"; СообщитьЛкс(Заголовок); //Текст = Новый ТекстовыйДокумент; //Текст.УстановитьТекст(Запрос.Текст); //Текст.Показать(Заголовок); КонецЕсли; Возврат Результат; КонецФункции // Получает константу языка запросов заданного типа с учетом квалификаторов описания типов. // // Параметры: // ТипПоля - Тип; // ОписаниеТипов - ОписаниеТипов - для обращения к квалификаторам. // // Возвращаемое значение: // Строка. // Функция ВыражениеПриведенияТипаНаЯзыкеЗапросовЛкс(Знач ТипПоля, Знач ОписаниеТипов = Неопределено, Знач БазовоеВыражение = "") Экспорт Если ТипПоля = Тип("Строка") Тогда Если БазовоеВыражение = "" Тогда БазовоеВыражение = """"""; КонецЕсли; Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК СТРОКА(" + XMLСтрока(ОписаниеТипов.КвалификаторыСтроки.Длина) + "))"; ИначеЕсли ТипПоля = Тип("Число") Тогда Если БазовоеВыражение = "" Тогда БазовоеВыражение = "0"; КонецЕсли; Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК ЧИСЛО(" + XMLСтрока(ОписаниеТипов.КвалификаторыЧисла.Разрядность) + ", " + XMLСтрока(ОписаниеТипов.КвалификаторыЧисла.РазрядностьДробнойЧасти) + "))"; ИначеЕсли ТипПоля = Тип("Дата") Тогда Если БазовоеВыражение = "" Тогда Если ОписаниеТипов.КвалификаторыДаты.ЧастиДаты = ЧастиДаты.Дата Тогда Результат = "ДАТАВРЕМЯ(1,1,1)"; Иначе Результат = "ДАТАВРЕМЯ(1,1,1,0,0,0)"; КонецЕсли; Иначе Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК ДАТА)"; КонецЕсли; ИначеЕсли ТипПоля = Тип("Булево") Тогда Если БазовоеВыражение = "" Тогда Результат = "ЛОЖЬ"; Иначе Результат = "ВЫРАЗИТЬ(" + БазовоеВыражение + " КАК БУЛЕВО)"; КонецЕсли; ИначеЕсли ТипПоля = Тип("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; КонецЕсли; Возврат ИндексКартинки; КонецФункции // Добавляет в таблицу строки из другой таблицы и в них значения колонок с совпадающими наименованиями. // // Параметры: // ТаблицаИсточник - ТаблицаЗначений, ТабличнаяЧасть - откуда берутся строки; // ТаблицаПриемник - ТаблицаЗначений, ТабличнаяЧасть - куда добавляются строки; // СтруктураЗначенийПоУмолчанию - Структура, *Неопределено - значения по умолчанию для добавляемых строк; // СтруктураНовыхЗначений - Структура, *Неопределено - значения колонок для добавляемых строк, имеют высший приоритет. // ОчиститьПередЗагрузкой - Булево, *Ложь - очищать приемник перед загрузкой, ускоряет выполнение // ОбязательныеКолонки - Структура, *Неопределено - имена колонок таблицы, которые нужно обязательно загрузить если они есть в приемнике. // Остальные будут загружены, если приемник пустой. Если не указано, то все совпадающие колонки обязательны. // Процедура ЗагрузитьВТаблицуЗначенийЛкс(Знач ТаблицаИсточник, Знач ТаблицаПриемник, Знач СтруктураЗначенийПоУмолчанию = Неопределено, Знач СтруктураНовыхЗначений = Неопределено, Знач ОчиститьПередЗагрузкой = Ложь, Знач ОбязательныеКолонки = Неопределено) Экспорт #Если Сервер И Не Сервер Тогда ТаблицаПриемник = Новый ТаблицаЗначений; ТаблицаИсточник = Новый ТаблицаЗначений; СтруктураЗначенийПоУмолчанию = Новый Структура; СтруктураНовыхЗначений = Новый Структура; #КонецЕсли Если ТаблицаИсточник = ТаблицаПриемник Тогда ВызватьИсключение "Нельзя загружать коллекцию в саму себя"; КонецЕсли; Если ОчиститьПередЗагрузкой Или ТаблицаПриемник.Количество() = 0 Тогда ТаблицаПриемник.Очистить(); Если Истина И СтруктураЗначенийПоУмолчанию = Неопределено И СтруктураНовыхЗначений = Неопределено И ЛиТабличнаяЧастьЛкс(ТаблицаПриемник) Тогда // оптимизация - для ТЧ это самый быстрый способ Если ЛиТабличнаяЧастьЛкс(ТаблицаИсточник) Тогда ТаблицаИсточник = ТаблицаИсточник.Выгрузить(); КонецЕсли; ТаблицаПриемник.Загрузить(ТаблицаИсточник); Возврат; КонецЕсли; КонецЕсли; Если ТаблицаИсточник.Количество() = 0 Тогда Возврат; КонецЕсли; СтрокаСовпадающихКолонок = ""; Если ТипЗнч(ТаблицаИсточник) = Тип("ТаблицаЗначений") Тогда КолонкиИсточника = ТаблицаИсточник.Колонки; Иначе КолонкиИсточника = ТаблицаИсточник.ВыгрузитьКолонки().Колонки; КонецЕсли; ЛиПриемникТаблицаЗначений = ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений"); Если ЛиПриемникТаблицаЗначений Тогда КолонкиПриемника = ТаблицаПриемник.Колонки; Иначе КолонкиПриемника = ТаблицаПриемник.ВыгрузитьКолонки().Колонки; КонецЕсли; ИмяПоляНомерСтроки = ПеревестиСтроку("НомерСтроки"); СовпадающиеКолонки = Новый Массив; // Ранее применялась однострочная форма кода Для каждого Колонка Из КолонкиПриемника Цикл Если СтруктураНовыхЗначений <> Неопределено Тогда Если СтруктураНовыхЗначений.Свойство(Колонка.Имя) Тогда Продолжить; КонецЕсли; КонецЕсли; Если Истина И (Ложь Или ЛиПриемникТаблицаЗначений Или Колонка.Имя <> ИмяПоляНомерСтроки) И (Ложь Или ОбязательныеКолонки = Неопределено Или ОбязательныеКолонки.Свойство(Колонка.Имя)) И КолонкиИсточника.Найти(Колонка.Имя) <> Неопределено Тогда СовпадающиеКолонки.Добавить(НРег(Колонка.Имя)); КонецЕсли; КонецЦикла; Если ЛиПриемникТаблицаЗначений И ТаблицаПриемник.Количество() = 0 Тогда // оптимизация - быстрый способ Для Счетчик = 1 По ТаблицаИсточник.Количество() Цикл ТаблицаПриемник.Добавить(); КонецЦикла; Если СтруктураНовыхЗначений <> Неопределено Тогда Для Каждого КлючИЗначение Из СтруктураНовыхЗначений Цикл ТаблицаПриемник.ЗаполнитьЗначения(КлючИЗначение.Значение, КлючИЗначение.Ключ); // Несовместимо с ТЧ КонецЦикла; КонецЕсли; ИндексыПересоздать = Новый Соответствие; Для Каждого ИмяКолонки Из СовпадающиеКолонки Цикл Массив = ТаблицаИсточник.ВыгрузитьКолонку(ИмяКолонки); ТаблицаПриемник.ЗагрузитьКолонку(Массив, ИмяКолонки); Для Каждого ИндексТаблицы Из ТаблицаПриемник.Индексы Цикл Если Найти(" " + Нрег(ИндексТаблицы) + ",", " " + ИмяКолонки + ",") > 0 Тогда ИндексыПересоздать.Вставить(ИндексТаблицы); КонецЕсли; КонецЦикла; КонецЦикла; // Антибаг https://www.hostedredmine.com/issues/936307 Для Каждого КлючИЗначение Из ИндексыПересоздать Цикл ОпределениеИндекса = "" + КлючИЗначение.Ключ; ТаблицаПриемник.Индексы.Удалить(КлючИЗначение.Ключ); ТаблицаПриемник.Индексы.Добавить(ОпределениеИндекса); КонецЦикла; Если СтруктураЗначенийПоУмолчанию <> Неопределено Тогда Для Каждого КлючИЗначение Из СтруктураЗначенийПоУмолчанию Цикл Если СовпадающиеКолонки.Найти(НРег(КлючИЗначение.Ключ)) <> Неопределено Тогда Продолжить; КонецЕсли; ТаблицаПриемник.ЗаполнитьЗначения(КлючИЗначение.Значение, КлючИЗначение.Ключ); // Несовместимо с ТЧ КонецЦикла; КонецЕсли; Иначе СтрокаСовпадающихКолонок = СтрСоединитьЛкс(СовпадающиеКолонки, ","); Для каждого СтрокаТаблицыИсточника Из ТаблицаИсточник Цикл СтрокаТаблицыПриемника = ТаблицаПриемник.Добавить(); Если СтруктураЗначенийПоУмолчанию <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтруктураЗначенийПоУмолчанию); КонецЕсли; // Заполним значения в совпадающих колонках. ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтрокаТаблицыИсточника, СтрокаСовпадающихКолонок); //Для каждого ЭлементМассива Из МассивСовпадающихКолонок Цикл // СтрокаТаблицыПриемника[ЭлементМассива] = СтрокаТаблицыИсточника[ЭлементМассива]; //КонецЦикла; Если СтруктураНовыхЗначений <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаТаблицыПриемника, СтруктураНовыхЗначений); КонецЕсли; КонецЦикла; КонецЕсли; КонецПроцедуры // Слияние таблиц значений одинаковой структуры. Меньшая из таблиц вливается в бОльшую. // // Параметры: // Таблица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); Если ОчиститьПередЗагрузкой Тогда ДеревоПриемник.Строки.Очистить(); КонецЕсли; ЗагрузитьВСтрокиДереваЗначенийЛкс(ДеревоИсточник, ДеревоПриемник, СтруктураЗначенийПоУмолчанию, СтруктураНовыхЗначений, СтрокаСовпадающихКолонок); КонецПроцедуры // ЗагрузитьВДеревоЗначенийЛкс() // Непростетирована. Добавляет в дерево значений строки из другой таблицы значений и // в них значения колонок с совпадающими наименованиями. // // Параметры: // ТаблицаИсточник - таблица значений, откуда берутся значения; // ТаблицаПриемник - таблица значений, куда добавляются строки; // *СтруктураЗначенийПоУмолчанию - Структура, *Неопределено - значения по умолчанию для добавляемых строк; // *СтруктураНовыхЗначений - Структура, *Неопределено - значения колонок для добавляемых строк, имеют высший приоритет. // Процедура ЗагрузитьВСтрокиДереваЗначенийЛкс(СтрокаРодительИсточника, СтрокаРодительПриемника, СтруктураЗначенийПоУмолчанию, СтруктураНовыхЗначений, СтрокаСовпадающихКолонок) Экспорт СтрокиПриемника = СтрокаРодительПриемника.Строки; Для каждого СтрокаИсточника Из СтрокаРодительИсточника.Строки Цикл СтрокаПриемника = СтрокиПриемника.Добавить(); Если СтруктураЗначенийПоУмолчанию <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаПриемника, СтруктураЗначенийПоУмолчанию); КонецЕсли; // Заполним значения в совпадающих колонках. ЗаполнитьЗначенияСвойств(СтрокаПриемника, СтрокаИсточника, СтрокаСовпадающихКолонок); Если СтруктураНовыхЗначений <> Неопределено Тогда ЗаполнитьЗначенияСвойств(СтрокаПриемника, СтруктураНовыхЗначений); КонецЕсли; ЗагрузитьВСтрокиДереваЗначенийЛкс(СтрокаИсточника, СтрокаПриемника, СтруктураЗначенийПоУмолчанию, СтруктураНовыхЗначений, СтрокаСовпадающихКолонок); КонецЦикла; КонецПроцедуры // Устарела. Вместо нее нужно вызывать СообщитьЛкс() // // Параметры: // ТекстСообщения - Строка; // МодальныйРежим - Булево, *Ложь; // *Статус - СтатусСообщения, *Неопределено. // Процедура СообщитьСУчетомМодальностиЛкс(ТекстСообщения, _МодальныйРежим = Ложь, Статус = Неопределено) Экспорт СообщитьЛкс(ТекстСообщения, Статус); КонецПроцедуры // Сообщает итог индикации (длительность). // // Параметры: // Индикатор - Структура - индикатора, полученная методом ПолучитьИндикаторПроцессаЛкс. // Процедура СообщитьИтогИндикацииЛкс(Индикатор) Экспорт ТекущаяДата = ТекущаяДата(); ПрошлоВремени = ТекущаяДата - Индикатор.ДатаНачалаПроцесса; ПрошлоВремениСтрока = Формат(Дата(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. Зачем это было сделано изначально, пока не разобрался //Если Истина // И ПустаяСтрока(СтрокаФормата) // И ТипЗнч(КолонкаТабличногоПоля.ЭлементУправления) = Тип("ПолеВвода") //Тогда // КвалификаторыЧисла = КолонкаТабличногоПоля.ЭлементУправления.ТипЗначения.КвалификаторыЧисла; // СтрокаФормата = "ЧЦ = " + КвалификаторыЧисла.Разрядность + "; ЧДЦ = " + КвалификаторыЧисла.РазрядностьДробнойЧасти; //КонецЕсли; КонецЕсли; Если ДобавлятьПредставлениеТипа Тогда Результат = Результат + ТипЗначения + ": "; КонецЕсли; Результат = Результат + Формат(Значение, СтрокаФормата); Если Истина И ЯвноеПреставлениеПустого //И Не ЗначениеЗаполнено(Значение) И Не ЗначениеЗаполнено(Результат) Тогда мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли Результат = мПлатформа.ПредставлениеПустогоЗначенияЛкс(Значение); КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ПредставлениеЗначенияЛкс(Значение) Экспорт Попытка Результат = "" + Значение; Исключение // Некоторые типы ошибочно не имеют отображения в строку 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[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда Возврат Ложь; КонецЕсли; КонецЦикла; КонецЕсли; Возврат Результат; КонецФункции Функция КоличествоОшибокВЖурналеЛкс(Знач Начало, Знач Конец, Знач СтруктураОтбора, Знач МаксимальныйРазмерВыгрузки = Неопределено) Экспорт АнализЖурналаРегистрации = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирАнализЖурналаРегистрации"); #Если Сервер И Не Сервер Тогда АнализЖурналаРегистрации = Обработки.ирАнализЖурналаРегистрации.Создать(); #КонецЕсли СобытияЗадания = АнализЖурналаРегистрации.ПолучитьДанные(Начало, Конец, СтруктураОтбора, МаксимальныйРазмерВыгрузки); КоличествоОшибокВЖурнале = СобытияЗадания.Количество(); Возврат КоличествоОшибокВЖурнале; КонецФункции Функция ШаблонРазметкиВхожденийЛкс() Экспорт // https://unicode-table.com/ru/sets/brackets/ Результат = ирКэш.Получить().ВыделениеРезультатовПоиска; Результат = Лев(Результат, 1) + "$1" + Прав(Результат, 1); Возврат Результат; КонецФункции Процедура ДобавитьСловаПоискаВСтруктуруРеквизитовЛкс(Знач ИмяСвойства, Знач Слово, Знач СловаПоСвойствам) Экспорт Слова = Неопределено; Если Не СловаПоСвойствам.Свойство(ИмяСвойства, Слова) Тогда Слова = Новый Массив; СловаПоСвойствам.Вставить(ИмяСвойства, Слова); КонецЕсли; Если Слова.Найти(Слово) = Неопределено Тогда Слова.Добавить(Слово); КонецЕсли; КонецПроцедуры Функция СловаПоискаПоКолонкамИзОтбораКомпоновкиЛкс(Знач Отбор) Экспорт СловаПоСвойствам = Новый Структура; #Если Сервер И Не Сервер Тогда Отбор = Новый НастройкиКомпоновкиДанных; Отбор = Отбор.Отбор; #КонецЕсли Для Каждого ЭлементОтбора Из Отбор.Элементы Цикл Если Истина И ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") И ЭлементОтбора.Использование И ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит И ЭлементОтбора.ПравоеЗначение <> "" Тогда ДобавитьСловаПоискаВСтруктуруРеквизитовЛкс(СтрЗаменить(ЭлементОтбора.ЛевоеЗначение, ".", "_"), ЭлементОтбора.ПравоеЗначение, СловаПоСвойствам); КонецЕсли; КонецЦикла; Возврат СловаПоСвойствам; КонецФункции Функция КоличествоИзмененийПоУзлуЛкс(Узел, МассивМетаданных = Неопределено) Экспорт #Если Клиент Тогда СостояниеЛкс("Вычисление количества изменений на узле…"); #КонецЕсли Запрос = Новый Запрос; Запрос.УстановитьПараметр("Узел", Узел); МетаПланОбмена = Узел.Метаданные(); ТекстЗапроса = ""; Для Каждого ЭлементСОстава Из МетаПланОбмена.Состав Цикл МетаОбъект = ЭлементСОстава.Метаданные; Если Ложь Или МетаОбъект = Неопределено Или (Истина И МассивМетаданных <> Неопределено И МассивМетаданных.Найти(МетаОбъект) = Неопределено) Тогда Продолжить; КонецЕсли; ИмяТаблицыДляПоискаЗарегистрированных = ирКэш.ИмяТаблицыИзМетаданныхЛкс(МетаОбъект.ПолноеИмя(), Истина); Если ИмяТаблицыДляПоискаЗарегистрированных = Неопределено Тогда Продолжить; КонецЕсли; Если ТекстЗапроса <> "" Тогда ТекстЗапроса = ТекстЗапроса + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС; КонецЕсли; ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ Количество(*) КАК Количество |ИЗ | " + ИмяТаблицыДляПоискаЗарегистрированных + " КАК РегистрацияИзменений |ГДЕ | РегистрацияИзменений.Узел = &Узел |"; КонецЦикла; Если ТекстЗапроса <> "" Тогда Запрос.Текст = ТекстЗапроса; ТаблицаКоличестваИзменений = Запрос.Выполнить().Выгрузить(); КоличествоИзменений = ТаблицаКоличестваИзменений.Итог("Количество"); Иначе КоличествоИзменений = 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].Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")); ФиктивноеПоле.ПутьКДанным = ИмяФиктивногоПоляСхемыКомпоновкиЛкс(); УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ФиктивноеПоле, Истина, Истина, Истина, Истина); КонецЕсли; Возврат СхемаКомпоновкиДанных; КонецФункции Функция ИмяКлючаСтрокиДереваЛкс() Экспорт Возврат "_КлючСтрокиДерева"; КонецФункции Функция ИмяКлючаСтрокиРодителяЛкс() Экспорт Возврат "_КлючСтрокиРодителя"; КонецФункции Функция СоздатьСхемуКомпоновкиЛкс() Экспорт СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных; ДобавитьЛокальныйИсточникДанныхЛкс(СхемаКомпоновкиДанных); Возврат СхемаКомпоновкиДанных; КонецФункции Функция КолонкиИсточникаДанныхЛкс(Знач ИсточникДанных) Если Ложь Или ТипЗнч(ИсточникДанных) = Тип("ДеревоЗначений") Или ТипЗнч(ИсточникДанных) = Тип("ТаблицаЗначений") Тогда КолонкиНабора = ИсточникДанных.Колонки; Иначе КолонкиНабора = ИсточникДанных.ВыгрузитьКолонки().Колонки; КонецЕсли; Возврат КолонкиНабора; КонецФункции // Создает новую или добавляет в существующую схему компоновки набор данных объект из полей настройки. // // Параметры: // ПоляНастройки - ПоляНастройки - <описание параметра> // <продолжение описания параметра>; // <Параметр2> - <Тип.Вид> - <описание параметра> // <продолжение описания параметра>. // Функция СоздатьСхемуПоПолямНастройкиЛкс(ПоляНастройки, СхемаКомпоновкиДанных = Неопределено, ИмяНабора = "Основной") Экспорт Если СхемаКомпоновкиДанных = Неопределено Тогда СхемаКомпоновкиДанных = СоздатьСхемуКомпоновкиЛкс(); КонецЕсли; #Если Сервер И Не Сервер Тогда СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных; #КонецЕсли НаборДанных = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхОбъектСхемыКомпоновкиДанных")); НаборДанных.Имя = ИмяНабора; НаборДанных.ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных[0].Имя; НаборДанных.ИмяОбъекта = ИмяНабора; Для Каждого ПолеНастройки Из ПоляНастройки Цикл Поле = НаборДанных.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных")); Поле.ПутьКДанным = ПолеНастройки.Имя; Поле.Поле = ПолеНастройки.ПутьКДанным; Поле.Заголовок = ПолеНастройки.Представление; Поле.ТипЗначения = ПолеНастройки.ТипЗначения; ОграничениеИспользования = Поле.ОграничениеИспользования; ОграничениеИспользования.Поле = Не ПолеНастройки.Поле; ОграничениеИспользования.Условие = Не ПолеНастройки.Отбор; ОграничениеИспользования.Порядок = Не ПолеНастройки.Порядок; ОграничениеИспользования.Группировка = Не ПолеНастройки.Измерение; ЗначениеОграничения = ПолеНастройки.Поля.Количество() = 0; ОграничениеИспользованияРеквизитов = Поле.ОграничениеИспользованияРеквизитов; ОграничениеИспользованияРеквизитов.Поле = ЗначениеОграничения; ОграничениеИспользованияРеквизитов.Условие = ЗначениеОграничения; ОграничениеИспользованияРеквизитов.Порядок = ЗначениеОграничения; ОграничениеИспользованияРеквизитов.Группировка = ЗначениеОграничения; КонецЦикла; Возврат СхемаКомпоновкиДанных; КонецФункции // Параметры: // Поле - // Доступность - // ПрименитьГруппировка - // ПрименитьПоле - // ПрименитьПорядок - // ПрименитьУсловие - // Возвращаемое значение: // Функция УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(Знач ПолеИлиОграничениеИспользования, Знач Ограничивать = Ложь, Знач ПрименитьГруппировка = Истина, Знач ПрименитьПоле = Истина, Знач ПрименитьПорядок = Истина, Знач ПрименитьУсловие = Истина) Экспорт МассивГруппОграничений = Новый Массив; Если ТипЗнч(ПолеИлиОграничениеИспользования) = Тип("ОграничениеИспользованияПоляСхемыКомпоновкиДанных") Тогда МассивГруппОграничений.Добавить(ПолеИлиОграничениеИспользования); Иначе Поле = ПолеИлиОграничениеИспользования; МассивГруппОграничений.Добавить(Поле.ОграничениеИспользования); Попытка МассивГруппОграничений.Добавить(Поле.ОграничениеИспользованияРеквизитов); Исключение КонецПопытки; КонецЕсли; Для Каждого ОграничениеИспользования Из МассивГруппОграничений Цикл Если ПрименитьГруппировка Тогда ОграничениеИспользования.Группировка = Ограничивать; КонецЕсли; Если ПрименитьПоле Тогда ОграничениеИспользования.Поле = Ограничивать; КонецЕсли; Если ПрименитьПорядок Тогда ОграничениеИспользования.Порядок = Ограничивать; КонецЕсли; Если ПрименитьУсловие Тогда ОграничениеИспользования.Условие = Ограничивать; КонецЕсли; КонецЦикла; КонецФункции // Функция добавляет в схему компоновки источник данных с типом "Local" Функция ДобавитьЛокальныйИсточникДанныхЛкс(СхемаКомпоновкиДанных) Экспорт ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить(); ИсточникДанных.Имя = "ИсточникДанных1"; ИсточникДанных.ТипИсточникаДанных = "Local"; Возврат ИсточникДанных; КонецФункции // Функция добавляет набор данных - запрос в указанную в параметре коллекцию наборов данных Функция ДобавитьНаборДанныхЗапросЛкс(НаборыДанных, ИсточникДанных, ИмяНабораДанных = "Основной") Экспорт НаборДанных = НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных")); НаборДанных.Имя = ИмяНабораДанных; НаборДанных.ИсточникДанных = ИсточникДанных.Имя; Возврат НаборДанных; КонецФункции Функция МассивВСписокЗначенийЛкс(Знач Массив) Экспорт Список = Новый СписокЗначений; Список.ЗагрузитьЗначения(Массив); Возврат Список; КонецФункции // Получает строку путем отсечения заданного числа последних символов. // // Параметры: // пСтрока - Строка - исходная; // пДлинаКонца - Число, *1 - количество отсекаемых символов; // // Возвращаемое значение: // - Строка. // Функция СтрокаБезКонцаЛкс(пСтрока, пДлинаКонца = 1) Экспорт Если СтрДлина(пСтрока) < пДлинаКонца Тогда Возврат ""; Иначе Возврат Лев(пСтрока, СтрДлина(пСтрока) - пДлинаКонца); КонецЕсли; КонецФункции Функция СтрокаБезПервогоФрагментаЛкс(Знач Строка, Знач Разделитель = ".") Экспорт Позиция = Найти(Строка, Разделитель); Если Позиция = 0 Тогда Результат = ""; Иначе Результат = Сред(Строка, Позиция + 1); КонецЕсли; Возврат Результат; КонецФункции Функция СтрокаБезПоследнегоФрагментаЛкс(Знач Строка, Знач Разделитель = ".") Экспорт Результат = Лев(Строка, СтрНайтиЛкс(Строка, Разделитель, Истина) - 1); Возврат Результат; КонецФункции // Получает строку путем повтора переданной строки заданное количество раз. // // Параметры: // СтрокаДляПовтора - Строка; // ЧислоПовторов - Число. // // Возвращаемое значение: // Строка. // Функция СтрокаПовторомЛкс(СтрокаДляПовтора, ЧислоПовторов) Экспорт Результат = ""; Для Счетчик = 1 По ЧислоПовторов Цикл Результат = Результат + СтрокаДляПовтора; КонецЦикла; Возврат Результат; КонецФункции // Преобразует исходную строку в число без вызова исключений. // // Параметры: // Значение - Строка - строка, которую необходимо привести к числу. // Например, "10", "+10", "010", вернет 10; // "(10)", "-10",вернет -10; // "10,2", "10.2",вернет 10.2; // "000", " ", "",вернет 0; // "10текст", вернет Неопределено. // ОписаниеТипов - ОписаниеТипов - Допустимое описание типов численного значения // выхПримечание - Строка - описание ошибки // // Возвращаемое значение: // Число - полученное число. // Функция СтрокаВЧислоЛкс(Представление, Знач ОписаниеТипов = Неопределено, выхПримечание = "") Экспорт _РежимОтладки = Ложь; Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 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); ЭтоЦифра = Символ >= "0" и Символ <= "9"; Если ЭтоЦифра Тогда Если НачалоЧисла = 0 Тогда НачалоЧисла = к; КонецЕсли; Иначе Если НачалоЧисла <> 0 Тогда СтрокаЧисла = Сред(Представление, НачалоЧисла, к - НачалоЧисла); Если СтрДлина(СтрокаЧисла) = 4 Тогда выхПозицияГода = МассивЧастей.Количество(); КонецЕсли; МассивЧастей.Добавить(Число(СтрокаЧисла)); КонецЕсли; НачалоЧисла = 0; КонецЕсли; КонецЦикла; Иначе // Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru) Для к = 1 По СтрДлина(Представление) Цикл   Символ = Сред(Представление, к ,1);   ЭтоЦифра = Символ >= "0" и Символ <= "9";   Если ЭтоЦифра Тогда   Если НачалоЧисла = 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 По Фрагменты.ВГраница() Цикл Фрагмент = СтрЗаменить(Фрагменты[Индекс], УИД, """"); Если Индекс % 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, ТекущаяСтрока[ИмяКлючевойКолонки]); ТекущаяСтрока = ТекущаяСтрока.Родитель; КонецЦикла; Возврат КлючиУровней; КонецФункции // Результат - Массив Функция ПолучитьАдресСтрокиДереваФормыЛкс(Знач СтрокаДерева, Знач ИмяКлючевойКолонки = "Ссылка") Экспорт КлючиУровней = Новый Массив(); ТекущаяСтрока = СтрокаДерева; Пока ТекущаяСтрока <> Неопределено Цикл КлючиУровней.Вставить(0, ТекущаяСтрока[ИмяКлючевойКолонки]); ТекущаяСтрока = ТекущаяСтрока.ПолучитьРодителя(); КонецЦикла; Возврат КлючиУровней; КонецФункции // Формирует путь строкой для элемента древовидной структуры. // Параметры: // ИмяКолонки - Строка - если задать пустое значение, то будет использован индекс строк дерева; // ИгнорироватьПростойПервыйУровень - Булево - если на первом уровне только одна строка, то игнорировать ее; Функция Дерево_ПутьСтрокойЛкс(СтрокаДерева, ИмяКолонки = "Имя", ИгнорироватьПростойПервыйУровень = Ложь, Разделитель = ".", Дерево = Неопределено, Исключения = Неопределено) Экспорт Если СтрокаДерева = Неопределено Тогда Возврат Неопределено; КонецЕсли; Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда Родитель = РодительСтрокиДереваЛкс(СтрокаДерева, Дерево); Дочерние = ДочерниеЭлементыДереваЛкс(Родитель); Результат = Дочерние.Индекс(СтрокаДерева); Иначе Если Исключения <> Неопределено Тогда Для Каждого Структура Из Исключения Цикл Если СравнитьЗначенияСвойствЛкс(СтрокаДерева, Структура, Структура.СвойстваДляСравнения) Тогда Результат = Структура[ИмяКолонки]; Прервать; КонецЕсли; КонецЦикла; КонецЕсли; Если Результат = Неопределено Тогда Результат = СтрокаДерева[ИмяКолонки]; КонецЕсли; КонецЕсли; Если ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева") Тогда Родитель = СтрокаДерева.ПолучитьРодителя(); Иначе Родитель = СтрокаДерева.Родитель; КонецЕсли; Если Родитель = Неопределено Тогда Если Истина И ИгнорироватьПростойПервыйУровень И СтрокаДерева.Владелец().Строки.Количество() = 1 Тогда Результат = Неопределено; КонецЕсли; Иначе РезультатСверху = Дерево_ПутьСтрокойЛкс(Родитель, ИмяКолонки, ИгнорироватьПростойПервыйУровень, Разделитель, Дерево, Исключения); Если РезультатСверху <> Неопределено Тогда Результат = РезультатСверху + Разделитель + Результат; КонецЕсли; КонецЕсли; Возврат XMLСтрока(Результат); КонецФункции // Ищет элемент древовидной структуры по пути строкой. // Параметры: // ИмяКолонки - Строка - если задать пустое значение, то будет использован индекс строк дерева; // ИгнорироватьПростойПервыйУровень - Булево - если на первом уровне только одна строка, то игнорировать ее; Функция Дерево_НайтиПоПутиСтрокойЛкс(СтрокаДерева, ИмяКолонки = "Имя", Путь, ИгнорироватьПростойПервыйУровень = Ложь, Разделитель = ".") Экспорт Если Истина И ИгнорироватьПростойПервыйУровень И ТипЗнч(СтрокаДерева) = Тип("ДеревоЗначений") И СтрокаДерева.Строки.Количество() = 1 Тогда Возврат Дерево_НайтиПоПутиСтрокойЛкс(СтрокаДерева.Строки[0], ИмяКолонки, Сред(Путь, 2)); КонецЕсли; ТекущийУровень = ПервыйФрагментЛкс(Путь, Разделитель); Если Не ЗначениеЗаполнено(ТекущийУровень) Тогда Возврат СтрокаДерева; КонецЕсли; ОстальнойПуть = Сред(Путь, СтрДлина(ТекущийУровень + Разделитель) + 1); Если Не ЗначениеЗаполнено(ИмяКолонки) Тогда ЗначениеИндекса = Число(ТекущийУровень); Дочерние = ДочерниеЭлементыДереваЛкс(СтрокаДерева); Если Дочерние.Количество() > ЗначениеИндекса Тогда ТекущаяСтрока = Дочерние[ЗначениеИндекса]; КонецЕсли; Иначе Если Ложь Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыДерево") Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева") Тогда ТекущаяСтрока = Неопределено; ДочерниеЭлементы = СтрокаДерева.ПолучитьЭлементы(); Для Каждого ДочернийЭлемент Из ДочерниеЭлементы Цикл Если ДочернийЭлемент[ИмяКолонки] = ТекущийУровень Тогда ТекущаяСтрока = ДочернийЭлемент; Прервать; КонецЕсли; КонецЦикла; Иначе ТекущаяСтрока = СтрокаДерева.Строки.Найти(ТекущийУровень, ИмяКолонки); КонецЕсли; КонецЕсли; Если ТекущаяСтрока <> Неопределено Тогда Возврат Дерево_НайтиПоПутиСтрокойЛкс(ТекущаяСтрока, ИмяКолонки, ОстальнойПуть,, Разделитель); Иначе Возврат СтрокаДерева; КонецЕсли; КонецФункции Функция ДочерниеЭлементыДереваЛкс(Знач СтрокаДерева) Экспорт Дочерние = Неопределено; Если Ложь Или ТипЗнч(СтрокаДерева) = Тип("ДеревоЗначений") Или ТипЗнч(СтрокаДерева) = Тип("СтрокаДереваЗначений") Тогда Дочерние = СтрокаДерева.Строки; ИначеЕсли Ложь Или ТипЗнч(СтрокаДерева) = Тип("ОтборКомпоновкиДанных") Или ТипЗнч(СтрокаДерева) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Или ТипЗнч(СтрокаДерева) = Тип("ДоступныеПоляКомпоновкиДанных") Или ТипЗнч(СтрокаДерева) = Тип("ДоступноеПолеКомпоновкиДанных") Или ТипЗнч(СтрокаДерева) = Тип("ДоступноеПолеОтбораКомпоновкиДанных") Тогда Дочерние = СтрокаДерева.Элементы; ИначеЕсли Ложь Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыДерево") Или ТипЗнч(СтрокаДерева) = Тип("ДанныеФормыЭлементДерева") Тогда Дочерние = СтрокаДерева.ПолучитьЭлементы(); Иначе ВызватьИсключение "Неподдерживаемый тип элемента дерева - " + ТипЗнч(СтрокаДерева); КонецЕсли; Возврат Дочерние; КонецФункции // Процедура заполняет колонку дерева значением. // // Параметры // ЭлементДЗ - ДеревоЗначений; // ИмяКолонки - Строка; // ЗначениеКолонки - Произвольный. // Процедура ЗаполнитьКолонкуДереваЛкс(ЭлементДЗ, ИмяКолонки, ЗначениеКолонки) Экспорт Для Каждого ПодчиненнаяСтрока Из ЭлементДЗ.Строки Цикл ПодчиненнаяСтрока[ИмяКолонки] = ЗначениеКолонки; ЗаполнитьКолонкуДереваЛкс(ПодчиненнаяСтрока, ИмяКолонки, ЗначениеКолонки); КонецЦикла; КонецПроцедуры Процедура ЗаполнитьКолонкуТабличнойЧастиЛкс(ТабличнаяЧасть, Знач ИмяКолонки, Знач Значение = Неопределено) Экспорт ВыгрузкаКолонки = ТабличнаяЧасть.Выгрузить(, ИмяКолонки); ВыгрузкаКолонки.ЗаполнитьЗначения(Значение); ТабличнаяЧасть.ЗагрузитьКолонку(ВыгрузкаКолонки.ВыгрузитьКолонку(0), ИмяКолонки); КонецПроцедуры // Процедура удаляет все строки таблицы или дерева со значением в колонке. // // Параметры // ЭлементДЗ - ДеревоЗначений, СтрокаДереваЗначений; // ИмяКолонки - Строка; // ЗначениеКолонки - Произвольный. // Процедура УдалитьСтрокиТаблицыИлиДереваПоЗначениюВКолонкеЛкс(Знач ТаблицаИлиДерево, Знач ИмяКолонки, Знач ЗначениеКолонки) Экспорт Если Ложь Или ТипЗнч(ТаблицаИлиДерево) = Тип("ДеревоЗначений") Или ТипЗнч(ТаблицаИлиДерево) = Тип("СтрокаДереваЗначений") Тогда Строки = ТаблицаИлиДерево.Строки; НачальноеКоличество = Строки.Количество(); Для Счетчик = 1 По НачальноеКоличество Цикл ПодчиненнаяСтрока = Строки[НачальноеКоличество - Счетчик]; Если ПодчиненнаяСтрока[ИмяКолонки] = ЗначениеКолонки Тогда Строки.Удалить(ПодчиненнаяСтрока); Иначе УдалитьСтрокиТаблицыИлиДереваПоЗначениюВКолонкеЛкс(ПодчиненнаяСтрока, ИмяКолонки, ЗначениеКолонки); КонецЕсли; КонецЦикла; Иначе //! ТаблицаИлиДерево = 0 // ТаблицаЗначений Найденные = ТаблицаИлиДерево.НайтиСтроки(Новый Структура(ИмяКолонки, ЗначениеКолонки)); Для Каждого Строка Из Найденные Цикл ТаблицаИлиДерево.Удалить(Строка); КонецЦикла; КонецЕсли; КонецПроцедуры Функция ДекодироватьТекстИзXMLЛкс(Знач Текст) Экспорт //{ Заменяем символы, критичные для XML Текст = СтрЗаменить(Текст,"&","&"); Текст = СтрЗаменить(Текст,"<","<"); Текст = СтрЗаменить(Текст,">",">"); Текст = СтрЗаменить(Текст," "," "); Результат = Текст; // Этот способ вернет пустую строку, если текст содержит XML элемент //ЧтениеXML = Новый ЧтениеXML; //ЧтениеXML.УстановитьСтроку("<ф>" + Текст + ""); //ЧтениеXML.Прочитать(); //ЧтениеXML.Прочитать(); //Результат = ЧтениеXML.Значение; Возврат Результат; КонецФункции Функция КодироватьТекстВXMLЛкс(Текст) Экспорт Если Текст = "" Тогда Возврат ""; КонецЕсли; //{ Заменяем символы, критичные для XML //выхХМЛТело = СтрЗаменить(выхХМЛТело,"&","&"); //выхХМЛТело = СтрЗаменить(выхХМЛТело,"<","<"); //выхХМЛТело = СтрЗаменить(выхХМЛТело,">",">"); ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.УстановитьСтроку(""); ЗаписьXML.ЗаписатьНачалоЭлемента("ф"); ЗаписьXML.ЗаписатьТекст(Текст); ЗаписьXML.ЗаписатьКонецЭлемента(); Результат = ТекстМеждуМаркерамиЛкс(ЗаписьXML.Закрыть(), "<ф>", "", Ложь); Возврат Результат; КонецФункции Функция СтрокаВнутрВХМЛТелоЛкс(Знач вхСтрока, выхХМЛТело = Неопределено, Знач ДобавитьПереносыСтрок = Ложь) Экспорт выхХМЛТело = вхСтрока; выхХМЛТело = КодироватьТекстВXMLЛкс(выхХМЛТело); МаркерПодмены = "по!ап17ъzg"; выхХМЛТело = СтрЗаменить(выхХМЛТело, ", ", МаркерПодмены); //выхХМЛТело = СтрЗаменить(выхХМЛТело, "{", ""); // Ложные срабатывания были выхХМЛТело = СтрЗаменить(Символы.ПС + выхХМЛТело, Символы.ПС + "{", Символы.ПС + ""); //выхХМЛТело = СтрЗаменить(выхХМЛТело, "}", ""); // Ложные срабатывания были выхХМЛТело = СтрЗаменить(выхХМЛТело, "},", ","); выхХМЛТело = СтрЗаменить(выхХМЛТело + Символы.ПС, "}" + Символы.ПС, "" + Символы.ПС); // Замена одинарных символов выхХМЛТело = СтрЗаменить(выхХМЛТело, ",", ""); // Удаляем лишние блоки и выхХМЛТело = СтрЗаменить(выхХМЛТело, "", ""); выхХМЛТело = СтрЗаменить(выхХМЛТело, "" + Символы.ПС + "", ""); выхХМЛТело = СтрЗаменить(выхХМЛТело, "", ""); выхХМЛТело = СтрЗаменить(выхХМЛТело, "" + Символы.ПС + "", ""); выхХМЛТело = СтрЗаменить(выхХМЛТело, МаркерПодмены, ", "); Если ДобавитьПереносыСтрок Тогда // Добавляем перенос строки к и к для удобства поиска различий выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "" + СИМВОЛЫ.ПС); выхХМЛТело = СтрЗаменить(выхХМЛТело, "", "" + СИМВОЛЫ.ПС); КонецЕсли; Возврат выхХМЛТело; КонецФункции Функция НоваяВКОбщаяЛкс(Счетчик = 0) Экспорт КэшКомпонентыИспорчен = Ложь; Суффикс = ""; Пока Счетчик < 60 Цикл Попытка //ВК = Новый ("AddIn.ирОбщая" + Суффикс + ".AddIn"); // При порче кэша тут попытка не срабатывала и исключение шло в вызывающий метод ВК = СоздатьВКОбщая(КэшКомпонентыИспорчен, Суффикс, Счетчик); Прервать; Исключение Это64битныйПроцесс = ирКэш.Это64битныйПроцессЛкс(); ИмяМакета = "ВК"; Если Это64битныйПроцесс Тогда ИмяМакета = ИмяМакета + "64"; Иначе ИмяМакета = ИмяМакета + "32"; КонецЕсли; Если ирКэш.ЛиПортативныйРежимЛкс() Тогда ДвоичныеДанные = ирПортативный.ПолучитьМакет(ИмяМакета); АдресКомпоненты = ПолучитьИмяВременногоФайла("dll"); ДвоичныеДанные.Записать(АдресКомпоненты); //АдресКомпоненты = "D:\VC\Native_Comp_RDT\binWin32\AddInNative.dll"; // Для отладки Иначе // https://www.hostedredmine.com/issues/967297 //ДвоичныеДанные = Обработки.ирПортативный.ПолучитьМакет(ИмяМакета); АдресКомпоненты = "Обработка.ирПортативный.Макет." + ИмяМакета; КонецЕсли; Если КэшКомпонентыИспорчен Тогда // https://www.hostedredmine.com/issues/889213 // Занимаем новую ячейку в кэше внутренних компонент рабочего процесса. Суффикс = XMLСтрока(Счетчик); КонецЕсли; Результат = ПодключитьВнешнююКомпоненту(АдресКомпоненты, "ирОбщая" + Суффикс, ТипВнешнейКомпоненты.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", СтрокаНомерТаблицы); СтрокаСтруктуры = СтруктураБД.Найти(ИмяКандидат, "КраткоеИмяТаблицыХранения"); Если СтрокаСтруктуры <> Неопределено Тогда Возврат СтрокаСтруктуры.Метаданные; КонецЕсли; КонецЦикла; Возврат Неопределено; КонецФункции // Функция - Преобразовать представление в ссылку лкс // // Параметры: // МенеджерИлиОбъектМД - - // Текст - - // ПроверятьПредставлениеТипаДокумента - - // КэшПоиска - - // // Возвращаемое значение: // Ссылка, СписокЗначений - // Функция ПреобразоватьПредставлениеВСсылкуЛкс(Знач МенеджерИлиОбъектМД, Знач Текст, Знач ПроверятьПредставлениеТипаДокумента = Ложь, КэшПоиска = Неопределено) Экспорт Если ТипЗнч(МенеджерИлиОбъектМД) = Тип("ОбъектМетаданных") Тогда Менеджер = ПолучитьМенеджерЛкс(МенеджерИлиОбъектМД); Иначе Менеджер = МенеджерИлиОбъектМД; // СправочникМенеджер КонецЕсли; Текст = СокрЛП(Текст); Если Не ПроверятьПредставлениеТипаДокумента Тогда УникальныйИдентификатор = ирКэш.Получить().УникальныйИдентификаторИзСтроки(Текст); Если УникальныйИдентификатор <> Неопределено Тогда Значение = Менеджер.ПолучитьСсылку(УникальныйИдентификатор); КонецЕсли; КонецЕсли; Если Не ЗначениеЗаполнено(Значение) Тогда ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(Менеджер)); ПоляБД = ирКэш.ПоляТаблицыБДЛкс(ОбъектМД.ПолноеИмя()); RegExp = ирКэш.Получить().RegExp; RegExp.Pattern = "([^ ]+)\ от\ (\d+\.\d+\.\d+\ \d+\:\d+\:\d+)$"; // станадартное представление документа Результаты = RegExp.НайтиВхождения(Текст); Если Истина И ПоляБД.Найти("Номер") <> Неопределено И ПоляБД.Найти("Дата") <> Неопределено И Результаты.Количество() > 0 Тогда Номер = Результаты[0].SubMatches(0); Дата = Результаты[0].SubMatches(1); Попытка Дата = Дата(Дата); Исключение Дата = Неопределено; КонецПопытки; ПредставлениеТипа = ОбъектМД.ПредставлениеОбъекта; Если Не ЗначениеЗаполнено(ПредставлениеТипа) Тогда ПредставлениеТипа = ОбъектМД.Представление(); КонецЕсли; Если Истина И Дата <> Неопределено И (Ложь Или Не ПроверятьПредставлениеТипаДокумента Или СтрокиРавныЛкс(Лев(Текст, Результаты[0].FirstIndex), ПредставлениеТипа + " ")) Тогда КлючКэша = ОбъектМД.ПолноеИмя() + "." + Текст; Если КэшПоиска <> Неопределено Тогда Значение = КэшПоиска[КлючКэша]; КонецЕсли; Если Значение = Неопределено Тогда Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ | _Т.Ссылка |ИЗ | " + ОбъектМД.ПолноеИмя() + " КАК _Т |ГДЕ | _Т.Номер = &Номер | И _Т.Дата = &Дата |"; Запрос.УстановитьПараметр("Номер", Номер); Запрос.УстановитьПараметр("Дата", Дата); Значение = Новый СписокЗначений; Значение.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(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 МенеджерЗаписи = МенеджерРегистра.СоздатьМенеджерЗаписи(); МенеджерЗаписи.Объект = Объект[ИмяПоляСсылка]; МенеджерЗаписи.Свойство = ДопРеквизит; МенеджерЗаписи.Значение = НовоеЗначение; Если ТаблицаДопСведения = Неопределено Тогда НаборЗаписей = МенеджерРегистра.СоздатьНаборЗаписей(); ДопСведения = НаборЗаписейИзКлючаЛкс(НаборЗаписей, МенеджерЗаписи, Истина); ЗаписатьОбъектЛкс(ДопСведения); Иначе #Если Сервер И Не Сервер Тогда ТаблицаДопСведения = Новый ТаблицаЗначений; #КонецЕсли СтрокаНабора = ТаблицаДопСведения.Найти(МенеджерЗаписи.Свойство , "Свойство"); Если СтрокаНабора = Неопределено Тогда СтрокаНабора = ТаблицаДопСведения.Добавить(); ЗаполнитьЗначенияСвойств(СтрокаНабора, МенеджерЗаписи); КонецЕсли; СтрокаНабора.Значение = МенеджерЗаписи.Значение; Если Не ЗначениеЗаполнено(СтрокаНабора.Значение) Или СтрокаНабора.Значение = Ложь Тогда ТаблицаДопСведения.Удалить(СтрокаНабора); КонецЕсли; КонецЕсли; КонецЕсли; КонецПроцедуры Функция ЗначениеДопРеквизитаБСПЛкс(Знач Объект, ДопРеквизит, Знач ИмяПоляСсылка = "") Экспорт Если Не ЗначениеЗаполнено(ИмяПоляСсылка) Тогда ИмяПоляСсылка = ПеревестиСтроку("Ссылка"); КонецЕсли; Если Не ДопРеквизит.ЭтоДополнительноеСведение Тогда // изменение дополнительного реквизита НайденнаяСтрока = Объект.ДополнительныеРеквизиты.Найти(ДопРеквизит, "Свойство"); Если НайденнаяСтрока <> Неопределено Тогда ТекущееЗначение = НайденнаяСтрока.Значение; КонецЕсли; Иначе Запрос = Новый Запрос; Запрос.Текст = " |ВЫБРАТЬ | ДополнительныеСведения.Значение КАК Значение |ИЗ | РегистрСведений.ДополнительныеСведения КАК ДополнительныеСведения |ГДЕ | ДополнительныеСведения.Свойство = &Свойство | И ДополнительныеСведения.Объект = &Объект |"; Запрос.УстановитьПараметр("Объект", Объект[ИмяПоляСсылка]); Запрос.УстановитьПараметр("Свойство", ДопРеквизит); Результат = Запрос.Выполнить().Выгрузить(); Если Результат.Количество() > 0 Тогда ТекущееЗначение = Результат[0].Значение; Иначе ТекущееЗначение = Неопределено; КонецЕсли; КонецЕсли; Возврат ТекущееЗначение; КонецФункции Функция ЭтоУпрДинамическийСписокИРЛкс(Знач Форма) Экспорт Возврат Форма.ИмяФормы = "Обработка.ирДинамическийСписок.Форма.ФормаУпр"; КонецФункции Функция УправляемаяФормаБСП_ВыполнитьНаСервереЛкс(Знач Форма, Знач Обработчик, ПараметрКоманды = Неопределено) Экспорт ИмяКомандыВФорме = ПоследнийФрагментЛкс(Обработчик); ПараметрыВызова = Новый Структура; ПараметрыВызова.Вставить("ИмяКомандыВФорме", ИмяКомандыВФорме); ПараметрыВызова.Вставить("ПараметрКоманды", ПараметрКоманды); ПараметрыВызова.Вставить("Результат", Новый Структура("Текст")); Если ЭтоУпрДинамическийСписокИРЛкс(Форма) Тогда Форма.Подключаемый_ВыполнитьКомандуНаСервере(ПараметрыВызова); РезультатВызова = ПараметрыВызова.Результат.Текст; ИначеЕсли Истина И ирКэш.НомерВерсииБСПЛкс() > 200 И (Ложь Или МетодРеализованЛкс(Форма, "Подключаемый_ВыполнитьКомандуНаСервере") Или МетодРеализованЛкс(Форма, "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере")) Тогда Попытка ТаблицаКомандБСП = ПолучитьИзВременногоХранилища(Форма.ПараметрыПодключаемыхКоманд.АдресТаблицыКоманд); Исключение ОписаниеОшибки = ОписаниеОшибки(); // Для отладки Возврат Неопределено; КонецПопытки; #Если Сервер И Не Сервер Тогда ТаблицаКомандБСП = Новый ТаблицаЗначений; УправляемаяФормаБСП_СерверныеМетаданныеЛкс(); #КонецЕсли Если ТаблицаКомандБСП.Найти(ИмяКомандыВФорме, "ИмяВФорме") = Неопределено Тогда ОписаниеКоманды = ТаблицаКомандБСП.Добавить(); ОписаниеКоманды.ИмяВФорме = ИмяКомандыВФорме; ОписаниеКоманды.Обработчик = Обработчик; АдресТаблицыКомандБСП = ПоместитьВоВременноеХранилище(ТаблицаКомандБСП, Форма.УникальныйИдентификатор); Форма.ПараметрыПодключаемыхКоманд.АдресТаблицыКоманд = АдресТаблицыКомандБСП; КонецЕсли; Если МетодРеализованЛкс(Форма, "Подключаемый_ВыполнитьКомандуНаСервере") Тогда Форма.Подключаемый_ВыполнитьКомандуНаСервере(ПараметрыВызова, ); ИначеЕсли МетодРеализованЛкс(Форма, "Подключаемый_ПродолжитьВыполнениеКомандыНаСервере") Тогда Форма.Подключаемый_ПродолжитьВыполнениеКомандыНаСервере(ПараметрыВызова, ); КонецЕсли; РезультатВызова = ПараметрыВызова.Результат.Текст; КонецЕсли; Возврат РезультатВызова; КонецФункции Функция УправляемаяФормаБСП_СерверныеМетаданныеЛкс(ПараметрКоманды, Контекст) Экспорт Результат = Новый Структура; НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных; СкопироватьЭлементыКомпоновкиЛкс(НастройкиКомпоновки.УсловноеОформление, Контекст.Форма.УсловноеОформление); ОбработчикиСобытий = ВсеОбработчикиСобытийФормаЛкс(Контекст.Форма); ОбработчикиСобытий.ЗаполнитьЗначения(Неопределено, "СтрокаОписания"); Результат.Вставить("ОбработчикиСобытий", ОбработчикиСобытий); Результат.Вставить("Компоновка", НастройкиКомпоновки); Контекст.Результат.Текст = Результат; КонецФункции Функция ВсеОбработчикиСобытийФормаЛкс(Знач Форма, Знач Кэшировать = Ложь) Экспорт СлужебныеДанные = СлужебныеДанныеФормыЛкс(Форма); Результат = Неопределено; Если Не Кэшировать Или Не СлужебныеДанные.Свойство("ВсеОбработчикиСобытий", Результат) Тогда Если Ложь #Если Клиент Тогда Или ТипЗнч(Форма) = Тип("Форма") #КонецЕсли Тогда Элементы = Форма.ЭлементыФормы; Иначе Элементы = Форма.Элементы; КонецЕсли; Элементы = МассивИзКоллекцииЛкс(Элементы); Элементы.Вставить(0, Форма); Результат = Новый ТаблицаЗначений; Результат.Колонки.Добавить("Имя"); Результат.Колонки.Добавить("Событие"); Результат.Колонки.Добавить("Обработчик"); Результат.Колонки.Добавить("НОбработчик"); Результат.Колонки.Добавить("СтрокаОписания"); Для Каждого ГлавныйЭлемент Из Элементы Цикл Если ТипЗнч(ГлавныйЭлемент) = Тип("ГруппаФормы") Тогда Продолжить; КонецЕсли; ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(ГлавныйЭлемент,, Результат, СлужебныеДанные); #Если Клиент Тогда Если ТипЗнч(ГлавныйЭлемент) = Тип("ТабличноеПоле") Тогда Для Каждого Колонка Из ГлавныйЭлемент.Колонки Цикл Если Колонка <> Неопределено Тогда ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(Колонка.ЭлементУправления, ГлавныйЭлемент.Имя + ".Колонки." + Колонка.Имя + ".ЭлементУправления", Результат); КонецЕсли; КонецЦикла; КонецЕсли; #КонецЕсли КонецЦикла; Результат.Индексы.Добавить("НОбработчик"); СлужебныеДанные.Вставить("ВсеОбработчикиСобытий", Результат); КонецЕсли; Возврат Результат; КонецФункции //. // Параметры: // ГлавныйЭлемент - СообщениеПользователю - // ОбработчикиСобытий - ТаблицаЗначений - Процедура ДобавитьОбработчикиЭлементаФормыВТаблицуЛкс(Знач Элемент, Знач ПолноеИмя = "", Знач ТаблицаОбработчиков, Знач СлужебныеДанные = Неопределено) События = СобытияЭлементаФормыЛкс(Элемент); Если События.Количество() = 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 Тогда СтрокаЗамера = ТаблицаЗамеров[ТаблицаЗамеров.Количество() - 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 По ТабличныйДокумент.ШиринаТаблицы Цикл Если ЛиПерваяСтрокаСодержитИменаКолонок Тогда ИмяКолонки = ТабличныйДокумент.Область(1, Счетчик).Текст; Если Найти(ИмяКолонки, ".") > 0 Тогда Если Найти(ИмяКолонки, "_") > 0 Тогда ВызватьИсключение "В именах колонок макета не допускается использование одновременно ""_"" и ""."""; КонецЕсли; ИмяКолонки = СтрЗаменить(ИмяКолонки, ".", "_"); КонецЕсли; ИмяКолонки = АвтоУникальноеИмяВКоллекцииЛкс(ТаблицаПриемник.Колонки, ИмяКолонки,,, "Колонка1"); Иначе ИмяКолонки = "Колонка" + Счетчик; КонецЕсли; Если ЛиВтораяСтрокаСодержитТипыЗначений Тогда ИменаТипов = ТабличныйДокумент.Область(2, Счетчик).Текст; Иначе ИменаТипов = ""; КонецЕсли; Если ЗначениеЗаполнено(ИменаТипов) Тогда ТипизированныеКолонки[Счетчик] = 1; ИначеЕсли Не ВычислятьНетипизированныеЗначения Тогда ИменаТипов = "Строка"; КонецЕсли; ТаблицаПриемник.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов(ИменаТипов),, ТабличныйДокумент.Область(1, Счетчик).ШиринаКолонки); КонецЦикла; // Цикл перебора строк табличного документа ВысотаТаблицы = ТабличныйДокумент.ВысотаТаблицы; //Индикатор = ПолучитьИндикаторПроцессаЛкс(ТабличныйДокумент.ВысотаТаблицы); Для НомерСтроки = НачальнаяСтрока По ВысотаТаблицы Цикл // Добавление строки результирующей таблицы НоваяСтрокаТЗ = ТаблицаПриемник.Добавить(); Для НомерКолонки = 1 По ТабличныйДокумент.ШиринаТаблицы Цикл Область = ТабличныйДокумент.Область(НомерСтроки, НомерКолонки); ТекстЯчейки = Область.Текст; Если ОбрезватьКонечныеПробелы Тогда ТекстЯчейки = СокрП(ТекстЯчейки); КонецЕсли; ЗначениеЯчейки = Неопределено; ОписаниеТиповКолонки = Неопределено; Если ТипизированныеКолонки[НомерКолонки] <> Неопределено Тогда ОписаниеТиповКолонки = ТаблицаПриемник.Колонки[НомерКолонки - 1].ТипЗначения; Если ОписаниеТиповКолонки.СодержитТип(Тип("ОписаниеТипов")) Тогда Попытка ЗначениеЯчейки = Новый ОписаниеТипов(ТекстЯчейки); Исключение КонецПопытки; ИначеЕсли ОписаниеТиповКолонки.СодержитТип(Тип("Тип")) Тогда Попытка ЗначениеЯчейки = Тип(ТекстЯчейки); Исключение КонецПопытки; ИначеЕсли ОписаниеТиповКолонки.СодержитТип(Тип("Картинка")) Тогда Поддокумент = ТабличныйДокумент.ПолучитьОбласть(НомерСтроки, НомерКолонки); // Тяжелая операция Если Поддокумент.Рисунки.Количество() > 0 Тогда ЗначениеЯчейки = Поддокумент.Рисунки[0].Картинка; КонецЕсли; КонецЕсли; КонецЕсли; Если Ложь Или ВычислятьНетипизированныеЗначения Или (Истина И ОписаниеТиповКолонки <> Неопределено И ЗначениеЯчейки = Неопределено) Тогда Если ВычислятьНетипизированныеЗначения Или ОписаниеТиповКолонки.СодержитТип(Тип("Булево")) Тогда Если СтрокиРавныЛкс(ТекстЯчейки, "Да",, Истина) Тогда ЗначениеЯчейки = Истина; ИначеЕсли СтрокиРавныЛкс(ТекстЯчейки, "Нет",, Истина) Тогда ЗначениеЯчейки = Ложь; КонецЕсли; КонецЕсли; Если ЗначениеЯчейки = Неопределено И ЗначениеЗаполнено(ТекстЯчейки) Тогда Попытка ЗначениеЯчейки = Вычислить(ТекстЯчейки); Исключение КонецПопытки; КонецЕсли; КонецЕсли; Если ЗначениеЯчейки = Неопределено Тогда ЗначениеЯчейки = ТекстЯчейки; КонецЕсли; НоваяСтрокаТЗ[НомерКолонки - 1] = ЗначениеЯчейки; КонецЦикла; КонецЦикла; Если НомерТекущейСтроки > 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 раза быстрее, но инициирует модули менеджеров Схема = Вычислить("Новый СхемаЗапроса"); #Если Сервер И Не Сервер Тогда Схема = Новый СхемаЗапроса; #КонецЕсли Попытка Схема.УстановитьТекстЗапроса(ТекстЗапроса); Исключение Если ВыбрасыватьИсключения Тогда ВызватьИсключение; КонецЕсли; Если ВыводитьСообщения Тогда СообщитьЛкс(ПодробноеПредставлениеОшибкиЛкс(ИнформацияОбОшибке().Причина)); КонецЕсли; //Возврат Неопределено; КонецПопытки; ТаблицаРезультата = Новый ТаблицаЗначений; Для Каждого КолонкаСхемы Из Схема.ПакетЗапросов[Схема.ПакетЗапросов.Количество() - 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 Тогда // Дочерние поля "ссылка" в дереве доступных полей компоновки отсутствуют Продолжить; КонецЕсли; Если ЗначениеЗаполнено(ТекущееИмяПоля) Тогда ТекущееИмяПоля = ТекущееИмяПоля + "."; КонецЕсли; ТекущееИмяПоля = ТекущееИмяПоля + Фрагмент; НовоеТекущееПоле = ТекущееПоле.Элементы.Найти(Новый ПолеКомпоновкиДанных(ТекущееИмяПоля)); Если Истина И ТекущееИмяПоля <> ПолноеИмяПоля И (Ложь Или НовоеТекущееПоле = Неопределено Или НовоеТекущееПоле.ТипЗначения.Типы().Количество() > ДопустимоеКоличествоТипов) Тогда Если Ложь Или Не МожноРодителя Или ТипЗнч(ТекущееПоле) = Тип("ДоступныеПоляКомпоновкиДанных") Тогда ТекущееПоле = Неопределено; КонецЕсли; Прервать; КонецЕсли; ТекущееПоле = НовоеТекущееПоле; КонецЦикла; Возврат ТекущееПоле; КонецФункции // Таблица - ТаблицаЗначений, ТабличнаяЧасть, НаборЗаписей Функция НеуникальныеЗначенияКолонкиТаблицыЛкс(Таблица, ИмяКолонки, ИгнорироватьРегистрДляПростогоСтрокогоТипа = Истина, ОтборСтрок = Неопределено) Экспорт Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда КопияТаблицы = Таблица.Скопировать(ОтборСтрок, ИмяКолонки); Иначе КопияТаблицы = Таблица.Выгрузить(ОтборСтрок, ИмяКолонки); КонецЕсли; Типы = КопияТаблицы.Колонки[ИмяКолонки].ТипЗначения.Типы(); Если Истина И Типы.Количество() = 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 Тогда Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл Если Ложь Или ЭлементОтбора.Использование Или ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы) Тогда Если СТипами Тогда ТипЗначения = ЭлементОтбора.ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ЭлементОтбора.Имя); КонецЕсли; КонецЦикла; КонецЕсли; Если ВключатьНомерСтроки Тогда Если ЛиКорневойТипПоследовательностиЛкс(ТипТаблицы) Тогда Для Каждого Измерение Из ОбъектМД.Измерения Цикл Если СТипами Тогда ТипЗначения = Измерение.Тип; КонецЕсли; СписокПолей.Добавить(ТипЗначения, Измерение.Имя); КонецЦикла; ИначеЕсли Истина И ТипТаблицы <> "Перерасчет" И (Ложь Или Не ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы) Или (ДляНабораЗаписейРегистраСведений И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору)) Тогда ИмяПоля = ПеревестиСтроку("НомерСтроки"); Если СТипами Тогда ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ИмяПоля); КонецЕсли; КонецЕсли; ИначеЕсли ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда ИмяПоля = ПеревестиСтроку("Ссылка"); Если СТипами Тогда ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ИмяПоля); Если ВключатьНомерСтроки Тогда ИмяПоля = ПеревестиСтроку("НомерСтроки"); Если СТипами Тогда ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ИмяПоля); КонецЕсли; ИначеЕсли ТипТаблицы = "Изменения" Тогда Для Каждого ПолеБД Из ПоляБД Цикл Если Ложь Или СтрокиРавныЛкс(ПолеБД.Имя, ПеревестиСтроку("НомерСообщения")) Тогда Продолжить; КонецЕсли; Если СТипами Тогда ТипЗначения = ПолеБД.ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ПолеБД.Имя); КонецЦикла; ИначеЕсли ТипТаблицы = "Внешняя" Тогда ТаблицаМД = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПолноеИмяТаблицыБД); Если ТаблицаМД.ТипДанныхТаблицы = Метаданные.СвойстваОбъектов.ТипДанныхТаблицыВнешнегоИсточникаДанных.ОбъектныеДанные Тогда СписокПолей.Добавить(Новый ОписаниеТипов(ИмяТипаДанныхТаблицыРегистраЛкс(ПолноеИмяТаблицыБД, "Ссылка")), ПеревестиСтроку("Ссылка")); Иначе НаборЗаписей = ирКэш.ЭталонныйНаборЗаписейЛкс(ПолноеИмяТаблицыБД); Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл Если СТипами Тогда ТипЗначения = ЭлементОтбора.ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ЭлементОтбора.Имя); КонецЦикла; КонецЕсли; ИначеЕсли ТипТаблицы = "ЖурналДокументов" Тогда ИмяПоля = ПеревестиСтроку("Ссылка"); Если СТипами Тогда ТипЗначения = ПоляБД.Найти(ИмяПоля, "Имя").ТипЗначения; КонецЕсли; СписокПолей.Добавить(ТипЗначения, ИмяПоля); ИначеЕсли ТипТаблицы = "Константа" Тогда ИначеЕсли ТипТаблицы = "Константы" Тогда ИначеЕсли Истина И ТипТаблицы = "ВиртуальнаяТаблица" И (Ложь Или СтрНачинаетсяСЛкс(ПолноеИмяТаблицыБД, "РегистрНакопления.") Или СтрНачинаетсяСЛкс(ПолноеИмяТаблицыБД, "РегистрБухгалтерии.")) Тогда ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицыБД); Для Каждого Поле Из ПоляБД Цикл Если Не ЛиПолеРожденоРесурсомНакопленияЛкс(ОбъектМД, Поле.Имя) Тогда СписокПолей.Добавить(Поле.ТипЗначения, Поле.Имя); КонецЕсли; КонецЦикла; Иначе ВызватьИсключение "Получение структуры ключа таблицы БД """ + ПолноеИмяТаблицыБД + """ не поддерживается"; КонецЕсли; Если ВернутьСтруктуру Тогда Результат = Новый Структура(); Для Каждого ЭлементСписка Из СписокПолей Цикл Результат.Вставить(ЭлементСписка.Представление, ЭлементСписка.Значение); КонецЦикла; Иначе Результат = СписокПолей; КонецЕсли; Возврат Результат; КонецФункции Функция ЛиПолеРожденоРесурсомНакопленияЛкс(ОбъектМД, ИмяПоля) Экспорт #Если Сервер И Не Сервер Тогда ОбъектМД = Метаданные.РегистрыБухгалтерии.Хозрасчетный; #КонецЕсли Успех = Ложь; Для Каждого Ресурс Из ОбъектМД.Ресурсы Цикл Если СтрНачинаетсяСЛкс(ИмяПоля, Ресурс.Имя) Тогда Успех = Истина; Прервать; КонецЕсли; КонецЦикла; Возврат Успех; КонецФункции Функция ДанныеСтрокиРегистраИзКлючаЗаписиЛкс(Знач КлючЗаписи, Знач ИмяТаблицыРегистра = "") Экспорт Если Не ЗначениеЗаполнено(ИмяТаблицыРегистра) Тогда ИмяТаблицыРегистра = ирКэш.ИмяТаблицыИзМетаданныхЛкс(Метаданные.НайтиПоТипу(ТипЗнч(КлючЗаписи)).ПолноеИмя()); КонецЕсли; СтруктураКлючаСтроки = СтруктураКлючаТаблицыБДЛкс(ИмяТаблицыРегистра,,, Ложь); ЗаполнитьЗначенияСвойств(СтруктураКлючаСтроки, КлючЗаписи); СхемаКомпоновки = СоздатьСхемуКомпоновкиТаблицыБДЛкс(ИмяТаблицыРегистра); НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных; СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, СтруктураКлючаСтроки); ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицыРегистра); Для Каждого ПолеТаблицы Из ПоляТаблицыБД Цикл #Если Сервер И Не Сервер Тогда ПолеТаблицы = Обработки.ирТипПолеБД.Создать(); #КонецЕсли НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, ПолеТаблицы.Имя); КонецЦикла; ДанныеСтроки = СкомпоноватьВКоллекциюЗначенийПоСхемеЛкс(СхемаКомпоновки, НастройкаКомпоновки); Результат = Неопределено; Если ДанныеСтроки.Количество() > 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 Функция ЗаполнитьЗначенияСвойствСтруктуройЛкс(Знач Приемник, Знач Источник, Знач СписокСвойств = Неопределено, Знач ИсключаяСвойства = Неопределено) Экспорт ИсключитьСвойстваИсточника = Новый Массив; для Каждого КлючИЗначение Из Новый Структура(ИсключаяСвойства) Цикл Если Источник.Свойство(КлючИЗначение.Ключ) Тогда ИсключитьСвойстваИсточника.Добавить(КлючИЗначение.Ключ); КонецЕсли; КонецЦикла; ЗаполнитьЗначенияСвойств(Приемник, Источник, СписокСвойств, СтрСоединитьЛкс(ИсключитьСвойстваИсточника)); КонецФункции Функция ИменаСвойствСтруктурыЛкс(Знач СтруктураИлиСтрокаТаблицы) Экспорт ИменаСвойств = ""; Если ТипЗнч(СтруктураИлиСтрокаТаблицы) <> Тип("Структура") Тогда СтруктураИлиСтрокаТаблицы = СтруктураИлиСтрокаТаблицы.Владелец().Колонки; КонецЕсли; Для Каждого КлючИЗначение Из СтруктураИлиСтрокаТаблицы Цикл Если ТипЗнч(КлючИЗначение) = Тип("КлючИЗначение") Тогда ИмяСвойства = КлючИЗначение.Ключ; Иначе ИмяСвойства = КлючИЗначение.Имя; КонецЕсли; ИменаСвойств = ИменаСвойств + "," + ИмяСвойства; КонецЦикла; ИменаСвойств = Сред(ИменаСвойств, 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 И ирКэш.ДоступныОбщиеРеквизитыЛкс() Тогда Если Метаданные.ОбщиеРеквизиты.Найти(СтрокаКолонкиБД.ИмяКолонки) <> Неопределено Тогда Продолжить; КонецЕсли; КонецЕсли; Если Не СтрокаКолонкиБД.ЕстьДоступ Тогда Продолжить; КонецЕсли; Если Не ЛиТекстПустой Тогда ТекстЗапроса.ЗаписатьБезОбработки(" |ОБЪЕДИНИТЬ ВСЕ"); Иначе ЛиТекстПустой = Ложь; КонецЕсли; ТекстЗапроса.ЗаписатьБезОбработки(" |ВЫБРАТЬ """ + СтрокаКолонкиБД.ПолноеИмяТаблицы + """ КАК ПолноеИмяТаблицы, """ + СтрокаКолонкиБД.ИмяКолонки + """ КАК ИмяКолонки, КОЛИЧЕСТВО(*) КАК Количество |ИЗ " + СтрокаКолонкиБД.ПолноеИмяТаблицы + " КАК Т"); // Очень долгий способ // ТекстЗапроса.ЗаписатьБезОбработки(" // |{ГДЕ Т." + СтрокаКолонкиБД.ИмяКолонки + " КАК ПолеОтбора}"); //КонецЦикла; //Схема = СоздатьСхемуКомпоновкиПоЗапросу(ТекстЗапроса,,, Истина); //НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных; //НайтиДобавитьЭлементОтбораКомпоновкиЛкс(НастройкаКомпоновки, "ПолеОтбора", ЗначениеОтбора, ВидСравненияНовый); //Запрос = ЗапросИзКомпоновкиЛкс(Схема, НастройкаКомпоновки); // ОписаниеПоля = ОписаниеПоляТаблицыБДЛкс(СтрокаКолонкиБД.ПолноеИмяТаблицы, СтрокаКолонкиБД.ИмяКолонки); ВыражениеСравнения = ВыражениеСравненияСПараметромВЗапросеЛкс(ОписаниеПоля, ВидСравненияНовый, "ЗначениеОтбора"); ТекстЗапроса.ЗаписатьБезОбработки(" |ГДЕ Т." + СтрокаКолонкиБД.ИмяКолонки + " " + ВыражениеСравнения); КонецЦикла; Запрос = Новый Запрос(ТекстЗапроса.Закрыть()); Запрос.Параметры.Вставить("ЗначениеОтбора", ЗначениеОтбора); Возврат Запрос; КонецФункции Функция ИмяВременнойТаблицыДляТаблицыБДЛкс(ПолноеИмяТаблицы, ИмяВременнойТаблицы = "ВТ") Экспорт ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы); Если ТипТаблицы = "Внешняя" Тогда ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы, Истина); ИмяВременнойТаблицы = ОбъектМД.Родитель().ПолноеИмя() + ".ВременнаяТаблица." + ИмяВременнойТаблицы; КонецЕсли; Возврат ИмяВременнойТаблицы; КонецФункции Функция ОписаниеПоляТаблицыБДЛкс(Знач ИмяТаблицыИлиПолноеИмяПоля, Знач ИмяПоля = "") Экспорт Если Не ЗначениеЗаполнено(ИмяПоля) Тогда ИмяПоля = ПоследнийФрагментЛкс(ИмяТаблицыИлиПолноеИмяПоля); ИмяТаблицыИлиПолноеИмяПоля = СтрокаБезПоследнегоФрагментаЛкс(ИмяТаблицыИлиПолноеИмяПоля); КонецЕсли; ПоляТаблицыБД = ирКэш.ПоляТаблицыБДЛкс(ИмяТаблицыИлиПолноеИмяПоля); ОписаниеПоля = ПоляТаблицыБД.Найти(ИмяПоля, "Имя"); Возврат ОписаниеПоля; КонецФункции Функция ПолноеИмяМДПоляТаблицыЛкс(ПолеТаблицыБД) Экспорт Попытка ПолноеИмя = ПолеТаблицыБД.Метаданные.ПолноеИмя(); Исключение ПолноеИмя = ""; КонецПопытки; Возврат ПолноеИмя; КонецФункции Функция ВыражениеСравненияСПараметромВЗапросеЛкс(Знач ОписаниеПоля, Знач ВидСравненияНовый, Знач ИмяПараметра) Экспорт Если ЛиОписаниеТиповНеограниченнойСтрокиЛкс(ОписаниеПоля.ТипЗначения) Тогда ВидСравненияНовый = ВидСравненияКомпоновкиДанных.Содержит; КонецЕсли; Если ОписаниеПоля.Имя = "ИмяПредопределенныхДанных" Тогда ВыражениеСравнения = " = 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 Или Найти(НОписаниеОшибки, "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); Результат = ТекстовыйДокумент.ПолучитьТекст(); КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ЛиЕстьКонтрольныеРусскиеБуквыЛкс(Строка) Экспорт КонтрольныеБуквыРусские = "ОоЕеАаИи"; Для Счетчик = 1 По СтрДлина(КонтрольныеБуквыРусские) Цикл Буква = Сред(КонтрольныеБуквыРусские, Счетчик, 1); Если Найти(Строка, Буква) > 0 Тогда Возврат Истина; КонецЕсли; КонецЦикла; Возврат Ложь; КонецФункции Функция НайтиИменаФайловЛкс(Путь, Маска = Неопределено, ИскатьВПодкаталогах = Истина, НаСервере = Ложь) Экспорт Если НаСервере Тогда Результат = ирСервер.НайтиИменаФайловЛкс(Путь, Маска, ИскатьВПодкаталогах); Иначе Файлы = НайтиФайлы(Путь, Маска, ИскатьВПодкаталогах); Результат = Новый Массив; Для Каждого Файл Из Файлы Цикл Результат.Добавить(Файл.ПолноеИмя); КонецЦикла; КонецЕсли; Возврат Результат; КонецФункции // Параметры: // ИзданиеПлатформы - Строка(0,П) // Функция КаталогПустойИнфобазыЛкс(Знач ИзданиеПлатформы = "") Экспорт Если Не ЗначениеЗаполнено(ИзданиеПлатформы) Тогда ИзданиеПлатформы = ирКэш.НомерИзданияПлатформыЛкс(); КонецЕсли; КаталогПустойИнфобазы = ирКэш.КаталогИзданияПлатформыВПрофилеЛкс(, ИзданиеПлатформы) + РазделительПутиКФайлуЛкс() + "EmptyDB"; Возврат КаталогПустойИнфобазы; КонецФункции Функция СтрокаСоединенияПустойИнфобазыЛкс(ИзданиеПлатформы = "", Знач СоздаватьБазуВСлучаеОтсутствия = Истина, Знач СоздаватьБазуВЛюбомСлучае = Ложь) Экспорт КаталогПустойИнфобазы = КаталогПустойИнфобазыЛкс(ИзданиеПлатформы); ФайлПустойИнфобазы = Новый Файл(КаталогПустойИнфобазы + РазделительПутиКФайлуЛкс() + "1CV8.1CD"); Если Ложь Или СоздаватьБазуВЛюбомСлучае Или СоздаватьБазуВСлучаеОтсутствия И Не ФайлПустойИнфобазы.Существует() Тогда УдалитьФайлы(КаталогПустойИнфобазы); СтрокаПараметров = "CREATEINFOBASE File=" + КаталогПустойИнфобазы + ";"; //СтрокаПараметров = СтрокаПараметров + " /AddInList ууууу"; ИмяФайлаЛога = ПолучитьИмяВременногоФайла(); СтрокаПараметров = СтрокаПараметров + " /out" + ИмяФайлаЛога; СтрокаЗапуска = """" + ИмяИсполняемогоФайлаКлиентаПлатформыЛкс() + """ " + СтрокаПараметров; РезультатКоманды = ВыполнитьКомандуОСЛкс(СтрокаЗапуска); Если ЗначениеЗаполнено(РезультатКоманды) Тогда СообщитьЛкс(РезультатКоманды); КонецЕсли; КонецЕсли; СтрокаСоединения = "File=""" + КаталогПустойИнфобазы + """;"; Результат = СтрокаСоединения; Возврат Результат; КонецФункции Функция КаталогОбщихФайловВсехВерсийПлатформыЛкс(x64 = Неопределено) Экспорт КаталогПрограммныхФайлов = КаталогПрограммныхФайловОСЛкс(x64); Если ирКэш.НомерИзданияПлатформыЛкс() = "82" Тогда Результат = КаталогПрограммныхФайлов + "\1cv82\common\"; ИначеЕсли ирКэш.НомерИзданияПлатформыЛкс() = "83" Тогда Результат = КаталогПрограммныхФайлов + "\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 ууууу"; Если Не ЗначениеЗаполнено(ПолноеИмяИсполняемогоФайла) Тогда ПолноеИмяИсполняемогоФайла = ИмяИсполняемогоФайлаКлиентаПлатформыЛкс(); КонецЕсли; ЗапуститьПриложение("""" + ПолноеИмяИсполняемогоФайла + """ " + СтрокаПараметров,, Истина); КонецЕсли; Возврат ""; КонецФункции // . // Параметры: // СтрокаСоединенияБазы - Строка - пустая строка трактуется как строка соединения пустой инфобазы Функция ВыполнитьКомандуКонфигуратораЛкс(Знач КомандаКонфигуратора, Знач СтрокаСоединенияБазы = "", выхТекстЛога = "", Знач ПодавлятьДиалоги = Истина, Знач Состояние = "", Знач УдалитьСуществующуюПустуюИнфобазу = Ложь, Знач ПолноеИмяИсполняемогоФайла = "", Знач ОжидатьЗавершения = Истина, Знач ИмяПользователя = "", Знач ПарольПользователя = "", Знач СообщитьСтрокуПараметров = Истина, Знач КодЯзыка = "", Знач СообщитьТекстЛога = Ложь, Знач ФормаВладелец = Неопределено, Знач ОтображатьОкно = Ложь) Экспорт #Если Клиент Тогда Если ЗначениеЗаполнено(Состояние) Тогда СообщитьЛкс(Состояние,,, Истина); КонецЕсли; #КонецЕсли Если Не ЗначениеЗаполнено(СтрокаСоединенияБазы) Тогда КаталогПустойИнфобазы = КаталогПустойИнфобазыЛкс(); СоздатьФайловуюБазу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Класса, ИмяСервераПроцессов); Если Не ЗначениеЗаполнено(СтрокаСоединения) Тогда СтрокаСоединения = СтрокаСоединенияИнформационнойБазы(); КонецЕсли; ПолнаяСтрокаСоединения = СтрокаСоединения + ДопСтрокаСоединения; Попытка РезультатСоединения = Соединение.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Класса, "ComConnector") Тогда СообщитьЛкс("Убедитесь что зарегистрирован COM класс COMConnector нужной разрядности и версии платформы"); КонецЕсли; #Если Клиент Тогда ирКлиент.ОткрытьФормуЛкс("Обработка.ирУправлениеCOMКлассами1С.Форма"); #КонецЕсли ВызватьИсключение "Ошибка создания COM объекта " + ИмяCOMКласса + ": " + ОписаниеОшибки(); КонецПопытки; Возврат Соединение; КонецФункции // Выполняет ожидание появления сеанса и только потом возвращает Функция ЗапуститьСеансПодПользователемЛкс(ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, ТипCOMОбъекта = "", РежимЗапуска = "Авто", КодРазрешения = "", СообщитьКоманднуюСтроку = Ложь, ОткрытьПортативныеИнструменты = Истина, ОчисткаКэшаКлиентСерверныхВызовов = Истина, ПрименитьТекущиеПараметрыЗапуска = Истина, ДополнительныеПараметры = "", РежимИнтерфейсаТакси = Ложь, Элевация = Ложь, РазделениеДанных = "", ОтключитьАутентификациюОС = Ложь, КодЯзыка = "", ПараметрЗапуска = "") Экспорт Если ЗначениеЗаполнено(ТипCOMОбъекта) Тогда Соединение = СоздатьСеансИнфобазы1С8Лкс(, ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, ТипCOMОбъекта, Истина,,,, КодРазрешения); Иначе #Если Клиент Тогда //Если ирКэш.НомерВерсииПлатформыЛкс() = 802015 Тогда // Предупреждение("В релиза 8.2.15 функция недоступна", 20); // Антибаг платформы 8.2.15 // Возврат; //КонецЕсли; Если РежимЗапуска = "Авто" Тогда // Антибаг платформы. При передачи этого режима в явном виде в некоторых случаях пароль в командной строке игнорируется ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователяИнфобазы); Если ПользовательИБ.РежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение Тогда КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий"; ИначеЕсли ПользовательИБ.РежимЗапуска = РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение Тогда КонечныйРежимЗапуска = "ОбычноеПриложение"; Иначе //Авто Если Метаданные.ОсновнойРежимЗапуска = РежимЗапускаКлиентскогоПриложения.УправляемоеПриложение Тогда КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий"; Иначе КонечныйРежимЗапуска = "ОбычноеПриложение"; КонецЕсли; КонецЕсли; Иначе КонечныйРежимЗапуска = РежимЗапуска; КонецЕсли; ПараметрыЗапуска = ПараметрыЗапускаПриложения1СЛкс(ИмяПользователяИнфобазы, ПарольПользователяИнфобазы, КодРазрешения, Ложь, КонечныйРежимЗапуска, ПрименитьТекущиеПараметрыЗапуска, ОчисткаКэшаКлиентСерверныхВызовов, ДополнительныеПараметры, СообщитьКоманднуюСтроку, , ОткрытьПортативныеИнструменты, РежимИнтерфейсаТакси, РазделениеДанных, ОтключитьАутентификациюОС, КодЯзыка, ПараметрЗапуска); ТекущаяДата = ирСервер.ТекущаяДатаЛкс(); Если Ложь Или Элевация Или КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий" Тогда СтрокаЗапуска = """" + ИмяИсполняемогоФайлаКлиентаПлатформыЛкс(, КонечныйРежимЗапуска = "УправляемоеПриложениеТонкий") + """ " + ПараметрыЗапуска; ЗапуститьСкрытоеПриложениеИДождатьсяЗавершенияЛкс(СтрокаЗапуска,,, Ложь, Элевация); Иначе ЗапуститьСистему(ПараметрыЗапуска); КонецЕсли; СостояниеЛкс("Ожидание запуска сеанса…"); Успех = Ложь; ДатаПоследнегоВопроса = ирСервер.ТекущаяДатаЛкс(); Пока Не Успех Цикл ОбработкаПрерыванияПользователя(); Если ирСервер.ТекущаяДатаЛкс() - ДатаПоследнегоВопроса >= 5 Тогда Ответ = Вопрос("Продолжить ожидание сеанса (5 сек)?", РежимДиалогаВопрос.ДаНет); Если Ответ = КодВозвратаДиалога.Нет Тогда Прервать; КонецЕсли; ДатаПоследнегоВопроса = ирСервер.ТекущаяДатаЛкс(); КонецЕсли; Сеансы = ПолучитьСеансыИнформационнойБазы(); // Иногда выполняется долго Успех = Ложь; Для Каждого Сеанс Из Сеансы Цикл Если Истина И Сеанс.НачалоСеанса >= ТекущаяДата И НРег(Сеанс.ИмяКомпьютера) = НРег(ИмяКомпьютера()) И Сеанс.Пользователь <> Неопределено И НРег(Сеанс.Пользователь.Имя) = НРег(ИмяПользователяИнфобазы) Тогда Успех = Истина; Прервать; КонецЕсли; КонецЦикла; КонецЦикла; СостояниеЛкс(""); #Иначе ВызватьИсключение "Запуск приложения допускается только на клиенте"; #КонецЕсли КонецЕсли; Возврат Соединение; КонецФункции Процедура ПерезапуститьСеансОтИмениАдминистратораОСЛкс(ФормаДляОткрытияВНовомСеансе = Неопределено) Экспорт ПараметрДляОткрытияФормы = ПараметрЗапускаДляОткрытияФормыЛкс(ФормаДляОткрытияВНовомСеансе); Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда РежимЗапуска = "УправляемоеПриложение"; Иначе РежимЗапуска = "ОбычноеПриложение"; КонецЕсли; ЗапуститьСеансПодПользователемЛкс(ИмяПользователя(),,, РежимЗапуска,,,,,,,, Истина,,,, ПараметрДляОткрытияФормы); КонецПроцедуры Функция ПараметрЗапускаДляОткрытияФормыЛкс(Знач ФормаДляОткрытияВНовомСеансе) Экспорт Результат = "ОткрытьФормуИР." + ПолноеИмяФормыЛкс(ФормаДляОткрытияВНовомСеансе); Возврат Результат; КонецФункции // Параметры: // 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 = МойЗаписьJSON(); #Если Сервер И Не Сервер Тогда ЗаписьJSON = Новый ЗаписьJSON; #КонецЕсли ПараметрыЗаписиJSON = Неопределено; Если ПрименятьОтступ Тогда ПараметрыЗаписиJSON = Вычислить("Новый ПараметрыЗаписиJSON(, Символы.Таб)"); КонецЕсли; ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON); // Метод ЗаписатьJSON появился в 8.3 Выполнить("ЗаписатьJSON(ЗаписьJSON, Объект)"); Результат = ЗаписьJSON.Закрыть(); Возврат Результат; КонецФункции Функция ФорматироватьТекстJSONЛкс(СтрокаJSON) Экспорт Если Не ЗначениеЗаполнено(СтрокаJSON) Тогда Возврат СтрокаJSON; КонецЕсли; Попытка СтруктураИзСтроки = ОбъектИзСтрокиJSONЛкс(Строка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Лкс(Объект); Параметры = Новый Массив(); Параметры.Добавить(СтрокаХМЛ); Параметры.Добавить(лАдресРезультата); #Если Сервер И Не Сервер Тогда ирОбщий.ЗаписатьОбъектДляОтладкиЛкс(); #КонецЕсли ДобавитьТекущемуПользователюРолиИРЛкс(); ФоновоеЗадание = ФоновыеЗадания.Выполнить("ирОбщий.ЗаписатьОбъектДляОтладкиЛкс", Параметры,, "Запись объекта для отладки (ИР)"); ФоновоеЗадание.ОжидатьЗавершения(10); Результат = ПолучитьИзВременногоХранилища(лАдресРезультата); Иначе Если ТипЗнч(Объект) = Тип("Строка") Тогда Объект = ОбъектИзСтрокиXMLЛкс(Объект); КонецЕсли; Если ТипЗнч(Объект) = Тип("Структура") Тогда Результат = ИмяНастройкиХраненияОбъектаОтложеннойОтладкиЛкс(); СохранитьЗначениеЛкс(Результат, Объект); Иначе ЗаписатьОбъектЛкс(Объект,,,, Ложь); Результат = Объект.Ссылка; КонецЕсли; Если АдресРезультата <> Неопределено Тогда ПоместитьВоВременноеХранилище(Результат, АдресРезультата); КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ИмяНастройкиХраненияОбъектаОтложеннойОтладкиЛкс() Экспорт Возврат "Объект для отладки"; КонецФункции // // Параметры: // КоллекцияСтрок - Структура, СписокЗначений, ТаблицаЗначений, КоллекцияСтрокДереваЗначений, ТабличнаяЧасть, НаборЗаписей Функция АвтоУникальноеИмяВКоллекцииЛкс(КоллекцияСтрок, БазовоеИмяИлиСтрока, ИмяКлючевойКолонки = "Имя", ИмяДолжноБытьИдентификатором = Истина, ЗаменаПустойСтроки = "_", Знач ДопустимаяДлинаИдентификатораЕслиНеЗаданаВКолонке = 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"); Если ДелатьОтступ Тогда ПараметрыЗаписи = Вычислить("Новый ПараметрыЗаписиJSON(, Символы.Таб)"); Результат.УстановитьСтроку(ПараметрыЗаписи); КонецЕсли; Возврат Результат; КонецФункции Функция ОптимальныйПотоковыйЧитательЛкс() Экспорт Если ирКэш.НомерВерсииПлатформыЛкс() >= 803006 Тогда ПотоковыйЧитатель = МойЧтениеJSON(); Иначе ПотоковыйЧитатель = Новый ЧтениеXML; КонецЕсли; Возврат ПотоковыйЧитатель; КонецФункции Функция МойЧтениеJSON() Экспорт Возврат Новый ("ЧтениеJSON"); КонецФункции Функция ЛиТекстJSONЛкс(Знач Текст) Экспорт ПервыйСимвол = Лев(СокрЛ(Текст), 1); Если ПервыйСимвол <> "{" И ПервыйСимвол <> "[" Тогда Результат = Ложь; Иначе Попытка ОбъектИзСтрокиJSONЛкс(Текст, Истина); Результат = Истина; Исключение Результат = Ложь; КонецПопытки; КонецЕсли; Возврат Результат; КонецФункции Функция ЛиТекстHTMLЛкс(Знач Текст) Экспорт Текст = СокрЛП(Текст); Результат = Истина И СтрНачинаетсяСЛкс(Текст, ""); Результат = Истина И СтрНачинаетсяСЛкс(Текст, "<") И Прав(Текст, 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 Или ПривилегированныйРежим() Или ПравоДоступа("АдминистрированиеДанных", Метаданные)) Тогда ИмяПользователя = ирКэш.ИмяПродукта(); Иначе //ИмяПользователя = Неопределено; // Такое значение вызывает ошибки у нестандартных хранилищ ИмяПользователя = ИмяПользователя(); КонецЕсли; Результат = ХранилищеОбщихНастроек.Загрузить(ирКэш.ИмяПродукта(), КлючНастроек,, ИмяПользователя); #Если Клиент Тогда Если Результат = Неопределено Тогда // Импорт из старого хранилища настроек Результат = ВосстановитьЗначение(КлючНастроек); Если Результат <> Неопределено Тогда СохранитьЗначениеЛкс(КлючНастроек, Результат); СохранитьЗначение(КлючНастроек, Неопределено); КонецЕсли; КонецЕсли; #КонецЕсли КонецЕсли; Возврат Результат; #КонецЕсли КонецФункции // Функция - Сохранить значение лкс // // Параметры: // КлючНастроек - - // Значение - - // ДляВсехПользователей - - // ХранитьНаКомпьютере - - ХранитьНаКлиенте - Булево - при "Истина" в толстом клиенте хранить настройку на текущем компьютере, иначе - в БД // ИмяПользователя - Строка - если пустая, то для текущего пользователя // // Возвращаемое значение: // - // Функция СохранитьЗначениеЛкс(КлючНастроек, Значение, ДляВсехПользователей = Ложь, Знач ХранитьНаКомпьютере = Ложь, Знач ИмяПользователя = "") Экспорт #Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда ирСервер.СохранитьЗначениеЛкс(КлючНастроек, Значение); #Иначе Если ХранитьНаКомпьютере Тогда мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли НастройкиКомпьютера = мПлатформа.НастройкиКомпьютера(); НастройкиКомпьютера.Вставить(КлючНастроек, Значение); мПлатформа.СохранитьНастройкиКомпьтера(); Иначе УстановитьПривилегированныйРежим(Истина); Если Истина И ДляВсехПользователей И (Ложь Или ирКэш.НомерВерсииПлатформыЛкс() < 803001 Или ПривилегированныйРежим() Или ПравоДоступа("АдминистрированиеДанных", Метаданные)) Тогда ИмяПользователя = ирКэш.ИмяПродукта(); Иначе //ИмяПользователя = Неопределено; // Такое значение вызывает ошибки у нестандартных хранилищ Если ПустаяСтрока(ИмяПользователя) Тогда ИмяПользователя = ИмяПользователя(); КонецЕсли; КонецЕсли; ХранилищеОбщихНастроек.Сохранить(ирКэш.ИмяПродукта(), КлючНастроек, Значение,, ИмяПользователя); КонецЕсли; #КонецЕсли КонецФункции Функция УдалитьХранимуюНастройкуЛкс(КлючНастроек, ДляВсехПользователей = Ложь) Экспорт #Если ТонкийКлиент Или ВебКлиент Или МобильныйКлиент Тогда ирСервер.УдалитьХранимуюНастройкуЛкс(КлючНастроек); #Иначе Если ДляВсехПользователей И ПравоДоступа("АдминистрированиеДанных", Метаданные) Тогда ИмяПользователя = ирКэш.ИмяПродукта(); Иначе //ИмяПользователя = Неопределено; // Такое значение вызывает ошибки у нестандартных хранилищ ИмяПользователя = ИмяПользователя(); КонецЕсли; ХранилищеОбщихНастроек.Удалить(ирКэш.ИмяПродукта(), КлючНастроек, ИмяПользователя); #КонецЕсли КонецФункции Процедура ДобавитьИндексВТаблицуЛкс(ТаблицаЗначений, Знач СтрокаИлиСтруктура) Экспорт #Если Сервер И Не Сервер Тогда ТаблицаЗначений = Новый ТаблицаЗначений; #КонецЕсли Если ТипЗнч(СтрокаИлиСтруктура) = Тип("Структура") Тогда // Из-за негарантированного порядка элементов можно получать разные имена одного по содержанию индекса. Поэтому могут создаваться дубли индексов СтрокаИндекса = ""; Разделитель = ", "; Для Каждого КлючИЗначение Из СтрокаИлиСтруктура Цикл СтрокаИндекса = СтрокаИндекса + Разделитель + КлючИЗначение.Ключ; КонецЦикла; СтрокаИндекса = Сред(СтрокаИндекса, СтрДлина(Разделитель) + 1); Иначе СтрокаИндекса = СтрокаИлиСтруктура; КонецЕсли; НСтрокаИндекса = НРег(СтрокаИндекса); ИндексНайден = Ложь; Для Каждого Индекс Из ТаблицаЗначений.Индексы Цикл Если НРег(Индекс) = НСтрокаИндекса Тогда ИндексНайден = Истина; Прервать; КонецЕсли; КонецЦикла; Если Не ИндексНайден Тогда НовыйИндекс = ТаблицаЗначений.Индексы.Добавить(СтрокаИндекса); Если "" + НовыйИндекс <> СтрокаИндекса Тогда ВызватьИсключение "Поля в составе индекса должны быть разделены запятой и пробелом"; КонецЕсли; КонецЕсли; КонецПроцедуры // Можно ради скорости отказываться от использования этой функции Функция ЛиПустаяПодгруппаRegExpЛкс(Подгруппа) Экспорт Результат = Ложь Или Подгруппа = Неопределено // наш случай Или Подгруппа = ""; // RegExV8 Возврат Результат; КонецФункции Процедура ОбновитьКопиюСвойстваВНижнемРегистреЛкс(Объект, ИмяСвойства = "Имя") Экспорт Объект["Н" + ИмяСвойства] = НРег(Объект[ИмяСвойства]); КонецПроцедуры Процедура ОбновитьКопиюКолонкиВНижнемРегистреЛкс(Знач Таблица, Знач ИмяКолонки = "Имя", НИмяКолонки = Неопределено) Экспорт #Если Сервер И Не Сервер Тогда Таблица = Новый ТаблицаЗначений; #КонецЕсли Если НИмяКолонки = Неопределено Тогда НИмяКолонки = "Н" + ИмяКолонки; Если ТипЗнч(Таблица) = Тип("ТаблицаЗначений") Тогда Если Таблица.Колонки.Найти(НИмяКолонки) = Неопределено Тогда Таблица.Колонки.Добавить(НИмяКолонки); Таблица.Индексы.Добавить(НИмяКолонки); КонецЕсли; КонецЕсли; КонецЕсли; // В одно строку для ускорения Для Каждого Строка Из Таблица Цикл Строка[НИмяКолонки] = НРег(Строка[ИмяКолонки]) КонецЦикла; КонецПроцедуры Функция ТекущаяДатаЛкс(НаСервере = Ложь, КэшироватьРазницуКлиентСервера = Ложь) Экспорт Если НаСервере Тогда Если КэшироватьРазницуКлиентСервера Тогда Результат = ТекущаяДата() - ирКэш.РазницаВремениКлиентСерверЛкс(); Иначе Результат = ирСервер.ТекущаяДатаЛкс(); КонецЕсли; Иначе Результат = ТекущаяДата(); КонецЕсли; Возврат Результат; КонецФункции Функция ДатаОбновленияКэшаМодулейЛкс(Знач ПапкаКэша = "") Экспорт мПлатформа = ирКэш.Получить(); Если Не ЗначениеЗаполнено(ПапкаКэша) Тогда ПапкаКэша = мПлатформа.ПапкаКэшаМодулей.ПолноеИмя; КонецЕсли; КонтрольныйФайл = Новый Файл(ПапкаКэша + "\" + мПлатформа.ИмяКонтрольногоФайлаКэшаМодулей()); ПапкаКэша = Новый Файл(ПапкаКэша); Попытка ДатаОбновленияКэша = КонтрольныйФайл.ПолучитьВремяИзменения(); Исключение Если ПапкаКэша.Существует() Тогда ДатаОбновленияКэша = Дата(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) // Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. Если ТипЗнч(МассивИлиСписок) = Тип("СписокЗначений") Тогда МассивИлиСписок = МассивИлиСписок.ВыгрузитьЗначения(); КонецЕсли; Запись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; КонецПопытки; ОбщийРазмер = ОбщийРазмер + РазмерФайла; КонецЦикла; Возврат ОбщийРазмер; КонецФункции // Выполняет копирование файлов рекурсивно Процедура СкопироватьФайлыЛкс(КаталогИсточник, КаталогПриемник) Экспорт Файлы = НайтиФайлы(КаталогИсточник, "*.*"); Разделитель = РазделительПутиКФайлуЛкс(); Для Каждого Файл Из Файлы Цикл ФайлПриемник = Новый Файл(КаталогПриемник + Разделитель + Файл.Имя); Если Файл.ЭтоКаталог() Тогда СоздатьКаталог(ФайлПриемник.ПолноеИмя); СкопироватьФайлыЛкс(Файл.ПолноеИмя, ФайлПриемник.ПолноеИмя); Продолжить; КонецЕсли; КопироватьФайл(Файл.ПолноеИмя, ФайлПриемник.ПолноеИмя); КонецЦикла; КонецПроцедуры Функция РазделительПутиКФайлуЛкс() Экспорт Если ирКэш.ЛиПлатформа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 Процедура СообщитьЛкс(Знач ТекстСообщения, Знач Статус = Неопределено, Знач ТолькоВоВременноеОкно = Ложь, Знач ПоказатьОповещениеВУП = Ложь, Знач ВывестиОперативноВУП = Истина) Экспорт Если Не ЗначениеЗаполнено(ТекстСообщения) Тогда Возврат; КонецЕсли; ВывестиСообщениеВСпецОкно = Ложь; #Если Не ВебКлиент И Не ТонкийКлиент Тогда МодальныеГруппы = МодальныеГруппыЛкс(); Если ирКэш.ЛиСеансТолстогоКлиентаУПЛкс() Тогда Если ПоказатьОповещениеВУП Тогда #Если Клиент Тогда ПоказатьОповещениеПользователя(,, ТекстСообщения); #КонецЕсли КонецЕсли; Если ирКэш.ЛиПлатформа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; Результат = ОписаниеРасширения + "|" + Результат; КонецЕсли; Если РазрешитьВсеФайлы Тогда Результат = Результат + "|Все файлы (*.*)|*.*"; КонецЕсли; Возврат Результат; КонецФункции // Копирует все элементы переданного массива, структуры, соответствия, списка значений или коллекции объектов метаданных // в однотипную коллекцию приемник (для метаданных в массив). Если коллекция приемник не указана, она будет создана. // Фиксированные коллекции превращаются в нефиксированные. // // Параметры: // КоллекцияИсточник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных - коллекция источник; // КоллекцияПриемник - Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных, *Неопределено - коллекция приемник. // // Возвращаемое значение: // Массив, Структура, Соответствие, СписокЗначений, КоллекцияОбъектовМетаданных - коллекция приемник. // Функция СкопироватьКоллекциюЛкс(КоллекцияИсточник, КоллекцияПриемник = Неопределено, Знач ВыводитьСообщения = Истина) Экспорт Если КоллекцияИсточник <> Неопределено И КоллекцияИсточник = КоллекцияПриемник Тогда ВызватьИсключение "Нельзя загружать коллекцию в саму себя"; КонецЕсли; ТипКоллекции = ТипЗнч(КоллекцияИсточник); Если Ложь Или ТипКоллекции = Тип("Массив") Или ТипКоллекции = Тип("ФиксированныйМассив") #Если Не ТонкийКлиент И Не ВебКлиент Тогда Или ТипКоллекции = Тип("КоллекцияОбъектовМетаданных") #КонецЕсли Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Массив; КонецЕсли; Для Каждого Элемент Из КоллекцияИсточник Цикл КоллекцияПриемник.Добавить(Элемент); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли Ложь Или ТипКоллекции = Тип("Структура") Или ТипКоллекции = Тип("ФиксированнаяСтруктура") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Структура; КонецЕсли; Для Каждого Элемент Из КоллекцияИсточник Цикл КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли Ложь Или ТипКоллекции = Тип("Соответствие") Или ТипКоллекции = Тип("ФиксированноеСоответствие") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый Соответствие; КонецЕсли; Для Каждого Элемент Из КоллекцияИсточник Цикл КоллекцияПриемник.Вставить(Элемент.Ключ, Элемент.Значение); КонецЦикла; Возврат КоллекцияПриемник; ИначеЕсли ТипКоллекции = Тип("СписокЗначений") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = Новый СписокЗначений; КонецЕсли; Для Каждого Элемент Из КоллекцияИсточник Цикл ЗаполнитьЗначенияСвойств(КоллекцияПриемник.Добавить(), Элемент); КонецЦикла; Возврат КоллекцияПриемник; #Если Не ТонкийКлиент И Не ВебКлиент И Не МобильныйКлиент Тогда ИначеЕсли ТипКоллекции = Тип("ТаблицаЗначений") Тогда Если КоллекцияПриемник = Неопределено Тогда КоллекцияПриемник = КоллекцияИсточник.СкопироватьКолонки(); КонецЕсли; ЗагрузитьВТаблицуЗначенийЛкс(КоллекцияИсточник, КоллекцияПриемник); Возврат КоллекцияПриемник; #КонецЕсли Иначе Если ВыводитьСообщения Тогда СообщитьЛкс(СтрШаблонИменЛкс("Неверный тип универсальной коллекции для копирования %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 ВызватьИсключение; КонецПопытки; Если Ложь Или ТипЗнч(КоллекцияВывода) = Тип("ТабличныйДокумент") #Если Клиент Тогда Или ТипЗнч(КоллекцияВывода) = Тип("ПолеТабличногоДокумента") #КонецЕсли Тогда выхЭлементыРезультата = Новый Массив; ЭлементыРасшифровки = Неопределено; Если ДанныеРасшифровки <> Неопределено Тогда ЭлементыРасшифровки = ДанныеРасшифровки.Элементы; КонецЕсли; ВывестиРезультатКомпоновкиСАвтофиксациейСтрокЛкс(КоллекцияВывода, ПроцессорКомпоновкиДанных, ЭлементыРасшифровки, , , Автофиксация, выхЭлементыРезультата); Иначе ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений; КоллекцияВывода.Колонки.Очистить(); ПроцессорВывода.УстановитьОбъект(КоллекцияВывода); ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных, Истина); КонецЕсли; Если АдресДанныхРасшифровки <> Неопределено Тогда АдресДанныхРасшифровки = ДанныеРасшифровки; КонецЕсли; выхДлительность = ТекущееВремяВМиллисекундахЛкс() - НачалоВывода; Если ЛиОтладка Тогда СообщитьСУчетомМодальностиЛкс("Формирование результата - " + Строка(выхДлительность) + " мс", МодальныйРежим); КонецЕсли; Возврат Истина; КонецФункции // Получает макет компоновки данных по схеме с использованием временных таблиц. // // Параметры: // Схема - СхемаКомпоновкиДанных; // Настройки - НастройкиКомпоновкиДанных; // *ВнешниеНаборыДанных - Структура, *Неопределено - туда добавляются временные таблицы; // *ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных, *Неопределено; // *ЛиОтладка - Булево, *Ложь - показывать тексты запросов и время выполнения этапов. // // Возвращаемое значение: // МакетКомпоновкиДанных. // Функция _МакетКомпоновкиДанныхСВременнымиТаблицамиЛкс(Схема, Настройки, ВнешниеНаборыДанных = Неопределено, ДанныеРасшифровки = Неопределено, ЛиОтладка = Ложь, СвойМакетОформления = Неопределено, ПроверятьДоступностьПолей = Ложь) Экспорт RegExp = НовоеРегВыражениеЛкс(); RegExp.Global = Истина; RegExp.MultiLine = Ложь; RegExp.IgnoreCase = Истина; // Допустим 1 уровень скобок. шСкобки = "\([^\)\(]*?\)"; RegExp.Pattern = "\(ВЫБРАТЬ(?:" + шСкобки + "|[^$\(\)])*?""ВременнаяТаблица"" = ""(.*?)""\)"; Если ВнешниеНаборыДанных = Неопределено Тогда ВнешниеНаборыДанных = Новый Структура; КонецЕсли; Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных; КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных; // Выполним создание всех временных таблиц. Временной таблицей считаем набор данных запрос, // имя которого начинается с "@". Наборы данных временных таблиц удаляются из предварительной схемы. ПредварительнаяСхема = КопияОбъектаЛкс(Схема); НаборыДанныхСхемы = ПредварительнаяСхема.НаборыДанных; ЕстьВременныеТаблицы = Ложь; НачальноеКоличество = НаборыДанныхСхемы.Количество(); Для СчетчикНаборыДанныхСхемы = 1 По НачальноеКоличество Цикл НаборДанных = НаборыДанныхСхемы[НачальноеКоличество - СчетчикНаборыДанныхСхемы]; Если Истина И Лев(НаборДанных.Имя, 1) = "@" И ТипЗнч(НаборДанных) = Тип("НаборДанныхЗапросСхемыКомпоновкиДанных") Тогда ВременнаяСхема = КопияОбъектаЛкс(Схема); // Кривое копирование набора данных в новую схемы, где он будет один. ВременнаяСхема.СвязиНаборовДанных.Очистить(); НаборыДанныхВременнойСхемы = ВременнаяСхема.НаборыДанных; НаборыДанныхВременнойСхемыВГраница = НаборыДанныхВременнойСхемы.Количество() - 1; Для СчетчикВременнойСхемы = 0 По НаборыДанныхВременнойСхемыВГраница Цикл НаборДанныхВременнойСхемы = НаборыДанныхВременнойСхемы[НаборыДанныхВременнойСхемыВГраница - СчетчикВременнойСхемы]; Если НаборДанныхВременнойСхемы.Имя <> НаборДанных.Имя Тогда НаборыДанныхВременнойСхемы.Удалить(НаборДанныхВременнойСхемы); КонецЕсли; КонецЦикла; Для Каждого ПолеНабора Из НаборыДанныхВременнойСхемы[0].Поля Цикл ПолеНабора.ОграничениеИспользования.Поле = Ложь; ПолеНабора.ВыражениеПредставления = ПолеНабора.ПутьКДанным; КонецЦикла; КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ВременнаяСхема)); КомпоновщикНастроек.ЗагрузитьНастройки(Настройки); КомпоновщикНастроек.Настройки.Структура.Очистить(); КомпоновщикНастроек.Настройки.Выбор.Элементы.Очистить(); КомпоновщикНастроекВосстановитьЛкс(КомпоновщикНастроек); ВременныеНастройки = КомпоновщикНастроек.Настройки; // Установим использование параметров Для Каждого ЭлементПараметра Из ВременныеНастройки.ПараметрыДанных.Элементы Цикл ЭлементПараметра.Использование = Истина; КонецЦикла; // Установим структуру и выбранные поля ЭлементСтруктуры = ВременныеНастройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных")); ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных")); Для Каждого ДоступноеПоле Из ВременныеНастройки.ДоступныеПоляВыбора.Элементы Цикл // Чтобы пропустить системные папки Если Не ДоступноеПоле.Папка Тогда НовоеВыбранноеПоле = ВременныеНастройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных")); НовоеВыбранноеПоле.Поле = ДоступноеПоле.Поле; НовоеВыбранноеПоле.Использование = Истина; КонецЕсли; КонецЦикла; МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ВременнаяСхема, ВременныеНастройки,,,, ПроверятьДоступностьПолей); Запрос.Текст = МакетКомпоновкиДанных.НаборыДанных[0].Запрос; Для Каждого Параметр Из МакетКомпоновкиДанных.ЗначенияПараметров Цикл Запрос.УстановитьПараметр(Параметр.Имя, Параметр.Значение); КонецЦикла; Запрос.Текст = RegExp.Заменить(Запрос.Текст, "$1"); ВыполнитьЗамеритьЗапросЛкс(Запрос, ЛиОтладка, "Предварительный запрос - " + НаборДанных.Имя); //// Недоступные поля набора данных цепляются в настройках при совпадении имен с выбранными полями //// http://partners.v8.1c.ru/forum/thread.jsp?id=514094 //Для Каждого Поле Из НаборДанных.Поля Цикл // Поле.ПутьКДанным = "_поле_" + Поле.ПутьКДанным; //КонецЦикла; НаборыДанныхСхемы.Удалить(НаборДанных); ЕстьВременныеТаблицы = Истина; КонецЕсли; КонецЦикла; Если Не ЕстьВременныеТаблицы Тогда Если ЛиОтладка Тогда ВремяНачалаКомпоновкиМакета = ТекущееВремяВМиллисекундахЛкс(); КонецЕсли; МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ПредварительнаяСхема, Настройки, ДанныеРасшифровки, СвойМакетОформления,, ПроверятьДоступностьПолей); Если ЛиОтладка Тогда СообщитьЛкс(СтрШаблонИменЛкс("Компоновка макета - %1мс",, ТекущееВремяВМиллисекундахЛкс() - ВремяНачалаКомпоновкиМакета)); КонецЕсли; Иначе // Выполним получение результата предварительного запроса КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(ПредварительнаяСхема)); КомпоновщикНастроек.ЗагрузитьНастройки(Настройки); КомпоновщикНастроекВосстановитьЛкс(КомпоновщикНастроек); ПредварительныеНастройки = КомпоновщикНастроек.Настройки; Если ЛиОтладка Тогда ВремяНачалаКомпоновкиМакета = ТекущееВремяВМиллисекундахЛкс(); КонецЕсли; МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(ПредварительнаяСхема, ПредварительныеНастройки, ДанныеРасшифровки, СвойМакетОформления,, ПроверятьДоступностьПолей); Если ЛиОтладка Тогда СообщитьЛкс(СтрШаблонИменЛкс("Компоновка макета - %1мс",, ТекущееВремяВМиллисекундахЛкс() - ВремяНачалаКомпоновкиМакета)); КонецЕсли; Для Каждого Параметр Из МакетКомпоновкиДанных.ЗначенияПараметров Цикл Запрос.УстановитьПараметр(Параметр.Имя, Параметр.Значение); КонецЦикла; СтруктураНаборовДанныхЗапросовМакета = ВсеНаборыДанныхЗапросовКомпоновкиЛкс(МакетКомпоновкиДанных.НаборыДанных); Для Каждого ЭлементНаборДанныхМакета Из СтруктураНаборовДанныхЗапросовМакета Цикл НаборДанных = ЭлементНаборДанныхМакета.Значение.НаборДанных; Запрос.Текст = НаборДанных.Запрос; Запрос.Текст = RegExp.Заменить(Запрос.Текст, "$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С И ПутиКДаннымПолей = Неопределено Тогда ДоступныеПоля = ПорядокКомпоновки.ДоступныеПоляПорядка; КонецЕсли; ПорядокКомпоновки = ПорядокКомпоновки.Элементы; КонецЕсли; Строка = ""; Для Каждого ЭлементПорядка Из ПорядокКомпоновки Цикл Если Ложь Или Не ЭлементПорядка.Использование Или ТипЗнч(ЭлементПорядка) = Тип("АвтоЭлементПорядкаКомпоновкиДанных") Или ИсключаемоеПоле = "" + ЭлементПорядка.Поле Тогда Продолжить; КонецЕсли; ИмяПоля = "" + ЭлементПорядка.Поле; Если ПутиКДаннымПолей <> Неопределено Тогда ПутьКДаннымПоля = НайтиЭлементКоллекцииЛкс(ПутиКДаннымПолей, "ПутьКДанным", ИмяПоля); Если ПутьКДаннымПоля = Неопределено Тогда // Например реквизит ТЧ Продолжить; КонецЕсли; ИмяПоля = ПутьКДаннымПоля.Имя; КонецЕсли; Если ДоступныеПоля <> Неопределено Тогда ДоступноеПоле = ДоступныеПоля.НайтиПоле(ЭлементПорядка.Поле); КонецЕсли; Если СимволЗаменыТочки <> Неопределено Тогда ИмяПоля = СтрЗаменить(ИмяПоля, ".", СимволЗаменыТочки); КонецЕсли; Если ДоступныеПоля <> Неопределено И ДоступноеПоле <> Неопределено Тогда ИмяПоля = ОбренутьВыражениеЗапросаДляГруппировкиЛкс(ИмяПоля, ДоступноеПоле.ТипЗначения, УчитыватьПравыеПробелыСтрок); КонецЕсли; Строка = Строка + ", " + ИмяПоля + " "; Если ЭлементПорядка.ТипУпорядочивания = НаправлениеСортировкиКомпоновкиДанных.Возр Тогда Строка = Строка + СтрокаВозр; Иначе Строка = Строка + СтрокаУбыв; КонецЕсли; КонецЦикла; Возврат Сред(Строка, 3); КонецФункции // ТипНастроек - Число Функция НастройкиДинамическогоСпискаЛкс(Знач ДинамическийСписок, ТипНастроек = "Результирующие") Экспорт Если ТипЗнч(ДинамическийСписок) = Тип("ДинамическийСписок") Тогда Если ТипНастроек = "Результирующие" Тогда НастройкиСписка = ДинамическийСписок.КомпоновщикНастроек.ПолучитьНастройки(); ИначеЕсли ТипНастроек = "Фиксированные" Тогда НастройкиСписка = ДинамическийСписок.КомпоновщикНастроек.ФиксированныеНастройки; ИначеЕсли Истина И ТипНастроек = "Пользовательские" И ирКэш.НомерРежимаСовместимостиЛкс() > 802013 // https://www.hostedredmine.com/issues/952896 Тогда НастройкиСписка = СтруктураПользовательскихНастроекКомпоновкиЛкс(ДинамическийСписок.КомпоновщикНастроек.ПользовательскиеНастройки); Иначе НастройкиСписка = ДинамическийСписок; КонецЕсли; Иначе НастройкиСписка = ДинамическийСписок; КонецЕсли; Возврат НастройкиСписка; КонецФункции Функция СтруктураПользовательскихНастроекКомпоновкиЛкс(Знач ПользовательскиеНастройки) Экспорт #Если Сервер И Не Сервер Тогда ПользовательскиеНастройки = Новый ПользовательскиеНастройкиКомпоновкиДанных; #КонецЕсли НастройкиСписка = Новый Структура("Отбор, Порядок, УсловноеОформление"); Для Каждого ЭлементПользовательскихНастроек Из ПользовательскиеНастройки.Элементы Цикл Если ТипЗнч(ЭлементПользовательскихНастроек) = Тип("ОтборКомпоновкиДанных") Тогда НастройкиСписка.Отбор = ЭлементПользовательскихНастроек; ИначеЕсли ТипЗнч(ЭлементПользовательскихНастроек) = Тип("ПорядокКомпоновкиДанных") Тогда НастройкиСписка.Порядок = ЭлементПользовательскихНастроек; ИначеЕсли ТипЗнч(ЭлементПользовательскихНастроек) = Тип("УсловноеОформлениеКомпоновкиДанных") Тогда НастройкиСписка.УсловноеОформление = ЭлементПользовательскихНастроек; КонецЕсли; КонецЦикла; Возврат НастройкиСписка; КонецФункции Функция ПредельноеЧислоВидимыхКолонокДинамСпискаЛкс() Экспорт Возврат 40; КонецФункции Функция ИмяОтсутствияПодсистемыЛкс() Экспорт Возврат "<Не входящие в подсистемы>"; КонецФункции Функция ПодсистемаПоПолномуИмениЛкс(Знач ПолноеИмяПодсистемы, Знач ПодсистемаПеревод = "") Экспорт Если Не ЗначениеЗаполнено(ПодсистемаПеревод) Тогда ПодсистемаПеревод = ПеревестиСтроку("Подсистема"); КонецЕсли; МДПодсистема = ирКэш.ОбъектМДПоПолномуИмениЛкс(ПодсистемаПеревод + "." + СтрЗаменить(ПолноеИмяПодсистемы, ".", "." + ПодсистемаПеревод + ".")); Возврат МДПодсистема; КонецФункции Функция ПолноеИмяПодсистемыЛкс(Знач Подсистема, Знач ПодсистемаПеревод = "") Экспорт Если Не ЗначениеЗаполнено(ПодсистемаПеревод) Тогда ПодсистемаПеревод = ПеревестиСтроку("Подсистема"); КонецЕсли; ПолноеИмяПодсистемы = СтрЗаменить(Подсистема.ПолноеИмя(), ПодсистемаПеревод + ".", ""); Возврат ПолноеИмяПодсистемы; КонецФункции Функция ВсеПодсистемыЛкс(Подсистема = Неопределено, Результат = Неопределено) Экспорт Если Подсистема = Неопределено Тогда Подсистема = Метаданные; КонецЕсли; Если Результат = Неопределено Тогда Результат = Новый СписокЗначений; КонецЕсли; Для Каждого ДочерняяПодсистема Из Подсистема.Подсистемы Цикл Результат.Добавить(ПолноеИмяПодсистемыЛкс(ДочерняяПодсистема)); ВсеПодсистемыЛкс(ДочерняяПодсистема, Результат); КонецЦикла; Возврат Результат; КонецФункции // . // // Параметры: // СписокПодсистем - СписокЗначений - значение содержит полное имя подсистемы // СтрокаДереваПодсистем - - // ОбъектыВыбранныхПодсистем - Соответствие - дублирует возвращаемое значение // // Возвращаемое значение: // Соответствие - : // * Ключ - ОбъектМетаданных - входящий в заданные подсистемы // Функция ОбъектыПодсистемЛкс(Знач СписокПодсистем, СтрокаДереваПодсистем = Неопределено, ОбъектыВыбранныхПодсистем = Неопределено) Экспорт #Если Сервер И Не Сервер Тогда СписокПодсистем = Новый СписокЗначений; #КонецЕсли Если ОбъектыВыбранныхПодсистем = Неопределено Тогда ОбъектыВыбранныхПодсистем = Новый Соответствие; КонецЕсли; ПодсистемаПеревод = ПеревестиСтроку("Подсистема"); ИмяОтсутствияПодсистемы = ИмяОтсутствияПодсистемыЛкс(); Для Каждого ЭлементСписка Из СписокПодсистем Цикл Если ЭлементСписка.Значение = ИмяОтсутствияПодсистемы Тогда ВсеПодсистемы = ВсеПодсистемыЛкс(); ОбъектыВсехПодсистем = ОбъектыПодсистемЛкс(ВсеПодсистемы); Для Каждого СтрокаТипаМетаданных Из ирКэш.ТипыМетаОбъектов(, Ложь, Ложь) Цикл Если СтрокаТипаМетаданных.Единственное = "Перерасчет" Тогда Продолжить; КонецЕсли; Для Каждого ОбъектМД Из Метаданные[СтрокаТипаМетаданных.Множественное] Цикл Если ОбъектыВсехПодсистем[ОбъектМД] <> Неопределено Тогда Продолжить; КонецЕсли; ОбъектыВыбранныхПодсистем.Вставить(ОбъектМД, 1); КонецЦикла; КонецЦикла; Иначе ПодсистемаМД = ПодсистемаПоПолномуИмениЛкс(ЭлементСписка.Значение); Если ПодсистемаМД <> Неопределено Тогда Для Каждого ЭлементСостава Из ПодсистемаМД.Состав Цикл ОбъектыВыбранныхПодсистем.Вставить(ЭлементСостава, 1); КонецЦикла; КонецЕсли; КонецЕсли; КонецЦикла; Возврат ОбъектыВыбранныхПодсистем; КонецФункции Функция НоваяТаблицаНастроекСтандартногоХранилищаЛкс() Экспорт ТабОписаний = Новый ТаблицаЗначений; ТабОписаний.Колонки.Добавить("ИмяХранилища"); ТабОписаний.Колонки.Добавить("ИмяОбъекта"); ТабОписаний.Колонки.Добавить("КлючНастроек"); ТабОписаний.Колонки.Добавить("Настройка"); ТабОписаний.Колонки.Добавить("ИмяПользователя"); ТабОписаний.Колонки.Добавить("Описание"); Возврат ТабОписаний; КонецФункции Функция НоваяТаблицаЗначенийЛкс(ИменаКолонок) Экспорт Результат = Новый ТаблицаЗначений; Для Каждого ИмяКолонки Из СтрРазделитьЛкс(ИменаКолонок, ",", Истина) Цикл Результат.Колонки.Добавить(ИмяКолонки); КонецЦикла; Возврат Результат; КонецФункции Функция МетаданныеНаборовЗаписейПоРегистраторуЛкс(мдОбъекта, ВключаяПоследовательности = Ложь, ВключаяПерерасчеты = Ложь, Сортировать = Ложь) Экспорт ОбъектыМД = Новый Массив(); ЗащитаОтДублей = Новый Соответствие; Для Каждого МетаРегистр из мдОбъекта.Движения Цикл Если ЗащитаОтДублей[МетаРегистр.Имя] <> Неопределено Тогда // 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 Тогда ОбработатьИндикаторЛкс(Индикатор, СчетчикСтроки); КонецЕсли; СтрокаТекста = ТекстовыйДокумент.ПолучитьСтроку(СчетчикСтроки); Массив = СтрРазделитьЛкс(СтрокаТекста, Разделитель, ОбрезатьНепечатныеСимволы, Истина, РазворачиватьКавычки); Если КоличествоКолонок < Массив.Количество() Тогда Если ТипЗнч(ТаблицаПриемник) = Тип("ТаблицаЗначений") Тогда Для ИндексКолонки = КоличествоКолонок По Массив.Количество() - 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 // ТабличноеПоле #Если Клиент Тогда ирКлиент.ТабличноеПолеВключитьСтаруюЦветовуюСхемуЛкс(ТабличноеПоле); #КонецЕсли Если ОписанияКолонок = Неопределено Тогда ОписанияКолонок = ТабличноеПоле.Значение.Колонки; // КоллекцияКолонокТаблицыЗначений КонецЕсли; КонецЕсли; КолонкиТабличногоПоля = ТабличноеПоле.Колонки; #Если Сервер И Не Сервер Тогда КолонкиТабличногоПоля = Новый ТаблицаЗначений; КолонкиТабличногоПоля = КолонкиТабличногоПоля.Колонки; #КонецЕсли МассивКолонокДанных = МассивИзКоллекцииЛкс(КолонкиТабличногоПоля); Для Каждого КолонкаДанных Из МассивКолонокДанных Цикл Для Каждого КолонкаДанныхОсновная Из МассивКолонокДанных Цикл Если "Несогласовано_" + КолонкаДанныхОсновная.Имя = КолонкаДанных.Имя Тогда КолонкиТабличногоПоля.Сдвинуть(КолонкаДанных, КолонкиТабличногоПоля.Индекс(КолонкаДанныхОсновная) - КолонкиТабличногоПоля.Индекс(КолонкаДанных) + 1); КонецЕсли; КонецЦикла; КонецЦикла; МинимальнаяШиринаКолонки = МинимальнаяШиринаКолонкиЛкс(); Для Каждого КолонкаТаблицы Из ОписанияКолонок Цикл Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда КолонкаТП = ТабличноеПоле.ПодчиненныеЭлементы.Найти(ТабличноеПоле.Имя + КолонкаТаблицы.Имя); Иначе //! ТабличноеПоле = 0 // ТабличноеПоле КолонкаТП = ТабличноеПоле.Колонки.Найти(КолонкаТаблицы.Имя); КонецЕсли; Если КолонкаТП = Неопределено Тогда Продолжить; КонецЕсли; Если КолонкаТП.Видимость Тогда УстановитьТекущуюКолонкуТаблицыФормыЛкс(ТабличноеПоле, КолонкаТП, Истина); КонецЕсли; Если ТолькоПросмотр Тогда КолонкаТП.ТолькоПросмотр = Истина; КонецЕсли; Если ЗначениеЗаполнено(Формат) Тогда КолонкаТП.Формат = Формат; КонецЕсли; Если ДоступныеПоляВыбора <> Неопределено Тогда ДоступноеПоле = ДоступныеПоляВыбора.НайтиПоле(Новый ПолеКомпоновкиДанных(КолонкаТаблицы.Имя)); Если ДоступноеПоле <> Неопределено Тогда ТекстШапки = ДоступноеПоле.Заголовок; Если ТипЗнч(ТабличноеПоле) = Тип("ТаблицаФормы") Тогда //! КолонкаТП = 0 // ПолеФормы КолонкаТП.Заголовок = ТекстШапки; Иначе //! КолонкаТП = 0 // КолонкаТабличногоПоля КолонкаТП.ТекстШапки = ТекстШапки; КонецЕсли; КонецЕсли; КонецЕсли; Если Ложь #Если Клиент Тогда Или ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле") #КонецЕсли Тогда ТипЗначенияКолонки = КолонкаТаблицы.ТипЗначения; #Если Сервер И Не Сервер Тогда ТипЗначенияКолонки = Новый ОписаниеТипов; #КонецЕсли ТипЗначенияКолонки = Новый ОписаниеТипов(ТипЗначенияКолонки,, "Null"); ТипыРеквизита = ТипЗначенияКолонки.Типы(); Если ТипыРеквизита.Количество() = 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; КонецФункции Функция НачалоИмениКнопкиПодменюПоследнихВыбранныхЛкс(ТипКлюча = "Выбранные") Экспорт Возврат "Последние" + ТипКлюча; КонецФункции Функция ИспользованиеДинамическогоСпискаВместоОсновнойФормыЛкс(ПолноеИмяМД) Экспорт Возврат ВосстановитьЗначениеЛкс("ирДинамическийСписок.ВместоОсновной." + ПолноеИмяМД) <> Ложь; КонецФункции Функция КлючУникальностиДинамическогоСпискаЛкс(Знач ИмяТаблицы, Знач КлючУникальности = "") Экспорт КлючУникальности = ИмяТаблицы + ";" + КлючУникальности; Возврат КлючУникальности; КонецФункции Функция КлючИсторииВыбораПоляВводаЛкс(Знач ПолеВводаИлиЭлементОтбора, Знач КлючИстории, Знач ДополнительныйКлючИстории = "") Экспорт Если ТипЗнч(КлючИстории) <> Тип("Строка") Тогда КлючИстории = КлючХраненияНастроекФормыЛкс(КлючИстории); КлючИстории = КлючИстории + ДополнительныйКлючИстории; КлючИстории = КлючИстории + "." + ПолеВводаИлиЭлементОтбора.Имя; ИначеЕсли Ложь Или ТипЗнч(ПолеВводаИлиЭлементОтбора) = Тип("ЭлементОтбора") Или ТипЗнч(ПолеВводаИлиЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда КлючИстории = КлючИстории + ДополнительныйКлючИстории; КлючИстории = КлючИсторииВыбораЗначенияОтбораЛкс(КлючИстории, ПолеВводаИлиЭлементОтбора); КонецЕсли; КлючИстории = КлючИстории + ".ПоследниеЗначения"; Возврат КлючИстории; КонецФункции // Процедура - Поле ввода с историей выбора начало выбора из списка лкс. // Вызывается с сервера в динамическом списке. // // Параметры: // ЭлементФормы - - // КлючИстории - Форма, Строка - // ДополнительныйКлючИстории - - // ОтборВыбора - - // Процедура ПолеВводаСИсториейВыбора_ОбновитьСписокЛкс(Знач ЭлементФормы, Знач КлючИстории, ДополнительныйКлючИстории = "", ОтборВыбора = Неопределено) Экспорт Если Ложь #Если Клиент Тогда Или ТипЗнч(ЭлементФормы) = Тип("КолонкаТабличногоПоля") #КонецЕсли Тогда ПолеВвода = ЭлементФормы.ЭлементУправления; Иначе ПолеВвода = ЭлементФормы; КонецЕсли; КлючИстории = КлючИсторииВыбораПоляВводаЛкс(ЭлементФормы, КлючИстории, ДополнительныйКлючИстории); ПоследниеЗначения = ВосстановитьЗначениеЛкс(КлючИстории); ПолеВвода.СписокВыбора.Очистить(); ПолеВвода_ОбновитьСписокЛкс(ПолеВвода); Если ТипЗнч(ПоследниеЗначения) = Тип("Массив") Тогда Если ОтборВыбора <> Неопределено Тогда ТаблицаСсылок = Новый ТаблицаЗначений; ТаблицаСсылок.Колонки.Добавить("Ссылка"); Для Каждого Значение Из ПоследниеЗначения Цикл ТаблицаСсылок.Добавить().Ссылка = Значение; КонецЦикла; ТаблицаСсылок = СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаСсылок); НастройкаКомпоновки = Новый НастройкиКомпоновкиДанных; НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкаКомпоновки.Выбор, "Ссылка"); СкопироватьОтборЛюбойЛкс(НастройкаКомпоновки.Отбор, ОтборВыбора,,,, "Ссылка"); ПоследниеЗначения = ОтобратьТаблицуЗначенийКомпоновкойЛкс(ТаблицаСсылок, НастройкаКомпоновки,, Истина); #Если Сервер И Не Сервер Тогда ПоследниеЗначения = Новый ТаблицаЗначений; #КонецЕсли ПоследниеЗначения = ПоследниеЗначения.ВыгрузитьКолонку("Ссылка"); КонецЕсли; Для Каждого Значение Из ПоследниеЗначения Цикл ПолеВвода.СписокВыбора.Добавить(Значение, РасширенноеПредставлениеЗначенияЛкс(Значение)); КонецЦикла; КонецЕсли; КонецПроцедуры Функция ПолеВвода_ОбновитьСписокЛкс(ПолеВвода) Экспорт СписокВыбора = ПолеВвода.СписокВыбора; #Если Сервер И Не Сервер Тогда СписокВыбора = Новый СписокЗначений; #КонецЕсли Значение = ДанныеЭлементаФормыЛкс(ПолеВвода); Если ТипЗнч(Значение) = Тип("Дата") Тогда Если ТипЗнч(ПолеВвода) = Тип("ПолеВвода") Тогда ПолеВвода.Значение = ПолеВвода.Значение + 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 = Истина, ДопустимоеОтклонениеВремени = 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Классов - - // ТабличноеПоле - - // Функция ЗаполнитьДоступныеСборкиПлатформыЛкс(СборкиПлатформы = Неопределено, Знач Компьютер = "", Знач ТипыComКлассов = Неопределено, Знач ТабличноеПоле = Неопределено) Экспорт Если СборкиПлатформы = Неопределено Тогда СборкиПлатформы = СоздатьОбъектПоИмениМетаданныхЛкс("Обработка.ирУправлениеСлужбамиСервера1С"); #Если Сервер И Не Сервер Тогда СборкиПлатформы = Обработки.ирУправлениеСлужбамиСервера1С.Создать(); #КонецЕсли СборкиПлатформы = СборкиПлатформы.СборкиПлатформы.ВыгрузитьКолонки(); #Если Сервер И Не Сервер Тогда СборкиПлатформы = Обработки.ирУправлениеСлужбамиСервера1С.Создать().СборкиПлатформы; #КонецЕсли КонецЕсли; #Если Клиент Тогда Если ТабличноеПоле <> Неопределено Тогда СостояниеСтрокТП = ирКлиент.ТабличноеПолеСостояниеСтрокЛкс(ТабличноеПоле, "Каталог"); КонецЕсли; #КонецЕсли СборкиПлатформы.Очистить(); // Оба варианта пришлось оставить, т.к. WMI вариант очень долгий Если ЭтоИмяЛокальногоКомпьютераЛкс(Компьютер) Тогда Инсталлер = Новый COMОбъект("WindowsInstaller.Installer"); Продукты = Инсталлер.Products; Иначе СлужбаWMI = ирКэш.ПолучитьCOMОбъектWMIЛкс(Компьютер); Если СлужбаWMI = Неопределено Тогда Возврат СборкиПлатформы; КонецЕсли; Продукты = СлужбаWMI.ExecQuery("SELECT * FROM Win32_Product WHERE Vendor LIKE '1C' OR Vendor LIKE '1С'"); КонецЕсли; Для Каждого Продукт Из Продукты Цикл Если ЭтоИмяЛокальногоКомпьютераЛкс(Компьютер) Тогда Попытка ПубликаторПродукта = Инсталлер.ProductInfo(Продукт, "Publisher"); Исключение Продолжить; КонецПопытки; Если Истина И ПубликаторПродукта <> "1C" // латинские буквы И ПубликаторПродукта <> "1С" // русские буквы И ПубликаторПродукта <> "1C-Soft" // латинские буквы И ПубликаторПродукта <> "1С-Софт" // русские буквы И ПубликаторПродукта <> "NetHelp" // Польша Тогда Продолжить; КонецЕсли; //НаименованиеПродукта = Инсталлер.ProductInfo(Продукт, "ProductName"); КаталогВерсии = Инсталлер.ProductInfo(Продукт, "InstallLocation"); //СтрокаРелиза = Инсталлер.ProductInfo(Продукт, "VersionString"); Иначе КаталогВерсии = Продукт.InstallLocation; КонецЕсли; СтрокаТаблицыСборок = СборкиПлатформы.Добавить(); СтрокаТаблицыСборок.Каталог = КаталогВерсии; ФайлПолученияВерсии = Неопределено; Если Типы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; Иначе Кодировка = КодировкаТекста.Системная; КонецЕсли; Возврат Кодировка; КонецФункции // <Описание процедуры> // // Параметры: // <Параметр1> - <Тип.Вид> - <описание параметра> // <продолжение описания параметра>; // ИмяФайлаРезультата - Краткое имя файла, в который будет выведен выходной поток, только в текущем каталоге. // Элевация - Булево - используется только если текущая учетная запись 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; КонецЕсли; Если Не РезультатПодключения Тогда СообщениеОбОшибке = "Ошибки подключения к СУБД:"; Для каждого ОшибкаПодключения Из ОшибкиПодключения Цикл СообщениеОбОшибке = СообщениеОбОшибке + Символы.ПС + ОшибкаПодключения; КонецЦикла; СообщитьЛкс(СообщениеОбОшибке); СоединениеADO = Неопределено; Иначе КлючНастроек = "" + Новый УникальныйИдентификатор; ХранилищеОбщихНастроек.Сохранить(ирКэш.ИмяПродукта(), КлючНастроек, Неопределено); РезультатЗапроса = ВыполнитьЗапросЭтойСУБДЛкс("SELECT 1 FROM _CommonSettings WHERE _SettingsKey = '" + КлючНастроек + "'",,,,, Ложь, СоединениеADO); ХранилищеОбщихНастроек.Удалить(ирКэш.ИмяПродукта(), КлючНастроек, ИмяПользователя()); Если РезультатЗапроса.Количество() = 0 Тогда Если ТранзакцияАктивна() Тогда СообщитьЛкс("Невозможно проверить подключение к БД текущей базы 1С внутри открытой транзакции. Закройте транзакцию и повторите проверку.", СтатусСообщения.Внимание); Иначе СообщитьЛкс("Указаны параметры подключения к БД, не связанной с текущей базой 1С", СтатусСообщения.Внимание); КонецЕсли; СоединениеADO = Неопределено; КонецЕсли; КонецЕсли; Возврат СоединениеADO; КонецФункции Функция ОбновитьМодульВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля, ТекстМодуляВКонсолиНеМенялся, ДатаИзмененияВнешнейОбработки, ИспользоватьБыструюРаспаковку = Ложь) Экспорт // Из-за негарантированной последовательности изменений одного файла в сетевом ресурсе, проводимых с разных компьютеров, серверное выполнение лишено смысла //Если НаСервере Тогда // Результат = ирСервер.ОбновитьМодульВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля, ТекстМодуляВКонсолиНеМенялся, ДатаИзмененияВнешнейОбработки); // Возврат Результат; //Иначе мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли ИмяФайлаВнешнейОбработки = ФайлВнешнейОбработкиДляОтладкиЛкс(БазовоеИмяВнешнейОбработки); Если Не ЗначениеЗаполнено(ИмяФайлаВнешнейОбработки) Тогда Возврат Ложь; КонецЕсли; ФайловыйКэшАлгоритмовДопускаетРедактирование = Истина; ФайлВнешнейОбработки = Новый Файл(ИмяФайлаВнешнейОбработки); Если ДатаИзмененияВнешнейОбработки <> Неопределено Тогда Если Ложь Или (Истина И ФайлВнешнейОбработки.Существует() И ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() > ДатаИзмененияВнешнейОбработки И ФайловыйКэшАлгоритмовДопускаетРедактирование) Или (Истина И ФайлВнешнейОбработки.Существует() И ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс() = ДатаИзмененияВнешнейОбработки И ТекстМодуляВКонсолиНеМенялся) Тогда Возврат Ложь; КонецЕсли; КонецЕсли; мПлатформа.СформироватьВнешнююОбработку(ФайлВнешнейОбработки, ИмяВнешнейОбработки, ТекстМодуля,,, ИспользоватьБыструюРаспаковку); //// 19.01.2019 Для ВерсияАлгоритма в консоли кода ////ДатаИзмененияВнешнейОбработки = ФайлВнешнейОбработки.ПолучитьВремяИзменения() + ирКэш.ПолучитьСмещениеВремениЛкс(); //Если ЗначениеЗаполнено(ДатаИзмененияВнешнейОбработки) Тогда // ФайлВнешнейОбработки.УстановитьВремяИзменения(ДатаИзмененияВнешнейОбработки); //КонецЕсли; Возврат Истина; //КонецЕсли; КонецФункции // Получает идентификатор из любой строки. // "3-я Дебиторка По контрагентам с интервалами СНГ (для Руководства)" => "_3_яДебиторкаПоКонтрагентамСИнтерваламиСНГ_дляРуководства_". // // Параметры: // Представление - - Строка. // ЗаменаПустойСтроки - - // ДопРазрешенныеСимволы - - // ЗаменаСпецСимвола - Строка - если пустая, то следующий символ приводится к верхнему регистру // // Возвращаемое значение: // Строка - . // Функция ИдентификаторИзПредставленияЛкс(Знач Представление = Неопределено, Знач ЗаменаПустойСтроки = "_", ДопРазрешенныеСимволы = "", Знач ЗаменаСпецСимвола = "_") Экспорт Если ПустаяСтрока(Представление) Тогда Представление = ЗаменаПустойСтроки; КонецЕсли; Если Истина И СокрЛП(Представление) = Представление И Найти(Представление, ",") = 0 Тогда Попытка Пустышка = Новый Структура(Представление); Возврат Представление; Исключение КонецПопытки; КонецЕсли; НовоеПредставление = Представление; ПервыйСимвол = Сред(Представление, 1, 1); Если ЛиЦифраЛкс(ПервыйСимвол) Тогда // Первый символ - цифра НовоеПредставление = "_" + НовоеПредставление; КонецЕсли; ПредыдущийСимвол = " "; ТекущаяСтрока = ""; ШаблонСимволаИдентификатора = ШаблонСимволаИдентификатораЛкс(ДопРазрешенныеСимволы); Для Счетчик = 1 По СтрДлина(НовоеПредставление) Цикл ТекущийСимвол = Сред(НовоеПредставление, Счетчик, 1); Если ПустаяСтрока(ПредыдущийСимвол) Тогда // Предыдущий символ - непечатаемый или спецсимвол ТекущийСимвол = ВРег(ТекущийСимвол); КонецЕсли; Если Найти(ШаблонСимволаИдентификатора, НРег(ТекущийСимвол)) > 0 Тогда // Предыдущий символ - непечатаемый ТекущаяСтрока = ТекущаяСтрока + ТекущийСимвол; Иначе Если Не ПустаяСтрока(ТекущийСимвол) Тогда ТекущаяСтрока = ТекущаяСтрока + ЗаменаСпецСимвола; Если ЗаменаСпецСимвола = "" Тогда ТекущийСимвол = " "; КонецЕсли; КонецЕсли; КонецЕсли; ПредыдущийСимвол = ТекущийСимвол; КонецЦикла; Результат = ТекущаяСтрока; Возврат ТекущаяСтрока; КонецФункции Функция ШаблонСимволаИдентификатораЛкс(Знач ДопРазрешенныеСимволы = "") Экспорт РусскиеБуквы = РусскиеБуквыЛкс(); ШаблонСимволаИдентификатора = НРег("_0123456789" + РусскиеБуквы + "abcdefghijklmnopqrstuvwxyz" + ДопРазрешенныеСимволы); // Русский и Ангийский Возврат ШаблонСимволаИдентификатора; КонецФункции Функция РусскиеБуквыЛкс() Экспорт РусскиеБуквы = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; Возврат РусскиеБуквы; КонецФункции Функция ЛиРусскаяБукваЛкс(Знач Символ) Возврат Символ <> "" И Найти(РусскиеБуквыЛкс(), НРег(Символ)) > 0; КонецФункции Функция ЛиБукваЛкс(Знач Символ) Экспорт Возврат НРег(Символ) <> ВРег(Символ); КонецФункции Функция ЛиЦифраЛкс(Символ) Экспорт Результат = Символ <> "" И Найти("0123456789", Символ) > 0; Возврат Результат; КонецФункции Функция ПроверитьКатегорииСимволаЛкс(Знач Символ, Знач МожноЦифра = Истина, Знач МожноБуква = Истина, Знач МожноПодчеркивание = Истина, Знач МожноНепечатный = Ложь) Экспорт Если МожноЦифра И ЛиЦифраЛкс(Символ) Тогда Возврат Истина; КонецЕсли; Если МожноБуква И ЛиБукваЛкс(Символ) Тогда Возврат Истина; КонецЕсли; Если МожноПодчеркивание И Символ = "_" Тогда Возврат Истина; КонецЕсли; Если МожноНепечатный И Символ <> "" И ПустаяСтрока(Символ) Тогда Возврат Истина; КонецЕсли; Возврат Ложь; КонецФункции Функция ФайлВнешнейОбработкиДляОтладкиЛкс(Знач ИмяВнешнейОбработки) Экспорт КаталогОбъектовДляОтладки = КаталогОбъектовДляОтладкиЛкс(); Если Не ЗначениеЗаполнено(КаталогОбъектовДляОтладки) Тогда СообщитьЛкс("В общих настройках инструментов не задан ""Каталог объектов для отладки""! Сохранение внешней обработки не выполнено.", СтатусСообщения.Внимание); Возврат ""; КонецЕсли; ИмяФайлаВнешнейОбработки = КаталогОбъектовДляОтладки + ИмяВнешнейОбработки + ".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 По ТекстовыйДокумент.КоличествоСтрок() Цикл ТекущаяСтрока = ТекстовыйДокумент.ПолучитьСтроку(Счетчик); Если ОбрезатьЛевыеПустые Тогда ТекущаяСтрока = СокрЛ(ТекущаяСтрока); КонецЕсли; ЗаписьТекста.ЗаписатьБезОбработки(Символы.ПС + Смещение + ТекущаяСтрока); КонецЦикла; ТекстПриемник = ТекстПриемник + ЗаписьТекста.Закрыть(); Возврат ТекстПриемник; КонецФункции Функция ЭтотРасширениеКонфигурацииЛкс() Экспорт Результат = Неопределено; Если Не РежимСовместимостиМеньше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; ТекстФайлаПрав.УстановитьСтроку(""); ТекстФайлаПрав.ЗаписатьБезОбработки(" | | 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"); ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя); //ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя); ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя); ТекстФайла = ТекстовыйДокумент.ПолучитьТекст(); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "", Ложь, Истина, Истина); НаЧтоЗаменять = " | " + ПоследнийФрагментЛкс(ФайлИсточник.ИмяБезРасширения) + " | Adopted | | | "; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина); НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>"; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ТекстовыйДокумент.УстановитьТекст(ТекстФайла); ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя); Если СгенерироватьРольВсеПрава Тогда Если Истина И Найти(ПолноеИмяМДXML, "Enum.") = 0 Тогда // Даем права Просмотр и ПросмотрИстории ТекстФайлаПрав.ЗаписатьБезОбработки(" | | " + ПолноеИмяМДXML + " | | Read | true | | | View | true | | | ReadDataHistory | true | | | ViewDataHistory | true | | "); КонецЕсли; КонецЕсли; КонецЦикла; Для Каждого КлючИЗначение Из ДобавленныеВнешниеИсточникиДанных Цикл ПолноеИмяМДXML = "ExternalDataSource." + КлючИЗначение.Ключ; ИмяКлассаМДXML = ПервыйФрагментЛкс(ПолноеИмяМДXML); // Добавим в описание конфигурации (Configuration.xml) ОбъектМД = Метаданные.ВнешниеИсточникиДанных[КлючИЗначение.Ключ]; ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя(); Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") > 0 Тогда Продолжить; КонецЕсли; УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML); УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя; УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта); // Укажем принадлежность объекта в его описании ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ПолноеИмяМДXML + ".xml"); ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя); //ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя); ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя); ТекстФайла = ТекстовыйДокумент.ПолучитьТекст(); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "", Ложь, Истина, Истина); НаЧтоЗаменять = " | " + ПоследнийФрагментЛкс(ФайлИсточник.ИмяБезРасширения) + " | Adopted | | | "; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМД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"); ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя); //ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя); ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя); ТекстФайла = ТекстовыйДокумент.ПолучитьТекст(); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "", Ложь, Истина, Истина); НаЧтоЗаменять = " | " + ИмяОбъектаОригинала + " | Adopted | | "; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМДXML + " uuid=", ">", Ложь, Истина, Истина); НаЧтоЗаменять = "<" + ИмяКлассаМДXML + " uuid=""" + Новый УникальныйИдентификатор + """>"; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ТекстовыйДокумент.УстановитьТекст(ТекстФайла); ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя); КонецЕсли; ФайлИсточник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ИмяОбъектаРасширения + ".Module.txt"); ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".Module.txt"); ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя); ТекстовыйДокумент.Записать(ФайлПриемник.ПолноеИмя); КонецЕсли; Если ПодключитьОтладкуОтчетов И Метаданные.ОсновнаяФормаОтчета <> Неопределено Тогда ИмяОбъектаОригинала = Метаданные.ОсновнаяФормаОтчета.Имя; ИмяОбъектаРасширения = Метаданные.ОбщиеФормы.ирФормаОтчетаРасширение.Имя; // Добавим в описание конфигурации (Configuration.xml) ИмяКлассаМДXML = "CommonForm"; ОбъектМД = Метаданные.ОбщиеФормы[ИмяОбъектаОригинала]; ТекстСпискаОбъектовРасширения = ТекстСпискаОбъектовРасширения + Символы.ПС + ОбъектМД.ПолноеИмя(); Если Найти(ОписаниеРасширения, "<" + ИмяКлассаМДXML + ">" + ОбъектМД.Имя + "<") = 0 Тогда УзелОбъекта = ДокументДом.СоздатьЭлемент(ИмяКлассаМДXML); УзелОбъекта.ТекстовоеСодержимое = ОбъектМД.Имя; УзелТиповСпискаОбъектов.ДобавитьДочерний(УзелОбъекта); // Укажем принадлежность объекта в его описании ФайлИсточник = Новый Файл(КаталогВыгрузкиКонфигурации + РазделительПутиКФайлуЛкс() + ИмяКлассаМДXML + "." + ОбъектМД.Имя + ".xml"); ФайлПриемник = Новый Файл(КаталогВыгрузкиРасширения + РазделительПутиКФайлуЛкс() + ФайлИсточник.Имя); //ПереместитьФайл(ФайлИсточник.ПолноеИмя, ФайлПриемник.ПолноеИмя); ТекстовыйДокумент.Прочитать(ФайлИсточник.ПолноеИмя); ТекстФайла = ТекстовыйДокумент.ПолучитьТекст(); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "", "", Ложь, Истина, Истина); НаЧтоЗаменять = " | " + ИмяОбъектаОригинала + " | Adopted | Managed | | "; ТекстФайла = СтрЗаменитьЛкс(ТекстФайла, ЧтоЗаменять, НаЧтоЗаменять); ЧтоЗаменять = ТекстМеждуМаркерамиЛкс(ТекстФайла, "<" + ИмяКлассаМД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", СтрокаСоединенияИнформационнойБазы(), выхТекстЛога, ПодавлятьДиалоги, "Выгрузка конфигурации в файлы",,,, ИмяПользователя, ПарольПользователя, СообщитьСтрокуПараметров); УдалитьФайлы(ИмяФайлаСпискаВыгрузкиКонфигурации); Если Не Успех Тогда СообщитьЛкс(выхТекстЛога); КонецЕсли; Возврат Успех; КонецФункции Функция ПредставлениеКлючаСтрокиБДЛкс(Знач КлючСтроки, ПолучатьПредставленияСсылок = Истина) Экспорт Если ТипЗнч(КлючСтроки) = Тип("Строка") Тогда ПредставленияКлюча = КлючСтроки; Иначе ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(КлючСтроки)); Если ОбъектМД = Неопределено Тогда // https://www.hostedredmine.com/issues/947191 ПредставленияКлюча = КлючСтроки; Иначе ПолноеИмяМД = ОбъектМД.ПолноеИмя(); Если ЛиКлючЗаписиРегистраЛкс(КлючСтроки) Тогда СтруктураКлюча = СтруктураКлючаТаблицыБДЛкс(ПолноеИмяМД, , Ложь, Ложь); ПредставленияКлюча = ""; Для Каждого ЭлементСписка Из СтруктураКлюча Цикл Если ПредставленияКлюча <> "" Тогда ПредставленияКлюча = ПредставленияКлюча + ", "; КонецЕсли; ПредставлениеЗначения = КлючСтроки[ЭлементСписка.Представление]; Если Не ПолучатьПредставленияСсылок И ЛиСсылкаНаОбъектБДЛкс(ПредставлениеЗначения) Тогда ПредставлениеЗначения = "" + ИдентификаторСсылкиЛкс(ПредставлениеЗначения); Иначе ПредставлениеЗначения = "" + ПредставлениеЗначения; КонецЕсли; ПредставленияКлюча = ПредставленияКлюча + ЭлементСписка.Представление + " = " + ПредставлениеЗначения; КонецЦикла; ИначеЕсли ЛиКорневойТипКонстантыЛкс(ПервыйФрагментЛкс(ПолноеИмяМД)) Тогда ПредставленияКлюча = ПолноеИмяМД; Иначе ПредставленияКлюча = "" + КлючСтроки; //СтруктураЧтения = Новый Структура("Владелец"); //Попытка // ЗаполнитьЗначенияСвойств(СтруктураЧтения, КлючСтроки); //Исключение // // Нет доступа //КонецПопытки; //Если ЗначениеЗаполнено(СтруктураЧтения.Владелец) Тогда // Если ПолучатьПредставленияСсылок Тогда // Владелец = Владелец.УникальныйИдентификатор(); // КонецЕсли; // ПредставленияКлюча = "[" + ПредставлениеКлючаСтрокиБДЛкс(Владелец) + "]" + ПредставленияКлюча; //КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; Возврат ПредставленияКлюча; КонецФункции Процедура ПроверитьСоздатьКаталогПередСозданиемФайлаЛкс(Знач ИмяКонфигурационногоФайла) Экспорт Файл = Новый Файл(ИмяКонфигурационногоФайла); ФайлКаталога = Новый Файл(Файл.Путь); Если Не ФайлКаталога.Существует() Тогда СоздатьКаталог(ФайлКаталога.ПолноеИмя); КонецЕсли; КонецПроцедуры Функция КаталогПрограммныхФайловОСЛкс(Знач x64 = Неопределено) Экспорт ПеременныеОкружения = ирКэш.ПеременныеОкруженияПроцессаЛкс(); Если ирКэш.Это64битнаяОСЛкс() Тогда Если x64 = Неопределено Тогда x64 = ирКэш.Это64битныйПроцессЛкс(); КонецЕсли; Если x64 Тогда ИмяПеременной = "ProgramW6432"; Иначе ИмяПеременной = "ProgramFiles(x86)"; КонецЕсли; Иначе ИмяПеременной = "ProgramFiles"; КонецЕсли; КаталогПрограммныхФайлов = ПеременныеОкружения.Item(ИмяПеременной); Возврат КаталогПрограммныхФайлов; КонецФункции Функция КаталогПеремещаемыхДанныхПриложенийЛкс() Экспорт ПеременныеОкружения = ирКэш.ПеременныеОкруженияПроцессаЛкс(); КаталогПеремещаемыхДанныхПриложений = ПеременныеОкружения.Item("Appdata"); Возврат КаталогПеремещаемыхДанныхПриложений; КонецФункции Функция ПараметрыСоединенияЭтойСУБДЛкс(выхИменаПараметров = "") Экспорт выхИменаПараметров = "ИмяСервера, ИмяБД, ИмяПользователя, Пароль, НаСервере, СобиратьТрассу, ТипСУБД"; Результат = Новый Структура(выхИменаПараметров); РезультатСохраненный = ВосстановитьЗначениеЛкс("ПараметрыСоединенияСУБД"); Если РезультатСохраненный = Неопределено Тогда // Старый формат настроек Результат.ИмяСервера = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяСервера"); Результат.ИмяБД = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяБД"); Результат.ИмяПользователя = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ИмяПользователя"); Результат.СобиратьТрассу = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.СобиратьТрассу"); Результат.ТипСУБД = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.ТипСУБД"); Результат.НаСервере = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.НаСервере"); Результат.Пароль = ВосстановитьЗначениеЛкс("ирПараметрыСоединенияСУБД.Пароль"); СохранитьПараметрыСоединенияСУБДЛкс(Результат); Иначе ЗаполнитьЗначенияСвойств(Результат, РезультатСохраненный); КонецЕсли; Если Результат.ТипСУБД = Неопределено Тогда Результат.ТипСУБД = "MSSQL"; КонецЕсли; Если Результат.Пароль <> Неопределено Тогда Результат.Пароль = Результат.Пароль.Получить(); КонецЕсли; Возврат Результат; КонецФункции //. // Параметры: // ТабличныйДокумент - ТабличныйДокумент - // Возвращаемое значение: // СписокЗначений - Функция ПараметрыТабличногоДокументаЛкс(Знач ТабличныйДокумент) Экспорт ПараметрыМакета = Новый СписокЗначений; ПараметрыМакета.ТипЗначения = Новый ОписаниеТипов("Строка"); Текст = ОбъектВСтрокуXMLЛкс(ТабличныйДокумент); //ирОбщий.ТекстВДокументDOMЛкс(Текст); // Вхождения = НайтиРегВыражениеЛкс(Текст, "(.+)"); Для Каждого Вхождение Из Вхождения Цикл ПараметрыМакета.Добавить(Вхождение.Подгруппа0); КонецЦикла; ПараметрыМакета.СортироватьПоЗначению(); Возврат ПараметрыМакета; КонецФункции Процедура СохранитьПараметрыСоединенияСУБДЛкс(Результат) Экспорт Если ТипЗнч(Результат.Пароль) = Тип("Строка") Тогда Результат.Пароль = Новый ХранилищеЗначения(Результат.Пароль); КонецЕсли; СохранитьЗначениеЛкс("ПараметрыСоединенияСУБД", Результат); КонецПроцедуры Функция ПроверитьСоединениеЭтойСУБДЛкс(Знач ИмяСервера = "", Знач ИмяБД = "", Знач ИмяПользователя = "", Знач Пароль = "", Знач НаСервере = Неопределено, ЗапрашиватьПараметрыПодключения = Истина, Асинхронно = Ложь, выхСоединение = Неопределено, Знач ТипСУБД = "MSSQL") Экспорт Если ПроверитьПлатформаНеWindowsЛкс(, "Прямой запрос к СУБД") Тогда Возврат Ложь; КонецЕсли; КоличествоПопыток = 1; НачальнаяПопытка = 1; Если ЗапрашиватьПараметрыПодключения Тогда КоличествоПопыток = 2; Если Не ЗначениеЗаполнено(ИмяСервера) Тогда ПараметрыСоединения = ПараметрыСоединенияЭтойСУБДЛкс(); Если Не ЗначениеЗаполнено(ПараметрыСоединения.ИмяСервера) Тогда НачальнаяПопытка = 2; КонецЕсли; КонецЕсли; КонецЕсли; Для НомерПопытки = НачальнаяПопытка По КоличествоПопыток Цикл Если НомерПопытки = 2 Тогда #Если Клиент Тогда ФормаПодключения = ирКлиент.ОткрытьФормуСоединенияСУБДЛкс(Истина); Если ФормаПодключения = Неопределено Тогда Возврат Ложь; КонецЕсли; Если НаСервере = Неопределено Тогда НаСервере = ФормаПодключения.НаСервере; КонецЕсли; #Иначе СообщитьЛкс("Необходимо с клиента выполнить проверку установки соединения с СУБД"); Возврат Ложь; #КонецЕсли Иначе Если НаСервере = Неопределено Тогда Если ПараметрыСоединения = Неопределено Тогда ПараметрыСоединения = ПараметрыСоединенияЭтойСУБДЛкс(); КонецЕсли; НаСервере = ПараметрыСоединения.НаСервере; КонецЕсли; КонецЕсли; Если НомерПопытки = 2 И Не ЗначениеЗаполнено(ИмяСервера) Тогда ЛиСоединениеУстановлено = Ложь; ИначеЕсли НаСервере = Истина Тогда ЛиСоединениеУстановлено = ирСервер.ПроверитьСоединениеЭтойСУБДЛкс(ИмяСервера, ИмяБД, ИмяПользователя, Пароль, Асинхронно, ТипСУБД); Если ЛиСоединениеУстановлено Тогда выхСоединение = "Готов"; КонецЕсли; Иначе выхСоединение = СоединениеЭтойСУБД(ИмяСервера, ИмяБД, ИмяПользователя, Пароль, Асинхронно, ТипСУБД); ЛиСоединениеУстановлено = выхСоединение <> Неопределено; КонецЕсли; Если ЛиСоединениеУстановлено Тогда Прервать; КонецЕсли; КонецЦикла; Возврат ЛиСоединениеУстановлено; КонецФункции Функция ВыполнитьЗапросЭтойСУБДЛкс(Знач ТекстЗапроса, Знач РежимОтладки = Ложь, Знач ПредставлениеЗапроса = "", Знач СмещениеГода = 2000, Знач ИспользованиеGWF = Истина, Знач НаСервере = Неопределено, СоединениеADO = Неопределено, БинарныеВСтроку = Истина, Знач ИспользоватьRecordset = Истина) Экспорт ТребоватьТипЛкс(ТекстЗапроса, "ТекстЗапроса", Тип("Строка")); #Если Клиент Тогда Если РежимОтладки Тогда ирКлиент.ОткрытьЗапросСУБДЛкс(ТекстЗапроса, ПредставлениеЗапроса); Возврат Неопределено; КонецЕсли; Если Истина И СоединениеADO = Неопределено И НаСервере = Неопределено Тогда НаСервере = ПараметрыСоединенияЭтойСУБДЛкс().НаСервере; КонецЕсли; #КонецЕсли Если НаСервере = Истина Тогда Таблица = ирСервер.ВыполнитьЗапросЭтойСУБДЛкс(ТекстЗапроса, СмещениеГода, ИспользованиеGWF); Иначе Если СоединениеADO = Неопределено Тогда Попытка СоединениеADO = ирКэш.СоединениеЭтойСУБД(); Исключение СоединениеADO = СоединениеЭтойСУБД(); КонецПопытки; Если СоединениеADO = Неопределено Тогда Возврат Неопределено; КонецЕсли; КонецЕсли; Если ИспользоватьRecordset Тогда РезультатЗапроса = Новый COMОбъект("ADODB.Recordset"); adOpenStatic = 3; adLockOptimistic = 3; adCmdText = 1; РезультатЗапроса.Open(ТекстЗапроса, СоединениеADO, adOpenStatic, adLockOptimistic, adCmdText); Иначе КомандаADO = Новый COMОбъект("ADODB.Command"); КомандаADO.CommandTimeout = 30; // секунд Команда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); КонецПроцедуры Процедура ПаузаМиллисекундЛкс(Число) Экспорт Попытка ВК = ВКОбщаяЛкс(); ВК.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 И ТипТаблицы = "ВиртуальнаяТаблица" Тогда СтрокиСтруктурыТаблицы = СтруктураХраненияБД.НайтиСтроки(Новый Структура("Назначение", "Основная")); выхИмяОстаток = ПеревестиСтроку("Остаток"); КонецЕсли; Возврат СтрокиСтруктурыТаблицы; КонецФункции Функция СтруктураХраненияОсновнойТаблицыМДЛкс(Знач ПолноеИмяМД) Экспорт //СтруктураХраненияПолей = ирКэш.СтруктураХраненияБДЛкс().НайтиСтроки(Новый Структура("Назначение, Метаданные", "Основная", ПолноеИмяМД))[0].Поля; ФильтрМетаданных = Новый Массив; ФильтрМетаданных.Добавить(ПолноеИмяМД); СтруктураХраненияТаблиц = ПолучитьСтруктуруХраненияБазыДанных(ФильтрМетаданных); ПеревестиКолонкиСтруктурыХраненияБДТаблицыЛкс(СтруктураХраненияТаблиц); Назначение = НазначениеОсновнойТаблицыХраненияМДЛкс(ПолноеИмяМД); СтруктураХраненияТаблицы = СтруктураХраненияТаблиц.НайтиСтроки(Новый Структура("Назначение, Метаданные", Назначение, ПолноеИмяМД))[0]; ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(СтруктураХраненияТаблицы.Поля); Возврат СтруктураХраненияТаблицы; КонецФункции Функция НазначениеОсновнойТаблицыХраненияМДЛкс(Знач ПолноеИмяМД) Экспорт СловоКонстанта = ПеревестиСтроку("Константа"); Если СтрНачинаетсяСЛкс(ПолноеИмяМД, СловоКонстанта) Тогда Назначение = СловоКонстанта; Иначе Назначение = ПеревестиСтроку("Основная"); КонецЕсли; Возврат Назначение; КонецФункции Функция ОсновнойПорядокТаблицыБДЛкс(Знач ПолноеИмяТаблицы, Знач СтрокаПорядка = "", Знач НастройкаПорядка = Неопределено, Знач СтруктураХраненияТаблицы = Неопределено, Знач СортироватьДатыПоУбыванию = Ложь) Экспорт Построитель = Новый ПостроительЗапроса("ВЫБРАТЬ * ИЗ " + ПолноеИмяТаблицы + " КАК Т"); ТипТаблицы = ТипТаблицыБДЛкс(ПолноеИмяТаблицы); Если СтруктураХраненияТаблицы = Неопределено Тогда ОбъектМД = ОбъектМДПоПолномуИмениТаблицыБДЛкс(ПолноеИмяТаблицы); Если Ложь Или ОбъектМД = Неопределено Или ТипТаблицы = "Внешняя" Или ТипТаблицы = "Изменения" Или ЛиТипВложеннойТаблицыБДЛкс(ТипТаблицы) Тогда Возврат Построитель; КонецЕсли; СтруктураХраненияТаблицы = СтруктураХраненияОсновнойТаблицыМДЛкс(ОбъектМД.ПолноеИмя()); КонецЕсли; выхСортировкаПоДате = Ложь; Построитель.ЗаполнитьНастройки(); ПорядокТаблицы = Построитель.Порядок; Если Не ЗначениеЗаполнено(СтрокаПорядка) Тогда ПредопределенныеПоля = Новый Массив(); Если ТипТаблицы = "ПланСчетов" Тогда ПредопределенныеПоля.Добавить(ПеревестиСтроку("Код")); КонецЕсли; ПредопределенныеПоля.Добавить(ПеревестиСтроку("Наименование")); ПредопределенныеПоля.Добавить(ПеревестиСтроку("Дата")); ПредопределенныеПоля.Добавить(ПеревестиСтроку("Период")); ПредопределенныеПоля.Добавить("ДатаИзменения"); ПредопределенныеПоля.Добавить("ДатаСоздания"); ПредопределенныеПоля.Добавить(ПеревестиСтроку("Номер")); ПредопределенныеПоля.Добавить(ПеревестиСтроку("Код")); ПеревестиКолонкиСтруктурыХраненияБДИндексыЛкс(СтруктураХраненияТаблицы.Индексы); Для Каждого ПредопределенноеПоле Из ПредопределенныеПоля Цикл Если НастройкаПорядка <> Неопределено Тогда ЭлементПорядка = НастройкаПорядка.Найти(ПредопределенноеПоле); Если ЭлементПорядка = Неопределено Тогда Продолжить; КонецЕсли; КонецЕсли; Для Каждого ИндексТаблицыБД Из СтруктураХраненияТаблицы.Индексы Цикл ПеревестиКолонкиСтруктурыХраненияБДПоляЛкс(ИндексТаблицыБД.Поля); Если ИндексТаблицыБД.Поля[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Лкс(КопияТаблицы,, ИмяКолонки); СуммаКолонки = КопияКолонки.Итог(ИмяКолонки); КонецЕсли; КонецЕсли; Возврат СуммаКолонки; КонецФункции // Функция - Прочитать результат фонового задания лкс // // Параметры: // АдресРезультата - - // ФормаРезультата - см. Обработка.ирПлатформа.Форма.РезультатФоновогоЗадания - с ее идентификатором создавался адрес временного хранилища // // Возвращаемое значение: // - // Функция ПрочитатьРезультатФоновогоЗаданияЛкс(Знач АдресРезультата, Знач ФормаРезультата = Неопределено) Экспорт Результат = ПолучитьИзВременногоХранилища(АдресРезультата); Если Результат = Null И ФормаРезультата <> Неопределено Тогда // Антибаг платформы https://www.hostedredmine.com/issues/884756 Если ТипЗнч(ФормаРезультата) = ТипУправляемаяФормаЛкс() Тогда ФормаРезультата.ОбновитьВременноеХранилище(АдресРезультата); // Тяжелая операция Результат = ПолучитьИзВременногоХранилища(АдресРезультата); КонецЕсли; Если Результат = Null Тогда СообщитьЛкс("Не удалось получить результат фонового задания. Возможные причины: https://www.hostedredmine.com/issues/884756, https://bugboard.v8.1c.ru/error/000133136. Асинхронность отключена до конца сеанса.", СтатусСообщения.Внимание); мПлатформа = ирКэш.Получить(); #Если Сервер И Не Сервер Тогда мПлатформа = Обработки.ирПлатформа.Создать(); #КонецЕсли мПлатформа.АсинхронностьЗапрещена = Истина; КонецЕсли; КонецЕсли; УдалитьИзВременногоХранилища(АдресРезультата); Возврат Результат КонецФункции Функция СтрокаТабличнойКоллекцииПоКлючуЛкс(Знач ТабличнаяКоллекция, Знач КлючТекущейСтроки) Экспорт Если ТипЗнч(КлючТекущейСтроки) = Тип("Структура") Тогда #Если Сервер И Не Сервер Тогда КлючТекущейСтроки = Новый Структура; #КонецЕсли НайденныеСтроки = Новый Массив; Если ТипЗнч(ТабличнаяКоллекция) = Тип("ДеревоЗначений") Тогда НайденныеСтроки = ТабличнаяКоллекция.Строки.НайтиСтроки(КлючТекущейСтроки, Истина); Иначе //! ТабличнаяКоллекция = 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 Тогда Продолжить; КонецЕсли; Если ТипЭлементаКоллекции = ТипОбъектовРезультата Тогда СтрокаНайденного = Результат.Добавить(); ЗаполнитьЗначенияСвойств(СтрокаНайденного, ОбъектМД); Для Каждого ИмяКолонкиРезультата Из КолонкиРасширенногоПредставления Цикл Попытка ЗначениеСвойства = ОбъектМД[ИмяКолонкиРезультата]; Исключение // Измерение последовательности Продолжить; КонецПопытки; СтрокаНайденного[ИмяКолонкиРезультата] = РасширенноеПредставлениеЗначенияЛкс(ЗначениеСвойства); КонецЦикла; СтрокаНайденного.ПолноеИмя = ПолноеИмяМД; СтрокаНайденного.ПолноеИмяРодителя = ПолноеИмяРодителя; Попытка РасширениеКонфигурации = ОбъектМД.РасширениеКонфигурации(); Исключение РасширениеКонфигурации = Неопределено; КонецПопытки; СтрокаНайденного.РасширениеКонфигурации = РасширениеКонфигурации; КонецЕсли; Если ЗначениеЗаполнено(ПолноеИмяМД) Тогда Если ЗащитаРекурсия[ПолноеИмяМД] = 1 Тогда Продолжить; КонецЕсли; ЗащитаРекурсия[ПолноеИмяМД] = 1; КонецЕсли; Если СтруктураТипаОбъекта = Неопределено Тогда СтруктураТипаОбъекта = мПлатформа.НоваяСтруктураТипа(); СтруктураТипаОбъекта.ИмяОбщегоТипа = ТипЭлементаКоллекции; КонецЕсли; СтруктураТипаОбъекта.Метаданные = ОбъектМД; Если Не ЛиЦелевойТипКорневой Тогда ЛиБылиПодходящиеКоллекцииСнизу = НайтиОбъектыМетаданныхРекурсивноЛкс(ТипОбъектовРезультата, ИскомаяСсылкаМД, Результат, КолонкиРасширенногоПредставления, СтруктураТипаОбъекта, ЛиЦелевойТипКорневой, ПолноеИмяМД, ЗащитаРекурсия, СвойстваРекурсия); Если ЛиБылиПодходящиеКоллекцииСнизу Тогда ЛиБылиПодходящиеКоллекции = Истина; КонецЕсли; Если Не ЛиБылиПодходящиеКоллекции Тогда Прервать; КонецЕсли; КонецЕсли; КонецЦикла; Если ИндикаторКоллекции <> Неопределено Тогда ОсвободитьИндикаторПроцессаЛкс(); КонецЕсли; КонецЦикла; Если ИндикаторСвойств <> Неопределено Тогда ОсвободитьИндикаторПроцессаЛкс(); КонецЕсли; Возврат ЛиБылиПодходящиеКоллекции; КонецФункции Процедура ДобавитьТекущемуПользователюРолиИРЛкс() Экспорт Если ирКэш.ЛиПортативныйРежимЛкс() Тогда Возврат; КонецЕсли; ТекущийПользовательЗапуска = ПользователиИнформационнойБазы.ТекущийПользователь(); Если СтрКончаетсяНаЛкс(ТекущийПользовательЗапуска.ПолноеИмя, МаркерВременныхРолейЛкс()) Тогда Возврат; КонецЕсли; Если ирКэш.НомерВерсииБСПЛкс() >= 300 И Метаданные.Справочники.Найти("ПрофилиГруппДоступа") <> Неопределено Тогда ирСервер.ДобавитьТекущемуПользователюБСПРолиИРЛкс(); КонецЕсли; ТекущийПользовательБД = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя()); Если Ложь Или ТекущийПользовательБД.Роли.Содержит(Метаданные.Роли.ирРазработчик) Или Не ЗначениеЗаполнено(ИмяПользователя()) Или Не ПравоДоступа("Администрирование", Метаданные) Тогда Возврат; КонецЕсли; ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирРазработчик); ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирПользователь); Если Метаданные.Роли.Найти("ирВсеПрава") <> Неопределено Тогда ТекущийПользовательБД.Роли.Добавить(Метаданные.Роли.ирВсеПрава); //@skip-check unknown-method-property КонецЕсли; ТекущийПользовательБД.Записать(); #Если Клиент Тогда ирКлиент.ОповеститьОЗаписиОбъектаЛкс(Тип("ПользовательИнформационнойБазы")); #КонецЕсли КонецПроцедуры Функция МаркерВременныхРолейЛкс() Экспорт Результат = " (временные роли ИР)"; Возврат Результат; КонецФункции Процедура ЗаполнитьКолонкуПорядкаТаблицыЛкс(Знач ТаблицаЗначений, Знач ИмяКолонкиПорядка = "Порядок") Экспорт #Если Сервер И Не Сервер Тогда ВсеВидыПравДоступа = Новый ТаблицаЗначений; #КонецЕсли Если ТаблицаЗначений.Колонки.Найти(ИмяКолонкиПорядка) = Неопределено Тогда ТаблицаЗначений.Колонки.Добавить(ИмяКолонкиПорядка); КонецЕсли; Счетчик = 1; Для Каждого Строка Из ТаблицаЗначений Цикл Строка[ИмяКолонкиПорядка] = Счетчик; Счетчик = Счетчик + 1; КонецЦикла; КонецПроцедуры // . // // Параметры: // ИмяМодуля - Строка - // НомерСтрокиМодуля - Число - // ИмяМетода - Строка - // СмещениеСтрокиМетода - - // ТекстСтроки - - // НомерКолонки - - // ИмяПараметра - - // Расширенная - Булево - если Ложь, то используется самый компактный стандартный формат ссылки, например {Обработка.ирКлсПолеТекстаПрограммы.МодульОбъекта(5362)} // // Возвращаемое значение: // Строка - Пример: {ОбщийМодуль.ирОбщий.Модуль(29754:СсылкаСтрокиМодуляЛкс.ИмяМодуля,1)}: Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда // Функция СсылкаСтрокиМодуляЛкс(Знач ИмяМодуля, Знач НомерСтрокиМодуля = 0, Знач ИмяМетода = "", Знач СмещениеСтрокиМетода = 0, Знач ТекстСтроки = "", Знач НомерКолонки = 0, Знач ИмяПараметра = "", Знач Расширенная = Истина) Экспорт Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда ИмяМодуля = СтрокаБезПоследнегоФрагментаЛкс(ИмяМодуля); КонецЕсли; //Если ЗначениеЗаполнено(ИмяРасширения) Тогда // ИмяМодуля = ИмяРасширения + " " + ИмяМодуля; //КонецЕсли; Результат = Новый Массив; Если НомерСтрокиМодуля = Неопределено Тогда НомерСтрокиМодуля = 0; КонецЕсли; КоординатыВМодуле = XMLСтрока(НомерСтрокиМодуля); Если ЗначениеЗаполнено(НомерКолонки) Тогда КоординатыВМодуле = КоординатыВМодуле + "," + XMLСтрока(НомерКолонки); КонецЕсли; Результат.Добавить(КоординатыВМодуле); Если Расширенная Тогда Если ЗначениеЗаполнено(ИмяМетода) Или ЗначениеЗаполнено(СмещениеСтрокиМетода) Тогда КоординатыМетода = XMLСтрока(ИмяМетода); Если ЗначениеЗаполнено(ИмяПараметра) Тогда КоординатыМетода = КоординатыМетода + "." + XMLСтрока(ИмяПараметра); КонецЕсли; Если ЗначениеЗаполнено(СмещениеСтрокиМетода) Тогда КоординатыМетода = КоординатыМетода + "," + XMLСтрока(СмещениеСтрокиМетода); КонецЕсли; Результат.Добавить(КоординатыМетода); КонецЕсли; Если Не СтрНачинаетсяСЛкс(ИмяМодуля, "Ф::") Тогда ИмяМодуля = СтрЗаменить(ИмяМодуля, "\", " "); КонецЕсли; КонецЕсли; Результат = СтрСоединитьЛкс(Результат, ":"); Результат = "{" + ИмяМодуля + "(" + Результат + ")}"; Если Расширенная И ЗначениеЗаполнено(ТекстСтроки) Тогда Результат = Результат + ": " + ирОбщий.ПредставлениеЗначенияСОграничениемДлиныЛкс(ТекстСтроки); КонецЕсли; Возврат Результат; КонецФункции //. // Параметры: // СсылкаСтрокиМодуля - Строка - Пример: {ОбщийМодуль.ирОбщий.Модуль(29754:СсылкаСтрокиМодуляЛкс.ИмяМодуля,1)}: Если СтрКончаетсяНаЛкс(ИмяМодуля, ".Форма.Модуль") Тогда Функция СтруктураСсылкиСтрокиМодуляЛкс(Знач СсылкаСтрокиМодуля, Знач НормализоватьИмяМодуля = Истина) Экспорт ШаблонСсылки = "(\{([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_<>\.]*)(?:,(-?\d+))?)?" + "(?:!([a-zа-яё0-9_]+))?\)\})"; Вхождения = НайтиРегВыражениеЛкс(СсылкаСтрокиМодуля, ШаблонСсылки); Если Вхождения.Количество() = 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]; Если НормализоватьИмяМодуля Тогда Модуль = Модуль + ".Модуль"; КонецЕсли; КонецЕсли; НомерСтроки = Число(Вхождение.Подгруппы[4]); Если Вхождение.Подгруппы[5] <> Неопределено Тогда НомерКолонки = Число(Вхождение.Подгруппы[5]); Иначе НомерКолонки = 1; КонецЕсли; Если Вхождение.Подгруппы[7] <> Неопределено Тогда СмещениеСтрокиМетода = Число(Вхождение.Подгруппы[7]); Иначе СмещениеСтрокиМетода = 0; КонецЕсли; ПриоритетМетода = Вхождение.Подгруппы[6] <> Неопределено; Если НомерСтроки = 0 Тогда ПриоритетМетода = Истина; НомерСтроки = 1; КонецЕсли; Метод = Вхождение.Подгруппы[6]; ФрагментыМетода = СтрРазделитьЛкс(Метод); Если ФрагментыМетода.Количество() > 1 Тогда Метод = ФрагментыМетода[0]; ПараметрМетода = ФрагментыМетода[1]; КонецЕсли; ТипМодуля = ПоследнийФрагментЛкс(Модуль); Если ЗначениеЗаполнено(Расширение) Тогда Модуль = Расширение + " " + Модуль; КонецЕсли; Команда = Вхождение.Подгруппы[8]; СтруктураСсылкиСтрокиМодуля = Новый Структура; СтруктураСсылкиСтрокиМодуля.Вставить("Модуль", Модуль); СтруктураСсылкиСтрокиМодуля.Вставить("Внутренняя", Внутренняя); // Для внешней обработки СтруктураСсылкиСтрокиМодуля.Вставить("Файл", ИмяФайла); СтруктураСсылкиСтрокиМодуля.Вставить("ТипОбъекта", ТипОбъекта); СтруктураСсылкиСтрокиМодуля.Вставить("ТипМодуля", ТипМодуля); СтруктураСсылкиСтрокиМодуля.Вставить("Расширение", Расширение); СтруктураСсылкиСтрокиМодуля.Вставить("Объект", Объект); СтруктураСсылкиСтрокиМодуля.Вставить("Форма", Форма); СтруктураСсылкиСтрокиМодуля.Вставить("НомерСтроки", НомерСтроки); СтруктураСсылкиСтрокиМодуля.Вставить("НомерКолонки", НомерКолонки); СтруктураСсылкиСтрокиМодуля.Вставить("Метод", Метод); СтруктураСсылкиСтрокиМодуля.Вставить("ПараметрМетода", ПараметрМетода); СтруктураСсылкиСтрокиМодуля.Вставить("СмещениеСтрокиМетода", СмещениеСтрокиМетода); СтруктураСсылкиСтрокиМодуля.Вставить("Текст", Текст); СтруктураСсылкиСтрокиМодуля.Вставить("Команда", Команда); СтруктураСсылкиСтрокиМодуля.Вставить("ТекстСсылки", Вхождение.ТекстВхождения); Возврат СтруктураСсылкиСтрокиМодуля; КонецФункции // Пример C:\TerminalDisk\ОтважныйБобр.epf -> file://C:/TerminalDisk/ОтважныйБобр.epf // Параметры: // ИмяФайла - Строка - // Возвращаемое значение: // Строка - Функция СсылкаФайлаЛкс(Знач ИмяФайла) Экспорт ИмяФайла = "file://" + СтрЗаменить(ИмяФайла, "\", "/"); Возврат ИмяФайла; КонецФункции // Функция - Заполнить значения ключами в структуре // // Параметры: // Структура - Структура - // // Возвращаемое значение: // Структура - // Функция ЗаполнитьЗначенияКлючамиВСтруктуреЛкс(Знач Структура) Экспорт Результат = Новый Структура; // см. Структура Для Каждого КлючИЗначение Из Структура Цикл Результат.Вставить(КлючИЗначение.Ключ, КлючИЗначение.Ключ); КонецЦикла; Возврат Результат; КонецФункции //////////////////////////////////////////////// // Многопоточность Функция НоваяСтруктураМногопоточнойОбработкиЛкс(Знач ИмяОбработчикаОбъекта, Знач МодульОбработчика, Знач ИмяОбработчикаРезультатаОбъекта, Знач КоличествоОбъектовВПорции, Знач КоличествоПотоков, Знач ОбщиеПараметрыОбработкиОдногоОбъекта = Неопределено, Знач ВыводитьСообщения = Истина) Экспорт #Если Сервер И Не Сервер Тогда МодульОбработчика = Обработки.ирПодборИОбработкаОбъектов.Создать(); #КонецЕсли ПотокиОбработки = Новый ТаблицаЗначений; ПотокиОбработки.Колонки.Добавить("АдресРезультата"); ПотокиОбработки.Колонки.Добавить("СтрокиРезультатовОбъектов"); ПотокиОбработки.Колонки.Добавить("УникальныйИдентификатор"); ДоступностьМногопоточности = Истина И ирКэш.ЭтоФоновоеЗаданиеЛкс() И Не ирКэш.ЛиФайловаяБазаЛкс() И Не ирКэш.ЛиПортативныйРежимЛкс(); Для Счетчик = 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) Экспорт Фрагменты = СтрРазделитьЛкс(Строка, Разделитель); Пока Фрагменты.Количество() > ЧислоФрагментов Цикл Фрагменты.Удалить(Фрагменты.ВГраница()); КонецЦикла; Результат = СтрСоединитьЛкс(Фрагменты, Разделитель); Возврат Результат; КонецФункции Функция СтрКончаетсяНаЛкс(Знач ПерваяСтрока, Знач ВтораяСтрока, Знач СУчетомРегистра = Ложь) Экспорт КонецСтроки = Прав(ПерваяСтрока, СтрДлина(ВтораяСтрока)); Если СУчетомРегистра Тогда Результат = КонецСтроки = ВтораяСтрока; Иначе Результат = НРег(КонецСтроки) = НРег(ВтораяСтрока); КонецЕсли; Возврат Результат; КонецФункции // Получает последний фрагмент, отделяемый разделителем от строки. // Для для длинных строк медленно! Для них рекомендуется использовать регулярные выражения. // // Параметры: // пСтрока - Строка - в которой ищем; // *пМаркер - Строка, "." - отсекающий маркер; // *пЛиИспользоватьГраницуЕслиМаркерНеНайден - Булево, *Истина - разрешение использования границ строки // в случае, если маркер не найден. // // Возвращаемое значение: // Неопределено - маркер не найден; // - Число - позиция маркера. // Функция ПоследнийФрагментЛкс(Знач пСтрока, Знач пМаркер = ".", Знач пЛиИспользоватьГраницуЕслиМаркерНеНайден = Истина) Экспорт _РежимОтладки = Ложь; Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 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) <> "\" Тогда КаталогИсполняемыхФайлов = КаталогИсполняемыхФайлов + "\"; КонецЕсли; КонецПроцедуры // Проверяет правильность заполнения реквизитов объекта // Параметры: // Объект - // ОбязательныеПоля - Строка(0,П), Массив // Отказ - Булево // Заголовок - Строка(0,П) // // Возвращаемое значение: Булево - истина, если проверка пройдена успешно Функция ПроверитьЗаполнениеРеквизитовОбъектаЛкс(Знач Объект, Знач ОбязательныеПоля = "", Отказ = Ложь) Экспорт Результат = Истина; Попытка ОбменДаннымиЗагрузка = Объект.ОбменДанными.Загрузка; Исключение ОбменДаннымиЗагрузка = Ложь; КонецПопытки; Если ОбменДаннымиЗагрузка Тогда Возврат Результат; КонецЕсли; Если ТипЗнч(ОбязательныеПоля) = Тип("Строка") Тогда МассивПолей = СтрРазделитьЛкс(ОбязательныеПоля, ",", Истина); ОбязательныеПоля = Новый Соответствие; Для каждого Значение Из МассивПолей Цикл ОбязательныеПоля[Значение] = ""; КонецЦикла; //ОбязательныеПоля = Новый Структура(ОбязательныеПоля); КонецЕсли; РеквизитыМД = Объект.Метаданные().Реквизиты; Для каждого КлючЗначение Из ОбязательныеПоля Цикл ПутьКДанным = КлючЗначение.Ключ; Значение = Вычислить("Объект." + ПутьКДанным); Если Не ЗначениеЗаполнено(Значение) Тогда // надо ругаться Если Не ЗначениеЗаполнено(КлючЗначение.Значение) Тогда Фрагменты = СтрРазделитьЛкс(ПутьКДанным); ИндексСтрокиТЧ = Неопределено; Если Фрагменты.Количество() > 1 Тогда ИндексСтрокиТЧ = ТекстМеждуМаркерамиЛкс(Фрагменты[0], "[", "]", Ложь); Если ИндексСтрокиТЧ <> Неопределено Тогда ИндексСтрокиТЧ = Число(ИндексСтрокиТЧ); //ИмяТЧ = ПолучитьПервыйФрагментИис(Фрагменты[0], "["); КонецЕсли; КонецЕсли; //ПредставлениеРеквизита = РеквизитыМД[КлючЗначение.Ключ].Представление(); ПредставлениеРеквизита = СокрЛП(Фрагменты[Фрагменты.ВГраница()]); СтрокаСообщения = "Не заполнено значение реквизита """ + ПредставлениеРеквизита + """"; Если ИндексСтрокиТЧ <> Неопределено Тогда СтрокаСообщения = СтрокаСообщения + " в строке №" + Формат(ИндексСтрокиТЧ + 1, "ЧГ=") + " таблицы """ + СокрЛП(ПервыйФрагментЛкс(Фрагменты[0], "[")) + """"; КонецЕсли; Иначе СтрокаСообщения = КлючЗначение.Значение; КонецЕсли; Отказ = Истина; СообщитьЛкс(СтрокаСообщения, СтатусСообщения.Внимание); Результат = Ложь; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции Функция ЛиОписанияТиповПересекаютсяЛкс(Знач ОписаниеТипов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 // Долго Тогда Возврат Ложь; КонецЕсли; //мПлатформа = ирКэш.Получить(); // Долго //РегВыражение = мПлатформа.RegExp; //РегВыражение.Pattern = мПлатформа.шИмя; //Результат = РегВыражение.Проверить(Строка); //Возврат Результат; // Долго //ПервыйСимвол = Лев(Строка, 1); //Если Истина // И ПервыйСимвол <> "_" // И Не ЛиБукваЛкс(ПервыйСимвол) //Тогда // Возврат Ложь; //КонецЕсли; Пустышка = Новый Структура; Попытка Пустышка.Вставить(Строка); Возврат Истина; Исключение Возврат Ложь; КонецПопытки; КонецФункции // Пространство имен текущей конфигурации. // Возвращаемое значение: // Функция ПространствоИменТекущейКонфигурацииЛкс() Экспорт Возврат "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) // Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. Для каждого Элемент Из Коллекция Цикл Если Истина И ТипЭлемента <> Неопределено И ТипЗнч(Элемент) <> ТипЭлемента Тогда Продолжить; КонецЕсли; ЗаполнитьЗначенияСвойств(Структура, Элемент, Свойство); Если Структура[Свойство] = Значение Тогда Результат = Элемент; Прервать; КонецЕсли; КонецЦикла; Иначе // Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" Для каждого Элемент Из Коллекция Цикл   Если Истина   И ТипЭлемента <> Неопределено   И ТипЗнч(Элемент) <> ТипЭлемента   Тогда   Продолжить;   КонецЕсли;   ЗаполнитьЗначенияСвойств(Структура, Элемент, Свойство);   Если Структура[Свойство] = Значение Тогда   Результат = Элемент;   Прервать;   КонецЕсли;   КонецЦикла;   КонецЕсли; Возврат Результат; КонецФункции Функция ЗначенияСвойстваКоллекцииЛкс(Знач Коллекция, Знач Свойство = "Имя", Знач ТипЭлемента = Неопределено) Экспорт Результат = Новый Массив; Для каждого Элемент Из Коллекция Цикл Если Истина И ТипЭлемента <> Неопределено И ТипЗнч(Элемент) <> ТипЭлемента Тогда Продолжить; КонецЕсли; Результат.Добавить(Элемент[Свойство]); КонецЦикла; Возврат Результат; КонецФункции Функция РежимОтладкиСервераИзКоманднойСтрокиЛкс(Знач СтрокаЗапускаПроцесса = "") Экспорт Если Не ЗначениеЗаполнено(СтрокаЗапускаПроцесса) Тогда ирСервер.ПолучитьПараметрыПроцессаАгентаСервера(, СтрокаЗапускаПроцесса); КонецЕсли; МаркерОтладки = "-debug"; ПозицияСтрокиТипаОтладчика = Найти(НРег(СтрокаЗапускаПроцесса), Нрег(МаркерОтладки)); Если ЗначениеЗаполнено(ПозицияСтрокиТипаОтладчика) Тогда СтрокаОтладчика = СокрЛ(Сред(СтрокаЗапускаПроцесса, ПозицияСтрокиТипаОтладчика + СтрДлина(МаркерОтладки))); Если Найти(НРег(СтрокаОтладчика), "-http") = 1 Тогда РежимОтладки = "http"; Иначе РежимОтладки = "tcp"; КонецЕсли; Иначе РежимОтладки = "нет"; КонецЕсли; Возврат РежимОтладки; КонецФункции Функция СтрЗаменитьЛкс(Знач ГдеЗаменять, Знач ЧтоЗаменять, Знач НаЧтоЗаменять, Знач ОставитьЧтоЗаменятьСлева = Ложь, Знач ВыброситьИсключениеПриОтсутствии = Истина) Экспорт Если ВыброситьИсключениеПриОтсутствии И Найти(ГдеЗаменять, ЧтоЗаменять) < 1 Тогда ВызватьИсключение "Шаблонная строка """ + ЧтоЗаменять + """ не найдена в тексте"; КонецЕсли; Если ОставитьЧтоЗаменятьСлева Тогда НаЧтоЗаменять = ЧтоЗаменять + НаЧтоЗаменять; КонецЕсли; Результат = СтрЗаменить(ГдеЗаменять, ЧтоЗаменять, НаЧтоЗаменять); Возврат Результат; КонецФункции Функция СтрНайтиЛкс(Знач Строка, Знач ПодстрокаПоиска, Знач НаправлениеПоискаСКонца = Ложь, Знач НачальнаяПозиция = Неопределено, Знач НомерВхождения = 1, Знач УчитыватьРегистр = Истина) Экспорт Если Не УчитыватьРегистр Тогда Строка = НРег(Строка); ПодстрокаПоиска = НРег(ПодстрокаПоиска); КонецЕсли; Если Не НаправлениеПоискаСКонца И НачальнаяПозиция = Неопределено И НомерВхождения = 1 Тогда Возврат Найти(Строка, ПодстрокаПоиска); КонецЕсли; Если ирКэш.НомерРежимаСовместимостиЛкс() >= 803006 И ирОбщий83 <> Неопределено Тогда Возврат ирОбщий83.СтрНайтиЛкс(Строка, ПодстрокаПоиска, ?(НаправлениеПоискаСКонца, ПредопределенноеЗначение("НаправлениеПоиска.СКонца"), ПредопределенноеЗначение("НаправлениеПоиска.СНачала")), НачальнаяПозиция, НомерВхождения); КонецЕсли; ТекущаяПозиция = 0; ЗнакНаправленияДвижения = 0; ДлинаСтрПоиска = СтрДлина(ПодстрокаПоиска); Попытка Если НачальнаяПозиция <> Неопределено Тогда НачальнаяПозиция = Число(НачальнаяПозиция); Если НачальнаяПозиция <= 0 ИЛИ НачальнаяПозиция > СтрДлина(Строка) Тогда ВызватьИсключение (""); КонецЕсли; КонецЕсли; Исключение ВызватьИсключение("Недопустимое значение параметра (параметр номер '4')"); КонецПопытки; Если НаправлениеПоискаСКонца Тогда НачальнаяПозиция = ?(НачальнаяПозиция <> Неопределено, НачальнаяПозиция, СтрДлина(Строка)); ЗнакНаправленияДвижения = -1; Иначе НачальнаяПозиция = ?(НачальнаяПозиция <> Неопределено, НачальнаяПозиция, 1); ЗнакНаправленияДвижения = 1; КонецЕсли; Если ирКэш.РежимОтладкиЛкс() Тогда // Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. Пока Истина И НомерВхождения <> 0 И (Ложь Или (Истина И Не НаправлениеПоискаСКонца И НачальнаяПозиция <= СтрДлина(Строка)) Или (Истина И НаправлениеПоискаСКонца И НачальнаяПозиция >= 0)) Цикл Позиция = Найти(Сред(Строка, НачальнаяПозиция, ДлинаСтрПоиска), ПодстрокаПоиска); Если Позиция Тогда ТекущаяПозиция = НачальнаяПозиция; НачальнаяПозиция = ТекущаяПозиция + ДлинаСтрПоиска * ЗнакНаправленияДвижения; НомерВхождения = НомерВхождения - 1; Иначе НачальнаяПозиция = НачальнаяПозиция + 1 * ЗнакНаправленияДвижения; КонецЕсли; КонецЦикла; Иначе // Однострочный код использован для ускорения. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru) Пока Истина   И НомерВхождения <> 0   И (Ложь   Или (Истина   И Не НаправлениеПоискаСКонца   И НачальнаяПозиция <= СтрДлина(Строка))   Или (Истина   И НаправлениеПоискаСКонца   И НачальнаяПозиция >= 0))   Цикл   Позиция = Найти(Сред(Строка, НачальнаяПозиция, ДлинаСтрПоиска), ПодстрокаПоиска);   Если Позиция Тогда   ТекущаяПозиция = НачальнаяПозиция;   НачальнаяПозиция = ТекущаяПозиция + ДлинаСтрПоиска * ЗнакНаправленияДвижения;   НомерВхождения = НомерВхождения - 1;   Иначе   НачальнаяПозиция = НачальнаяПозиция + 1 * ЗнакНаправленияДвижения;   КонецЕсли;   КонецЦикла;   КонецЕсли; Если НомерВхождения Тогда ТекущаяПозиция = 0; КонецЕсли; Возврат ТекущаяПозиция; КонецФункции Функция СтрНачинаетсяСЛкс(ГдеИщем, ЧтоИщем, УчитыватьРегистр = Ложь) Экспорт Результат = Ложь Или (Истина И УчитыватьРегистр И Лев(ГдеИщем, СтрДлина(ЧтоИщем)) = ЧтоИщем) Или (Истина И Не УчитыватьРегистр И Лев(НРег(ГдеИщем), СтрДлина(ЧтоИщем)) = НРег(ЧтоИщем)); Возврат Результат; КонецФункции // Функция разбивает строку разделителем. // Старые имена - РазбитьСтрокуРазделителем, ПолучитьМассивИзСтрокиСРазделителем // // Параметры: // Стр - Строка - которую разбиваем; // Разделитель - Строка, "." - символ-разделитель; // ОбрезатьНепечатныеСимволы - Булево, *Ложь - делать СокрЛП. // ОставлятьПустуюСтроку - Булево, *Истина - если передана пустая строка, то добавлять ее в массив // УчитыватьКавычки - Булево - если да, то разделители внутри кавычек игнорируются, а сами крание кавычки фрагментов удаляются // ПропускатьПустые - Булево - если да, то пропускать пустые фрагменты // // Возвращаемое значение: // Массив - фрагментов. // Функция СтрРазделитьЛкс(Знач Стр, Знач Разделитель = ".", Знач ОбрезатьНепечатныеСимволы = Ложь, Знач ОставлятьПустуюСтроку = Истина, Знач УчитыватьКавычки = Ложь, Знач ПропускатьПустые = Ложь, Знач ТолькоПервыйРазделитель = Ложь, Знач УчитыватьРегистр = Истина) Экспорт //_РежимОтладки = ирКэш.РежимОтладкиЛкс() // Закомментировано для избежания беконечной рекурсии _РежимОтладки = Ложь; Если _РежимОтладки Тогда // Можно менять на Истина в точке останова, например условием ирОбщий.Пр(_РежимОтладки, 1, 1) // Пассивный оригинал расположенного ниже однострочного кода. Выполняйте изменения синхронно в обоих вариантах. МассивСтрок = Новый Массив; Если Истина И Не ОставлятьПустуюСтроку И ПустаяСтрока(Стр) Тогда Возврат МассивСтрок; КонецЕсли; НужнаПостобработка = Ложь Или ПропускатьПустые Или УчитыватьКавычки И Найти(Стр, """") > 0; Если Разделитель = " " Тогда Стр = СокрЛП(Стр); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; МассивСтрок.Добавить(Лев(Стр, Поз-1)); Стр = СокрЛ(Сред(Стр, Поз)); Если ТолькоПервыйРазделитель Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; КонецЦикла; Иначе ОбрезатьНепечатныеСимволыСразу = ОбрезатьНепечатныеСимволы И Не НужнаПостобработка; ДлинаРазделителя = СтрДлина(Разделитель); Пока 1=1 Цикл Поз = Найти(Стр, Разделитель); Если Поз=0 Тогда Фрагмент = Стр; Если ОбрезатьНепечатныеСимволыСразу Тогда Фрагмент = СокрЛП(Фрагмент); КонецЕсли; МассивСтрок.Добавить(Фрагмент); Прервать; КонецЕсли; Фрагмент = Лев(Стр, Поз-1); Если ОбрезатьНепечатныеСимволыСразу Тогда Фрагмент = СокрЛП(Фрагмент); КонецЕсли; МассивСтрок.Добавить(Фрагмент); Стр = Сред(Стр, Поз+ДлинаРазделителя); Если ТолькоПервыйРазделитель Тогда МассивСтрок.Добавить(Стр); Прервать; КонецЕсли; КонецЦикла; КонецЕсли; Если НужнаПостобработка Тогда СтроковыйЛитерал = Неопределено; Для Индекс = 1 - МассивСтрок.Количество() По 0 Цикл // Обратный обход ТекстЯчейки = МассивСтрок[-Индекс]; Если СтроковыйЛитерал = Неопределено И Прав(СтрЗаменить(ТекстЯчейки, """""", ""), 1) = """" Тогда СтроковыйЛитерал = ТекстЯчейки; ИначеЕсли СтроковыйЛитерал <> Неопределено Тогда СтроковыйЛитерал = ТекстЯчейки + Разделитель + СтроковыйЛитерал; КонецЕсли; Если Истина И СтроковыйЛитерал <> Неопределено И Лев(СтрЗаменить(СтроковыйЛитерал, """""", ""), 1) = """" Тогда ТекстЯчейки = ТекстИзВстроенногоЯзыкаЛкс(СтроковыйЛитерал); СтроковыйЛитерал = Неопределено; ИначеЕсли Не ОбрезатьНепечатныеСимволы Тогда Продолжить; КонецЕсли; Если Ложь Или СтроковыйЛитерал <> Неопределено Или ПропускатьПустые И ПустаяСтрока(ТекстЯчейки) Тогда МассивСтрок.Удалить(-Индекс); Иначе Если ОбрезатьНепечатныеСимволы Тогда ТекстЯчейки = СокрЛП(ТекстЯчейки); КонецЕсли; МассивСтрок[-Индекс] = ТекстЯчейки; КонецЕсли; КонецЦикла; КонецЕсли; Иначе // Однострочный код использован для ускорения при разрешенной отладке. Выше расположен оригинал. Выполняйте изменения синхронно в обоих вариантах. Преобразовано консолью кода из подсистемы "Инструменты разработчика" МассивСтрок = Новый Массив;   Если Истина   И Не ОставлятьПустуюСтроку   И ПустаяСтрока(Стр)   Тогда   Возврат МассивСтрок;   КонецЕсли;   НужнаПостобработка = Ложь   Или ПропускатьПустые   Или УчитыватьКавычки И Найти(Стр, """") > 0;   Если Разделитель = " " Тогда   Стр = СокрЛП(Стр);   Пока 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); Если ВключатьМаркеры Тогда Если НачальныйМаркер <> Неопределено Тогда Результат = НачальныйМаркер + Результат; КонецЕсли; Если КонечныйМаркер <> Неопределено Тогда Результат = Результат + КонечныйМаркер; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции Функция ПервыеНепечатныеСимволыПервойНепустойСтрокиЛкс(Текст) Экспорт RegExp = ирКэш.ВычислительРегВыраженийЛкс(); RegExp.Global = Ложь; RegExp.Pattern = "\S"; Результат = RegExp.НайтиВхождения(Текст); Если Результат.Количество() > 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 Цикл ЭлементыДерева = ТекущаяСтрока.ПолучитьЭлементы(); лТекущаяСтрока = НайтиЭлементКоллекцииЛкс(ЭлементыДерева, ИмяКлючевойКолонки, КлючиУровней[Уровень]); Если лТекущаяСтрока <> Неопределено Тогда ТекущаяСтрока = лТекущаяСтрока; Иначе Прервать; КонецЕсли; КонецЦикла; Возврат ТекущаяСтрока; КонецФункции #Если Сервер И Не Сервер Тогда ирПортативный = Обработки.ирПортативный.Создать(); #КонецЕсли