Возникла у меня необходимость в существующем отчете на СКД, имеющем набор данных - запрос, изменить тип набора данных с запроса на объект - таблицу значений. Но при смене типа набора данных слетели все поля, роли, ресурсы, оформление – в общем все слетело.
Погуглил и нашел способ – редактирование xml- файла схемы компоновки данных в текстовом редакторе. А почему бы не написать обработку [1] для 1С [1], которая все сделает сама?
Предлагаю вместе создать такую обработку [1].
Итак, у нас xml – файл СКД, в котором присутствует набор данных – запрос (учтем, что в данном файле наборы данных могут быть не только на основании запросов, но и объектов, а также объединения). Файл получен, нажатием в конфигураторе кнопки «Сохранить схему в файл»:
Предлагаю на форме разместить два поля: первое для отображения наборов данных (тип ДеревоЗначений, т.к. объединение тоже может содержать различные наборы данных, то использование таблицы значений нам не подойдет), второе для отображения текста запроса набора данных-запрос(строка неограниченной длины, на форме многострочная):
Теперь организуем выбор и обработку [1] файла исходной схемы компоновки данных. Для этого создадим кнопку «Заполнить из файла», назначим ей событие при нажатии:
Процедура КоманднаяПанель1ЗаполнитьИзФайла(Кнопка) //Открытие диалога выбора файла Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); Диалог.ПолноеИмяФайла = ""; Диалог.Фильтр = "файлы СКД *.xml|*.xml"; Диалог.МножественныйВыбор = Ложь; Диалог.Заголовок = "Выберите файл СКД - ресурс"; Если Диалог.Выбрать() Тогда МассивФайлов = Диалог.ВыбранныеФайлы; Для Каждого ИмяФайла Из МассивФайлов Цикл ИсходныйФайл = ИмяФайла; КонецЦикла; Файл = Новый Файл(ИсходныйФайл); Если Файл.Существует() Тогда ЗаполнитьТЧ(ИсходныйФайл);//Чтение XML-файла и заполнение дерева наборов Иначе Сообщить("Не найден файл " + ИсходныйФайл); КонецЕсли; КонецЕсли; КонецПроцедуры
Процедура ЗаполнитьТЧ() рекурсивно формирует дерево наборов данных и создает колонки соответствующего элемента формы:
Процедура ЗаполнитьДерево(Позиция, НаборыДанных) Сч = 0; Для Каждого НаборДанных Из НаборыДанных Цикл Сч = Сч + 1; НовСтр = Позиция.Строки.Добавить(); ЗаполнитьЗначенияСвойств(НовСтр, НаборДанных); НовСтр.Номер = Сч; Если ЗначениеЗаполнено(НовСтр.Запрос) Тогда НовСтр.ТипНабора = "Запрос"; ИначеЕсли ЗначениеЗаполнено(НовСтр.ИсточникДанных) Тогда НовСтр.ТипНабора = "Объект"; Иначе НовСтр.ТипНабора = "Объединение"; //Т.к. объединение может содержать различные наборы, //то разберем набор-объединение по наборам данных ЗаполнитьДерево(НовСтр, НаборДанных.Элементы); КонецЕсли; КонецЦикла; КонецПроцедуры
Для того, чтобы в нижней части обработки в поле РасшифровкаСтроки отображался текст запроса текущего набора данных (если, конечно, этот набор даных-запрос) используем событие ПриАктивацииСтроки нашего дерева:
Процедура ДеревоНаборовПриАктивизацииСтроки(Элемент) ТекДанные = Элемент.ТекущиеДанные; Если ТекДанные.ТипНабора = "Запрос" Тогда РасшифровкаСтроки = ТекДанные.Запрос; ИначеЕсли ТекДанные.ТипНабора = "Объект" Тогда РасшифровкаСтроки = ТекДанные.ИмяОбъекта; Иначе РасшифровкаСтроки = ""; КонецЕсли; КонецПроцедуры
Теперь можно в дереве указать какие наборы заменять (установка флажка в колонке «Пометка» и имя объекта, содержащего данные в колонке «Имя объекта»), например, так:
Создадим кнопку «Сохранить СКД в файл как…», процедура, вызываемая по нажатию этой кнопки:
Процедура КоманднаяПанель1СохранитьВФайл(Кнопка) Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение); Диалог.ПолноеИмяФайла = ""; Диалог.Фильтр = "файлы СКД *.xml|*.xml"; Диалог.МножественныйВыбор = Ложь; Диалог.Заголовок = "Файл СКД исправленный"; Если Диалог.Выбрать() Тогда МассивФайлов = Диалог.ВыбранныеФайлы; Для Каждого ИмяФайла Из МассивФайлов Цикл КоррФайл = ИмяФайла; КонецЦикла; НовСКД = Новый СхемаКомпоновкиДанных; НовСКД = СКД; ВыполнитьЗамену(ДеревоНаборов.Строки, НовСКД.НаборыДанных); ЗаписьXML = Новый ЗаписьXML; ЗаписьXML.ОткрытьФайл(КоррФайл); СериализаторXDTO.ЗаписатьXML(ЗаписьXML, НовСКД); КонецЕсли; КонецПроцедуры
А вот и сама, так сказать, процедура-гвоздь программы ВыполнитьЗамену():
Процедура ВыполнитьЗамену(ДеревоНаборовСтроки, НовСКДНаборыДанных) Для Каждого Стр Из ДеревоНаборовСтроки Цикл Если Стр.Отметка Тогда НовыйНабор = НовСКДНаборыДанных.Вставить(Стр.Номер-1, Тип("НаборДанныхОбъектСхемыКомпоновкиДанных")); СтарыйНабор = НовСКДНаборыДанных[Стр.Номер]; ЗаполнитьЗначенияСвойств(НовыйНабор, СтарыйНабор); НовыйНабор.ИмяОбъекта = Стр.ИмяОбъекта; Для Каждого СтарыйНаборПоле ИЗ СтарыйНабор.Поля Цикл НовПоле = НовыйНабор.Поля.Добавить(ТипЗнч(СтарыйНаборПоле)); ЗаполнитьЗначенияСвойств(НовПоле ,СтарыйНаборПоле); КонецЦикла; НовСКДНаборыДанных.Удалить(СтарыйНабор); Иначе Если Стр.ТипНабора = "Объединение" Тогда ВыполнитьЗамену(Стр.Строки, НовСКДНаборыДанных[Стр.Номер-1].Элементы); КонецЕсли; КонецЕсли; КонецЦикла; КонецПроцедуры
Все очень просто, Обработка [1] (неуправляемые формы) прилагается – используйте.
При необходимости, не против добавить и на управляемых формах. Удачи…
Ссылки
[1] https://www.mykib.org/article/den-devyatyy-integriroval-samyy-bolshoy-katalog-razrabotok-dlya-platformy-1s
[2] https://www.mykib.org/tags/1s-8
[3] https://www.mykib.org/sites/default/files/downloads/smenatipovnaborovskd.zip
[4] https://www.mykib.org/users/mykiborg
[5] https://www.mykib.org/comment/20#comment-20
Комментарии
Часть2. На управляемых формах [5]