Предисловие
Любое решение требует поддержки, в том числе и в части улучшения программного кода и архитектуры решения. Это то, в чем нуждается каждое программа, а в нашем случае каждая конфигурация, созданная на базе платформы 1С.
Модули конфигураций чаще всего подвергаются адаптации под изменяющуюся архитектуру, но как обстоят дела с внешними отчетами и обработками? В одной из прошлых публикаций был сделан простой инструмент для пакетной выгрузки и загрузки внешних отчетов и обработок, который будет постепенно развиваться дальше.
Давайте рассмотрим простой пример того, как выгрузить внешние отчеты и обработки для обновления и улучшения, а после загрузить изменения массово обратно.
Суть проблемы
Реальная ситуация: после полугода доработки конфигурации появилась необходимость привести ее программный код в порядок. Разработчики по всем вносимым доработкам, например, использовали один общий модуль. Настало время разделить процедуры и функции этого модуля на отдельные части. Для решения подобной задачи нужно определиться со структурой конфигурацией, четко определить границы подсистем, включаемых в ее состав. Затем перенести процедуры и функции в соответствующие модули.
Конечно же, останавливаться на этом нельзя, но может потребовать внесения изменений в модули внешних отчетов и обработок. Все это можно проделать с помощью механизма глобальной замены конфигуратора.
Сегодня мы и рассмотрим как выгрузить справочник внешних обработок на диск для их последующего изменения, а после загрузить все обратно.
Решение
Чтобы решить задачу мы можем воспользоваться стандартной возможностью конфигуратора по поиску и замене текстов модулей. На этот раз нам нужно будет установить настройки на вкладке "Файлы", где мы укажем каталог с внешними обработками и отчетами, а также указать текст поиска и замены.
Остается только выгрузить все внешние обработки из информационной базы в назначенный каталог, обработать тексты их модулей и загрузить обратно. Мы, конечно, можем проделать это вручную, но мы ведь программисты! Напишем пару скриптов для автоматизации выгрузки / загрузки внешний отчетов и обработок. Для примера решим эту задачу для конфигурации "Управление производственным предприятием" версии 1.3, а после для чего-нибудь более нового. Например, для "Бухгалтерии предприятия" редакции 3.
Автоматизация процесса для УПП
Обработка для выгрузки будет достаточно простой, поэтому алгоритм выгрузки и загрузки приведу в обычных листингах кода. Для УПП все внешние обработки и отчеты, прикрепленные к информационной базе, хранятся в справочнике "ВнешниеОбработки". Вот так выглядит структура метаданных справочника:
И так, приступим! На следующем листинге представлен алгоритм выгрузки внешний обработок и отчетов в выбранный каталог.
Выгрузка внешних отчетов и обработок для УПП 1.3
Скрипт для выгрузки внешних отчетов и обработок с предварительным выбором каталога.
Процедура КнопкаВыгрузкиВнешнихОтчетовИОбработокВыполнитьНажатие(Кнопка)
// Вызываем диалог выбора каталога для выгрузки
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите каталог";
Если ДиалогОткрытияФайла.Выбрать() Тогда
ПутьККаталогу = ДиалогОткрытияФайла.Каталог;
Иначе
Текст = "Каталог не выбран";
Предупреждение(Текст);
КонецЕсли;
// Получаем внешние обработки и отчеты из базы данных
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВнешниеОбработки.Наименование КАК ИмяОбработки,
| ВнешниеОбработки.ХранилищеВнешнейОбработки КАК ФайлОбработки,
| ЛОЖЬ КАК ЭтоТабЧасть,
| ВнешниеОбработки.КомментарийКФайлуИсточнику КАК КомментарийСРасширениемФайла,
| ВнешниеОбработки.Код
|ИЗ
| Справочник.ВнешниеОбработки КАК ВнешниеОбработки
|ГДЕ
| НЕ ВнешниеОбработки.ПометкаУдаления
| И НЕ ВнешниеОбработки.ЭтоГруппа";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
ДвоичныеДанные = Выборка.ФайлОбработки.Получить();
// Если элемент справочника "ВнешниеОбработки" содержит двоичные данные файла,
// то записываем его в каталог
Если ДвоичныеДанные Неопределено Тогда
// Имя сохраняемой обработки - код элемента справочника "Внешние обработки",
// чтобы избежать затирания файлов при одинаковом наименовании
// При необходимости можно изменить на наименование или GUID элемента справочника
ПутьДляСохраненияФайлаОбработки = ПутьККаталогу + "\" + Выборка.Код + "."
+ ПолучитьРасширениеФайла(Выборка.КомментарийСРасширениемФайла);
ДвоичныеДанные.Записать(ПутьДляСохраненияФайлаОбработки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Выгрузка данных из строк табличной части справочника не выполняется.
Загрузка внешних обработок представлена далее.
Загрузка внешних отчетов и обработок для УПП 1.3
Аналогичный скрипт с выбором каталога, но для загрузки файлов внешних отчетов и обработок в соответствующий справочник.
Процедура КнопкаЗагрузкиВнешнихОтчетовИОбработокВыполнитьНажатие(Кнопка)
// Выбираем каталог выгруженных ранее внешних обработок
Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
ДиалогОткрытияФайла.Заголовок = "Выберите каталог с обработками";
Если ДиалогОткрытияФайла.Выбрать() Тогда
КаталогОбработок = ДиалогОткрытияФайла.Каталог;
Иначе
Текст = "ru = ""Каталог не выбран!""; en = ""Folder not selected!""";
Предупреждение(НСтр(Текст));
Возврат;
КонецЕсли;
// Получаем все файлы в каталоге
МассивВнешниеОбработки = НайтиФайлы(КаталогОбработок, "*.*");
ЕстьОшибки = Ложь; // Запись внешних обработок в инф. базу делам
// в единой транзакции и проверяем на ошибки
НачатьТранзакцию();
Для Каждого Стр Из МассивВнешниеОбработки Цикл
// Ищем элемент справочника "Внешние обработки"
// по имени файла (в имени был ранее записан код элемента)
РезультатПоиска = Справочники.ВнешниеОбработки.НайтиПоКоду(Стр.ИмяБезРасширения);
Если НЕ РезультатПоиска.Пустая() Тогда
// Если обработка найдена - получаем объект элемента и помещаем
// в него двоичные данные файла обработки/отчета
ОбъектОбработка = РезультатПоиска.ПолучитьОбъект();
ОбъектОбработка.ХранилищеВнешнейОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(Стр.ПолноеИмя));
Попытка
ОбъектОбработка.Записать();
Исключение
ОбщегоНазначения.Сообщение("Не удалось записать обработку с кодом: "
+ ОбъектОбработка.Код);
ЕстьОшибки = Истина;
Прервать;
КонецПопытки;
КонецЕсли;
КонецЦикла;
// Если были ошибки - отменяем транзакцию. Все изменения отменяются.
Если ЕстьОшибки Тогда
ОтменитьТранзакцию();
Иначе
ЗафиксироватьТранзакцию();
КонецЕсли;
КонецПроцедуры
Поиск выполняется по коду, т.к. в предыдущем скрипте для выгрузки использовался именно он. При использовании наименования или GUID'а скрипт нужно подкорректировать.
Используя приведенный алгоритм проблем с выгрузкой/загрузкой внешний обработок и отчетов быть не должно. Нужно лишь учитывать, что коды элементов справочника должны иметь уникальные имена и у пользователя, запускающего обработку, должны быть соответствующие права доступа.
Стоит понимать, что в некоторых случаях внешние обработки и отчеты могут храниться не в реквизите "ХранилищеВнешнейОбработки", а в табличной части "Принадлежность". Тогда необходимо доработать представленные выше алгоритмы выгрузки/загрузки. Обычно это редко встречается, т.к. такой подход хранения создает некоторые проблемы в сопровождении - все эти обработки нужно отслеживать и дорабатывать отдельно.
Алгоритмы для БП 3.x
В современных конфигурациях справочник "Дополнительные отчеты и обработки" значительно отличается от того, что было в предыдущих версиях решений на обычных формах. Структура метаданных справочника имеет следующий вид.
Выгружать внешние отчеты и обработки будем в явно указанный каталог. Если база файловая, то выгрузка будет выполняться там, где запущено клиентское приложение. Если база клиент-серверная, то выгрузка выполняется на стороне сервера. Пример алгоритма для выгрузки отчетов и обработок в каталог под следующим спойлером.
Выгрузка внешних отчетов и обработок для БП 3.x
Алгоритм выгрузки достаточно простой. Все что нужно:
- Получаем элементы справочника, у которого нет пометки на удаление и это не группа.
- Если есть двоичные данные файла в справочнике, то выгружаем в каталог.
- Расширение файла зависит от вида внешней обработки / отчета.
- Профит!
Процедура ВыгрузитьОбработкиНаСервере()
КаталогВыгрузкиОбработок = "S:\ВыгрузкаОбработок";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеОтчетыИОбработки.ИмяОбъекта КАК ИмяОбъекта,
| ДополнительныеОтчетыИОбработки.Вид КАК Вид,
| ДополнительныеОтчетыИОбработки.ХранилищеОбработки КАК ХранилищеОбработки
|ИЗ
| Справочник.ДополнительныеОтчетыИОбработки КАК ДополнительныеОтчетыИОбработки
|ГДЕ
| НЕ ДополнительныеОтчетыИОбработки.ПометкаУдаления
| И НЕ ДополнительныеОтчетыИОбработки.ЭтоГруппа";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
ЭтоОтчет = Ложь;
Если Выборка.Вид = Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительныйОтчет
ИЛИ Выборка.Вид = Перечисления.ВидыДополнительныхОтчетовИОбработок.Отчет Тогда
ЭтоОтчет = Истина;
КонецЕсли;
// Имя выгружаемого файла - это имя объекта, которое должно быть уникальным для каждой обработки / отчета в справочнике.
// При этом не учитываются элементы, помеченные на удаление.
ПутьВыгрузки = КаталогВыгрузкиОбработок
+ "\"
+ Выборка.ИмяОбъекта
+ "."
+ ?(ЭтоОтчет, "erf", "epf");
ДвоичныеДанныеЭлемента = Выборка.ХранилищеОбработки.Получить();
Если НЕ ДвоичныеДанныеЭлемента = Неопределено Тогда
ДвоичныеДанныеЭлемента.Записать(ПутьВыгрузки);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Теперь у нас есть выгруженные обработки и отчеты в каталоге. Ура!
Теперь задача поинтересней - нужно ранее выгруженные файлы загрузить обратно в справочник.
Загрузка внешних отчетов и обработок для БП 3.x
Алгоритм загрузки намного сложнее, т.к. требует доп. проверок и вызова типовых алгоритмов регистрации дополнительных отчетов и обработок.
Процедура ЗагрузитьОбработкиНаСервере()
КаталогДляЗагрузки = "S:\ВыгрузкаОбработок";
ФайлыДляЗагрузки = НайтиФайлы(КаталогДляЗагрузки, "*.*");
НачатьТранзакцию();
ЕстьОшибки = Ложь;
Для Каждого ФайлДляЗагрузки Из ФайлыДляЗагрузки Цикл
ИмяОбъектаИзФайла = ФайлДляЗагрузки.ИмяБезРасширения;
Если ВРег(ФайлДляЗагрузки.Расширение) = ".ERF" Тогда
ЭтоОтчет = Истина;
Иначе
ЭтоОтчет = Ложь;
КонецЕсли;
ЭлементДляОбновления = НайтиДополнительныйОтчетОбработкуПоИмениОбъекта(ИмяОбъектаИзФайла, ЭтоОтчет);
Если ЗначениеЗаполнено(ЭлементДляОбновления) Тогда
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ФайлДляЗагрузки.ПолноеИмя);
СправочникОбъект = ЭлементДляОбновления.ПолучитьОбъект();
// Далее выполняем типовые действия из подсистемы "Дополнительный отчеты и обработки",
// чтобы корректно зарегистрировать обработку в системе и обновить сведений о ней
#Область ОбработкаТиповымиАлгоритмамиБСП
АдресДанных = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла);
Менеджер = ?(ЭтоОтчет, ВнешниеОтчеты, ВнешниеОбработки);
ИмяОбъекта = Менеджер.Подключить(АдресДанных, , Истина, ОбщегоНазначения.ОписаниеЗащитыБезПредупреждений());
ВнешнийОбъект = Менеджер.Создать(ИмяОбъекта);
ВнешнийОбъектМетаданные = ВнешнийОбъект.Метаданные();
ОбработкаСведения = ВнешнийОбъект.СведенияОВнешнейОбработке();
Если ОбработкаСведения.Наименование = Неопределено ИЛИ ОбработкаСведения.Информация = Неопределено Тогда
Если ОбработкаСведения.Наименование = Неопределено Тогда
ОбработкаСведения.Наименование = ВнешнийОбъектМетаданные.Представление();
КонецЕсли;
Если ОбработкаСведения.Информация = Неопределено Тогда
ОбработкаСведения.Информация = ВнешнийОбъектМетаданные.Комментарий;
КонецЕсли;
КонецЕсли;
ЗаполнитьЗначенияСвойств(СправочникОбъект, ОбработкаСведения, "Наименование, БезопасныйРежим, Версия, Информация");
// Выгрузка настроек команд, которые переопределяются администратором.
ПоискЗаданий = Новый Соответствие;
Для Каждого СтараяКоманда Из СправочникОбъект.Команды Цикл
Если ЗначениеЗаполнено(СтараяКоманда.РегламентноеЗаданиеGUID) Тогда
ПоискЗаданий.Вставить(ВРег(СтараяКоманда.Идентификатор), СтараяКоманда.РегламентноеЗаданиеGUID);
КонецЕсли;
КонецЦикла;
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("АдресДанныхОбработки", АдресДанных);
ПараметрыРегистрации.Вставить("ЭтоОтчет", ЭтоОтчет);
ПараметрыРегистрации.Вставить("ОтключатьКонфликтующие", Ложь);
ПараметрыРегистрации.Вставить("ИмяФайла", ФайлДляЗагрузки.Имя);
ПараметрыРегистрации.Вставить("ОтключатьПубликацию", Ложь);
СправочникОбъект.ИмяОбъекта = Неопределено;
СправочникОбъект.Публикация = Перечисления.ВариантыПубликацииДополнительныхОтчетовИОбработок.Используется;
СправочникОбъект.Вид = ПолучитьВидОбработкиПоСтроковомуПредставлениюВида(ОбработкаСведения.Вид);
Результат = ДополнительныеОтчетыИОбработки.ЗарегистрироватьОбработку(СправочникОбъект, ПараметрыРегистрации);
Если Не Результат.Успех И Результат.ИмяОбъектаЗанято Тогда
ПараметрыРегистрации.Вставить("ОтключатьКонфликтующие", Истина);
ПараметрыРегистрации.Вставить("Конфликтующие", Результат.Конфликтующие);
Результат = ДополнительныеОтчетыИОбработки.ЗарегистрироватьОбработку(СправочникОбъект, ПараметрыРегистрации);
КонецЕсли;
Если Не Результат.Успех Тогда
Если Результат.ИмяОбъектаЗанято Тогда
Результат.ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Имя ""%1"" занято объектами ""%2""'"),
ИмяОбъекта,
Строка(Результат.Конфликтующие));
КонецЕсли;
КонецЕсли;
СправочникОбъект.ХранилищеОбработки = Новый ХранилищеЗначения(ДвоичныеДанныеФайла);
СправочникОбъект.ИмяОбъекта = ВнешнийОбъектМетаданные.Имя;
СправочникОбъект.ИмяФайла = ФайлДляЗагрузки.Имя;
// Очистка и загрузка новых команд.
Для Каждого Команда Из СправочникОбъект.Команды Цикл
РегламентноеЗаданиеGUID = ПоискЗаданий.Получить(ВРег(Команда.Идентификатор));
Если РегламентноеЗаданиеGUID <> Неопределено Тогда
Команда.РегламентноеЗаданиеGUID = РегламентноеЗаданиеGUID;
ПоискЗаданий.Удалить(ВРег(Команда.Идентификатор));
КонецЕсли;
КонецЦикла;
// Удаление неактуальных заданий.
Для Каждого КлючИЗначение Из ПоискЗаданий Цикл
Попытка
Задание = РегламентныеЗаданияСервер.Задание(КлючИЗначение.Значение);
Задание.Удалить();
Исключение
ЗаписьЖурналаРегистрации(
ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(),
УровеньЖурналаРегистрации.Ошибка,
Метаданные.Справочники.ДополнительныеОтчетыИОбработки,
СправочникОбъект.Ссылка,
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при удалении задания ""%1"":%2'"),
КлючИЗначение.Значение,
Символы.ПС + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
КонецПопытки;
КонецЦикла;
Если ДополнительныеОтчетыИОбработки.ПроверитьГлобальнаяОбработка(СправочникОбъект.Вид) Тогда
ТаблицаОбъектовМетаданных = ДополнительныеОтчетыИОбработки.ПодключенныеОбъектыМетаданных(СправочникОбъект.Вид);
Для Каждого СтрокаТаблицы Из ТаблицаОбъектовМетаданных Цикл
РазделСсылка = СтрокаТаблицы.Ссылка;
СтрокаРаздела = СправочникОбъект.Разделы.Найти(РазделСсылка, "Раздел");
Если СтрокаРаздела = Неопределено Тогда
СтрокаРаздела = СправочникОбъект.Разделы.Добавить();
СтрокаРаздела.Раздел = РазделСсылка;
КонецЕсли;
КонецЦикла;
Иначе
Для Каждого ОписаниеНазначения Из ОбработкаСведения.Назначение Цикл
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ОписаниеНазначения);
Если ОбъектМетаданных = Неопределено Тогда
Продолжить;
КонецЕсли;
ОбъектНазначенияСсылка = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ОбъектМетаданных);
СтрокаНазначения = СправочникОбъект.Назначение.Найти(ОбъектНазначенияСсылка, "ОбъектНазначения");
Если СтрокаНазначения = Неопределено Тогда
СтрокаНазначения = СправочникОбъект.Назначение.Добавить();
СтрокаНазначения.ОбъектНазначения = ОбъектНазначенияСсылка;
КонецЕсли;
КонецЦикла;
КонецЕсли;
#КонецОбласти
Попытка
ОбновлениеИнформационнойБазы.ЗаписатьОбъект(СправочникОбъект, , Истина);
Исключение
ЕстьОшибки = Истина;
Прервать;
КонецПопытки;
КонецЕсли;
КонецЦикла;
Если ЕстьОшибки Тогда
ОтменитьТранзакцию();
Иначе
ЗафиксироватьТранзакцию();
КонецЕсли;
КонецПроцедуры
Функция ПолучитьВидОбработкиПоСтроковомуПредставлениюВида(СтроковоеПредставление) Экспорт
Если СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.ЗаполнениеОбъекта;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиОтчет() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.Отчет;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.ПечатнаяФорма;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиСозданиеСвязанныхОбъектов() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.СозданиеСвязанныхОбъектов;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиШаблонСообщения() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.ШаблонСообщения;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительнаяОбработка;
ИначеЕсли СтроковоеПредставление = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительныйОтчет() Тогда
Возврат Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительныйОтчет;
КонецЕсли;
КонецФункции
Функция НайтиДополнительныйОтчетОбработкуПоИмениОбъекта(ИмяОбъекта, ЭтоОтчет)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДополнительныеОтчетыИОбработки.Ссылка КАК Ссылка,
| ВЫБОР
| КОГДА ДополнительныеОтчетыИОбработки.Вид В (&ВидыОтчетов)
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ЭтоОтчет
|ИЗ
| Справочник.ДополнительныеОтчетыИОбработки КАК ДополнительныеОтчетыИОбработки
|ГДЕ
| ДополнительныеОтчетыИОбработки.ЭтоГруппа = ЛОЖЬ
| И ДополнительныеОтчетыИОбработки.ПометкаУдаления = ЛОЖЬ
| И ДополнительныеОтчетыИОбработки.ИмяОбъекта = &ИмяОбъекта
| И ВЫБОР
| КОГДА ДополнительныеОтчетыИОбработки.Вид В (&ВидыОтчетов)
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ = &ЭтоОтчет";
ВидыОтчетов = Новый Массив;
ВидыОтчетов.Добавить(Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительныйОтчет);
ВидыОтчетов.Добавить(Перечисления.ВидыДополнительныхОтчетовИОбработок.Отчет);
Запрос.УстановитьПараметр("ВидыОтчетов", ВидыОтчетов);
Запрос.УстановитьПараметр("ИмяОбъекта", ИмяОбъекта);
Запрос.УстановитьПараметр("ЭтоОтчет", ЭтоОтчет);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Ссылка;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Для ключевых частей алгоритма добавлены комментарии.
Если у Вас бардак в справочнике из-за обменов или некорректной работы со справочником программным образом, то типовые алгоритмы регистрации могут выдавать оповещения об ошибках или просто предупреждения о корректности настройки элементов.
Вот и все, задача решена!
Выводы
В итоге, внесение изменений в модули внешних обработок / отчетов сводятся к трем шагам:
- Выгрузка внешних обработок и отчетов из информационной базы в каталог на диске.
- Изменение модулей. Простые изменения можно выполнять с помощью стандартных возможностей конфигуратора по поиску и замене текстов модулей, а в сложных случаях нужно подходить индивидуально.
- Загрузка внешний отчетов и обработок обратно в информационную базу (соответствие файлов и элемента справочника устанавливается по коду элемента, который был записан ранее в имя файла. Последнее поведение может быть изменено по необходимости).
Пример ситуации, когда понадобилось массовое изменение внешних отчетов и обработок Вы также можете найти в публикации "Пакетная выгрузка / загрузка внешних отчетов и обработок".
Управлять внешними отчетами и обработками будет намного проще, если они будут храниться в GIT, а их изменения будут версионироваться. Но это уже совсем другая история.
А как Вы выполняете массовые изменения внешних отчетов и обработок?
Другие ссылки
Авторские разработки