Regular Expressions 101

Save & Share

Flavor

  • PCRE2 (PHP >=7.3)
  • PCRE (PHP <7.3)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java 8
  • .NET 7.0 (C#)
  • Rust
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests

Tools

Sponsors
There are currently no sponsors. Become a sponsor today!
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Non-capturing group
    (?:...)
  • Capturing group
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression
No Match

r"
"
gmi

Test String

Code Generator

Generated Code

using System; using System.Text.RegularExpressions; public class Example { public static void Main() { string pattern = @"(?<=(?:\/\/){1}[ [ruА-Яа-яёЁ])((?:[ruА-Яа-яёЁ\s\d \,\.\:\-\""\&\d\*\;\(\)\.\,\'\=\<\>\!-\?\@^#])*?)$(?:[\b\t\s]+((?:Функция|Процедура)\s+(?:[\w\d]|[А-Яа-я])+\([\w\W]*?\)\s*(?:Экспорт)?))"; string input = @"/////////////////////////////////////////////////////////////////////////////////////////////////////// // Copyright (c) 2023, ООО 1С-Софт // Все права защищены. Эта программа и сопроводительные материалы предоставляются // в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0) // Текст лицензии доступен по ссылке: // https://creativecommons.org/licenses/by/4.0/legalcode /////////////////////////////////////////////////////////////////////////////////////////////////////// #Область ПрограммныйИнтерфейс #Область ОповещениеПользователя // Формирует и выводит сообщение, которое может быть связано с элементом управления формы. // // В фоновом задании длительной операции, если вызов выполнен вне транзакции, // сообщение записывается в служебный регистр и отправляется сразу на клиент, // если подключена система взаимодействия. // В конце фонового задания длительной операции, а также при отправке прогресса, // все сообщения извлекаются из очереди сообщений фонового задания, // записываются в служебный регистр и отправляются сразу на клиент, // если подключена система взаимодействия. // // АПК:142-выкл 4 необязательных параметра для совместимости // с устаревшей процедурой ОбщегоНазначенияКлиентСервер.СообщитьПользователю. // // Параметры: // ТекстСообщенияПользователю - Строка - текст сообщения. // КлючДанных - ЛюбаяСсылка - объект или ключ записи информационной базы, к которому это сообщение относится. // Поле - Строка - наименование реквизита формы. // ПутьКДанным - Строка - путь к данным (путь к реквизиту формы). // Отказ - Булево - выходной параметр, всегда устанавливается в значение Истина. // // Пример: // // 1. Для вывода сообщения у поля управляемой формы, связанного с реквизитом объекта: // ОбщегоНазначения.СообщитьПользователю( // НСтр(""ru = 'Сообщение об ошибке.'""), , // ""ПолеВРеквизитеФормыОбъект"", // ""Объект""); // // Альтернативный вариант использования в форме объекта: // ОбщегоНазначения.СообщитьПользователю( // НСтр(""ru = 'Сообщение об ошибке.'""), , // ""Объект.ПолеВРеквизитеФормыОбъект""); // // 2. Для вывода сообщения рядом с полем управляемой формы, связанным с реквизитом формы: // ОбщегоНазначения.СообщитьПользователю( // НСтр(""ru = 'Сообщение об ошибке.'""), , // ""ИмяРеквизитаФормы""); // // 3. Для вывода сообщения связанного с объектом информационной базы: // ОбщегоНазначения.СообщитьПользователю( // НСтр(""ru = 'Сообщение об ошибке.'""), ОбъектИнформационнойБазы, ""Ответственный"",,Отказ); // // 4. Для вывода сообщения по ссылке на объект информационной базы: // ОбщегоНазначения.СообщитьПользователю( // НСтр(""ru = 'Сообщение об ошибке.'""), Ссылка, , , Отказ); // // Случаи некорректного использования: // 1. Передача одновременно параметров КлючДанных и ПутьКДанным. // 2. Передача в параметре КлючДанных значения типа отличного от допустимого. // 3. Установка ссылки без установки поля (и/или пути к данным). // Процедура СообщитьПользователю(Знач ТекстСообщенияПользователю, Знач КлючДанных = Неопределено, Знач Поле = "", Знач ПутьКДанным = "", Отказ = Ложь) Экспорт ЭтоОбъект = Ложь; Если КлючДанных <> Неопределено И XMLТипЗнч(КлючДанных) <> Неопределено Тогда ТипЗначенияСтрокой = XMLТипЗнч(КлючДанных).ИмяТипа; ЭтоОбъект = СтрНайти(ТипЗначенияСтрокой, ""Object."") > 0; КонецЕсли; Сообщение = ОбщегоНазначенияСлужебныйКлиентСервер.СообщениеПользователю(ТекстСообщенияПользователю, КлючДанных, Поле, ПутьКДанным, Отказ, ЭтоОбъект); #Если НЕ МобильныйАвтономныйСервер Тогда Если СтандартныеПодсистемыПовтИсп.ЭтоСеансДлительнойОперации() И Не ТранзакцияАктивна() Тогда ДлительныеОперации.ОтправитьОповещениеКлиенту(""СообщениеПользователю"", Сообщение); Иначе Сообщение.Сообщить(); КонецЕсли; #Иначе Сообщение.Сообщить(); #КонецЕсли КонецПроцедуры // АПК:142-вкл #КонецОбласти #Если НЕ МобильныйАвтономныйСервер Тогда #Область ДанныеВБазе //////////////////////////////////////////////////////////////////////////////// // Общие процедуры и функции для работы с данными в базе. // Возвращает структуру, содержащую значения реквизитов, прочитанные из информационной базы по ссылке на объект. // Рекомендуется использовать вместо обращения к реквизитам объекта через точку от ссылки на объект // для быстрого чтения отдельных реквизитов объекта из базы данных. // // Если необходимо зачитать реквизит независимо от прав текущего пользователя, // то следует использовать предварительный переход в привилегированный режим. // // Параметры: // Ссылка - ЛюбаяСсылка - объект, значения реквизитов которого необходимо получить. // - Строка - полное имя предопределенного элемента, значения реквизитов которого необходимо получить. // Реквизиты - Строка - имена реквизитов, перечисленные через запятую, в формате // требований к свойствам структуры. // Например, ""Код, Наименование, Родитель"". // - Структура // - ФиксированнаяСтруктура - в качестве ключа передается // псевдоним поля для возвращаемой структуры с результатом, а в качестве // значения (опционально) фактическое имя поля в таблице. // Если ключ задан, а значение не определено, то имя поля берется из ключа. // Допускается указание имени поля через точку, но при этом параметр КодЯзыка для такого поля // учитываться не будет. // - Массив из Строка // - ФиксированныйМассив из Строка - имена реквизитов в формате требований к свойствам структуры. // ВыбратьРазрешенные - Булево - если Истина, то запрос к объекту выполняется с учетом прав пользователя; // если есть ограничение на уровне записей, то все реквизиты вернутся со // значением Неопределено; если нет прав для работы с таблицей, то возникнет исключение; // если Ложь, то возникнет исключение при отсутствии прав на таблицу // или любой из реквизитов. // КодЯзыка - Строка - код языка для мультиязычного реквизита. Значение по умолчанию - основной язык конфигурации. // // Возвращаемое значение: // Структура - содержит имена (ключи) и значения затребованных реквизитов. // Если в параметр Реквизиты передана пустая строка, то возвращается пустая структура. // Если в параметр Ссылка передана пустая ссылка, то возвращается структура, // соответствующая именам реквизитов со значениями Неопределено. // Если в параметр Ссылка передана ссылка несуществующего объекта (битая ссылка), // то все реквизиты вернутся со значением Неопределено. // Функция ЗначенияРеквизитовОбъекта(Ссылка, Знач Реквизиты, ВыбратьРазрешенные = Ложь, Знач КодЯзыка = Неопределено) Экспорт // Если передано имя предопределенного. Если ТипЗнч(Ссылка) = Тип(""Строка"") Тогда ПолноеИмяПредопределенногоЭлемента = Ссылка; // Вычисление ссылки по имени предопределенного. // - дополнительно выполняет проверку метаданных предопределенного, выполняется предварительно. Попытка Ссылка = ПредопределенныйЭлемент(ПолноеИмяПредопределенногоЭлемента); Исключение ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный первый параметр %1 в функции %2: |%3'""), ""Ссылка"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъекта"", ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение ТекстОшибки; КонецПопытки; // Разбор полного имени предопределенного. ЧастиПолногоИмени = СтрРазделить(ПолноеИмяПредопределенногоЭлемента, "".""); ПолноеИмяОбъектаМетаданных = ЧастиПолногоИмени[0] + ""."" + ЧастиПолногоИмени[1]; // Если предопределенный не создан в ИБ, то требуется выполнить проверку доступа к объекту. // В других сценариях проверка доступа выполняется в момент исполнения запроса. Если Ссылка = Неопределено Тогда МетаданныеОбъекта = ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъектаМетаданных); Если Не ПравоДоступа(""Чтение"", МетаданныеОбъекта) Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недостаточно прав для работы с таблицей ""%1""'""), ПолноеИмяОбъектаМетаданных); КонецЕсли; КонецЕсли; Иначе // Если передана ссылка. Попытка ПолноеИмяОбъектаМетаданных = Ссылка.Метаданные().ПолноеИмя(); Исключение ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный первый параметр %1 в функции %2: |Значение должно быть ссылкой или именем предопределенного элемента.'""), ""Ссылка"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъекта""); КонецПопытки; КонецЕсли; // Разбор реквизитов, если второй параметр Строка. Если ТипЗнч(Реквизиты) = Тип(""Строка"") Тогда Если ПустаяСтрока(Реквизиты) Тогда Возврат Новый Структура; КонецЕсли; Реквизиты = СтрРазделить(Реквизиты, "","", Ложь); Для Индекс = 0 По Реквизиты.ВГраница() Цикл Реквизиты[Индекс] = СокрЛП(Реквизиты[Индекс]); КонецЦикла; КонецЕсли; МультиязычныеРеквизиты = Новый Соответствие; СуффиксЯзыка = ""; Если ЗначениеЗаполнено(КодЯзыка) Тогда Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); СуффиксЯзыка = МодульМультиязычностьСервер.СуффиксЯзыка(КодЯзыка); Если ЗначениеЗаполнено(СуффиксЯзыка) Тогда МультиязычныеРеквизиты = МодульМультиязычностьСервер.МультиязычныеРеквизитыОбъекта(Ссылка); КонецЕсли; КонецЕсли; КонецЕсли; // Приведение реквизитов к единому формату. СтруктураПолей = Новый Структура; Если ТипЗнч(Реквизиты) = Тип(""Структура"") Или ТипЗнч(Реквизиты) = Тип(""ФиксированнаяСтруктура"") Тогда Для Каждого КлючИЗначение Из Реквизиты Цикл СтруктураПолей.Вставить(КлючИЗначение.Ключ, СокрЛП(КлючИЗначение.Значение)); КонецЦикла; ИначеЕсли ТипЗнч(Реквизиты) = Тип(""Массив"") Или ТипЗнч(Реквизиты) = Тип(""ФиксированныйМассив"") Тогда Для Каждого Реквизит Из Реквизиты Цикл Реквизит = СокрЛП(Реквизит); Попытка ПсевдонимПоля = СтрЗаменить(Реквизит, ""."", ""); СтруктураПолей.Вставить(ПсевдонимПоля, Реквизит); Исключение // Если псевдоним не является ключом. // Поиск ошибки доступности полей. Результат = ПроверитьСуществованиеРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, Реквизиты); Если Результат.Ошибка Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: %3'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъекта"", Результат.ОписаниеОшибки); КонецЕсли; // Не удалось распознать ошибку, проброс первичной ошибки. ВызватьИсключение; КонецПопытки; КонецЦикла; Иначе ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный тип второго параметра %1 в функции %2: %3.'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъекта"", Строка(ТипЗнч(Реквизиты))); КонецЕсли; // Подготовка результата (после выполнения запроса переопределится). Результат = Новый Структура; // Формирование текста запроса к выбираемым полям. ТекстЗапросаПолей = ""; Для каждого КлючИЗначение Из СтруктураПолей Цикл ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ); ПсевдонимПоля = КлючИЗначение.Ключ; Если МультиязычныеРеквизиты[ИмяПоля] <> Неопределено Тогда ИмяПоля = ИмяПоля + СуффиксЯзыка; КонецЕсли; ТекстЗапросаПолей = ТекстЗапросаПолей + ?(ПустаяСтрока(ТекстЗапросаПолей), "", "","") + "" | "" + ИмяПоля + "" КАК "" + ПсевдонимПоля; // Предварительное добавление поля по псевдониму в возвращаемый результат. Результат.Вставить(ПсевдонимПоля); КонецЦикла; // Если предопределенного нет в ИБ. // - приведение результата к отсутствию объекта в ИБ или передаче пустой ссылки. Если Ссылка = Неопределено Тогда Возврат Результат; КонецЕсли; Если Тип(""Структура"") = ТипЗнч(Реквизиты) Или Тип(""ФиксированнаяСтруктура"") = ТипЗнч(Реквизиты) Тогда Реквизиты = Новый Массив; Для Каждого КлючИЗначение Из СтруктураПолей Цикл ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ); Реквизиты.Добавить(ИмяПоля); КонецЦикла; КонецЕсли; РеквизитыЧерезТочку = Новый Массив; Для Индекс = -Реквизиты.ВГраница() По 0 Цикл ИмяПоля = Реквизиты[-Индекс]; Если СтрНайти(ИмяПоля, ""."") Тогда РеквизитыЧерезТочку.Добавить(ИмяПоля); Реквизиты.Удалить(-Индекс); КонецЕсли; КонецЦикла; Если ЗначениеЗаполнено(Реквизиты) Тогда ЗначенияРеквизитовОбъекта = ЗначенияРеквизитовОбъектов(ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Ссылка), Реквизиты, ВыбратьРазрешенные, КодЯзыка)[Ссылка]; Если ЗначенияРеквизитовОбъекта <> Неопределено Тогда Для Каждого КлючИЗначение Из СтруктураПолей Цикл ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ); Если СтрНайти(ИмяПоля, ""."") = 0 И ЗначенияРеквизитовОбъекта.Свойство(ИмяПоля) Тогда Результат[КлючИЗначение.Ключ] = ЗначенияРеквизитовОбъекта[ИмяПоля]; КонецЕсли; КонецЦикла; КонецЕсли; КонецЕсли; Если Не ЗначениеЗаполнено(РеквизитыЧерезТочку) Тогда Возврат Результат; КонецЕсли; Реквизиты = РеквизитыЧерезТочку; ТекстЗапроса = ""ВЫБРАТЬ РАЗРЕШЕННЫЕ |&ТекстЗапросаПолей |ИЗ | &ПолноеИмяОбъектаМетаданных КАК ПсевдонимЗаданнойТаблицы |ГДЕ | ПсевдонимЗаданнойТаблицы.Ссылка = &Ссылка""; Если Не ВыбратьРазрешенные Тогда ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""РАЗРЕШЕННЫЕ"", ""); // @Query-part-1 КонецЕсли; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ТекстЗапросаПолей"", ТекстЗапросаПолей); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ПолноеИмяОбъектаМетаданных"", ПолноеИмяОбъектаМетаданных); // Выполнение запроса. Запрос = Новый Запрос; Запрос.УстановитьПараметр(""Ссылка"", Ссылка); Запрос.Текст = ТекстЗапроса; Попытка Выборка = Запрос.Выполнить().Выбрать(); Исключение // Если реквизиты были переданы строкой, то они уже конвертированы в массив. // Если реквизиты - массив, оставляем без изменений. // Если реквизиты - структура - конвертируем в массив. // В остальных случаях уже было бы выброшено исключение. Если Тип(""Структура"") = ТипЗнч(Реквизиты) Или Тип(""ФиксированнаяСтруктура"") = ТипЗнч(Реквизиты) Тогда Реквизиты = Новый Массив; Для каждого КлючИЗначение Из СтруктураПолей Цикл ИмяПоля = ?(ЗначениеЗаполнено(КлючИЗначение.Значение), КлючИЗначение.Значение, КлючИЗначение.Ключ); Реквизиты.Добавить(ИмяПоля); КонецЦикла; КонецЕсли; // Поиск ошибки доступности полей. Результат = ПроверитьСуществованиеРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, Реквизиты); Если Результат.Ошибка Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: %3'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъекта"", Результат.ОписаниеОшибки); КонецЕсли; // Не удалось распознать ошибку, проброс первичной ошибки. ВызватьИсключение; КонецПопытки; // Заполнение реквизитов. Если Выборка.Следующий() Тогда ЗаполнитьЗначенияСвойств(Результат, Выборка); КонецЕсли; Возврат Результат; КонецФункции // Возвращает значения реквизита, прочитанного из информационной базы по ссылке на объект. // Рекомендуется использовать вместо обращения к реквизитам объекта через точку от ссылки на объект // для быстрого чтения отдельных реквизитов объекта из базы данных. // // Если необходимо зачитать реквизит независимо от прав текущего пользователя, // то следует использовать предварительный переход в привилегированный режим. // // Если передано имя несуществующего реквизита, то вызывается исключение ""Поле объекта не существует"". // // Параметры: // Ссылка - ЛюбаяСсылка - объект, значения реквизитов которого необходимо получить. // - Строка - полное имя предопределенного элемента, значения реквизитов которого необходимо получить. // ИмяРеквизита - Строка - имя получаемого реквизита. // Допускается указание имени реквизита через точку, но при этом параметр КодЯзыка для // такого реквизита учитываться не будет. // ВыбратьРазрешенные - Булево - если Истина, то запрос к объекту выполняется с учетом прав пользователя; // если есть ограничение на уровне записей, то возвращается Неопределено; // если нет прав для работы с таблицей, то возникнет исключение; // если Ложь, то возникнет исключение при отсутствии прав на таблицу // или любой из реквизитов. // КодЯзыка - Строка - код языка для мультиязычного реквизита. Значение по умолчанию - основной язык конфигурации. // // Возвращаемое значение: // Произвольный - если в параметр Ссылка передана пустая ссылка, то возвращается Неопределено. // Если в параметр Ссылка передана ссылка несуществующего объекта (битая ссылка), // то возвращается Неопределено. // Функция ЗначениеРеквизитаОбъекта(Ссылка, ИмяРеквизита, ВыбратьРазрешенные = Ложь, Знач КодЯзыка = Неопределено) Экспорт Если ПустаяСтрока(ИмяРеквизита) Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: |Имя реквизита должно быть заполнено.'""), ""ИмяРеквизита"", ""ОбщегоНазначения.ЗначениеРеквизитаОбъекта""); КонецЕсли; Результат = ЗначенияРеквизитовОбъекта(Ссылка, ИмяРеквизита, ВыбратьРазрешенные, КодЯзыка); Возврат Результат[СтрЗаменить(ИмяРеквизита, ""."", "")]; КонецФункции // Возвращает значения реквизитов, прочитанные из информационной базы для нескольких объектов. // Рекомендуется использовать вместо обращения к реквизитам объекта через точку от ссылки на объект // для быстрого чтения отдельных реквизитов объекта из базы данных. // // Если необходимо зачитать реквизит независимо от прав текущего пользователя, // то следует использовать предварительный переход в привилегированный режим. // // Если передано имя несуществующего реквизита, то вызывается исключение ""Поле объекта не существует"". // // Параметры: // Ссылки - Массив из ЛюбаяСсылка // - ФиксированныйМассив из ЛюбаяСсылка - ссылки на объекты. // Если массив пуст, то результатом будет пустое соответствие. // Реквизиты - Строка - имена реквизитов перечисленные через запятую, в формате требований к свойствам // структуры. Например, ""Код, Наименование, Родитель"". // - Массив из Строка // - ФиксированныйМассив из Строка - имена реквизитов в формате требований к свойствам структуры. // ВыбратьРазрешенные - Булево - если Истина, то запрос к объектам выполняется с учетом прав пользователя; // если какой-либо объект будет исключен из выборки по правам, то этот объект // будет исключен и из результата; // если Ложь, то возникнет исключение при отсутствии прав на таблицу // или любой из реквизитов. // КодЯзыка - Строка - код языка для мультиязычного реквизита. Значение по умолчанию - основной язык конфигурации. // // Возвращаемое значение: // Соответствие из КлючИЗначение - список объектов и значений их реквизитов: // * Ключ - ЛюбаяСсылка - ссылка на объект; // * Значение - Структура: // ** Ключ - Строка - имя реквизита; // ** Значение - Произвольный - значение реквизита. // Функция ЗначенияРеквизитовОбъектов(Ссылки, Знач Реквизиты, ВыбратьРазрешенные = Ложь, Знач КодЯзыка = Неопределено) Экспорт Если ТипЗнч(Реквизиты) = Тип(""Массив"") Или ТипЗнч(Реквизиты) = Тип(""ФиксированныйМассив"") Тогда Реквизиты = СтрСоединить(Реквизиты, "",""); КонецЕсли; Если ПустаяСтрока(Реквизиты) Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: |Поле объекта должно быть указано.'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъектов""); КонецЕсли; Если СтрНайти(Реквизиты, ""."") <> 0 Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: |Обращение через точку не поддерживается.'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъектов""); КонецЕсли; ЗначенияРеквизитов = Новый Соответствие; Если Ссылки.Количество() = 0 Тогда Возврат ЗначенияРеквизитов; КонецЕсли; Если ЗначениеЗаполнено(КодЯзыка) Тогда КодЯзыка = СтрРазделить(КодЯзыка, ""_"", Истина)[0]; КонецЕсли; РеквизитыТекстЗапроса = Реквизиты; Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); Если ЗначениеЗаполнено(КодЯзыка) Тогда СуффиксЯзыка = МодульМультиязычностьСервер.СуффиксЯзыка(КодЯзыка); Если ЗначениеЗаполнено(СуффиксЯзыка) Тогда МультиязычныеРеквизиты = МодульМультиязычностьСервер.МультиязычныеРеквизитыОбъекта(Ссылки[0]); НаборРеквизитов = СтрРазделить(Реквизиты, "",""); Для Позиция = 0 По НаборРеквизитов.ВГраница() Цикл ИмяРеквизита = СокрЛП(НаборРеквизитов[Позиция]); Если МультиязычныеРеквизиты[ИмяРеквизита] <> Неопределено Тогда ИмяССуффиксом = ИмяРеквизита + СуффиксЯзыка; НаборРеквизитов[Позиция] = ИмяССуффиксом + "" КАК "" + ИмяРеквизита; КонецЕсли; КонецЦикла; РеквизитыТекстЗапроса = СтрСоединить(НаборРеквизитов, "",""); КонецЕсли; КонецЕсли; КонецЕсли; СсылкиПоТипам = Новый Соответствие; Для Каждого Ссылка Из Ссылки Цикл Тип = ТипЗнч(Ссылка); Если СсылкиПоТипам[Тип] = Неопределено Тогда СсылкиПоТипам[Тип] = Новый Массив; КонецЕсли; ЭлементПоТипу = СсылкиПоТипам[Тип]; // Массив ЭлементПоТипу.Добавить(Ссылка); КонецЦикла; ТекстыЗапросов = Новый Массив; ПараметрыЗапроса = Новый Структура; ИменаОбъектовМетаданных = Новый Массив; Для Каждого СсылкиПоТипу Из СсылкиПоТипам Цикл Тип = СсылкиПоТипу.Ключ; ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип); Если ОбъектМетаданных = Неопределено Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный первый параметр %1 в функции %2: |Значения массива должны быть ссылками.'""), ""Ссылки"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъектов""); КонецЕсли; ПолноеИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя(); ИменаОбъектовМетаданных.Добавить(ПолноеИмяОбъектаМетаданных); ТекстЗапроса = ""ВЫБРАТЬ РАЗРЕШЕННЫЕ | Ссылка, | &Реквизиты |ИЗ | &ПолноеИмяОбъектаМетаданных КАК ПсевдонимЗаданнойТаблицы |ГДЕ | ПсевдонимЗаданнойТаблицы.Ссылка В (&Ссылки)""; Если Не ВыбратьРазрешенные Или ТекстыЗапросов.Количество() > 0 Тогда ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""РАЗРЕШЕННЫЕ"", ""); // @Query-part-1 КонецЕсли; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&Реквизиты"", РеквизитыТекстЗапроса); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ПолноеИмяОбъектаМетаданных"", ПолноеИмяОбъектаМетаданных); ИмяПараметра = ""Ссылки"" + СтрЗаменить(ПолноеИмяОбъектаМетаданных, ""."", ""); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&Ссылки"", ""&"" + ИмяПараметра); // @Query-part-1 ПараметрыЗапроса.Вставить(ИмяПараметра, СсылкиПоТипу.Значение); Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); Если ЗначениеЗаполнено(КодЯзыка) И КодЯзыка <> КодОсновногоЯзыка() И МодульМультиязычностьСервер.ОбъектСодержитТЧПредставления(ПолноеИмяОбъектаМетаданных) Тогда МультиязычныеРеквизиты = МодульМультиязычностьСервер.МультиязычныеРеквизитыОбъекта(ОбъектМетаданных); ПоляТаблиц = Новый Массив; ПоляТаблиц.Добавить(""ПсевдонимЗаданнойТаблицы.Ссылка""); Для Каждого Реквизит Из СтрРазделить(Реквизиты, "","") Цикл Если МультиязычныеРеквизиты[Реквизит] <> Неопределено Тогда Если МультиязычныеРеквизиты[Реквизит] = Истина Тогда ПолеРеквизита = ""ЕСТЬNULL(ТаблицаПредставления."" + Реквизит + "", """")""; Иначе СуффиксЯзыка = МодульМультиязычностьСервер.СуффиксЯзыка(КодЯзыка); ПолеРеквизита = ?(ЗначениеЗаполнено(СуффиксЯзыка), Реквизит + СуффиксЯзыка, Реквизит); КонецЕсли; ПоляТаблиц.Добавить(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(""%1 КАК %2"", ПолеРеквизита, Реквизит)); Иначе ПоляТаблиц.Добавить(Реквизит); КонецЕсли; КонецЦикла; ПоляТаблиц = СтрСоединить(ПоляТаблиц, "","" + Символы.ПС); Таблицы = ПолноеИмяОбъектаМетаданных + "" "" + ""КАК ПсевдонимЗаданнойТаблицы"" + Символы.ПС + ""ЛЕВОЕ СОЕДИНЕНИЕ"" + "" "" + ПолноеИмяОбъектаМетаданных + "".Представления КАК ТаблицаПредставления"" + Символы.ПС + ""ПО ТаблицаПредставления.Ссылка = ПсевдонимЗаданнойТаблицы.Ссылка И ТаблицаПредставления.КодЯзыка = &КодЯзыка""; ИмяПараметра = ""Ссылки"" + СтрЗаменить(ПолноеИмяОбъектаМетаданных, ""."", ""); Условия = ""ПсевдонимЗаданнойТаблицы.Ссылка В (&"" + ИмяПараметра + "")""; СтрокиЗапроса = Новый Массив; СтрокиЗапроса.Добавить(""ВЫБРАТЬ"" + ?(ВыбратьРазрешенные И Не ЗначениеЗаполнено(ТекстыЗапросов), "" "" + ""РАЗРЕШЕННЫЕ"", "")); // @Query-part-1, @Query-part-3 СтрокиЗапроса.Добавить(ПоляТаблиц); СтрокиЗапроса.Добавить(""ИЗ""); // @Query-part-1 СтрокиЗапроса.Добавить(Таблицы); СтрокиЗапроса.Добавить(""ГДЕ""); // @Query-part-1 СтрокиЗапроса.Добавить(Условия); ТекстЗапроса = СтрСоединить(СтрокиЗапроса, Символы.ПС); КонецЕсли; КонецЕсли; ТекстыЗапросов.Добавить(ТекстЗапроса); КонецЦикла; ТекстЗапроса = СтрСоединить(ТекстыЗапросов, Символы.ПС + ""ОБЪЕДИНИТЬ ВСЕ"" + Символы.ПС); Запрос = Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр(""КодЯзыка"", КодЯзыка); Для Каждого Параметр Из ПараметрыЗапроса Цикл Запрос.УстановитьПараметр(Параметр.Ключ, Параметр.Значение); КонецЦикла; Попытка Выборка = Запрос.Выполнить().Выбрать(); Исключение // Удаление пробелов. Реквизиты = СтрЗаменить(Реквизиты, "" "", ""); // Преобразование параметра в массив полей. Реквизиты = СтрРазделить(Реквизиты, "",""); // Поиск ошибки доступности полей. СписокОшибок = Новый Массив; Для Каждого ПолноеИмяОбъектаМетаданных Из ИменаОбъектовМетаданных Цикл Результат = ПроверитьСуществованиеРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, Реквизиты); Если Результат.Ошибка Тогда СписокОшибок.Добавить(Результат.ОписаниеОшибки); КонецЕсли; КонецЦикла; Если ЗначениеЗаполнено(СписокОшибок) Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: %3'""), ""Реквизиты"", ""ОбщегоНазначения.ЗначенияРеквизитовОбъектов"", СтрСоединить(СписокОшибок, Символы.ПС)); КонецЕсли; // Не удалось распознать ошибку, проброс первичной ошибки. ВызватьИсключение; КонецПопытки; Пока Выборка.Следующий() Цикл Результат = Новый Структура(Реквизиты); ЗаполнитьЗначенияСвойств(Результат, Выборка); ЗначенияРеквизитов[Выборка.Ссылка] = Результат; КонецЦикла; Возврат ЗначенияРеквизитов; КонецФункции // Возвращает значения реквизита, прочитанного из информационной базы для нескольких объектов. // Рекомендуется использовать вместо обращения к реквизитам объекта через точку от ссылки на объект // для быстрого чтения отдельных реквизитов объекта из базы данных. // // Если необходимо зачитать реквизит независимо от прав текущего пользователя, // то следует использовать предварительный переход в привилегированный режим. // // Если передано имя несуществующего реквизита, то вызывается исключение ""Поле объекта не существует"". // // Параметры: // МассивСсылок - Массив из ЛюбаяСсылка // - ФиксированныйМассив из ЛюбаяСсылка // ИмяРеквизита - Строка - например, ""Код"". // ВыбратьРазрешенные - Булево - если Истина, то запрос к объектам выполняется с учетом прав пользователя; // если какой-либо объект будет исключен из выборки по правам, то этот объект // будет исключен и из результата; // если Ложь, то возникнет исключение при отсутствии прав на таблицу // или любой из реквизитов. // КодЯзыка - Строка - код языка для мультиязычного реквизита. Значение по умолчанию - основной язык конфигурации. // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - ЛюбаяСсылка - ссылка на объект, // * Значение - Произвольный - значение прочитанного реквизита. // Функция ЗначениеРеквизитаОбъектов(МассивСсылок, ИмяРеквизита, ВыбратьРазрешенные = Ложь, Знач КодЯзыка = Неопределено) Экспорт Если ПустаяСтрока(ИмяРеквизита) Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неверный второй параметр %1 в функции %2: |Имя реквизита должно быть заполнено.'""), ""ИмяРеквизита"", ""ОбщегоНазначения.ЗначениеРеквизитаОбъектов""); КонецЕсли; ЗначенияРеквизитов = ЗначенияРеквизитовОбъектов(МассивСсылок, ИмяРеквизита, ВыбратьРазрешенные, КодЯзыка); Для каждого Элемент Из ЗначенияРеквизитов Цикл ЗначенияРеквизитов[Элемент.Ключ] = Элемент.Значение[ИмяРеквизита]; КонецЦикла; Возврат ЗначенияРеквизитов; КонецФункции // Добавляет или изменяет значение реквизита в объекте. // // Если передано имя несуществующего реквизита, то вызывается исключение. // // Параметры: // Объект - СправочникОбъект // - ДокументОбъект // - ПланВидовХарактеристикОбъект // - РегистрСведенийЗапись - заполняемый объект. // ИмяРеквизита - Строка - имя заполняемого реквизита. Например, ""Комментарий"" // Значение - Строка - значение помещаемое в реквизит. // КодЯзыка - Строка - код языка реквизита. Например, ""ru"". // Процедура УстановитьЗначениеРеквизита(Объект, ИмяРеквизита, Значение, КодЯзыка = Неопределено) Экспорт УстановитьЗначенияРеквизитов(Объект, Новый Структура(ИмяРеквизита, Значение), КодЯзыка); КонецПроцедуры // Добавляет или изменяет значения реквизитов в объекте. // // Если передано имя несуществующего реквизита, то вызывается исключение. // // Параметры: // Объект - СправочникОбъект // - ДокументОбъект // - ПланВидовХарактеристикОбъект // - РегистрСведенийЗапись - заполняемый объект. // Значения - Структура - где ключ это имя реквизита, а значение содержит строку помещаемую в реквизит. // КодЯзыка - Строка - код языка реквизита. Например, ""ru"". // Процедура УстановитьЗначенияРеквизитов(Объект, Значения, КодЯзыка = Неопределено) Экспорт Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); МодульМультиязычностьСервер.УстановитьЗначенияРеквизитов(Объект, Значения, КодЯзыка); Возврат; КонецЕсли; Для Каждого ЗначениеРеквизита Из Значения Цикл Значение = ЗначениеРеквизита.Значение; Если ТипЗнч(Значение) = Тип(""Строка"") И СтрокаВВидеНСтр(Значение) Тогда Значение = НСтр(ЗначениеРеквизита.Значение); КонецЕсли; Объект[ЗначениеРеквизита.Ключ] = Значение; КонецЦикла; КонецПроцедуры // Возвращает код основного языка информационной базы, например ""ru"". // На котором программно записываются автогенерируемые строки в информационную базу. // Например, при начальном заполнении информационной базы данными из макета, автогенерации комментария // к проводке или определении значения параметра ИмяСобытия метода ЗаписьЖурналаРегистрации. // // Возвращаемое значение: // Строка // Функция КодОсновногоЯзыка() Экспорт Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); Возврат МодульМультиязычностьСервер.КодОсновногоЯзыка(); КонецЕсли; Возврат Метаданные.ОсновнойЯзык.КодЯзыка; КонецФункции // Возвращает признак того, что для пользователя установлен язык интерфейса // соответствующий основному языку информационной базы. // // Возвращаемое значение: // Булево // Функция ЭтоОсновнойЯзык() Экспорт Возврат СтрСравнить(КодОсновногоЯзыка(), ТекущийЯзык().КодЯзыка) = 0; КонецФункции // Возвращает ссылку предопределенного элемента по его полному имени. // Предопределенные элементы могут содержаться только в следующих объектах: // - справочники; // - планы видов характеристик; // - планы счетов; // - планы видов расчета. // После изменения состава предопределенных следует выполнить метод // ОбновитьПовторноИспользуемыеЗначения(), который сбросит кэш ПовтИсп в текущем сеансе. // // Параметры: // ПолноеИмяПредопределенного - Строка - полный путь к предопределенному элементу, включая его имя. // Формат аналогичен функции глобального контекста ПредопределенноеЗначение(). // Например: // ""Справочник.ВидыКонтактнойИнформации.EmailПользователя"" // ""ПланСчетов.Хозрасчетный.Материалы"" // ""ПланВидовРасчета.Начисления.ОплатаПоОкладу"". // // Возвращаемое значение: // ЛюбаяСсылка - ссылка на предопределенный элемент. // Неопределено - если предопределенный элемент есть в метаданных, но не создан в ИБ. // Функция ПредопределенныйЭлемент(ПолноеИмяПредопределенного) Экспорт СтандартнаяОбработка = ОбщегоНазначенияСлужебныйКлиентСервер.ИспользоватьСтандартнуюФункциюПолученияПредопределенного( ПолноеИмяПредопределенного); Если СтандартнаяОбработка Тогда Возврат ПредопределенноеЗначение(ПолноеИмяПредопределенного); КонецЕсли; ПоляПредопределенного = ОбщегоНазначенияСлужебныйКлиентСервер.ИмяПредопределенногоПоПолям(ПолноеИмяПредопределенного); ПредопределенныеЗначения = СтандартныеПодсистемыПовтИсп.СсылкиПоИменамПредопределенных( ПоляПредопределенного.ПолноеИмяОбъектаМетаданных); Возврат ОбщегоНазначенияСлужебныйКлиентСервер.ПредопределенныйЭлемент( ПолноеИмяПредопределенного, ПоляПредопределенного, ПредопределенныеЗначения); КонецФункции // Возвращает информацию о том, являются ли переданные элементы предопределенными. // Если нет прав доступа на уровне записей, то элемент не включается в результат. // Если нет прав доступа к таблице, то вызывается исключение. // // Параметры: // Элементы - Массив из ЛюбаяСсылка // // Возвращаемое значение: // Соответствие из КлючИЗначение - список объектов и значений их реквизитов: // * Ключ - ЛюбаяСсылка - ссылка на объект. // * Значение - Булево - Истина, если это ссылка на предопределенный элемент. // Функция ЭтоПредопределенныеЭлементы(Знач Элементы) Экспорт ИменаРеквизитов = Новый Массив; Для каждого ИмяРеквизита Из СтандартныеПодсистемыСервер.РеквизитыПредопределенныхДанных() Цикл ИменаРеквизитов.Добавить(ИмяРеквизита.Ключ); КонецЦикла; ЗначенияРеквизитов = СтандартныеПодсистемыСервер.ЗначенияРеквизитовОбъектовЕслиСуществуют(Элементы, ИменаРеквизитов); Результат = Новый Соответствие; Для каждого Элемент Из ЗначенияРеквизитов Цикл ЭтоПредопределенныйЭлемент = Ложь; Для каждого Значение Из Элемент.Значение Цикл Если ЗначениеЗаполнено(Значение.Значение) Тогда ЭтоПредопределенныйЭлемент = Истина; КонецЕсли; КонецЦикла; Результат[Элемент.Ключ] = ЭтоПредопределенныйЭлемент; КонецЦикла; Возврат Результат; КонецФункции // Проверяет статус проведения переданных документов и возвращает // те из них, которые не проведены. // // Параметры: // Документы - Массив из ДокументСсылка - документы, статус проведения которых необходимо проверить. // // Возвращаемое значение: // Массив из ДокументСсылка - непроведенные документы. // Функция ПроверитьПроведенностьДокументов(Знач Документы) Экспорт Результат = Новый Массив; ШаблонЗапроса = ""ВЫБРАТЬ | ПсевдонимЗаданнойТаблицы.Ссылка КАК Ссылка |ИЗ | &ИмяДокумента КАК ПсевдонимЗаданнойТаблицы |ГДЕ | ПсевдонимЗаданнойТаблицы.Ссылка В(&МассивДокументов) | И НЕ ПсевдонимЗаданнойТаблицы.Проведен""; ТекстОбъединитьВсе = "" | |ОБЪЕДИНИТЬ ВСЕ | |""; ИменаДокументов = Новый Массив; Для Каждого Документ Из Документы Цикл МетаданныеДокумента = Документ.Метаданные(); Если ИменаДокументов.Найти(МетаданныеДокумента.ПолноеИмя()) = Неопределено И Метаданные.Документы.Содержит(МетаданныеДокумента) И МетаданныеДокумента.Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда ИменаДокументов.Добавить(МетаданныеДокумента.ПолноеИмя()); КонецЕсли; КонецЦикла; ТекстЗапроса = ""; Для Каждого ИмяДокумента Из ИменаДокументов Цикл Если Не ПустаяСтрока(ТекстЗапроса) Тогда ТекстЗапроса = ТекстЗапроса + ТекстОбъединитьВсе; КонецЕсли; ТекстПодзапроса = СтрЗаменить(ШаблонЗапроса, ""&ИмяДокумента"", ИмяДокумента); ТекстЗапроса = ТекстЗапроса + ТекстПодзапроса; КонецЦикла; Запрос = Новый Запрос; Запрос.Текст = ТекстЗапроса; Запрос.УстановитьПараметр(""МассивДокументов"", Документы); Если Не ПустаяСтрока(ТекстЗапроса) Тогда Результат = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(""Ссылка""); КонецЕсли; Возврат Результат; КонецФункции // Выполняет попытку проведения документов. // // Параметры: // Документы - Массив из ДокументСсылка - документы, которые необходимо провести. // // Возвращаемое значение: // Массив из Структура: // * Ссылка - ДокументСсылка - документ, который не удалось провести, // * ОписаниеОшибки - Строка - текст описания ошибки при проведении. // Функция ПровестиДокументы(Документы) Экспорт НепроведенныеДокументы = Новый Массив; Для Каждого ДокументСсылка Из Документы Цикл ВыполненоУспешно = Ложь; ДокументОбъект = ДокументСсылка.ПолучитьОбъект(); Если ДокументОбъект.ПроверитьЗаполнение() Тогда РежимПроведения = РежимПроведенияДокумента.Неоперативный; Если ДокументОбъект.Дата >= НачалоДня(ТекущаяДатаСеанса()) И ДокументСсылка.Метаданные().ОперативноеПроведение = Метаданные.СвойстваОбъектов.ОперативноеПроведение.Разрешить Тогда РежимПроведения = РежимПроведенияДокумента.Оперативный; КонецЕсли; Попытка ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение, РежимПроведения); ВыполненоУспешно = Истина; Исключение ПредставлениеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); КонецПопытки; Иначе ПредставлениеОшибки = НСтр(""ru = 'Поля документа не заполнены.'""); КонецЕсли; Если Не ВыполненоУспешно Тогда НепроведенныеДокументы.Добавить(Новый Структура(""Ссылка,ОписаниеОшибки"", ДокументСсылка, ПредставлениеОшибки)); КонецЕсли; КонецЦикла; Возврат НепроведенныеДокументы; КонецФункции // Проверяет наличие ссылок на объект в базе данных. // При вызове в неразделенном сеансе не выявляет ссылок в разделенных областях. // // Параметры: // СсылкаИлиМассивСсылок - ЛюбаяСсылка // - Массив из ЛюбаяСсылка - объект или список объектов. // ИскатьСредиСлужебныхОбъектов - Булево - если Истина, то не будут учитываться // исключения поиска ссылок, заданные при разработке конфигурации. // Про исключение поиска ссылок см. подробнее // ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок. // // Возвращаемое значение: // Булево - Истина, если есть ссылки на объект. // Функция ЕстьСсылкиНаОбъект(Знач СсылкаИлиМассивСсылок, Знач ИскатьСредиСлужебныхОбъектов = Ложь) Экспорт Если ТипЗнч(СсылкаИлиМассивСсылок) = Тип(""Массив"") Тогда МассивСсылок = СсылкаИлиМассивСсылок; Иначе МассивСсылок = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СсылкаИлиМассивСсылок); КонецЕсли; УстановитьПривилегированныйРежим(Истина); МестаИспользования = НайтиПоСсылкам(МассивСсылок); УстановитьПривилегированныйРежим(Ложь); Если Не ИскатьСредиСлужебныхОбъектов Тогда Для каждого Элемент Из СлужебныеСвязиДанных(МестаИспользования) Цикл МестаИспользования.Удалить(Элемент.Ключ); КонецЦикла; КонецЕсли; Возврат МестаИспользования.Количество() > 0; КонецФункции // Определяет, указаны ли места использования в исключениях поиска ссылок. // // Параметры: // МестаИспользования - ТаблицаЗначений - результат функции НайтиПоСсылкам: // * Ссылка - ЛюбаяСсылка - проверяемая ссылка. // * Данные - ЛюбаяСсылка - место использования. // * Метаданные - ОбъектМетаданных - метаданные места использования. // ИсключенияПоискаСсылок - см. ИсключенияПоискаСсылок // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - СтрокаТаблицыЗначений // * Значение - Булево - всегда Истина. Если это не служебная связь данных, то в соответствии нет элемента. // Функция СлужебныеСвязиДанных(Знач МестаИспользования, Знач ИсключенияПоискаСсылок = Неопределено) Экспорт Если ИсключенияПоискаСсылок = Неопределено Тогда ИсключенияПоискаСсылок = ИсключенияПоискаСсылок(); КонецЕсли; Результат = Новый Соответствие; МестоИспользованияПоМетаданным = Новый Соответствие; Для каждого МестоИспользования Из МестаИспользования Цикл ИсключениеПоиска = ИсключенияПоискаСсылок[МестоИспользования.Метаданные]; // Данные могут быть как ссылкой, так и ключом записи регистра. Если ИсключениеПоиска = Неопределено Тогда Если МестоИспользования.Ссылка = МестоИспользования.Данные Тогда Результат[МестоИспользования] = Истина; // Ссылку саму на себя исключаем. КонецЕсли; Продолжить; ИначеЕсли ИсключениеПоиска = ""*"" Тогда Результат[МестоИспользования] = Истина; // Если указано исключить все - считаем все исключением. Продолжить; КонецЕсли; ЭтоСсылка = ЭтоСсылка(ТипЗнч(МестоИспользования.Данные)); Если Не ЭтоСсылка Тогда Для Каждого ПутьКРеквизиту Из ИсключениеПоиска Цикл ЗначениеРеквизита = Новый Структура(ПутьКРеквизиту); ЗаполнитьЗначенияСвойств(ЗначениеРеквизита, МестоИспользования.Данные); Если ЗначениеРеквизита[ПутьКРеквизиту] = МестоИспользования.Ссылка Тогда Результат[МестоИспользования] = Истина; Прервать; КонецЕсли; КонецЦикла; Продолжить; КонецЕсли; Если ИсключениеПоиска.Количество() = 0 Тогда Продолжить; КонецЕсли; ИмяТаблицы = МестоИспользования.Метаданные.ПолноеИмя(); Значение = МестоИспользованияПоМетаданным[ИмяТаблицы]; Если Значение = Неопределено Тогда Значение = Новый ТаблицаЗначений; Значение.Колонки.Добавить(""Ссылка"", ОписаниеТипаВсеСсылки()); Значение.Колонки.Добавить(""Данные"", ОписаниеТипаВсеСсылки()); Значение.Колонки.Добавить(""Метаданные""); МестоИспользованияПоМетаданным[ИмяТаблицы] = Значение; КонецЕсли; ЗаполнитьЗначенияСвойств(Значение.Добавить(), МестоИспользования); КонецЦикла; Индекс = 1; Запрос = Новый Запрос; ТекстыЗапроса = Новый Массив; ВременныеТаблицы = Новый Массив; Для каждого МестоИспользования Из МестоИспользованияПоМетаданным Цикл ИмяТаблицы = МестоИспользования.Ключ; // Строка МестоИспользования = МестоИспользования.Значение; // ТаблицаЗначений // Проверка, есть ли по исключаемому пути в указанных данных проверяемая ссылка. Если МестоИспользования.Количество() > 1 Тогда ШаблонЗапроса = ""ВЫБРАТЬ | Ссылки.Данные КАК Ссылка, | Ссылки.Ссылка КАК ПроверяемаяСсылка |ПОМЕСТИТЬ ВТТаблицаСсылок |ИЗ | &Ссылки КАК Ссылки |; | |ВЫБРАТЬ | ТаблицаСсылок.Ссылка КАК Ссылка, | ТаблицаСсылок.ПроверяемаяСсылка КАК ПроверяемаяСсылка |ИЗ | ВТТаблицаСсылок КАК ТаблицаСсылок | ЛЕВОЕ СОЕДИНЕНИЕ #ПолноеИмяОбъектаМетаданных КАК Таблица | ПО ТаблицаСсылок.Ссылка = Таблица.Ссылка |ГДЕ | &Условие""; ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, ""#ПолноеИмяОбъектаМетаданных"", ИмяТаблицы); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""ВТТаблицаСсылок"", ""ВТТаблицаСсылок"" + Формат(Индекс, ""ЧГ=;ЧН="")); ИмяПараметра = ""Ссылки"" + Формат(Индекс, ""ЧГ=;ЧН=""); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&Ссылки"", ""&"" + ИмяПараметра); Запрос.УстановитьПараметр(ИмяПараметра, МестоИспользования); ЧастиЗапроса = СтрРазделить(ТекстЗапроса, "";""); ВременныеТаблицы.Добавить(ЧастиЗапроса[0]); ТекстЗапроса = ЧастиЗапроса[1]; Иначе ШаблонЗапроса = ""ВЫБРАТЬ | &СсылкаНаВладельца КАК Ссылка, | &ПроверяемаяСсылка КАК ПроверяемаяСсылка |ИЗ | #ПолноеИмяОбъектаМетаданных КАК Таблица |ГДЕ | Таблица.Ссылка = &СсылкаНаВладельца | И (&Условие)""; ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, ""#ПолноеИмяОбъектаМетаданных"", ИмяТаблицы); ИмяПараметра = ""СсылкаНаВладельца"" + Формат(Индекс, ""ЧГ=;ЧН=""); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&СсылкаНаВладельца"", ""&"" + ИмяПараметра); Запрос.УстановитьПараметр(ИмяПараметра, МестоИспользования[0].Данные); ИмяПараметра = ""ПроверяемаяСсылка"" + Формат(Индекс, ""ЧГ=;ЧН=""); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ПроверяемаяСсылка"", ""&"" + ИмяПараметра); Запрос.УстановитьПараметр(ИмяПараметра, МестоИспользования[0].Ссылка); КонецЕсли; ТекстУсловия = Новый Массив; // Относительный путь к реквизиту: ""<ИмяРеквизитаИлиТЧ>[.<ИмяРеквизитаТЧ>]"". Для Каждого ПутьКРеквизиту Из ИсключенияПоискаСсылок[МестоИспользования[0].Метаданные] Цикл ТекстУсловия.Добавить(ПутьКРеквизиту + "" = "" + ?(МестоИспользования.Количество() > 1, ""ТаблицаСсылок.ПроверяемаяСсылка"", ""&"" + ИмяПараметра)); КонецЦикла; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&Условие"", СтрСоединить(ТекстУсловия, "" ИЛИ "")); ТекстыЗапроса.Добавить(ТекстЗапроса); Индекс = Индекс + 1; КонецЦикла; Если ТекстыЗапроса.Количество() = 0 Тогда Возврат Результат; КонецЕсли; Запрос.Текст = СтрСоединить(ВременныеТаблицы, "";"" + Символы.ПС) + ?(ВременныеТаблицы.Количество() > 0, "";"" + Символы.ПС, "") + СтрСоединить(ТекстыЗапроса, Символы.ПС + ""ОБЪЕДИНИТЬ"" + Символы.ПС); УстановитьПривилегированныйРежим(Истина); ВыборкаЗапроса = Запрос.Выполнить().Выбрать(); УстановитьПривилегированныйРежим(Ложь); МестаИспользования.Индексы.Добавить(""Ссылка,Данные""); Пока ВыборкаЗапроса.Следующий() Цикл СлужебныеСвязиДанных = МестаИспользования.НайтиСтроки(Новый Структура(""Ссылка,Данные"", ВыборкаЗапроса.ПроверяемаяСсылка, ВыборкаЗапроса.Ссылка)); Для каждого СлужебнаяСвязьДанных Из СлужебныеСвязиДанных Цикл Результат[СлужебнаяСвязьДанных] = Истина; КонецЦикла; КонецЦикла; Возврат Результат; КонецФункции // Определяет, указано ли место использования в исключениях поиска ссылок. // // Параметры: // МестоИспользования - Структура: // * Ссылка - ЛюбаяСсылка - проверяемая ссылка. // * Данные - ЛюбаяСсылка - место использования. // * Метаданные - ОбъектМетаданных - метаданные места использования. // ИсключенияПоискаСсылок - см. ИсключенияПоискаСсылок // // Возвращаемое значение: // Булево // Функция ЭтоСлужебнаяСвязьДанных(Знач МестоИспользования, Знач ИсключенияПоискаСсылок = Неопределено) Экспорт Если ИсключенияПоискаСсылок = Неопределено Тогда ИсключенияПоискаСсылок = ИсключенияПоискаСсылок(); КонецЕсли; Значение = Новый ТаблицаЗначений; Значение.Колонки.Добавить(""Ссылка"", ОписаниеТипаВсеСсылки()); Значение.Колонки.Добавить(""Данные"", ОписаниеТипаВсеСсылки()); Значение.Колонки.Добавить(""Метаданные""); МестоИспользованияСтрока = Значение.Добавить(); ЗаполнитьЗначенияСвойств(МестоИспользованияСтрока, МестоИспользования); Результат = СлужебныеСвязиДанных(Значение, ИсключенияПоискаСсылок); Возврат Результат[МестоИспользованияСтрока] <> Неопределено; КонецФункции // Производит замену ссылок во всех данных. После замены неиспользуемые ссылки опционально удаляются. // Замена ссылок происходит с транзакциями по изменяемому объекту и его связям, не по анализируемой ссылке. // При вызове в неразделенном сеансе не выявляет ссылок в разделенных областях. // Если описаны связи подчиненных и основных объектов (см. СвязиПодчиненныхОбъектов), то: // * при замене основных объектов будет выполнен поиск замен подчиненных объектов; // * если ВыполнятьАвтоматическийПоискЗамен = Истина, то будет выполнена попытка поиска замен для подчиненных объектов // по значениям полей связи. В случае, если объект не существует, будет выполнена процедура ПриПоискеЗаменыСсылок; // * если МетодПоиска в описании связей задан, то если автоматический поиск не нашел замен // или не выполнялся, будет вызван МетодПоиска для подбора замен. // // Параметры: // ПарыЗамен - Соответствие из КлючИЗначение: // * Ключ - ЛюбаяСсылка - что ищем (дубль). // * Значение - ЛюбаяСсылка - на что заменяем (оригинал). // Ссылки сами на себя и пустые ссылки для поиска будут проигнорированы. // // ПараметрыЗамены - см. ОбщегоНазначения.ПараметрыЗаменыСсылок // // Возвращаемое значение: // ТаблицаЗначений - неуспешные замены (ошибки): // * Ссылка - ЛюбаяСсылка - ссылка, которую заменяли. // * ОбъектОшибки - Произвольный - объект-причина ошибки. // * ПредставлениеОбъектаОшибки - Строка - строковое представление объекта ошибки. // * ТипОшибки - Строка - тип ошибки: // ""ОшибкаБлокировки"" - при обработке ссылки некоторые объекты были заблокированы. // ""ДанныеИзменены"" - в процессе обработки данные были изменены другим пользователем. // ""ОшибкаЗаписи"" - не смогли записать объект, или метод ВозможностьЗаменыЭлементов вернул отказ. // ""ОшибкаУдаления"" - не смогли удалить объект. // ""НеизвестныеДанные"" - при обработке были найдены данные, которые не планировались к замене. // * ТекстОшибки - Строка - подробное описание ошибки. // Функция ЗаменитьСсылки(Знач ПарыЗамен, Знач ПараметрыЗамены = Неопределено) Экспорт Статистика = Новый Соответствие; ТипСтрока = Новый ОписаниеТипов(""Строка""); ОшибкиЗамены = Новый ТаблицаЗначений; ОшибкиЗамены.Колонки.Добавить(""Ссылка""); ОшибкиЗамены.Колонки.Добавить(""ОбъектОшибки""); ОшибкиЗамены.Колонки.Добавить(""ПредставлениеОбъектаОшибки"", ТипСтрока); ОшибкиЗамены.Колонки.Добавить(""ТипОшибки"", ТипСтрока); ОшибкиЗамены.Колонки.Добавить(""ТекстОшибки"", ТипСтрока); ОшибкиЗамены.Индексы.Добавить(""Ссылка""); ОшибкиЗамены.Индексы.Добавить(""Ссылка, ОбъектОшибки, ТипОшибки""); Результат = РезультатЗаменыСсылок(ОшибкиЗамены); ПараметрыВыполнения = НовыйПараметрыВыполненияЗаменыСсылок(ПараметрыЗамены); ПараметрыПоискаМестИспользования = ПараметрыПоискаМестИспользования(); ДополнитьИсключенияПоискаСсылокПодчиненнымиОбъектами(ПараметрыПоискаМестИспользования.ДополнительныеИсключенияПоискаСсылок); ПараметрыВыполнения.Вставить(""ПараметрыПоискаМестИспользования"", ПараметрыПоискаМестИспользования); ИнтеграцияПодсистемБСП.ПередПоискомМестИспользования(ПарыЗамен, ПараметрыВыполнения); Если ПарыЗамен.Количество() = 0 Тогда Возврат Результат.Ошибки; КонецЕсли; Дубли = СформироватьДубли(ПараметрыВыполнения, ПараметрыЗамены, ПарыЗамен, Результат); ТаблицаПоиска = МестаИспользования(Дубли,, ПараметрыВыполнения.ПараметрыПоискаМестИспользования); // Для каждой ссылки объекта будем производить замены в порядке ""Константа"", ""Объект"", ""Набор"". // Одновременно пустая строка в этой колонке - флаг того, что эта замена не нужна или уже была произведена. ТаблицаПоиска.Колонки.Добавить(""КлючЗамены"", ТипСтрока); ТаблицаПоиска.Индексы.Добавить(""Ссылка, КлючЗамены""); ТаблицаПоиска.Индексы.Добавить(""Данные, КлючЗамены""); // Вспомогательные данные ТаблицаПоиска.Колонки.Добавить(""ЦелеваяСсылка""); ТаблицаПоиска.Колонки.Добавить(""Обработано"", Новый ОписаниеТипов(""Булево"")); // Определяем порядок обработки и проверяем то, что можно обработать. ОшибкиРазметки = Новый Массив; ОбъектыСОшибками = Новый Массив; Количество = Дубли.Количество(); Для Номер = 1 По Количество Цикл ОбратныйИндекс = Количество - Номер; Дубль = Дубли[ОбратныйИндекс]; РезультатРазметки = РазметитьМестаИспользования(ПараметрыВыполнения, Дубль, ПарыЗамен[Дубль], ТаблицаПоиска); Если Не РезультатРазметки.Успех Тогда Дубли.Удалить(ОбратныйИндекс); Для Каждого Ошибка Из РезультатРазметки.ОшибкиРазметки Цикл Ошибка.Вставить(""Дубль"", Дубль); ОбъектыСОшибками.Добавить(Ошибка.Объект); КонецЦикла; ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ОшибкиРазметки, РезультатРазметки.ОшибкиРазметки); КонецЕсли; КонецЦикла; Если ОшибкиРазметки.Количество() > 0 Тогда ПредставленияОбъектов = ПредметыСтрокой(ОбъектыСОшибками); Для Каждого Ошибка Из ОшибкиРазметки Цикл ЗарегистрироватьОшибкуЗамены(Результат, Ошибка.Дубль, ОписаниеОшибкиЗамены(""НеизвестныеДанные"", Ошибка.Объект, ПредставленияОбъектов[Ошибка.Объект], Ошибка.Текст)); КонецЦикла; КонецЕсли; // Замена и удаление найденных дублей. ПараметрыВыполнения.Вставить(""ПарыЗамен"", ПарыЗамен); ПараметрыВыполнения.Вставить(""УспешныеЗамены"", Новый Соответствие); ОтключитьОбновлениеКлючейДоступа(Истина); Попытка КоличествоДублей = Дубли.Количество(); Номер = 1; Для Каждого Дубль Из Дубли Цикл БылиОшибки = Результат.ЕстьОшибки; Результат.ЕстьОшибки = Ложь; // @skip-check query-in-loop - Порционная обработка большого объема данных. ЗаменитьСсылкиКороткимиТранзакциями(Результат, ПараметрыВыполнения, Дубль, ТаблицаПоиска); Если НЕ Результат.ЕстьОшибки Тогда ПараметрыВыполнения.УспешныеЗамены.Вставить(Дубль, ПараметрыВыполнения.ПарыЗамен[Дубль]); КонецЕсли; Результат.ЕстьОшибки = Результат.ЕстьОшибки ИЛИ БылиОшибки; ДополнительныеПараметры = Новый Структура; ДополнительныеПараметры.Вставить(""НомерСеанса"", НомерСеансаИнформационнойБазы()); ДополнительныеПараметры.Вставить(""КоличествоОбработанных"", Номер); ДлительныеОперации.СообщитьПрогресс(Номер, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Замена дублей... обработано (%1 из %2)'""), Номер, КоличествоДублей), ДополнительныеПараметры); Номер = Номер + 1; ДобавитьВСтатистикуЗаменыСсылок(Статистика, Дубль, Результат.ЕстьОшибки); КонецЦикла; ОбщегоНазначенияПереопределяемый.ПослеЗаменыСсылок(Результат, ПараметрыВыполнения, ТаблицаПоиска); ОтключитьОбновлениеКлючейДоступа(Ложь); Исключение ОтключитьОбновлениеКлючейДоступа(Ложь); ВызватьИсключение; КонецПопытки; Если ПодсистемаСуществует(""СтандартныеПодсистемы.УдалениеПомеченныхОбъектов"") И ПараметрыВыполнения.УдалятьНепосредственно Тогда МодульУдалениеПомеченныхОбъектов = ОбщийМодуль(""УдалениеПомеченныхОбъектов""); ДлительныеОперации.СообщитьПрогресс(0, НСтр(""ru = 'Удаление дублей...'"")); РезультатУдаления = МодульУдалениеПомеченныхОбъектов.УдалитьПомеченныеОбъекты(Результат.ОчередьКНепосредственномуУдалению); ЗарегистрироватьОшибкиУдаления(Результат, РезультатУдаления.ПрепятствующиеУдалению); КонецЕсли; ОтправитьСтатистикуЗаменыСсылок(Статистика); Возврат Результат.Ошибки; КонецФункции // Конструктор структуры для параметра ПараметрыЗамены функции ОбщегоНазначения.ЗаменитьСсылки. // // Возвращаемое значение: // Структура: // * СпособУдаления - Строка - указывает, что делать с дублем после успешной замены: // "" - не предпринимать никаких действий (по умолчанию); // ""Пометка"" - помечать на удаление; // ""Непосредственно"" - удалять непосредственно. // * УчитыватьПрикладныеПравила - Булево - если Истина, то для каждой пары ""дубль-оригинал"" // вызывается функция ВозможностьЗаменыЭлементов модуля менеджера // (требуется подсистема ""Поиск и удаление дублей""). По умолчанию, Ложь. // * ВключатьБизнесЛогику - Булево - режим записи объектов при замене в них ссылок дублей на оригиналы. // Если Истина (по умолчанию), то места использования дублей записываются в обычном режиме, // иначе запись ведется в режиме ОбменДанными.Загрузка = Истина. // * ЗаменаПарыВТранзакции - Булево - устарел. определяет размер транзакции при замене дублей. // Если Истина (по умолчанию), то все места использования одного дубля заменяются в одной транзакции. // Это может быть очень ресурсоемко в случае большого количества мест использований. // Если Ложь, то замена в каждом месте использования выполняется в отдельной транзакции. // * ПривилегированнаяЗапись - Булево - если Истина, то устанавливать привилегированный режим перед запись // объектов при замене в них ссылок дублей на оригиналы. По умолчанию Ложь. // Функция ПараметрыЗаменыСсылок() Экспорт Результат = Новый Структура; Результат.Вставить(""СпособУдаления"", ""); Результат.Вставить(""УчитыватьПрикладныеПравила"", Ложь); Результат.Вставить(""ВключатьБизнесЛогику"", Истина); Результат.Вставить(""ЗаменаПарыВТранзакции"", Ложь); Результат.Вставить(""ПривилегированнаяЗапись"", Ложь); Возврат Результат; КонецФункции // Получает все места использования ссылок. // Если какая-либо ссылка нигде не используется, то строк для нее в результирующей таблице не будет. // При вызове в неразделенном сеансе не выявляет ссылок в разделенных областях. // // Параметры: // НаборСсылок - Массив из ЛюбаяСсылка - ссылки, для которых ищем места использования. // АдресРезультата - Строка - адрес во временном хранилище, куда будет помещен копия результата замены. // ДополнительныеПараметры - см. ОбщегоНазначения.ПараметрыПоискаМестИспользования // // Возвращаемое значение: // ТаблицаЗначений: // * Ссылка - ЛюбаяСсылка - ссылка, которая анализируется. // * Данные - Произвольный - данные, содержащие анализируемую ссылку. // * Метаданные - ОбъектМетаданных - метаданные найденных данных. // * ПредставлениеДанных - Строка - представление данных, содержащих анализируемую ссылку. // * ТипСсылки - Тип - тип анализируемой ссылки. // * ВспомогательныеДанные - Булево - Истина, если данные используются анализируемой ссылкой как // вспомогательные данные (ведущее измерение или попали в исключение ПриДобавленииИсключенийПоискаСсылок). // * ЭтоСлужебныеДанные - Булево - данные попали в исключение ПриДобавленииИсключенийПоискаСсылок // Функция МестаИспользования(Знач НаборСсылок, Знач АдресРезультата = "", ДополнительныеПараметры = Неопределено) Экспорт МестаИспользования = Новый ТаблицаЗначений; УстановитьПривилегированныйРежим(Истина); МестаИспользования = НайтиПоСсылкам(НаборСсылок); // см. МестаИспользования. УстановитьПривилегированныйРежим(Ложь); // МестаИспользования - ТаблицаЗначений - где: // * Ссылка - ЛюбаяСсылка - Ссылка, которая анализируется. // * Данные - Произвольный - Данные, содержащие анализируемую ссылку. // * Метаданные - ОбъектМетаданных - Метаданные найденных данных. МестаИспользования.Колонки.Добавить(""ПредставлениеДанных"", Новый ОписаниеТипов(""Строка"")); МестаИспользования.Колонки.Добавить(""ТипСсылки""); МестаИспользования.Колонки.Добавить(""ИнформацияОМестеИспользования""); МестаИспользования.Колонки.Добавить(""ВспомогательныеДанные"", Новый ОписаниеТипов(""Булево"")); МестаИспользования.Колонки.Добавить(""ЭтоСлужебныеДанные"", Новый ОписаниеТипов(""Булево"")); МестаИспользования.Индексы.Добавить(""Ссылка""); МестаИспользования.Индексы.Добавить(""Данные""); МестаИспользования.Индексы.Добавить(""ВспомогательныеДанные""); МестаИспользования.Индексы.Добавить(""Ссылка, ВспомогательныеДанные""); ТипКлючиЗаписей = ОписаниеТипаКлючиЗаписей(); ТипВсеСсылки = ОписаниеТипаВсеСсылки(); МетаданныеПоследовательностей = Метаданные.Последовательности; МетаданныеКонстант = Метаданные.Константы; МетаданныеДокументов = Метаданные.Документы; ИсключенияПоискаСсылок = ИсключенияПоискаСсылок(); ДополнительныеИсключенияПоискаСсылок = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры( ДополнительныеПараметры, ""ДополнительныеИсключенияПоискаСсылок"", Новый Соответствие); Для каждого МетаданныеРеквизитыИсключения Из ДополнительныеИсключенияПоискаСсылок Цикл ЗначениеИсключения = ИсключенияПоискаСсылок[МетаданныеРеквизитыИсключения.Ключ]; Если ЗначениеИсключения = Неопределено Тогда ИсключенияПоискаСсылок.Вставить(МетаданныеРеквизитыИсключения.Ключ, МетаданныеРеквизитыИсключения.Значение); Иначе Если ТипЗнч(ЗначениеИсключения) = Тип(""Массив"") Тогда ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ЗначениеИсключения, МетаданныеРеквизитыИсключения.Значение); КонецЕсли; КонецЕсли; КонецЦикла; ОтменаИсключенийПоискаСсылок = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ДополнительныеПараметры, ""ОтменаИсключенийПоискаСсылок"", Новый Массив); Для каждого ОтменаИсключения Из ОтменаИсключенийПоискаСсылок Цикл ИсключенияПоискаСсылок.Удалить(ОтменаИсключения); КонецЦикла; СлужебныеСвязиДанных = СлужебныеСвязиДанных(МестаИспользования, ИсключенияПоискаСсылок); КэшИзмеренийРегистров = Новый Соответствие; Для Каждого МестоИспользования Из МестаИспользования Цикл ТипДанных = ТипЗнч(МестоИспользования.Данные); ЭтоСлужебныеДанные = СлужебныеСвязиДанных[МестоИспользования] <> Неопределено; ЭтоВспомогательныеДанные = ЭтоСлужебныеДанные; Если ТипДанных = Неопределено Или МетаданныеДокументов.Содержит(МестоИспользования.Метаданные) Тогда Представление = Строка(МестоИспользования.Данные); ИначеЕсли МетаданныеКонстант.Содержит(МестоИспользования.Метаданные) Тогда Представление = МестоИспользования.Метаданные.Представление() + "" ("" + НСтр(""ru = 'константа'"") + "")""; ИначеЕсли МетаданныеПоследовательностей.Содержит(МестоИспользования.Метаданные) Тогда Представление = МестоИспользования.Метаданные.Представление() + "" ("" + НСтр(""ru = 'последовательность'"") + "")""; ИначеЕсли ТипВсеСсылки.СодержитТип(ТипДанных) Тогда МетаПредставлениеОбъекта = Новый Структура(""ПредставлениеОбъекта""); ЗаполнитьЗначенияСвойств(МетаПредставлениеОбъекта, МестоИспользования.Метаданные); Если ПустаяСтрока(МетаПредставлениеОбъекта.ПредставлениеОбъекта) Тогда МетаПредставление = МестоИспользования.Метаданные.Представление(); Иначе МетаПредставление = МетаПредставлениеОбъекта.ПредставлениеОбъекта; КонецЕсли; Представление = Строка(МестоИспользования.Данные); Если Не ПустаяСтрока(МетаПредставление) Тогда Представление = Представление + "" ("" + МетаПредставление + "")""; КонецЕсли; ИначеЕсли ТипКлючиЗаписей.СодержитТип(ТипДанных) Тогда Представление = МестоИспользования.Метаданные.ПредставлениеЗаписи; Если ПустаяСтрока(Представление) Тогда Представление = МестоИспользования.Метаданные.Представление(); КонецЕсли; ОписаниеИзмерений = Новый Массив; Для Каждого МетаданныеРеквизитыИсключения Из ОписаниеИзмеренийНабора(МестоИспользования.Метаданные, КэшИзмеренийРегистров) Цикл Значение = МестоИспользования.Данные[МетаданныеРеквизитыИсключения.Ключ]; Описание = МетаданныеРеквизитыИсключения.Значение; Если МестоИспользования.Ссылка = Значение Тогда Если Описание.Ведущее Тогда ЭтоВспомогательныеДанные = Истина; КонецЕсли; КонецЕсли; Если Не ЭтоСлужебныеДанные Тогда // для оптимизации ФорматЗначения = Описание.Формат; ОписаниеИзмерений.Добавить(Описание.Представление + "" """" + ?(ФорматЗначения = Неопределено, Строка(Значение), Формат(Значение, ФорматЗначения)) + """"); КонецЕсли; КонецЦикла; Если ОписаниеИзмерений.Количество() > 0 Тогда Представление = Представление + "" ("" + СтрСоединить(ОписаниеИзмерений, "", "") + "")""; КонецЕсли; Иначе Представление = Строка(МестоИспользования.Данные); КонецЕсли; МестоИспользования.ПредставлениеДанных = Представление; МестоИспользования.ВспомогательныеДанные = ЭтоВспомогательныеДанные; МестоИспользования.ЭтоСлужебныеДанные = ЭтоСлужебныеДанные; МестоИспользования.ТипСсылки = ТипЗнч(МестоИспользования.Ссылка); КонецЦикла; Если Не ПустаяСтрока(АдресРезультата) Тогда ПоместитьВоВременноеХранилище(МестаИспользования, АдресРезультата); КонецЕсли; Возврат МестаИспользования; КонецФункции // Возвращает структуру для параметра ДополнительныеПараметры функции ОбщегоНазначения.МестаИспользования. // // Возвращаемое значение: // Структура: // * ДополнительныеИсключенияПоискаСсылок - Соответствие - позволяет расширить исключения поиска ссылок // см. ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок // * ОтменаИсключенийПоискаСсылок - Массив из ОбъектМетаданных - полностью отменяет исключения поиска ссылок для // объектов метаданных. // Функция ПараметрыПоискаМестИспользования() Экспорт ПараметрыПоиска = Новый Структура; ПараметрыПоиска.Вставить(""ДополнительныеИсключенияПоискаСсылок"", Новый Соответствие); ПараметрыПоиска.Вставить(""ОтменаИсключенийПоискаСсылок"", Новый Соответствие); Возврат ПараметрыПоиска; КонецФункции // Возвращает исключения при поиске мест использования объектов. // // Возвращаемое значение: // Соответствие из КлючИЗначение - исключения поиска ссылок в разрезе объектов метаданных: // * Ключ - ОбъектМетаданных - объект метаданных, для которого применяются исключения. // * Значение - Строка // - Массив из Строка - описание исключенных реквизитов. // Если ""*"", то исключены все реквизиты объекта метаданных. // Если массив строк, то содержит относительные имена исключенных реквизитов. // Функция ИсключенияПоискаСсылок() Экспорт ИсключенияПоискаИнтеграция = Новый Массив; ИнтеграцияПодсистемБСП.ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоискаИнтеграция); ИсключенияПоиска = Новый Массив; ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ИсключенияПоиска, ИсключенияПоискаИнтеграция); ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоиска); Результат = Новый Соответствие; Для Каждого ИсключениеПоиска Из ИсключенияПоиска Цикл // Определение полного имени реквизита и объекта метаданных - носителя реквизита. Если ТипЗнч(ИсключениеПоиска) = Тип(""Строка"") Тогда ПолноеИмя = ИсключениеПоиска; МассивПодстрок = СтрРазделить(ПолноеИмя, "".""); КоличествоПодстрок = МассивПодстрок.Количество(); ОбъектМетаданных = ОбъектМетаданныхПоПолномуИмени(МассивПодстрок[0] + ""."" + МассивПодстрок[1]); Иначе ОбъектМетаданных = ИсключениеПоиска; ПолноеИмя = ОбъектМетаданных.ПолноеИмя(); МассивПодстрок = СтрРазделить(ПолноеИмя, "".""); КоличествоПодстрок = МассивПодстрок.Количество(); Если КоличествоПодстрок > 2 Тогда Пока Истина Цикл Родитель = ОбъектМетаданных.Родитель(); Если ТипЗнч(Родитель) = Тип(""ОбъектМетаданныхКонфигурация"") Тогда Прервать; Иначе ОбъектМетаданных = Родитель; КонецЕсли; КонецЦикла; КонецЕсли; КонецЕсли; // Регистрация. Если КоличествоПодстрок < 4 Тогда Результат.Вставить(ОбъектМетаданных, ""*""); Иначе ПутиКРеквизитам = Результат.Получить(ОбъектМетаданных); Если ПутиКРеквизитам = ""*"" Тогда Продолжить; // Весь объект метаданных уже исключен. ИначеЕсли ПутиКРеквизитам = Неопределено Тогда ПутиКРеквизитам = Новый Массив; Результат.Вставить(ОбъектМетаданных, ПутиКРеквизитам); КонецЕсли; // Формат реквизита: // ""<ВидОМ>.<ИмяОМ>.<ТипРеквизитаИлиТЧ>.<ИмяРеквизитаИлиТЧ>[.<ТипРеквизита>.<ИмяРеквизитаТЧ>]"". // Примеры: // ""РегистрСведений.ВерсииОбъектов.Реквизит.АвторВерсии"", // ""Документ._ДемоЗаказПокупателя.ТабличнаяЧасть.СчетаНаОплату.Реквизит.Счет"", // ""ПланВидовРасчета._ДемоОсновныеНачисления.СтандартнаяТабличнаяЧасть.БазовыеВидыРасчета.СтандартныйРеквизит.ВидРасчета"". // Относительный путь к реквизиту должен получиться таким, чтобы его можно было использовать в условиях запроса: // ""<ИмяРеквизитаИлиТЧ>[.<ИмяРеквизитаТЧ>]"". Если КоличествоПодстрок = 4 Тогда ОтносительныйПутьКРеквизиту = МассивПодстрок[3]; Иначе ОтносительныйПутьКРеквизиту = МассивПодстрок[3] + ""."" + МассивПодстрок[5]; КонецЕсли; ПутиКРеквизитам.Добавить(ОтносительныйПутьКРеквизиту); КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Возвращает связи подчиненных объектов и перечень реквизитов, по которым осуществляется связь. // // Есть возможность переопределить процедуру поиска подчиненных объектов. // Для этого в общем модуле или модуле менеджера необходимо реализовать процедуру // ПриПоискеЗаменыСсылок с параметрами: // ПарыЗамен - Соответствие - содержит пары значение оригинал/дубль. // НеобработанныеЗначенияОригиналов - Массив из Структура - дополнительная информация об обрабатываемых объектах: // * ЗаменяемоеЗначение - ПроизвольнаяСсылка - оригинальное значение заменяемого объекта. // * ИспользуемыеСвязи - см. ОбщегоНазначения.СвязиПодчиненныхОбъектовПоТипам // * ЗначениеКлючевыхРеквизитов - Структура - где Ключ - имя реквизита, значение - значение реквизита. // // Возвращаемое значение: // ТаблицаЗначений: // * ПодчиненныйОбъект - ОбъектМетаданных - объект метаданных подчиненного объекта. // * ПоляСвязей - Строка - имена реквизитов, определяющих связь между основными и подчиненными объектами. // * ПриПоискеЗаменыСсылок - Строка - опционально. Имя общего модуля или модуля менеджера, в котором определена // процедура ПриПоискеЗаменыСсылок. // * ВыполнятьАвтоматическийПоискЗаменСсылок - Булево - если указать Истина, то будет выполнена попытка поиска замен // для подчиненных объектов по значениям полей связи. В случае, если объект не существует, // будет выполнена процедура ПриПоискеЗаменыСсылок. См. также ЗаменитьСсылки. // Функция ПодчиненныеОбъекты() Экспорт ОписаниеСвязей = Новый ТаблицаЗначений; ОписаниеСвязей.Колонки.Добавить(""ПодчиненныйОбъект"", Новый ОписаниеТипов(""ОбъектМетаданных"")); ОписаниеСвязей.Колонки.Добавить(""ПоляСвязей""); ОписаниеСвязей.Колонки.Добавить(""ПриПоискеЗаменыСсылок"", ОписаниеТипаСтрока(0)); ОписаниеСвязей.Колонки.Добавить(""ВыполнятьАвтоматическийПоискЗаменСсылок"", Новый ОписаниеТипов(""Булево"")); ИнтеграцияПодсистемБСП.ПриОпределенииПодчиненныхОбъектов(ОписаниеСвязей); ОбщегоНазначенияПереопределяемый.ПриОпределенииПодчиненныхОбъектов(ОписаниеСвязей); // Если передали соответствие или структуру преобразуем к необходимому типу. Для каждого СтрокаСвязи Из ОписаниеСвязей Цикл ТипОписанияПолейСвязи = ТипЗнч(СтрокаСвязи.ПоляСвязей); Если ТипОписанияПолейСвязи = Тип(""Структура"") ИЛИ ТипОписанияПолейСвязи = Тип(""Соответствие"") Тогда ПоляСвязейСтрокой = ""; Для каждого КлючЗначение Из СтрокаСвязи.ПоляСвязей Цикл ПоляСвязейСтрокой = ПоляСвязейСтрокой + КлючЗначение.Ключ + "",""; КонецЦикла; СтроковыеФункцииКлиентСервер.УдалитьПоследнийСимволВСтроке(ПоляСвязейСтрокой,1); СтрокаСвязи.ПоляСвязей = ПоляСвязейСтрокой; КонецЕсли; Если ТипОписанияПолейСвязи = Тип(""Массив"") Тогда СтрокаСвязи.ПоляСвязей = СтрСоединить(СтрокаСвязи.ПоляСвязей, "",""); КонецЕсли; КонецЦикла; Возврат ОписаниеСвязей; КонецФункции // Возвращает связи подчиненных объектов с указанием типа поля связи. // // Возвращаемое значение: // ТаблицаЗначений: // * Ключ - Строка // * ТипРеквизита - Тип // * ИмяРеквизита - Строка // * Используется - Булево // * Метаданные - ОбъектМетаданных // Функция СвязиПодчиненныхОбъектовПоТипам() Экспорт Результат = Новый ТаблицаЗначений; Результат.Колонки.Добавить(""ТипРеквизита"", Новый ОписаниеТипов(""Тип"")); Результат.Колонки.Добавить(""ИмяРеквизита"", ОписаниеТипаСтрока(0)); Результат.Колонки.Добавить(""Ключ"", ОписаниеТипаСтрока(0)); Результат.Колонки.Добавить(""Используется"", Новый ОписаниеТипов(""Булево"")); Результат.Колонки.Добавить(""Метаданные""); Возврат Результат; КонецФункции #КонецОбласти #Область УсловныеВызовы //////////////////////////////////////////////////////////////////////////////// // Процедуры и функции для вызова необязательных подсистем. // Возвращает Истина, если функциональная подсистема существует в конфигурации. // Предназначена для реализации вызова необязательной подсистемы (условного вызова). // У функциональной подсистемы снят флажок ""Включать в командный интерфейс"". // См. также ОбщегоНазначенияПереопределяемый.ПриОпределенииОтключенныхПодсистем // и ОбщегоНазначенияКлиент.ПодсистемаСуществует для вызова из клиентского кода. // // Параметры: // ПолноеИмяПодсистемы - Строка - полное имя объекта метаданных подсистема // без слов ""Подсистема."" и с учетом регистра символов. // Например: ""СтандартныеПодсистемы.ВариантыОтчетов"". // // Пример: // Если ОбщегоНазначения.ПодсистемаСуществует(""СтандартныеПодсистемы.ВариантыОтчетов"") Тогда // МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль(""ВариантыОтчетов""); // МодульВариантыОтчетов.<Имя метода>(); // КонецЕсли; // // Возвращаемое значение: // Булево - Истина, если подсистема существует. // Функция ПодсистемаСуществует(ПолноеИмяПодсистемы) Экспорт ИменаПодсистем = СтандартныеПодсистемыПовтИсп.ИменаПодсистем(); Возврат ИменаПодсистем.Получить(ПолноеИмяПодсистемы) <> Неопределено; КонецФункции // Возвращает ссылку на общий модуль или модуль менеджера по имени. // // Параметры: // Имя - Строка - имя общего модуля. // // Возвращаемое значение: // ОбщийМодуль // МодульМенеджераОбъекта // // Пример: // Если ОбщегоНазначения.ПодсистемаСуществует(""СтандартныеПодсистемы.ОбновлениеКонфигурации"") Тогда // МодульОбновлениеКонфигурации = ОбщегоНазначения.ОбщийМодуль(""ОбновлениеКонфигурации""); // МодульОбновлениеКонфигурации.<Имя метода>(); // КонецЕсли; // // Если ОбщегоНазначения.ПодсистемаСуществует(""СтандартныеПодсистемы.ПолнотекстовыйПоиск"") Тогда // МодульПолнотекстовыйПоискСервер = ОбщегоНазначения.ОбщийМодуль(""ПолнотекстовыйПоискСервер""); // МодульПолнотекстовыйПоискСервер.<Имя метода>(); // КонецЕсли; // Функция ОбщийМодуль(Имя) Экспорт Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда // АПК:488-выкл ВычислитьВБезопасномРежиме не используется, чтобы избежать вызова ОбщийМодуль рекурсивно. УстановитьБезопасныйРежим(Истина); Модуль = Вычислить(Имя); // АПК:488-вкл ИначеЕсли СтрЧислоВхождений(Имя, ""."") = 1 Тогда Возврат СерверныйМодульМенеджера(Имя); Иначе Модуль = Неопределено; КонецЕсли; Если ТипЗнч(Модуль) <> Тип(""ОбщийМодуль"") Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Общий модуль ""%1"" не существует.'""), Имя); КонецЕсли; Возврат Модуль; КонецФункции #КонецОбласти #Область ТекущееОкружение //////////////////////////////////////////////////////////////////////////////// // Функции описания текущего окружения клиентского приложения и операционной системы. // Возвращает Истина, если клиентское приложение запущено под управлением ОС Windows. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоWindowsКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоWindowsКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоWindowsКлиент""); Если ЭтоWindowsКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоWindowsКлиент; КонецФункции // Возвращает Истина, если текущий сеанс выполняется на сервере, работающем под управлением ОС Windows. // // Возвращаемое значение: // Булево - Истина, если сервер работает под управлением ОС Windows. // Функция ЭтоWindowsСервер() Экспорт СистемнаяИнформация = Новый СистемнаяИнформация; Возврат СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Или СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64; КонецФункции // Возвращает Истина, если клиентское приложение запущено под управлением ОС Linux. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоLinuxКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоLinuxКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоLinuxКлиент""); Если ЭтоLinuxКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоLinuxКлиент; КонецФункции // Возвращает Истина, если текущий сеанс выполняется на сервере, работающем под управлением ОС Linux. // // Возвращаемое значение: // Булево - Истина, если сервер работает под управлением ОС Linux. // Функция ЭтоLinuxСервер() Экспорт СистемнаяИнформация = Новый СистемнаяИнформация; Возврат СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86 Или СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Или ОбщегоНазначенияКлиентСервер.СравнитьВерсии(СистемнаяИнформация.ВерсияПриложения, ""8.3.22.1923"") >= 0 И (СистемнаяИнформация.ТипПлатформы = ТипПлатформы[""Linux_ARM64""] Или СистемнаяИнформация.ТипПлатформы = ТипПлатформы[""Linux_E2K""]); КонецФункции // Возвращает Истина, если клиентское приложение запущено под управлением macОС. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоMacOSКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоMacOSКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоMacOSКлиент""); Если ЭтоMacOSКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоMacOSКлиент; КонецФункции // Возвращает Истина, если клиентское приложение является Веб-клиентом. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоВебКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоВебКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоВебКлиент""); Если ЭтоВебКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоВебКлиент; КонецФункции // Возвращает Истина, если клиентское приложение является мобильным клиентом. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоМобильныйКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоМобильныйКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоМобильныйКлиент""); Если ЭтоМобильныйКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоМобильныйКлиент; КонецФункции // Возвращает Истина, если клиентское приложение подключено к базе через веб-сервер. // // Возвращаемое значение: // Булево - Истина, если подключен. // Функция КлиентПодключенЧерезВебСервер() Экспорт УстановитьПривилегированныйРежим(Истина); СтрокаСоединенияИнформационнойБазы = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""СтрокаСоединенияИнформационнойБазы""); Если СтрокаСоединенияИнформационнойБазы = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат СтрНайти(ВРег(СтрокаСоединенияИнформационнойБазы), ""WS="") = 1; КонецФункции // Возвращает системную информацию клиента, если есть клиентское приложение. // До первого серверного вызова с клиента вернет Неопределено. // // Возвращаемое значение: // ФиксированнаяСтруктура: // * ВерсияОС - Строка // * ВерсияПриложения - Строка // * ИдентификаторКлиента - УникальныйИдентификатор // * ИнформацияПрограммыПросмотра - Строка // * ОперативнаяПамять - Число // * Процессор - Строка // * ТипПлатформы - см. ОбщегоНазначенияКлиентСервер.ИмяТипаПлатформы // Неопределено - если нет клиентского приложения или информация запрашивается // до первого серверного вызова, например, при первом вызове события // платформы УстановкаПараметровСеанса в модуле сеанса. // Функция СистемнаяИнформацияКлиента() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""СистемнаяИнформация""); КонецФункции // Возвращает имя используемого клиента, а для веб-браузера название и версию, если есть. // До первого серверного вызова с клиента вернет Неопределено. // // Возвращаемое значение: // Строка - варианты строк ""ВебКлиент.<Название>[.<Версия>]"", ""ТонкийКлиент"", // ""ТолстыйКлиентУправляемоеПриложение"", ""ТолстыйКлиентОбычноеПриложение"", // где <Название> - варианты строк ""Chrome"", ""Firefox"", ""Safari"", ""IE"", ""Opera"" // или ""Другой"", когда не определен (ни один из указанных), например ""ВебКлиент.Chrome.109"". // Неопределено - если нет клиентского приложения или информация запрашивается // до первого серверного вызова, например, при первом вызове события // платформы УстановкаПараметровСеанса в модуле сеанса. // Функция ИспользуемыйКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ИспользуемыйКлиент""); КонецФункции // Возвращает Истина, если включен режим отладки. // // Возвращаемое значение: // Булево - Истина, если включен режим отладки. // Функция РежимОтладки() Экспорт ПараметрЗапускаПриложения = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере(Ложь).Получить(""ПараметрЗапуска""); Возврат СтрНайти(ПараметрЗапускаПриложения, ""РежимОтладки"") > 0; КонецФункции // Возвращает объем оперативной памяти, доступной клиентскому приложению. // // Возвращаемое значение: // Число - количество гигабайтов оперативной памяти с точностью до десятых долей. // Неопределено - нет клиентского приложения, то есть ТекущийРежимЗапуска() = Неопределено. // Функция ОперативнаяПамятьДоступнаяКлиентскомуПриложению() Экспорт ДоступныйОбъем = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ОперативнаяПамять""); Возврат ДоступныйОбъем; КонецФункции // Определяет режим эксплуатации информационной базы файловый (Истина) или серверный (Ложь). // При проверке используется СтрокаСоединенияИнформационнойБазы, которую можно указать явно. // // Параметры: // СтрокаСоединенияИнформационнойБазы - Строка - параметр используется, если // нужно проверить строку соединения не текущей информационной базы. // // Возвращаемое значение: // Булево - Истина, если файловая. // Функция ИнформационнаяБазаФайловая(Знач СтрокаСоединенияИнформационнойБазы = "") Экспорт Если ПустаяСтрока(СтрокаСоединенияИнформационнойБазы) Тогда СтрокаСоединенияИнформационнойБазы = СтрокаСоединенияИнформационнойБазы(); КонецЕсли; Возврат СтрНайти(ВРег(СтрокаСоединенияИнформационнойБазы), ""FILE="") = 1; КонецФункции // Возвращает Истина, если эта информационная база подключена к 1С:Fresh. // // Возвращаемое значение: // Булево - признак автономного рабочего места. // Функция ЭтоАвтономноеРабочееМесто() Экспорт Если ПодсистемаСуществует(""СтандартныеПодсистемы.ОбменДанными"") Тогда МодульОбменДаннымиСервер = ОбщийМодуль(""ОбменДаннымиСервер""); Возврат МодульОбменДаннымиСервер.ЭтоАвтономноеРабочееМесто(); КонецЕсли; Возврат Ложь; КонецФункции // Возвращает признак того, что информационная база является распределенной (РИБ). // // Возвращаемое значение: // Булево // Функция ЭтоРаспределеннаяИнформационнаяБаза() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат СтандартныеПодсистемыПовтИсп.ИспользуетсяРИБ(); КонецФункции // Определяет, что эта информационная база является подчиненным узлом // распределенной информационной базы (РИБ). // // Возвращаемое значение: // Булево - Истина, если эта информационная база является подчиненным узлом РИБ. // Функция ЭтоПодчиненныйУзелРИБ() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат ПланыОбмена.ГлавныйУзел() <> Неопределено; КонецФункции // Определяет, что эта информационная база является подчиненным узлом // распределенной информационной базы (РИБ) с фильтром. // // Возвращаемое значение: // Булево - Истина, если эта информационная база является подчиненным узлом РИБ с фильтром. // Функция ЭтоПодчиненныйУзелРИБСФильтром() Экспорт УстановитьПривилегированныйРежим(Истина); Если ПланыОбмена.ГлавныйУзел() <> Неопределено И ПодсистемаСуществует(""СтандартныеПодсистемы.ОбменДанными"") Тогда МодульОбменДаннымиСервер = ОбщийМодуль(""ОбменДаннымиСервер""); Если МодульОбменДаннымиСервер.НазначениеПланаОбмена(ПланыОбмена.ГлавныйУзел().Метаданные().Имя) = ""РИБСФильтром"" Тогда Возврат Истина; КонецЕсли; КонецЕсли; Возврат Ложь; КонецФункции // Возвращает Истина при необходимости обновления конфигурации информационной базы подчиненного узла РИБ. // В главном узле всегда Ложь. // // Возвращаемое значение: // Булево - Истина, если требуется. // Функция ТребуетсяОбновлениеКонфигурацииПодчиненногоУзлаРИБ() Экспорт Возврат ЭтоПодчиненныйУзелРИБ() И КонфигурацияИзменена(); КонецФункции // Возвращает признак работы в режиме разделения данных по областям // (технически это признак условного разделения). // // Возвращает Ложь, если конфигурация не может работать в режиме разделения данных // (не содержит общих реквизитов, предназначенных для разделения данных). // // Возвращаемое значение: // Булево - Истина, если разделение включено, // Ложь, если разделение выключено или не поддерживается. // Функция РазделениеВключено() Экспорт Возврат СтандартныеПодсистемыПовтИсп.РазделениеВключено(); КонецФункции // Возвращает признак возможности обращения к разделенным данным (которые входят в состав разделителей). // Признак относится к сеансу, но может меняться во время работы сеанса, если разделение было включено // в самом сеансе, поэтому проверку следует делать непосредственно перед обращением к разделенным данным. // // Возвращает Истина, если конфигурация не может работать в режиме разделения данных // (не содержит общих реквизитов, предназначенных для разделения данных). // // Возвращаемое значение: // Булево - Истина, если разделение не поддерживается, либо разделение выключено, // либо разделение включено и разделители установлены. // Ложь, если разделение включено и разделители не установлены. // Функция ДоступноИспользованиеРазделенныхДанных() Экспорт Возврат СтандартныеПодсистемыПовтИсп.ДоступноИспользованиеРазделенныхДанных(); КонецФункции // Возвращает адрес публикации информационной базы для формирования прямых ссылок на объекты ИБ // для возможности перехода к ним пользователей, имеющих доступ к базе через публикацию в сети Интернет. // Например, если такой адрес включить в электронное письмо, то из письма одним нажатием // можно перейти к форме объекта в самой программе. // // Возвращаемое значение: // Строка - адрес информационной базы, как он задан в настройке ""Адрес в Интернете"" в панели администрирования // (хранится в константе АдресПубликацииИнформационнойБазыВИнтернете). // Например, ""http://1c.com/database"". // // Пример: // ОбщегоНазначения.АдресПубликацииИнформационнойБазыВЛокальнойСети() + ""/"" + e1cib/app/Обработка.ВыгрузкаДанныхПроекта""; // возвращает прямую ссылку для открытия обработки ВыгрузкаДанныхПроекта. // Функция АдресПубликацииИнформационнойБазыВИнтернете() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат Константы.АдресПубликацииИнформационнойБазыВИнтернете.Получить(); КонецФункции // Возвращает адрес публикации информационной базы для формирования прямых ссылок на объекты ИБ // для возможности перехода к ним пользователей, имеющих доступ к базе через публикацию локальной сети. // Например, если такой адрес включить в электронное письмо, то из письма за одно нажатие // можно перейти к форме объекта в самой программе. // // Возвращаемое значение: // Строка - адрес информационной базы, как он задан в настройке ""Локальный адрес"" в панели администрирования // (хранится в константе АдресПубликацииИнформационнойБазыВЛокальнойСети). // Например, ""http://localserver/base"". // // Пример: // ОбщегоНазначения.АдресПубликацииИнформационнойБазыВЛокальнойСети() + ""/"" + e1cib/app/Обработка.ВыгрузкаДанныхПроекта""; // возвращает прямую ссылку для открытия обработки ВыгрузкаДанныхПроекта. // Функция АдресПубликацииИнформационнойБазыВЛокальнойСети() Экспорт УстановитьПривилегированныйРежим(Истина); Возврат Константы.АдресПубликацииИнформационнойБазыВЛокальнойСети.Получить(); КонецФункции // Формирует ссылку для входа в программу для указанного пользователя. // // Параметры: // Пользователь - Строка - логин пользователя для входа в программу; // Пароль - Строка - пароль пользователя для входа в программу; // ВидПубликацииИБ - Строка - через какую публикацию пользователь входит в программу: // ""ВИнтернете"" или ""ВЛокальнойСети"". // // Возвращаемое значение: // Строка, Неопределено - адрес входа в программу или Неопределено, если адрес не настроен. // Функция АдресВходаВПрограмму(Пользователь, Пароль, ВидПубликацииИБ) Экспорт Результат = ""; Если НРег(ВидПубликацииИБ) = НРег(""ВИнтернете"") Тогда Результат = АдресПубликацииИнформационнойБазыВИнтернете(); ИначеЕсли НРег(ВидПубликацииИБ) = НРег(""ВЛокальнойСети"") Тогда Результат = АдресПубликацииИнформационнойБазыВЛокальнойСети(); КонецЕсли; Если ПустаяСтрока(Результат) Тогда Возврат Неопределено; КонецЕсли; Если Не СтрЗаканчиваетсяНа(Результат, ""/"") Тогда Результат = Результат + ""/""; КонецЕсли; Результат = Результат + ""?n="" + КодироватьСтроку(Пользователь, СпособКодированияСтроки.КодировкаURL); Если ЗначениеЗаполнено(Пароль) Тогда Результат = Результат + ""&p="" + КодироватьСтроку(Пароль, СпособКодированияСтроки.КодировкаURL); КонецЕсли; Возврат Результат; КонецФункции // Возвращает редакцию конфигурации. // Редакцией принято называть две первые группы цифр полной версии конфигурации. // Например, у версии ""1.2.3.4"" редакция ""1.2"". // // Возвращаемое значение: // Строка - номер редакции конфигурации. // Функция РедакцияКонфигурации() Экспорт Результат = ""; ВерсияКонфигурации = Метаданные.Версия; Позиция = СтрНайти(ВерсияКонфигурации, "".""); Если Позиция > 0 Тогда Результат = Лев(ВерсияКонфигурации, Позиция); ВерсияКонфигурации = Сред(ВерсияКонфигурации, Позиция + 1); Позиция = СтрНайти(ВерсияКонфигурации, "".""); Если Позиция > 0 Тогда Результат = Результат + Лев(ВерсияКонфигурации, Позиция - 1); Иначе Результат = ""; КонецЕсли; КонецЕсли; Если ПустаяСтрока(Результат) Тогда Результат = Метаданные.Версия; КонецЕсли; Возврат Результат; КонецФункции // Общие параметры подсистемы. // // См. ОбщегоНазначенияПереопределяемый.ПриОпределенииОбщихПараметровБазовойФункциональности // // Возвращаемое значение: // Структура: // * ИмяФормыПерсональныхНастроек - Строка - имя формы для редактирования персональных настроек. // * ЗапрашиватьПодтверждениеПриЗавершенииПрограммы - Булево - по умолчанию Истина. Если установить в Ложь, то // подтверждение при завершении работы программы не // будет запрашиваться, если явно не разрешить в // персональных настройках программы. // * МинимальнаяВерсияПлатформы - Строка - минимальная версии платформы, требуемая для запуска программы. // Запуск программы на версии платформы ниже указанной будет невозможен. // Например, ""8.3.6.1650"". // * РекомендуемаяВерсияПлатформы - Строка - рекомендуемая версия платформы для запуска программы. // Например, ""8.3.8.2137"". // * ОтключитьИдентификаторыОбъектовМетаданных - Булево - отключает заполнение справочников ИдентификаторыОбъектовМетаданных // и ИдентификаторыОбъектовРасширений, процедуру выгрузки и загрузки в узлах РИБ. // Для частичного встраивания отдельных функций библиотеки в конфигурации без постановки на поддержку. // * РекомендуемыйОбъемОперативнойПамяти - Число - объем памяти в гигабайтах, рекомендуемый для комфортной работы в // программе. // Устарели, следует использовать свойства МинимальнаяВерсияПлатформы и РекомендуемаяВерсияПлатформы: // * МинимальноНеобходимаяВерсияПлатформы - Строка - полный номер версии платформы для запуска программы. // Например, ""8.3.4.365"". // * РаботаВПрограммеЗапрещена - Булево - начальное значение Ложь. // Функция ОбщиеПараметрыБазовойФункциональности() Экспорт ОбщиеПараметры = Новый Структура; ОбщиеПараметры.Вставить(""ИмяФормыПерсональныхНастроек"", ""); ОбщиеПараметры.Вставить(""ЗапрашиватьПодтверждениеПриЗавершенииПрограммы"", Истина); ОбщиеПараметры.Вставить(""ОтключитьИдентификаторыОбъектовМетаданных"", Ложь); ОбщиеПараметры.Вставить(""РекомендуемыйОбъемОперативнойПамяти"", 4); ОбщиеПараметры.Вставить(""МинимальнаяВерсияПлатформы"", МинимальнаяВерсияПлатформы()); ОбщиеПараметры.Вставить(""РекомендуемаяВерсияПлатформы"", ОбщиеПараметры.МинимальнаяВерсияПлатформы); // Устарело, следует использовать свойства МинимальнаяВерсияПлатформы и РекомендуемаяВерсияПлатформы: ОбщиеПараметры.Вставить(""МинимальноНеобходимаяВерсияПлатформы"", ""); ОбщиеПараметры.Вставить(""РаботаВПрограммеЗапрещена"", Ложь); // Блокировать запуск, если версия ниже минимальной. ОбщегоНазначенияПереопределяемый.ПриОпределенииОбщихПараметровБазовойФункциональности(ОбщиеПараметры); ОбщиеПараметры.МинимальнаяВерсияПлатформы = НомерСборкиПоТекущейВерсииПлатформы(ОбщиеПараметры.МинимальнаяВерсияПлатформы); ОбщиеПараметры.РекомендуемаяВерсияПлатформы = НомерСборкиПоТекущейВерсииПлатформы(ОбщиеПараметры.РекомендуемаяВерсияПлатформы); // Локализация УточнитьМинимальнуюВерсиюПлатформыИзСервиса(ОбщиеПараметры); // Конец Локализация СистемнаяИнформация = Новый СистемнаяИнформация; Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(СистемнаяИнформация.ВерсияПриложения, ОбщиеПараметры.МинимальнаяВерсияПлатформы) < 0 И ЭтоВерсияЗащищенногоПрограммногоКомплекса(СистемнаяИнформация.ВерсияПриложения) Тогда ОбщиеПараметры.МинимальнаяВерсияПлатформы = СистемнаяИнформация.ВерсияПриложения; ОбщиеПараметры.РекомендуемаяВерсияПлатформы = СистемнаяИнформация.ВерсияПриложения; КонецЕсли; Минимальная = ОбщиеПараметры.МинимальнаяВерсияПлатформы; Рекомендуемая = ОбщиеПараметры.РекомендуемаяВерсияПлатформы; Если МинимальнаяИРекомендуемаяВерсияПлатформыЗаполненаНеПравильно(Минимальная, Рекомендуемая) Тогда ТекстСообщения = НСтр(""ru = 'Указанные в %1 минимальная и рекомендуемая версии платформы не соответствуют следующим требованиям: | - минимальная версия должна быть заполнена; | - минимальная версия не должна быть меньше минимальной версии БСП (см. %2); | - минимальная версия не должна быть меньше рекомендуемой версии. |Минимальная версия: %3 |Минимальная версия БСП: %4 |Рекомендуемая версия: %5'"", КодОсновногоЯзыка()); ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСообщения, ""ОбщегоНазначенияПереопределяемый.ПриОпределенииОбщихПараметровБазовойФункциональности"", ""ОбщегоНазначения.МинимальнаяВерсияПлатформы"", Минимальная, НомерСборкиПоТекущейВерсииПлатформы(МинимальнаяВерсияПлатформы()), Рекомендуемая); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Базовая функциональность'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Предупреждение,,, ТекстСообщения); КонецЕсли; // Обратная совместимость. МинимальноНеобходимаяВерсияПлатформы = ОбщиеПараметры.МинимальноНеобходимаяВерсияПлатформы; Если ЗначениеЗаполнено(МинимальноНеобходимаяВерсияПлатформы) Тогда Если ОбщиеПараметры.РаботаВПрограммеЗапрещена Тогда ОбщиеПараметры.МинимальнаяВерсияПлатформы = МинимальноНеобходимаяВерсияПлатформы; ОбщиеПараметры.РекомендуемаяВерсияПлатформы = ""; Иначе ОбщиеПараметры.РекомендуемаяВерсияПлатформы = МинимальноНеобходимаяВерсияПлатформы; ОбщиеПараметры.МинимальнаяВерсияПлатформы = ""; КонецЕсли; Иначе Текущая = СистемнаяИнформация.ВерсияПриложения; Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Минимальная, Текущая) > 0 Тогда ОбщиеПараметры.МинимальноНеобходимаяВерсияПлатформы = Минимальная; ОбщиеПараметры.РаботаВПрограммеЗапрещена = Истина; Иначе ОбщиеПараметры.МинимальноНеобходимаяВерсияПлатформы = Рекомендуемая; ОбщиеПараметры.РаботаВПрограммеЗапрещена = Ложь; КонецЕсли; КонецЕсли; УточнитьВерсиюПлатформы(ОбщиеПараметры); Возврат ОбщиеПараметры; КонецФункции // Возвращает описания всех библиотек конфигурации, включая // описание самой конфигурации. // // Возвращаемое значение: // Массив - структур со свойствами: // * Имя - Строка - имя подсистемы, например, ""СтандартныеПодсистемы"". // * ИдентификаторИнтернетПоддержки - Строка - уникальное имя программы в сервисах интернет-поддержки. // * Версия - Строка - версия в формате из четырех цифр, например ""2.3.3.1"". // * ЭтоКонфигурация - Булево - признак того, что данная подсистема является основной конфигурацией. // Функция ОписанияПодсистем() Экспорт Результат = Новый Массив; ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем(); Для Каждого ОписаниеПодсистемы Из ОписанияПодсистем.ПоИменам Цикл Параметры = Новый Структура; Параметры.Вставить(""Имя""); Параметры.Вставить(""ИдентификаторИнтернетПоддержки""); Параметры.Вставить(""Версия""); Параметры.Вставить(""ЭтоКонфигурация""); ЗаполнитьЗначенияСвойств(Параметры, ОписаниеПодсистемы.Значение); Результат.Добавить(Параметры); КонецЦикла; Возврат Результат; КонецФункции // Возвращает идентификатор Интернет-поддержки основной конфигурации. // // Возвращаемое значение: // Строка - уникальное имя программы в сервисах Интернет-поддержки. // Функция ИдентификаторИнтернетПоддержкиКонфигурации() Экспорт ОписанияПодсистем = СтандартныеПодсистемыПовтИсп.ОписанияПодсистем(); Для Каждого ОписаниеПодсистемы Из ОписанияПодсистем.ПоИменам Цикл Если ОписаниеПодсистемы.Значение.ЭтоКонфигурация Тогда Возврат ОписаниеПодсистемы.Значение.ИдентификаторИнтернетПоддержки; КонецЕсли; КонецЦикла; Возврат ""; КонецФункции #КонецОбласти #Область Даты //////////////////////////////////////////////////////////////////////////////// // Функции для работы с датами с учетом часового пояса сеанса // Преобразует локальную дату к формату ""YYYY-MM-DDThh:mm:ssTZD"" согласно ISO 8601. // // Параметры: // ЛокальнаяДата - Дата - дата в часовом поясе сеанса. // // Возвращаемое значение: // Строка - представление даты. // Функция ПредставлениеЛокальнойДатыСоСмещением(ЛокальнаяДата) Экспорт Смещение = СмещениеСтандартногоВремени(ЧасовойПоясСеанса()); Возврат ОбщегоНазначенияСлужебныйКлиентСервер.ПредставлениеЛокальнойДатыСоСмещением(ЛокальнаяДата, Смещение); КонецФункции // Возвращает строковое представление интервала между переданными датами или // относительно переданной даты и текущей даты сеанса. // // Параметры: // ВремяНачала - Дата - начальная точка интервала. // ВремяОкончания - Дата - конечная точка интервала, если не задана - берется текущая дата сеанса. // // Возвращаемое значение: // Строка - представление интервала времени. // Функция ИнтервалВремениСтрокой(ВремяНачала, ВремяОкончания = Неопределено) Экспорт Если ВремяОкончания = Неопределено Тогда ВремяОкончания = ТекущаяДатаСеанса(); ИначеЕсли ВремяНачала > ВремяОкончания Тогда ВызватьИсключение НСтр(""ru = 'Дата окончания интервала не может быть меньше даты начала.'""); КонецЕсли; ВеличинаИнтервала = ВремяОкончания - ВремяНачала; ВеличинаИнтервалаВДнях = Цел(ВеличинаИнтервала/60/60/24); Если ВеличинаИнтервалаВДнях > 365 Тогда ОписаниеИнтервала = НСтр(""ru = 'более года'""); ИначеЕсли ВеличинаИнтервалаВДнях > 31 Тогда ОписаниеИнтервала = НСтр(""ru = 'более месяца'""); ИначеЕсли ВеличинаИнтервалаВДнях >= 1 Тогда ОписаниеИнтервала = Формат(ВеличинаИнтервалаВДнях, ""ЧДЦ=0"") + "" "" + ПользователиСлужебныйКлиентСервер.ПредметЦелогоЧисла(ВеличинаИнтервалаВДнях, "", НСтр(""ru = 'день,дня,дней,,,,,,0'"")); Иначе ОписаниеИнтервала = НСтр(""ru = 'менее одного дня'""); КонецЕсли; Возврат ОписаниеИнтервала; КонецФункции //////////////////////////////////////////////////////////////////////////////// // Функции для работы с настройкой рабочей даты. // Сохраняет настройку рабочей даты пользователя. // // Параметры: // НоваяРабочаяДата - Дата - дата, которую необходимо установить в качестве рабочей даты пользователя. // ИмяПользователя - Строка - имя пользователя, для которого устанавливается рабочая дата. // Если не задано, то устанавливается для текущего пользователя. // Процедура УстановитьРабочуюДатуПользователя(НоваяРабочаяДата, ИмяПользователя = Неопределено) Экспорт КлючОбъекта = ВРег(""РабочаяДата""); ХранилищеОбщихНастроекСохранить(КлючОбъекта, "", НоваяРабочаяДата, , ИмяПользователя); КонецПроцедуры // Возвращает значение настройки рабочей даты для пользователя. // // Параметры: // ИмяПользователя - Строка - имя пользователя, для которого запрашивается рабочая дата. // Если не задано, то устанавливается для текущего пользователя. // // Возвращаемое значение: // Дата - значение настройки рабочей даты пользователя или пустая дата, если настройка не задана. // Функция РабочаяДатаПользователя(ИмяПользователя = Неопределено) Экспорт КлючОбъекта = ВРег(""РабочаяДата""); Результат = ХранилищеОбщихНастроекЗагрузить(КлючОбъекта, "", '0001-01-01', , ИмяПользователя); Если ТипЗнч(Результат) <> Тип(""Дата"") Тогда Результат = '0001-01-01'; КонецЕсли; Возврат Результат; КонецФункции // Возвращает значение настройки рабочей даты для пользователя или текущей даты сеанса, // если рабочая дата пользователя не задана. // // Параметры: // ИмяПользователя - Строка - имя пользователя, для которого запрашивается рабочая дата. // Если не задано, то устанавливается для текущего пользователя. // // Возвращаемое значение: // Дата - значение настройки рабочей даты пользователя или текущая дата сеанса, если настройка не задана. // Функция ТекущаяДатаПользователя(ИмяПользователя = Неопределено) Экспорт Результат = РабочаяДатаПользователя(ИмяПользователя); Если НЕ ЗначениеЗаполнено(Результат) Тогда Результат = ТекущаяДатаСеанса(); КонецЕсли; Возврат НачалоДня(Результат); КонецФункции #КонецОбласти #Область Данные //////////////////////////////////////////////////////////////////////////////// // Общие процедуры и функции для работы с прикладными типами и коллекциями значений. // Возвращает строковое имя значения перечисления по его ссылке. // Вызывает исключение, если передано несуществующее значение перечисления // (например, удаленное в конфигурации или от отключенного расширения конфигурации). // // Параметры: // Значение - ПеречислениеСсылка - значение, для которого необходимо получить имя перечисления. // // Возвращаемое значение: // Строка // // Пример: // В результат будет помещено строковое значение ""ФизическоеЛицо"": // Результат = ОбщегоНазначения.ИмяЗначенияПеречисления(Перечисления.ЮридическоеФизическоеЛицо.ФизическоеЛицо); // Функция ИмяЗначенияПеречисления(Значение) Экспорт ОбъектМетаданных = Значение.Метаданные(); ИндексЗначения = Перечисления[ОбъектМетаданных.Имя].Индекс(Значение); Возврат ОбъектМетаданных.ЗначенияПеречисления[ИндексЗначения].Имя; КонецФункции // Процедура удаляет из массива МассивРеквизитов элементы, соответствующие именам // реквизитов объекта из массива МассивНепроверяемыхРеквизитов. // Для использования в обработчиках события ОбработкаПроверкиЗаполнения. // // Параметры: // МассивРеквизитов - Массив - коллекция имен реквизитов объекта. // МассивНепроверяемыхРеквизитов - Массив - коллекция имен реквизитов объекта, не требующих проверки. // Процедура УдалитьНепроверяемыеРеквизитыИзМассива(МассивРеквизитов, МассивНепроверяемыхРеквизитов) Экспорт Для Каждого ЭлементМассива Из МассивНепроверяемыхРеквизитов Цикл ПорядковыйНомер = МассивРеквизитов.Найти(ЭлементМассива); Если ПорядковыйНомер <> Неопределено Тогда МассивРеквизитов.Удалить(ПорядковыйНомер); КонецЕсли; КонецЦикла; КонецПроцедуры // Преобразует таблицу значений в массив структур. // Может использоваться для передачи на клиент данных в том случае, если таблица // значений содержит только такие значения, которые могут // быть переданы с сервера на клиент. // // Полученный массив содержит структуры, каждая из которых повторяет // структуру колонок таблицы значений. // // Не рекомендуется использовать для преобразования таблиц значений // с большим количеством строк. // // Параметры: // ТаблицаЗначений - ТаблицаЗначений - исходная таблица значений. // // Возвращаемое значение: // Массив - коллекция строк таблицы в виде структур. // Функция ТаблицаЗначенийВМассив(ТаблицаЗначений) Экспорт Массив = Новый Массив(); СтруктураСтрокой = ""; НужнаЗапятая = Ложь; Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл Если НужнаЗапятая Тогда СтруктураСтрокой = СтруктураСтрокой + "",""; КонецЕсли; СтруктураСтрокой = СтруктураСтрокой + Колонка.Имя; НужнаЗапятая = Истина; КонецЦикла; Для Каждого Строка Из ТаблицаЗначений Цикл НоваяСтрока = Новый Структура(СтруктураСтрокой); ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка); Массив.Добавить(НоваяСтрока); КонецЦикла; Возврат Массив; КонецФункции // Преобразует строку таблицы значений в структуру. // Свойства структуры и их значения совпадают с колонками переданной строки. // // Параметры: // СтрокаТаблицыЗначений - СтрокаТаблицыЗначений // // Возвращаемое значение: // Структура - преобразованная строка таблицы значений. // Функция СтрокаТаблицыЗначенийВСтруктуру(СтрокаТаблицыЗначений) Экспорт Структура = Новый Структура; Для каждого Колонка Из СтрокаТаблицыЗначений.Владелец().Колонки Цикл Структура.Вставить(Колонка.Имя, СтрокаТаблицыЗначений[Колонка.Имя]); КонецЦикла; Возврат Структура; КонецФункции // Создает структуру, содержащую имена и значения измерений, ресурсов и реквизитов // переданного менеджера записи регистра сведений. // // Параметры: // МенеджерЗаписи - РегистрСведенийМенеджерЗаписиИмяРегистраСведений - менеджер записи, из которого надо получить структуру. // МетаданныеРегистра - ОбъектМетаданныхРегистрСведений - метаданные регистра сведений. // // Возвращаемое значение: // Структура - коллекция измерений ресурсов и реквизитов, переданного менеджеру записи. // Функция СтруктураПоМенеджеруЗаписи(МенеджерЗаписи, МетаданныеРегистра) Экспорт ЗаписьКакСтруктура = Новый Структура; Если МетаданныеРегистра.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда ЗаписьКакСтруктура.Вставить(""Период"", МенеджерЗаписи.Период); КонецЕсли; Для Каждого Поле Из МетаданныеРегистра.Измерения Цикл ЗаписьКакСтруктура.Вставить(Поле.Имя, МенеджерЗаписи[Поле.Имя]); КонецЦикла; Для Каждого Поле Из МетаданныеРегистра.Ресурсы Цикл ЗаписьКакСтруктура.Вставить(Поле.Имя, МенеджерЗаписи[Поле.Имя]); КонецЦикла; Для Каждого Поле Из МетаданныеРегистра.Реквизиты Цикл ЗаписьКакСтруктура.Вставить(Поле.Имя, МенеджерЗаписи[Поле.Имя]); КонецЦикла; Возврат ЗаписьКакСтруктура; КонецФункции // Создает массив и копирует в него значения, содержащиеся в колонке объекта, для // которого доступен обход посредством оператора Для каждого … Из. // // Параметры: // КоллекцияСтрок - ТаблицаЗначений // - ДеревоЗначений // - СписокЗначений // - ТабличнаяЧасть // - Соответствие // - Структура - коллекция, колонку которой нужно выгрузить в массив. // А так же другие объекты, для которых доступен обход // посредством оператора Для каждого … Из … Цикл. // ИмяКолонки - Строка - имя поля коллекции, значения которого нужно выгрузить. // ТолькоУникальныеЗначения - Булево - если Истина, то в массив будут включены // только различающиеся значения. // // Возвращаемое значение: // Массив - значения колонки. // Функция ВыгрузитьКолонку(КоллекцияСтрок, ИмяКолонки, ТолькоУникальныеЗначения = Ложь) Экспорт МассивЗначений = Новый Массив; УникальныеЗначения = Новый Соответствие; Для каждого СтрокаКоллекции Из КоллекцияСтрок Цикл Значение = СтрокаКоллекции[ИмяКолонки]; Если ТолькоУникальныеЗначения И УникальныеЗначения[Значение] <> Неопределено Тогда Продолжить; КонецЕсли; МассивЗначений.Добавить(Значение); УникальныеЗначения.Вставить(Значение, Истина); КонецЦикла; Возврат МассивЗначений; КонецФункции // Преобразует текст указанного формата XML в таблицу значений, // при этом колонки таблицы формируются на основе описания в XML. // // Схема XML: // <?xml version=""1.0"" encoding=""utf-8""?> // <xs:schema attributeFormDefault=""unqualified"" elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema""> // <xs:element name=""Items""> // <xs:complexType> // <xs:sequence> // <xs:element maxOccurs=""unbounded"" name=""Item""> // <xs:complexType> // <xs:attribute name=""Code"" type=""xs:integer"" use=""required"" /> // <xs:attribute name=""Name"" type=""xs:string"" use=""required"" /> // <xs:attribute name=""Socr"" type=""xs:string"" use=""required"" /> // <xs:attribute name=""Index"" type=""xs:string"" use=""required"" /> // </xs:complexType> // </xs:element> // </xs:sequence> // <xs:attribute name=""Description"" type=""xs:string"" use=""required"" /> // <xs:attribute name=""Columns"" type=""xs:string"" use=""required"" /> // </xs:complexType> // </xs:element> // </xs:schema> // // Параметры: // XML - Строка // - ЧтениеXML - текст в формате XML или ЧтениеXML. // // Возвращаемое значение: // Структура: // * ИмяТаблицы - Строка - имя таблицы. // * Данные - ТаблицаЗначений - преобразованная из XML таблица. // // Пример: // КлассификаторТаблица = ОбщегоНазначения.ПрочитатьXMLВТаблицу( // Обработки.ЗагрузкаКурсовВалют.ПолучитьМакет(""ОбщероссийскийКлассификаторВалют"").ПолучитьТекст()).Данные; // Функция ПрочитатьXMLВТаблицу(Знач XML) Экспорт Если ТипЗнч(XML) <> Тип(""ЧтениеXML"") Тогда Чтение = Новый ЧтениеXML; Чтение.УстановитьСтроку(XML); Иначе Чтение = XML; КонецЕсли; // Прочитаем первый узел и проверим его. Если Не Чтение.Прочитать() Тогда ВызватьИсключение НСтр(""ru = 'Пустой XML'""); ИначеЕсли Чтение.Имя <> ""Items"" Тогда ВызватьИсключение НСтр(""ru = 'Ошибка в структуре XML'""); КонецЕсли; // Получим описание таблицы и создадим ее. ИмяТаблицы = Чтение.ПолучитьАтрибут(""Description""); ИменаКолонок = СтрЗаменить(Чтение.ПолучитьАтрибут(""Columns""), "","", Символы.ПС); Колонок = СтрЧислоСтрок(ИменаКолонок); ТаблицаЗначений = Новый ТаблицаЗначений; Для Сч = 1 По Колонок Цикл ТаблицаЗначений.Колонки.Добавить(СтрПолучитьСтроку(ИменаКолонок, Сч), Новый ОписаниеТипов(""Строка"")); КонецЦикла; // Заполним значения в таблице. Пока Чтение.Прочитать() Цикл Если Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента И Чтение.Имя = ""Items"" Тогда Прервать; ИначеЕсли Чтение.ТипУзла <> ТипУзлаXML.НачалоЭлемента Тогда Продолжить; ИначеЕсли Чтение.Имя <> ""Item"" Тогда ВызватьИсключение НСтр(""ru = 'Ошибка в структуре XML'""); КонецЕсли; новСтр = ТаблицаЗначений.Добавить(); Для Сч = 1 По Колонок Цикл ИмяКолонки = СтрПолучитьСтроку(ИменаКолонок, Сч); новСтр[Сч-1] = Чтение.ПолучитьАтрибут(ИмяКолонки); КонецЦикла; КонецЦикла; // Заполним результат Результат = Новый Структура; Результат.Вставить(""ИмяТаблицы"", ИмяТаблицы); Результат.Вставить(""Данные"", ТаблицаЗначений); Возврат Результат; КонецФункции // Сравнивает две коллекции строк (ТаблицаЗначений, ДеревоЗначений и т.д.), // для которых доступен обход посредством оператора Для каждого … Из … Цикл. // Сравниваемые коллекции должны отвечать следующим требованиям: // - доступен обход посредством оператора Для каждого … Из … Цикл, // - наличие в обеих коллекциях всех колонок, перечисленных в параметре ИменаКолонок // (если ИменаКолонок не заполнен - все колонки первой коллекции должны существовать во второй коллекции). // Также позволяет сравнивать массивы. // // Параметры: // КоллекцияСтрок1 - ТаблицаЗначений // - ДеревоЗначений // - СписокЗначений // - ТабличнаяЧасть // - Соответствие // - Массив // - ФиксированныйМассив // - Структура - коллекция, отвечающая вышеописанным требованиям. А также другие // объекты, для которых доступен обход посредством оператора Для каждого … Из … Цикл. // КоллекцияСтрок2 - ТаблицаЗначений // - ДеревоЗначений // - СписокЗначений // - ТабличнаяЧасть // - Соответствие // - Массив // - ФиксированныйМассив // - Структура - коллекция, отвечающая вышеописанным требованиям. А также другие // объекты, для которых доступен обход посредством оператора Для каждого … Из … Цикл. // ИменаКолонок - Строка - имена колонок через запятую, по которым производится сравнение. // Не обязательно для коллекций, состав колонок которых можно определить автоматически: // ТаблицаЗначений, СписокЗначений, Соответствие, Структура. // Если не указан, то сравнение производится по колонкам первой коллекции. // Для коллекций других типов является обязательным. // ИсключаяКолонки - Строка - имена колонок, которые игнорируются при сравнении. // УчитыватьПоследовательностьСтрок - Булево - если Истина, то коллекции признаются // идентичными, только если одинаковые строки размещены в коллекциях на одинаковых местах. // // Возвращаемое значение: // Булево - Истина, если идентичны. // Функция КоллекцииИдентичны(КоллекцияСтрок1, КоллекцияСтрок2, Знач ИменаКолонок = "", Знач ИсключаяКолонки = "", УчитыватьПоследовательностьСтрок = Ложь) Экспорт ТипКоллекции = ТипЗнч(КоллекцияСтрок1); СравниваютсяМассивы = (ТипКоллекции = Тип(""Массив"") Или ТипКоллекции = Тип(""ФиксированныйМассив"")); СравниваемыеКолонки = Неопределено; Если Не СравниваютсяМассивы Тогда СравниваемыеКолонки = СравниваемыеКолонки(КоллекцияСтрок1, ИменаКолонок, ИсключаяКолонки); КонецЕсли; Если УчитыватьПоследовательностьСтрок Тогда Возврат СравнитьСУчетомПоследовательности(КоллекцияСтрок1, КоллекцияСтрок2, СравниваемыеКолонки); ИначеЕсли СравниваютсяМассивы Тогда // Для массивов используется более простой алгоритм. Возврат СравнитьМассивы(КоллекцияСтрок1, КоллекцияСтрок2); Иначе Возврат СравнитьБезУчетаПоследовательности(КоллекцияСтрок1, КоллекцияСтрок2, СравниваемыеКолонки); КонецЕсли; КонецФункции // Сравнивает данные сложной структуры с учетом вложенности. // // Параметры: // Данные1 - Структура // - ФиксированнаяСтруктура // - Соответствие // - ФиксированноеСоответствие // - Массив // - ФиксированныйМассив // - ХранилищеЗначения // - ТаблицаЗначений // - Строка // - Число // - Булево - сравниваемые данные. // Данные2 - Произвольный - те же типы, что и для параметра Данные1. // // Возвращаемое значение: // Булево - Истина, если совпадают. // Функция ДанныеСовпадают(Данные1, Данные2) Экспорт Если ТипЗнч(Данные1) <> ТипЗнч(Данные2) Тогда Возврат Ложь; КонецЕсли; Если ТипЗнч(Данные1) = Тип(""Структура"") ИЛИ ТипЗнч(Данные1) = Тип(""ФиксированнаяСтруктура"") Тогда Если Данные1.Количество() <> Данные2.Количество() Тогда Возврат Ложь; КонецЕсли; Для каждого КлючИЗначение Из Данные1 Цикл СтароеЗначение = Неопределено; Если НЕ Данные2.Свойство(КлючИЗначение.Ключ, СтароеЗначение) ИЛИ НЕ ДанныеСовпадают(КлючИЗначение.Значение, СтароеЗначение) Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Возврат Истина; ИначеЕсли ТипЗнч(Данные1) = Тип(""Соответствие"") ИЛИ ТипЗнч(Данные1) = Тип(""ФиксированноеСоответствие"") Тогда Если Данные1.Количество() <> Данные2.Количество() Тогда Возврат Ложь; КонецЕсли; КлючиНовогоСоответствия = Новый Соответствие; Для каждого КлючИЗначение Из Данные1 Цикл КлючиНовогоСоответствия.Вставить(КлючИЗначение.Ключ, Истина); СтароеЗначение = Данные2.Получить(КлючИЗначение.Ключ); Если НЕ ДанныеСовпадают(КлючИЗначение.Значение, СтароеЗначение) Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Для каждого КлючИЗначение Из Данные2 Цикл Если КлючиНовогоСоответствия[КлючИЗначение.Ключ] = Неопределено Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Возврат Истина; ИначеЕсли ТипЗнч(Данные1) = Тип(""Массив"") ИЛИ ТипЗнч(Данные1) = Тип(""ФиксированныйМассив"") Тогда Если Данные1.Количество() <> Данные2.Количество() Тогда Возврат Ложь; КонецЕсли; Индекс = Данные1.Количество()-1; Пока Индекс >= 0 Цикл Если НЕ ДанныеСовпадают(Данные1.Получить(Индекс), Данные2.Получить(Индекс)) Тогда Возврат Ложь; КонецЕсли; Индекс = Индекс - 1; КонецЦикла; Возврат Истина; ИначеЕсли ТипЗнч(Данные1) = Тип(""ТаблицаЗначений"") Тогда Если Данные1.Количество() <> Данные2.Количество() Тогда Возврат Ложь; КонецЕсли; Если Данные1.Колонки.Количество() <> Данные2.Колонки.Количество() Тогда Возврат Ложь; КонецЕсли; Для каждого Колонка Из Данные1.Колонки Цикл Если Данные2.Колонки.Найти(Колонка.Имя) = Неопределено Тогда Возврат Ложь; КонецЕсли; Индекс = Данные1.Количество()-1; Пока Индекс >= 0 Цикл Если НЕ ДанныеСовпадают(Данные1[Индекс][Колонка.Имя], Данные2[Индекс][Колонка.Имя]) Тогда Возврат Ложь; КонецЕсли; Индекс = Индекс - 1; КонецЦикла; КонецЦикла; Возврат Истина; ИначеЕсли ТипЗнч(Данные1) = Тип(""ХранилищеЗначения"") Тогда Если НЕ ДанныеСовпадают(Данные1.Получить(), Данные2.Получить()) Тогда Возврат Ложь; КонецЕсли; Возврат Истина; КонецЕсли; Возврат Данные1 = Данные2; КонецФункции // Фиксирует данные типов Структура, Соответствие, Массив с учетом вложенности. // // Параметры: // Данные - Структура // - Соответствие // - Массив - коллекции, значения которых являются примитивными типами, // хранилищем значения или не могут быть изменены. Поддерживаются типы значений: // Булево, Строка, Число, Дата, Неопределено, УникальныйИдентификатор, Null, Тип, // ХранилищеЗначения, ОбщийМодуль, ОбъектМетаданных, ТипЗначенияXDTO, ТипОбъектаXDTO, // ЛюбаяСсылка. // // ВызыватьИсключение - Булево - начальное значение Истина. Когда установлено Ложь, тогда в случае наличия // нефиксируемых данных исключение не будет вызвано, при этом данные будут // зафиксированы на сколько возможно. // // Возвращаемое значение: // ФиксированнаяСтруктура, ФиксированноеСоответствие, ФиксированныйМассив - фиксированные данные, аналогичные // переданным в параметре Данные. // Функция ФиксированныеДанные(Данные, ВызыватьИсключение = Истина) Экспорт Если ТипЗнч(Данные) = Тип(""Массив"") Тогда Массив = Новый Массив; Для каждого Значение Из Данные Цикл Если ТипЗнч(Значение) = Тип(""Структура"") ИЛИ ТипЗнч(Значение) = Тип(""Соответствие"") ИЛИ ТипЗнч(Значение) = Тип(""Массив"") Тогда Массив.Добавить(ФиксированныеДанные(Значение, ВызыватьИсключение)); Иначе Если ВызыватьИсключение Тогда ПроверкаФиксированностиДанных(Значение, Истина); КонецЕсли; Массив.Добавить(Значение); КонецЕсли; КонецЦикла; Возврат Новый ФиксированныйМассив(Массив); ИначеЕсли ТипЗнч(Данные) = Тип(""Структура"") ИЛИ ТипЗнч(Данные) = Тип(""Соответствие"") Тогда Если ТипЗнч(Данные) = Тип(""Структура"") Тогда Коллекция = Новый Структура; Иначе Коллекция = Новый Соответствие; КонецЕсли; Для каждого КлючИЗначение Из Данные Цикл Значение = КлючИЗначение.Значение; Если ТипЗнч(Значение) = Тип(""Структура"") ИЛИ ТипЗнч(Значение) = Тип(""Соответствие"") ИЛИ ТипЗнч(Значение) = Тип(""Массив"") Тогда Коллекция.Вставить( КлючИЗначение.Ключ, ФиксированныеДанные(Значение, ВызыватьИсключение)); Иначе Если ВызыватьИсключение Тогда ПроверкаФиксированностиДанных(Значение, Истина); КонецЕсли; Коллекция.Вставить(КлючИЗначение.Ключ, Значение); КонецЕсли; КонецЦикла; Если ТипЗнч(Данные) = Тип(""Структура"") Тогда Возврат Новый ФиксированнаяСтруктура(Коллекция); Иначе Возврат Новый ФиксированноеСоответствие(Коллекция); КонецЕсли; ИначеЕсли ВызыватьИсключение Тогда ПроверкаФиксированностиДанных(Данные); КонецЕсли; Возврат Данные; КонецФункции // Вычисляет контрольную сумму для произвольных данных по указанному алгоритму. // // Параметры: // Данные - Произвольный - любое сериализуемое значение. // Алгоритм - ХешФункция - алгоритм расчета контрольной суммы. По умолчанию, MD5. // // Возвращаемое значение: // Строка - контрольная сумма строкой без пробелов (например 32 символа). // Функция КонтрольнаяСуммаСтрокой(Знач Данные, Знач Алгоритм = Неопределено) Экспорт Если Алгоритм = Неопределено Тогда Алгоритм = ХешФункция.MD5; КонецЕсли; ХешированиеДанных = Новый ХешированиеДанных(Алгоритм); Если ТипЗнч(Данные) <> Тип(""Строка"") И ТипЗнч(Данные) <> Тип(""ДвоичныеДанные"") Тогда Данные = ЗначениеВСтрокуXML(Данные); КонецЕсли; ХешированиеДанных.Добавить(Данные); Если ТипЗнч(ХешированиеДанных.ХешСумма) = Тип(""ДвоичныеДанные"") Тогда Результат = СтрЗаменить(ХешированиеДанных.ХешСумма, "" "", ""); ИначеЕсли ТипЗнч(ХешированиеДанных.ХешСумма) = Тип(""Число"") Тогда Результат = Формат(ХешированиеДанных.ХешСумма, ""ЧГ=""); КонецЕсли; Возврат Результат; КонецФункции // Сокращает строку до нужной длины, при этом обрезанная часть хешируется, // обеспечивая уникальность строки. Проверяет длину строки на входе и, в случае // превышения максимальной длины, преобразует ее конец по алгоритму MD5 в // уникальную строку из 32 символов. // // Параметры: // Строка - Строка - исходная строка произвольной длины. // МаксимальнаяДлина - Число - требуемое максимальное количество символов в строке, // минимальное значение: 32. // // Возвращаемое значение: // Строка - строка, не превышающая максимальную длину. // Функция СократитьСтрокуКонтрольнойСуммой(Строка, МаксимальнаяДлина) Экспорт Если МаксимальнаяДлина < 32 Тогда ОбщегоНазначенияКлиентСервер.Проверить(Ложь, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Параметр %1 не может быть меньше 32.'""), ""МаксимальнаяДлина""), ""ОбщегоНазначения.СократитьСтрокуКонтрольнойСуммой""); КонецЕсли; Результат = Строка; Если СтрДлина(Строка) > МаксимальнаяДлина Тогда Результат = Лев(Строка, МаксимальнаяДлина - 32); ХешированиеДанных = Новый ХешированиеДанных(ХешФункция.MD5); ХешированиеДанных.Добавить(Сред(Строка, МаксимальнаяДлина - 32 + 1)); Результат = Результат + СтрЗаменить(ХешированиеДанных.ХешСумма, "" "", ""); КонецЕсли; Возврат Результат; КонецФункции // Создает полную копию структуры, соответствия, массива, списка или таблицы значений, рекурсивно, // с учетом типов дочерних элементов. При этом содержимое значений объектных типов // (СправочникОбъект, ДокументОбъект и т.п.) не копируются, а возвращаются ссылки на исходный объект. // // Параметры: // Источник - Структура // - ФиксированнаяСтруктура // - Соответствие // - ФиксированноеСоответствие // - Массив // - ФиксированныйМассив // - СписокЗначений - объект, который необходимо скопировать. // ФиксироватьДанные - Булево - если Истина - фиксировать, если Ложь - снять фиксацию. // - Неопределено - не изменять. // // Возвращаемое значение: // Структура, // ФиксированнаяСтруктура, // Соответствие // ФиксированноеСоответствие // Массив // ФиксированныйМассив // СписокЗначений - копия объекта, переданного в параметре Источник. // Функция СкопироватьРекурсивно(Источник, ФиксироватьДанные = Неопределено) Экспорт Перем Приемник; ТипИсточника = ТипЗнч(Источник); Если ТипИсточника = Тип(""ТаблицаЗначений"") Тогда Приемник = Источник.Скопировать(); СкопироватьЗначенияТаблицыЗначений(Приемник, ФиксироватьДанные); ИначеЕсли ТипИсточника = Тип(""ДеревоЗначений"") Тогда Приемник = Источник.Скопировать(); СкопироватьЗначенияСтрокиДереваЗначений(Приемник.Строки, ФиксироватьДанные); ИначеЕсли ТипИсточника = Тип(""Структура"") Или ТипИсточника = Тип(""ФиксированнаяСтруктура"") Тогда Приемник = СкопироватьСтруктуру(Источник, ФиксироватьДанные); ИначеЕсли ТипИсточника = Тип(""Соответствие"") Или ТипИсточника = Тип(""ФиксированноеСоответствие"") Тогда Приемник = СкопироватьСоответствие(Источник, ФиксироватьДанные); ИначеЕсли ТипИсточника = Тип(""Массив"") Или ТипИсточника = Тип(""ФиксированныйМассив"") Тогда Приемник = СкопироватьМассив(Источник, ФиксироватьДанные); ИначеЕсли ТипИсточника = Тип(""СписокЗначений"") Тогда Приемник = СкопироватьСписокЗначений(Источник, ФиксироватьДанные); Иначе Приемник = Источник; КонецЕсли; Возврат Приемник; КонецФункции // Возвращает описание предмета в виде текстовой строки. // Для документов возвращается представление, для остальных ссылочных типов возвращается // представление и тип в скобках, например, ""Ножницы (Номенклатура)"". // Для пустых ссылок, Неопределено или незаполненных значений примитивных типов возвращается ""не задан"". // // Параметры: // СсылкаНаПредмет - Произвольный. // // Возвращаемое значение: // Строка - например, ""Ножницы (Номенклатура)"", ""Заказ клиента № 0001 от 01.01.2001"" или ""не задан"". // Функция ПредметСтрокой(СсылкаНаПредмет) Экспорт Если СсылкаНаПредмет <> Неопределено Тогда Возврат ПредметыСтрокой(ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СсылкаНаПредмет))[СсылкаНаПредмет]; Иначе Возврат НСтр(""ru = 'не задан'""); КонецЕсли; КонецФункции // Возвращает описания предметов СсылкиНаПредметы. // Для документов возвращается представление, для остальных ссылочных типов возвращается // представление и тип в скобках, например, ""Ножницы (Номенклатура)"". // Для пустых ссылок или незаполненных значений примитивных типов возвращается ""не задан"". // Значение ""удален"", если объект не существует в информационной базе. // Значения Неопределено пропускаются. // // Параметры: // СсылкиНаПредметы - Массив из ЛюбаяСсылка // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - ЛюбаяСсылка // * Значение - Строка - например, ""Ножницы (Номенклатура)"", ""Заказ клиента № 0001 от 01.01.2001"" или ""не задан"". // Функция ПредметыСтрокой(Знач СсылкиНаПредметы) Экспорт ПроверяемыеСсылки = Новый Массив; Результат = Новый Соответствие; Для каждого СсылкаНаПредмет Из СсылкиНаПредметы Цикл Если СсылкаНаПредмет = Неопределено Тогда Результат[СсылкаНаПредмет] = НСтр(""ru = 'не задан'""); ИначеЕсли Не ЭтоСсылка(ТипЗнч(СсылкаНаПредмет)) Тогда Результат[СсылкаНаПредмет] = Строка(СсылкаНаПредмет); ИначеЕсли СсылкаНаПредмет.Пустая() Тогда Результат[СсылкаНаПредмет] = НСтр(""ru = 'не задан'""); ИначеЕсли Метаданные.Перечисления.Содержит(СсылкаНаПредмет.Метаданные()) Тогда Результат[СсылкаНаПредмет] = Строка(СсылкаНаПредмет); Иначе ПроверяемыеСсылки.Добавить(СсылкаНаПредмет); КонецЕсли; КонецЦикла; Для каждого СуществующаяСсылка Из ПредставленияСсылок(ПроверяемыеСсылки) Цикл СсылкаНаПредмет = СуществующаяСсылка.Ключ; Результат[СсылкаНаПредмет] = СуществующаяСсылка.Значение; Если Не Метаданные.Документы.Содержит(СсылкаНаПредмет.Метаданные()) Тогда ПредставлениеОбъекта = СсылкаНаПредмет.Метаданные().ПредставлениеОбъекта; Если ПустаяСтрока(ПредставлениеОбъекта) Тогда ПредставлениеОбъекта = СсылкаНаПредмет.Метаданные().Представление(); КонецЕсли; Результат[СсылкаНаПредмет] = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(""%1 (%2)"", Результат[СсылкаНаПредмет], ПредставлениеОбъекта); КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Возвращает представления переданных ссылок. // // Параметры: // ПроверяемыеСсылки - Массив из ЛюбаяСсылка, ЛюбаяСсылка // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - ЛюбаяСсылка // * Значение - Строка - представление ссылки или ""удален"", если ссылка не существует в информационной базе. // Функция ПредставленияСсылок(ПроверяемыеСсылки) Экспорт ОбъектыПоТипу = Новый Соответствие; Если ТипЗнч(ПроверяемыеСсылки) = Тип(""Массив"") Тогда Для каждого ПроверяемаяСсылка Из ПроверяемыеСсылки Цикл Объекты = ОбъектыПоТипу[ПроверяемаяСсылка.Метаданные()]; Если Объекты = Неопределено Тогда Объекты = Новый Массив; ОбъектыПоТипу[ПроверяемаяСсылка.Метаданные()] = Объекты; КонецЕсли; Объекты.Добавить(ПроверяемаяСсылка); КонецЦикла; Иначе ОбъектыПоТипу[ПроверяемыеСсылки.Метаданные()] = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ПроверяемыеСсылки); КонецЕсли; Результат = Новый Соответствие; Если ОбъектыПоТипу.Количество() = 0 Тогда Возврат Результат; КонецЕсли; Запрос = Новый Запрос; ТекстыЗапросов = Новый Массив; Индекс = 0; Для каждого ТипОбъекта Из ОбъектыПоТипу Цикл ТекстЗапроса = ""ВЫБРАТЬ РАЗРЕШЕННЫЕ | Представление КАК Представление, | Таблица.Ссылка КАК Ссылка |ИЗ | &ИмяТаблицы КАК Таблица |ГДЕ | Таблица.Ссылка В (&Ссылка)""; Если ТекстыЗапросов.Количество() > 0 Тогда ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""ВЫБРАТЬ РАЗРЕШЕННЫЕ"", ""ВЫБРАТЬ""); // @query-part-1, @query-part-2 КонецЕсли; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ИмяТаблицы"", ТипОбъекта.Ключ.ПолноеИмя()); ИмяПараметра = ""Ссылка"" + Формат(Индекс, ""ЧГ=;ЧН=""); ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&Ссылка"", ""&"" + ИмяПараметра); ТекстыЗапросов.Добавить(ТекстЗапроса); Запрос.УстановитьПараметр(ИмяПараметра, ТипОбъекта.Значение); Индекс = Индекс + 1; КонецЦикла; Запрос.Текст = СтрСоединить(ТекстыЗапросов, Символы.ПС + ""ОБЪЕДИНИТЬ ВСЕ"" + Символы.ПС); // @query-part; УстановитьПривилегированныйРежим(Истина); ФактическиеСсылки = Запрос.Выполнить().Выгрузить(); УстановитьПривилегированныйРежим(Ложь); ПредставленияСсылок = Запрос.Выполнить().Выгрузить(); ПредставленияСсылок.Индексы.Добавить(""Ссылка""); Для каждого Ссылка Из ФактическиеСсылки Цикл Если ЗначениеЗаполнено(Ссылка.Ссылка) Тогда ПредставлениеСсылки = ПредставленияСсылок.Найти(Ссылка.Ссылка, ""Ссылка""); Результат[Ссылка.Ссылка] = ?(ПредставлениеСсылки <> Неопределено, ПредставлениеСсылки.Представление, Строка(Ссылка.Ссылка)); КонецЕсли; КонецЦикла; Для каждого Ссылка Из ПроверяемыеСсылки Цикл Если Результат[Ссылка] = Неопределено Тогда Результат[Ссылка] = НСтр(""ru = 'удален'""); КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции #КонецОбласти #Область ДинамическийСписок // Создает структуру для второго параметра СвойстваСписка процедуры УстановитьСвойстваДинамическогоСписка. // // Возвращаемое значение: // Структура - любое поле может иметь значение Неопределено, если оно не устанавливается: // * ТекстЗапроса - Строка - новый текст запроса. // * ОсновнаяТаблица - Строка - имя основной таблицы. // * ДинамическоеСчитываниеДанных - Булево - признак использования динамического считывания. // Функция СтруктураСвойствДинамическогоСписка() Экспорт Возврат Новый Структура(""ТекстЗапроса, ОсновнаяТаблица, ДинамическоеСчитываниеДанных""); КонецФункции // Установить текст запроса, основную таблицу или динамическое считывание в динамическом списке. // Устанавливать эти свойства следует за один вызов этой процедуры, чтобы не снижалась производительность. // // Параметры: // Список - ТаблицаФормы - элемент формы динамического списка, для которого устанавливаются свойства. // СвойстваСписка - см. СтруктураСвойствДинамическогоСписка // Процедура УстановитьСвойстваДинамическогоСписка(Список, СвойстваСписка) Экспорт Форма = Список.Родитель; ТипФормаКлиентскогоПриложения = Тип(""ФормаКлиентскогоПриложения""); Пока ТипЗнч(Форма) <> ТипФормаКлиентскогоПриложения Цикл Форма = Форма.Родитель; КонецЦикла; ДинамическийСписок = Форма[Список.ПутьКДанным]; ТекстЗапроса = СвойстваСписка.ТекстЗапроса; Если Не ПустаяСтрока(ТекстЗапроса) Тогда ДинамическийСписок.ТекстЗапроса = ТекстЗапроса; КонецЕсли; ОсновнаяТаблица = СвойстваСписка.ОсновнаяТаблица; Если ОсновнаяТаблица <> Неопределено Тогда ДинамическийСписок.ОсновнаяТаблица = ОсновнаяТаблица; КонецЕсли; ДинамическоеСчитываниеДанных = СвойстваСписка.ДинамическоеСчитываниеДанных; Если ТипЗнч(ДинамическоеСчитываниеДанных) = Тип(""Булево"") Тогда ДинамическийСписок.ДинамическоеСчитываниеДанных = ДинамическоеСчитываниеДанных; КонецЕсли; КонецПроцедуры #КонецОбласти #Область ВнешнееСоединение //////////////////////////////////////////////////////////////////////////////// // Процедуры и функции для работы с внешним соединением. // Возвращает CLSID COM-класса для работы с ""1С:Предприятием 8"" через COM-соединение. // // Параметры: // ИмяCOMСоединителя - Строка - имя COM-класса для работы с ""1С:Предприятием 8"" через COM-соединение. // // Возвращаемое значение: // Строка - строковое представление CLSID. // Функция ИдентификаторCOMСоединителя(Знач ИмяCOMСоединителя) Экспорт Если ИмяCOMСоединителя = ""v83.COMConnector"" Тогда Возврат ""181E893D-73A4-4722-B61D-D604B3D67D47""; КонецЕсли; ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'На задан CLSID для класса %1.'""), ИмяCOMСоединителя); КонецФункции // Устанавливает внешнее соединение с информационной базой по переданным параметрам подключения и возвращает указатель // на это соединение. // // Параметры: // Параметры - см. ОбщегоНазначенияКлиентСервер.СтруктураПараметровДляУстановкиВнешнегоСоединения // // Возвращаемое значение: // Структура: // * Соединение - COMОбъект // - Неопределено - COM-объект соединения или Неопределено в случае ошибки; // * КраткоеОписаниеОшибки - Строка - краткое описание ошибки; // * ПодробноеОписаниеОшибки - Строка - подробное описание ошибки; // * ОшибкаПодключенияКомпоненты - Булево - флаг ошибки подключения COM. // Функция УстановитьВнешнееСоединениеСБазой(Параметры) Экспорт ПодключениеНедоступно = ЭтоLinuxСервер(); КраткоеОписаниеОшибки = НСтр(""ru = 'Прямое подключение к информационной базе недоступно на сервере под управлением ОС Linux.'""); Возврат ОбщегоНазначенияСлужебныйКлиентСервер.УстановитьВнешнееСоединениеСБазой(Параметры, ПодключениеНедоступно, КраткоеОписаниеОшибки); КонецФункции #КонецОбласти #Область Метаданные //////////////////////////////////////////////////////////////////////////////// // Функции определения типов объектов метаданных. // Ссылочные типы данных // Определяет принадлежность объекта метаданных к общему типу ""Документ"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к документам. // // Возвращаемое значение: // Булево - Истина, если объект является документом. // Функция ЭтоДокумент(ОбъектМетаданных) Экспорт Возврат Метаданные.Документы.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Справочник"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является справочником. // Функция ЭтоСправочник(ОбъектМетаданных) Экспорт Возврат Метаданные.Справочники.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Перечисление"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является перечислением. // Функция ЭтоПеречисление(ОбъектМетаданных) Экспорт Возврат Метаданные.Перечисления.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""План обмена"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является планом обмена. // Функция ЭтоПланОбмена(ОбъектМетаданных) Экспорт Возврат Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""План видов характеристик"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является планом видов характеристик. // Функция ЭтоПланВидовХарактеристик(ОбъектМетаданных) Экспорт Возврат Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Бизнес-процесс"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является бизнес-процессом. // Функция ЭтоБизнесПроцесс(ОбъектМетаданных) Экспорт Возврат Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Задача"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является задачей. // Функция ЭтоЗадача(ОбъектМетаданных) Экспорт Возврат Метаданные.Задачи.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""План счетов"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является планом счетов. // Функция ЭтоПланСчетов(ОбъектМетаданных) Экспорт Возврат Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""План видов расчета"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является планом видов расчета. // Функция ЭтоПланВидовРасчета(ОбъектМетаданных) Экспорт Возврат Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных); КонецФункции // Регистры // Определяет принадлежность объекта метаданных к общему типу ""Регистр сведений"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является регистром сведений. // Функция ЭтоРегистрСведений(ОбъектМетаданных) Экспорт Возврат Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Регистр накопления"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является регистром накопления. // Функция ЭтоРегистрНакопления(ОбъектМетаданных) Экспорт Возврат Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Регистр бухгалтерии"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является регистром бухгалтерии. // Функция ЭтоРегистрБухгалтерии(ОбъектМетаданных) Экспорт Возврат Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к общему типу ""Регистр расчета"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является регистром расчета. // Функция ЭтоРегистрРасчета(ОбъектМетаданных) Экспорт Возврат Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных); КонецФункции // Константы // Определяет принадлежность объекта метаданных к общему типу ""Константа"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является константой. // Функция ЭтоКонстанта(ОбъектМетаданных) Экспорт Возврат Метаданные.Константы.Содержит(ОбъектМетаданных); КонецФункции // Журналы документов // Определяет принадлежность объекта метаданных к общему типу ""Журнал документов"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является журналом документов. // Функция ЭтоЖурналДокументов(ОбъектМетаданных) Экспорт Возврат Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных); КонецФункции // Последовательности // Определяет принадлежность объекта метаданных к общему типу ""Последовательности"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является последовательностью. // Функция ЭтоПоследовательность(ОбъектМетаданных) Экспорт Возврат Метаданные.Последовательности.Содержит(ОбъектМетаданных); КонецФункции // РегламентныеЗадания // Определяет принадлежность объекта метаданных к общему типу ""Регламентные задания"". // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является регламентным заданием. // Функция ЭтоРегламентноеЗадание(ОбъектМетаданных) Экспорт Возврат Метаданные.РегламентныеЗадания.Содержит(ОбъектМетаданных); КонецФункции // Общие // Определяет принадлежность объекта метаданных к типу регистр. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект является каким-либо регистром. // Функция ЭтоРегистр(ОбъектМетаданных) Экспорт Возврат Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Или Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Или Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Или Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных); КонецФункции // Определяет принадлежность объекта метаданных к ссылочному типу. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо определить принадлежность к заданному типу. // // Возвращаемое значение: // Булево - Истина, если объект ссылочного типа. // Функция ЭтоОбъектСсылочногоТипа(ОбъектМетаданных) Экспорт ИмяОбъектаМетаданных = ОбъектМетаданных.ПолноеИмя(); Позиция = СтрНайти(ИмяОбъектаМетаданных, "".""); Если Позиция > 0 Тогда ИмяБазовогоТипа = Лев(ИмяОбъектаМетаданных, Позиция - 1); Возврат ИмяБазовогоТипа = ""Справочник"" Или ИмяБазовогоТипа = ""Документ"" Или ИмяБазовогоТипа = ""БизнесПроцесс"" Или ИмяБазовогоТипа = ""Задача"" Или ИмяБазовогоТипа = ""ПланСчетов"" Или ИмяБазовогоТипа = ""ПланОбмена"" Или ИмяБазовогоТипа = ""ПланВидовХарактеристик"" Или ИмяБазовогоТипа = ""ПланВидовРасчета""; Иначе Возврат Ложь; КонецЕсли; КонецФункции //////////////////////////////////////////////////////////////////////////////// // Процедуры и функции для работы с типами, объектами метаданных и их строковыми представлениями. // Возвращает имена реквизитов объекта заданного типа. // // Параметры: // Ссылка - ЛюбаяСсылка - ссылка на элемент базы данных, для которого требуется получить результат функции; // Тип - Тип - тип значения реквизита. // // Возвращаемое значение: // Строка - строка реквизитов объекта метаданных конфигурации, разделенных символом "","". // // Пример: // РеквизитыОрганизации = ОбщегоНазначения.ИменаРеквизитовПоТипу(Документ.Ссылка, Тип(""СправочникСсылка.Организации"")); // Функция ИменаРеквизитовПоТипу(Ссылка, Тип) Экспорт Результат = ""; МетаданныеОбъекта = Ссылка.Метаданные(); Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл Если Реквизит.Тип.СодержитТип(Тип) Тогда Результат = Результат + ?(ПустаяСтрока(Результат), "", "", "") + Реквизит.Имя; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Возвращает имя базового типа по переданному значению объекта метаданных. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект метаданных, по которому необходимо определить базовый тип. // // Возвращаемое значение: // Строка - имя базового типа по переданному значению объекта метаданных. // // Пример: // ИмяБазовогоТипа = ОбщегоНазначения.ИмяБазовогоТипаПоОбъектуМетаданных(Метаданные.Справочники.Номенклатура); = ""Справочники"". // Функция ИмяБазовогоТипаПоОбъектуМетаданных(ОбъектМетаданных) Экспорт Если Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда Возврат ""Документы""; ИначеЕсли Метаданные.Справочники.Содержит(ОбъектМетаданных) Тогда Возврат ""Справочники""; ИначеЕсли Метаданные.Перечисления.Содержит(ОбъектМетаданных) Тогда Возврат ""Перечисления""; ИначеЕсли Метаданные.РегистрыСведений.Содержит(ОбъектМетаданных) Тогда Возврат ""РегистрыСведений""; ИначеЕсли Метаданные.РегистрыНакопления.Содержит(ОбъектМетаданных) Тогда Возврат ""РегистрыНакопления""; ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(ОбъектМетаданных) Тогда Возврат ""РегистрыБухгалтерии""; ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных) Тогда Возврат ""РегистрыРасчета""; ИначеЕсли Метаданные.ПланыОбмена.Содержит(ОбъектМетаданных) Тогда Возврат ""ПланыОбмена""; ИначеЕсли Метаданные.ПланыВидовХарактеристик.Содержит(ОбъектМетаданных) Тогда Возврат ""ПланыВидовХарактеристик""; ИначеЕсли Метаданные.БизнесПроцессы.Содержит(ОбъектМетаданных) Тогда Возврат ""БизнесПроцессы""; ИначеЕсли Метаданные.Задачи.Содержит(ОбъектМетаданных) Тогда Возврат ""Задачи""; ИначеЕсли Метаданные.ПланыСчетов.Содержит(ОбъектМетаданных) Тогда Возврат ""ПланыСчетов""; ИначеЕсли Метаданные.ПланыВидовРасчета.Содержит(ОбъектМетаданных) Тогда Возврат ""ПланыВидовРасчета""; ИначеЕсли Метаданные.Константы.Содержит(ОбъектМетаданных) Тогда Возврат ""Константы""; ИначеЕсли Метаданные.ЖурналыДокументов.Содержит(ОбъектМетаданных) Тогда Возврат ""ЖурналыДокументов""; ИначеЕсли Метаданные.Последовательности.Содержит(ОбъектМетаданных) Тогда Возврат ""Последовательности""; ИначеЕсли Метаданные.РегламентныеЗадания.Содержит(ОбъектМетаданных) Тогда Возврат ""РегламентныеЗадания""; ИначеЕсли Метаданные.РегистрыРасчета.Содержит(ОбъектМетаданных.Родитель()) И ОбъектМетаданных.Родитель().Перерасчеты.Найти(ОбъектМетаданных.Имя) = ОбъектМетаданных Тогда Возврат ""Перерасчеты""; ИначеЕсли Метаданные.Обработки.Содержит(ОбъектМетаданных) Тогда Возврат ""Обработки""; ИначеЕсли Метаданные.Отчеты.Содержит(ОбъектМетаданных) Тогда Возврат ""Отчеты""; ИначеЕсли Метаданные.Подсистемы.Содержит(ОбъектМетаданных) Тогда Возврат ""Подсистемы""; ИначеЕсли Метаданные.ОбщиеМодули.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеМодули""; ИначеЕсли Метаданные.ПараметрыСеанса.Содержит(ОбъектМетаданных) Тогда Возврат ""ПараметрыСеанса""; ИначеЕсли Метаданные.Роли.Содержит(ОбъектМетаданных) Тогда Возврат ""Роли""; ИначеЕсли Метаданные.ОбщиеРеквизиты.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеРеквизиты""; ИначеЕсли Метаданные.КритерииОтбора.Содержит(ОбъектМетаданных) Тогда Возврат ""КритерииОтбора""; ИначеЕсли Метаданные.ПодпискиНаСобытия.Содержит(ОбъектМетаданных) Тогда Возврат ""ПодпискиНаСобытия""; ИначеЕсли Метаданные.ФункциональныеОпции.Содержит(ОбъектМетаданных) Тогда Возврат ""ФункциональныеОпции""; ИначеЕсли Метаданные.ПараметрыФункциональныхОпций.Содержит(ОбъектМетаданных) Тогда Возврат ""ПараметрыФункциональныхОпций""; ИначеЕсли Метаданные.ХранилищаНастроек.Содержит(ОбъектМетаданных) Тогда Возврат ""ХранилищаНастроек""; ИначеЕсли Метаданные.ОбщиеФормы.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеФормы""; ИначеЕсли Метаданные.ОбщиеКоманды.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеКоманды""; ИначеЕсли Метаданные.ГруппыКоманд.Содержит(ОбъектМетаданных) Тогда Возврат ""ГруппыКоманд""; ИначеЕсли Метаданные.ОбщиеМакеты.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеМакеты""; ИначеЕсли Метаданные.ОбщиеКартинки.Содержит(ОбъектМетаданных) Тогда Возврат ""ОбщиеКартинки""; ИначеЕсли Метаданные.ПакетыXDTO.Содержит(ОбъектМетаданных) Тогда Возврат ""ПакетыXDTO""; ИначеЕсли Метаданные.WebСервисы.Содержит(ОбъектМетаданных) Тогда Возврат ""WebСервисы""; ИначеЕсли Метаданные.WSСсылки.Содержит(ОбъектМетаданных) Тогда Возврат ""WSСсылки""; ИначеЕсли Метаданные.Стили.Содержит(ОбъектМетаданных) Тогда Возврат ""Стили""; ИначеЕсли Метаданные.Языки.Содержит(ОбъектМетаданных) Тогда Возврат ""Языки""; ИначеЕсли Метаданные.ВнешниеИсточникиДанных.Содержит(ОбъектМетаданных) Тогда Возврат ""ВнешниеИсточникиДанных""; Иначе Возврат ""; КонецЕсли; КонецФункции // Возвращает менеджер объекта по полному имени объекта метаданных. // Ограничение: не обрабатываются точки маршрутов бизнес-процессов. // // Параметры: // ПолноеИмя - Строка - полное имя объекта метаданных. Пример: ""Справочник.Организации"". // // Возвращаемое значение: // СправочникМенеджер, ДокументМенеджер, ОбработкаМенеджер, РегистрСведенийМенеджер - менеджер объекта. // // Пример: // МенеджерСправочника = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(""Справочник.Организации""); // ПустаяСсылка = МенеджерСправочника.ПустаяСсылка(); // Функция МенеджерОбъектаПоПолномуИмени(ПолноеИмя) Экспорт Перем КлассОМ, ИмяОМ, Менеджер; ЧастиИмени = СтрРазделить(ПолноеИмя, "".""); Если ЧастиИмени.Количество() >= 2 Тогда КлассОМ = ЧастиИмени[0]; ИмяОМ = ЧастиИмени[1]; Иначе Менеджер = Неопределено; КонецЕсли; Если ВРег(КлассОМ) = ""ПЛАНОБМЕНА"" Тогда Менеджер = ПланыОбмена; ИначеЕсли ВРег(КлассОМ) = ""СПРАВОЧНИК"" Тогда Менеджер = Справочники; ИначеЕсли ВРег(КлассОМ) = ""ДОКУМЕНТ"" Тогда Менеджер = Документы; ИначеЕсли ВРег(КлассОМ) = ""ЖУРНАЛДОКУМЕНТОВ"" Тогда Менеджер = ЖурналыДокументов; ИначеЕсли ВРег(КлассОМ) = ""ПЕРЕЧИСЛЕНИЕ"" Тогда Менеджер = Перечисления; ИначеЕсли ВРег(КлассОМ) = ""ОТЧЕТ"" Тогда Менеджер = Отчеты; ИначеЕсли ВРег(КлассОМ) = ""ОБРАБОТКА"" Тогда Менеджер = Обработки; ИначеЕсли ВРег(КлассОМ) = ""ПЛАНВИДОВХАРАКТЕРИСТИК"" Тогда Менеджер = ПланыВидовХарактеристик; ИначеЕсли ВРег(КлассОМ) = ""ПЛАНСЧЕТОВ"" Тогда Менеджер = ПланыСчетов; ИначеЕсли ВРег(КлассОМ) = ""ПЛАНВИДОВРАСЧЕТА"" Тогда Менеджер = ПланыВидовРасчета; ИначеЕсли ВРег(КлассОМ) = ""РЕГИСТРСВЕДЕНИЙ"" Тогда Менеджер = РегистрыСведений; ИначеЕсли ВРег(КлассОМ) = ""РЕГИСТРНАКОПЛЕНИЯ"" Тогда Менеджер = РегистрыНакопления; ИначеЕсли ВРег(КлассОМ) = ""РЕГИСТРБУХГАЛТЕРИИ"" Тогда Менеджер = РегистрыБухгалтерии; ИначеЕсли ВРег(КлассОМ) = ""РЕГИСТРРАСЧЕТА"" Тогда Если ЧастиИмени.Количество() = 2 Тогда Менеджер = РегистрыРасчета; ИначеЕсли ЧастиИмени.Количество() = 4 Тогда КлассПодчиненногоОМ = ЧастиИмени[2]; ИмяПодчиненногоОМ = ЧастиИмени[3]; Если ВРег(КлассПодчиненногоОМ) = ""ПЕРЕРАСЧЕТ"" Тогда Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты; ИмяОм = ИмяПодчиненногоОМ; Иначе Менеджер = Неопределено; КонецЕсли; Иначе Менеджер = Неопределено; КонецЕсли; ИначеЕсли ВРег(КлассОМ) = ""БИЗНЕСПРОЦЕСС"" Тогда Менеджер = БизнесПроцессы; ИначеЕсли ВРег(КлассОМ) = ""ЗАДАЧА"" Тогда Менеджер = Задачи; ИначеЕсли ВРег(КлассОМ) = ""КОНСТАНТА"" Тогда Менеджер = Константы; ИначеЕсли ВРег(КлассОМ) = ""ПОСЛЕДОВАТЕЛЬНОСТЬ"" Тогда Менеджер = Последовательности; Иначе Менеджер = Неопределено; КонецЕсли; Если Менеджер = Неопределено Тогда ПроверитьОбъектМетаданныхСуществует(ПолноеИмя); ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Объект метаданных ""%1"" не имеет менеджера объекта.'""), ПолноеИмя); КонецЕсли; Попытка Возврат Менеджер[ИмяОМ]; Исключение ПроверитьОбъектМетаданныхСуществует(ПолноеИмя); ВызватьИсключение; КонецПопытки; КонецФункции // Возвращает менеджер объекта по ссылке на объект. // Ограничение: не обрабатываются точки маршрутов бизнес-процессов. // См. также ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени. // // Параметры: // Ссылка - ЛюбаяСсылка - объект, менеджер которого требуется получить. // // Возвращаемое значение: // СправочникМенеджер, ДокументМенеджер, ОбработкаМенеджер, РегистрСведенийМенеджер - менеджер объекта. // // Пример: // МенеджерСправочника = ОбщегоНазначения.МенеджерОбъектаПоСсылке(СсылкаНаОрганизацию); // ПустаяСсылка = МенеджерСправочника.ПустаяСсылка(); // Функция МенеджерОбъектаПоСсылке(Ссылка) Экспорт ИмяОбъекта = Ссылка.Метаданные().Имя; ТипСсылки = ТипЗнч(Ссылка); Если Справочники.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат Справочники[ИмяОбъекта]; ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат Документы[ИмяОбъекта]; ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат БизнесПроцессы[ИмяОбъекта]; ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат ПланыВидовХарактеристик[ИмяОбъекта]; ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат ПланыСчетов[ИмяОбъекта]; ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат ПланыВидовРасчета[ИмяОбъекта]; ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат Задачи[ИмяОбъекта]; ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат ПланыОбмена[ИмяОбъекта]; ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипСсылки) Тогда Возврат Перечисления[ИмяОбъекта]; Иначе Возврат Неопределено; КонецЕсли; КонецФункции // Проверка того, что переданный тип является ссылочным типом данных. // Для типа Неопределено возвращается Ложь. // // Параметры: // ПроверяемыйТип - Тип - для проверки на ссылочный тип данных. // // Возвращаемое значение: // Булево - Истина, если это ссылка. // Функция ЭтоСсылка(ПроверяемыйТип) Экспорт Возврат ПроверяемыйТип <> Тип(""Неопределено"") И ОписаниеТипаВсеСсылки().СодержитТип(ПроверяемыйТип); КонецФункции // Проверяет физическое наличие записи в информационной базе данных о переданном значении ссылки. // // Параметры: // ПроверяемаяСсылка - ЛюбаяСсылка - значение любой ссылки информационной базы данных. // // Возвращаемое значение: // Булево - Истина, если существует. // Функция СсылкаСуществует(ПроверяемаяСсылка) Экспорт ТекстЗапроса = ""ВЫБРАТЬ ПЕРВЫЕ 1 | 1 КАК Поле1 |ИЗ | &ИмяТаблицы КАК Таблица |ГДЕ | Таблица.Ссылка = &Ссылка""; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ИмяТаблицы"", ИмяТаблицыПоСсылке(ПроверяемаяСсылка)); Запрос = Новый Запрос; Запрос.Текст = ТекстЗапроса; Запрос.УстановитьПараметр(""Ссылка"", ПроверяемаяСсылка); УстановитьПривилегированныйРежим(Истина); Возврат НЕ Запрос.Выполнить().Пустой(); КонецФункции // Возвращает имя вида объектов метаданных по ссылке на объект. // Ограничение: не обрабатываются точки маршрутов бизнес-процессов. // См. так же ВидОбъектаПоТипу. // // Параметры: // Ссылка - ЛюбаяСсылка - объект, вид которого требуется получить. // // Возвращаемое значение: // Строка - имя вида объектов метаданных. Например: ""Справочник"", ""Документ"". // Функция ВидОбъектаПоСсылке(Ссылка) Экспорт Возврат ВидОбъектаПоТипу(ТипЗнч(Ссылка)); КонецФункции // Возвращает имя вида объектов метаданных по типу объекта. // Ограничение: не обрабатываются точки маршрутов бизнес-процессов. // См. так же ВидОбъектаПоСсылке. // // Параметры: // ТипОбъекта - Тип - тип прикладного объекта, определенный в конфигурации. // // Возвращаемое значение: // Строка - имя вида объектов метаданных. Например: ""Справочник"", ""Документ"". // Функция ВидОбъектаПоТипу(ТипОбъекта) Экспорт Если Справочники.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""Справочник""; ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""Документ""; ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""БизнесПроцесс""; ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""ПланВидовХарактеристик""; ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""ПланСчетов""; ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""ПланВидовРасчета""; ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""Задача""; ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""ПланОбмена""; ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипОбъекта) Тогда Возврат ""Перечисление""; Иначе ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Неверный тип значения параметра (%1)'""), Строка(ТипОбъекта)); КонецЕсли; КонецФункции // Возвращает полное имя объекта метаданных по переданному значению ссылки. // // Параметры: // Ссылка - ЛюбаяСсылка - объект, для которого необходимо получить имя таблицы ИБ. // // Возвращаемое значение: // Строка - полное имя объекта метаданных для указанного объекта. Например: ""Справочник.Номенклатура"". // Функция ИмяТаблицыПоСсылке(Ссылка) Экспорт Возврат Ссылка.Метаданные().ПолноеИмя(); КонецФункции // Проверяет, что переданное значение имеет ссылочный тип данных. // // Параметры: // Значение - Произвольный - проверяемое значение. // // Возвращаемое значение: // Булево - Истина, если тип значения ссылочный. // Функция ЗначениеСсылочногоТипа(Значение) Экспорт Возврат ЭтоСсылка(ТипЗнч(Значение)); КонецФункции // Проверяет, является ли элемент справочника или плана видов характеристик группой элементов. // // Параметры: // Объект - СправочникСсылка // - ПланВидовХарактеристикСсылка // - СправочникОбъект // - ПланВидовХарактеристикОбъект - проверяемый объект. // // Возвращаемое значение: // Булево // Функция ОбъектЯвляетсяГруппой(Объект) Экспорт Если ЗначениеСсылочногоТипа(Объект) Тогда Ссылка = Объект; Иначе Ссылка = Объект.Ссылка; КонецЕсли; МетаданныеОбъекта = Ссылка.Метаданные(); Если ЭтоСправочник(МетаданныеОбъекта) Тогда Если Не МетаданныеОбъекта.Иерархический Или МетаданныеОбъекта.ВидИерархии <> Метаданные.СвойстваОбъектов.ВидИерархии.ИерархияГруппИЭлементов Тогда Возврат Ложь; КонецЕсли; ИначеЕсли Не ЭтоПланВидовХарактеристик(МетаданныеОбъекта) Или Не МетаданныеОбъекта.Иерархический Тогда Возврат Ложь; КонецЕсли; Если Ссылка <> Объект Тогда Возврат Объект.ЭтоГруппа; КонецЕсли; Возврат ЗначениеРеквизитаОбъекта(Ссылка, ""ЭтоГруппа"") = Истина; КонецФункции // Возвращает ссылку, соответствующую объекту метаданных, для использования в базе данных. // См. также ОбщегоНазначения.ИдентификаторыОбъектовМетаданных. // // Ссылки возвращаются для следующих объектов метаданных: // - Подсистемы (см. также ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных); // - Роли (см. также ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных); // - ПланыОбмена; // - Константы; // - Справочники; // - Документы; // - ЖурналыДокументов; // - Отчеты; // - Обработки; // - ПланыВидовХарактеристик; // - ПланыСчетов; // - ПланыВидовРасчета; // - РегистрыСведений; // - РегистрыНакопления; // - РегистрыБухгалтерии; // - РегистрыРасчета; // - БизнесПроцессы; // - Задачи. // // Параметры: // ОписаниеОбъектаМетаданных - ОбъектМетаданных - объект метаданных конфигурации; // - Тип - тип, который можно использовать в функции Метаданные.НайтиПоТипу; // - Строка - полное имя объекта метаданных, которое можно // использовать в функции Метаданные.НайтиПоПолномуИмени. // // ВызыватьИсключение - Булево - если Ложь, то вместо вызова исключения возвращается Null для несуществующего // или неподдерживаемого объекта метаданных. // // Возвращаемое значение: // СправочникСсылка.ИдентификаторыОбъектовМетаданных // СправочникСсылка.ИдентификаторыОбъектовРасширений // Null // // Пример: // Идентификатор = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ТипЗнч(Ссылка)); // Идентификатор = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ОбъектМетаданных); // Идентификатор = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(""Справочник.Организации""); // Функция ИдентификаторОбъектаМетаданных(ОписаниеОбъектаМетаданных, ВызыватьИсключение = Истина) Экспорт Возврат Справочники.ИдентификаторыОбъектовМетаданных.ИдентификаторОбъектаМетаданных( ОписаниеОбъектаМетаданных, ВызыватьИсключение); КонецФункции // Возвращает ссылки, соответствующие объектам метаданных, для использования в базе данных. // См. также ОбщегоНазначения.ИдентификаторОбъектаМетаданных. // // Ссылки возвращаются для следующих объектов метаданных: // - Подсистемы (см. также ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных); // - Роли (см. также ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных); // - ПланыОбмена. // - Константы. // - Справочники. // - Документы. // - ЖурналыДокументов. // - Отчеты. // - Обработки. // - ПланыВидовХарактеристик. // - ПланыСчетов. // - ПланыВидовРасчета. // - РегистрыСведений. // - РегистрыНакопления. // - РегистрыБухгалтерии. // - РегистрыРасчета. // - БизнесПроцессы. // - Задачи. // // Параметры: // ОписаниеОбъектовМетаданных - Массив из ОбъектМетаданных - объекты метаданных конфигурации; // - Массив из Строка - полные имена объектов метаданных, которые можно использовать // в функции Метаданные.НайтиПоПолномуИмени; // - Массив из Тип - типы, которые можно использовать в функции Метаданные.НайтиПоТипу. // ВызыватьИсключение - Булево - если Ложь, то несуществующие и неподдерживаемые объекты метаданных // будут пропущены в возвращаемом значении. // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - Строка - полное имя указанного объекта метаданных. // * Значение - СправочникСсылка.ИдентификаторыОбъектовМетаданных // - СправочникСсылка.ИдентификаторыОбъектовРасширений - найденный идентификатор. // // Пример: // ПолныеИмена = Новый Массив; // ПолныеИмена.Добавить(Метаданные.Справочники.Валюты.ПолноеИмя()); // ПолныеИмена.Добавить(Метаданные.РегистрыСведений.КурсыВалют.ПолноеИмя()); // Идентификаторы = ОбщегоНазначения.ИдентификаторыОбъектовМетаданных(ПолныеИмена); // Функция ИдентификаторыОбъектовМетаданных(ОписаниеОбъектовМетаданных, ВызыватьИсключение = Истина) Экспорт Возврат Справочники.ИдентификаторыОбъектовМетаданных.ИдентификаторыОбъектовМетаданных( ОписаниеОбъектовМетаданных, ВызыватьИсключение); КонецФункции // Возвращает объект метаданных по переданному идентификатору. // // Параметры: // Идентификатор - СправочникСсылка.ИдентификаторыОбъектовМетаданных // - СправочникСсылка.ИдентификаторыОбъектовРасширений - идентификатор // объекта метаданных конфигурации или расширения конфигурации. // // ВызыватьИсключение - Булево - если Ложь, тогда в случае, когда объект метаданных // не существует или недоступен, возвращает соответственно // Null или Неопределено вместо вызова исключения. // // Возвращаемое значение: // ОбъектМетаданных - объект метаданных, соответствующий идентификатору. // // Null - возвращается, когда ВызыватьИсключение = Ложь. Обозначает, что // для указанного идентификатора объект метаданных не существует (идентификатор устарел). // // Неопределено - возвращается, когда ВызыватьИсключение = Ложь. Обозначает, // что идентификатор действующий, но в текущем сеансе ОбъектМетаданных не может быть получен. // Для расширений конфигурации это значит, что расширение установлено, но не подключено, // либо потому что перезапуск еще не выполнен, либо при подключении произошла ошибка. // Для конфигурации это значит, что в новом сеансе (новом динамическом поколении) объект // метаданных имеется, а в текущем (старом) сеансе нет. // Функция ОбъектМетаданныхПоИдентификатору(Идентификатор, ВызыватьИсключение = Истина) Экспорт Возврат Справочники.ИдентификаторыОбъектовМетаданных.ОбъектМетаданныхПоИдентификатору( Идентификатор, ВызыватьИсключение); КонецФункции // Возвращает объекты метаданных по переданным идентификаторам. // // Параметры: // Идентификаторы - Массив - со значениями: // * Значение - СправочникСсылка.ИдентификаторыОбъектовМетаданных // - СправочникСсылка.ИдентификаторыОбъектовРасширений - идентификаторы // объектов метаданных конфигурации или расширений конфигурации. // // ВызыватьИсключение - Булево - если Ложь, тогда в случае, когда объект метаданных // не существует или недоступен, возвращает соответственно // Null или Неопределено вместо вызова исключения. // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - СправочникСсылка.ИдентификаторыОбъектовМетаданных // - СправочникСсылка.ИдентификаторыОбъектовРасширений - переданный идентификатор. // * Значение - ОбъектМетаданных - объект метаданных, соответствующий идентификатору. // - Null - возвращается, когда ВызыватьИсключение = Ложь. Обозначает, что // для указанного идентификатора объект метаданных не существует (идентификатор устарел). // - Неопределено - возвращается, когда ВызыватьИсключение = Ложь. Обозначает, // что идентификатор действующий, но в текущем сеансе ОбъектМетаданных не может быть получен. // Для расширений конфигурации это значит, что расширение установлено, но не подключено, // либо потому что перезапуск еще не выполнен, либо при подключении произошла ошибка. // Для конфигурации это значит, что в новом сеансе (новом динамическом поколении) объект // метаданных имеется, а в текущем (старом) сеансе нет. // Функция ОбъектыМетаданныхПоИдентификаторам(Идентификаторы, ВызыватьИсключение = Истина) Экспорт Возврат Справочники.ИдентификаторыОбъектовМетаданных.ОбъектыМетаданныхПоИдентификаторам( Идентификаторы, ВызыватьИсключение); КонецФункции // Возвращает ОбъектМетаданных, быстро найденный по полному имени. // Более производительный аналог метода платформы Метаданные.НайтиПоПолномуИмени // для корневых объектов метаданных. // // Параметры: // ПолноеИмя - Строка - полное имя объекта метаданных, например, Справочник.Организации // // Возвращаемое значение: // ОбъектМетаданных - когда найден // Неопределено - когда не найден // Функция ОбъектМетаданныхПоПолномуИмени(ПолноеИмя) Экспорт ПозицияТочки = СтрНайти(ПолноеИмя, "".""); ИмяБазовогоТипа = Лев(ПолноеИмя, ПозицияТочки - 1); ИменаКоллекций = СтандартныеПодсистемыПовтИсп.ИменаКоллекцийПоИменамБазовыхТипов(); Коллекция = ИменаКоллекций.Получить(ВРег(ИмяБазовогоТипа)); Если Коллекция <> Неопределено Тогда Если Коллекция <> ""Подсистемы"" Тогда ИмяОбъекта = Сред(ПолноеИмя, ПозицияТочки + 1); ОбъектМетаданных = Метаданные[Коллекция].Найти(ИмяОбъекта); Иначе ИменаПодсистем = СтрРазделить(ВРег(ПолноеИмя), "".""); Количество = ИменаПодсистем.Количество(); Подсистема = Метаданные; ОбъектМетаданных = Неопределено; Индекс = 0; Пока Истина Цикл Индекс = Индекс + 1; Если Индекс >= Количество Тогда Прервать; КонецЕсли; ИмяПодсистемы = ИменаПодсистем[Индекс]; Подсистема = Подсистема.Подсистемы.Найти(ИмяПодсистемы); Если Подсистема = Неопределено Тогда Прервать; КонецЕсли; Индекс = Индекс + 1; Если Индекс = Количество Тогда ОбъектМетаданных = Подсистема; Прервать; КонецЕсли; КонецЦикла; КонецЕсли; КонецЕсли; Если ОбъектМетаданных = Неопределено Тогда ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмя); КонецЕсли; Возврат ОбъектМетаданных; КонецФункции // Определяет доступность объекта метаданных по функциональным опциям. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных // - Строка - проверяемый объект метаданных. // // Возвращаемое значение: // Булево - Истина, если объект доступен. // Функция ОбъектМетаданныхДоступенПоФункциональнымОпциям(Знач ОбъектМетаданных) Экспорт Если ОбъектМетаданных = Неопределено Тогда Возврат Ложь; КонецЕсли; Если ТипЗнч(ОбъектМетаданных) <> Тип(""Строка"") Тогда ПолноеИмя = ОбъектМетаданных.ПолноеИмя(); Иначе ПолноеИмя = ОбъектМетаданных; КонецЕсли; Возврат СтандартныеПодсистемыПовтИсп.ДоступностьОбъектовПоОпциям().Получить(ПолноеИмя) <> Ложь; КонецФункции // Добавляет описание переименования объекта метаданных при переходе на указанную версию конфигурации. // Добавление выполняется в структуру Итог, которая передается в // процедуру ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных. // // Параметры: // Итог - см. ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных.Итог // ВерсияИБ - Строка - версия конечной конфигурации, при переходе на которую нужно // выполнить переименование, например, ""2.1.2.14"". // СтароеПолноеИмя - Строка - старое полное имя объекта метаданных, которое нужно переименовать, // например ""Подсистема._ДемоПодсистемы"". // НовоеПолноеИмя - Строка - новое полное имя объекта метаданных, на которое нужно переименовать, // например ""Подсистема._ДемоСервисныеПодсистемы"". // ИдентификаторБиблиотеки - Строка - внутренний идентификатор библиотеки, к которой относится ВерсияИБ. // Для основной конфигурации не требуется. // Например, ""СтандартныеПодсистемы"" - как указано // в ОбновлениеИнформационнойБазыБСП.ПриДобавленииПодсистемы. // Пример: // ОбщегоНазначения.ДобавитьПереименование(Итог, ""2.1.2.14"", // ""Подсистема._ДемоПодсистемы"", // ""Подсистема._ДемоСервисныеПодсистемы""); // Процедура ДобавитьПереименование(Итог, ВерсияИБ, СтароеПолноеИмя, НовоеПолноеИмя, ИдентификаторБиблиотеки = "") Экспорт Справочники.ИдентификаторыОбъектовМетаданных.ДобавитьПереименование(Итог, ВерсияИБ, СтароеПолноеИмя, НовоеПолноеИмя, ИдентификаторБиблиотеки); КонецПроцедуры // Возвращает строковое представление типа, например, ""СправочникСсылка.ИмяОбъекта"", ""ДокументСсылка.ИмяОбъекта"". // Для остальных типов приводит тип к строке, например ""Число"". // // Параметры: // Тип - Тип - для которого надо получить представление. // // Возвращаемое значение: // Строка // Функция СтроковоеПредставлениеТипа(Тип) Экспорт Представление = ""; Если ЭтоСсылка(Тип) Тогда ПолноеИмя = Метаданные.НайтиПоТипу(Тип).ПолноеИмя(); ИмяОбъекта = СтрРазделить(ПолноеИмя, ""."")[1]; Если Справочники.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""СправочникСсылка""; ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ДокументСсылка""; ИначеЕсли БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""БизнесПроцессСсылка""; ИначеЕсли БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(Тип) Тогда Представление = ""ТочкаМаршрутаБизнесПроцессаСсылка""; ИначеЕсли ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ПланВидовХарактеристикСсылка""; ИначеЕсли ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ПланСчетовСсылка""; ИначеЕсли ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ПланВидовРасчетаСсылка""; ИначеЕсли Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ЗадачаСсылка""; ИначеЕсли ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ПланОбменаСсылка""; ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(Тип) Тогда Представление = ""ПеречислениеСсылка""; КонецЕсли; Результат = ?(Представление = "", Представление, Представление + ""."" + ИмяОбъекта); ИначеЕсли Тип = Тип(""Неопределено"") Тогда Результат = ""Неопределено""; ИначеЕсли Тип = Тип(""Строка"") Тогда Результат = ""Строка""; ИначеЕсли Тип = Тип(""Число"") Тогда Результат = ""Число""; ИначеЕсли Тип = Тип(""Булево"") Тогда Результат = ""Булево""; ИначеЕсли Тип = Тип(""Дата"") Тогда Результат = ""Дата""; Иначе Результат = Строка(Тип); КонецЕсли; Возврат Результат; КонецФункции // Возвращает таблицу значений с описанием требуемых свойств всех реквизитов объекта метаданных. // Получает значения свойств стандартных реквизитов и пользовательских реквизитов (созданных в режиме конфигуратора). // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - объект, для которого необходимо получить значение свойств реквизитов. // Например: Метаданные.Документ.РеализацияТоваровИУслуг // Свойства - Строка - свойства реквизитов, перечисленные через запятую, значение которых необходимо получить. // Например: ""Имя, Тип, Синоним, Подсказка"". // // Возвращаемое значение: // ТаблицаЗначений - описание требуемых свойств всех реквизитов объекта метаданных. // Функция ОписаниеСвойствОбъекта(ОбъектМетаданных, Свойства) Экспорт МассивСвойств = СтрРазделить(Свойства, "",""); // Возвращаемое значение функции. ТаблицаОписанияСвойствОбъекта = Новый ТаблицаЗначений; // Добавляем в таблицу поля согласно именам переданных свойств. Для Каждого ИмяСвойства Из МассивСвойств Цикл ТаблицаОписанияСвойствОбъекта.Колонки.Добавить(СокрЛП(ИмяСвойства)); КонецЦикла; // Заполняем строку таблицы свойствами реквизитов объекта метаданных. Для Каждого Реквизит Из ОбъектМетаданных.Реквизиты Цикл ЗаполнитьЗначенияСвойств(ТаблицаОписанияСвойствОбъекта.Добавить(), Реквизит); КонецЦикла; // Заполняем строку таблицы свойствами стандартных реквизитов объекта метаданных. Для Каждого Реквизит Из ОбъектМетаданных.СтандартныеРеквизиты Цикл ЗаполнитьЗначенияСвойств(ТаблицаОписанияСвойствОбъекта.Добавить(), Реквизит); КонецЦикла; Возврат ТаблицаОписанияСвойствОбъекта; КонецФункции // Возвращает признак того, что реквизит входит в подмножество стандартных реквизитов. // // Параметры: // СтандартныеРеквизиты - ОписанияСтандартныхРеквизитов - тип и значение, описывающие коллекцию настроек различных // стандартных реквизитов; // ИмяРеквизита - Строка - реквизит, который необходимо проверить на принадлежность множеству стандартных // реквизитов. // // Возвращаемое значение: // Булево - Истина, если реквизит входит в подмножество стандартных реквизитов. // Функция ЭтоСтандартныйРеквизит(СтандартныеРеквизиты, ИмяРеквизита) Экспорт Для Каждого Реквизит Из СтандартныеРеквизиты Цикл Если Реквизит.Имя = ИмяРеквизита Тогда Возврат Истина; КонецЕсли; КонецЦикла; Возврат Ложь; КонецФункции // Позволяет определить, есть ли среди реквизитов объекта реквизит с переданным именем. // // Параметры: // ИмяРеквизита - Строка - имя реквизита; // МетаданныеОбъекта - ОбъектМетаданных - объект, в котором требуется проверить наличие реквизита. // // Возвращаемое значение: // Булево - Истина, если есть. // Функция ЕстьРеквизитОбъекта(ИмяРеквизита, МетаданныеОбъекта) Экспорт Реквизиты = МетаданныеОбъекта.Реквизиты; // КоллекцияОбъектовМетаданных Возврат НЕ (Реквизиты.Найти(ИмяРеквизита) = Неопределено); КонецФункции // Проверить, что описание типа состоит из единственного типа значения и // совпадает с нужным типом. // // Параметры: // ОписаниеТипа - ОписаниеТипов - проверяемая коллекция типов; // ТипЗначения - Тип - проверяемый тип. // // Возвращаемое значение: // Булево - Истина, если совпадает. // // Пример: // Если ОбщегоНазначения.ОписаниеТипаСостоитИзТипа(ТипЗначенияСвойства, Тип(""Булево"") Тогда // // Выводим поле в виде флажка. // КонецЕсли; // Функция ОписаниеТипаСостоитИзТипа(ОписаниеТипа, ТипЗначения) Экспорт Если ОписаниеТипа.Типы().Количество() = 1 И ОписаниеТипа.Типы().Получить(0) = ТипЗначения Тогда Возврат Истина; КонецЕсли; Возврат Ложь; КонецФункции // Создает объект ОписаниеТипов, содержащий тип Строка. // // Параметры: // ДлинаСтроки - Число - длина строки. // // Возвращаемое значение: // ОписаниеТипов - описание типа Строка. // Функция ОписаниеТипаСтрока(ДлинаСтроки) Экспорт Возврат Новый ОписаниеТипов(""Строка"", , Новый КвалификаторыСтроки(ДлинаСтроки)); КонецФункции // Создает объект ОписаниеТипов, содержащий тип Число. // // Параметры: // Разрядность - Число - общее количество разрядов числа (количество разрядов // целой части плюс количество разрядов дробной части). // РазрядностьДробнойЧасти - Число - число разрядов дробной части. // ЗнакЧисла - ДопустимыйЗнак - допустимый знак числа. // // Возвращаемое значение: // ОписаниеТипов - описание типа Число. // Функция ОписаниеТипаЧисло(Разрядность, РазрядностьДробнойЧасти = 0, Знач ЗнакЧисла = Неопределено) Экспорт Если ЗнакЧисла = Неопределено Тогда ЗнакЧисла = ДопустимыйЗнак.Любой; КонецЕсли; Возврат Новый ОписаниеТипов(""Число"", Новый КвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти, ЗнакЧисла)); КонецФункции // Создает объект ОписаниеТипов, содержащий тип Дата. // // Параметры: // ЧастиДаты - ЧастиДаты - набор вариантов использования значений типа Дата. // // Возвращаемое значение: // ОписаниеТипов - описание типа Дата. // Функция ОписаниеТипаДата(ЧастиДаты) Экспорт Возврат Новый ОписаниеТипов(""Дата"", , , Новый КвалификаторыДаты(ЧастиДаты)); КонецФункции // Возвращает описание типа, включающего в себя все возможные ссылочные типы конфигурации. // // Возвращаемое значение: // ОписаниеТипов - все ссылочные типы конфигурации. // Функция ОписаниеТипаВсеСсылки() Экспорт Возврат СтандартныеПодсистемыПовтИсп.ОписаниеТипаВсеСсылки(); КонецФункции // Возвращает строковое представление списка, заданное в свойствах объекта метаданных. // В зависимости от того, какие свойства объекта метаданных заполнены, функция возвращают одно из них в указанном // порядке: Расширенное представление списка, Представление списка, Синоним или Имя. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - произвольный объект. // // Возвращаемое значение: // Строка - представление списка. // Функция ПредставлениеСписка(ОбъектМетаданных) Экспорт СвойстваОбъекта = Новый Структура(""РасширенноеПредставлениеСписка,ПредставлениеСписка""); ЗаполнитьЗначенияСвойств(СвойстваОбъекта, ОбъектМетаданных); Если ЗначениеЗаполнено(СвойстваОбъекта.РасширенноеПредставлениеСписка) Тогда Результат = СвойстваОбъекта.РасширенноеПредставлениеСписка; ИначеЕсли ЗначениеЗаполнено(СвойстваОбъекта.ПредставлениеСписка) Тогда Результат = СвойстваОбъекта.ПредставлениеСписка; Иначе Результат = ОбъектМетаданных.Представление(); КонецЕсли; Возврат Результат; КонецФункции // Возвращает строковое представление объекта, заданное в свойствах объекта метаданных. // В зависимости от того, какие свойства объекта метаданных заполнены, функция возвращают одно из них в указанном // порядке: Расширенное представление объекта, Представление объекта, Синоним или Имя. // // Параметры: // ОбъектМетаданных - ОбъектМетаданных - произвольный объект. // // Возвращаемое значение: // Строка - представление объекта. // Функция ПредставлениеОбъекта(ОбъектМетаданных) Экспорт СвойстваОбъекта = Новый Структура(""РасширенноеПредставлениеОбъекта,ПредставлениеОбъекта""); ЗаполнитьЗначенияСвойств(СвойстваОбъекта, ОбъектМетаданных); Если ЗначениеЗаполнено(СвойстваОбъекта.РасширенноеПредставлениеОбъекта) Тогда Результат = СвойстваОбъекта.РасширенноеПредставлениеОбъекта; ИначеЕсли ЗначениеЗаполнено(СвойстваОбъекта.ПредставлениеОбъекта) Тогда Результат = СвойстваОбъекта.ПредставлениеОбъекта; Иначе Результат = ОбъектМетаданных.Представление(); КонецЕсли; Возврат Результат; КонецФункции #КонецОбласти #Область ХранилищеНастроек //////////////////////////////////////////////////////////////////////////////// // Сохранение, чтение и удаление настроек из хранилищ. // Сохраняет настройку в хранилище общих настроек, как метод платформы Сохранить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // Настройки - Произвольный - см. синтакс-помощник платформы. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы. // Процедура ХранилищеОбщихНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт ХранилищеСохранить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения); КонецПроцедуры // Сохраняет несколько настроек в хранилище общих настроек, как метод платформы Сохранить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки. // // Параметры: // НесколькоНастроек - Массив - со значениями: // * Значение - Структура: // * Объект - Строка - см. параметр КлючОбъекта в синтакс-помощнике платформы. // * Настройка - Строка - см. параметр КлючНастроек в синтакс-помощнике платформы. // * Значение - Произвольный - см. параметр Настройки в синтакс-помощнике платформы. // // ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы. // Процедура ХранилищеОбщихНастроекСохранитьМассив(НесколькоНастроек, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт Если Не ПравоДоступа(""СохранениеДанныхПользователя"", Метаданные) Тогда Возврат; КонецЕсли; Для Каждого Элемент Из НесколькоНастроек Цикл ХранилищеОбщихНастроек.Сохранить(Элемент.Объект, КлючНастроек(Элемент.Настройка), Элемент.Значение); КонецЦикла; Если ОбновитьПовторноИспользуемыеЗначения Тогда ОбновитьПовторноИспользуемыеЗначения(); КонецЕсли; КонецПроцедуры // Загружает настройку из хранилища общих настроек, как метод платформы Загрузить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Кроме того, возвращает указанное значение по умолчанию, если настройки не существуют. // Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки. // // В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно // - возвращаемая ссылка заменяется на указанное значение по умолчанию; // - из данных типа Массив ссылки удаляются; // - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено; // - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // ЗначениеПоУмолчанию - Произвольный - значение, которое возвращается, если настройки не существуют. // Если не указано, возвращается значение Неопределено. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // // Возвращаемое значение: // Произвольный - см. синтакс-помощник платформы. // Функция ХранилищеОбщихНастроекЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт Возврат ХранилищеЗагрузить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек, ИмяПользователя); КонецФункции // Удаляет настройку из хранилища общих настроек, как метод платформы Удалить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка // - Неопределено - см. синтакс-помощник платформы. // КлючНастроек - Строка // - Неопределено - см. синтакс-помощник платформы. // ИмяПользователя - Строка // - Неопределено - см. синтакс-помощник платформы. // Процедура ХранилищеОбщихНастроекУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт ХранилищеУдалить(ХранилищеОбщихНастроек, КлючОбъекта, КлючНастроек, ИмяПользователя); КонецПроцедуры // Сохраняет настройку в хранилище системных настроек, как метод платформы Сохранить // объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек // более 128 символов путем хеширования части, которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // Настройки - Произвольный - см. синтакс-помощник платформы. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы. // Процедура ХранилищеСистемныхНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт ХранилищеСохранить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения); КонецПроцедуры // Загружает настройку из хранилища системных настроек, как метод платформы Загрузить, // объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек // более 128 символов путем хеширования части, которая превышает 96 символов. // Кроме того, возвращает указанное значение по умолчанию, если настройки не существуют. // Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки. // // В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно: // - возвращаемая ссылка заменяется на указанное значение по умолчанию; // - из данных типа Массив ссылки удаляются; // - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено; // - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // ЗначениеПоУмолчанию - Произвольный - значение, которое возвращается, если настройки не существуют. // Если не указано, возвращается значение Неопределено. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // // Возвращаемое значение: // Произвольный - см. синтакс-помощник платформы. // Функция ХранилищеСистемныхНастроекЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт Возврат ХранилищеЗагрузить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек, ИмяПользователя); КонецФункции // Удаляет настройку из хранилища системных настроек, как метод платформы Удалить, // объекта СтандартноеХранилищеНастроекМенеджер, но с поддержкой длины ключа настроек // более 128 символов путем хеширования части, которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка // - Неопределено - см. синтакс-помощник платформы. // КлючНастроек - Строка // - Неопределено - см. синтакс-помощник платформы. // ИмяПользователя - Строка // - Неопределено - см. синтакс-помощник платформы. // Процедура ХранилищеСистемныхНастроекУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт ХранилищеУдалить(ХранилищеСистемныхНастроек, КлючОбъекта, КлючНастроек, ИмяПользователя); КонецПроцедуры // Сохраняет настройку в хранилище настроек данных форм, как метод платформы Сохранить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, сохранение пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // Настройки - Произвольный - см. синтакс-помощник платформы. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // ОбновитьПовторноИспользуемыеЗначения - Булево - выполнить одноименный метод платформы. // Процедура ХранилищеНастроекДанныхФормСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено, ОбновитьПовторноИспользуемыеЗначения = Ложь) Экспорт ХранилищеСохранить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения); КонецПроцедуры // Загружает настройку из хранилища настроек данных форм, как метод платформы Загрузить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Кроме того, возвращает указанное значение по умолчанию, если настройки не существуют. // Если нет права СохранениеДанныхПользователя, возвращается значение по умолчанию без ошибки. // // В возвращаемом значении очищаются ссылки на несуществующий объект в базе данных, а именно // - возвращаемая ссылка заменяется на указанное значение по умолчанию; // - из данных типа Массив ссылки удаляются; // - у данных типа Структура и Соответствие ключ не меняется, а значение устанавливается Неопределено; // - анализ значений в данных типа Массив, Структура, Соответствие выполняется рекурсивно. // // Параметры: // КлючОбъекта - Строка - см. синтакс-помощник платформы. // КлючНастроек - Строка - см. синтакс-помощник платформы. // ЗначениеПоУмолчанию - Произвольный - значение, которое возвращается, если настройки не существуют. // Если не указано, возвращается значение Неопределено. // ОписаниеНастроек - ОписаниеНастроек - см. синтакс-помощник платформы. // ИмяПользователя - Строка - см. синтакс-помощник платформы. // // Возвращаемое значение: // Произвольный - см. синтакс-помощник платформы. // Функция ХранилищеНастроекДанныхФормЗагрузить(КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию = Неопределено, ОписаниеНастроек = Неопределено, ИмяПользователя = Неопределено) Экспорт Возврат ХранилищеЗагрузить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек, ИмяПользователя); КонецФункции // Удаляет настройку из хранилища настроек данных форм, как метод платформы Удалить, // объектов СтандартноеХранилищеНастроекМенеджер или ХранилищеНастроекМенеджер.<Имя хранилища>, // но с поддержкой длины ключа настроек более 128 символов путем хеширования части, // которая превышает 96 символов. // Если нет права СохранениеДанныхПользователя, удаление пропускается без ошибки. // // Параметры: // КлючОбъекта - Строка // - Неопределено - см. синтакс-помощник платформы. // КлючНастроек - Строка // - Неопределено - см. синтакс-помощник платформы. // ИмяПользователя - Строка // - Неопределено - см. синтакс-помощник платформы. // Процедура ХранилищеНастроекДанныхФормУдалить(КлючОбъекта, КлючНастроек, ИмяПользователя) Экспорт ХранилищеУдалить(ХранилищеНастроекДанныхФорм, КлючОбъекта, КлючНастроек, ИмяПользователя); КонецПроцедуры #КонецОбласти #Область СериализацияXML // Преобразует (сериализует) любое значение в XML-строку. // Преобразованы в могут быть только те объекты, для которых в синтакс-помощнике указано, что они сериализуются. // См. также ЗначениеИзСтрокиXML. // // Параметры: // Значение - Произвольный - значение, которое необходимо сериализовать в XML-строку. // // Возвращаемое значение: // Строка - XML-строка. // Функция ЗначениеВСтрокуXML(Значение) Экспорт ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.УстановитьСтроку(); СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, НазначениеТипаXML.Явное); Возврат ЗаписьXML.Закрыть(); КонецФункции // Выполняет преобразование (десериализацию) XML-строки в значение. // См. также ЗначениеВСтрокуXML. // // Параметры: // СтрокаXML - Строка - XML-строка, с сериализованным объектом.. // // Возвращаемое значение: // Произвольный - значение, полученное из переданной XML-строки. // Функция ЗначениеИзСтрокиXML(СтрокаXML) Экспорт ЧтениеXML = Новый ЧтениеXML; ЧтениеXML.УстановитьСтроку(СтрокаXML); Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML); КонецФункции // Возвращает XML-представление XDTO-объекта. // // Параметры: // ОбъектXDTO - ОбъектXDTO - объект, для которого требуется сформировать XML-представление. // Фабрика - ФабрикаXDTO - фабрика, с использованием которой требуется формировать XML-представление. // Если параметр не указан - будет использоваться глобальная фабрика XDTO. // // Возвращаемое значение: // Строка - XML-представление XDTO-объекта. // Функция ОбъектXDTOВСтрокуXML(Знач ОбъектXDTO, Знач Фабрика = Неопределено) Экспорт ОбъектXDTO.Проверить(); Если Фабрика = Неопределено Тогда Фабрика = ФабрикаXDTO; КонецЕсли; Запись = Новый ЗаписьXML(); Запись.УстановитьСтроку(); Фабрика.ЗаписатьXML(Запись, ОбъектXDTO, , , , НазначениеТипаXML.Явное); Возврат Запись.Закрыть(); КонецФункции // Формирует XDTO-объект по XML-представлению. // // Параметры: // СтрокаXML - Строка - XML-представление XDTO-объекта, // Фабрика - ФабрикаXDTO - фабрика, с использованием которой требуется формировать XDTO-объект. // Если параметр не указан - будет использоваться глобальная фабрика XDTO. // // Возвращаемое значение: // ОбъектXDTO - XDTO-объект. // Функция ОбъектXDTOИзСтрокиXML(Знач СтрокаXML, Знач Фабрика = Неопределено) Экспорт Если Фабрика = Неопределено Тогда Фабрика = ФабрикаXDTO; КонецЕсли; Чтение = Новый ЧтениеXML(); Чтение.УстановитьСтроку(СтрокаXML); Возврат Фабрика.ПрочитатьXML(Чтение); КонецФункции #КонецОбласти #Область СериализацияJSON // Преобразует значение в строку JSON при помощи метода глобального контекста ЗаписатьJSON. // Допускаются не все типы значений, подробности см. в синтакс-помощнике. // Даты преобразуются в формат ISO (YYYY-MM-DDThh:mm:ssZ). // // Параметры: // Значение - Произвольный // // Возвращаемое значение: // Строка // Функция ЗначениеВJSON(Знач Значение) Экспорт ЗаписьJSON = Новый ЗаписьJSON; ЗаписьJSON.УстановитьСтроку(); ЗаписатьJSON(ЗаписьJSON, Значение); Возврат ЗаписьJSON.Закрыть(); КонецФункции // Преобразует строку в формате JSON в значение при помощи метода глобального контекста ПрочитатьJSON. // См. ограничения в синтакс-помощнике. // Объекты JSON по умолчанию преобразует в значения типа Соответствие. // Имена свойств со значением типа Дата необходимо явно указывать, чтобы было выполнено преобразование. // Ожидаемый формат дат - ISO (YYYY-MM-DDThh:mm:ssZ). // // Параметры: // Строка - Строка - значение в формате JSON. // ИменаСвойствСоЗначениямиДата - Строка - имя свойства, содержащее значение типа Дата. Допустимо указывать несколько // свойств через запятую. // - Массив из Строка // ПрочитатьВСоответствие - Булево - если Ложь, то объекты JSON будут преобразованы в значение типа Структура. // // Возвращаемое значение: // Произвольный // Функция JSONВЗначение(Знач Строка, Знач ИменаСвойствСоЗначениямиДата = Неопределено, Знач ПрочитатьВСоответствие = Истина) Экспорт Если ТипЗнч(ИменаСвойствСоЗначениямиДата) = Тип(""Строка"") Тогда ИменаСвойствСоЗначениямиДата = СтрРазделить(ИменаСвойствСоЗначениямиДата, "", "" + Символы.ПС, Ложь); КонецЕсли; ЧтениеJSON = Новый ЧтениеJSON; ЧтениеJSON.УстановитьСтроку(Строка); Возврат ПрочитатьJSON(ЧтениеJSON, ПрочитатьВСоответствие, ИменаСвойствСоЗначениямиДата); КонецФункции #КонецОбласти #Область ВебСервисы // Возвращает структуру параметров для функции СоздатьWSПрокси. // // Возвращаемое значение: // см. СоздатьWSПрокси.ПараметрыПодключенияWSПрокси // Функция ПараметрыПодключенияWSПрокси() Экспорт Результат = Новый Структура; Результат.Вставить(""АдресWSDL""); Результат.Вставить(""URIПространстваИмен""); Результат.Вставить(""ИмяСервиса""); Результат.Вставить(""ИмяТочкиПодключения"", ""); Результат.Вставить(""ИмяПользователя""); Результат.Вставить(""Пароль""); Результат.Вставить(""Таймаут"", 0); Результат.Вставить(""Местоположение""); Результат.Вставить(""ИспользоватьАутентификациюОС"", Ложь); Результат.Вставить(""ДелатьКонтрольныйВызов"", Ложь); Результат.Вставить(""ЗащищенноеСоединение"", Неопределено); Возврат Результат; КонецФункции // Конструктор объекта WSПрокси с дополнительными возможностями по сравнению с конструктором Новый WSПрокси: // - создает WSОпределения; // - кэширует файл WSDL для ускорения работы с веб-сервисом; // - не требуется указание ИнтернетПрокси (используется автоматически, если настроен); // - позволяет делать быструю проверку доступности сервиса с помощью операции Ping. // // Параметры: // ПараметрыПодключенияWSПрокси - Структура: // * АдресWSDL - Строка - месторасположение wsdl, например, ""http://webservice.net/webservice.asmx?wsdl"". // * URIПространстваИмен - Строка - URI пространства имен web-сервиса, например, ""http://www.webservice.net/WebService/1.0.0.1"". // * ИмяСервиса - Строка - имя сервиса, например, ""WebService_1_0_0_1"". // * ИмяТочкиПодключения - Строка - необязательный параметр. Если не задано, образуется как ""<ИмяСервиса>Soap"". // * ИмяПользователя - Строка - необязательный параметр. Имя пользователя для входа на сервер. // * Пароль - Строка - необязательный параметр. Пароль пользователя. // * Таймаут - Число - необязательный параметр. Таймаут на операции веб-сервиса, выполняемые // через прокси. В секундах. // * Местоположение - Строка - необязательный параметр. Фактический адрес сервиса. Используется, если // адрес реального расположения сервиса отличается от адреса, который указан // в WSDL-файле. // * ИспользоватьАутентификациюОС - Булево - необязательный параметр. Включает использование авторизации NTLM или // Negotiate на сервере. // * ДелатьКонтрольныйВызов - Булево - необязательный параметр. Выполнять проверку доступности сервиса (требуется // поддержка команды Ping в веб-сервисе). По умолчанию, Ложь. // * ЗащищенноеСоединение - ЗащищенноеСоединениеOpenSSL // - Неопределено - необязательные параметры защищенного соединения. // // Возвращаемое значение: // WSПрокси // // Пример: // ПараметрыПодключения = ОбщегоНазначения.ПараметрыПодключенияWSПрокси(); // ПараметрыПодключения.АдресWSDL = ""http://webservice.net/webservice.asmx?wsdl""; // ПараметрыПодключения.URIПространстваИмен = ""http://www.webservice.net/WebService/1.0.0.1""; // ПараметрыПодключения.ИмяСервиса = ""WebService_1_0_0_1""; // ПараметрыПодключения.Таймаут = 20; // Прокси = ОбщегоНазначения.СоздатьWSПрокси(ПараметрыПодключения); // Функция СоздатьWSПрокси(Знач ПараметрыПодключенияWSПрокси) Экспорт ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(""СоздатьWSПрокси"", ""Параметры"", ПараметрыПодключенияWSПрокси, Тип(""Структура""), Новый Структура(""АдресWSDL,URIПространстваИмен,ИмяСервиса"", Тип(""Строка""), Тип(""Строка""), Тип(""Строка""))); ПараметрыПодключения = ПараметрыПодключенияWSПрокси(); ЗаполнитьЗначенияСвойств(ПараметрыПодключения, ПараметрыПодключенияWSПрокси); ДелатьКонтрольныйВызов = ПараметрыПодключения.ДелатьКонтрольныйВызов; Таймаут = ПараметрыПодключения.Таймаут; Если ДелатьКонтрольныйВызов И Таймаут <> Неопределено И Таймаут > 20 Тогда ПараметрыПодключения.Таймаут = 7; WSПроксиPing = РегистрыСведений.КэшПрограммныхИнтерфейсов.ВнутренняяWSПрокси(ПараметрыПодключения); Попытка WSПроксиPing.Ping(); Исключение АдресТочкиПодключения = WSПроксиPing.ТочкаПодключения.Местоположение; ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось проверить доступность web-сервиса |%1 |по причине: |%2'""), ПараметрыПодключения.АдресWSDL, ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())); Если ПодсистемаСуществует(""СтандартныеПодсистемы.ПолучениеФайловИзИнтернета"") Тогда МодульПолучениеФайловИзИнтернета = ОбщийМодуль(""ПолучениеФайловИзИнтернета""); РезультатДиагностики = МодульПолучениеФайловИзИнтернета.ДиагностикаСоединения(АдресТочкиПодключения); ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = '%1 |Результат диагностики: |%2'""), ТекстОшибки, РезультатДиагностики.ОписаниеОшибки); КонецЕсли; ВызватьИсключение ТекстОшибки; КонецПопытки; ПараметрыПодключения.Таймаут = Таймаут; КонецЕсли; Возврат РегистрыСведений.КэшПрограммныхИнтерфейсов.ВнутренняяWSПрокси(ПараметрыПодключения); КонецФункции ///////////////////////////////////////////////////////////////////////////////// // Версионирование программных интерфейсов. // Возвращает номера версий программных интерфейсов удаленной системы, доступной через веб-сервис. // Позволяет обеспечивать полную обратную совместимость при изменениях в программных интерфейсах // с помощью их явного версионирования. Например, если программный интерфейс выше определенной версии, // то только в этом случае допустимо вызывать у него новую функцию. // // В целях экономии трафика при интенсивном взаимодействии между вызывающей и вызываемой сторонами // сведения о версиях кэшируются на одни сутки. Если для целей отладки требуется сбросить кэш раньше этого времени, // следует удалить соответствующие записи из регистра сведений КэшПрограммныхИнтерфейсов. // // Параметры: // Адрес - Строка - адрес веб-сервиса версионирования интерфейсов InterfaceVersion; // Пользователь - Строка - имя пользователя веб-сервиса; // Пароль - Строка - пароль пользователя веб-сервиса; // Интерфейс - Строка - имя запрашиваемого программного интерфейса, например, ""СервисПередачиФайлов"". // // Возвращаемое значение: // ФиксированныйМассив - массив строк, каждая строка является представлением номера версии интерфейса. // Например, ""1.0.2.1"". // // Пример: // Версии = ПолучитьВерсииИнтерфейса(""http://vsrvx/sm"", ""ivanov"",, ""СервисПередачиФайлов""); // // Также для обратной совместимости поддерживается устаревший вариант вызова: // ПараметрыПодключения = Новый Структура; // ПараметрыПодключения.Вставить(""URL"", ""http://vsrvx/sm""); // ПараметрыПодключения.Вставить(""UserName"", ""ivanov""); // ПараметрыПодключения.Вставить(""Password"", ""); // Версии = ПолучитьВерсииИнтерфейса(ПараметрыПодключения, ""СервисПередачиФайлов""); // Функция ПолучитьВерсииИнтерфейса(Знач Адрес, Знач Пользователь, Знач Пароль = Неопределено, Знач Интерфейс = Неопределено) Экспорт Если ТипЗнч(Адрес) = Тип(""Структура"") Тогда // для обратной совместимости ПараметрыПодключения = Адрес; ИмяИнтерфейса = Пользователь; Иначе ПараметрыПодключения = Новый Структура; ПараметрыПодключения.Вставить(""URL"", Адрес); ПараметрыПодключения.Вставить(""UserName"", Пользователь); ПараметрыПодключения.Вставить(""Password"", Пароль); ИмяИнтерфейса = Интерфейс; КонецЕсли; Если Не ПараметрыПодключения.Свойство(""URL"") Или Не ЗначениеЗаполнено(ПараметрыПодключения.URL) Тогда ВызватьИсключение(НСтр(""ru = 'Не задан URL сервиса.'"")); КонецЕсли; ПараметрыПолучения = Новый Массив; ПараметрыПолучения.Добавить(ПараметрыПодключения); ПараметрыПолучения.Добавить(ИмяИнтерфейса); Возврат РегистрыСведений.КэшПрограммныхИнтерфейсов.ДанныеКэшаВерсий( РегистрыСведений.КэшПрограммныхИнтерфейсов.ИдентификаторЗаписиКэшаВерсий(ПараметрыПодключения.URL, ИмяИнтерфейса), Перечисления.ТипыДанныхКэшаПрограммныхИнтерфейсов.ВерсииИнтерфейса, ПараметрыПолучения, Истина); КонецФункции // Возвращает номера версий программных интерфейсов удаленной системы, подключенной через внешнее соединение. // Позволяет обеспечивать полную обратную совместимость при изменениях в программных интерфейсах // с помощью их явного версионирования. Например, если программный интерфейс выше определенной версии, // то только в этом случае допустимо вызывать у него новую функцию. // // Параметры: // ВнешнееСоединение - COMОбъект - внешнее соединение, которое используется для работы с удаленной системой. // ИмяИнтерфейса - Строка - имя запрашиваемого программного интерфейса, например ""СервисПередачиФайлов"". // // Возвращаемое значение: // ФиксированныйМассив - массив строк, каждая строка является представлением номера версии интерфейса. // Например ""1.0.2.1"". // // Пример: // Версии = ОбщегоНазначения.ПолучитьВерсииИнтерфейсаЧерезВнешнееСоединение(ВнешнееСоединение, ""СервисПередачиФайлов""); // Функция ПолучитьВерсииИнтерфейсаЧерезВнешнееСоединение(ВнешнееСоединение, Знач ИмяИнтерфейса) Экспорт Попытка ВерсииИнтерфейсаXML = ВнешнееСоединение.СтандартныеПодсистемыСервер.ПоддерживаемыеВерсии(ИмяИнтерфейса); Исключение СтрокаСообщения = НСтр(""ru = 'Корреспондент не поддерживает версионирование программных интерфейсов. |Описание ошибки: %1'""); СтрокаСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(СтрокаСообщения, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Получение версий интерфейса'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, , , СтрокаСообщения); Возврат Новый ФиксированныйМассив(Новый Массив); КонецПопытки; Возврат Новый ФиксированныйМассив(ЗначениеИзСтрокиXML(ВерсииИнтерфейсаXML)); КонецФункции // Удаляет записи кэша версий программных интерфейсов, содержащих в идентификаторе указанную подстроку. // В качестве подстроки может использоваться, например, имя интерфейса, более не используемого в конфигурации. // // Параметры: // ПодстрокаПоискаИдентификаторов - Строка - подстрока поиска идентификаторов. // Не может содержать символов %, _ и [. // Процедура УдалитьЗаписиКэшаВерсий(Знач ПодстрокаПоискаИдентификаторов) Экспорт НачатьТранзакцию(); Попытка Блокировка = Новый БлокировкаДанных; Блокировка.Добавить(""РегистрСведений.КэшПрограммныхИнтерфейсов""); Блокировка.Заблокировать(); ТекстЗапроса = ""ВЫБРАТЬ | ТаблицаКэша.Идентификатор КАК Идентификатор, | ТаблицаКэша.ТипДанных КАК ТипДанных |ИЗ | РегистрСведений.КэшПрограммныхИнтерфейсов КАК ТаблицаКэша |ГДЕ | ТаблицаКэша.Идентификатор ПОДОБНО ""%ПодстрокаПоиска%"" СПЕЦСИМВОЛ ""~""""; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""ПодстрокаПоиска"", СформироватьСтрокуДляПоискаВЗапросе(ПодстрокаПоискаИдентификаторов)); Запрос = Новый Запрос(ТекстЗапроса); Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл Запись = РегистрыСведений.КэшПрограммныхИнтерфейсов.СоздатьМенеджерЗаписи(); Запись.Идентификатор = Выборка.Идентификатор; Запись.ТипДанных = Выборка.ТипДанных; Запись.Удалить(); КонецЦикла; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ВызватьИсключение; КонецПопытки; КонецПроцедуры #КонецОбласти #Область БезопасноеХранилище //////////////////////////////////////////////////////////////////////////////// // Процедуры и функции для работы с хранилищем паролей. // Записывает конфиденциальные данные в безопасное хранилище. // Вызывающий код должен самостоятельно устанавливать привилегированный режим. // // Безопасное хранилище недоступно для чтения пользователям (кроме администраторов), // а доступно только коду, который делает обращения только к своей части данных и // в том контексте, который предполагает чтение или запись конфиденциальных данных. // // Параметры: // Владелец - ПланОбменаСсылка // - СправочникСсылка // - Строка - ссылка на объект информационной базы, // представляющий объект-владелец сохраняемого пароля или строка до 128 символов. // Для объектов других типов в качестве владельца рекомендуется использовать ссылку на // элемент метаданных этого типа в справочнике ИдентификаторыОбъектовМетаданных // или ключ в виде строки с учетом имен подсистем. // Например, для БСП: // Владелец = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(""РегистрСведений.АдресныеОбъекты""); // если нужно 1 хранилище на подсистему БСП: // Владелец = ""СтандартныеПодсистемы.УправлениеДоступом""; // если нужно более 1 хранилища на подсистему БСП: // Владелец = ""СтандартныеПодсистемы.УправлениеДоступом.<Уточнение>""; // Данные - Произвольный - данные помещаемые в безопасное хранилище. Неопределенно - удаляет все данные. // Для удаления данных по ключу следует использовать процедуру УдалитьДанныеИзБезопасногоХранилища. // - Структура - если параметр Ключ содержит Неопределено. Подробнее см. описание параметра Ключ // Ключ - Строка - ключ сохраняемых настроек, по умолчанию ""Пароль"". // Ключ должен соответствовать правилам имен идентификаторов: // 1. Первым символом ключа должна быть буква или символ подчеркивания (_). // 2. Каждый из последующих символов может быть буквой, цифрой или символом подчеркивания (_). // Неопределено - для добавления набора данных структурой, где ключ структуры - это имя ключа данных, // а значение - сохраняемые данные. Пример использования см. ниже. // // Пример: // // Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи) // Если ТекущийПользовательМожетИзменятьПароль Тогда // УстановитьПривилегированныйРежим(Истина); // ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(ТекущийОбъект.Ссылка, Логин, ""Логин""); // ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(ТекущийОбъект.Ссылка, Пароль); // УстановитьПривилегированныйРежим(Ложь); // КонецЕсли; // КонецПроцедуры // // Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи) // Если ТекущийПользовательМожетИзменятьПароль Тогда // ЛогинИПароль = Новый Структура; // ЛогинИПароль.Вставить(""Логин"", Логин); // ЛогинИПароль.Вставить(""Пароль"", Пароль); // УстановитьПривилегированныйРежим(Истина); // ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(ТекущийОбъект.Ссылка, ЛогинИПароль, Неопределено); // УстановитьПривилегированныйРежим(Ложь); // КонецЕсли; // КонецПроцедуры // Процедура ЗаписатьДанныеВБезопасноеХранилище(Владелец, Данные, Ключ = ""Пароль"") Экспорт ОбщегоНазначенияКлиентСервер.Проверить(ЗначениеЗаполнено(Владелец), СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недопустимое значение параметра %1 в %2. |параметр должен содержать ссылку; передано значение: %3 (тип %4).'""), ""Владелец"", ""ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище"", Владелец, ТипЗнч(Владелец))); Если ЗначениеЗаполнено(Ключ) Тогда ОбщегоНазначенияКлиентСервер.Проверить(ТипЗнч(Ключ) = Тип(""Строка""), СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недопустимое значение параметра %1 в %2. |параметр должен содержать строку; передано значение: %3 (тип %4).'""), ""Ключ"", ""ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище"", Ключ, ТипЗнч(Ключ))); Иначе ОбщегоНазначенияКлиентСервер.Проверить(ТипЗнч(Данные) = Тип(""Структура""), СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недопустимое значение параметра %1 в %2. |Если Ключ = Неопределено, то параметр должен содержать структуру; передано значение: %3 (тип %4).'""), ""Данные"", ""ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище"", Данные, ТипЗнч(Данные))); КонецЕсли; ЭтоОбластьДанных = РазделениеВключено() И ДоступноИспользованиеРазделенныхДанных(); Если ЭтоОбластьДанных Тогда БезопасноеХранилищеДанных = РегистрыСведений.БезопасноеХранилищеДанныхОбластейДанных.СоздатьМенеджерЗаписи(); Иначе БезопасноеХранилищеДанных = РегистрыСведений.БезопасноеХранилищеДанных.СоздатьМенеджерЗаписи(); КонецЕсли; БезопасноеХранилищеДанных.Владелец = Владелец; БезопасноеХранилищеДанных.Прочитать(); Если Данные <> Неопределено Тогда Если БезопасноеХранилищеДанных.Выбран() Тогда ДанныеДляСохранения = БезопасноеХранилищеДанных.Данные.Получить(); Если ТипЗнч(ДанныеДляСохранения) <> Тип(""Структура"") Тогда ДанныеДляСохранения = Новый Структура(); КонецЕсли; Если ЗначениеЗаполнено(Ключ) Тогда ДанныеДляСохранения.Вставить(Ключ, Данные); Иначе ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(ДанныеДляСохранения, Данные, Истина); КонецЕсли; ДанныеДляХранилищеЗначения = Новый ХранилищеЗначения(ДанныеДляСохранения, Новый СжатиеДанных(6)); БезопасноеХранилищеДанных.Данные = ДанныеДляХранилищеЗначения; БезопасноеХранилищеДанных.Записать(); Иначе ДанныеДляСохранения = ?(ЗначениеЗаполнено(Ключ), Новый Структура(Ключ, Данные), Данные); ДанныеДляХранилищеЗначения = Новый ХранилищеЗначения(ДанныеДляСохранения, Новый СжатиеДанных(6)); БезопасноеХранилищеДанных.Данные = ДанныеДляХранилищеЗначения; БезопасноеХранилищеДанных.Владелец = Владелец; БезопасноеХранилищеДанных.Записать(); КонецЕсли; Иначе БезопасноеХранилищеДанных.Удалить(); КонецЕсли; КонецПроцедуры // Возвращает данные из безопасного хранилища. // Вызывающий код должен самостоятельно устанавливать привилегированный режим. // // Безопасное хранилище недоступно для чтения пользователям (кроме администраторов), // а доступно только коду, который делает обращения только к своей части данных и // в том контексте, который предполагает чтение или запись конфиденциальных данных. // // Параметры: // Владельцы - Массив из ПланОбменаСсылка // - Массив из СправочникСсылка // - Массив из Строка - ссылки на объекты информационной базы, // представляющих объекты-владельцы или уникальные строки(до 128 символов) владельцев данных. // Ключи - Строка - содержит имя ключа данных или список имен ключей, указанных через запятую. // - Неопределено - будут возвращены все сохраненные данные переданных владельцев. // ОбщиеДанные - Булево - Истина, если требуется в модели сервиса получить данные из общих данных в разделенном режиме. // // Возвращаемое значение: // Соответствие из КлючИЗначение: // * Ключ - ПланОбменаСсылка // - СправочникСсылка // - Строка - ссылка на объект информационной базы // или строка до 128 символов идентифицирующая владельца данных. // * Значение - Произвольный - если в параметре Ключи указан один ключ, // то возвращается его значение произвольного типа. // - Структура - если в параметре Ключи указано несколько ключей или Неопределено, // где ключ структуры - это имя ключа сохраненных данных, // а значение - данные произвольного типа. Когда для ключа отсутствуют данные, // то значение содержит Неопределено. // - Неопределено - если данные по ключу отсутствуют. // // Пример: // Процедура РассылкаПриглашений(Пользователи) // // УстановитьПривилегированныйРежим(Истина); // ДанныеАвторизации = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(Пользователи, ""Логин, Пароль""); // УстановитьПривилегированныйРежим(Ложь); // // Для каждого Пользователь Из Пользователи Цикл // ОтправитьПриглашение(Пользователь, ДанныеАвторизации[Пользователь]); // КонецЦикла; // // КонецПроцедуры // Функция ПрочитатьДанныеВладельцевИзБезопасногоХранилища(Владельцы, Ключи = ""Пароль"", ОбщиеДанные = Неопределено) Экспорт ОбщегоНазначенияКлиентСервер.Проверить(ТипЗнч(Владельцы) = Тип(""Массив""), СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недопустимое значение параметра %1 в %2. |параметр должен содержать массив; передано значение: %3 (тип %4).'""), ""Владельцы"", ""ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища"", Владельцы, ТипЗнч(Владельцы))); Результат = ДанныеИзБезопасногоХранилища(Владельцы, Ключи, ОбщиеДанные); Возврат Результат; КонецФункции // Возвращает данные из безопасного хранилища. // Вызывающий код должен самостоятельно устанавливать привилегированный режим. // // Безопасное хранилище недоступно для чтения пользователям (кроме администраторов), // а доступно только коду, который делает обращения только к своей части данных и // в том контексте, который предполагает чтение или запись конфиденциальных данных. // // Параметры: // Владелец - ПланОбменаСсылка // - СправочникСсылка // - Строка - ссылка на объект информационной базы, // представляющий объект-владелец сохраняемого пароля или уникальная строка(до 128 символов). // Ключи - Строка - содержит список имен сохраненных данных, указанных через запятую. // - Неопределено - будут возвращены все сохраненные данные владельца. // ОбщиеДанные - Булево - Истина, если требуется в модели сервиса получить данные из общих данных в разделенном режиме. // // Возвращаемое значение: // Произвольный, Структура, Неопределено - данные из безопасного хранилища. Если указан один ключ, // то возвращается его значение, иначе структура. // Если данные отсутствуют - Неопределенно. // // Пример: // Если ТекущийПользовательМожетИзменятьПароль Тогда // УстановитьПривилегированныйРежим(Истина); // Логин = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(ТекущийОбъект.Ссылка, ""Логин""); // Пароль = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(ТекущийОбъект.Ссылка); // УстановитьПривилегированныйРежим(Ложь); // Иначе // Элементы.ГруппаЛогинИПароль.Видимость = Ложь; // КонецЕсли; // // УстановитьПривилегированныйРежим(Истина); // ЛогинИПароль = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(ТекущийОбъект.Ссылка, Неопределено); // Функция ПрочитатьДанныеИзБезопасногоХранилища(Владелец, Ключи = ""Пароль"", ОбщиеДанные = Неопределено) Экспорт Владельцы = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Владелец); ДанныеВладельца = ПрочитатьДанныеВладельцевИзБезопасногоХранилища(Владельцы, Ключи, ОбщиеДанные); Результат = ДанныеВладельца[Владелец]; Возврат Результат; КонецФункции // Удаляет конфиденциальные данные в безопасное хранилище. // Вызывающий код должен самостоятельно устанавливать привилегированный режим. // // Безопасное хранилище недоступно для чтения пользователям (кроме администраторов), // а доступно только коду, который делает обращения только к своей части данных и // в том контексте, который предполагает чтение или запись конфиденциальных данных. // // Параметры: // Владелец - ПланОбменаСсылка // - СправочникСсылка // - Строка - ссылка на объект информационной базы, // представляющий объект-владелец сохраняемого пароля или уникальная строка(до 128 символов). // - Массив - ссылки на объекты информационной базы для удаления данным по нескольким владельцам. // Ключи - Строка - содержит список имен удаляемых данных, указанных через запятую. // Неопределено - удаляет все данные. // // Пример: // Процедура ПередУдалением(Отказ) // // // Проверка значения свойства ОбменДанными.Загрузка отсутствует, так как удалять данные // // из безопасного хранилища нужно даже при удалении объекта при обмене данными. // // УстановитьПривилегированныйРежим(Истина); // ОбщегоНазначения.УдалитьДанныеИзБезопасногоХранилища(Ссылка); // УстановитьПривилегированныйРежим(Ложь); // // КонецПроцедуры // Процедура УдалитьДанныеИзБезопасногоХранилища(Владелец, Ключи = Неопределено) Экспорт ОбщегоНазначенияКлиентСервер.Проверить(ЗначениеЗаполнено(Владелец), СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Недопустимое значение параметра %1 в %2. |параметр должен содержать ссылку; передано значение: %3 (тип %4).'""), ""Владелец"", ""ОбщегоНазначения.УдалитьДанныеИзБезопасногоХранилища"", Владелец, ТипЗнч(Владелец))); Если РазделениеВключено() И ДоступноИспользованиеРазделенныхДанных() Тогда БезопасноеХранилищеДанных = РегистрыСведений.БезопасноеХранилищеДанныхОбластейДанных.СоздатьМенеджерЗаписи(); Иначе БезопасноеХранилищеДанных = РегистрыСведений.БезопасноеХранилищеДанных.СоздатьМенеджерЗаписи(); КонецЕсли; Владельцы = ?(ТипЗнч(Владелец) = Тип(""Массив""), Владелец, ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Владелец)); Для Каждого ВладелецДанных Из Владельцы Цикл БезопасноеХранилищеДанных.Владелец = ВладелецДанных; БезопасноеХранилищеДанных.Прочитать(); Если ТипЗнч(БезопасноеХранилищеДанных.Данные) = Тип(""ХранилищеЗначения"") Тогда ДанныеДляСохранения = БезопасноеХранилищеДанных.Данные.Получить(); Если Ключи <> Неопределено И ТипЗнч(ДанныеДляСохранения) = Тип(""Структура"") Тогда СписокКлючей = СтрРазделить(Ключи, "","", Ложь); Если БезопасноеХранилищеДанных.Выбран() И СписокКлючей.Количество() > 0 Тогда Для каждого КлючДляУдаления Из СписокКлючей Цикл Если ДанныеДляСохранения.Свойство(КлючДляУдаления) Тогда ДанныеДляСохранения.Удалить(КлючДляУдаления); КонецЕсли; КонецЦикла; ДанныеДляХранилищеЗначения = Новый ХранилищеЗначения(ДанныеДляСохранения, Новый СжатиеДанных(6)); БезопасноеХранилищеДанных.Данные = ДанныеДляХранилищеЗначения; БезопасноеХранилищеДанных.Записать(); Возврат; КонецЕсли; КонецЕсли; КонецЕсли; БезопасноеХранилищеДанных.Удалить(); КонецЦикла; КонецПроцедуры #КонецОбласти #Область БуферОбмена //////////////////////////////////////////////////////////////////////////////// // Процедуры и функции для работы с внутренним буфером обмена. // Помещает выделенные строки табличной части во внутренний буфер обмена // откуда их можно получить с помощью СтрокиИзБуфераОбмена. // // Параметры: // ТабличнаяЧасть - ДанныеФормыКоллекция - табличная часть, строки которой // необходимо поместить во внутренний буфер обмена. // ВыделенныеСтроки - Массив - массив идентификаторов выделенных строк. // Источник - Строка - произвольный строковый идентификатор, например, имя объекта, // строки табличной части которого помещаются во внутренний буфер обмена. // Процедура СкопироватьСтрокиВБуферОбмена(ТабличнаяЧасть, ВыделенныеСтроки, Источник = Неопределено) Экспорт Если ВыделенныеСтроки = Неопределено Тогда Возврат; КонецЕсли; ТаблицаЗначений = ТабличнаяЧасть.Выгрузить(); ТаблицаЗначений.Очистить(); УдаляемыеКолонки = Новый Массив; УдаляемыеКолонки.Добавить(""ИсходныйНомерСтроки""); УдаляемыеКолонки.Добавить(""НомерСтроки""); Для Каждого ИмяКолонки Из УдаляемыеКолонки Цикл Колонка = ТаблицаЗначений.Колонки.Найти(ИмяКолонки); Если Колонка = Неопределено Тогда Продолжить; КонецЕсли; ТаблицаЗначений.Колонки.Удалить(Колонка); КонецЦикла; Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл КопируемаяСтрока = ТабличнаяЧасть.НайтиПоИдентификатору(ИдентификаторСтроки); ЗаполнитьЗначенияСвойств(ТаблицаЗначений.Добавить(), КопируемаяСтрока); КонецЦикла; СкопироватьВБуферОбмена(ТаблицаЗначений, Источник); КонецПроцедуры // Помещает произвольные данные во внутренний буфер обмена, откуда их можно получить с помощью СтрокиИзБуфераОбмена. // // Параметры: // Данные - Произвольный - данные, которые необходимо поместить в внутренний буфер обмена. // Источник - Строка - произвольный строковый идентификатор, например, имя объекта, // строки табличной части которого помещаются во внутренний буфер обмена. // Процедура СкопироватьВБуферОбмена(Данные, Источник = Неопределено) Экспорт ТекущийБуферОбмена = ПараметрыСеанса.БуферОбмена; Если ЗначениеЗаполнено(ТекущийБуферОбмена.Данные) Тогда Адрес = ТекущийБуферОбмена.Данные; Иначе Адрес = Новый УникальныйИдентификатор; КонецЕсли; ДанныеВХранилище = ПоместитьВоВременноеХранилище(Данные, Адрес); СтруктураБуфераОбмена = Новый Структура; СтруктураБуфераОбмена.Вставить(""Источник"", Источник); СтруктураБуфераОбмена.Вставить(""Данные"", ДанныеВХранилище); ПараметрыСеанса.БуферОбмена = Новый ФиксированнаяСтруктура(СтруктураБуфераОбмена); КонецПроцедуры // Получает строки табличной части, помещенные во внутренний буфер обмена с помощью СкопироватьСтрокиВБуферОбмена. // // Возвращаемое значение: // Структура: // * Данные - Произвольный - данные из внутреннего буфера обмена. // Например, ТаблицаЗначений при вызове СкопироватьСтрокиВБуферОбмена. // * Источник - Строка - объект, к которому относятся данные. // Если при помещении во внутренний буфер не был указан, то Неопределено. // Функция СтрокиИзБуфераОбмена() Экспорт Результат = Новый Структура; Результат.Вставить(""Источник"", Неопределено); Результат.Вставить(""Данные"", Неопределено); Если ПустойБуферОбмена() Тогда Возврат Результат; КонецЕсли; ТекущийБуферОбмена = ПараметрыСеанса.БуферОбмена; // см. СтрокиИзБуфераОбмена Результат.Источник = ТекущийБуферОбмена.Источник; Результат.Данные = ПолучитьИзВременногоХранилища(ТекущийБуферОбмена.Данные); Возврат Результат; КонецФункции // Проверяет наличие сохраненных данных во внутренний буфере обмена. // // Параметры: // Источник - Строка - если передан, то проверяется наличие данных // в внутреннем буфере обмена с этим ключом. // По умолчанию - Неопределено. // Возвращаемое значение: // Булево - Истина, если пустой. // Функция ПустойБуферОбмена(Источник = Неопределено) Экспорт ТекущийБуферОбмена = ПараметрыСеанса.БуферОбмена; // см. СтрокиИзБуфераОбмена ИсточникСовпадает = Истина; Если Источник <> Неопределено Тогда ИсточникСовпадает = (Источник = ТекущийБуферОбмена.Источник); КонецЕсли; Возврат (Не ИсточникСовпадает Или Не ЗначениеЗаполнено(ТекущийБуферОбмена.Данные)); КонецФункции #КонецОбласти #Область БезопасноеВыполнениеВнешнегоКода //////////////////////////////////////////////////////////////////////////////// // Функции для поддержки работы конфигурации с профилем безопасности, в котором // запрещено подключение внешних модулей без установки безопасного режима. // // Выполнить экспортную процедуру по имени с уровнем привилегий конфигурации. // При включении профилей безопасности для вызова оператора Выполнить() используется // переход в безопасный режим с профилем безопасности, используемым для информационной базы // (если выше по стеку не был установлен другой безопасный режим). // // Параметры: // ИмяМетода - Строка - имя экспортной процедуры в формате // <имя объекта>.<имя процедуры>, где <имя объекта> - это // общий модуль или модуль менеджера объекта. // Параметры - Массив - параметры передаются в процедуру <ИмяЭкспортнойПроцедуры> // в порядке расположения элементов массива. // // Пример: // Параметры = Новый Массив(); // Параметры.Добавить(""1""); // ОбщегоНазначения.ВыполнитьМетодКонфигурации(""МойОбщийМодуль.МояПроцедура"", Параметры); // Процедура ВыполнитьМетодКонфигурации(Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт ПроверитьИмяПроцедурыКонфигурации(ИмяМетода); Если ПодсистемаСуществует(""СтандартныеПодсистемы.ПрофилиБезопасности"") Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности() И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы(); Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда УстановитьБезопасныйРежим(ПрофильИнформационнойБазы); Если БезопасныйРежим() = Истина Тогда УстановитьБезопасныйРежим(Ложь); КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; ПараметрыСтрока = ""; Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда Для Индекс = 0 По Параметры.ВГраница() Цикл ПараметрыСтрока = ПараметрыСтрока + ""Параметры["" + XMLСтрока(Индекс) + ""],""; КонецЦикла; ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1); КонецЕсли; Выполнить ИмяМетода + ""("" + ПараметрыСтрока + "")""; КонецПроцедуры // Выполнить экспортную процедуру объекта встроенного языка по имени. // При включении профилей безопасности для вызова оператора Выполнить() используется // переход в безопасный режим с профилем безопасности, используемым для информационной базы // (если выше по стеку не был установлен другой безопасный режим). // // Параметры: // Объект - Произвольный - объект встроенного языка 1С:Предприятия, содержащий методы (например, ОбработкаОбъект). // ИмяМетода - Строка - имя экспортной процедуры модуля объекта обработки. // Параметры - Массив - параметры передаются в процедуру <ИмяПроцедуры> // в порядке расположения элементов массива. // Процедура ВыполнитьМетодОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт // Проверка имени метода на корректность. Попытка Тест = Новый Структура(ИмяМетода, ИмяМетода); Если Тест = Неопределено Тогда ВызватьИсключение НСтр(""ru = 'Синтетический тест'""); КонецЕсли; Исключение ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Некорректное значение параметра %1 (%2) в %3.'""), ""ИмяМетода"", ИмяМетода, ""ОбщегоНазначения.ВыполнитьМетодОбъекта""); КонецПопытки; Если ПодсистемаСуществует(""СтандартныеПодсистемы.ПрофилиБезопасности"") Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности() И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы(); Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда УстановитьБезопасныйРежим(ПрофильИнформационнойБазы); Если БезопасныйРежим() = Истина Тогда УстановитьБезопасныйРежим(Ложь); КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; ПараметрыСтрока = ""; Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда Для Индекс = 0 По Параметры.ВГраница() Цикл ПараметрыСтрока = ПараметрыСтрока + ""Параметры["" + XMLСтрока(Индекс) + ""],""; КонецЦикла; ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1); КонецЕсли; Выполнить ""Объект."" + ИмяМетода + ""("" + ПараметрыСтрока + "")""; КонецПроцедуры // Выполняет произвольный алгоритм на встроенном языке 1С:Предприятия, предварительно устанавливая // безопасный режим выполнения кода и безопасный режим разделения данных для всех разделителей, // присутствующих в составе конфигурации. // // Параметры: // Алгоритм - Строка - алгоритм на встроенном языке ""1С:Предприятия"". // Параметры - Произвольный - контекст, который требуется для выполнения алгоритма. // В тексте алгоритма обращение к контексту должно происходить по имени ""Параметры"". // Например, выражение ""Параметры.Значение1 = Параметры.Значение2"" обращается к значениям // ""Значение1"" и ""Значение2"", переданным в Параметры, как свойства. // // Пример: // // Параметры = Новый Структура; // Параметры.Вставить(""Значение1"", 1); // Параметры.Вставить(""Значение2"", 10); // ОбщегоНазначения.ВыполнитьВБезопасномРежиме(""Параметры.Значение1 = Параметры.Значение2"", Параметры); // Процедура ВыполнитьВБезопасномРежиме(Знач Алгоритм, Знач Параметры = Неопределено) Экспорт УстановитьБезопасныйРежим(Истина); Если ПодсистемаСуществует(""ТехнологияСервиса.БазоваяФункциональность"") Тогда МодульРаботаВМоделиСервиса = ОбщийМодуль(""РаботаВМоделиСервиса""); МассивРазделителей = МодульРаботаВМоделиСервиса.РазделителиКонфигурации(); Иначе МассивРазделителей = Новый Массив; КонецЕсли; Для Каждого ИмяРазделителя Из МассивРазделителей Цикл УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина); КонецЦикла; Выполнить Алгоритм; КонецПроцедуры // Вычисляет переданное выражение, предварительно устанавливая безопасный режим выполнения кода // и безопасный режим разделения данных для всех разделителей, присутствующих в составе конфигурации. // // Параметры: // Выражение - Строка - выражение на встроенном языке 1С:Предприятия. // Параметры - Произвольный - контекст, который требуется для вычисления выражения. // В тексте выражения обращение к контексту должно происходить по имени ""Параметры"". // Например, выражение ""Параметры.Значение1 = Параметры.Значение2"" обращается к значениям // ""Значение1"" и ""Значение2"" переданные в Параметры, как свойства. // // Возвращаемое значение: // Произвольный - результат вычисления выражения. // // Пример: // // // Пример 1 // Параметры = Новый Структура; // Параметры.Вставить(""Значение1"", 1); // Параметры.Вставить(""Значение2"", 10); // Результат = ОбщегоНазначения.ВычислитьВБезопасномРежиме(""Параметры.Значение1 = Параметры.Значение2"", Параметры); // // // Пример 2 // Результат = ОбщегоНазначения.ВычислитьВБезопасномРежиме(""СтандартныеПодсистемыСервер.ВерсияБиблиотеки()""); // Функция ВычислитьВБезопасномРежиме(Знач Выражение, Знач Параметры = Неопределено) Экспорт УстановитьБезопасныйРежим(Истина); Если ПодсистемаСуществует(""ТехнологияСервиса.БазоваяФункциональность"") Тогда МодульРаботаВМоделиСервиса = ОбщийМодуль(""РаботаВМоделиСервиса""); МассивРазделителей = МодульРаботаВМоделиСервиса.РазделителиКонфигурации(); Иначе МассивРазделителей = Новый Массив; КонецЕсли; Для Каждого ИмяРазделителя Из МассивРазделителей Цикл УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина); КонецЦикла; Возврат Вычислить(Выражение); КонецФункции // Возвращает описание защиты от опасных действий с отключенными предупреждениями. // // Возвращаемое значение: // ОписаниеЗащитыОтОпасныхДействий - со свойством ПредупреждатьОбОпасныхДействиях = Ложь. // Функция ОписаниеЗащитыБезПредупреждений() Экспорт ОписаниеЗащиты = Новый ОписаниеЗащитыОтОпасныхДействий; ОписаниеЗащиты.ПредупреждатьОбОпасныхДействиях = Ложь; Возврат ОписаниеЗащиты; КонецФункции #КонецОбласти #Область Запросы // Подготавливает строку для использования в качестве шаблона поиска в запросе с оператором ПОДОБНО. // Экранирует служебные символы, если они есть в строке. // // Параметры: // СтрокаПоиска - Строка - произвольная строка. // // Возвращаемое значение: // Строка // // Пример: // ВЫБРАТЬ // Номенклатура.Ссылка КАК Ссылка // ИЗ // Справочник.Номенклатура КАК Номенклатура // ГДЕ // Номенклатура.Наименование ПОДОБНО &Шаблон СПЕЦСИМВОЛ ""~"" // // Запрос.УстановитьПараметр(""Шаблон"", ОбщегоНазначения.СформироватьСтрокуДляПоискаВЗапросе(ИскомыйТекст)); // Функция СформироватьСтрокуДляПоискаВЗапросе(Знач СтрокаПоиска) Экспорт Результат = СтрокаПоиска; Результат = СтрЗаменить(Результат, ""~"", ""~~""); Результат = СтрЗаменить(Результат, ""%"", ""~%""); Результат = СтрЗаменить(Результат, ""_"", ""~_""); Результат = СтрЗаменить(Результат, ""["", ""~[""); Результат = СтрЗаменить(Результат, ""]"", ""~]""); Результат = СтрЗаменить(Результат, ""^"", ""~^""); Возврат Результат; КонецФункции // Возвращает фрагмент текста запроса, отделяющего один запрос от другого. // // Возвращаемое значение: // Строка - разделитель запросов. // Функция РазделительПакетаЗапросов() Экспорт Возврат "" |; | |//////////////////////////////////////////////////////////////////////////////// |""; КонецФункции #КонецОбласти #Область Прочее // Выполняет проверки перед выполнением обработчика регламентного задания и прерывает выполнение, // если его запуск в данный момент невозможен, например: // - еще не завершено обновление программы; // - запуск через консоль или другим способом, минуя включение функциональной опции // (если регламентное задание зависит от функциональных опций); // - попытка выполнения задания, работающего с внешними ресурсами в копии информационной базы. // // Параметры: // РегламентноеЗадание - ОбъектМетаданныхРегламентноеЗадание - регламентное задание, // из которого вызывается данная процедура. // // Пример: // ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.<ИмяРегламентногоЗадания>); // Процедура ПриНачалеВыполненияРегламентногоЗадания(РегламентноеЗадание = Неопределено) Экспорт УстановитьПривилегированныйРежим(Истина); Если РегистрыСведений.ПараметрыРаботыПрограммы.НеобходимоОбновление() Тогда Текст = НСтр(""ru = 'Вход в программу временно невозможен в связи с обновлением на новую версию. |Рекомендуется запрещать выполнение регламентных заданий на время обновления.'""); РегламентныеЗаданияСервер.ОтменитьВыполнениеЗадания(РегламентноеЗадание, Текст); ВызватьИсключение Текст; КонецЕсли; Если Не РазделениеВключено() И ПланыОбмена.ГлавныйУзел() = Неопределено И ЗначениеЗаполнено(Константы.ГлавныйУзел.Получить()) Тогда Текст = НСтр(""ru = 'Вход в программу временно невозможен до восстановления связи с главным узлом. |Рекомендуется запрещать выполнение регламентных заданий на время восстановления.'""); РегламентныеЗаданияСервер.ОтменитьВыполнениеЗадания(РегламентноеЗадание, Текст); ВызватьИсключение Текст; КонецЕсли; Если РегламентноеЗадание <> Неопределено И ПодсистемаСуществует(""СтандартныеПодсистемы.РегламентныеЗадания"") Тогда МодульБлокировкаРаботыСВнешнимиРесурсами = ОбщийМодуль(""БлокировкаРаботыСВнешнимиРесурсами""); МодульБлокировкаРаботыСВнешнимиРесурсами.ПриНачалеВыполненияРегламентногоЗадания(РегламентноеЗадание); МодульРегламентныеЗаданияСлужебный = ОбщийМодуль(""РегламентныеЗаданияСлужебный""); Доступно = МодульРегламентныеЗаданияСлужебный.РегламентноеЗаданиеДоступноПоФункциональнымОпциям(РегламентноеЗадание); Если Не Доступно Тогда Задания = РегламентныеЗаданияСервер.НайтиЗадания(Новый Структура(""Метаданные"", РегламентноеЗадание)); Для Каждого Задание Из Задания Цикл РегламентныеЗаданияСервер.ИзменитьЗадание(Задание.УникальныйИдентификатор, Новый Структура(""Использование"", Ложь)); КонецЦикла; Текст = НСтр(""ru = 'Регламентное задание недоступно по функциональным опциям или |не поддерживает работу в текущем режиме работы программы. |Выполнение прервано. Задание отключено.'""); РегламентныеЗаданияСервер.ОтменитьВыполнениеЗадания(РегламентноеЗадание, Текст); ВызватьИсключение Текст; КонецЕсли; КонецЕсли; Если СтандартныеПодсистемыСервер.ТребуетсяУстановкаРегиональныхНастроекИнформационнойБазы() Тогда Текст = НСтр(""ru = 'Регламентное задание недоступно до установки начальных региональных настроек программы. |Выполнение прервано.'""); РегламентныеЗаданияСервер.ОтменитьВыполнениеЗадания(РегламентноеЗадание, Текст); ВызватьИсключение Текст; КонецЕсли; Справочники.ВерсииРасширений.ЗарегистрироватьИспользованиеВерсииРасширений(); РегистрыСведений.ПараметрыРаботыВерсийРасширений.ПриУспешномНачалеВыполненияРегламентногоЗадания(); КонецПроцедуры // Переводит параметры сеанса в состояние ""Не установлено"". // // Параметры: // ПараметрыДляОчистки - Строка - имена параметров сеанса для очистки, разделенные "","". // Исключения - Строка - имена параметров сеанса не предназначенные для очистки, разделенные "","". // Процедура ОчиститьПараметрыСеанса(ПараметрыДляОчистки = "", Исключения = "") Экспорт МассивИсключений = СтрРазделить(Исключения, "",""); МассивПараметровДляОчистки = СтрРазделить(ПараметрыДляОчистки, "","", Ложь); Если МассивПараметровДляОчистки.Количество() = 0 Тогда Для Каждого ПараметрСеанса Из Метаданные.ПараметрыСеанса Цикл Если МассивИсключений.Найти(ПараметрСеанса.Имя) = Неопределено Тогда МассивПараметровДляОчистки.Добавить(ПараметрСеанса.Имя); КонецЕсли; КонецЦикла; КонецЕсли; Индекс = МассивПараметровДляОчистки.Найти(""ПараметрыКлиентаНаСервере""); Если Индекс <> Неопределено Тогда МассивПараметровДляОчистки.Удалить(Индекс); КонецЕсли; Индекс = МассивПараметровДляОчистки.Найти(""ОсновнойЯзык""); Если Индекс <> Неопределено Тогда МассивПараметровДляОчистки.Удалить(Индекс); КонецЕсли; Индекс = МассивПараметровДляОчистки.Найти(""УстановленныеРасширения""); Если Индекс <> Неопределено Тогда МассивПараметровДляОчистки.Удалить(Индекс); КонецЕсли; ПараметрыСеанса.Очистить(МассивПараметровДляОчистки); КонецПроцедуры // Проверяет, умещаются ли переданные табличные документы на страницу при печати. // // Параметры: // ТабДокумент - ТабличныйДокумент - табличный документ. // ВыводимыеОбласти - Массив // - ТабличныйДокумент - массив из проверяемых таблиц или табличный документ. // РезультатПриОшибке - Булево - какой возвращать результат при возникновении ошибки. // // Возвращаемое значение: // Булево - умещаются или нет переданные документы. // Функция ПроверитьВыводТабличногоДокумента(ТабДокумент, ВыводимыеОбласти, РезультатПриОшибке = Истина) Экспорт Попытка Возврат ТабДокумент.ПроверитьВывод(ВыводимыеОбласти); Исключение Возврат РезультатПриОшибке; КонецПопытки; КонецФункции // Сохраняет персональные настройки пользователя, относящиеся к подсистеме БазоваяФункциональность. // Для получения настроек предусмотрены следующие функции: // - ОбщегоНазначенияКлиент.ПредлагатьУстановкуРасширенияРаботыСФайлами(), // - СтандартныеПодсистемыСервер.ЗапрашиватьПодтверждениеПриЗавершенииПрограммы(), // - СтандартныеПодсистемыСервер.ПоказыватьПредупреждениеОбУстановленныхОбновленияхПрограммы(). // // Параметры: // Настройки - Структура: // * НапоминатьОбУстановкеРасширенияРаботыСФайлами - Булево - признак необходимости // напоминания об установке расширения. // * ЗапрашиватьПодтверждениеПриЗавершенииПрограммы - Булево - запрашивать подтверждение по завершении работы. // * ПоказыватьПредупреждениеОбУстановленныхОбновленияхПрограммы - Булево - показывать оповещение при // динамическом обновлении программы. // Процедура СохранитьПерсональныеНастройки(Настройки) Экспорт Если Настройки.Свойство(""НапоминатьОбУстановкеРасширенияРаботыСФайлами"") Тогда Если ЭтоВебКлиент() Тогда ИдентификаторКлиента = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ИдентификаторКлиента""); Если ИдентификаторКлиента = Неопределено Тогда СистемнаяИнформация = Новый СистемнаяИнформация; ИдентификаторКлиента = СистемнаяИнформация.ИдентификаторКлиента; КонецЕсли; ХранилищеОбщихНастроекСохранить( ""НастройкиПрограммы/ПредлагатьУстановкуРасширенияРаботыСФайлами"", ИдентификаторКлиента, Настройки.НапоминатьОбУстановкеРасширенияРаботыСФайлами); КонецЕсли; КонецЕсли; Если Настройки.Свойство(""ЗапрашиватьПодтверждениеПриЗавершенииПрограммы"") Тогда ХранилищеОбщихНастроекСохранить(""ОбщиеНастройкиПользователя"", ""ЗапрашиватьПодтверждениеПриЗавершенииПрограммы"", Настройки.ЗапрашиватьПодтверждениеПриЗавершенииПрограммы); КонецЕсли; Если Настройки.Свойство(""ПоказыватьПредупреждениеОбУстановленныхОбновленияхПрограммы"") Тогда ХранилищеОбщихНастроекСохранить(""ОбщиеНастройкиПользователя"", ""ПоказыватьПредупреждениеОбУстановленныхОбновленияхПрограммы"", Настройки.ПоказыватьПредупреждениеОбУстановленныхОбновленияхПрограммы); КонецЕсли; КонецПроцедуры // Выполняет пропорциональное распределение суммы в соответствии // с заданными коэффициентами распределения. // // Параметры: // РаспределяемаяСумма - Число - сумма, которую надо распределить, если сумма равна 0 - то возвращается Неопределено; // Если передана отрицательная - расчет по модулю и после инверсия знаков результата. // Коэффициенты - Массив из Число - коэффициенты распределения, должны быть положительны или отрицательными // одновременно. // Точность - Число - точность округления при распределении. // // Возвращаемое значение: // Массив из Число - массив размерностью равный массиву коэффициентов, содержит // суммы в соответствии с весом коэффициента (из массива коэффициентов). // В случае, если распределить невозможно (кол-во коэффициентов = 0 // есть коэффициенты с отрицательным значением или суммарный вес коэффициентов = 0), // тогда будет возвращено Неопределено. // // Пример: // // Коэффициенты = Новый Массив; // Коэффициенты.Добавить(1); // Коэффициенты.Добавить(2); // Результат = ОбщегоНазначенияКлиентСервер.РаспределитьСуммуПропорциональноКоэффициентам(1, Коэффициенты); // // Результат = [0.33, 0.67] // Функция РаспределитьСуммуПропорциональноКоэффициентам( Знач РаспределяемаяСумма, Коэффициенты, Знач Точность = 2) Экспорт Возврат ОбщегоНазначенияКлиентСервер.РаспределитьСуммуПропорциональноКоэффициентам( РаспределяемаяСумма, Коэффициенты, Точность); КонецФункции // Процедура предназначена для заполнения реквизита формы типа ДанныеФормыДерево. // // Параметры: // КоллекцияЭлементовДерева - ДанныеФормыКоллекцияЭлементовДерева - реквизит, который нужно заполнить. // ДеревоЗначений - ДеревоЗначений - данные для заполнения. // Процедура ЗаполнитьКоллекциюЭлементовДереваДанныхФормы(КоллекцияЭлементовДерева, ДеревоЗначений) Экспорт Для Каждого Строка Из ДеревоЗначений.Строки Цикл ЭлементДерева = КоллекцияЭлементовДерева.Добавить(); ЗаполнитьЗначенияСвойств(ЭлементДерева, Строка); Если Строка.Строки.Количество() > 0 Тогда ЗаполнитьКоллекциюЭлементовДереваДанныхФормы(ЭлементДерева.ПолучитьЭлементы(), Строка); КонецЕсли; КонецЦикла; КонецПроцедуры // Подключает внешнюю компоненту, выполненную по технологии Native API или COM, // из макета конфигурации (хранится в виде ZIP-архива). // // Параметры: // Идентификатор - Строка - идентификатор объекта внешней компоненты. // ПолноеИмяМакета - Строка - полное имя макета конфигурации с ZIP-архивом. // Изолированно - Булево, Неопределено - (по умолчанию Ложь) если Истина, компонента будет подключена // изолированно, в этом случае внешняя компонента загружается в отдельный процесс операционной системы; // Ложь - в этом случае внешняя компонента будет выполняться в том же процессе операционной системы, // который выполняет код встроенного языка; Неопределено - поддерживается поведение платформы по умолчанию: // не изолированно - если компонентой поддерживается только этот режим, изолированно - в остальных случаях. // См. https://its.1c.eu/db/v83doc#bookmark:dev:TI000001866 // // // Возвращаемое значение: // ОбъектВнешнейКомпоненты, Неопределено - экземпляр объекта внешней компоненты или Неопределено, если не удалось создать. // // Пример: // // ПодключаемыйМодуль = ОбщегоНазначения.ПодключитьКомпонентуИзМакета( // ""QRCodeExtension"", // ""ОбщийМакет.КомпонентаПечатиQRКода""); // // Если ПодключаемыйМодуль <> Неопределено Тогда // // ПодключаемыйМодуль содержит созданный экземпляр подключенной компоненты. // КонецЕсли; // // ПодключаемыйМодуль = Неопределено; // Функция ПодключитьКомпонентуИзМакета(Знач Идентификатор, Знач ПолноеИмяМакета, Знач Изолированно = Ложь) Экспорт РезультатПроверкиВнешнейКомпоненты = Неопределено; Если ПодсистемаСуществует(""СтандартныеПодсистемы.ВнешниеКомпоненты"") Тогда МодульВнешниеКомпонентыСлужебный = ОбщийМодуль(""ВнешниеКомпонентыСлужебный""); РезультатПроверкиВнешнейКомпоненты = МодульВнешниеКомпонентыСлужебный.ПроверитьПодключениеКомпоненты(Идентификатор); РезультатПроверкиВнешнейКомпоненты.Вставить(""Доступна"", Не ЗначениеЗаполнено(РезультатПроверкиВнешнейКомпоненты.ОписаниеОшибки)); КонецЕсли; КомпонентаПоследнейВерсии = СтандартныеПодсистемыСервер.КомпонентаПоследнейВерсии( Идентификатор, ПолноеИмяМакета, РезультатПроверкиВнешнейКомпоненты); Результат = ПодключитьКомпонентуПоИдентификатору(Идентификатор, КомпонентаПоследнейВерсии.Местоположение, Изолированно); Возврат Результат.ПодключаемыйМодуль; КонецФункции #КонецОбласти #Область УстаревшиеПроцедурыИФункции // Устарела. Следует использовать // ОбщегоНазначения.РазделениеВключено И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных. // // Возвращаемое значение: // Булево // Функция ИспользованиеРазделителяСеанса() Экспорт Если Не РазделениеВключено() Тогда Возврат Ложь; КонецЕсли; Если ПодсистемаСуществует(""ТехнологияСервиса.БазоваяФункциональность"") Тогда МодульРаботаВМоделиСервиса = ОбщийМодуль(""РаботаВМоделиСервиса""); Возврат МодульРаботаВМоделиСервиса.ИспользованиеРазделителяСеанса(); КонецЕсли; КонецФункции // Устарела. Следует использовать ФайловаяСистема.СоздатьВременныйКаталог // Создает временный каталог. После окончания работы с временным каталогом его необходимо удалить // с помощью ОбщегоНазначения.УдалитьВременныйКаталог. // // Параметры: // Расширение - Строка - расширение каталога, которое идентифицирует назначение временного каталога // и подсистему, которая его создала. // Рекомендуется указывать на английском языке. // // Возвращаемое значение: // Строка - полный путь к каталогу с разделителем пути. // Функция СоздатьВременныйКаталог(Знач Расширение = "") Экспорт Возврат ФайловаяСистема.СоздатьВременныйКаталог(Расширение); КонецФункции // Устарела. Следует использовать ФайловаяСистема.УдалитьВременныйКаталог // Удаляет временный каталог вместе с его содержимым, если возможно. // Если временный каталог не может быть удален (например, он занят каким-то процессом), // то в журнал регистрации записывается соответствующее предупреждение, а процедура завершается. // // Для совместного использования с ОбщегоНазначения.СоздатьВременныйКаталог, // после окончания работы с временным каталогом. // // Параметры: // ПутьККаталогу - Строка - полный путь к временному каталогу. // Процедура УдалитьВременныйКаталог(Знач ПутьККаталогу) Экспорт ФайловаяСистема.УдалитьВременныйКаталог(ПутьККаталогу); КонецПроцедуры // Устарела. Проверяет наличие механизма платформы, предупреждающего об опасных действиях. // // Возвращаемое значение: // Булево - если Истина, тогда работает механизм предупреждений безопасности. // Функция ЕстьЗащитаОтОпасныхДействий() Экспорт Возврат Истина; КонецФункции // Устарела. Создает и возвращает экземпляр отчета или обработки по полному имени объекта метаданных. // // Параметры: // ПолноеИмя - Строка - полное имя объекта метаданных. Пример: ""Отчет.БизнесПроцессы"". // // Возвращаемое значение: // ОтчетОбъект // ОбработкаОбъект - экземпляр отчета или обработки. // Функция ОбъектПоПолномуИмени(ПолноеИмя) Экспорт МассивСтрок = СтрРазделить(ПолноеИмя, "".""); Если МассивСтрок.Количество() >= 2 Тогда Вид = ВРег(МассивСтрок[0]); Имя = МассивСтрок[1]; Иначе ВызватьИсключение СтрЗаменить(НСтр(""ru = 'Некорректное полное имя отчета или обработки ""%1"".'""), ""%1"", ПолноеИмя); КонецЕсли; Если Вид = ""ОТЧЕТ"" Тогда Возврат Отчеты[Имя].Создать(); ИначеЕсли Вид = ""ОБРАБОТКА"" Тогда Возврат Обработки[Имя].Создать(); Иначе ВызватьИсключение СтрЗаменить(НСтр(""ru = '""%1"" не является отчетом или обработкой.'""), ""%1"", ПолноеИмя); КонецЕсли; КонецФункции // Устарела. Следует использовать ОбщегоНазначения.ЭтоMacOSКлиент // Возвращает Истина, если клиентское приложение запущено под управлением ОС X. // // Возвращаемое значение: // Булево - если нет клиентского приложения, возвращается Ложь. // Функция ЭтоOSXКлиент() Экспорт УстановитьПривилегированныйРежим(Истина); ЭтоMacOSКлиент = СтандартныеПодсистемыСервер.ПараметрыКлиентаНаСервере().Получить(""ЭтоMacOSКлиент""); Если ЭтоMacOSКлиент = Неопределено Тогда Возврат Ложь; // Нет клиентского приложения. КонецЕсли; Возврат ЭтоMacOSКлиент; КонецФункции #КонецОбласти #КонецЕсли #КонецОбласти #Если НЕ МобильныйАвтономныйСервер Тогда #Область СлужебныйПрограммныйИнтерфейс // Выгружает запрос в строку XML, которую можно вставить в Консоль запросов. // Для переноса запроса и всех его параметров в Консоль запросов, необходимо вызвать функцию в окне. // ""Вычислить выражение"" (Shift + F9), скопировать полученный XML в поле ""Текст запроса"" // консоли запросов и выполнить команду ""Заполнить из XML"" из меню ""Еще"". // Подробнее об использование функции смотрите в справке к консоли запросов. // // Параметры: // Запрос - Запрос - запрос, который необходимо выгрузить в формат строки XML. // // Возвращаемое значение: // Строка - строка в формате XML, которую можно извлечь при помощи метода ""ОбщегоНазначения.ЗначениеИзСтрокиXML"". // После извлечения получится объект типа ""Структура"" с полями: // * Текст - Строка - текст запроса. // * Параметры - Структура - параметры запроса. // Функция ЗапросВСтрокуXML(Запрос) Экспорт // АПК:299 - используется при отладке запросов, см. описание функции. Структура = Новый Структура(""Текст, Параметры""); ЗаполнитьЗначенияСвойств(Структура, Запрос); Возврат ЗначениеВСтрокуXML(Структура); КонецФункции Функция ПодключитьКомпонентуПоИдентификатору(Знач Идентификатор, Знач Местоположение, Знач Изолированно = Ложь) Экспорт ПроверитьМестоположениеКомпоненты(Идентификатор, Местоположение); Результат = Новый Структура; Результат.Вставить(""Подключено"", Ложь); Результат.Вставить(""ПодключаемыйМодуль"", Неопределено); Результат.Вставить(""ОписаниеОшибки"", ""); Попытка #Если МобильноеПриложениеСервер Тогда РезультатПодключения = ПодключитьВнешнююКомпоненту(Местоположение, Идентификатор + ""SymbolicName""); #Иначе РезультатПодключения = ПодключитьВнешнююКомпоненту(Местоположение, Идентификатор + ""SymbolicName"",, ОбщегоНазначенияСлужебныйКлиентСервер.ТипПодключенияКомпоненты(Изолированно)); #КонецЕсли Исключение Результат.ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось подключить внешнюю компоненту ""%1"" на сервере по причине: |%2.'""), Идентификатор, ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Подключение внешней компоненты на сервере'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Результат.ОписаниеОшибки); Возврат Результат; КонецПопытки; Если Не РезультатПодключения Тогда Результат.ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось подключить внешнюю компоненту ""%1"" на сервере по причине: |Метод %2 вернул Ложь.'""), Идентификатор, ""ПодключитьВнешнююКомпоненту""); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Подключение внешней компоненты на сервере'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Результат.ОписаниеОшибки); Возврат Результат; КонецЕсли; ПодключаемыйМодуль = Неопределено; Попытка ПодключаемыйМодуль = Новый(""AddIn."" + Идентификатор + ""SymbolicName"" + ""."" + Идентификатор); Если ПодключаемыйМодуль = Неопределено Тогда ВызватьИсключение НСтр(""ru = 'Оператор Новый вернул Неопределено'""); КонецЕсли; Исключение ПодключаемыйМодуль = Неопределено; ТекстОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); КонецПопытки; Если ПодключаемыйМодуль = Неопределено Тогда Результат.ОписаниеОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось создать объект внешней компоненты ""%1"", подключенной на сервере, по причине: |%2'""), Идентификатор, ТекстОшибки); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Подключение внешней компоненты на сервере'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка,,, Результат.ОписаниеОшибки); Возврат Результат; КонецЕсли; Результат.Подключено = Истина; Результат.ПодключаемыйМодуль = ПодключаемыйМодуль; Возврат Результат; КонецФункции Функция СтрокаВВидеНСтр(Знач ПроверяемаяСтрока) Экспорт ПроверяемаяСтрока = СтрЗаменить(ПроверяемаяСтрока, "" "", ""); ВариантыСовпадений = Новый Массив; Для каждого Язык Из Метаданные.Языки Цикл ВариантыСовпадений.Добавить(Язык.КодЯзыка + ""=""); КонецЦикла; Для каждого ВариантСовпадения Из ВариантыСовпадений Цикл Если СтрНайти(ПроверяемаяСтрока, ВариантСовпадения) > 0 Тогда Возврат Истина; КонецЕсли; КонецЦикла; Возврат Ложь; КонецФункции // Устанавливает условное оформление списка выбора // // Параметры: // Форма - ФормаКлиентскогоПриложения - форма, для которой устанавливается оформление. // ИмяЭлемента - Строка - имя элемента, для которого устанавливается оформление. // ИмяПоляКомпоновкиДанных - Строка - имя поля компоновки данных. // Процедура УстановитьУсловноеОформлениеСпискаВыбора(Форма, ИмяЭлемента, ИмяПоляКомпоновкиДанных) Экспорт Элементы = Форма.Элементы; УсловноеОформление = Форма.УсловноеОформление; Для каждого ЭлементВыбора Из Элементы[ИмяЭлемента].СписокВыбора Цикл Элемент = УсловноеОформление.Элементы.Добавить(); ПолеЭлемента = Элемент.Поля.Элементы.Добавить(); ЭлементФормы = Элементы[ИмяЭлемента]; // ПолеФормы ПолеЭлемента.Поле = Новый ПолеКомпоновкиДанных(ЭлементФормы.Имя); ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип(""ЭлементОтбораКомпоновкиДанных"")); ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(ИмяПоляКомпоновкиДанных); ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно; ОтборЭлемента.ПравоеЗначение = ЭлементВыбора.Значение; Элемент.Оформление.УстановитьЗначениеПараметра(""Текст"", ЭлементВыбора.Представление); КонецЦикла; КонецПроцедуры // Возвращает суффикс текущего языка для мультиязычных реквизитов. // // Возвращаемое значение: // Строка - ""Язык1"" или ""Язык2"", если язык пользователя является дополнительным // Пустая строка, если язык пользователя является основным. // Неопределено - мультиязычное хранение данных не используется. // Функция СуффиксЯзыкаТекущегоПользователя() Экспорт Результат = Новый Структура(); Результат.Вставить(""СуффиксТекущегоЯзыка"", ""); Результат.Вставить(""ЭтоОсновнойЯзык"", ""); Если ПодсистемаСуществует(""СтандартныеПодсистемы.Мультиязычность"") Тогда МодульМультиязычностьСервер = ОбщийМодуль(""МультиязычностьСервер""); СуффиксТекущегоЯзыка = МодульМультиязычностьСервер.СуффиксТекущегоЯзыка(); Если ЗначениеЗаполнено(СуффиксТекущегоЯзыка) Тогда Возврат СуффиксТекущегоЯзыка; КонецЕсли; Иначе СуффиксТекущегоЯзыка = ""; КонецЕсли; Если ЭтоОсновнойЯзык() Тогда Возврат СуффиксТекущегоЯзыка; КонецЕсли; Возврат Неопределено; КонецФункции // Сокращает имя файла с расширением. // Сокращение имени, производится, когда имя файла с расширением превышает размер 255 байт. // Сокращение ими файла достигая за счет сокращения имени файла без расширения и // добавления значения хеш функции сокращенной строки. // // Параметры: // ИмяФайла - Строка - имя файла с расширением // Процедура СократитьИмяФайла(ИмяФайла) Экспорт ОграничениеВБайтах = 255; Если РазмерСтрокиВБайтах(ИмяФайла) <= ОграничениеВБайтах Тогда Возврат; КонецЕсли; Файл = Новый Файл(ИмяФайла); ИмяБезРасширения = Файл.ИмяБезРасширения; ОграничениеВБайтах = ОграничениеВБайтах - РазмерСтрокиВБайтах(Файл.Расширение); ДлинаСтроки = СтрДлина(ИмяБезРасширения); ИспользуемоеКоличествоСимволов = ОграничениеВБайтах - 32; БольшееКоличествоСимволов = Мин(ДлинаСтроки, ОграничениеВБайтах); МеньшееКоличествоСимволов = Цел((ОграничениеВБайтах - 32)/4); Уменьшить = Истина; Пока Истина Цикл Если Уменьшить Тогда ИспользуемоеКоличествоСимволов = МеньшееКоличествоСимволов + Цел((ИспользуемоеКоличествоСимволов-МеньшееКоличествоСимволов)/2); Иначе ИспользуемоеКоличествоСимволов = ИспользуемоеКоличествоСимволов + Цел((БольшееКоличествоСимволов - ИспользуемоеКоличествоСимволов)/2); КонецЕсли; РазмерСтрокиВБайтах = РазмерСтрокиВБайтах(ИмяБезРасширения)+32; Если РазмерСтрокиВБайтах = ОграничениеВБайтах Или БольшееКоличествоСимволов - МеньшееКоличествоСимволов = 1 Тогда Прервать; КонецЕсли; Если РазмерСтрокиВБайтах > ОграничениеВБайтах Тогда Уменьшить = Истина; БольшееКоличествоСимволов = ИспользуемоеКоличествоСимволов; Иначе Уменьшить = Ложь; МеньшееКоличествоСимволов = ИспользуемоеКоличествоСимволов; КонецЕсли; КонецЦикла; СокращеннаяСтрока = СократитьСтрокуКонтрольнойСуммой(ИмяБезРасширения, ИспользуемоеКоличествоСимволов+32); ИмяФайла = СокращеннаяСтрока+Файл.Расширение; КонецПроцедуры // Служебные объекты и объекты при загрузке из резервной копии, // должны записываться без какой-либо прикладной логики. // // Запись служебных объектов без отключения прикладной логики, // может привести к зацикливанию, снижению производительности, // а также избыточным изменениях, которые в некоторых случаях // могут неожиданно повлиять на логику работы. // // Служебными являются объекты, которые обычно не участвуют // в обмене данными, не зависят от других объектов, например: // - кэши; // - даты обновления кэшей и аналогичные признаки; // - промежуточные данные для передачи параметров в фоновые задания; // - вспомогательные служебные данные (например, ключи доступа, // идентификаторы объектов метаданных). // // При использовании подсистемы Управление доступом, требуется // отдельно вызывать процедуру ОтключитьОбновлениеКлючейДоступа // общего модуля УправлениеДоступом. // // Процедура включает режим загрузки данных, // отключает регистрацию объектов на планах обмена, // отключает контроль механизма удаления помеченных объектов. // // Параметры: // Объект - ПланОбменаОбъект // - КонстантаМенеджерЗначения // - СправочникОбъект // - ДокументОбъект // - ПоследовательностьНаборЗаписей // - ПланВидовХарактеристикОбъект // - ПланСчетовОбъект // - ПланВидовРасчетаОбъект // - БизнесПроцессОбъект // - ЗадачаОбъект // - УдалениеОбъекта // - РегистрСведенийНаборЗаписей // - РегистрНакопленияНаборЗаписей // - РегистрБухгалтерииНаборЗаписей // - РегистрРасчетаНаборЗаписей // - ПерерасчетНаборЗаписей // // ЭтоУзелПланаОбмена - Булево // Процедура ОтключитьКонтрольЗаписи(Объект, ЭтоУзелПланаОбмена = Ложь) Экспорт Объект.ДополнительныеСвойства.Вставить(""НеВыполнятьКонтрольУдаляемых""); Объект.ДополнительныеСвойства.Вставить(""ОтключитьМеханизмРегистрацииОбъектов""); Объект.ОбменДанными.Загрузка = Истина; Если Не ЭтоУзелПланаОбмена Тогда Объект.ОбменДанными.Получатели.АвтоЗаполнение = Ложь; КонецЕсли; КонецПроцедуры #КонецОбласти #Область СлужебныеПроцедурыИФункции #Область ДанныеВБазе #Область ЗначенияРеквизитов // Проверяет существование указанных реквизитов у объекта метаданных. // // Параметры: // ПолноеИмяОбъектаМетаданных - Строка - полное имя проверяемого объекта. // ПроверяемыеВыражения - Массив - имена полей или проверяемые выражения объекта метаданных. // // Возвращаемое значение: // Структура: // * Ошибка - Булево - найдена ошибка. // * ОписаниеОшибки - Строка - описание найденных ошибок. // // Пример: // // Реквизиты = Новый Массив; // Реквизиты.Добавить(""Номер""); // Реквизиты.Добавить(""Валюта.НаименованиеПолное""); // // Результат = ОбщегоНазначения.ПроверитьСуществованиеРеквизитовОбъекта(""Документ._ДемоЗаказПокупателя"", Реквизиты); // // Если Результат.Ошибка Тогда // ВызватьИсключение Результат.ОписаниеОшибки; // КонецЕсли; // Функция ПроверитьСуществованиеРеквизитовОбъекта(ПолноеИмяОбъектаМетаданных, ПроверяемыеВыражения) МетаданныеОбъекта = ОбъектМетаданныхПоПолномуИмени(ПолноеИмяОбъектаМетаданных); Если МетаданныеОбъекта = Неопределено Тогда Возврат Новый Структура(""Ошибка, ОписаниеОшибки"", Истина, СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Несуществующий объект метаданных ""%1"".'""), ПолноеИмяОбъектаМетаданных)); КонецЕсли; // Разрешение вызова из безопасного режима внешней обработки или расширения. // Информация о доступности полей источника схемы при проверке метаданных не является секретной. УстановитьОтключениеБезопасногоРежима(Истина); УстановитьПривилегированныйРежим(Истина); Схема = Новый СхемаЗапроса; Пакет = Схема.ПакетЗапросов.Добавить(Тип(""ЗапросВыбораСхемыЗапроса"")); Оператор = Пакет.Операторы.Получить(0); Источник = Оператор.Источники.Добавить(ПолноеИмяОбъектаМетаданных, ""Таблица""); ТекстОшибки = ""; Для Каждого ТекущееВыражение Из ПроверяемыеВыражения Цикл Если Не ПолеИсточникаСхемыЗапросаДоступно(Источник, ТекущееВыражение) Тогда ТекстОшибки = ТекстОшибки + Символы.ПС + СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Поле объекта ""%1"" не существует.'""), ТекущееВыражение); КонецЕсли; КонецЦикла; Возврат Новый Структура(""Ошибка, ОписаниеОшибки"", Не ПустаяСтрока(ТекстОшибки), ТекстОшибки); КонецФункции // Используется в ПроверитьСуществованиеРеквизитовОбъекта. // Выполняет проверку доступности поля проверяемого выражения в источнике оператора схемы запроса. // Функция ПолеИсточникаСхемыЗапросаДоступно(ИсточникОператора, ПроверяемоеВыражение) ЧастиИмениПоля = СтрРазделить(ПроверяемоеВыражение, "".""); ДоступныеПоля = ИсточникОператора.Источник.ДоступныеПоля; ТекущаяЧастьИмениПоля = 0; Пока ТекущаяЧастьИмениПоля < ЧастиИмениПоля.Количество() Цикл ТекущееПоле = ДоступныеПоля.Найти(ЧастиИмениПоля.Получить(ТекущаяЧастьИмениПоля)); Если ТекущееПоле = Неопределено Тогда Возврат Ложь; КонецЕсли; // Инкрементация следующей части имени поля и соответствующего списка доступности полей. ТекущаяЧастьИмениПоля = ТекущаяЧастьИмениПоля + 1; ДоступныеПоля = ТекущееПоле.Поля; КонецЦикла; Возврат Истина; КонецФункции #КонецОбласти #Область ЗаменитьСсылки Функция РазметитьМестаИспользования(Знач ПараметрыВыполнения, Знач Ссылка, Знач ЦелеваяСсылка, Знач ТаблицаПоиска) УстановитьПривилегированныйРежим(Истина); // Устанавливаем порядок известных и проверяем наличие неопознанных объектов. Результат = Новый Структура; Результат.Вставить(""МестаИспользования"", ТаблицаПоиска.НайтиСтроки(Новый Структура(""Ссылка"", Ссылка))); Результат.Вставить(""ОшибкиРазметки"", Новый Массив); Результат.Вставить(""Успех"", Истина); Для Каждого МестоИспользования Из Результат.МестаИспользования Цикл Если МестоИспользования.ЭтоСлужебныеДанные Тогда Продолжить; // Зависимые данные не обрабатываются. КонецЕсли; Информация = ИнформацияОТипе(МестоИспользования.Метаданные, ПараметрыВыполнения); Если Информация.Вид = ""КОНСТАНТА"" Тогда МестоИспользования.КлючЗамены = ""Константа""; МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка; ИначеЕсли Информация.Вид = ""ПОСЛЕДОВАТЕЛЬНОСТЬ"" Тогда МестоИспользования.КлючЗамены = ""Последовательность""; МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка; ИначеЕсли Информация.Вид = ""РЕГИСТРСВЕДЕНИЙ"" Тогда МестоИспользования.КлючЗамены = ""РегистрСведений""; МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка; ИначеЕсли Информация.Вид = ""РЕГИСТРБУХГАЛТЕРИИ"" Или Информация.Вид = ""РЕГИСТРНАКОПЛЕНИЯ"" Или Информация.Вид = ""РЕГИСТРРАСЧЕТА"" Тогда МестоИспользования.КлючЗамены = ""КлючЗаписи""; МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка; ИначеЕсли Информация.Ссылочный Тогда МестоИспользования.КлючЗамены = ""Объект""; МестоИспользования.ЦелеваяСсылка = ЦелеваяСсылка; Иначе // Неизвестный объект для замены ссылок. Результат.Успех = Ложь; Текст = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Замена ссылок в ""%1"" не поддерживается.'""), Информация.ПолноеИмя); ОписаниеОшибки = Новый Структура(""Объект, Текст"", МестоИспользования.Данные, Текст); Результат.ОшибкиРазметки.Добавить(ОписаниеОшибки); КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции // Параметры: // ТаблицаПоиска - см. МестаИспользования // Процедура ЗаменитьСсылкиКороткимиТранзакциями(Результат, Знач ПараметрыВыполнения, Знач Дубль, Знач ТаблицаПоиска) // Основной цикл обработки ФильтрСсылок = Новый Структура(""Ссылка, КлючЗамены""); Результат.ЕстьОшибки = Ложь; ФильтрСсылок.Ссылка = Дубль; ФильтрСсылок.КлючЗамены = ""Константа""; МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок); Для Каждого МестоИспользования Из МестаИспользования Цикл ПроизвестиЗаменуВКонстанте(Результат, МестоИспользования, ПараметрыВыполнения); КонецЦикла; ФильтрСсылок.КлючЗамены = ""Объект""; МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок); Для Каждого МестоИспользования Из МестаИспользования Цикл ПроизвестиЗаменуВОбъекте(Результат, МестоИспользования, ПараметрыВыполнения); КонецЦикла; ФильтрСсылок.КлючЗамены = ""КлючЗаписи""; МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок); Для Каждого МестоИспользования Из МестаИспользования Цикл ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения); КонецЦикла; ФильтрСсылок.КлючЗамены = ""Последовательность""; МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок); Для Каждого МестоИспользования Из МестаИспользования Цикл ПроизвестиЗаменуВНаборе(Результат, МестоИспользования, ПараметрыВыполнения); КонецЦикла; ФильтрСсылок.КлючЗамены = ""РегистрСведений""; МестаИспользования = ТаблицаПоиска.НайтиСтроки(ФильтрСсылок); Для Каждого МестоИспользования Из МестаИспользования Цикл ПроизвестиЗаменуВРегистреСведений(Результат, МестоИспользования, ПараметрыВыполнения); КонецЦикла; ПроизводимыеЗамены = Новый Массив; ПроизводимыеЗамены.Добавить(Дубль); Если ПараметрыВыполнения.УдалятьНепосредственно ИЛИ ПараметрыВыполнения.ПомечатьНаУдаление Тогда УстановитьПометкуУдаленияДляОбъектов(Результат, ПроизводимыеЗамены, ПараметрыВыполнения); Иначе ТаблицаПовторногоПоиска = МестаИспользования(ПроизводимыеЗамены,, ПараметрыВыполнения.ПараметрыПоискаМестИспользования); ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, ТаблицаПовторногоПоиска); КонецЕсли; КонецПроцедуры Процедура ПроизвестиЗаменуВКонстанте(Результат, Знач МестоИспользования, Знач ПараметрыЗаписи) УстановитьПривилегированныйРежим(Истина); Данные = МестоИспользования.Данные; МетаданныеКонстанты = МестоИспользования.Метаданные; ПредставлениеДанных = Строка(Данные); // Будем производить сразу все замены для этих данных. Фильтр = Новый Структура(""Данные, КлючЗамены"", Данные, ""Константа""); ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр); // см. МестаИспользования // Помечаем как обработанные Для Каждого Строка Из ОбрабатываемыеСтроки Цикл Строка.КлючЗамены = ""; КонецЦикла; СостояниеОперации = ""; Ошибка = ""; НачатьТранзакцию(); Попытка Блокировка = Новый БлокировкаДанных; Блокировка.Добавить(МетаданныеКонстанты.ПолноеИмя()); Попытка Блокировка.Заблокировать(); Исключение Ошибка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось заблокировать константу %1'""), ПредставлениеДанных); СостояниеОперации = ""ОшибкаБлокировки""; ВызватьИсключение; КонецПопытки; МенеджерКонстанты = Константы[МетаданныеКонстанты.Имя].СоздатьМенеджерЗначения(); МенеджерКонстанты.Прочитать(); ЗаменаПроизведена = Ложь; Для Каждого Строка Из ОбрабатываемыеСтроки Цикл Если МенеджерКонстанты.Значение = Строка.Ссылка Тогда МенеджерКонстанты.Значение = Строка.ЦелеваяСсылка; ЗаменаПроизведена = Истина; КонецЕсли; КонецЦикла; Если Не ЗаменаПроизведена Тогда ОтменитьТранзакцию(); Возврат; КонецЕсли; // Пытаемся сохранить Если Не ПараметрыЗаписи.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Ложь); КонецЕсли; Попытка ЗаписатьОбъект(МенеджерКонстанты, ПараметрыЗаписи); Исключение ОписаниеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); Ошибка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось записать %1 по причине: %2'""), ПредставлениеДанных, ОписаниеОшибки); СостояниеОперации = ""ОшибкаЗаписи""; ВызватьИсключение; КонецПопытки; Если Не ПараметрыЗаписи.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Истина); КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, МетаданныеКонстанты,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); Если СостояниеОперации = ""ОшибкаЗаписи"" Тогда Для Каждого Строка Из ОбрабатываемыеСтроки Цикл ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, ОписаниеОшибкиЗамены(""ОшибкаЗаписи"", Данные, ПредставлениеДанных, Ошибка)); КонецЦикла; Иначе ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, ОписаниеОшибкиЗамены(СостояниеОперации, Данные, ПредставлениеДанных, Ошибка)); КонецЕсли; КонецПопытки; КонецПроцедуры Процедура ПроизвестиЗаменуВОбъекте(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения) УстановитьПривилегированныйРежим(Истина); Данные = МестоИспользования.Данные; // Будем производить сразу все замены для этих данных. Фильтр = Новый Структура(""Данные, КлючЗамены"", Данные, ""Объект""); ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр); // см. МестаИспользования ПредставлениеДанных = ПредметСтрокой(Данные); СостояниеОперации = ""; ТекстОшибки = ""; НачатьТранзакцию(); Попытка Блокировка = Новый БлокировкаДанных; ЗаблокироватьМестоИспользования(ПараметрыВыполнения, Блокировка, МестоИспользования); Попытка Блокировка.Заблокировать(); Исключение СостояниеОперации = ""ОшибкаБлокировки""; ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось заблокировать объект ""%1"": |%2'""), ПредставлениеДанных, ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение; КонецПопытки; ОбъектыЗаписи = ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки); // Пытаемся сохранить, сам объект идет последним. Если Не ПараметрыВыполнения.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Ложь); КонецЕсли; Попытка Если ПараметрыВыполнения.ВключатьБизнесЛогику Тогда // Первая запись без контроля, чтобы устранить циклические ссылки. НовыеПараметрыВыполнения = СкопироватьРекурсивно(ПараметрыВыполнения); НовыеПараметрыВыполнения.ВключатьБизнесЛогику = Ложь; Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл ЗаписатьОбъект(КлючЗначение.Ключ, НовыеПараметрыВыполнения); КонецЦикла; // Вторая запись c контролем. НовыеПараметрыВыполнения.ВключатьБизнесЛогику = Истина; Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл ЗаписатьОбъект(КлючЗначение.Ключ, НовыеПараметрыВыполнения); КонецЦикла; Иначе // Запись без контроля бизнес-логики. Для Каждого КлючЗначение Из ОбъектыЗаписи Цикл ЗаписатьОбъект(КлючЗначение.Ключ, ПараметрыВыполнения); КонецЦикла; КонецЕсли; Исключение СостояниеОперации = ""ОшибкаЗаписи""; ОписаниеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось записать %1 по причине: %2'""), ПредставлениеДанных, ОписаниеОшибки); ВызватьИсключение; КонецПопытки; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); Информация = ИнформацияОбОшибке(); ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, МестоИспользования.Метаданные,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(Информация)); Ошибка = ОписаниеОшибкиЗамены(СостояниеОперации, Данные, ПредставлениеДанных, ТекстОшибки); Если СостояниеОперации = ""ОшибкаЗаписи"" Тогда Для Каждого Строка Из ОбрабатываемыеСтроки Цикл ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, Ошибка); КонецЦикла; Иначе ЗарегистрироватьОшибкуЗамены(Результат, МестоИспользования.Ссылка, Ошибка); КонецЕсли; КонецПопытки; // Помечаем как обработанные Для Каждого Строка Из ОбрабатываемыеСтроки Цикл Строка.КлючЗамены = ""; КонецЦикла; КонецПроцедуры Процедура ПроизвестиЗаменуВНаборе(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения) УстановитьПривилегированныйРежим(Истина); Данные = МестоИспользования.Данные; Мета = МестоИспользования.Метаданные; ПредставлениеДанных = Строка(Данные); // Будем производить сразу все замены для этих данных. Фильтр = Новый Структура(""Данные, КлючЗамены""); ЗаполнитьЗначенияСвойств(Фильтр, МестоИспользования); ОбрабатываемыеСтроки = МестоИспользования.Владелец().НайтиСтроки(Фильтр); // см. МестаИспользования ОписаниеНабора = ОписаниеКлючаЗаписи(Мета); НаборЗаписей = ОписаниеНабора.НаборЗаписей; // РегистрСведенийНаборЗаписей ПарыЗамен = Новый Соответствие; Для Каждого Строка Из ОбрабатываемыеСтроки Цикл ПарыЗамен.Вставить(Строка.Ссылка, Строка.ЦелеваяСсылка); КонецЦикла; // Помечаем как обработанные Для Каждого Строка Из ОбрабатываемыеСтроки Цикл Строка.КлючЗамены = ""; КонецЦикла; СостояниеОперации = ""; Ошибка = ""; НачатьТранзакцию(); Попытка // Блокировка и подготовка набора. Блокировка = Новый БлокировкаДанных; Для Каждого КлючЗначение Из ОписаниеНабора.СписокИзмерений Цикл ТипИзмерения = КлючЗначение.Значение; Имя = КлючЗначение.Ключ; Значение = Данные[Имя]; Для Каждого Строка Из ОбрабатываемыеСтроки Цикл ТекущаяСсылка = Строка.Ссылка; Если ТипИзмерения.СодержитТип(ТипЗнч(ТекущаяСсылка)) Тогда Блокировка.Добавить(ОписаниеНабора.ПространствоБлокировки).УстановитьЗначение(Имя, ТекущаяСсылка); КонецЕсли; КонецЦикла; НаборЗаписей.Отбор[Имя].Установить(Значение); КонецЦикла; Попытка Блокировка.Заблокировать(); Исключение Ошибка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось заблокировать набор %1'""), ПредставлениеДанных); СостояниеОперации = ""ОшибкаБлокировки""; ВызватьИсключение; КонецПопытки; НаборЗаписей.Прочитать(); ЗаменитьВКоллекцииСтрок(""НаборЗаписей"", ""НаборЗаписей"", НаборЗаписей, НаборЗаписей, ОписаниеНабора.СписокПолей, ПарыЗамен); Если НаборЗаписей.Модифицированность() Тогда ОтменитьТранзакцию(); Возврат; КонецЕсли; Если Не ПараметрыВыполнения.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Ложь); КонецЕсли; Попытка ЗаписатьОбъект(НаборЗаписей, ПараметрыВыполнения); Исключение ОписаниеОшибки = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); Ошибка = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось записать %1 по причине: %2'""), ПредставлениеДанных, ОписаниеОшибки); СостояниеОперации = ""ОшибкаЗаписи""; ВызватьИсключение; КонецПопытки; Если Не ПараметрыВыполнения.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Истина); КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); Информация = ИнформацияОбОшибке(); ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, Мета,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(Информация)); Ошибка = ОписаниеОшибкиЗамены(СостояниеОперации, Данные, ПредставлениеДанных, Ошибка); Если СостояниеОперации = ""ОшибкаЗаписи"" Тогда Для Каждого Строка Из ОбрабатываемыеСтроки Цикл ЗарегистрироватьОшибкуЗамены(Результат, Строка.Ссылка, Ошибка); КонецЦикла; Иначе ЗарегистрироватьОшибкуЗамены(Результат, МестоИспользования.Ссылка, Ошибка); КонецЕсли; КонецПопытки; КонецПроцедуры Процедура ПроизвестиЗаменуВРегистреСведений(Результат, Знач МестоИспользования, Знач ПараметрыВыполнения) Если МестоИспользования.Обработано Тогда Возврат; КонецЕсли; МестоИспользования.Обработано = Истина; // В случае, если дубль указан в измерениях набора, тогда используется 2 набора записей: // НаборЗаписейДубля - чтение старых значений (по старым измерениям) и удаление старых значений. // НаборЗаписейОригинала - чтение актуальных значений (по новым измерениям) и запись новых значений. // Данные дублей и оригиналов объединяются по правилам: // Приоритет у данных оригинала. // Если в оригинале нет данных, то берутся данные из дубля. // Набор оригинала записывается, а набор дубля удаляется. // // В случае, если дубль не указан в измерениях набора, тогда используется 1 набор записей: // НаборЗаписейДубля - чтение старых значений и запись новых значений. // // Замена ссылок в ресурсах и реквизитах производится в обоих случаях. УстановитьПривилегированныйРежим(Истина); Дубль = МестоИспользования.Ссылка; Оригинал = МестоИспользования.ЦелеваяСсылка; МетаданныеРегистра = МестоИспользования.Метаданные; КлючЗаписиРегистра = МестоИспользования.Данные; Информация = ИнформацияОТипе(МетаданныеРегистра, ПараметрыВыполнения); ТребуетсяДваНабора = Ложь; Для Каждого КлючЗначение Из Информация.Измерения Цикл ЗначениеИзмеренияДубля = КлючЗаписиРегистра[КлючЗначение.Ключ]; Если ЗначениеИзмеренияДубля = Дубль Или ПараметрыВыполнения.УспешныеЗамены[ЗначениеИзмеренияДубля] = Дубль Тогда ТребуетсяДваНабора = Истина; // Дубль указан в измерениях. Прервать; КонецЕсли; КонецЦикла; Менеджер = МенеджерОбъектаПоПолномуИмени(Информация.ПолноеИмя); НаборЗаписейДубля = Менеджер.СоздатьНаборЗаписей(); Если ТребуетсяДваНабора Тогда ЗначенияИзмеренийОригинала = Новый Структура; НаборЗаписейОригинала = Менеджер.СоздатьНаборЗаписей(); КонецЕсли; НачатьТранзакцию(); Попытка Блокировка = Новый БлокировкаДанных; БлокировкаДубля = Блокировка.Добавить(Информация.ПолноеИмя); Если ТребуетсяДваНабора Тогда БлокировкаОригинала = Блокировка.Добавить(Информация.ПолноеИмя); КонецЕсли; Для Каждого КлючЗначение Из Информация.Измерения Цикл ЗначениеИзмеренияДубля = КлючЗаписиРегистра[КлючЗначение.Ключ]; // Для решения проблемы уникальности // выполняется замена старых значений измерений ключа записи на актуальные. // Соответствие старых и актуальных обеспечивает соответствием УспешныеЗамены. // Данные соответствия актуальны на текущий момент времени, // т.к. пополняются только после успешной обработки очередной пары и фиксации транзакции. НовоеЗначениеИзмеренияДубля = ПараметрыВыполнения.УспешныеЗамены[ЗначениеИзмеренияДубля]; Если НовоеЗначениеИзмеренияДубля <> Неопределено Тогда ЗначениеИзмеренияДубля = НовоеЗначениеИзмеренияДубля; КонецЕсли; НаборЗаписейДубля.Отбор[КлючЗначение.Ключ].Установить(ЗначениеИзмеренияДубля); // Замена в конкретной паре и блокировка на конкретную замену. БлокировкаДубля.УстановитьЗначение(КлючЗначение.Ключ, ЗначениеИзмеренияДубля); Если ТребуетсяДваНабора Тогда Если ЗначениеИзмеренияДубля = Дубль Тогда ЗначениеИзмеренияОригинала = Оригинал; Иначе ЗначениеИзмеренияОригинала = ЗначениеИзмеренияДубля; КонецЕсли; НаборЗаписейОригинала.Отбор[КлючЗначение.Ключ].Установить(ЗначениеИзмеренияОригинала); ЗначенияИзмеренийОригинала.Вставить(КлючЗначение.Ключ, ЗначениеИзмеренияОригинала); // Замена в конкретной паре и блокировка на конкретную замену. БлокировкаОригинала.УстановитьЗначение(КлючЗначение.Ключ, ЗначениеИзмеренияОригинала); КонецЕсли; КонецЦикла; // Установка блокировки. Попытка Блокировка.Заблокировать(); Исключение // Вид ошибки ""БлокировкаДляРегистра"". ВызватьИсключение; КонецПопытки; // Откуда читаем? НаборЗаписейДубля.Прочитать(); Если НаборЗаписейДубля.Количество() = 0 Тогда // Нечего писать. ОтменитьТранзакцию(); // Замена не требуется. Возврат; КонецЕсли; ЗаписьДубля = НаборЗаписейДубля[0]; // Куда пишем? Если ТребуетсяДваНабора Тогда // Пишем в набор с другими измерениями. НаборЗаписейОригинала.Прочитать(); Если НаборЗаписейОригинала.Количество() = 0 Тогда ЗаписьОригинала = НаборЗаписейОригинала.Добавить(); ЗаполнитьЗначенияСвойств(ЗаписьОригинала, ЗаписьДубля); ЗаполнитьЗначенияСвойств(ЗаписьОригинала, ЗначенияИзмеренийОригинала); Иначе ЗаписьОригинала = НаборЗаписейОригинала[0]; КонецЕсли; Иначе // Пишем туда-же, откуда и читаем. НаборЗаписейОригинала = НаборЗаписейДубля; ЗаписьОригинала = ЗаписьДубля; // Ситуация с нулевым количеством записей в наборе обработана выше. КонецЕсли; // Замена дубля на оригинал в ресурсах и реквизитах. Для Каждого КлючЗначение Из Информация.Ресурсы Цикл ЗначениеРеквизитаВОригинале = ЗаписьОригинала[КлючЗначение.Ключ]; Если ЗначениеРеквизитаВОригинале = Дубль Тогда ЗаписьОригинала[КлючЗначение.Ключ] = Оригинал; КонецЕсли; КонецЦикла; Для Каждого КлючЗначение Из Информация.Реквизиты Цикл ЗначениеРеквизитаВОригинале = ЗаписьОригинала[КлючЗначение.Ключ]; Если ЗначениеРеквизитаВОригинале = Дубль Тогда ЗаписьОригинала[КлючЗначение.Ключ] = Оригинал; КонецЕсли; КонецЦикла; Если Не ПараметрыВыполнения.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Ложь); КонецЕсли; // Удаление данных дубля. Если ТребуетсяДваНабора Тогда НаборЗаписейДубля.Очистить(); Попытка ЗаписатьОбъект(НаборЗаписейДубля, ПараметрыВыполнения); Исключение // Вид ошибки ""УдалитьНаборДубля"". ВызватьИсключение; КонецПопытки; КонецЕсли; // Запись данных оригинала. Если НаборЗаписейОригинала.Модифицированность() Тогда Попытка ЗаписатьОбъект(НаборЗаписейОригинала, ПараметрыВыполнения); Исключение // Вид ошибки ""ЗаписатьНаборОригинала"". ВызватьИсключение; КонецПопытки; КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ЗарегистрироватьОшибкуВТаблицу(Результат, Дубль, Оригинал, КлючЗаписиРегистра, Информация, ""БлокировкаДляРегистра"", ИнформацияОбОшибке()); КонецПопытки КонецПроцедуры Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки) Данные = МестоИспользования.Данные; ОписаниеПоследовательностей = ОписаниеПоследовательностей(МестоИспользования.Метаданные); ОписаниеДвижений = ОписаниеДвижений(МестоИспользования.Метаданные); ОписаниеЗадач = ОписаниеЗадач(МестоИспользования.Метаданные); УстановитьПривилегированныйРежим(Истина); // Возвращаем измененные обработанные объекты. Измененные = Новый Соответствие; // Считываем Описание = ОписаниеОбъекта(Данные.Метаданные()); Попытка Объект = Данные.ПолучитьОбъект(); Исключение // Был уже обработан с ошибками. Объект = Неопределено; КонецПопытки; Если Объект = Неопределено Тогда Возврат Измененные; КонецЕсли; Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл ОписаниеДвижения.НаборЗаписей.Отбор.Регистратор.Установить(Данные); ОписаниеДвижения.НаборЗаписей.Прочитать(); КонецЦикла; Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл ОписаниеПоследовательности.НаборЗаписей.Отбор.Регистратор.Установить(Данные); ОписаниеПоследовательности.НаборЗаписей.Прочитать(); КонецЦикла; // Заменяем сразу все варианты. ПарыЗамен = Новый Соответствие; Для Каждого МестоИспользования Из ОбрабатываемыеСтроки Цикл ПарыЗамен.Вставить(МестоИспользования.Ссылка, МестоИспользования.ЦелеваяСсылка); КонецЦикла; ВыполнитьЗаменуВРеквизитахОбъекта(Объект, Описание, ПарыЗамен); // Движения Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл ЗаменитьВКоллекцииСтрок( ""Движения"", ОписаниеДвижения.ПространствоБлокировки, ОписаниеДвижения.НаборЗаписей, ОписаниеДвижения.НаборЗаписей, ОписаниеДвижения.СписокПолей, ПарыЗамен); КонецЦикла; // Последовательности Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл ЗаменитьВКоллекцииСтрок( ""Последовательности"", ОписаниеПоследовательности.ПространствоБлокировки, ОписаниеПоследовательности.НаборЗаписей, ОписаниеПоследовательности.НаборЗаписей, ОписаниеПоследовательности.СписокПолей, ПарыЗамен); КонецЦикла; Для Каждого ОписаниеДвижения Из ОписаниеДвижений Цикл Если ОписаниеДвижения.НаборЗаписей.Модифицированность() Тогда Измененные.Вставить(ОписаниеДвижения.НаборЗаписей, Ложь); КонецЕсли; КонецЦикла; Для Каждого ОписаниеПоследовательности Из ОписаниеПоследовательностей Цикл Если ОписаниеПоследовательности.НаборЗаписей.Модифицированность() Тогда Измененные.Вставить(ОписаниеПоследовательности.НаборЗаписей, Ложь); КонецЕсли; КонецЦикла; Если ОписаниеЗадач <> Неопределено Тогда ЗадачаПроцесса = ЗадачиПроцесса(Данные, ОписаниеЗадач.ПространствоБлокировки); Пока ЗадачаПроцесса.Следующий() Цикл ЗадачаОбъект = ЗадачаПроцесса.Ссылка.ПолучитьОбъект(); Фильтр = Новый Структура(""Данные, КлючЗамены"", ЗадачаПроцесса.Ссылка, ""Объект""); ОбрабатываемыеСтрокиЗадачи = МестоИспользования.Владелец().НайтиСтроки(Фильтр); // см. МестаИспользования Для каждого МестоИспользованияЗадачи Из ОбрабатываемыеСтрокиЗадачи Цикл ПарыЗамен.Вставить(МестоИспользованияЗадачи.Ссылка, МестоИспользованияЗадачи.ЦелеваяСсылка); КонецЦикла; ВыполнитьЗаменуВРеквизитахОбъекта(ЗадачаОбъект, ОписаниеЗадач, ПарыЗамен); Если ЗадачаОбъект.Модифицированность() Тогда Измененные.Вставить(ЗадачаОбъект, Ложь); КонецЕсли; КонецЦикла; КонецЕсли; // Сам объект последний - для возможного перепроведения. Если Объект.Модифицированность() Тогда Измененные.Вставить(Объект, Описание.МожетБытьПроведен); КонецЕсли; Возврат Измененные; КонецФункции Функция ЗадачиПроцесса(БизнесПроцесс, ТипЗадач) ТекстЗапроса = ""ВЫБРАТЬ | ИмяТаблицы.Ссылка |ИЗ | &ИмяТаблицы КАК ИмяТаблицы |ГДЕ | ИмяТаблицы.БизнесПроцесс = &БизнесПроцесс""; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ИмяТаблицы"", ТипЗадач); Запрос = Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр(""БизнесПроцесс"", БизнесПроцесс); Возврат Запрос.Выполнить().Выбрать(); КонецФункции Процедура ВыполнитьЗаменуВРеквизитахОбъекта(Объект, Описание, ПарыЗамен) // Реквизиты Для Каждого КлючЗначение Из Описание.Реквизиты Цикл Имя = КлючЗначение.Ключ; ЦелеваяСсылка = ПарыЗамен[ Объект[Имя] ]; Если ЦелеваяСсылка <> Неопределено Тогда ЗарегистрироватьФактЗамены(Объект, Объект[Имя], ЦелеваяСсылка, ""Реквизиты"", Имя); Объект[Имя] = ЦелеваяСсылка; КонецЕсли; КонецЦикла; // Стандартные реквизиты Для Каждого КлючЗначение Из Описание.СтандартныеРеквизиты Цикл Имя = КлючЗначение.Ключ; ЦелеваяСсылка = ПарыЗамен[ Объект[Имя] ]; Если ЦелеваяСсылка <> Неопределено Тогда ЗарегистрироватьФактЗамены(Объект, Объект[Имя], ЦелеваяСсылка, ""СтандартныеРеквизиты"", Имя); Объект[Имя] = ЦелеваяСсылка; КонецЕсли; КонецЦикла; // Табличные части Для Каждого Элемент Из Описание.ТабличныеЧасти Цикл ЗаменитьВКоллекцииСтрок( ""ТабличныеЧасти"", Элемент.Имя, Объект, Объект[Элемент.Имя], Элемент.СписокПолей, ПарыЗамен); КонецЦикла; // Стандартные табличные части. Для Каждого Элемент Из Описание.СтандартныеТабличныеЧасти Цикл ЗаменитьВКоллекцииСтрок( ""СтандартныеТабличныеЧасти"", Элемент.Имя, Объект, Объект[Элемент.Имя], Элемент.СписокПолей, ПарыЗамен); КонецЦикла; Для Каждого Реквизит Из Описание.РеквизитыАдресации Цикл Имя = Реквизит.Ключ; ЦелеваяСсылка = ПарыЗамен[ Объект[Имя] ]; Если ЦелеваяСсылка <> Неопределено Тогда ЗарегистрироватьФактЗамены(Объект, Объект[Имя], ЦелеваяСсылка, ""РеквизитыАдресации"", Имя); Объект[Имя] = ЦелеваяСсылка; КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ЗарегистрироватьФактЗамены(Объект, СсылкаДубля, СсылкаОригинала, ВидРеквизита, ИмяРеквизита, Индекс = Неопределено, ИмяКолонки = Неопределено) ЕстьДополнительныеСвойства = Новый Структура(""ДополнительныеСвойства""); ЗаполнитьЗначенияСвойств(ЕстьДополнительныеСвойства, Объект); Если ТипЗнч(ЕстьДополнительныеСвойства.ДополнительныеСвойства) <> Тип(""Структура"") Тогда Возврат; КонецЕсли; ДополнительныеСвойства = Объект.ДополнительныеСвойства; ДополнительныеСвойства.Вставить(""ЗаменаСсылок"", Истина); ВыполненныеЗамены = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ДополнительныеСвойства, ""ВыполненныеЗамены""); Если ВыполненныеЗамены = Неопределено Тогда ВыполненныеЗамены = Новый Массив; ДополнительныеСвойства.Вставить(""ВыполненныеЗамены"", ВыполненныеЗамены); КонецЕсли; ОписаниеЗамены = Новый Структура; ОписаниеЗамены.Вставить(""СсылкаДубля"", СсылкаДубля); ОписаниеЗамены.Вставить(""СсылкаОригинала"", СсылкаОригинала); ОписаниеЗамены.Вставить(""ВидРеквизита"", ВидРеквизита); ОписаниеЗамены.Вставить(""ИмяРеквизита"", ИмяРеквизита); ОписаниеЗамены.Вставить(""Индекс"", Индекс); ОписаниеЗамены.Вставить(""ИмяКолонки"", ИмяКолонки); ВыполненныеЗамены.Добавить(ОписаниеЗамены); КонецПроцедуры Процедура УстановитьПометкуУдаленияДляОбъектов(Результат, Знач УдаляемыеСсылки, Знач ПараметрыВыполнения) УстановитьПривилегированныйРежим(Истина); ЕстьВнешняяТранзакция = ТранзакцияАктивна(); ВсеМестаИспользования = МестаИспользования(УдаляемыеСсылки,,ПараметрыВыполнения.ПараметрыПоискаМестИспользования); Для Каждого УдаляемаяСсылка Из УдаляемыеСсылки Цикл Информация = ИнформацияОТипе(ТипЗнч(УдаляемаяСсылка), ПараметрыВыполнения); Блокировка = Новый БлокировкаДанных; Блокировка.Добавить(Информация.ПолноеИмя).УстановитьЗначение(""Ссылка"", УдаляемаяСсылка); НачатьТранзакцию(); Попытка ЭтоОшибкаБлокировки = Истина; Блокировка.Заблокировать(); ЭтоОшибкаБлокировки = Ложь; Успешно = УстановитьПометкуУдаления(Результат, УдаляемаяСсылка, ВсеМестаИспользования, ПараметрыВыполнения, ЕстьВнешняяТранзакция); Если Не Успешно Тогда ОтменитьТранзакцию(); Продолжить; КонецЕсли; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); Если ЭтоОшибкаБлокировки Тогда ЗарегистрироватьОшибкуВТаблицу(Результат, УдаляемаяСсылка, Неопределено, УдаляемаяСсылка, Информация, ""БлокировкаДляУдаленияДубля"", ИнформацияОбОшибке()); КонецЕсли; Если ЕстьВнешняяТранзакция Тогда ВызватьИсключение; КонецЕсли; КонецПопытки; КонецЦикла; КонецПроцедуры Функция УстановитьПометкуУдаления(Результат, Знач УдаляемаяСсылка, Знач ВсеМестаИспользования, Знач ПараметрыВыполнения, ЕстьВнешняяТранзакция) УстановитьПривилегированныйРежим(Истина); ПредставлениеСсылки = ПредметСтрокой(УдаляемаяСсылка); Фильтр = Новый Структура(""Ссылка""); Фильтр.Ссылка = УдаляемаяСсылка; МестаИспользования = ВсеМестаИспользования.НайтиСтроки(Фильтр); Индекс = МестаИспользования.ВГраница(); Пока Индекс >= 0 Цикл Если МестаИспользования[Индекс].ВспомогательныеДанные Тогда МестаИспользования.Удалить(Индекс); КонецЕсли; Индекс = Индекс - 1; КонецЦикла; Если МестаИспользования.Количество() > 0 Тогда ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, МестаИспользования); Возврат Ложь; // Остались места использования, нельзя удалять. КонецЕсли; Объект = УдаляемаяСсылка.ПолучитьОбъект(); // ДокументОбъект, СправочникОбъект Если Объект = Неопределено Тогда Возврат Ложь; // Уже удален. КонецЕсли; Если Не ПараметрыВыполнения.ПривилегированнаяЗапись Тогда УстановитьПривилегированныйРежим(Ложь); КонецЕсли; Успешно = Истина; Попытка ОбработатьОбъектСПерехватомСообщений(Объект, ""ПометкаУдаления"", Неопределено, ПараметрыВыполнения); Результат.ОчередьКНепосредственномуУдалению.Добавить(Объект.Ссылка); Исключение ТекстОшибки = НСтр(""ru = 'Элемент не был помечен на удаление по причине:'""); ТекстОшибки = ТекстОшибки + Символы.ПС + СокрЛП(ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())); ОписаниеОшибки = ОписаниеОшибкиЗамены(""ОшибкаУдаления"", УдаляемаяСсылка, ПредставлениеСсылки, ТекстОшибки); ЗарегистрироватьОшибкуЗамены(Результат, УдаляемаяСсылка, ОписаниеОшибки); Успешно = Ложь; Если ЕстьВнешняяТранзакция Тогда ВызватьИсключение; КонецЕсли; КонецПопытки; Возврат Успешно; КонецФункции Процедура ДобавитьРезультатыЗаменыИзмененныхОбъектов(Результат, ТаблицаПовторногоПоиска) Фильтр = Новый Структура(""ТипОшибки, Ссылка, ОбъектОшибки"", ""); Для Каждого Строка Из ТаблицаПовторногоПоиска Цикл Тест = Новый Структура(""ВспомогательныеДанные"", Ложь); ЗаполнитьЗначенияСвойств(Тест, Строка); Если Тест.ВспомогательныеДанные Тогда Продолжить; КонецЕсли; Данные = Строка.Данные; Ссылка = Строка.Ссылка; ПредставлениеДанных = Строка(Данные); Фильтр.ОбъектОшибки = Данные; Фильтр.Ссылка = Ссылка; Если Результат.Ошибки.НайтиСтроки(Фильтр).Количество() > 0 Тогда Продолжить; // По данной проблеме уже записана ошибка. КонецЕсли; ЗарегистрироватьОшибкуЗамены(Результат, Ссылка, ОписаниеОшибкиЗамены(""ДанныеИзменены"", Данные, ПредставлениеДанных, НСтр(""ru = 'Заменены не все места использования. Возможно места использования были добавлены или изменены другим пользователем.'""))); КонецЦикла; КонецПроцедуры Процедура ЗаблокироватьМестоИспользования(ПараметрыВыполнения, Блокировка, МестоИспользования) Если МестоИспользования.КлючЗамены = ""Константа"" Тогда Блокировка.Добавить(МестоИспользования.Метаданные.ПолноеИмя()); ИначеЕсли МестоИспользования.КлючЗамены = ""Объект"" Тогда СсылкаОбъекта = МестоИспользования.Данные; МетаданныеОбъекта = МестоИспользования.Метаданные; // Сам объект. Блокировка.Добавить(МетаданныеОбъекта.ПолноеИмя()).УстановитьЗначение(""Ссылка"", СсылкаОбъекта); // Движения по регистратору. ОписаниеДвижений = ОписаниеДвижений(МетаданныеОбъекта); Для Каждого Элемент Из ОписаниеДвижений Цикл Блокировка.Добавить(Элемент.ПространствоБлокировки + "".НаборЗаписей"").УстановитьЗначение(""Регистратор"", СсылкаОбъекта); КонецЦикла; // Последовательности. ОписаниеПоследовательностей = ОписаниеПоследовательностей(МетаданныеОбъекта); Для Каждого Элемент Из ОписаниеПоследовательностей Цикл Блокировка.Добавить(Элемент.ПространствоБлокировки).УстановитьЗначение(""Регистратор"", СсылкаОбъекта); КонецЦикла; // Задачи (для бизнес-процессов) ОписаниеЗадач = ОписаниеЗадач(МетаданныеОбъекта); Если ОписаниеЗадач <> Неопределено Тогда Блокировка.Добавить(ОписаниеЗадач.ПространствоБлокировки).УстановитьЗначение(""БизнесПроцесс"", СсылкаОбъекта); КонецЕсли; ИначеЕсли МестоИспользования.КлючЗамены = ""Последовательность"" Тогда СсылкаОбъекта = МестоИспользования.Данные; МетаданныеОбъекта = МестоИспользования.Метаданные; ОписаниеПоследовательностей = ОписаниеПоследовательностей(МетаданныеОбъекта); Для Каждого Элемент Из ОписаниеПоследовательностей Цикл Блокировка.Добавить(Элемент.ПространствоБлокировки).УстановитьЗначение(""Регистратор"", СсылкаОбъекта); КонецЦикла; ИначеЕсли МестоИспользования.КлючЗамены = ""КлючЗаписи"" Или МестоИспользования.КлючЗамены = ""РегистрСведений"" Тогда Информация = ИнформацияОТипе(МестоИспользования.Метаданные, ПараметрыВыполнения); ТипДубля = МестоИспользования.ТипСсылки; ТипОригинала = ТипЗнч(МестоИспользования.ЦелеваяСсылка); Для Каждого КлючЗначение Из Информация.Измерения Цикл ТипИзмерения = КлючЗначение.Значение.Тип; Если ТипИзмерения.СодержитТип(ТипДубля) Тогда БлокировкаПоИзмерению = Блокировка.Добавить(Информация.ПолноеИмя); БлокировкаПоИзмерению.УстановитьЗначение(КлючЗначение.Ключ, МестоИспользования.Ссылка); КонецЕсли; Если ТипИзмерения.СодержитТип(ТипОригинала) Тогда БлокировкаПоИзмерению = Блокировка.Добавить(Информация.ПолноеИмя); БлокировкаПоИзмерению.УстановитьЗначение(КлючЗначение.Ключ, МестоИспользования.ЦелеваяСсылка); КонецЕсли; КонецЦикла; КонецЕсли; КонецПроцедуры Процедура ОтключитьОбновлениеКлючейДоступа(Значение) Если ПодсистемаСуществует(""СтандартныеПодсистемы.УправлениеДоступом"") Тогда УстановитьПривилегированныйРежим(Истина); МодульУправлениеДоступом = ОбщийМодуль(""УправлениеДоступом""); МодульУправлениеДоступом.ОтключитьОбновлениеКлючейДоступа(Значение); КонецЕсли; КонецПроцедуры // Параметры: // ОбъектМетаданных - ОбъектМетаданных // // Возвращаемое значение: // Массив из Структура: // * СписокПолей - Структура // * СтруктураИзмерений - Структура // * СписокВедущих - Структура // * НаборЗаписей - РегистрСведенийНаборЗаписей // * ПространствоБлокировки - Строка // Функция ОписаниеДвижений(Знач ОбъектМетаданных) ОписаниеДвижений = Новый Массив; Если Не Метаданные.Документы.Содержит(ОбъектМетаданных) Тогда Возврат ОписаниеДвижений; КонецЕсли; Для Каждого Движение Из ОбъектМетаданных.Движения Цикл Если Метаданные.РегистрыНакопления.Содержит(Движение) Тогда НаборЗаписей = РегистрыНакопления[Движение.Имя].СоздатьНаборЗаписей(); ИсключатьПоля = ""Активность, НомерСтроки, Период, Регистратор""; ИначеЕсли Метаданные.РегистрыСведений.Содержит(Движение) Тогда НаборЗаписей = РегистрыСведений[Движение.Имя].СоздатьНаборЗаписей(); ИсключатьПоля = ""Активность, ВидДвижения, НомерСтроки, Период, Регистратор""; ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(Движение) Тогда НаборЗаписей = РегистрыБухгалтерии[Движение.Имя].СоздатьНаборЗаписей(); ИсключатьПоля = ""Активность, ВидДвижения, НомерСтроки, Период, Регистратор""; ИначеЕсли Метаданные.РегистрыРасчета.Содержит(Движение) Тогда НаборЗаписей = РегистрыРасчета[Движение.Имя].СоздатьНаборЗаписей(); ИсключатьПоля = ""Активность, БазовыйПериодКонец, БазовыйПериодНачало, НомерСтроки, ПериодДействия, |ПериодДействияКонец, ПериодДействияНачало, ПериодРегистрации, Регистратор, Сторно, |ФактическийПериодДействия""; Иначе // Неизвестный тип Продолжить; КонецЕсли; // Поля ссылочного типа и измерения - кандидаты. // @skip-check query-in-loop - Пустой запрос для получения списка полей таблицы. Описание = СпискиПолейОбъекта(НаборЗаписей, Движение.Измерения, ИсключатьПоля); Если Описание.СписокПолей.Количество() = 0 Тогда // Незачем обрабатывать Продолжить; КонецЕсли; Описание.Вставить(""НаборЗаписей"", НаборЗаписей); Описание.Вставить(""ПространствоБлокировки"", Движение.ПолноеИмя() ); ОписаниеДвижений.Добавить(Описание); КонецЦикла; Возврат ОписаниеДвижений; КонецФункции // Параметры: // Мета - ОбъектМетаданных // // Возвращаемое значение: // Массив из Структура: // * НаборЗаписей - ПоследовательностьНаборЗаписей // * ПространствоБлокировки - Строка // * Измерения - Структура // Функция ОписаниеПоследовательностей(Знач Мета) ОписаниеПоследовательностей = Новый Массив; Если Не Метаданные.Документы.Содержит(Мета) Тогда Возврат ОписаниеПоследовательностей; КонецЕсли; Для Каждого Последовательность Из Метаданные.Последовательности Цикл Если Не Последовательность.Документы.Содержит(Мета) Тогда Продолжить; КонецЕсли; ИмяТаблицы = Последовательность.ПолноеИмя(); // @skip-check query-in-loop - Пустой запрос для получения списка полей таблицы. Описание = СпискиПолейОбъекта(ИмяТаблицы, Последовательность.Измерения, ""Регистратор""); Если Описание.СписокПолей.Количество() > 0 Тогда Описание.Вставить(""НаборЗаписей"", Последовательности[Последовательность.Имя].СоздатьНаборЗаписей()); Описание.Вставить(""ПространствоБлокировки"", ИмяТаблицы + "".Записи""); Описание.Вставить(""Измерения"", Новый Структура); ОписаниеПоследовательностей.Добавить(Описание); КонецЕсли; КонецЦикла; Возврат ОписаниеПоследовательностей; КонецФункции // Возвращаемое значение: // Структура: // * СтандартныеРеквизиты - Структура // * РеквизитыАдресации - Структура // * Реквизиты - Структура // * СтандартныеТабличныеЧасти - Массив из Структура: // ** Имя - Строка // ** СписокПолей - Структура // * ТабличныеЧасти - Массив из Структура: // ** Имя - Строка // ** СписокПолей - Структура // * МожетБытьПроведен - Булево // Функция ОписаниеОбъекта(Знач ОбъектМетаданных) ТипВсеСсылки = ОписаниеТипаВсеСсылки(); Кандидаты = Новый Структура(""Реквизиты, СтандартныеРеквизиты, ТабличныеЧасти, СтандартныеТабличныеЧасти, РеквизитыАдресации""); ЗаполнитьЗначенияСвойств(Кандидаты, ОбъектМетаданных); ОписаниеОбъекта = Новый Структура; ОписаниеОбъекта.Вставить(""Реквизиты"", Новый Структура); Если Кандидаты.Реквизиты <> Неопределено Тогда Для Каждого МетаРеквизит Из Кандидаты.Реквизиты Цикл Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда ОписаниеОбъекта.Реквизиты.Вставить(МетаРеквизит.Имя); КонецЕсли; КонецЦикла; КонецЕсли; ОписаниеОбъекта.Вставить(""СтандартныеРеквизиты"", Новый Структура); Если Кандидаты.СтандартныеРеквизиты <> Неопределено Тогда Исключаемые = Новый Структура(""Ссылка""); Для Каждого МетаРеквизит Из Кандидаты.СтандартныеРеквизиты Цикл Имя = МетаРеквизит.Имя; Если Не Исключаемые.Свойство(Имя) И ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда ОписаниеОбъекта.Реквизиты.Вставить(МетаРеквизит.Имя); КонецЕсли; КонецЦикла; КонецЕсли; ОписаниеОбъекта.Вставить(""ТабличныеЧасти"", Новый Массив); Если Кандидаты.ТабличныеЧасти <> Неопределено Тогда Для Каждого МетаТаблица Из Кандидаты.ТабличныеЧасти Цикл СписокПолей = Новый Структура; Для Каждого МетаРеквизит Из МетаТаблица.Реквизиты Цикл Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда СписокПолей.Вставить(МетаРеквизит.Имя); КонецЕсли; КонецЦикла; Если СписокПолей.Количество() > 0 Тогда ОписаниеОбъекта.ТабличныеЧасти.Добавить(Новый Структура(""Имя, СписокПолей"", МетаТаблица.Имя, СписокПолей)); КонецЕсли; КонецЦикла; КонецЕсли; ОписаниеОбъекта.Вставить(""СтандартныеТабличныеЧасти"", Новый Массив); Если Кандидаты.СтандартныеТабличныеЧасти <> Неопределено Тогда Для Каждого МетаТаблица Из Кандидаты.СтандартныеТабличныеЧасти Цикл СписокПолей = Новый Структура; Для Каждого МетаРеквизит Из МетаТаблица.СтандартныеРеквизиты Цикл Если ОписанияТиповПересекаются(МетаРеквизит.Тип, ТипВсеСсылки) Тогда СписокПолей.Вставить(МетаРеквизит.Имя); КонецЕсли; КонецЦикла; Если СписокПолей.Количество() > 0 Тогда ОписаниеОбъекта.СтандартныеТабличныеЧасти.Добавить(Новый Структура(""Имя, СписокПолей"", МетаТаблица.Имя, СписокПолей)); КонецЕсли; КонецЦикла; КонецЕсли; ОписаниеОбъекта.Вставить(""РеквизитыАдресации"", Новый Структура); Если Кандидаты.РеквизитыАдресации <> Неопределено Тогда Для Каждого Реквизит Из Кандидаты.РеквизитыАдресации Цикл Если ОписанияТиповПересекаются(Реквизит.Тип, ТипВсеСсылки) Тогда ОписаниеОбъекта.РеквизитыАдресации.Вставить(Реквизит.Имя); КонецЕсли; КонецЦикла; КонецЕсли; ОписаниеОбъекта.Вставить(""МожетБытьПроведен"", Метаданные.Документы.Содержит(ОбъектМетаданных)); Возврат ОписаниеОбъекта; КонецФункции // Параметры: // ОбъектМетаданных - ОбъектМетаданных // // Возвращаемое значение: // Массив из Структура: // * СписокПолей - Структура // * СтруктураИзмерений - Структура // * СписокВедущих - Структура // * НаборЗаписей - РегистрСведенийНаборЗаписей // * ПространствоБлокировки - Строка // Функция ОписаниеЗадач(Знач Мета) ОписаниеЗадач = Неопределено; Если НЕ Метаданные.БизнесПроцессы.Содержит(Мета) Тогда Возврат ОписаниеЗадач; КонецЕсли; ОписаниеЗадач = ОписаниеОбъекта(Мета.Задача); ОписаниеЗадач.Вставить(""ПространствоБлокировки"", Мета.Задача.ПолноеИмя()); Возврат ОписаниеЗадач; КонецФункции Функция ОписаниеКлючаЗаписи(Знач МетаданныеТаблицы) ИмяТаблицы = МетаданныеТаблицы.ПолноеИмя(); // Поля ссылочного типа - кандидаты и набор измерений. // @skip-check query-in-loop - Пустой запрос для получения списка полей таблицы. ОписаниеКлюча = СпискиПолейОбъекта(ИмяТаблицы, МетаданныеТаблицы.Измерения, ""Период, Регистратор""); Если Метаданные.РегистрыСведений.Содержит(МетаданныеТаблицы) Тогда НаборЗаписей = РегистрыСведений[МетаданныеТаблицы.Имя].СоздатьНаборЗаписей(); ИначеЕсли Метаданные.РегистрыНакопления.Содержит(МетаданныеТаблицы) Тогда НаборЗаписей = РегистрыНакопления[МетаданныеТаблицы.Имя].СоздатьНаборЗаписей(); ИначеЕсли Метаданные.РегистрыБухгалтерии.Содержит(МетаданныеТаблицы) Тогда НаборЗаписей = РегистрыБухгалтерии[МетаданныеТаблицы.Имя].СоздатьНаборЗаписей(); ИначеЕсли Метаданные.РегистрыРасчета.Содержит(МетаданныеТаблицы) Тогда НаборЗаписей = РегистрыРасчета[МетаданныеТаблицы.Имя].СоздатьНаборЗаписей(); ИначеЕсли Метаданные.Последовательности.Содержит(МетаданныеТаблицы) Тогда НаборЗаписей = Последовательности[МетаданныеТаблицы.Имя].СоздатьНаборЗаписей(); Иначе НаборЗаписей = Неопределено; КонецЕсли; ОписаниеКлюча.Вставить(""НаборЗаписей"", НаборЗаписей); ОписаниеКлюча.Вставить(""ПространствоБлокировки"", ИмяТаблицы); Возврат ОписаниеКлюча; КонецФункции Функция ОписанияТиповПересекаются(Знач Описание1, Знач Описание2) Для Каждого Тип Из Описание1.Типы() Цикл Если Описание2.СодержитТип(Тип) Тогда Возврат Истина; КонецЕсли; КонецЦикла; Возврат Ложь; КонецФункции // Возвращает описание по имени таблицы или по набору записей. Функция СпискиПолейОбъекта(Знач ИсточникДанных, Знач МетаданныеИзмеренийРегистра, Знач ИсключатьПоля) Описание = Новый Структура; Описание.Вставить(""СписокПолей"", Новый Структура); Описание.Вставить(""СтруктураИзмерений"", Новый Структура); Описание.Вставить(""СписокВедущих"", Новый Структура); ТипКонтроля = ОписаниеТипаВсеСсылки(); Исключаемые = Новый Структура(ИсключатьПоля); ТипИсточникаДанных = ТипЗнч(ИсточникДанных); Если ТипИсточникаДанных = Тип(""Строка"") Тогда // Источник - имя таблицы, получаем поля запросом. ТекстЗапроса = ""ВЫБРАТЬ * ИЗ &ИмяТаблицы ГДЕ ЛОЖЬ""; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""&ИмяТаблицы"", ИсточникДанных); Запрос = Новый Запрос(ТекстЗапроса); ИсточникПолей = Запрос.Выполнить(); Иначе // Источник - набор записей ИсточникПолей = ИсточникДанных.ВыгрузитьКолонки(); КонецЕсли; Для Каждого Колонка Из ИсточникПолей.Колонки Цикл Имя = Колонка.Имя; Если Не Исключаемые.Свойство(Имя) И ОписанияТиповПересекаются(Колонка.ТипЗначения, ТипКонтроля) Тогда Описание.СписокПолей.Вставить(Имя); // И проверка на ведущее измерение. Мета = МетаданныеИзмеренийРегистра.Найти(Имя); Если Мета <> Неопределено Тогда Описание.СтруктураИзмерений.Вставить(Имя, Мета.Тип); Тест = Новый Структура(""Ведущее"", Ложь); ЗаполнитьЗначенияСвойств(Тест, Мета); Если Тест.Ведущее Тогда Описание.СписокВедущих.Вставить(Имя, Мета.Тип); КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла; Возврат Описание; КонецФункции Процедура ЗаменитьВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СписокПолей, Знач ПарыЗамен) ИзмененнаяКоллекция = Коллекция.Выгрузить(); Модифицировано = Ложь; ИменаИзмененныхРеквизитов = Новый Массив; Для Каждого Строка Из ИзмененнаяКоллекция Цикл Для Каждого КлючЗначение Из СписокПолей Цикл ИмяРеквизита = КлючЗначение.Ключ; ЦелеваяСсылка = ПарыЗамен[ Строка[ИмяРеквизита] ]; Если ЦелеваяСсылка <> Неопределено Тогда ЗарегистрироватьФактЗамены(Объект, Строка[ИмяРеквизита], ЦелеваяСсылка, ВидКоллекции, ИмяКоллекции, ИзмененнаяКоллекция.Индекс(Строка), ИмяРеквизита); Строка[ИмяРеквизита] = ЦелеваяСсылка; Модифицировано = Истина; ИменаИзмененныхРеквизитов.Добавить(ИмяРеквизита); КонецЕсли; КонецЦикла; КонецЦикла; Если Модифицировано Тогда ЭтоРегистрБухгалтерии = ВидКоллекции = ""Движения"" И ЭтоРегистрБухгалтерии(Коллекция.Метаданные()); Если ЭтоРегистрБухгалтерии Тогда ЗагрузитьИзмененныйНаборВРегистрБухгалтерии(Коллекция, ИзмененнаяКоллекция, ИменаИзмененныхРеквизитов); Иначе Коллекция.Загрузить(ИзмененнаяКоллекция); КонецЕсли; КонецЕсли; КонецПроцедуры Процедура ЗагрузитьИзмененныйНаборВРегистрБухгалтерии(НаборЗаписей, ИзмененнаяКоллекция, ИменаИзмененныхРеквизитов) НеизмененныеИзмерения = Новый Соответствие; ИзмененныеИзмерения = Новый Соответствие; МетаданныеРегистра = НаборЗаписей.Метаданные(); Для каждого Измерение Из МетаданныеРегистра.Измерения Цикл ИменаИзмерений = Новый Массив; Если Измерение.Балансовый ИЛИ НЕ МетаданныеРегистра.Корреспонденция Тогда ИменаИзмерений.Добавить(Измерение.Имя); Иначе ИменаИзмерений.Добавить(Измерение.Имя + ""Дт""); ИменаИзмерений.Добавить(Измерение.Имя + ""Кт""); КонецЕсли; Для каждого ИмяИзмерения Из ИменаИзмерений Цикл Если ИменаИзмененныхРеквизитов.Найти(ИмяИзмерения) = Неопределено Тогда НеизмененныеИзмерения.Вставить(ИмяИзмерения, НаборЗаписей.ВыгрузитьКолонку(ИмяИзмерения)); Иначе ИзмененныеИзмерения.Вставить(ИмяИзмерения, НаборЗаписей.ВыгрузитьКолонку(ИмяИзмерения)); КонецЕсли; КонецЦикла; КонецЦикла; Для Сч = 0 По НаборЗаписей.Количество()-1 Цикл Для каждого ИмяИзмеренияЗначения Из ИзмененныеИзмерения Цикл Если НаборЗаписей[Сч][ИмяИзмеренияЗначения.Ключ] = NULL Тогда ИмяИзмеренияЗначения.Значение[Сч] = NULL; Иначе ИмяИзмеренияЗначения.Значение[Сч] = ИзмененнаяКоллекция[Сч][ИмяИзмеренияЗначения.Ключ]; КонецЕсли; КонецЦикла; КонецЦикла; НаборЗаписей.Загрузить(ИзмененнаяКоллекция); Для каждого ИзмеренияЗначенияВКолонке Из НеизмененныеИзмерения Цикл НаборЗаписей.ЗагрузитьКолонку(ИзмеренияЗначенияВКолонке.Значение, ИзмеренияЗначенияВКолонке.Ключ); КонецЦикла; Для каждого ИзмеренияЗначенияВКолонке Из ИзмененныеИзмерения Цикл НаборЗаписей.ЗагрузитьКолонку(ИзмеренияЗначенияВКолонке.Значение, ИзмеренияЗначенияВКолонке.Ключ); КонецЦикла; КонецПроцедуры Процедура ОбработатьОбъектСПерехватомСообщений(Знач Объект, Знач Действие, Знач РежимЗаписи, Знач ПараметрыЗаписи) // Текущие сообщения до исключения запоминаем. ПредыдущиеСообщения = ПолучитьСообщенияПользователю(Истина); СообщатьПовторно = ТекущийРежимЗапуска() <> Неопределено; Попытка Если Действие = ""Запись"" Тогда Объект.ОбменДанными.Загрузка = Не ПараметрыЗаписи.ВключатьБизнесЛогику; Если РежимЗаписи = Неопределено Тогда Объект.Записать(); Иначе Объект.Записать(РежимЗаписи); КонецЕсли; ИначеЕсли Действие = ""ПометкаУдаления"" Тогда МетаданныеОбъекта = Объект.Метаданные(); Если ЭтоСправочник(МетаданныеОбъекта) Или ЭтоПланВидовХарактеристик(МетаданныеОбъекта) Или ЭтоПланСчетов(МетаданныеОбъекта) Тогда Объект.ОбменДанными.Загрузка = Не ПараметрыЗаписи.ВключатьБизнесЛогику; Объект.УстановитьПометкуУдаления(Истина, Ложь); ИначеЕсли ЭтоДокумент(МетаданныеОбъекта) И МетаданныеОбъекта.Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда Объект.УстановитьПометкуУдаления(Истина); Иначе Объект.ОбменДанными.Загрузка = Не ПараметрыЗаписи.ВключатьБизнесЛогику; Объект.УстановитьПометкуУдаления(Истина); КонецЕсли; КонецЕсли; Исключение // Перехватываем все сообщенное при ошибке и добавляем их в одно исключение. ТекстИсключения = ""; Для Каждого Сообщение Из ПолучитьСообщенияПользователю(Ложь) Цикл ТекстИсключения = ТекстИсключения + Символы.ПС + Сообщение.Текст; КонецЦикла; // Сообщаем предыдущие Если СообщатьПовторно Тогда СообщитьОтложенныеСообщения(ПредыдущиеСообщения); КонецЕсли; Если ТекстИсключения = "" Тогда ВызватьИсключение; КонецЕсли; ВызватьИсключение СокрЛП(ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()) + Символы.ПС + СокрЛП(ТекстИсключения)); КонецПопытки; Если СообщатьПовторно Тогда СообщитьОтложенныеСообщения(ПредыдущиеСообщения); КонецЕсли; КонецПроцедуры Процедура СообщитьОтложенныеСообщения(Знач Сообщения) Для Каждого Сообщение Из Сообщения Цикл Сообщение.Сообщить(); КонецЦикла; КонецПроцедуры Процедура ЗаписатьОбъект(Знач Объект, Знач ПараметрыЗаписи) МетаданныеОбъекта = Объект.Метаданные(); Если ЭтоДокумент(МетаданныеОбъекта) Тогда ОбработатьОбъектСПерехватомСообщений(Объект, ""Запись"", РежимЗаписиДокумента.Запись, ПараметрыЗаписи); Возврат; КонецЕсли; // Проверка на возможные циклические ссылки. СвойстваОбъекта = Новый Структура(""Иерархический, ВидыСубконто, Владельцы"", Ложь, Неопределено, Новый Массив); ЗаполнитьЗначенияСвойств(СвойстваОбъекта, МетаданныеОбъекта); // По родителю Если СвойстваОбъекта.Иерархический Или СвойстваОбъекта.ВидыСубконто <> Неопределено Тогда Если Объект.Родитель = Объект.Ссылка Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'При записи ""%1"" возникает циклическая ссылка в иерархии.'""), Строка(Объект)); КонецЕсли; КонецЕсли; // По владельцу Если СвойстваОбъекта.Владельцы.Количество() > 1 И Объект.Владелец = Объект.Ссылка Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'При записи ""%1"" возникает циклическая ссылка в подчинении.'""), Строка(Объект)); КонецЕсли; // Для последовательностей право ""Изменение"" может отсутствовать даже у роли ""АдминистраторСистемы"". Если ЭтоПоследовательность(МетаданныеОбъекта) И Не ПравоДоступа(""Изменение"", МетаданныеОбъекта) И Пользователи.ЭтоПолноправныйПользователь(,, Ложь) Тогда УстановитьПривилегированныйРежим(Истина); КонецЕсли; // Просто запись ОбработатьОбъектСПерехватомСообщений(Объект, ""Запись"", Неопределено, ПараметрыЗаписи); КонецПроцедуры Функция СобытиеЖурналаРегистрацииЗаменыСсылок() Возврат НСтр(""ru = 'Поиск и удаление ссылок'"", КодОсновногоЯзыка()); КонецФункции // Параметры: // Результат - см. РезультатЗаменыСсылок // Ссылка - ЛюбаяСсылка // ОписаниеОшибки - см. ОписаниеОшибкиЗамены // Процедура ЗарегистрироватьОшибкуЗамены(Результат, Знач Ссылка, Знач ОписаниеОшибки) Результат.ЕстьОшибки = Истина; Строка = Результат.Ошибки.Добавить(); Строка.Ссылка = Ссылка; Строка.ПредставлениеОбъектаОшибки = ОписаниеОшибки.ПредставлениеОбъектаОшибки; Строка.ОбъектОшибки = ОписаниеОшибки.ОбъектОшибки; Строка.ТекстОшибки = ОписаниеОшибки.ТекстОшибки; Строка.ТипОшибки = ОписаниеОшибки.ТипОшибки; КонецПроцедуры // Возвращаемое значение: // Структура: // * ТипОшибки - Строка // * ОбъектОшибки - ЛюбаяСсылка // * ПредставлениеОбъектаОшибки - Строка // * ТекстОшибки - Строка // Функция ОписаниеОшибкиЗамены(Знач ТипОшибки, Знач ОбъектОшибки, Знач ПредставлениеОбъектаОшибки, Знач ТекстОшибки) Результат = Новый Структура; Результат.Вставить(""ТипОшибки"", ТипОшибки); Результат.Вставить(""ОбъектОшибки"", ОбъектОшибки); Результат.Вставить(""ПредставлениеОбъектаОшибки"", ПредставлениеОбъектаОшибки); Результат.Вставить(""ТекстОшибки"", ТекстОшибки); Возврат Результат; КонецФункции // Возвращаемое значение: // Структура: // * ЕстьОшибки - Булево // * ОчередьКНепосредственномуУдалению - Массив // * Ошибки - см. ОбщегоНазначения.ЗаменитьСсылки // Функция РезультатЗаменыСсылок(Знач ОшибкиЗамены) Результат = Новый Структура; Результат.Вставить(""ЕстьОшибки"", Ложь); Результат.Вставить(""ОчередьКНепосредственномуУдалению"", Новый Массив); Результат.Вставить(""Ошибки"", ОшибкиЗамены); Возврат Результат КонецФункции Процедура ЗарегистрироватьОшибкуВТаблицу(Результат, Дубль, Оригинал, Данные, Информация, ТипОшибки, ИнформацияОбОшибке) Результат.ЕстьОшибки = Истина; ЗаписьЖурналаРегистрации( СобытиеЖурналаРегистрацииЗаменыСсылок(), УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке)); ПолноеПредставлениеДанных = Строка(Данные) + "" ("" + Информация.ПредставлениеЭлемента + "")""; Ошибка = Результат.Ошибки.Добавить(); Ошибка.Ссылка = Дубль; Ошибка.ОбъектОшибки = Данные; Ошибка.ПредставлениеОбъектаОшибки = ПолноеПредставлениеДанных; Если ТипОшибки = ""БлокировкаДляРегистра"" Тогда НовыйШаблон = НСтр(""ru = 'Не удалось начать редактирование %1: %2'""); Ошибка.ТипОшибки = ""ОшибкаБлокировки""; ИначеЕсли ТипОшибки = ""БлокировкаДляУдаленияДубля"" Тогда НовыйШаблон = НСтр(""ru = 'Не удалось начать удаление: %2'""); Ошибка.ТипОшибки = ""ОшибкаБлокировки""; ИначеЕсли ТипОшибки = ""УдалитьНаборДубля"" Тогда НовыйШаблон = НСтр(""ru = 'Не удалось очистить сведения о дубле в %1: %2'""); Ошибка.ТипОшибки = ""ОшибкаЗаписи""; ИначеЕсли ТипОшибки = ""ЗаписатьНаборОригинала"" Тогда НовыйШаблон = НСтр(""ru = 'Не удалось обновить сведения в %1: %2'""); Ошибка.ТипОшибки = ""ОшибкаЗаписи""; Иначе НовыйШаблон = ТипОшибки + "" (%1): %2""; Ошибка.ТипОшибки = ТипОшибки; КонецЕсли; НовыйШаблон = НовыйШаблон + Символы.ПС + Символы.ПС + НСтр(""ru = 'Подробности в журнале регистрации.'""); КраткоеПредставление = ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке); Ошибка.ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НовыйШаблон, ПолноеПредставлениеДанных, КраткоеПредставление); КонецПроцедуры // Формирует информацию о типе объекта метаданных: полное имя, представления, вид и т.п. Функция ИнформацияОТипе(ПолноеИмяИлиМетаданныеИлиТип, Кэш) ТипПервогоПараметра = ТипЗнч(ПолноеИмяИлиМетаданныеИлиТип); Если ТипПервогоПараметра = Тип(""Строка"") Тогда ОбъектМетаданных = ОбъектМетаданныхПоПолномуИмени(ПолноеИмяИлиМетаданныеИлиТип); Иначе Если ТипПервогоПараметра = Тип(""Тип"") Тогда // Поиск объекта метаданных. ОбъектМетаданных = Метаданные.НайтиПоТипу(ПолноеИмяИлиМетаданныеИлиТип); Иначе ОбъектМетаданных = ПолноеИмяИлиМетаданныеИлиТип; КонецЕсли; КонецЕсли; ПолноеИмя = ВРег(ОбъектМетаданных.ПолноеИмя()); ИнформацияОТипах = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Кэш, ""ИнформацияОТипах""); Если ИнформацияОТипах = Неопределено Тогда ИнформацияОТипах = Новый Соответствие; Кэш.Вставить(""ИнформацияОТипах"", ИнформацияОТипах); Иначе Информация = ИнформацияОТипах.Получить(ПолноеИмя); Если Информация <> Неопределено Тогда Возврат Информация; КонецЕсли; КонецЕсли; Информация = Новый Структура(""ПолноеИмя, ПредставлениеЭлемента, |Вид, Ссылочный, Технический, Разделенный, |Иерархический, |ЕстьПодчиненные, ИменаПодчиненных, |Измерения, Реквизиты, Ресурсы""); ИнформацияОТипах.Вставить(ПолноеИмя, Информация); // Заполнение базовой информации. Информация.ПолноеИмя = ПолноеИмя; // Представление элемента. Информация.ПредставлениеЭлемента = ПредставлениеОбъекта(ОбъектМетаданных); // Вид и его свойства. Информация.Вид = Лев(Информация.ПолноеИмя, СтрНайти(Информация.ПолноеИмя, ""."")-1); Если Информация.Вид = ""СПРАВОЧНИК"" Или Информация.Вид = ""ДОКУМЕНТ"" Или Информация.Вид = ""ПЕРЕЧИСЛЕНИЕ"" Или Информация.Вид = ""ПЛАНВИДОВХАРАКТЕРИСТИК"" Или Информация.Вид = ""ПЛАНСЧЕТОВ"" Или Информация.Вид = ""ПЛАНВИДОВРАСЧЕТА"" Или Информация.Вид = ""БИЗНЕСПРОЦЕСС"" Или Информация.Вид = ""ЗАДАЧА"" Или Информация.Вид = ""ПЛАНОБМЕНА"" Тогда Информация.Ссылочный = Истина; Иначе Информация.Ссылочный = Ложь; КонецЕсли; Если Информация.Вид = ""СПРАВОЧНИК"" Или Информация.Вид = ""ПЛАНВИДОВХАРАКТЕРИСТИК"" Тогда Информация.Иерархический = ОбъектМетаданных.Иерархический; ИначеЕсли Информация.Вид = ""ПЛАНСЧЕТОВ"" Тогда Информация.Иерархический = Истина; Иначе Информация.Иерархический = Ложь; КонецЕсли; Информация.ЕстьПодчиненные = Ложь; Если Информация.Вид = ""СПРАВОЧНИК"" Или Информация.Вид = ""ПЛАНВИДОВХАРАКТЕРИСТИК"" Или Информация.Вид = ""ПЛАНОБМЕНА"" Или Информация.Вид = ""ПЛАНСЧЕТОВ"" Или Информация.Вид = ""ПЛАНВИДОВРАСЧЕТА"" Тогда Для Каждого Справочник Из Метаданные.Справочники Цикл Если Справочник.Владельцы.Содержит(ОбъектМетаданных) Тогда Если Информация.ЕстьПодчиненные = Ложь Тогда Информация.ЕстьПодчиненные = Истина; Информация.ИменаПодчиненных = Новый Массив; КонецЕсли; ИменаПодчиненных = Информация.ИменаПодчиненных; // Массив - ИменаПодчиненных.Добавить(Справочник.ПолноеИмя()); КонецЕсли; КонецЦикла; КонецЕсли; Если Информация.ПолноеИмя = ""СПРАВОЧНИК.ИДЕНТИФИКАТОРЫОБЪЕКТОВМЕТАДАННЫХ"" Или Информация.ПолноеИмя = ""СПРАВОЧНИК.ПРЕДОПРЕДЕЛЕННЫЕВАРИАНТЫОТЧЕТОВ"" Тогда Информация.Технический = Истина; Информация.Разделенный = Ложь; Иначе Информация.Технический = Ложь; Если Не Кэш.Свойство(""МодельСервиса"") Тогда Кэш.Вставить(""МодельСервиса"", РазделениеВключено()); Если Кэш.МодельСервиса Тогда Если ПодсистемаСуществует(""ТехнологияСервиса.БазоваяФункциональность"") Тогда МодульРаботаВМоделиСервиса = ОбщийМодуль(""РаботаВМоделиСервиса""); РазделительОсновныхДанных = МодульРаботаВМоделиСервиса.РазделительОсновныхДанных(); РазделительВспомогательныхДанных = МодульРаботаВМоделиСервиса.РазделительВспомогательныхДанных(); Иначе РазделительОсновныхДанных = Неопределено; РазделительВспомогательныхДанных = Неопределено; КонецЕсли; Кэш.Вставить(""ВОбластиДанных"", РазделениеВключено() И ДоступноИспользованиеРазделенныхДанных()); Кэш.Вставить(""РазделительОсновныхДанных"", РазделительОсновныхДанных); Кэш.Вставить(""РазделительВспомогательныхДанных"", РазделительВспомогательныхДанных); КонецЕсли; КонецЕсли; Если Кэш.МодельСервиса Тогда Если ПодсистемаСуществует(""ТехнологияСервиса.БазоваяФункциональность"") Тогда МодульРаботаВМоделиСервиса = ОбщийМодуль(""РаботаВМоделиСервиса""); ЭтоРазделенныйОбъектМетаданных = МодульРаботаВМоделиСервиса.ЭтоРазделенныйОбъектМетаданных(ОбъектМетаданных); Иначе ЭтоРазделенныйОбъектМетаданных = Истина; КонецЕсли; Информация.Разделенный = ЭтоРазделенныйОбъектМетаданных; КонецЕсли; КонецЕсли; Информация.Измерения = Новый Структура; Информация.Реквизиты = Новый Структура; Информация.Ресурсы = Новый Структура; ВидыРеквизитов = Новый Структура(""СтандартныеРеквизиты, Реквизиты, Измерения, Ресурсы""); ЗаполнитьЗначенияСвойств(ВидыРеквизитов, ОбъектМетаданных); Для Каждого КлючИЗначение Из ВидыРеквизитов Цикл Коллекция = КлючИЗначение.Значение; // КоллекцияОбъектовМетаданных Если ТипЗнч(Коллекция) = Тип(""КоллекцияОбъектовМетаданных"") Тогда КудаПишем = ?(Информация.Свойство(КлючИЗначение.Ключ), Информация[КлючИЗначение.Ключ], Информация.Реквизиты); Для Каждого Реквизит Из Коллекция Цикл КудаПишем.Вставить(Реквизит.Имя, ИнформацияПоРеквизиту(Реквизит)); КонецЦикла; КонецЕсли; КонецЦикла; Если Информация.Вид = ""РЕГИСТРСВЕДЕНИЙ"" И ОбъектМетаданных.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический Тогда ИнформацияПоРеквизиту = Новый Структура(""Ведущее, Представление, Формат, Тип, ЗначениеПоУмолчанию, ЗаполнятьИзДанныхЗаполнения""); ИнформацияПоРеквизиту.Ведущее = Ложь; ИнформацияПоРеквизиту.ЗаполнятьИзДанныхЗаполнения = Ложь; Если ОбъектМетаданных.ПериодичностьРегистраСведений = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.ПозицияРегистратора Тогда ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов(""МоментВремени""); ИначеЕсли ОбъектМетаданных.ПериодичностьРегистраСведений = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Секунда Тогда ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов(""Дата"", , , Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)); Иначе ИнформацияПоРеквизиту.Тип = Новый ОписаниеТипов(""Дата"", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)); КонецЕсли; Информация.Измерения.Вставить(""Период"", ИнформацияПоРеквизиту); КонецЕсли; Возврат Информация; КонецФункции // Параметры: // МетаданныеРеквизита - ОбъектМетаданныхРеквизит // Функция ИнформацияПоРеквизиту(МетаданныеРеквизита) // ОписаниеСтандартногоРеквизита // ОбъектМетаданных: Измерение // ОбъектМетаданных: Ресурс // ОбъектМетаданных: Реквизит Информация = Новый Структура(""Ведущее, Представление, Формат, Тип, ЗначениеПоУмолчанию, ЗаполнятьИзДанныхЗаполнения""); ЗаполнитьЗначенияСвойств(Информация, МетаданныеРеквизита); Информация.Представление = МетаданныеРеквизита.Представление(); Если Информация.ЗаполнятьИзДанныхЗаполнения = Истина Тогда Информация.ЗначениеПоУмолчанию = МетаданныеРеквизита.ЗначениеЗаполнения; Иначе Информация.ЗначениеПоУмолчанию = МетаданныеРеквизита.Тип.ПривестиЗначение(); КонецЕсли; Возврат Информация; КонецФункции Процедура ДобавитьВСтатистикуЗаменыСсылок(Статистика, Дубль, ЕстьОшибки) КлючДубля = Дубль.Метаданные().ПолноеИмя(); ЭлементСтатистики = Статистика[КлючДубля]; Если ЭлементСтатистики = Неопределено Тогда ЭлементСтатистики = Новый Структура(""КоличествоЭлементов, КоличествоОшибок"",0,0); Статистика.Вставить(КлючДубля, ЭлементСтатистики); КонецЕсли; ЭлементСтатистики.КоличествоЭлементов = ЭлементСтатистики.КоличествоЭлементов + 1; ЭлементСтатистики.КоличествоОшибок = ЭлементСтатистики.КоличествоОшибок + ?(ЕстьОшибки, 1,0); КонецПроцедуры Процедура ОтправитьСтатистикуЗаменыСсылок(Статистика) Если НЕ ПодсистемаСуществует(""СтандартныеПодсистемы.ЦентрМониторинга"") Тогда Возврат; КонецЕсли; МодульЦентрМониторинга = ОбщийМодуль(""ЦентрМониторинга""); Для каждого ЭлементСтатистики Из Статистика Цикл МодульЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики( ""БазоваяФункциональность.ЗаменаСсылок."" + ЭлементСтатистики.Ключ, ЭлементСтатистики.Значение.КоличествоЭлементов); МодульЦентрМониторинга.ЗаписатьОперациюБизнесСтатистики( ""БазоваяФункциональность.ЗаменаСсылокКоличествоОшибок."" + ЭлементСтатистики.Ключ, ЭлементСтатистики.Значение.КоличествоОшибок); КонецЦикла; КонецПроцедуры Процедура ДополнитьИсключенияПоискаСсылокПодчиненнымиОбъектами(Знач ИсключенияПоискаСсылок) Для каждого ОписаниеПодчиненногоОбъекта Из ПодчиненныеОбъекты() Цикл ПоляСвязи = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок( ОписаниеПодчиненногоОбъекта.ПоляСвязей, "","",, Истина); ЗначениеИсключенияПоискаСсылок = Новый Массив; Для каждого ПолеСвязи Из ПоляСвязи Цикл ЗначениеИсключенияПоискаСсылок.Добавить(ПолеСвязи); КонецЦикла; ИсключенияПоискаСсылок.Вставить(ОписаниеПодчиненногоОбъекта.ПодчиненныйОбъект, ЗначениеИсключенияПоискаСсылок); КонецЦикла; КонецПроцедуры Процедура ЗарегистрироватьОшибкиУдаления(Результат, ПрепятствующиеУдалению) ПредставленияСсылок = ПредметыСтрокой(ПрепятствующиеУдалению.ВыгрузитьКолонку(""МестоИспользования"")); Для каждого ПрепятствующиеУдалению Из ПрепятствующиеУдалению Цикл ТекстОшибки = НСтр(""ru = 'Элемент не удален, т.к. на него есть ссылки'""); ОписаниеОшибки = ОписаниеОшибкиЗамены(""ОшибкаУдаления"", ПрепятствующиеУдалению.МестоИспользования, ПредставленияСсылок[ПрепятствующиеУдалению.МестоИспользования], ТекстОшибки); ЗарегистрироватьОшибкуЗамены(Результат, ПрепятствующиеУдалению.УдаляемыйСсылка, ОписаниеОшибки); КонецЦикла; КонецПроцедуры Функция СформироватьДубли(ПараметрыВыполнения, ПараметрыЗамены, ПарыЗамен, Результат) Дубли = Новый Массив; Для Каждого КлючЗначение Из ПарыЗамен Цикл Дубль = КлючЗначение.Ключ; Оригинал = КлючЗначение.Значение; Если Дубль = Оригинал Или Дубль.Пустая() Тогда Продолжить; // Самого на себя и пустые ссылки не заменяем. КонецЕсли; Дубли.Добавить(Дубль); // Пропускаем промежуточные замены, чтобы не строить граф (если A->B и B->C то вместо A->B производится замена A->C). ОригиналОригинала = ПарыЗамен[Оригинал]; ЕстьОригиналОригинала = (ОригиналОригинала <> Неопределено И ОригиналОригинала <> Дубль И ОригиналОригинала <> Оригинал); Если ЕстьОригиналОригинала Тогда Пока ЕстьОригиналОригинала Цикл Оригинал = ОригиналОригинала; ОригиналОригинала = ПарыЗамен[Оригинал]; ЕстьОригиналОригинала = (ОригиналОригинала <> Неопределено И ОригиналОригинала <> Дубль И ОригиналОригинала <> Оригинал); КонецЦикла; ПарыЗамен.Вставить(Дубль, Оригинал); КонецЕсли; КонецЦикла; Если ПараметрыВыполнения.УчитыватьПрикладныеПравила И ПодсистемаСуществует(""СтандартныеПодсистемы.ПоискИУдалениеДублей"") Тогда МодульПоискИУдалениеДублей = ОбщийМодуль(""ПоискИУдалениеДублей""); Ошибки = МодульПоискИУдалениеДублей.ПроверитьВозможностьЗаменыЭлементов(ПарыЗамен, ПараметрыЗамены); ОригиналыОбъектов = Новый Массив; Для Каждого КлючЗначение Из Ошибки Цикл Дубль = КлючЗначение.Ключ; ОригиналыОбъектов.Добавить(ПарыЗамен[Дубль]); Индекс = Дубли.Найти(Дубль); Если Индекс <> Неопределено Тогда Дубли.Удалить(Индекс); // пропускаем проблемный элемент. КонецЕсли; КонецЦикла; ПредставленияОбъектов = ПредметыСтрокой(ОригиналыОбъектов); Для Каждого КлючЗначение Из Ошибки Цикл Дубль = КлючЗначение.Ключ; Оригинал = ПарыЗамен[Дубль]; ТекстОшибки = КлючЗначение.Значение; Причина = ОписаниеОшибкиЗамены(""ОшибкаЗаписи"", Оригинал, ПредставленияОбъектов[Оригинал], ТекстОшибки); ЗарегистрироватьОшибкуЗамены(Результат, Дубль, Причина); КонецЦикла; КонецЕсли; Возврат Дубли; КонецФункции Функция НовыйПараметрыВыполненияЗаменыСсылок(Знач ПараметрыЗамены) ПараметрыПоУмолчанию = ПараметрыЗаменыСсылок(); ПараметрыВыполнения = Новый Структура; ПараметрыВыполнения.Вставить(""УдалятьНепосредственно"", ПараметрыПоУмолчанию.СпособУдаления = ""Непосредственно""); ПараметрыВыполнения.Вставить(""ПомечатьНаУдаление"", ПараметрыПоУмолчанию.СпособУдаления = ""Пометка""); ПараметрыВыполнения.Вставить(""ВключатьБизнесЛогику"", ПараметрыПоУмолчанию.ВключатьБизнесЛогику); ПараметрыВыполнения.Вставить(""ПривилегированнаяЗапись"", ПараметрыПоУмолчанию.ПривилегированнаяЗапись); ПараметрыВыполнения.Вставить(""УчитыватьПрикладныеПравила"", ПараметрыПоУмолчанию.УчитыватьПрикладныеПравила); ПараметрыВыполнения.Вставить(""МестаЗамены"", Новый Массив); // Переданные параметры обрабатываются условно для обратной совместимости. ЗначениеПараметра = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗамены, ""СпособУдаления""); Если ЗначениеПараметра = ""Непосредственно"" Тогда ПараметрыВыполнения.УдалятьНепосредственно = Истина; ПараметрыВыполнения.ПомечатьНаУдаление = Ложь; ИначеЕсли ЗначениеПараметра = ""Пометка"" Тогда ПараметрыВыполнения.УдалятьНепосредственно = Ложь; ПараметрыВыполнения.ПомечатьНаУдаление = Истина; КонецЕсли; ЗначениеПараметра = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗамены, ""ВключатьБизнесЛогику""); Если ТипЗнч(ЗначениеПараметра) = Тип(""Булево"") Тогда ПараметрыВыполнения.ВключатьБизнесЛогику = ЗначениеПараметра; КонецЕсли; ЗначениеПараметра = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗамены, ""ПривилегированнаяЗапись""); Если ТипЗнч(ЗначениеПараметра) = Тип(""Булево"") Тогда ПараметрыВыполнения.ПривилегированнаяЗапись = ЗначениеПараметра; КонецЕсли; ЗначениеПараметра = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗамены, ""УчитыватьПрикладныеПравила""); Если ТипЗнч(ЗначениеПараметра) = Тип(""Булево"") Тогда ПараметрыВыполнения.УчитыватьПрикладныеПравила = ЗначениеПараметра; КонецЕсли; ЗначениеПараметра = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗамены, ""МестаЗамены"", Новый Массив); Если (ЗначениеПараметра.Количество() > 0) Тогда ПараметрыВыполнения.МестаЗамены = Новый Массив(Новый ФиксированныйМассив(ЗначениеПараметра)); КонецЕсли; Возврат ПараметрыВыполнения; КонецФункции #КонецОбласти #Область МестаИспользования Функция ОписаниеТипаКлючиЗаписей() ДобавляемыеТипы = Новый Массив; Для Каждого Мета Из Метаданные.РегистрыСведений Цикл ДобавляемыеТипы.Добавить(Тип(""РегистрСведенийКлючЗаписи."" + Мета.Имя)); КонецЦикла; Для Каждого Мета Из Метаданные.РегистрыНакопления Цикл ДобавляемыеТипы.Добавить(Тип(""РегистрНакопленияКлючЗаписи."" + Мета.Имя)); КонецЦикла; Для Каждого Мета Из Метаданные.РегистрыБухгалтерии Цикл ДобавляемыеТипы.Добавить(Тип(""РегистрБухгалтерииКлючЗаписи."" + Мета.Имя)); КонецЦикла; Для Каждого Мета Из Метаданные.РегистрыРасчета Цикл ДобавляемыеТипы.Добавить(Тип(""РегистрРасчетаКлючЗаписи."" + Мета.Имя)); КонецЦикла; Возврат Новый ОписаниеТипов(ДобавляемыеТипы); КонецФункции Функция ОписаниеИзмеренийНабора(Знач МетаданныеРегистра, КэшИзмеренийРегистров) ОписаниеИзмерений = КэшИзмеренийРегистров[МетаданныеРегистра]; Если ОписаниеИзмерений <> Неопределено Тогда Возврат ОписаниеИзмерений; КонецЕсли; // Период и регистратор, если есть. ОписаниеИзмерений = Новый Структура; ДанныеИзмерения = Новый Структура(""Ведущее, Представление, Формат, Тип"", Ложь); Если Метаданные.РегистрыСведений.Содержит(МетаданныеРегистра) Тогда // Возможно есть период МетаПериод = МетаданныеРегистра.ПериодичностьРегистраСведений; Периодичность = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений; Если МетаПериод = Периодичность.ПозицияРегистратора Тогда ДанныеИзмерения.Тип = Документы.ТипВсеСсылки(); ДанныеИзмерения.Представление = НСтр(""ru = 'Регистратор'""); ДанныеИзмерения.Ведущее = Истина; ОписаниеИзмерений.Вставить(""Регистратор"", ДанныеИзмерения); ИначеЕсли МетаПериод = Периодичность.Год Тогда ДанныеИзмерения.Тип = Новый ОписаниеТипов(""Дата""); ДанныеИзмерения.Представление = НСтр(""ru = 'Период'""); ДанныеИзмерения.Формат = НСтр(""ru = 'ДФ=''yyyy ""г.""''; ДП=''Дата не задана'''""); ОписаниеИзмерений.Вставить(""Период"", ДанныеИзмерения); ИначеЕсли МетаПериод = Периодичность.День Тогда ДанныеИзмерения.Тип = Новый ОписаниеТипов(""Дата""); ДанныеИзмерения.Представление = НСтр(""ru = 'Период'""); ДанныеИзмерения.Формат = НСтр(""ru = 'ДЛФ=D; ДП=''Дата не задана'''""); ОписаниеИзмерений.Вставить(""Период"", ДанныеИзмерения); ИначеЕсли МетаПериод = Периодичность.Квартал Тогда ДанныеИзмерения.Тип = Новый ОписаниеТипов(""Дата""); ДанныеИзмерения.Представление = НСтр(""ru = 'Период'""); ДанныеИзмерения.Формат = НСтр(""ru = 'ДФ=''к """"квартал """"yyyy """"г.""""''; ДП=''Дата не задана'''""); ОписаниеИзмерений.Вставить(""Период"", ДанныеИзмерения); ИначеЕсли МетаПериод = Периодичность.Месяц Тогда ДанныеИзмерения.Тип = Новый ОписаниеТипов(""Дата""); ДанныеИзмерения.Представление = НСтр(""ru = 'Период'""); ДанныеИзмерения.Формат = НСтр(""ru = 'ДФ=''ММММ yyyy """"г.""""''; ДП=''Дата не задана'''""); ОписаниеИзмерений.Вставить(""Период"", ДанныеИзмерения); ИначеЕсли МетаПериод = Периодичность.Секунда Тогда ДанныеИзмерения.Тип = Новый ОписаниеТипов(""Дата""); ДанныеИзмерения.Представление = НСтр(""ru = 'Период'""); ДанныеИзмерения.Формат = НСтр(""ru = 'ДЛФ=DT; ДП=''Дата не задана'''""); ОписаниеИзмерений.Вставить(""Период"", ДанныеИзмерения); КонецЕсли; Иначе ДанныеИзмерения.Тип = Документы.ТипВсеСсылки(); ДанныеИзмерения.Представление = НСтр(""ru = 'Регистратор'""); ДанныеИзмерения.Ведущее = Истина; ОписаниеИзмерений.Вставить(""Регистратор"", ДанныеИзмерения); КонецЕсли; // Все измерения Для Каждого МетаИзмерение Из МетаданныеРегистра.Измерения Цикл ДанныеИзмерения = Новый Структура(""Ведущее, Представление, Формат, Тип""); ДанныеИзмерения.Тип = МетаИзмерение.Тип; ДанныеИзмерения.Представление = МетаИзмерение.Представление(); ДанныеИзмерения.Ведущее = МетаИзмерение.Ведущее; ОписаниеИзмерений.Вставить(МетаИзмерение.Имя, ДанныеИзмерения); КонецЦикла; КэшИзмеренийРегистров[МетаданныеРегистра] = ОписаниеИзмерений; Возврат ОписаниеИзмерений; КонецФункции #КонецОбласти #КонецОбласти #Область УсловныеВызовы // Возвращает серверный модуль менеджера по имени объекта. Функция СерверныйМодульМенеджера(Имя) ОбъектНайден = Ложь; ЧастиИмени = СтрРазделить(Имя, "".""); Если ЧастиИмени.Количество() = 2 Тогда ИмяВида = ВРег(ЧастиИмени[0]); ИмяОбъекта = ЧастиИмени[1]; Если ИмяВида = ВРег(""Константы"") Тогда Если Метаданные.Константы.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""РегистрыСведений"") Тогда Если Метаданные.РегистрыСведений.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""РегистрыНакопления"") Тогда Если Метаданные.РегистрыНакопления.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""РегистрыБухгалтерии"") Тогда Если Метаданные.РегистрыБухгалтерии.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""РегистрыРасчета"") Тогда Если Метаданные.РегистрыРасчета.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""Справочники"") Тогда Если Метаданные.Справочники.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""Документы"") Тогда Если Метаданные.Документы.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""Отчеты"") Тогда Если Метаданные.Отчеты.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""Обработки"") Тогда Если Метаданные.Обработки.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""БизнесПроцессы"") Тогда Если Метаданные.БизнесПроцессы.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""ЖурналыДокументов"") Тогда Если Метаданные.ЖурналыДокументов.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""Задачи"") Тогда Если Метаданные.Задачи.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""ПланыСчетов"") Тогда Если Метаданные.ПланыСчетов.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""ПланыОбмена"") Тогда Если Метаданные.ПланыОбмена.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""ПланыВидовХарактеристик"") Тогда Если Метаданные.ПланыВидовХарактеристик.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; ИначеЕсли ИмяВида = ВРег(""ПланыВидовРасчета"") Тогда Если Метаданные.ПланыВидовРасчета.Найти(ИмяОбъекта) <> Неопределено Тогда ОбъектНайден = Истина; КонецЕсли; КонецЕсли; КонецЕсли; Если Не ОбъектНайден Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Объект метаданных ""%1"" не существует.'""), Имя); КонецЕсли; // АПК:488-выкл ВычислитьВБезопасномРежиме не используется, чтобы избежать вызова ОбщийМодуль рекурсивно. УстановитьБезопасныйРежим(Истина); Модуль = Вычислить(Имя); // АПК:488-вкл Возврат Модуль; КонецФункции #КонецОбласти #Область Данные Функция СравниваемыеКолонки(Знач КоллекцияСтрок, Знач ИменаКолонок, Знач ИсключаяКолонки) Если ПустаяСтрока(ИменаКолонок) Тогда ТипКоллекции = ТипЗнч(КоллекцияСтрок); ЭтоСписокЗначений = (ТипКоллекции = Тип(""СписокЗначений"")); ЭтоТаблицаЗначений = (ТипКоллекции = Тип(""ТаблицаЗначений"")); ЭтоКоллекцияКлючИЗначение = (ТипКоллекции = Тип(""Соответствие"")) Или (ТипКоллекции = Тип(""Структура"")) Или (ТипКоллекции = Тип(""ФиксированноеСоответствие"")) Или (ТипКоллекции = Тип(""ФиксированнаяСтруктура"")); СравниваемыеКолонки = Новый Массив; Если ЭтоТаблицаЗначений Тогда Для Каждого Колонка Из КоллекцияСтрок.Колонки Цикл СравниваемыеКолонки.Добавить(Колонка.Имя); КонецЦикла; ИначеЕсли ЭтоСписокЗначений Тогда СравниваемыеКолонки.Добавить(""Значение""); СравниваемыеКолонки.Добавить(""Картинка""); СравниваемыеКолонки.Добавить(""Пометка""); СравниваемыеКолонки.Добавить(""Представление""); ИначеЕсли ЭтоКоллекцияКлючИЗначение Тогда СравниваемыеКолонки.Добавить(""Ключ""); СравниваемыеКолонки.Добавить(""Значение""); Иначе ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Для коллекции типа %1 укажите имена полей, по которым производится сравнение в %2.'""), ТипКоллекции, ""ОбщегоНазначения.КоллекцииИдентичны""); КонецЕсли; Иначе СравниваемыеКолонки = СтрРазделить(СтрЗаменить(ИменаКолонок, "" "", ""), "",""); КонецЕсли; // Вычитаем исключаемые поля Если Не ПустаяСтрока(ИсключаяКолонки) Тогда ИсключаяКолонки = СтрРазделить(СтрЗаменить(ИсключаяКолонки, "" "", ""), "",""); СравниваемыеКолонки = ОбщегоНазначенияКлиентСервер.РазностьМассивов(СравниваемыеКолонки, ИсключаяКолонки); КонецЕсли; Возврат СравниваемыеКолонки; КонецФункции Функция СравнитьСУчетомПоследовательности(Знач КоллекцияСтрок1, Знач КоллекцияСтрок2, Знач СравниваемыеКолонки) ТипКоллекции = ТипЗнч(КоллекцияСтрок1); СравниваютсяМассивы = (ТипКоллекции = Тип(""Массив"") Или ТипКоллекции = Тип(""ФиксированныйМассив"")); // Параллельный обход обеих коллекций. НомерСтрокиКоллекции1 = 0; Для Каждого СтрокаКоллекции1 Из КоллекцияСтрок1 Цикл // Спозиционируемся на аналогичную строку второй коллекции. НомерСтрокиКоллекции2 = 0; ЕстьСтрокиКоллекции2 = Ложь; Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл ЕстьСтрокиКоллекции2 = Истина; Если НомерСтрокиКоллекции2 = НомерСтрокиКоллекции1 Тогда Прервать; КонецЕсли; НомерСтрокиКоллекции2 = НомерСтрокиКоллекции2 + 1; КонецЦикла; Если Не ЕстьСтрокиКоллекции2 Тогда // Во второй коллекции вообще нет строк. Возврат Ложь; КонецЕсли; // Сравниваем значения полей двух строк. Если СравниваютсяМассивы Тогда Если СтрокаКоллекции1 <> СтрокаКоллекции2 Тогда Возврат Ложь; КонецЕсли; Иначе Для Каждого ИмяКолонки Из СравниваемыеКолонки Цикл Если СтрокаКоллекции1[ИмяКолонки] <> СтрокаКоллекции2[ИмяКолонки] Тогда Возврат Ложь; КонецЕсли; КонецЦикла; КонецЕсли; НомерСтрокиКоллекции1 = НомерСтрокиКоллекции1 + 1; КонецЦикла; КоличествоСтрокКоллекции1 = НомерСтрокиКоллекции1; // Отдельно подсчитаем количество строк второй коллекции. КоличествоСтрокКоллекции2 = 0; Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл КоличествоСтрокКоллекции2 = КоличествоСтрокКоллекции2 + 1; КонецЦикла; // Если в первой коллекции не оказалось строк, // то их не должно быть и во второй. Если КоличествоСтрокКоллекции1 = 0 Тогда Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл Возврат Ложь; КонецЦикла; КоличествоСтрокКоллекции2 = 0; КонецЕсли; // Количество строк не должно отличаться. Если КоличествоСтрокКоллекции1 <> КоличествоСтрокКоллекции2 Тогда Возврат Ложь; КонецЕсли; Возврат Истина; КонецФункции Функция СравнитьБезУчетаПоследовательности(Знач КоллекцияСтрок1, Знач КоллекцияСтрок2, Знач СравниваемыеКолонки) // Строки отбора накапливаем по первой коллекции для того, чтобы: // - повторно не искать одинаковые строки, // - убедиться, что во второй коллекции ни одной такой строки, которой нет в накопленных. СтрокиОтбора = Новый ТаблицаЗначений; ПараметрыОтбора = Новый Структура; Для Каждого ИмяКолонки Из СравниваемыеКолонки Цикл СтрокиОтбора.Колонки.Добавить(ИмяКолонки); ПараметрыОтбора.Вставить(ИмяКолонки); КонецЦикла; ЕстьСтрокиКоллекции1 = Ложь; Для Каждого СтрокаОтбора Из КоллекцияСтрок1 Цикл ЗаполнитьЗначенияСвойств(ПараметрыОтбора, СтрокаОтбора); Если СтрокиОтбора.НайтиСтроки(ПараметрыОтбора).Количество() > 0 Тогда // Строку с такими полями уже искали. Продолжить; КонецЕсли; ЗаполнитьЗначенияСвойств(СтрокиОтбора.Добавить(), СтрокаОтбора); // Подсчитаем количество таких строк в первой коллекции. НайденоСтрокКоллекции1 = 0; Для Каждого СтрокаКоллекции1 Из КоллекцияСтрок1 Цикл СтрокаПодходит = Истина; Для Каждого ИмяКолонки Из СравниваемыеКолонки Цикл Если СтрокаКоллекции1[ИмяКолонки] <> СтрокаОтбора[ИмяКолонки] Тогда СтрокаПодходит = Ложь; Прервать; КонецЕсли; КонецЦикла; Если СтрокаПодходит Тогда НайденоСтрокКоллекции1 = НайденоСтрокКоллекции1 + 1; КонецЕсли; КонецЦикла; // Подсчитаем количество таких строк во второй коллекции. НайденоСтрокКоллекции2 = 0; Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл СтрокаПодходит = Истина; Для Каждого ИмяКолонки Из СравниваемыеКолонки Цикл Если СтрокаКоллекции2[ИмяКолонки] <> СтрокаОтбора[ИмяКолонки] Тогда СтрокаПодходит = Ложь; Прервать; КонецЕсли; КонецЦикла; Если СтрокаПодходит Тогда НайденоСтрокКоллекции2 = НайденоСтрокКоллекции2 + 1; // Если количество таких строк во второй коллекции превысило количество в первой, // то уже можно сделать вывод, что коллекции не идентичны. Если НайденоСтрокКоллекции2 > НайденоСтрокКоллекции1 Тогда Возврат Ложь; КонецЕсли; КонецЕсли; КонецЦикла; // Количество таких строк не должно отличаться. Если НайденоСтрокКоллекции1 <> НайденоСтрокКоллекции2 Тогда Возврат Ложь; КонецЕсли; ЕстьСтрокиКоллекции1 = Истина; КонецЦикла; // Если в первой коллекции не оказалось строк, // то их не должно быть и во второй. Если Не ЕстьСтрокиКоллекции1 Тогда Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл Возврат Ложь; КонецЦикла; КонецЕсли; // Проверим, что во второй коллекции нет ни одной такой строки, которой нет в накопленных. Для Каждого СтрокаКоллекции2 Из КоллекцияСтрок2 Цикл ЗаполнитьЗначенияСвойств(ПараметрыОтбора, СтрокаКоллекции2); Если СтрокиОтбора.НайтиСтроки(ПараметрыОтбора).Количество() = 0 Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Возврат Истина; КонецФункции Функция СравнитьМассивы(Знач Массив1, Знач Массив2) Если Массив1.Количество() <> Массив2.Количество() Тогда Возврат Ложь; КонецЕсли; Для Каждого Элемент Из Массив1 Цикл Если Массив2.Найти(Элемент) = Неопределено Тогда Возврат Ложь; КонецЕсли; КонецЦикла; Возврат Истина; КонецФункции Процедура ПроверкаФиксированностиДанных(Данные, ДанныеВЗначенииФиксированныхТипов = Ложь) ТипДанных = ТипЗнч(Данные); СоставТипов = Новый ОписаниеТипов( ""ХранилищеЗначения, |ФиксированныйМассив, |ФиксированнаяСтруктура, |ФиксированноеСоответствие""); Если СоставТипов.СодержитТип(ТипДанных) Тогда Возврат; КонецЕсли; Если ДанныеВЗначенииФиксированныхТипов Тогда СоставТипов = Новый ОписаниеТипов( ""Булево,Строка,Число,Дата, |Неопределено,УникальныйИдентификатор,Null,Тип, |ХранилищеЗначения,ОбщийМодуль,ОбъектМетаданных, |ТипЗначенияXDTO,ТипОбъектаXDTO, |ИдентификаторОбсужденияСистемыВзаимодействия""); Если СоставТипов.СодержитТип(ТипДанных) Или ЭтоСсылка(ТипДанных) Тогда Возврат; КонецЕсли; КонецЕсли; ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Данные типа %1 не могут быть зафиксированы в функции %2.'""), Строка(ТипДанных), ""ОбщегоНазначения.ФиксированныеДанные""); КонецПроцедуры Функция РазмерСтрокиВБайтах(Знач Строка) Возврат ПолучитьДвоичныеДанныеИзСтроки(Строка, ""UTF-8"").Размер(); КонецФункции #Область СкопироватьРекурсивно Функция СкопироватьСтруктуру(СтруктураИсточник, ФиксироватьДанные) СтруктураРезультат = Новый Структура; Для Каждого КлючИЗначение Из СтруктураИсточник Цикл СтруктураРезультат.Вставить(КлючИЗначение.Ключ, СкопироватьРекурсивно(КлючИЗначение.Значение, ФиксироватьДанные)); КонецЦикла; Если ФиксироватьДанные = Истина Или ФиксироватьДанные = Неопределено И ТипЗнч(СтруктураИсточник) = Тип(""ФиксированнаяСтруктура"") Тогда Возврат Новый ФиксированнаяСтруктура(СтруктураРезультат); КонецЕсли; Возврат СтруктураРезультат; КонецФункции Функция СкопироватьСоответствие(СоответствиеИсточник, ФиксироватьДанные) СоответствиеРезультат = Новый Соответствие; Для Каждого КлючИЗначение Из СоответствиеИсточник Цикл СоответствиеРезультат.Вставить(КлючИЗначение.Ключ, СкопироватьРекурсивно(КлючИЗначение.Значение, ФиксироватьДанные)); КонецЦикла; Если ФиксироватьДанные = Истина Или ФиксироватьДанные = Неопределено И ТипЗнч(СоответствиеИсточник) = Тип(""ФиксированноеСоответствие"") Тогда Возврат Новый ФиксированноеСоответствие(СоответствиеРезультат); КонецЕсли; Возврат СоответствиеРезультат; КонецФункции Функция СкопироватьМассив(МассивИсточник, ФиксироватьДанные) МассивРезультат = Новый Массив; Для Каждого Элемент Из МассивИсточник Цикл МассивРезультат.Добавить(СкопироватьРекурсивно(Элемент, ФиксироватьДанные)); КонецЦикла; Если ФиксироватьДанные = Истина Или ФиксироватьДанные = Неопределено И ТипЗнч(МассивИсточник) = Тип(""ФиксированныйМассив"") Тогда Возврат Новый ФиксированныйМассив(МассивРезультат); КонецЕсли; Возврат МассивРезультат; КонецФункции Функция СкопироватьСписокЗначений(СписокИсточник, ФиксироватьДанные) СписокРезультат = Новый СписокЗначений; Для Каждого ЭлементСписка Из СписокИсточник Цикл СписокРезультат.Добавить( СкопироватьРекурсивно(ЭлементСписка.Значение, ФиксироватьДанные), ЭлементСписка.Представление, ЭлементСписка.Пометка, ЭлементСписка.Картинка); КонецЦикла; Возврат СписокРезультат; КонецФункции Процедура СкопироватьЗначенияТаблицыЗначений(ТаблицаЗначений, ФиксироватьДанные) Для Каждого СтрокаТаблицыЗначений Из ТаблицаЗначений Цикл Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл СтрокаТаблицыЗначений[Колонка.Имя] = СкопироватьРекурсивно(СтрокаТаблицыЗначений[Колонка.Имя], ФиксироватьДанные); КонецЦикла; КонецЦикла; КонецПроцедуры Процедура СкопироватьЗначенияСтрокиДереваЗначений(СтрокиДереваЗначений, ФиксироватьДанные); Для Каждого СтрокаДереваЗначений Из СтрокиДереваЗначений Цикл Для Каждого Колонка Из СтрокаДереваЗначений.Владелец().Колонки Цикл СтрокаДереваЗначений[Колонка.Имя] = СкопироватьРекурсивно(СтрокаДереваЗначений[Колонка.Имя], ФиксироватьДанные); КонецЦикла; СкопироватьЗначенияСтрокиДереваЗначений(СтрокаДереваЗначений.Строки, ФиксироватьДанные); КонецЦикла; КонецПроцедуры #КонецОбласти #КонецОбласти #Область Метаданные Процедура ПроверитьОбъектМетаданныхСуществует(ПолноеИмя) Если ОбъектМетаданныхПоПолномуИмени(ПолноеИмя) = Неопределено Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неизвестный тип объекта метаданных ""%1"".'""), ПолноеИмя); КонецЕсли; КонецПроцедуры #КонецОбласти #Область ХранилищеНастроек Процедура ХранилищеСохранить(МенеджерХранилища, КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения) Если Не ПравоДоступа(""СохранениеДанныхПользователя"", Метаданные) Тогда Возврат; КонецЕсли; МенеджерХранилища.Сохранить(КлючОбъекта, КлючНастроек(КлючНастроек), Настройки, ОписаниеНастроек, ИмяПользователя); Если ОбновитьПовторноИспользуемыеЗначения Тогда ОбновитьПовторноИспользуемыеЗначения(); КонецЕсли; КонецПроцедуры Функция ХранилищеЗагрузить(МенеджерХранилища, КлючОбъекта, КлючНастроек, ЗначениеПоУмолчанию, ОписаниеНастроек, ИмяПользователя) Результат = Неопределено; Если ПравоДоступа(""СохранениеДанныхПользователя"", Метаданные) Тогда Результат = МенеджерХранилища.Загрузить(КлючОбъекта, КлючНастроек(КлючНастроек), ОписаниеНастроек, ИмяПользователя); КонецЕсли; Если Результат = Неопределено Тогда Результат = ЗначениеПоУмолчанию; Иначе УстановитьПривилегированныйРежим(Истина); Если ОчиститьНесуществующиеСсылки(Результат) Тогда Результат = ЗначениеПоУмолчанию; КонецЕсли; КонецЕсли; Возврат Результат; КонецФункции // Удаляет из переданной коллекции ссылки, ссылающиеся на несуществующие данные в информационной базе. // Не очищает переданное значение, если в нем передана несуществующая ссылка, а возвращает Ложь. // // Параметры: // Значение - ЛюбаяСсылка // - Произвольный - проверяемое значение или коллекция. // // Возвращаемое значение: // Булево - Истина, если Значение ссылочного типа и объект не существует в информационной базе. // Ложь, если Значение не ссылочного типа или объект существует. // Функция ОчиститьНесуществующиеСсылки(Значение) Тип = ТипЗнч(Значение); Если Тип = Тип(""Неопределено"") Или Тип = Тип(""Булево"") Или Тип = Тип(""Строка"") Или Тип = Тип(""Число"") Или Тип = Тип(""Дата"") Тогда // Оптимизация - часто используемые примитивные типы. Возврат Ложь; // Не ссылка. ИначеЕсли Тип = Тип(""Массив"") Тогда Количество = Значение.Количество(); Для Номер = 1 По Количество Цикл ОбратныйИндекс = Количество - Номер; // @skip-check query-in-loop - выборка ссылок из разных таблиц. Если ОчиститьНесуществующиеСсылки(Значение[ОбратныйИндекс]) Тогда Значение.Удалить(ОбратныйИндекс); КонецЕсли; КонецЦикла; Возврат Ложь; // Не ссылка. ИначеЕсли Тип = Тип(""Структура"") Или Тип = Тип(""Соответствие"") Тогда Для Каждого КлючИЗначение Из Значение Цикл // @skip-check query-in-loop - выборка ссылок из разных таблиц. Если ОчиститьНесуществующиеСсылки(КлючИЗначение.Значение) Тогда Значение.Вставить(КлючИЗначение.Ключ, Неопределено); КонецЕсли; КонецЦикла; Возврат Ложь; // Не ссылка. ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(Тип) Или Справочники.ТипВсеСсылки().СодержитТип(Тип) Или Перечисления.ТипВсеСсылки().СодержитТип(Тип) Или ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип) Или ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип) Или ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип) Или ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип) Или БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип) Или Задачи.ТипВсеСсылки().СодержитТип(Тип) Тогда // Ссылочный тип, исключая ТочкаМаршрутаБизнесПроцессаСсылка. Если Значение.Пустая() Тогда Возврат Ложь; // Ссылка пустая. КонецЕсли; Возврат ЗначениеРеквизитаОбъекта(Значение, ""Ссылка"") = Неопределено; Иначе Возврат Ложь; // Не ссылка. КонецЕсли; КонецФункции Процедура ХранилищеУдалить(МенеджерХранилища, КлючОбъекта, КлючНастроек, ИмяПользователя) Если ПравоДоступа(""СохранениеДанныхПользователя"", Метаданные) Тогда МенеджерХранилища.Удалить(КлючОбъекта, КлючНастроек(КлючНастроек), ИмяПользователя); КонецЕсли; КонецПроцедуры // Возвращает строку ключа настроек, не превышающую допустимую длину 128 символов. // Если указанная строка превышает 128, тогда вместо символов сверх 96 символов // добавляется их хеш-сумма по алгоритму MD5 размером 32 символа. // // Параметры: // Строка - Строка - строка произвольной длины. // // Возвращаемое значение: // Строка - не более 128 символов. // Функция КлючНастроек(Знач Строка) Возврат СократитьСтрокуКонтрольнойСуммой(Строка, 128); КонецФункции #КонецОбласти #Область БезопасноеХранилище Функция ДанныеИзБезопасногоХранилища(Владельцы, Ключи, ОбщиеДанные) ИмяБезопасногоХранилищаДанных = ""РегистрСведений.БезопасноеХранилищеДанных""; Если РазделениеВключено() И ДоступноИспользованиеРазделенныхДанных() И ОбщиеДанные <> Истина Тогда ИмяБезопасногоХранилищаДанных = ""РегистрСведений.БезопасноеХранилищеДанныхОбластейДанных""; КонецЕсли; ТекстЗапроса = ""ВЫБРАТЬ | БезопасноеХранилищеДанных.Владелец КАК ВладелецДанных, | БезопасноеХранилищеДанных.Данные КАК Данные |ИЗ | #ИмяБезопасногоХранилищаДанных КАК БезопасноеХранилищеДанных |ГДЕ | БезопасноеХранилищеДанных.Владелец В (&Владельцы)""; ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ""#ИмяБезопасногоХранилищаДанных"", ИмяБезопасногоХранилищаДанных); Запрос = Новый Запрос(ТекстЗапроса); Запрос.УстановитьПараметр(""Владельцы"", Владельцы); РезультатЗапроса = Запрос.Выполнить().Выбрать(); Результат = Новый Соответствие(); НаборДанныхКлюча = ?(ЗначениеЗаполнено(Ключи) И СтрНайти(Ключи, "",""), Новый Структура(Ключи), Неопределено); Для Каждого ВладелецДанных Из Владельцы Цикл Результат.Вставить(ВладелецДанных, НаборДанныхКлюча); КонецЦикла; Пока РезультатЗапроса.Следующий() Цикл ДанныеВладельца = Новый Структура(Ключи); Если ЗначениеЗаполнено(РезультатЗапроса.Данные) Тогда СохраненныеДанные = РезультатЗапроса.Данные.Получить(); Если ЗначениеЗаполнено(СохраненныеДанные) Тогда Если ЗначениеЗаполнено(Ключи) Тогда ВладелецДанных = Результат[РезультатЗапроса.ВладелецДанных]; ЗаполнитьЗначенияСвойств(ДанныеВладельца, СохраненныеДанные); Иначе ДанныеВладельца = СохраненныеДанные; КонецЕсли; Если Ключи <> Неопределено И ДанныеВладельца <> Неопределено И ДанныеВладельца.Количество() = 1 Тогда ЗначениеПоКлючу = ?(ДанныеВладельца.Свойство(Ключи), ДанныеВладельца[Ключи], Неопределено); Результат.Вставить(РезультатЗапроса.ВладелецДанных, ЗначениеПоКлючу); Иначе Результат.Вставить(РезультатЗапроса.ВладелецДанных, ДанныеВладельца); КонецЕсли; КонецЕсли; КонецЕсли; КонецЦикла; Возврат Результат; КонецФункции #КонецОбласти #Область БезопасноеВыполнениеВнешнегоКода // Проверяет, что переданное имя ИмяПроцедуры является именем экспортной процедуры конфигурации. // Может использоваться для проверки, что переданная строка не содержит произвольного алгоритма // на встроенном языке 1С:Предприятия перед использованием его в операторах Выполнить и Вычислить // при их использовании для динамического вызова методов код конфигурации. // // В случае если переданная строка не является именем процедуры конфигурации, генерируется исключение. // // Предназначена для вызова из см. процедуру ВыполнитьМетодКонфигурации. // // Параметры: // ИмяПроцедуры - Строка - проверяемое имя экспортной процедуры. // Процедура ПроверитьИмяПроцедурыКонфигурации(Знач ИмяПроцедуры) ЧастиИмени = СтрРазделить(ИмяПроцедуры, "".""); Если ЧастиИмени.Количество() <> 2 И ЧастиИмени.Количество() <> 3 Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неправильный формат параметра %1 (передано значение: ""%2"") в %3.'""), ""ИмяПроцедуры"", ИмяПроцедуры, ""ОбщегоНазначения.ВыполнитьМетодКонфигурации""); КонецЕсли; ИмяОбъекта = ЧастиИмени[0]; Если ЧастиИмени.Количество() = 2 И Метаданные.ОбщиеМодули.Найти(ИмяОбъекта) = Неопределено Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неправильный формат параметра %1 (передано значение: ""%2"") в %3: |Не существует общий модуль ""%4"".'""), ""ИмяПроцедуры"", ИмяПроцедуры, ""ОбщегоНазначения.ВыполнитьМетодКонфигурации"", ИмяОбъекта); КонецЕсли; Если ЧастиИмени.Количество() = 3 Тогда ПолноеИмяОбъекта = ЧастиИмени[0] + ""."" + ЧастиИмени[1]; Попытка Менеджер = МенеджерОбъектаПоИмени(ПолноеИмяОбъекта); Исключение Менеджер = Неопределено; КонецПопытки; Если Менеджер = Неопределено Тогда ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неправильный формат параметра %1 (передано значение: ""%2"") в %3: |Не существует менеджер объекта ""%4"".'""), ""ИмяПроцедуры"", ИмяПроцедуры, ""ОбщегоНазначения.ВыполнитьМетодКонфигурации"", ПолноеИмяОбъекта); КонецЕсли; КонецЕсли; ИмяМетодаОбъекта = ЧастиИмени[ЧастиИмени.ВГраница()]; ВременнаяСтруктура = Новый Структура; Попытка // Проверка того, что ИмяПроцедуры является допустимым идентификатором. // Например: МояПроцедура. ВременнаяСтруктура.Вставить(ИмяМетодаОбъекта); Исключение ЗаписьЖурналаРегистрации(НСтр(""ru = 'Безопасное выполнение метода'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Неправильный формат параметра %1 (передано значение: ""%2"") в %3: |Имя метода ""%4"" не соответствует требованиям образования имен процедур и функций.'""), ""ИмяПроцедуры"", ИмяПроцедуры, ""ОбщегоНазначения.ВыполнитьМетодКонфигурации"", ИмяМетодаОбъекта); КонецПопытки; КонецПроцедуры // Возвращает менеджер объекта по имени. // Ограничение: не обрабатываются точки маршрутов бизнес-процессов. // // Параметры: // Имя - Строка - имя например, ""Справочник"", ""Справочники"", ""Справочник.Организации"". // // Возвращаемое значение: // СправочникиМенеджер // СправочникМенеджер // ДокументыМенеджер // ДокументМенеджер // ... // Функция МенеджерОбъектаПоИмени(Имя) Перем КлассОМ, ИмяОМ, Менеджер; ЧастиИмени = СтрРазделить(Имя, "".""); Если ЧастиИмени.Количество() > 0 Тогда КлассОМ = ВРег(ЧастиИмени[0]); КонецЕсли; Если ЧастиИмени.Количество() > 1 Тогда ИмяОМ = ЧастиИмени[1]; КонецЕсли; Если КлассОМ = ""ПЛАНОБМЕНА"" Или КлассОМ = ""ПЛАНЫОБМЕНА"" Тогда Менеджер = ПланыОбмена; ИначеЕсли КлассОМ = ""СПРАВОЧНИК"" Или КлассОМ = ""СПРАВОЧНИКИ"" Тогда Менеджер = Справочники; ИначеЕсли КлассОМ = ""ДОКУМЕНТ"" Или КлассОМ = ""ДОКУМЕНТЫ"" Тогда Менеджер = Документы; ИначеЕсли КлассОМ = ""ЖУРНАЛДОКУМЕНТОВ"" Или КлассОМ = ""ЖУРНАЛЫДОКУМЕНТОВ"" Тогда Менеджер = ЖурналыДокументов; ИначеЕсли КлассОМ = ""ПЕРЕЧИСЛЕНИЕ"" Или КлассОМ = ""ПЕРЕЧИСЛЕНИЯ"" Тогда Менеджер = Перечисления; ИначеЕсли КлассОМ = ""ОБЩИЙМОДУЛЬ"" Или КлассОМ = ""ОБЩИЕМОДУЛИ"" Тогда Возврат ОбщийМодуль(ИмяОМ); ИначеЕсли КлассОМ = ""ОТЧЕТ"" Или КлассОМ = ""ОТЧЕТЫ"" Тогда Менеджер = Отчеты; ИначеЕсли КлассОМ = ""ОБРАБОТКА"" Или КлассОМ = ""ОБРАБОТКИ"" Тогда Менеджер = Обработки; ИначеЕсли КлассОМ = ""ПЛАНВИДОВХАРАКТЕРИСТИК"" Или КлассОМ = ""ПЛАНЫВИДОВХАРАКТЕРИСТИК"" Тогда Менеджер = ПланыВидовХарактеристик; ИначеЕсли КлассОМ = ""ПЛАНСЧЕТОВ"" Или КлассОМ = ""ПЛАНЫСЧЕТОВ"" Тогда Менеджер = ПланыСчетов; ИначеЕсли КлассОМ = ""ПЛАНВИДОВРАСЧЕТА"" Или КлассОМ = ""ПЛАНЫВИДОВРАСЧЕТА"" Тогда Менеджер = ПланыВидовРасчета; ИначеЕсли КлассОМ = ""РЕГИСТРСВЕДЕНИЙ"" Или КлассОМ = ""РЕГИСТРЫСВЕДЕНИЙ"" Тогда Менеджер = РегистрыСведений; ИначеЕсли КлассОМ = ""РЕГИСТРНАКОПЛЕНИЯ"" Или КлассОМ = ""РЕГИСТРЫНАКОПЛЕНИЯ"" Тогда Менеджер = РегистрыНакопления; ИначеЕсли КлассОМ = ""РЕГИСТРБУХГАЛТЕРИИ"" Или КлассОМ = ""РЕГИСТРЫБУХГАЛТЕРИИ"" Тогда Менеджер = РегистрыБухгалтерии; ИначеЕсли КлассОМ = ""РЕГИСТРРАСЧЕТА"" Или КлассОМ = ""РЕГИСТРЫРАСЧЕТА"" Тогда Если ЧастиИмени.Количество() < 3 Тогда // Регистр расчета Менеджер = РегистрыРасчета; Иначе КлассПодчиненногоОМ = ВРег(ЧастиИмени[2]); Если ЧастиИмени.Количество() > 3 Тогда ИмяПодчиненногоОМ = ЧастиИмени[3]; КонецЕсли; Если КлассПодчиненногоОМ = ""ПЕРЕРАСЧЕТ"" Или КлассПодчиненногоОМ = ""ПЕРЕРАСЧЕТЫ"" Тогда // Перерасчет Попытка Менеджер = РегистрыРасчета[ИмяОМ].Перерасчеты; ИмяОМ = ИмяПодчиненногоОМ; Исключение Менеджер = Неопределено; КонецПопытки; КонецЕсли; КонецЕсли; ИначеЕсли КлассОМ = ""БИЗНЕСПРОЦЕСС"" Или КлассОМ = ""БИЗНЕСПРОЦЕССЫ"" Тогда Менеджер = БизнесПроцессы; ИначеЕсли КлассОМ = ""ЗАДАЧА"" Или КлассОМ = ""ЗАДАЧИ"" Тогда Менеджер = Задачи; ИначеЕсли КлассОМ = ""КОНСТАНТА"" Или КлассОМ = ""КОНСТАНТЫ"" Тогда Менеджер = Константы; ИначеЕсли КлассОМ = ""ПОСЛЕДОВАТЕЛЬНОСТЬ"" Или КлассОМ = ""ПОСЛЕДОВАТЕЛЬНОСТИ"" Тогда Менеджер = Последовательности; КонецЕсли; Если Менеджер <> Неопределено Тогда Если ЗначениеЗаполнено(ИмяОМ) Тогда Попытка Возврат Менеджер[ИмяОМ]; Исключение Менеджер = Неопределено; КонецПопытки; Иначе Возврат Менеджер; КонецЕсли; КонецЕсли; ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр(""ru = 'Не удалось получить менеджер для объекта ""%1""'""), Имя); КонецФункции // Вызвать экспортную функцию по имени с уровнем привилегий конфигурации. // При включении профилей безопасности для вызова оператора Выполнить() используется // переход в безопасный режим с профилем безопасности, используемом для информационной базы // (если выше по стеку не был установлен другой безопасный режим). // // Параметры: // ИмяМетода - Строка - имя экспортной функции в формате // <имя объекта>.<имя процедуры>, где <имя объекта> - это // общий модуль или модуль менеджера объекта. // Параметры - Массив - параметры передаются в функцию <ИмяМетода> // в порядке расположения элементов массива. // // Возвращаемое значение: // Произвольный - результат вызываемой функции. // Функция ВызватьФункциюКонфигурации(Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт ПроверитьИмяПроцедурыКонфигурации(ИмяМетода); Если ПодсистемаСуществует(""СтандартныеПодсистемы.ПрофилиБезопасности"") Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности() И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы(); Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда УстановитьБезопасныйРежим(ПрофильИнформационнойБазы); Если БезопасныйРежим() = Истина Тогда УстановитьБезопасныйРежим(Ложь); КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; ПараметрыСтрока = ""; Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда Для Индекс = 0 По Параметры.ВГраница() Цикл ПараметрыСтрока = ПараметрыСтрока + ""Параметры["" + XMLСтрока(Индекс) + ""],""; КонецЦикла; ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1); КонецЕсли; Возврат Вычислить(ИмяМетода + ""("" + ПараметрыСтрока + "")""); // АПК:488 Исполняемый код безопасен. КонецФункции // Вызвать экспортную функцию объекта встроенного языка по имени. // При включении профилей безопасности для вызова оператора Выполнить() используется // переход в безопасный режим с профилем безопасности, используемом для информационной базы // (если выше по стеку не был установлен другой безопасный режим). // // Параметры: // Объект - Произвольный - объект встроенного языка 1С:Предприятия, содержащий методы (например, ОбработкаОбъект). // ИмяМетода - Строка - имя экспортной функции модуля объекта обработки. // Параметры - Массив - параметры передаются в функцию <ИмяМетода> // в порядке расположения элементов массива. // // Возвращаемое значение: // Произвольный - результат вызываемой функции. // Функция ВызватьФункциюОбъекта(Знач Объект, Знач ИмяМетода, Знач Параметры = Неопределено) Экспорт // Проверка имени метода на корректность. Попытка Тест = Новый Структура; Тест.Вставить(ИмяМетода, ИмяМетода); Исключение ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Некорректное значение параметра %1 (%2) в %3.'""), ""ИмяМетода"", ИмяМетода, ""ОбщегоНазначения.ВыполнитьМетодОбъекта""); КонецПопытки; Если ПодсистемаСуществует(""СтандартныеПодсистемы.ПрофилиБезопасности"") Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); Если МодульРаботаВБезопасномРежиме.ИспользуютсяПрофилиБезопасности() И Не МодульРаботаВБезопасномРежиме.УстановленБезопасныйРежим() Тогда МодульРаботаВБезопасномРежиме = ОбщийМодуль(""РаботаВБезопасномРежиме""); ПрофильИнформационнойБазы = МодульРаботаВБезопасномРежиме.ПрофильБезопасностиИнформационнойБазы(); Если ЗначениеЗаполнено(ПрофильИнформационнойБазы) Тогда УстановитьБезопасныйРежим(ПрофильИнформационнойБазы); Если БезопасныйРежим() = Истина Тогда УстановитьБезопасныйРежим(Ложь); КонецЕсли; КонецЕсли; КонецЕсли; КонецЕсли; ПараметрыСтрока = ""; Если Параметры <> Неопределено И Параметры.Количество() > 0 Тогда Для Индекс = 0 По Параметры.ВГраница() Цикл ПараметрыСтрока = ПараметрыСтрока + ""Параметры["" + XMLСтрока(Индекс) + ""],""; КонецЦикла; ПараметрыСтрока = Сред(ПараметрыСтрока, 1, СтрДлина(ПараметрыСтрока) - 1); КонецЕсли; Возврат Вычислить(""Объект."" + ИмяМетода + ""("" + ПараметрыСтрока + "")""); // АПК:488 Исполняемый код безопасен. КонецФункции #КонецОбласти #Область ВнешниеКомпоненты Процедура ПроверитьМестоположениеКомпоненты(Идентификатор, Местоположение) Если МакетСуществует(Местоположение) Тогда Возврат; КонецЕсли; Если ПодсистемаСуществует(""СтандартныеПодсистемы.ВнешниеКомпоненты"") Тогда МодульВнешниеКомпонентыСлужебный = ОбщийМодуль(""ВнешниеКомпонентыСлужебный""); МодульВнешниеКомпонентыСлужебный.ПроверитьМестоположениеКомпоненты(Идентификатор, Местоположение); Иначе ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Указан несуществующий макет ""%1"" при подключении внешней компоненты ""%2"".'""), Местоположение, Идентификатор); КонецЕсли; КонецПроцедуры Функция МакетСуществует(ПолноеИмяМакета) Макет = Метаданные.НайтиПоПолномуИмени(ПолноеИмяМакета); Если ТипЗнч(Макет) = Тип(""ОбъектМетаданных"") Тогда Шаблон = Новый Структура(""ТипМакета""); ЗаполнитьЗначенияСвойств(Шаблон, Макет); ТипМакета = Неопределено; Если Шаблон.Свойство(""ТипМакета"", ТипМакета) Тогда Возврат ТипМакета <> Неопределено; КонецЕсли; КонецЕсли; Возврат Ложь; КонецФункции #КонецОбласти #Область ТекущееОкружение Функция НомерСборкиПоТекущейВерсииПлатформы(НомераСборокСтрокой) НомераСборок = СтрРазделить(НомераСборокСтрокой, "";"", Истина); СборкиПоВерсиям = Новый Соответствие; Для Каждого НомерСборки Из НомераСборок Цикл НомерВерсии = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(НомерСборки); СборкиПоВерсиям.Вставить(СокрЛП(НомерВерсии), СокрЛП(НомерСборки)); КонецЦикла; СистемнаяИнформация = Новый СистемнаяИнформация; ТекущаяВерсия = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(СистемнаяИнформация.ВерсияПриложения); Результат = СборкиПоВерсиям[ТекущаяВерсия]; Если Не ЗначениеЗаполнено(Результат) Тогда Результат = НомераСборок[0]; КонецЕсли; Возврат Результат; КонецФункции // Ниже этой версии БСП может запуститься и показать окно с рекомендациями, если она выше чем в МинимальнаяВерсияПлатформыДляЗапуска. Функция МинимальнаяВерсияПлатформы() Экспорт // АПК:581 - экспортная, так как используется при тестировании. ВерсияРежимаСовместимости = ВерсияРежимаСовместимости(); ПоддерживаемыеВерсииПлатформы = ПоддерживаемыеВерсииПлатформы(); НайденнаяВерсия = ПоддерживаемыеВерсииПлатформы.НайтиПоЗначению(ВерсияРежимаСовместимости); Если НайденнаяВерсия = Неопределено Тогда НайденнаяВерсия = ПоддерживаемыеВерсииПлатформы[ПоддерживаемыеВерсииПлатформы.Количество() - 1]; КонецЕсли; НомераСборок = НайденнаяВерсия.Представление; Возврат НомераСборок; КонецФункции // Ниже этой версии БСП не может запуститься и показать окно с рекомендациями. Функция МинимальнаяВерсияПлатформыДляЗапуска() Экспорт Возврат ""8.3.21.1622; 8.3.22.1704""; КонецФункции // Возвращаемое значение: // СписокЗначений: // * Значение - Строка - поддерживаемый номер версии (режим совместимости); // * Представление - Строка - минимальные номера сборок платформы, разделитель - точка с запятой. // Функция ПоддерживаемыеВерсииПлатформы() Экспорт ПоддерживаемыеВерсииПлатформы = Новый СписокЗначений; ПоддерживаемыеВерсииПлатформы.Добавить(""8.3.21"", ""8.3.21.1775; 8.3.22.1923""); ПоддерживаемыеВерсииПлатформы.Добавить(""8.3.22"", ""8.3.22.2355; 8.3.23.2011; 8.3.24.1304""); ПоддерживаемыеВерсииПлатформы.Добавить(""8.3.23"", ""8.3.23.2011; 8.3.24.1304""); ПоддерживаемыеВерсииПлатформы.Добавить(""8.3.24"", ""8.3.24.1304""); Возврат ПоддерживаемыеВерсииПлатформы; КонецФункции Функция ВерсияРежимаСовместимости() Экспорт СистемнаяИнформация = Новый СистемнаяИнформация(); РежимСовместимости = Метаданные.РежимСовместимости; Если РежимСовместимости = Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Тогда ВерсияРежимаСовместимости = ОбщегоНазначенияКлиентСервер.ВерсияКонфигурацииБезНомераСборки(СистемнаяИнформация.ВерсияПриложения); Иначе ВерсияРежимаСовместимости = СтрСоединить(СтрРазделить(РежимСовместимости, СтрСоединить(СтрРазделить(РежимСовместимости, ""1234567890"", Ложь), ""), Ложь), "".""); КонецЕсли; Возврат ВерсияРежимаСовместимости; КонецФункции // Выполняет проверку правильности заполнения минимальной и рекомендуемой версии платформы. // // Параметры: // Минимальная - Строка - номер версия платформы. // Рекомендуемая - Строка - номер версия платформы. // // Возвращаемое значение: // Булево - Истина, если минимальная и рекомендуемая версия платформы заполнена неправильно. // Функция МинимальнаяИРекомендуемаяВерсияПлатформыЗаполненаНеПравильно(Минимальная, Рекомендуемая) // Минимальная версия платформы должна быть заполнена. Если ПустаяСтрока(Минимальная) Тогда Возврат Истина; КонецЕсли; // Минимальная версия платформы, заданная в конфигурации, не должна быть меньше минимальной версии платформы, // заданной в библиотеке. МинимальнаяБСП = НомерСборкиПоТекущейВерсииПлатформы(МинимальнаяВерсияПлатформы()); Если Не ЭтоВерсияЗащищенногоПрограммногоКомплекса(Минимальная) И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(МинимальнаяБСП, Минимальная) > 0 Тогда Возврат Истина; КонецЕсли; // Минимальная версия платформы не должны быть больше рекомендуемой. Возврат Не ПустаяСтрока(Минимальная) И Не ПустаяСтрока(Рекомендуемая) И ОбщегоНазначенияКлиентСервер.СравнитьВерсии(Минимальная, Рекомендуемая) > 0; КонецФункции Функция НедопустимыеВерсииПлатформы() Экспорт Возврат ""; КонецФункции Функция ЭтоВерсияЗащищенногоПрограммногоКомплекса(Версия) Версии = Новый Массив; Версии.Добавить(""8.3.21.1676""); Версии.Добавить(""8.3.21.1901""); Возврат Версии.Найти(Версия) <> Неопределено; КонецФункции // Для функции ОбщиеПараметрыБазовойФункциональности. Процедура УточнитьВерсиюПлатформы(ОбщиеПараметры) СистемнаяИнформация = Новый СистемнаяИнформация; НоваяСборка = НоваяСборка(СистемнаяИнформация.ВерсияПриложения); Если Не ЗначениеЗаполнено(НоваяСборка) Тогда НоваяРекомендуемаяСборка = НоваяСборка(ОбщиеПараметры.МинимальнаяВерсияПлатформы); Если ЗначениеЗаполнено(НоваяРекомендуемаяСборка) Тогда МинимальнаяСборка = НомерСборкиПоТекущейВерсииПлатформы(МинимальнаяВерсияПлатформы()); ОбщиеПараметры.МинимальнаяВерсияПлатформы = МинимальнаяСборка; ОбщиеПараметры.МинимальноНеобходимаяВерсияПлатформы = МинимальнаяСборка; Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ОбщиеПараметры.РекомендуемаяВерсияПлатформы, НоваяРекомендуемаяСборка) < 0 Тогда ОбщиеПараметры.РекомендуемаяВерсияПлатформы = НоваяРекомендуемаяСборка; КонецЕсли; КонецЕсли; ИначеЕсли ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ОбщиеПараметры.МинимальнаяВерсияПлатформы, НоваяСборка) < 0 Тогда ОбщиеПараметры.РекомендуемаяВерсияПлатформы = НоваяСборка; ОбщиеПараметры.МинимальнаяВерсияПлатформы = НоваяСборка; ОбщиеПараметры.МинимальноНеобходимаяВерсияПлатформы = НоваяСборка; ОбщиеПараметры.РаботаВПрограммеЗапрещена = Истина; КонецЕсли; КонецПроцедуры // Для процедуры УточнитьВерсиюПлатформы. Функция НоваяСборка(ТекущаяСборка) Если СтрНайти(""8.3.22.1672,8.3.22.1603"", ТекущаяСборка) Тогда Возврат ""8.3.22.1709""; ИначеЕсли СтрНайти(""8.3.21.1607,8.3.21.1508,8.3.21.1484"", ТекущаяСборка) Тогда Возврат ""8.3.21.1624""; КонецЕсли; Возврат ""; КонецФункции // Локализация // Параметры: // ОбщиеПараметры - см. ОбщиеПараметрыБазовойФункциональности // Процедура УточнитьМинимальнуюВерсиюПлатформыИзСервиса(ОбщиеПараметры) Если Не ПодсистемаСуществует(""ИнтернетПоддержкаПользователей.ПолучениеОбновленийПрограммы"") Тогда Возврат; КонецЕсли; // Проверка версии БИП начиная с которой появился программный интерфейс МодульИнтернетПоддержкаПользователейКлиентСервер = ОбщийМодуль(""ИнтернетПоддержкаПользователейКлиентСервер""); ВерсияБИП = МодульИнтернетПоддержкаПользователейКлиентСервер.ВерсияБиблиотеки(); Если ОбщегоНазначенияКлиентСервер.СравнитьВерсии(ВерсияБИП, ""2.7.1.35"") <= 0 Тогда Возврат; КонецЕсли; Попытка МодульПолучениеОбновленийПрограммы = ОбщийМодуль(""ПолучениеОбновленийПрограммы""); ИнформацияОВерсияхПлатформы = МодульПолучениеОбновленийПрограммы.ИнформацияОВерсияхПлатформы(); // Контроль заполнения версий платформы по данным сервиса Если ПустаяСтрока(ИнформацияОВерсияхПлатформы.МинимальнаяВерсияПлатформы) И ПустаяСтрока(ИнформацияОВерсияхПлатформы.РекомендуемаяВерсияПлатформы) Тогда Возврат; КонецЕсли; Минимальная = НомерСборкиПоТекущейВерсииПлатформы(ИнформацияОВерсияхПлатформы.МинимальнаяВерсияПлатформы); Рекомендуемая = НомерСборкиПоТекущейВерсииПлатформы(ИнформацияОВерсияхПлатформы.РекомендуемаяВерсияПлатформы); Если МинимальнаяИРекомендуемаяВерсияПлатформыЗаполненаНеПравильно(Минимальная, Рекомендуемая) Тогда МодульПолучениеОбновленийПрограммы.УдалитьИнформациюОВерсияхПлатформы(); ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Минимальная и рекомендуемая версии платформы ""1С:Предприятие"", полученные с сервиса обновления программ, не соответствуют следующим требованиям: | - минимальная версия должна быть заполнена; | - минимальная версия не должна быть меньше минимальной версии БСП (см. %1); | - минимальная версия не должна быть меньше рекомендуемой версии. |Минимальная версия сервиса обновления программ: %2 |Минимальная версия БСП: %3 |Рекомендуемая версия сервиса обновления программ: %4 | |Минимальная и рекомендуемая версия платформы ""1С:Предприятие"" установлена по данным см. %5. |Минимальная версия: %6 |Рекомендуемая версия: %7'"", КодОсновногоЯзыка()), ""ОбщегоНазначения.МинимальнаяВерсияПлатформы"", Минимальная, НомерСборкиПоТекущейВерсииПлатформы(МинимальнаяВерсияПлатформы()), Рекомендуемая, ""ОбщегоНазначенияПереопределяемый.ПриОпределенииОбщихПараметровБазовойФункциональности"", ОбщиеПараметры.МинимальнаяВерсияПлатформы, ОбщиеПараметры.РекомендуемаяВерсияПлатформы); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Базовая функциональность'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Предупреждение,,, ТекстСообщения); Возврат; КонецЕсли; ОбщиеПараметры.МинимальнаяВерсияПлатформы = Минимальная; ОбщиеПараметры.РекомендуемаяВерсияПлатформы = Рекомендуемая; Исключение ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку( НСтр(""ru = 'Не удалось изменить минимальную и рекомендуемую версию платформы ""1С:Предприятие"", полученную с сервиса обновления программ, по причине: |%1'"", КодОсновногоЯзыка()), ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ЗаписьЖурналаРегистрации(НСтр(""ru = 'Базовая функциональность'"", КодОсновногоЯзыка()), УровеньЖурналаРегистрации.Предупреждение,,, ТекстСообщения); КонецПопытки; КонецПроцедуры // Конец Локализация #КонецОбласти #КонецОбласти #КонецЕсли "; RegexOptions options = RegexOptions.Multiline | RegexOptions.IgnoreCase; foreach (Match m in Regex.Matches(input, pattern, options)) { Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index); } } }

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for C#, please visit: https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex(v=vs.110).aspx