RDT1C/DataProcessors/ирПоискДублейИЗаменаСсылок/Ext/ObjectModule.bsl
Администратор ebf21867b6 Редактор пользователей
+В списке добавлена группа колонок свойств настроек управляемого приложения
        +Добавлена кнопка "Установить..." для установки настроек управляемого приложения выделенным пользователям
        +В форме запуска под пользователем добавлен флажок "Режим интерфейса "Такси""
        +Запуск под пользователем с флагом "Разрешить отладку" теперь сразу подключает текущий отладчик к запускаемому сеансу
    Общее
        +Команда "Запустить обычное приложение" теперь в обоих типах управляемого приложения открывает одинаковую форму, в которой добавлен включенный по умолчанию флажок "Текущий пользователь"
        +Команда "Запустить связанный тонкий клиент" теперь передает имя текущего пользователя в строке соединения
        +При включенной параметром запуска /EnableCheckModal проверке модальности теперь при первом в сеансе открытии любой формы подсистемы предлагается запуск нового сеанса без проверки модальности
    Интерфейсная панель.
        +В контекстном меню добавлена команда "Связанный динамический список", открывающая единое окно динамического списка, обновляющее список при активизации строки
    Динамический список
        +Добавлена кнопка "Связанный редактор объекта БД", открывающая прикрепленное окно редактора объекта БД, загружающее объект при активизации строки
        +Реализовано автоматическое обновление отображаемых строк при записи объекта в редакторе объекта БД
        *Реализован обход ошибки платформы установки табличному полю типа списка независимого непериодического регистра сведений без измерений
    Редактор объекта БД
        *Увеличена длина дробной части значений отбора набора записей
    Контекстная подсказка
        *Исправлена ошибка инициализации формы списка слов при отсутствии activex компоненты Forms20
    Консоль запросов
        *Кнопка "Найти в дереве запроса" теперь доступна только в режиме просмотра узла дерева запроса
        *При сохранении узла дерева запроса, текущий узел теперь ищется не по именам, а по индексам узлов
        *Исправлено зависание программы при копировании папки дерева запросов
        *Исправлено некорректное определение имени узла дерева запроса в некоторых случаях при наличии функции ЗНАЧЕНИЕ(...)
        *При выборе основного элемента результата пакетного запроса теперь игнорируются результаты уничтожения таблиц
    Редактор табличного документа
        +Добавлена кнопка "Сохранить"

3.70
    Консоль компоновки данных
        +В настройках компоновки в таблице условного оформления добавлен пример оформления текста в колонке "Пример"
    Консоль кода
        +Добавлено дерево алгоритмов
        +Изменен формат файлов на t1c, старый формат f1c доступен только для открытия файлов
        *После сохранения в файл теперь сбрасывается модифицированность формы
        +Добавлена кнопка объединения с файлом
        +Добавлено подменю последних открытых файлов
        +Для булевых параметров реализовано отображение флажка
    Консоль запросов
        +При генерации текста модуля пакетного запроса теперь добавляется установка переменных вида "Индекс_<ИмяЗапроса>=<Индекс>" для всех именованных запросов
        +Команде "Найти в дереве" назначено сочетание клавиш CTRL+T
        +Для булевых параметров реализовано отображение флажка
        *Исправлено некорректное отображение количества строк в дереве результата при наличии выборок итогов
    Общее
        *Исправлены ошибки работы подсистемы при наличии общего модуля с именем ОбменДанными
        *Кнопка "Установить одинаковую ширину для всех колонок" заменена на "Расширить все колонки на 5 символов"
    Синтакс-помощник
        *Исправлено построение дерева, сломавшееся несколько версий назад
    Управление службами серверов 1С
        *Исправлена ошибка чтения служб при наличии службы сервера 1С без ключа "range" в строке запуска
    Редактор объекта БД
        +Для наборов записей добавлена фиксированная колонка картинки вида движения регистра накопления
        +По умолчанию для списка движений теперь включен отбор "Только не пустые"
        +Кнопка открытия редактора для таблицы движений теперь передает текущую строку
    Подбор и обработка объектов
        +Реализована поддержка журналов документов в однотабличном режиме
    Динамический список
        +В режиме выбора в заголовке теперь добавляется "(выбор)"
    Интерфейсная панель
        +Теперь уважает настройку использования "Динамический список / Основная форма списка"

3.69
    Общее
        +Вместо форм выбора теперь по умолчанию всегда открывается динамический список
        -Кнопка "Редактировать список" для значения отбор компоновки везде удалена, теперь редактирование списка всегда выполняется в расширенном режиме
    Динамический список
        +Добавлен флажок "Вместо основной" сохраняемый в настройках пользователя в разрезе объектов метаданных, управляющий подменой форм выбора
    Консоль компоновки
        *Исправлена ошибка команды "переставить с родителем" для группировок колонок и строк таблиц
    Контекстная подсказка
        *Кнопка "Удалить переносы" теперь еще заменяет двойные кавычки обычными
    Конструктор запросов
        +Для списка доступных таблиц добавлена закладка-отбор "Параметр"
        +При добавлении таблицы-параметра в выбранные таблицы сразу устанавливать тип запроса и имя временной таблицы
    Консоль запросов
        *Исправлена вычисление группировок итогов с закомментированным словом ОБЩИЕ
        +Кнопки выполнения запроса разделены на "Выполнить отображаемый запрос (F7)" и "Выполнить полный запрос (F8)"
    Редактор объекта БД
        *Исправлена ошибка поиска значения в бизнес процессе

3.68
    Редактор констант
        +Добавлена частичная поддержка констант с типом значения "Хранилище значения"
    Динамический список
        +Добавлена кнопка открытия основной формы списка с передачей отбора, текущей строки и владельца формы
        *Исправлена свежая ошибки открытия журнала документов
    Менеджер табличного поля
        *Исправлено ограничение типа значений элементов отбора
    Редактор объекта БД
        +В элементах управления колонок набора записей и движений реализован учет многострочного режима и других свойств из метаданных
        *Исправлена свежая поломка привязок на вкладке "Связанные колонки"
    Управление службами 1с
        *Исправлено перезаполнение списка при изменении компьютера
    Консоль запросов
        +Реализовано сохранение и восстановление позиции в тексте запроса при переходе между запросами и переключении режима дерева запроса
        +Для поля текста запроса добавлена команда "найти в дереве запроса" (текущую позицию в тексте запроса)
    Поиск дублей и замена ссылок
        *Исправлена свежая ошибка выполнения замены в иерархическом справочнике без флажка "Изменять поля по связям параметров выбора"
    Расширенный ввод значений
        +Добавлено распознавание навигационных ссылок
    Общее
        +Кнопка запуска связанного тонкого клиента теперь при повторном нажатии позволяет открыть в редакторе объекта БД один из открытых в связанном сеансе объектов
    Контекстная подсказка
        +Включена поддержка 8.3.8 в низкоуровневом получении описаний объектов

3.67
    Управление службами серверов 1С
        *Устранена ошибка открытия при наличии в строке соединения порта
        *Исправлено открытие при ошибках подключения WMI
    Консоль компоновки
        *Исправлена ошибка расшифровки при наличии пользовательских настроек компоновки
        +В панели настроек добавлена закладка "Пользовательские настройки" только для просмотра
        +В подменю "Исследовать" добавлена команда "Пользовательские настройки"
        +При сохранении варианта настроек добавлен пункт "<Новый>"
        +Реализовано перетаскивание полей на строки-коллекции в структуре
    Консоль запросов
        *Исправлена некорректная работа команды "найти результат" дерева запроса
        *Исправлена некорректная работа команды "Встроить из подзапроса" дерева запроса
    Конструктор запросов
        *Исправлено обновление представления условия связи при перетаскивании элементов отбора между связями
    Подбор и обработка объектов
        *Исправлены свежие ошибки при обработке подчиненных регистров сведений
    Редактор объекта БД
        *Исправлена недоступность для изменения основной формы измененного объекта
        +Добавлена кнопка "Отрыть основную форму объекта по ссылке"
        +При двойном клике по имени регистра в списке движений открывается его форма списка с отбором по регистратору
        *Исправлен сломанный несколько версий назад расширенный ввод значений в поле Ссылка
    Общее
        +В панели инструментов добавлена кнопка "Запустить связанный тонкий клиент"
    Интерфейсная панель
        +Реализовано явное отображение пустых ссылок в дереве
    Динамический список
        +Добавлена команда "Редактор объекта БД ячейки"
    Поиск дублей и замена ссылок
        +При выполнении замены реализовано предотвращение зацикливания уровней путем поднятия до ближайшего корректного родителя
    Настройка техножурнала
        *Реализован обход проблемы платформы со смещением времени изменения файла на 1ч

3.66
    +Добавлен инструмент "Управление службами серверов 1С"
    Поиск дублей и замена ссылок
        *Исправлена ошибка вывода сообщения об ошибке при отказе в записи независимых регистров сведений
        *Исправлено неверное замещение неуникальных записей в подчиненных регистрах сведений
    Подбор и обработка объектов
        *Исправлены ошибки при работе с подчиненными регистрами сведений
    Общее
        *Исправлено восстановление пароля в форме подключения СУБД
        *Исправлено свежее незапланированное изменение в поведении кнопки "Редактор объекта БД"
    Консоль компоновки данных
        *Кнопка "Исполняемый запрос" теперь открывает консоль запросов немодально
    Различные значения колонки
        +Добавлена кнопка "В список"
        *Исправлено некорректное вычисление типов значений
    Редактор объекта БД
        +Реализована поддержка флагов "Многострочный режим" и "Расширенное редактирование" колонок табличных частей и наборов записей
2016-12-04 00:22:14 +03:00

1218 lines
87 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирПривилегированный Экспорт;
Перем мПлатформа Экспорт;
Перем мСервисныйПроцессор Экспорт; // Для программного вызова из Интеграции
Перем ТаблицаБукв;
Перем мИскомыйОбъектПоискаДублей Экспорт;
Перем мСтруктураПоиска Экспорт;
Функция ЭтоБуква (Символ)
Код = КодСимвола(Символ);
Если (Код<=47) ИЛИ (Код>=58 И Код<=64) ИЛИ (Код>=91 И Код<=96) ИЛИ (Код>=123 И Код<=126) Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции
Функция АнализРазличийВСловах(Список1, Список2, ПолныйСписок, ОдинаковыхСлов, ДопустимоеРазличиеСлов) Экспорт
Если Ложь
Или Список1.Количество() = ПолныйСписок.Количество()
Или Список2.Количество() = ПолныйСписок.Количество()
Тогда
Возврат Истина;
КонецЕсли;
Если ПолныйСписок.Количество() = 0 Тогда
Возврат Истина;
КонецЕсли;
Если Список1.Количество() = Список2.Количество() Тогда
ЕстьОтличия = ПроверитьСловаНаОтличие(Список1, Список2, ДопустимоеРазличиеСлов);
ЕСли НЕ ЕстьОтличия Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
ЦелоеСлово = "";
Для Каждого Слово ИЗ ПолныйСписок Цикл
ЦелоеСлово = ЦелоеСлово + Слово.Значение;
КонецЦикла;
Слово1 = "";
Для Каждого Слово ИЗ Список1 Цикл
Слово1 = Слово1 + Слово.Значение;
КонецЦикла;
Слово2 = "";
Для Каждого Слово ИЗ Список2 Цикл
Слово2 = Слово2 + Слово.Значение;
КонецЦикла;
Если Истина
И Окр(СтрДлина(Слово1)/СтрДлина(ЦелоеСлово)*100) < ДопустимоеРазличиеСлов
И Окр(СтрДлина(Слово2)/СтрДлина(ЦелоеСлово)*100) < ДопустимоеРазличиеСлов
Тогда
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
Функция СравнитьСлова(Слово1, Слово2, ДопустимоеРазличиеСлов)
ТаблицаБукв.Очистить();
ТаблицаБуквПустая = Истина;
ЕСли СтрДлина(Слово1)<=СтрДлина(Слово2) Тогда
Слово = ВРЕГ(Слово1);
ИскомоеСлово = ВРЕГ(Слово2);
Иначе
Слово = ВРЕГ(Слово2);
ИскомоеСлово = ВРЕГ(Слово1);
КонецЕсли;
Для индекс = 1 по СтрДлина(Слово) Цикл
Символ = Сред(Слово, индекс, 1);
ЕСли ТаблицаБуквПустая Тогда
поз = Найти(ИскомоеСлово, Символ);
поправка = 0;
Пока поз>0 Цикл
ТаблицаБуквПустая = Ложь;
НовСтр = ТаблицаБукв.Добавить();
НовСтр.Позиция = поз + поправка;
НовСтр.ДлинаСлова = 1;
НовСтр.КолвоПропущенных = 0;
поправка = поправка + поз;
поз = Найти(Сред(ИскомоеСлово, поправка+1), Символ);
КонецЦикла;
Иначе
Для Каждого Вхождение ИЗ ТаблицаБукв Цикл
Если Сред(ИскомоеСлово, Вхождение.Позиция + Вхождение.ДлинаСлова, 1) = Символ Тогда
Вхождение.ДлинаСлова = Вхождение.ДлинаСлова + 1;
ИначеЕсли Сред(Слово, Вхождение.Позиция + Вхождение.ДлинаСлова - Вхождение.КолвоПропущенных, 1) = Вхождение.ПропущеноНа Тогда
Вхождение.ПропущеноНа = "";
Вхождение.ДлинаСлова = Вхождение.ДлинаСлова + 1;
Если Сред(ИскомоеСлово, Вхождение.Позиция + Вхождение.ДлинаСлова, 1) = Символ Тогда
Вхождение.ДлинаСлова = Вхождение.ДлинаСлова + 1;
Иначе
Вхождение.КолвоПропущенных = Вхождение.КолвоПропущенных + 1;
КонецЕсли;
Иначе
ЕСли Окр((Вхождение.КолвоПропущенных + 1) / СтрДлина(ИскомоеСлово) * 100)<=ДопустимоеРазличиеСлов Тогда
Вхождение.КолвоПропущенных = Вхождение.КолвоПропущенных + 1;
Вхождение.ДлинаСлова = Вхождение.ДлинаСлова + 1;
Вхождение.ПропущеноНа = Символ;
Иначе
Вхождение.КолвоПропущенных = Вхождение.КолвоПропущенных + 1;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
ЕСли ТаблицаБуквПустая Тогда
Возврат Ложь;
КонецЕсли;
ТаблицаБукв.Сортировать("ДлинаСлова УБЫВ, КолвоПропущенных ВОЗР");
СовпалоСимволов = ТаблицаБукв[0].ДлинаСлова - ТаблицаБукв[0].КолвоПропущенных;
Возврат (Окр(СовпалоСимволов / СтрДлина(ИскомоеСлово) * 100) >= (100 - ДопустимоеРазличиеСлов));
КонецФункции
Функция ПроверитьСловаНаОтличие(СписокСлов1, СписокСлов2, ДопустимоеРазличиеСлов) Экспорт
СписокРазличающихсяСлов = Новый СписокЗначений;
Для Каждого Слово1 ИЗ СписокСлов1 Цикл
ЕстьПара = Ложь;
Для Каждого Слово2 Из СписокСлов2 Цикл
Если СравнитьСлова(Слово1.Значение, Слово2.Значение, ДопустимоеРазличиеСлов) Тогда
ЕстьПара = Истина;
СписокСлов2.Удалить(Слово2);
Прервать;
КонецЕсли;
КонецЦикла;
ЕСли НЕ ЕстьПара Тогда
СписокРазличающихсяСлов.Добавить(Слово1.Значение);
КонецЕсли;
КонецЦикла;
СписокСлов1 = СписокРазличающихсяСлов;
Возврат Не (СписокСлов1.Количество() = 0 И СписокСлов2.Количество() = 0)
КонецФункции
Функция ПолучитьСписокСлов(ЗначениеРеквизита) Экспорт
СписокСлов = Новый СписокЗначений;
Слово = "";
Для индекс = 1 по СтрДлина(ЗначениеРеквизита) Цикл
Символ = Сред(ЗначениеРеквизита, индекс, 1);
Если ЭтоБуква(Символ) Тогда
Слово = Слово + Символ;
Иначе
Если Слово<>"" Тогда
СписокСлов.Добавить(ВРЕГ(Слово));
Слово = "";
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Слово<>"" Тогда
СписокСлов.Добавить(ВРЕГ(Слово));
КонецЕсли;
СписокСлов.СортироватьПоЗначению();
Возврат СписокСлов;
КонецФункции // ()
Функция _НайтиДубли(ИскомыйОбъект, СтруктураПоиска) Экспорт
мИскомыйОбъектПоискаДублей = ИскомыйОбъект;
мСтруктураПоиска = СтруктураПоиска;
НайденныеОбъекты = Новый ТаблицаЗначений;
НайденныеОбъекты.Колонки.Добавить("Ссылка");
ИмяСправочника = ИскомыйОбъект.Метаданные().Имя;
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ Разрешенные
| Ссылка*
|Из Справочник." + ИмяСправочника + " КАК Спр
|Где Не Спр.ЭтоГруппа";
Реквизиты = "";
СтрокаГде = "";
ВЗапросеТолькоРавенство = Истина;
МетаданныеОбъекта = ИскомыйОбъект.Метаданные();
МетаданныеРеквизитов = МетаданныеОбъекта.Реквизиты;
СтруктураИсходныхРеквизитов = Новый Структура;
Для каждого КлючИЗначение Из СтруктураПоиска Цикл
ИмяРеквизита = КлючИЗначение.Ключ;
СтепеньСхожести = КлючИЗначение.Значение;
ЗначениеРеквизита = ИскомыйОбъект[ИмяРеквизита];
МетаданныеРеквизита = МетаданныеРеквизитов.Найти(ИмяРеквизита);
ПредставлениеРеквизита = ?(МетаданныеРеквизита = Неопределено, ИмяРеквизита, Строка(МетаданныеРеквизита));
СтруктураИсходногоРеквизита = Новый Структура("ЗначениеРеквизита,СтепеньСхожести,СписокСлов"
,ЗначениеРеквизита,СтепеньСхожести,ПолучитьСписокСлов(ЗначениеРеквизита));
СтруктураИсходныхРеквизитов.Вставить(ИмяРеквизита,СтруктураИсходногоРеквизита);
Если Не МетаданныеРеквизита = Неопределено Тогда
ТипРеквизита = МетаданныеРеквизита.Тип;
ИначеЕсли ИмяРеквизита = "Код" Тогда
Если МетаданныеОбъекта.ТипКода = Метаданные.СвойстваОбъектов.ТипКодаСправочника.Строка Тогда
ТипРеквизита = Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(МетаданныеОбъекта.ДлинаКода));
Иначе
ТипРеквизита = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(МетаданныеОбъекта.ДлинаКода));
КонецЕсли;
ИначеЕсли ИмяРеквизита = "Наименование" Тогда
ТипРеквизита = Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(МетаданныеОбъекта.ДлинаНаименования));
Иначе
ТипРеквизита = Неопределено;
КонецЕсли;
НайденныеОбъекты.Колонки.Добавить(ИмяРеквизита, ТипРеквизита, ПредставлениеРеквизита);
НайденныеОбъекты.Колонки.Добавить(ИмяРеквизита+"_Флаг");
Реквизиты = Реквизиты+",
| "+ ИмяРеквизита;
Если ЗначениеЗаполнено(ЗначениеРеквизита) Тогда
Если СтепеньСхожести = "=" Тогда
ЗнакСравнения = ?(Не МетаданныеРеквизита = Неопределено И МетаданныеРеквизита.Тип.СодержитТип(Тип("Строка")) и МетаданныеРеквизита.Тип.КвалификаторыСтроки.Длина = 0,"Подобно","=");
СтрокаГде = ?(СтрокаГде = "", "",СтрокаГде +" или ")+"Спр."+ИмяРеквизита +" " +ЗнакСравнения+ " &"+ИмяРеквизита;
Запрос.УстановитьПараметр(""+ИмяРеквизита,ЗначениеРеквизита);
ИначеЕсли Не СтепеньСхожести = Неопределено Тогда
ВЗапросеТолькоРавенство = Ложь;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "*", Реквизиты);
Если ВЗапросеТолькоРавенство Тогда
Запрос.Текст = Запрос.Текст + Символы.ПС + " И("+СтрокаГде+")";
КонецЕсли;
ТаблицаСправочника = Запрос.Выполнить().Выгрузить();
Для каждого Строка Из ТаблицаСправочника Цикл
СтруктураНайденных = Новый Структура;
Для каждого КлючИЗначение Из СтруктураИсходныхРеквизитов Цикл
СтепеньСхожести = КлючИЗначение.Значение.СтепеньСхожести;
Если СтепеньСхожести = "=" Тогда
ИмяРеквизита = КлючИЗначение.Ключ;
ЗначениеРеквизита = КлючИЗначение.Значение.ЗначениеРеквизита;
//Поиск по равному значению
Если ЗначениеРеквизита = Строка[ИмяРеквизита] Тогда
СтруктураНайденных.Вставить(ИмяРеквизита);
КонецЕсли;
ИначеЕсли Не СтепеньСхожести = Неопределено Тогда
ИмяРеквизита = КлючИЗначение.Ключ;
//Поиск по похожим словам
СписокИскомыхСлов = КлючИЗначение.Значение.СписокСлов.Скопировать();
СписокНайденыхСлов = ПолучитьСписокСлов(Строка[ИмяРеквизита]);
Если Не ПроверитьСловаНаОтличие(СписокИскомыхСлов,СписокНайденыхСлов,СтепеньСхожести) Тогда
СтруктураНайденных.Вставить(ИмяРеквизита);
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Не СтруктураНайденных.Количество()=0 Тогда
НоваяСтрока = НайденныеОбъекты.Добавить();
НоваяСтрока.Ссылка = Строка.Ссылка;
Для каждого КлючИЗначение Из СтруктураПоиска Цикл
ИмяРеквизита = КлючИЗначение.Ключ;
НоваяСтрока[ИмяРеквизита] = Строка[ИмяРеквизита];
НоваяСтрока[ИмяРеквизита+"_Флаг"] = СтруктураНайденных.Свойство(ИмяРеквизита);
КонецЦикла;
КонецЕсли;
КонецЦикла;
Возврат НайденныеОбъекты;
КонецФункции // ()
// Заменяемые - Соответствие, Массив строк таблицы
// ТаблицаСсылающихсяОбъектов - ТаблицаЗначений, *Неопределено - таблица ссылающихся объектов возвращаемая методом НайтиПоСсылкам или ее часть
// ЗамещениеВсегда - Число - замещение к ключах независимых регистров сведений, 1 - замещать, 0 - спрашивать (на клиенте) или пропускать
//
Функция ВыполнитьЗаменуЭлементов(Заменяемые, ТаблицаСсылающихсяОбъектов = Неопределено, Знач ЗаголовокИндикации = "", ЗамещениеВсегда = 0) Экспорт
//Если ТранзакцияАктивна() Тогда
// ВызватьИсключение "Замена ссылок не допускается в общей транзакции";
//КонецЕсли;
БылиИсключения = Ложь;
Параметры = Новый Структура;
Параметры.Вставить("Объект", Неопределено);
СтруктураКоллизий = Новый Структура;
ИзмененныеПроведенныеДокументы.Очистить();
Если ТаблицаСсылающихсяОбъектов = Неопределено Тогда
СписокСсылок = Новый Массив;
Для Каждого КлючИЗначение Из Заменяемые Цикл
СписокСсылок.Добавить(КлючИЗначение.Ключ);
КонецЦикла;
ТаблицаСсылающихсяОбъектов = НайтиПоСсылкам(СписокСсылок);
КонецЕсли;
РодителиПравильных = Новый Соответствие;
Для Каждого КлючИЗначение Из Заменяемые Цикл
ОбъектМД = Метаданные.НайтиПоТипу(ТипЗнч(КлючИЗначение.Ключ));
Если ОбъектМД = Неопределено Тогда
ВызватьИсключение "Не найден объект метаданных по типу";
КонецЕсли;
Если ирОбщий.ЛиМетаданныеИерархическогоОбъектаЛкс(ОбъектМД) Тогда
МассивРодителей = Новый Массив;
Родитель = КлючИЗначение.Значение;
Если ТипЗнч(Родитель) = Тип("Структура") Тогда
Родитель = Родитель.Значение;
КонецЕсли;
Пока ЗначениеЗаполнено(Родитель) Цикл
МассивРодителей.Добавить(Родитель);
Родитель = Родитель.Родитель;
КонецЦикла;
РодителиПравильных[КлючИЗначение.Значение] = МассивРодителей;
КонецЕсли;
КонецЦикла;
Если ТаблицаСсылающихсяОбъектов.Количество() > 0 Тогда
Если Не ЗначениеЗаполнено(ЗаголовокИндикации) Тогда
ЗаголовокИндикации = "Замена ссылок";
КонецЕсли;
СтрокаГруппировок = "Метаданные,Данные";
Если ТипЗнч(ТаблицаСсылающихсяОбъектов) = Тип("ТаблицаЗначений") Тогда
СсылающиесяОбъекты = ТаблицаСсылающихсяОбъектов.Скопировать(, СтрокаГруппировок);
Иначе
СсылающиесяОбъекты = ТаблицаСсылающихсяОбъектов.Выгрузить(, СтрокаГруппировок);
КонецЕсли;
СсылающиесяОбъекты.Индексы.Добавить(СтрокаГруппировок);
СсылающиесяОбъекты.Свернуть(СтрокаГруппировок);
СсылающиесяОбъекты.Сортировать(СтрокаГруппировок);
КлючПоиска = Новый Структура("Данные");
Если мСервисныйПроцессор <> Неопределено Тогда
Индикатор = мСервисныйПроцессор.ПолучитьИндикаторПроцесса(СсылающиесяОбъекты.Количество(), ЗаголовокИндикации);
Иначе
Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(СсылающиесяОбъекты.Количество(), ЗаголовокИндикации);
КонецЕсли;
ТранзакцииРазрешены = Истина;
Если Истина
И ЗаписьНаСервере
И ирКэш.ЛиПортативныйРежимЛкс()
И Не ирПортативный.ЛиСерверныйМодульДоступенЛкс(Ложь)
И ирПортативный.ЭмуляцияЗаписиНаСервере
Тогда
Сообщить("В режиме эмуляции записи на сервере транзакции не поддерживаются");
ТранзакцииРазрешены = Ложь;
ОбщаяТранзакция = Ложь;
КонецЕсли;
Если ОбщаяТранзакция Тогда
НачатьТранзакцию();
КонецЕсли;
Попытка
Для Каждого ОписаниеОбъекта Из СсылающиесяОбъекты Цикл
Если мСервисныйПроцессор <> Неопределено Тогда
мСервисныйПроцессор.ОбновитьИндикатор(Индикатор);
Иначе
ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
КонецЕсли;
ОбъектИзменен = Ложь;
Если ТипЗнч(ОписаниеОбъекта.Данные) = Тип("Строка") Тогда
ОбъектСодержащийСсылку = ЗначениеИзСтрокиВнутр(ОписаниеОбъекта.Данные);
Иначе
ОбъектСодержащийСсылку = ОписаниеОбъекта.Данные;
КонецЕсли;
Если ТипЗнч(ОписаниеОбъекта.Метаданные) = Тип("Строка") Тогда
//ОбъектМД = Метаданные.НайтиПоПолномуИмени(ОписаниеОбъекта.Метаданные);
ОбъектМД = мПлатформа.ПолучитьОбъектМДПоПолномуИмени(ОписаниеОбъекта.Метаданные);
Иначе
ОбъектМД = ОписаниеОбъекта.Метаданные;
КонецЕсли;
Если КомментироватьЗаменуСсылок Тогда
Сообщить("Обрабатывается " + ОбъектСодержащийСсылку);
КонецЕсли;
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
ТипТаблицы = ирОбщий.ПолучитьТипТаблицыБДЛкс(ПолноеИмяМД);
ЗаполнитьЗначенияСвойств(КлючПоиска, ОписаниеОбъекта);
СсылкиВОбъектеНаНеправильныеЭлементы = ТаблицаСсылающихсяОбъектов.НайтиСтроки(КлючПоиска);
НеправильныеСсылкиВОбъекте = Новый Массив;
Для Каждого СтрокаНеправильнойСсылки Из СсылкиВОбъектеНаНеправильныеЭлементы Цикл
НеправильныеСсылкиВОбъекте.Добавить(СтрокаНеправильнойСсылки.Ссылка);
КонецЦикла;
Если ирОбщий.ЛиКорневойТипСсылочногоОбъектаБДЛкс(ТипТаблицы) Тогда
Если ТранзакцииРазрешены Тогда
НачатьТранзакцию();
КонецЕсли;
Попытка
ирОбщий.ЗаблокироватьСсылкуВТранзакцииЛкс(ОбъектСодержащийСсылку, Истина);
ОбъектБД = ОбъектСодержащийСсылку.ПолучитьОбъект();
Если ОбъектБД <> Неопределено Тогда
Для Каждого НеправильнаяСсылка Из НеправильныеСсылкиВОбъекте Цикл
ОбъектИзменен = ЗаменитьЗначениеВОбъектеБДЛкс(ОбъектБД, НеправильнаяСсылка, Заменяемые[НеправильнаяСсылка], РодителиПравильных[Заменяемые[НеправильнаяСсылка]]) Или ОбъектИзменен;
КонецЦикла;
КонецЕсли;
ЗаписатьОбъектЕслиИзменен(ОбъектБД, БылиИсключения, ОбъектИзменен, ОбъектМД);
Если ТранзакцииРазрешены Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
Если ТранзакцииРазрешены Тогда
ОтменитьТранзакцию();
КонецЕсли;
БылиИсключения = Истина;
Если ОбщаяТранзакция Тогда
ВызватьИсключение;
КонецЕсли;
Сообщить("Ошибка обработки ссылающегося объекта " + ирОбщий.ПолучитьXMLКлючОбъектаБДЛкс(ОбъектСодержащийСсылку) + ": " + ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
Если Не БылиИсключения Тогда
Если Метаданные.Документы.Содержит(ОбъектМД) Тогда
Для Каждого Движение ИЗ ОбъектМД.Движения Цикл
НаборЗаписей = Новый (СтрЗаменить(Движение.ПолноеИмя(), ".", "НаборЗаписей."));
НаборЗаписей.Отбор.Регистратор.Установить(ОбъектСодержащийСсылку);
БылиИсключения = Не ВыполнитьЗаменуВНабореЗаписей(НаборЗаписей, Заменяемые, НеправильныеСсылкиВОбъекте, ТранзакцииРазрешены);
КонецЦикла;
Для Каждого Последовательность ИЗ Метаданные.Последовательности Цикл
Если Последовательность.Документы.Содержит(ОбъектМД) Тогда
НаборЗаписей = Новый (СтрЗаменить(Последовательность.ПолноеИмя(), ".", "НаборЗаписей."));
НаборЗаписей.Отбор.Регистратор.Установить(ОбъектСодержащийСсылку);
БылиИсключения = Не ВыполнитьЗаменуВНабореЗаписей(НаборЗаписей, Заменяемые, НеправильныеСсылкиВОбъекте, ТранзакцииРазрешены);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
ИначеЕсли ирОбщий.ЛиКорневойТипКонстантыЛкс(ТипТаблицы) Тогда
Если ТранзакцииРазрешены Тогда
НачатьТранзакцию();
КонецЕсли;
Попытка
ОбъектБД = Константы[ОбъектМД.Имя].СоздатьМенеджерЗначения();
ирОбщий.ЗаблокироватьКонстантуЛкс(ОбъектБД, Истина);
ОбъектБД.Прочитать();
НовоеЗначение = Заменяемые[ОбъектБД.Значение];
Если НовоеЗначение <> Неопределено Тогда
ОбъектБД.Значение = НовоеЗначение;
ОбъектИзменен = Истина;
КонецЕсли;
Если ТранзакцииРазрешены Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
Если ТранзакцииРазрешены Тогда
ОтменитьТранзакцию();
КонецЕсли;
БылиИсключения = Истина;
Если ОбщаяТранзакция Тогда
ВызватьИсключение;
КонецЕсли;
Сообщить("Ошибка обработки ссылающегося объекта " + ирОбщий.ПолучитьXMLКлючОбъектаБДЛкс(ОбъектБД) + ": " + ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
ИначеЕсли ирОбщий.ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы) Тогда
МассивИзмененныхИзмерений = Новый Массив;
МенеджерЗаписи = РегистрыСведений[ОбъектМД.Имя].СоздатьМенеджерЗаписи();
КоллизийныйМенеджерЗаписи = РегистрыСведений[ОбъектМД.Имя].СоздатьМенеджерЗаписи();
Если ТранзакцииРазрешены Тогда
НачатьТранзакцию();
КонецЕсли;
Попытка
БылаКоллизия = Ложь;
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ОбъектСодержащийСсылку);
ЗаполнитьЗначенияСвойств(КоллизийныйМенеджерЗаписи, ОбъектСодержащийСсылку);
ИмяТаблицыРегистра = ирОбщий.ПолучитьИмяТаблицыИзМетаданныхЛкс(ОбъектМД);
НаборЗаписей = ирОбщий.ПолучитьНаборЗаписейПоКлючуЛкс(ИмяТаблицыРегистра, ОбъектСодержащийСсылку);
ирОбщий.ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, Истина);
КоллизийныйМенеджерЗаписи.Прочитать();
Если КоллизийныйМенеджерЗаписи.Выбран() Тогда
ПоляТаблицыБД = ирОбщий.ПолучитьПоляТаблицыМДЛкс(ПолноеИмяМД);
ОбъектИзменен = ВыполнитьЗаменуВСтрокеНабораЗаписей(КоллизийныйМенеджерЗаписи, Заменяемые, ПоляТаблицыБД);
Если Не БылиИсключения И ОбъектИзменен Тогда
Для каждого МетаИзмерение Из ОбъектМД.Измерения Цикл
Если КоллизийныйМенеджерЗаписи[МетаИзмерение.Имя] <> ОбъектСодержащийСсылку[МетаИзмерение.Имя] Тогда
МассивИзмененныхИзмерений.Добавить(МетаИзмерение.Имя);
КонецЕсли;
КонецЦикла;
Если МассивИзмененныхИзмерений.Количество() > 0 Тогда
НаборЗаписей = ирОбщий.ПолучитьНаборЗаписейПоКлючуЛкс(ИмяТаблицыРегистра, КоллизийныйМенеджерЗаписи);
ирОбщий.ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, Истина);
КоллизийныйМенеджерЗаписи.Прочитать();
Если КоллизийныйМенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.Прочитать();
МассивКоллекцийРеквизитов = Новый Массив;
МассивКоллекцийРеквизитов.Добавить(ОбъектМД.Ресурсы);
МассивКоллекцийРеквизитов.Добавить(ОбъектМД.Реквизиты);
Если Не СтруктураКоллизий.Свойство(ОбъектМД.Имя) Тогда
ТаблицаЗаписей = РегистрыСведений[ОбъектМД.Имя].СоздатьНаборЗаписей().Выгрузить();
ТаблицаЗаписей.Колонки.Добавить("МенеджерЗамены");
ТаблицаЗаписей.Колонки.Добавить("МенеджерОригинала");
Для Каждого КоллекцияРеквизитов Из МассивКоллекцийРеквизитов Цикл
Для Каждого МетаРеквизит Из КоллекцияРеквизитов Цикл
ИмяКолонки = МетаРеквизит.Имя;
ПредставлениеКолонки = МетаРеквизит.Представление();
КолонкаОригинала = ТаблицаЗаписей.Колонки[ИмяКолонки];
КолонкаОригинала.Имя = "Оригинал" + ИмяКолонки;
КолонкаОригинала.Заголовок = "Оригинал: " + ПредставлениеКолонки;
КолонкаЗамены = ТаблицаЗаписей.Колонки.Вставить(ТаблицаЗаписей.Колонки.Индекс(КолонкаОригинала),
"Замена" + ИмяКолонки, , "Замена: " + ПредставлениеКолонки);
ЗаполнитьЗначенияСвойств(КолонкаЗамены, КолонкаОригинала, , "Имя, Заголовок");
КонецЦикла;
КонецЦикла;
ТаблицаЗаписей.Колонки.Вставить(0, "Заменить", Новый ОписаниеТипов("Булево"), "Заменить");
СтруктураКоллизий.Вставить(ОбъектМД.Имя, ТаблицаЗаписей);
КонецЕсли;
НоваяКоллизийнаяЗапись = СтруктураКоллизий[ОбъектМД.Имя].Добавить();
Для Каждого КоллекцияРеквизитов Из МассивКоллекцийРеквизитов Цикл
Для Каждого МетаРеквизит Из КоллекцияРеквизитов Цикл
ИмяКолонки = МетаРеквизит.Имя;
ЗначениеРеквизита = МенеджерЗаписи[ИмяКолонки];
НоваяКоллизийнаяЗапись["Оригинал" + ИмяКолонки] = КоллизийныйМенеджерЗаписи[ИмяКолонки];
ЗаменаЗначения = Заменяемые[ЗначениеРеквизита];
Если ЗаменаЗначения <> Неопределено Тогда
НоваяКоллизийнаяЗапись["Замена" + ИмяКолонки] = ЗаменаЗначения;
Иначе
НоваяКоллизийнаяЗапись["Замена" + ИмяКолонки] = ЗначениеРеквизита;
КонецЕсли;
КоллизийныйМенеджерЗаписи[ИмяКолонки] = НоваяКоллизийнаяЗапись["Замена" + ИмяКолонки];
Если НоваяКоллизийнаяЗапись["Оригинал" + ИмяКолонки] <> НоваяКоллизийнаяЗапись["Замена" + ИмяКолонки] Тогда
БылаКоллизия = Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если БылаКоллизия И ЗамещениеВсегда <> 1 Тогда
ЗаполнитьЗначенияСвойств(НоваяКоллизийнаяЗапись, КоллизийныйМенеджерЗаписи);
Для Каждого ИмяКолонки Из МассивИзмененныхИзмерений Цикл
НоваяКоллизийнаяЗапись[ИмяКолонки] = МенеджерЗаписи[ИмяКолонки];
КонецЦикла;
НоваяКоллизийнаяЗапись.МенеджерЗамены = КоллизийныйМенеджерЗаписи;
НоваяКоллизийнаяЗапись.МенеджерОригинала = МенеджерЗаписи;
Иначе
СтруктураКоллизий[ОбъектМД.Имя].Удалить(НоваяКоллизийнаяЗапись);
МенеджерЗаписи.Удалить();
БылаКоллизия = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если БылаКоллизия Тогда
БылиИсключения = Ложь;
Иначе
БылиИсключения = Не ВыполнитьЗаменуВНабореЗаписей(МенеджерЗаписи, Заменяемые, НеправильныеСсылкиВОбъекте);
КонецЕсли;
Если ТранзакцииРазрешены Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
Если ТранзакцииРазрешены Тогда
ОтменитьТранзакцию();
КонецЕсли;
БылиИсключения = Истина;
Если ОбщаяТранзакция Тогда
ВызватьИсключение;
КонецЕсли;
Сообщить("Ошибка обработки ссылающегося объекта " + ирОбщий.ПолучитьXMLКлючОбъектаБДЛкс(НаборЗаписей) + ": " + ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
Иначе
БылиИсключения = Истина;
Сообщить("Замена ссылок в объектах типа " + ОбъектМД.ПолноеИмя() + " не поддерживается");
КонецЕсли;
КонецЦикла;
Если ОбщаяТранзакция Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
Если ОбщаяТранзакция Тогда
ОтменитьТранзакцию();
КонецЕсли;
ВызватьИсключение;
КонецПопытки;
Если мСервисныйПроцессор <> Неопределено Тогда
мСервисныйПроцессор.ОсвободитьИндикаторПроцесса(Индикатор, Истина);
Иначе
ирОбщий.ОсвободитьИндикаторПроцессаЛкс(Индикатор, Истина);
КонецЕсли;
КонецЕсли;
МассивЭлементовКУдалению = Новый Массив;
Для Каждого ЭлементТаблицыРегистра Из СтруктураКоллизий Цикл
Если ЭлементТаблицыРегистра.Значение.Количество() = 0 Тогда
МассивЭлементовКУдалению.Добавить(ЭлементТаблицыРегистра.Ключ);
КонецЕсли;
КонецЦикла;
Для Каждого ЭлементКУдалению Из МассивЭлементовКУдалению Цикл
СтруктураКоллизий.Удалить(ЭлементКУдалению);
КонецЦикла;
Если СтруктураКоллизий.Количество() > 0 Тогда
Если ЗамещениеВсегда = 1 Тогда
ЗамещатьВЭтотРаз = Истина;
Иначе
#Если Клиент Тогда
ФормаЗамещенияВНезависимыхРегистрахСведений = ПолучитьФорму("ФормаЗамещенияВНезависимыхРегистрахСведений");
ФормаЗамещенияВНезависимыхРегистрахСведений.КодВсегда = ЗамещениеВсегда;
ФормаЗамещенияВНезависимыхРегистрахСведений.СтруктураКоллизий = СтруктураКоллизий;
ФормаЗамещенияВНезависимыхРегистрахСведений.ОткрытьМодально();
ЗамещениеВсегда = ФормаЗамещенияВНезависимыхРегистрахСведений.КодВсегда;
ЗамещатьВЭтотРаз = ФормаЗамещенияВНезависимыхРегистрахСведений.РезультатФормы;
#Иначе
ЗамещатьВЭтотРаз = Ложь;
#КонецЕсли
КонецЕсли;
Если ЗамещатьВЭтотРаз Тогда
Для Каждого ЭлементРегистра Из СтруктураКоллизий Цикл
Для Каждого СтрокаЗаписи Из ЭлементРегистра.Значение Цикл
Если СтрокаЗаписи.Заменить Тогда
СтрокаЗаписи.МенеджерЗамены.Записать();
КонецЕсли;
СтрокаЗаписи.МенеджерОригинала.Удалить();
КонецЦикла;
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат Не БылиИсключения;
КонецФункции
Процедура ЗаписатьОбъектЕслиИзменен(ОбъектБД, БылиИсключения, ОбъектИзменен, ОбъектМД)
Если ОбъектБД <> Неопределено Тогда
//Если Объект.Модифицированность() Тогда
Если ОбъектИзменен Тогда
Попытка
ирОбщий.ЗаписатьОбъектЛкс(ОбъектБД, ЗаписьНаСервере,,, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений);
//Если ОтключатьКонтрольЗаписи Тогда
// ЗаписьЖурналаРегистрации("Запись с флагом Загрузка", УровеньЖурналаРегистрации.Информация, ОбъектМД,
// ОбъектСодержащийСсылку, "");
//КонецЕсли;
Исключение
Сообщить(ОписаниеОшибки(), СтатусСообщения.Важное);
БылиИсключения = Истина;
ОбъектИзменен = Ложь;
КонецПопытки;
Если Истина
И ОбъектИзменен
И Метаданные.Документы.Содержит(ОбъектМД)
И ОбъектМД.Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить
И ОбъектБД.Проведен
Тогда
СтрокаДляДокумента = ИзмененныеПроведенныеДокументы.Добавить();
СтрокаДляДокумента.ДатаДокумента = ОбъектБД.Дата;
СтрокаДляДокумента.ТипДокумента = ОбъектМД.Имя;
СтрокаДляДокумента.Документ = ОбъектБД.Ссылка;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры // ВыполнитьЗаменуЭлементов()
// Ищет все экземпляры значения ЧтоЗаменять в объекте и заменяет их на НаЧтоЗаменять
Функция ЗаменитьЗначениеВОбъектеБДЛкс(Объект, ЧтоЗаменять, НаЧтоЗаменять, РодителиПравильного = Неопределено)
ОбъектМД = Объект.Метаданные();
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
ПоляТаблицыБД = ирОбщий.ПолучитьПоляТаблицыМДЛкс(ПолноеИмяМД);
#Если _ Тогда
ПоляТаблицыБД = ПолучитьСтруктуруХраненияБазыДанных().Колонки;
#КонецЕсли
ОбъектИзменен = Ложь;
Для Каждого ПолеТаблицыБД Из ПоляТаблицыБД Цикл
Если ПолеТаблицыБД.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Попытка
ТабличнаяЧасть = Объект[ПолеТаблицыБД.Имя];
Исключение
// Сюда например попадаем в случае системной папки СистемныеПоля
ТабличнаяЧасть = Неопределено;
КонецПопытки;
Если ТабличнаяЧасть <> Неопределено Тогда
МетаТЧ = ОбъектМД.ТабличныеЧасти[ПолеТаблицыБД.Имя];
ПоляТаблицыТЧ = ирОбщий.ПолучитьПоляТаблицыМДЛкс(МетаТЧ.ПолноеИмя());
Для Каждого КолонкаТЧ Из ТабличнаяЧасть.Выгрузить().Колонки Цикл
ИмяРеквизита = КолонкаТЧ.Имя;
Если КолонкаТЧ.ТипЗначения.СодержитТип(ТипЗнч(ЧтоЗаменять)) Тогда
СтрокиТабЧасти = ТабличнаяЧасть.НайтиСтроки(Новый Структура(ИмяРеквизита, ЧтоЗаменять));
Для Каждого СтрокаТабЧасти Из СтрокиТабЧасти Цикл
ОбъектИзменен = ЗаменитьЗначениеРеквизитаСПроверкойВозможности(СтрокаТабЧасти, ИмяРеквизита, НаЧтоЗаменять, ПоляТаблицыТЧ) Или ОбъектИзменен;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Иначе
ИмяРеквизита = "" + ПолеТаблицыБД.Имя;
Если ирОбщий.СтрокиРавныЛкс(ИмяРеквизита, "Ссылка") Тогда
Продолжить;
КонецЕсли;
Если ПолеТаблицыБД.ТипЗначения.СодержитТип(ТипЗнч(ЧтоЗаменять)) И Объект[ИмяРеквизита] = ЧтоЗаменять Тогда
Если Истина
И РодителиПравильного <> Неопределено
И ирОбщий.СтрокиРавныЛкс(ПолеТаблицыБД.Имя, "Родитель")
И РодителиПравильного.Найти(Объект.Ссылка) <> Неопределено
Тогда
// Вместо зацикливания уровней иерархии поднимаем до ближайшего корректного родителя
лНаЧтоЗаменять = ЧтоЗаменять.Родитель;
Пока РодителиПравильного.Найти(лНаЧтоЗаменять) <> Неопределено Цикл
лНаЧтоЗаменять = лНаЧтоЗаменять.Родитель;
КонецЦикла;
Сообщить("Родитель объекта """ + Объект + """ был заменен на """ + лНаЧтоЗаменять + """ для избежания зацикливания уровней");
Иначе
лНаЧтоЗаменять = НаЧтоЗаменять;
КонецЕсли;
ОбъектИзменен = ЗаменитьЗначениеРеквизитаСПроверкойВозможности(Объект, ИмяРеквизита, лНаЧтоЗаменять, ПоляТаблицыБД) Или ОбъектИзменен;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ОбъектИзменен;
КонецФункции
// Результат - Булево - была ли выполнена замена
Функция ЗаменитьЗначениеРеквизитаСПроверкойВозможности(СтрокаТаблицы, ИмяРеквизита, НаЧтоЗаменять, ПоляТаблицыБД)
ОбъектНеИзменен = Истина;
ПолнаяЗаменаВозможна = ЗаменитьЗначениеРеквизитаСВлияющимиИЗависимыми(СтрокаТаблицы, ИмяРеквизита, НаЧтоЗаменять, ПоляТаблицыБД, , Истина);
Если ПолнаяЗаменаВозможна Тогда
ОбъектНеИзменен = ЗаменитьЗначениеРеквизитаСВлияющимиИЗависимыми(СтрокаТаблицы, ИмяРеквизита, НаЧтоЗаменять, ПоляТаблицыБД, , Ложь);
КонецЕсли;
Возврат Не ОбъектНеИзменен;
КонецФункции
// Результат - Булево
// Если ТолькоПроверитьВозможность = Истина, то содержит успешность полной замены
// Если ТолькоПроверитьВозможность = Ложь, то содержит факт отсутствия изменения объекта
Функция ЗаменитьЗначениеРеквизитаСВлияющимиИЗависимыми(СтрокаТаблицыБД, ИмяРеквизита, Знач НаЧтоЗаменять, ПоляТаблицыБД, ПравилаЗаменыЗависимых = Неопределено,
ТолькоПроверитьВозможность = Истина, ИмяРеквизитаОтбора = "Ссылка", ИсключитьЗависимое = "", ИсключитьВлияющее = "")
Результат = Истина;
Если ТипЗнч(НаЧтоЗаменять) = Тип("Структура") Тогда
ПравилаЗаменыЗависимых = НаЧтоЗаменять.ПравилаЗависимых;
НаЧтоЗаменять = НаЧтоЗаменять.Значение;
КонецЕсли;
ЧтоЗаменять = СтрокаТаблицыБД[ИмяРеквизита];
Если ТипЗнч(ЧтоЗаменять) = Тип("ЭлементОтбора") Тогда
ЧтоЗаменять = ЧтоЗаменять.Значение;
КонецЕсли;
Если ЧтоЗаменять = НаЧтоЗаменять Тогда
Возврат Результат;
КонецЕсли;
Если ПравилаЗаменыЗависимых <> Неопределено Тогда
ПолеТаблицы = ПоляТаблицыБД.Найти(ИмяРеквизита, "Имя");
ДанныеДляПоискаСвязейПоВладельцу = Неопределено;
Если ОпределятьСвязьПоВладельцуПоДанным Тогда
ДанныеДляПоискаСвязейПоВладельцу = СтрокаТаблицыБД;
КонецЕсли;
Если ПолеТаблицы.Метаданные <> Неопределено Тогда
СвязиПараметровВыбора = Новый Массив(ПолеТаблицы.Метаданные.СвязиПараметровВыбора);
Если ОпределятьСвязьПоВладельцуПоДанным Тогда
Попытка
ЗначениеВладельца = ЧтоЗаменять.Владелец;
Исключение
ЗначениеВладельца = Неопределено;
КонецПопытки;
Если ЗначениеЗаполнено(ЗначениеВладельца) Тогда
Для Каждого ПолеТаблицыБДВладельца Из ПоляТаблицыБД Цикл
Попытка
ЗначениеПоляВладельца = ДанныеДляПоискаСвязейПоВладельцу[ПолеТаблицыБДВладельца.Имя];
Исключение
// Ссылка у строки ТЧ
Продолжить;
КонецПопытки;
Если ТипЗнч(ЗначениеПоляВладельца) = Тип("ЭлементОтбора") Тогда
ЗначениеПоляВладельца = ЗначениеПоляВладельца.Значение;
КонецЕсли;
Если ЗначениеПоляВладельца = ЗначениеВладельца Тогда
СвязиПараметровВыбора.Добавить(Новый Структура("Имя, ПутьКДанным", "Отбор.Владелец", ПолеТаблицыБДВладельца.Имя));
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
УжеОбработанныеРеквизиты = Новый Структура;
Для Каждого СвязьПараметровВыбора Из СвязиПараметровВыбора Цикл
ИмяРеквизитаСодежащегоВлияющее = СвязьПараметровВыбора.ПутьКДанным;
ИмяРеквизитаСодежащегоВлияющее = ирОбщий.ПолучитьПоследнийФрагментЛкс(ИмяРеквизитаСодежащегоВлияющее);
Если ИсключитьВлияющее = ИмяРеквизитаСодежащегоВлияющее Тогда
Продолжить;
КонецЕсли;
ИмяРеквизитаОтбора = СтрЗаменить(СвязьПараметровВыбора.Имя, "Отбор.", "");
Если УжеОбработанныеРеквизиты.Свойство(ИмяРеквизитаОтбора) Тогда
Продолжить;
КонецЕсли;
УжеОбработанныеРеквизиты.Вставить(ИмяРеквизитаОтбора);
ВлияющееЗначениеЧтоЗаменять = ЧтоЗаменять[ИмяРеквизитаОтбора];
ВлияющееЗначениеНаЧтоЗаменять = НаЧтоЗаменять[ИмяРеквизитаОтбора];
Если ВлияющееЗначениеЧтоЗаменять <> ВлияющееЗначениеНаЧтоЗаменять Тогда
Результат = ЗаменитьЗначениеРеквизитаСВлияющимиИЗависимыми(СтрокаТаблицыБД, ИмяРеквизитаСодежащегоВлияющее, ВлияющееЗначениеНаЧтоЗаменять, ПоляТаблицыБД,
ПравилаЗаменыЗависимых, ТолькоПроверитьВозможность, ИмяРеквизитаОтбора, ИмяРеквизита) И Результат;
КонецЕсли;
КонецЦикла;
КонецЕсли;
ЗависимыеРеквизиты = ПолучитьЗависимыеРеквизитыМД(ПоляТаблицыБД, ИмяРеквизита, ДанныеДляПоискаСвязейПоВладельцу);
Для Каждого КлючИЗначение Из ЗависимыеРеквизиты Цикл
Если ИсключитьЗависимое = КлючИЗначение.Ключ Тогда
Продолжить;
КонецЕсли;
ЗависимоеЗначение = СтрокаТаблицыБД[КлючИЗначение.Ключ];
Если ТипЗнч(ЗависимоеЗначение) = Тип("ЭлементОтбора") Тогда
ЗависимоеЗначение = ЗависимоеЗначение.Значение;
КонецЕсли;
Если Не ЗначениеЗаполнено(ЗависимоеЗначение) Тогда
Продолжить;
КонецЕсли;
КлючПоискаПравила = Новый Структура("ПутьКДаннымВлияющего, ТипЗначения, ЧтоЗаменять, ЗависимоеВлияющее, ВлияющееЧтоЗаменять",
ИмяРеквизитаОтбора, Новый (ТипЗнч(ЗависимоеЗначение)), ЗависимоеЗначение, КлючИЗначение.Значение, ЧтоЗаменять);
ПравилаЗаменыЗависимого = ПравилаЗаменыЗависимых.НайтиСтроки(КлючПоискаПравила);
Если ПравилаЗаменыЗависимого.Количество() > 0 Тогда
ПравилоЗаменыЗависимого = ПравилаЗаменыЗависимого[0];
Если ПравилоЗаменыЗависимого.Пометка Тогда
Результат = ЗаменитьЗначениеРеквизитаСВлияющимиИЗависимыми(СтрокаТаблицыБД, КлючИЗначение.Ключ, ПравилоЗаменыЗависимого.НаЧтоЗаменять, ПоляТаблицыБД,
ПравилаЗаменыЗависимых, ТолькоПроверитьВозможность, ПравилоЗаменыЗависимого.ЗависимоеВлияющее,, ИмяРеквизита) И Результат;
Иначе
Результат = Ложь;
КонецЕсли;
Иначе
ПравилоЗаменыЗависимого = ПравилаЗаменыЗависимых.Добавить();
ЗаполнитьЗначенияСвойств(ПравилоЗаменыЗависимого, КлючПоискаПравила);
Результат = Ложь;
КонецЕсли;
ПравилоЗаменыЗависимого.НайденоСтрок = ПравилоЗаменыЗависимого.НайденоСтрок + 1;
ПравилоЗаменыЗависимого.Требуется = Истина;
КонецЦикла;
КонецЕсли;
Если Не ТолькоПроверитьВозможность Тогда
Если ТипЗнч(СтрокаТаблицыБД[ИмяРеквизита]) = Тип("ЭлементОтбора") Тогда
Результат = Не ирОбщий.БезопасноПрисвоитьПроизвольнуюСсылкуЛкс(СтрокаТаблицыБД[ИмяРеквизита].Значение, НаЧтоЗаменять) И Результат;
Иначе
Результат = Не ирОбщий.БезопасноПрисвоитьПроизвольнуюСсылкуЛкс(СтрокаТаблицыБД[ИмяРеквизита], НаЧтоЗаменять) И Результат;
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
Функция ВыполнитьЗаменуВНабореЗаписей(НаборЗаписейИлиМенеджерЗаписи, Заменяемые, НеправильныеСсылкиВОбъекте, Блокировать = Истина)
ОбъектМД = ирОбщий.ПолучитьМетаданныеЛкс(НаборЗаписейИлиМенеджерЗаписи);
ИмяТаблицыРегистра = ирОбщий.ПолучитьИмяТаблицыИзМетаданныхЛкс(ОбъектМД);
Если ирОбщий.ЛиМенеджерЗаписиРегистраЛкс(НаборЗаписейИлиМенеджерЗаписи) Тогда
НаборЗаписей = ирОбщий.ПолучитьНаборЗаписейПоКлючуЛкс(ИмяТаблицыРегистра, НаборЗаписейИлиМенеджерЗаписи);
Иначе
НаборЗаписей = НаборЗаписейИлиМенеджерЗаписи;
КонецЕсли;
Если Блокировать Тогда
НачатьТранзакцию();
КонецЕсли;
Попытка
Если Блокировать Тогда
ирОбщий.ЗаблокироватьНаборЗаписейПоОтборуЛкс(НаборЗаписей, Истина);
КонецЕсли;
ТипТаблицы = ирОбщий.ПолучитьТипТаблицыБДЛкс(ИмяТаблицыРегистра);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() = 0 Тогда
Если Блокировать Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Возврат Истина;
КонецЕсли;
ПоляТаблицыБД = ирОбщий.ПолучитьПоляТаблицыМДЛкс(ОбъектМД);
#Если _ Тогда
ПоляТаблицыБД = ПолучитьСтруктуруХраненияБазыДанных().Колонки;
#КонецЕсли
// Старый пустой набор нужен для очистки строк по старому отбору в случае изменения отбора набора
СтарыйНабор = ирОбщий.СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ИмяТаблицыРегистра);
ирОбщий.СкопироватьОтборЛкс(СтарыйНабор.Отбор, НаборЗаписей.Отбор);
ОтборИзменен = Ложь;
Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
ЗначениеПоля = ЭлементОтбора.Значение;
НаЧтоЗаменять = Заменяемые[ЗначениеПоля];
Если НаЧтоЗаменять = Неопределено Тогда
Продолжить;
КонецЕсли;
ОтборИзменен = ЗаменитьЗначениеРеквизитаСПроверкойВозможности(НаборЗаписей.Отбор, ЭлементОтбора.Имя, НаЧтоЗаменять, ПоляТаблицыБД) Или ОтборИзменен;
КонецЦикла;
ОбъектИзменен = ОтборИзменен; // Антибаг платформы 8.2. При изменении реквизитов строк набора записей для регистра бухгалтерии не взводится модифицированность
ЭтоРегистрБухгалтерии = ирОбщий.ПолучитьПервыйФрагментЛкс(ИмяТаблицыРегистра) = "РегистрБухгалтерии";
Если ЭтоРегистрБухгалтерии Тогда
ТаблицаНабора = НаборЗаписей.Выгрузить();
Иначе
ТаблицаНабора = НаборЗаписей;
КонецЕсли;
Для Каждого СтрокаНабора Из ТаблицаНабора Цикл
ОбъектИзменен = ВыполнитьЗаменуВСтрокеНабораЗаписей(СтрокаНабора, Заменяемые, ПоляТаблицыБД) Или ОбъектИзменен;
#Если Клиент Тогда
ОбработкаПрерыванияПользователя();
#КонецЕсли
КонецЦикла;
Если ЭтоРегистрБухгалтерии Тогда
НаборЗаписей.Загрузить(ТаблицаНабора);
ирОбщий.НаборЗаписейПослеЗагрузкиИзТаблицыЗначенийЛкс(НаборЗаписей);
ИначеЕсли ТипТаблицы = "РегистрСведений" И ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору Тогда
// Избавимся от неуникальных строк набора
Если НаборЗаписей.Количество() > 1 Тогда
СтруктураКлюча = ирОбщий.ПолучитьСтруктуруКлючаТаблицыБДЛкс(ИмяТаблицыРегистра,,, Ложь);
СтрокаПолейКлюча = "";
Для Каждого КлючИЗначение Из СтруктураКлюча Цикл
СтрокаПолейКлюча = СтрокаПолейКлюча + "," + КлючИЗначение.Ключ;
КонецЦикла;
СтрокаПолейКлюча = Сред(СтрокаПолейКлюча, 2);
НеуникальныеКлючи = ирОбщий.ПолучитьНеуникальныеКлючиКолонкиТаблицыЛкс(НаборЗаписей, СтрокаПолейКлюча);
Если НеуникальныеКлючи.Количество() > 0 Тогда
ТаблицаНабора = НаборЗаписей.Выгрузить();
Для Каждого НеуникальныйКлюч Из НеуникальныеКлючи Цикл
СтрокиНеуникальногоКлюча = ТаблицаНабора.НайтиСтроки(НеуникальныйКлюч);
Для ИндексУдаляемойСтроки = 0 По СтрокиНеуникальногоКлюча.Количество() - 2 Цикл
ТаблицаНабора.Удалить(СтрокиНеуникальногоКлюча[ИндексУдаляемойСтроки]);
КонецЦикла;
ПредставлениеСтруктуры = ирОбщий.ПолучитьПредставлениеСтруктурыЛкс(НеуникальныйКлюч);
Сообщить("Замещены неуникальные строки регистра сведений " + ОбъектМД.Имя + " по ключу " + ПредставлениеСтруктуры);
КонецЦикла;
НаборЗаписей.Загрузить(ТаблицаНабора);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ОбъектИзменен Тогда
Если ОтборИзменен Тогда
ирОбщий.ЗаписатьОбъектЛкс(СтарыйНабор, ЗаписьНаСервере,,, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений);
КонецЕсли;
ирОбщий.ЗаписатьОбъектЛкс(НаборЗаписей, ЗаписьНаСервере,,, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений);
КонецЕсли;
Если ТипТаблицы = "РегистрРасчета" Тогда
Для Каждого Перерасчет Из ОбъектМД.Перерасчеты Цикл
ИмяТаблицыПерерасчета = ирОбщий.ПолучитьИмяТаблицыИзМетаданныхЛкс(Перерасчет);
НаборЗаписейПерерасчета = ирОбщий.СоздатьНаборЗаписейПоИмениТаблицыБДЛкс(ИмяТаблицыПерерасчета);
НаборЗаписейПерерасчета.Отбор.ОбъектПерерасчета.Установить(НаборЗаписей.Отбор.Регистратор.Значение);
БылиИсключения = Не ВыполнитьЗаменуВНабореЗаписей(НаборЗаписейПерерасчета, Заменяемые, НеправильныеСсылкиВОбъекте, Ложь);
Если БылиИсключения Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Блокировать Тогда
ЗафиксироватьТранзакцию();
КонецЕсли;
Исключение
Если Блокировать Тогда
ОтменитьТранзакцию();
КонецЕсли;
Если ОбщаяТранзакция Тогда
ВызватьИсключение;
КонецЕсли;
Сообщить("Ошибка обработки ссылающегося объекта " + ирОбщий.ПолучитьXMLКлючОбъектаБДЛкс(НаборЗаписей) + ": " + ОписаниеОшибки(), СтатусСообщения.Внимание);
Возврат Ложь;
КонецПопытки;
Возврат Истина;
КонецФункции
Функция ВыполнитьЗаменуВСтрокеНабораЗаписей(СтрокаНабора, Заменяемые, ПоляТаблицыБД)
ОбъектИзменен = Ложь;
Для Каждого ПолеТаблицыБД Из ПоляТаблицыБД Цикл
Если ПолеТаблицыБД.ТипЗначения.СодержитТип(Тип("ТаблицаЗначений")) Тогда
Продолжить;
КонецЕсли;
//Если Не Поле.Поле Тогда // было для полей построителя запроса
// // Антибаг платформы. Зачем то добавляются лишние поля в доступные поля, не свойственные по признаку наличия корресподнеции
// // у бухгалтерских таблиц.
// Продолжить;
//КонецЕсли;
//ИмяПоля = Поле.Имя;
ИмяПоля = ПолеТаблицыБД.Имя;
ЗначениеПоля = СтрокаНабора[ИмяПоля];
НаЧтоЗаменять = Заменяемые[ЗначениеПоля];
Если НаЧтоЗаменять = Неопределено Тогда
Продолжить;
КонецЕсли;
ОбъектИзменен = ЗаменитьЗначениеРеквизитаСПроверкойВозможности(СтрокаНабора, ИмяПоля, НаЧтоЗаменять, ПоляТаблицыБД) Или ОбъектИзменен;
КонецЦикла;
Возврат ОбъектИзменен;
КонецФункции
Функция ПолучитьЗависимыеРеквизитыМД(ПоляТаблицы, ИмяРеквизита, ДанныеДляПоискаСвязейПоВладельцу = Неопределено) Экспорт
Результат = Новый Структура;
Для Каждого ПолеТаблицы Из ПоляТаблицы Цикл
Если ПолеТаблицы.Метаданные = Неопределено Тогда
Продолжить;
КонецЕсли;
Для Каждого СвязьПараметровВыбора Из ПолеТаблицы.Метаданные.СвязиПараметровВыбора Цикл
ИмяРеквизитаСодежащегоВлияющее = СвязьПараметровВыбора.ПутьКДанным;
//Если Найти(ИмяРеквизитаСодежащегоВлияющее, ОбъектМД.Имя + ".") = 1 Тогда
// // Это строка ТЧ
ИмяРеквизитаСодежащегоВлияющее = ирОбщий.ПолучитьПоследнийФрагментЛкс(ИмяРеквизитаСодежащегоВлияющее);
//КонецЕсли;
Если ИмяРеквизитаСодежащегоВлияющее = ИмяРеквизита Тогда
ИмяРеквизитаОтбора = СтрЗаменить(СвязьПараметровВыбора.Имя, "Отбор.", "");
Результат.Вставить(ПолеТаблицы.Имя, ИмяРеквизитаОтбора);
КонецЕсли;
КонецЦикла;
Если ДанныеДляПоискаСвязейПоВладельцу <> Неопределено Тогда
Попытка
ЗначениеВладельца = ДанныеДляПоискаСвязейПоВладельцу[ПолеТаблицы.Имя].Владелец;
Исключение
ЗначениеВладельца = Неопределено;
КонецПопытки;
Если ЗначениеВладельца <> Неопределено Тогда
Если ЗначениеВладельца = ДанныеДляПоискаСвязейПоВладельцу[ИмяРеквизита] Тогда
Результат.Вставить(ПолеТаблицы.Имя, "Владелец");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ОбработатьНеправильныйОбъектПослеЗамены(УдаляемаяСсылка, НепосредственноеУдаление = Ложь, СсылкаДляЗаменыДанных = Неопределено) Экспорт
#Если _ Тогда
УдаляемаяСсылка = Справочники.УчастникиИис.ПустаяСсылка();
#КонецЕсли
Объект = УдаляемаяСсылка.ПолучитьОбъект();
ОбъектУдалили = Объект = Неопределено;
Если Не ОбъектУдалили Тогда
КорневойТип = ирОбщий.ПолучитьКорневойТипКонфигурацииЛкс(УдаляемаяСсылка);
НачатьТранзакцию();
Попытка
ПредставлениеОбъекта = "" + Объект;
Если СсылкаДляЗаменыДанных <> Неопределено Тогда
ПравильныйЭлементСНеправильнымиДанными = СсылкаДляЗаменыДанных.ПолучитьОбъект();
СтандартнаяОбработка = Истина;
Если ЗначениеЗаполнено(ОбработкаЗаменыДанных) Тогда
ТекстАлгоритма = "ПравильныйОбъект = _П0; НеправильныйОбъект = _П1; СтандартнаяОбработка = _П2; " + ОбработкаЗаменыДанных + "; _П2 = СтандартнаяОбработка;";
ирОбщий.ВыполнитьАлгоритм(ТекстАлгоритма,,, ПравильныйЭлементСНеправильнымиДанными, Объект, СтандартнаяОбработка);
КонецЕсли;
Если СтандартнаяОбработка Тогда
НеправильныйОбъектXDTO = СериализаторXDTO.ЗаписатьXDTO(ПравильныйЭлементСНеправильнымиДанными);
НеправильныйОбъектXDTO.Ref = УдаляемаяСсылка;
ПравильныйОбъектXDTO = СериализаторXDTO.ЗаписатьXDTO(Объект);
ПравильныйОбъектXDTO.Ref = СсылкаДляЗаменыДанных;
ПравильныйОбъект = СериализаторXDTO.ПрочитатьXDTO(ПравильныйОбъектXDTO);
Если Истина
И Не ирОбщий.РежимСовместимостиМеньше8_3_4Лкс()
И ирОбщий.ЛиКорневойТипОбъектаСПредопределеннымЛкс(КорневойТип)
И (Ложь
Или Не НепосредственноеУдаление
Или (Истина
И НепосредственноеУдаление
И Не ЗначениеЗаполнено(ПравильныйОбъект.ИмяПредопределенныхДанных)))
Тогда
ПравильныйОбъект.ИмяПредопределенныхДанных = ПравильныйЭлементСНеправильнымиДанными.ИмяПредопределенныхДанных;
КонецЕсли;
Иначе
ПравильныйОбъект = ПравильныйЭлементСНеправильнымиДанными;
КонецЕсли;
ирОбщий.ЗаписатьОбъектЛкс(ПравильныйОбъект, ЗаписьНаСервере, , , Истина);
Если СтандартнаяОбработка Тогда
Объект = СериализаторXDTO.ПрочитатьXDTO(НеправильныйОбъектXDTO);
Объект.Прочитать();
ПредставлениеОбъекта = "" + Объект;
КонецЕсли;
КонецЕсли;
Если НепосредственноеУдаление Тогда
ирОбщий.УдалитьОбъектЛкс(Объект, ЗаписьНаСервере, ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений);
ОбъектУдалили = Истина;
Сообщить("Удалили """ + ПредставлениеОбъекта + """");
Иначе
ирОбщий.УстановитьПометкуУдаленияОбъектаЛкс(Объект, ЗаписьНаСервере, Истина);
Сообщить("Установили пометку удаления """ + ПредставлениеОбъекта + """");
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
Сообщить("Обработка неправильного """ + ПредставлениеОбъекта + """: " + ОписаниеОшибки());
ОтменитьТранзакцию();
КонецПопытки;
КонецЕсли;
Возврат ОбъектУдалили;
КонецФункции
Процедура ОбработатьПравильныйОбъектПослеЗамены(ПравильнаяСсылка, СнятьПометкуУдаления = Ложь, Перезаписать = Ложь) Экспорт
Если Истина
И Не СнятьПометкуУдаления
И Не Перезаписать
Тогда
Возврат;
КонецЕсли;
Объект = ПравильнаяСсылка.ПолучитьОбъект();
Попытка
Если СнятьПометкуУдаления Тогда
Объект.ПометкаУдаления = Ложь;
Сообщить("Сняли пометку удаления """ + Объект + """");
КонецЕсли;
ирОбщий.ЗаписатьОбъектЛкс(Объект, ЗаписьНаСервере, , , ОтключатьКонтрольЗаписи, БезАвторегистрацииИзменений);
Исключение
Сообщить("Обработка правильного """ + Объект + """: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
КонецПопытки;
КонецПроцедуры
Функция ПолучитьСсылочныеИзмеренияРегистраЛкс(НаборЗаписей, МетаРегистр) Экспорт
ПоляТаблицы = НаборЗаписей.ВыгрузитьКолонки();
Результат = Новый Структура;
Для Каждого МетаИзмерение Из МетаРегистр.Измерения Цикл
ПолеТаблицы = ПоляТаблицы.Найти(МетаИзмерение.Имя);
Если ПолеТаблицы = Неопределено Тогда
// Например, небалансовое измерение регистра бухгалтерии
Продолжить;
КонецЕсли;
Для Каждого Тип Из МетаИзмерение.Тип.Типы() Цикл
Если Найти(XMLТип(Тип).ИмяТипа, "Ref.") > 0 Тогда
Результат.Вставить(МетаИзмерение.Имя, МетаИзмерение.Тип);
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат Результат;
КонецФункции
Процедура ЗаблокироватьРегистрПоОтборуИИзмерениямПередЗаменой(НаборЗаписей, НайденныеВОбъектеНеправильныеСсылки) Экспорт
Блокировка = Новый БлокировкаДанных;
ОбъектМД = НаборЗаписей.Метаданные();
ПолноеИмяМД = ОбъектМД.ПолноеИмя();
ИмяТаблицыРегистра = ирОбщий.ПолучитьИмяТаблицыИзМетаданныхЛкс(ОбъектМД);
ТипТаблицы = ирОбщий.ПолучитьТипТаблицыБДЛкс(ИмяТаблицыРегистра);
// По регистратору
Если Ложь
Или Не ирОбщий.ЛиКорневойТипРегистраСведенийЛкс(ТипТаблицы)
Или ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору
Тогда
ПространствоБлокировок = ПолноеИмяМД + ".НаборЗаписей";
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
ЭлементБлокировки.УстановитьЗначение("Регистратор", НаборЗаписей.Отбор.Регистратор.Значение);
КонецЕсли;
// По измерениям блокируем все возможные диапазоны. В большинстве случаев при замене ссылок такие блокировки будут неоправданными
ПространствоБлокировок = ПолноеИмяМД;
ЭлементБлокировки = Блокировка.Добавить(ПространствоБлокировок);
СсылочныеИзмерения = ПолучитьСсылочныеИзмеренияРегистраЛкс(НаборЗаписей, ОбъектМД);
Для Каждого КлючЗначение Из СсылочныеИзмерения Цикл
ИмяИзмерения = КлючЗначение.Ключ;
ТипИзмерения = КлючЗначение.Значение;
Для Каждого НеправильнаяСсылка Из НайденныеВОбъектеНеправильныеСсылки Цикл
Если ТипИзмерения.СодержитТип(ТипЗнч(НеправильнаяСсылка)) Тогда
Блокировка.Добавить(ПространствоБлокировок).УстановитьЗначение(ИмяИзмерения, НеправильнаяСсылка);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Блокировка.Заблокировать();
КонецПроцедуры // ВыполнитьЗаменуВНабореЗаписей()
//ирПортативный лФайл = Новый Файл(ИспользуемоеИмяФайла);
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = Лев(лФайл.Путь, СтрДлина(лФайл.Путь) - СтрДлина("Модули\")) + "ирПортативный.epf";
//ирПортативный #Если Клиент Тогда
//ирПортативный Контейнер = Новый Структура();
//ирПортативный Оповестить("ирПолучитьБазовуюФорму", Контейнер);
//ирПортативный Если Не Контейнер.Свойство("ирПортативный", ирПортативный) Тогда
//ирПортативный ПолноеИмяФайлаБазовогоМодуля = ВосстановитьЗначение("ирПолноеИмяФайлаОсновногоМодуля");
//ирПортативный ирПортативный = ВнешниеОбработки.ПолучитьФорму(ПолноеИмяФайлаБазовогоМодуля);
//ирПортативный КонецЕсли;
//ирПортативный #Иначе
//ирПортативный ирПортативный = ВнешниеОбработки.Создать(ПолноеИмяФайлаБазовогоМодуля, Ложь); // Это будет второй экземпляр объекта
//ирПортативный #КонецЕсли
//ирПортативный ирОбщий = ирПортативный.ПолучитьОбщийМодульЛкс("ирОбщий");
//ирПортативный ирКэш = ирПортативный.ПолучитьОбщийМодульЛкс("ирКэш");
//ирПортативный ирСервер = ирПортативный.ПолучитьОбщийМодульЛкс("ирСервер");
//ирПортативный ирПривилегированный = ирПортативный.ПолучитьОбщийМодульЛкс("ирПривилегированный");
мПлатформа = ирКэш.Получить();
ТаблицаБукв = Новый ТаблицаЗначений;
ТаблицаБукв.Колонки.Добавить("Позиция");
ТаблицаБукв.Колонки.Добавить("КолвоПропущенных");
ТаблицаБукв.Колонки.Добавить("ДлинаСлова");
ТаблицаБукв.Колонки.Добавить("ПропущеноНа");
ЗаписьНаСервере = ирОбщий.ПолучитьРежимЗаписиНаСервереПоУмолчаниюЛкс();
ЭтотОбъект.ОтключатьКонтрольЗаписи = Истина;