Представленные в публикации процедуры были рождены потребностью сохранять настройки внешних обработок с возможностью последующего их использования на других компьютерах и в других информационных базах. Работают они, однако, не только для обработок, но и для любых других объектов 1С, имеющих реквизиты и табличные части. Сам я пользуюсь ими достаточно часто, при решении самых различных задач, потому решил поделиться, глядишь кому-нибудь пригодится. Так же, думаю, этот материал может быть полезен начинающим программистам как пример рекурсивного чтения структуры XML-файла, к тому же процедуры малы, просты и легко «допиливаются» под специфические задачи.
Сохранение производится процедурой СохранитьРеквизитыИТабличныеЧасти. В качестве параметров она принимает сохраняемый объект и имя файла. Ссылочные реквизиты сохраняются в виде GUID.
Процедура СохранитьРеквизитыИТабличныеЧасти (Объект, ИмяФайлаXML=Неопределено) Экспорт
ФайлXML = Новый ЗаписьXML;
ФайлXML.ОткрытьФайл(ИмяФайлаXML);
ФайлXML.ЗаписатьОбъявлениеXML();
ФайлXML.ЗаписатьНачалоЭлемента(«Root»);
ФайлXML.ЗаписатьАтрибут(«Объект»,Объект.Метаданные().Имя);
//Сохраняем реквизиты
Для Каждого Реквизит Из Объект.Метаданные().Реквизиты Цикл
ФайлXML.ЗаписатьНачалоЭлемента(«Реквизит»);
ФайлXML.ЗаписатьАтрибут(«Имя», Реквизит.Имя);
ТипЗначения = ТипЗнч(Объект[Реквизит.Имя]);
Если Не ТипЗначения = Тип(«Неопределено») Тогда
ФайлXML.ЗаписатьАтрибут(«ИмяТипа», XMLТип(ТипЗначения).ИмяТипа);
ФайлXML.ЗаписатьАтрибут(«URI», XMLТип(ТипЗначения).URIПространстваИмен);
КонецЕсли;
ФайлXML.ЗаписатьТекст(XMLСтрока(Объект[Реквизит.Имя]));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
//Сохраняем табличные части
Для Каждого ТЧ из Объект.Метаданные().ТабличныеЧасти Цикл
ФайлXML.ЗаписатьНачалоЭлемента(«ТабличнаяЧасть»);
ФайлXML.ЗаписатьАтрибут(«Имя», ТЧ.Имя);
Для Каждого СтрокаТЧ из Объект[ТЧ.Имя] Цикл
ФайлXML.ЗаписатьНачалоЭлемента(«ЭлементКоллекции»);
Для Каждого РеквизитТЧ Из ТЧ.Реквизиты Цикл
ФайлXML.ЗаписатьНачалоЭлемента(«Реквизит»);
ФайлXML.ЗаписатьАтрибут(«Имя», РеквизитТЧ.Имя);
ТипЗначения = ТипЗнч(СтрокаТЧ[РеквизитТЧ.Имя]);
Если Не ТипЗначения = Тип(«Неопределено») Тогда
ФайлXML.ЗаписатьАтрибут(«ИмяТипа», XMLТип(ТипЗначения).ИмяТипа);
ФайлXML.ЗаписатьАтрибут(«URI», XMLТип(ТипЗначения).URIПространстваИмен);
КонецЕсли;
ФайлXML.ЗаписатьТекст(XMLСтрока(СтрокаТЧ[РеквизитТЧ.Имя]));
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ФайлXML.ЗаписатьКонецЭлемента();
КонецЦикла;
Если Не ФайлXML=Null Тогда
ФайлXML.ЗаписатьКонецЭлемента();
ФайлXML.Закрыть();
КонецЕсли;
КонецПроцедуры
За чтение объекта отвечают процедуры ЗагрузитьРеквизитыИТабличныеЧасти и ЗагрузитьОбъектРекурсивно. Чтобы прочитать объект вызывается первая, ей передаются объект, который необходимо заполнить, и имя файла. Вторая является вспомогательной.
Процедура ЗагрузитьРеквизитыИТабличныеЧасти(Объект, ИмяФайлаXML=Неопределено) Экспорт
Если Не ИмяФайлаXML = Неопределено Тогда
ФайлXML = Новый ЧтениеXML;
ФайлXML.ОткрытьФайл(ИмяФайлаXML);
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект, ФайлXML.Имя);
КонецЕсли
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ЗагрузитьОбъектРекурсивно(ФайлXML, Объект, знач ИмяУзла)
ИмяТипа = «»;
ПространствоИмен = «»;
Пока ФайлXML.ПрочитатьАтрибут() Цикл
Если ФайлXML.Имя = «ИмяТипа» Тогда
ИмяТипа = ФайлXML.Значение;
ИначеЕсли ФайлXML.Имя = «URI» Тогда
ПространствоИмен = ФайлXML.Значение;
КонецЕсли;
КонецЦикла;
Пока ФайлXML.Прочитать() Цикл
Если ФайлXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ФайлXML.Имя = ИмяУзла Тогда
Возврат;
ИначеЕсли ФайлXML.ТипУзла = ТипУзлаXML.Текст Тогда
ТипОбъекта = ИзXMLТипа(ИмяТипа, ПространствоИмен);
Если НЕ ТипОбъекта = Неопределено тогда
Объект = XMLЗначение(ТипОбъекта, ФайлXML.Значение);
КонецЕсли;
ИначеЕсли ФайлXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяТекУзла = ФайлXML.Имя;
Если ФайлXML.Имя = «ЭлементКоллекции» Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект.Добавить(), ИмяТекУзла);
Иначе
Если ФайлXML.ПрочитатьАтрибут() Тогда
ЗагрузитьОбъектРекурсивно(ФайлXML, Объект[ФайлXML.Значение], ИмяТекУзла);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В приложенном файле демонстрационная обработка, позволяющая сохранить ссылочный объект БД в файл и заполнить объект из файла. Заполняемый объект должен быть того же типа, что и сохраненный, а также он должен быть предварительно создан, сохранен в ИБ и выбран в поле «Ссылка».
Конечно + но все это есть в выгрузка загрузка хмл. стандартной обработке.
Конечно, там это есть, и даже гораздо больше. Я же только лишь предложил минимальный механизм, который без лишних сложностей можно использовать в собственных разработках.
Рекомендую как пример работы с XML
Спасибо, очень хорошо, как пример вполне устраивает!
Отличный универсальный механизм. А нельзя как — то также регистры выгружать или там планы счетов? Выложите может код?
(5) Как-то необходимости не возникало. С регистрами много вопросов: весь регистр выкидывать или по отбору? или по запросу? и как загружать: только дописывать или очищать имеющиеся записи? Если бы мне поставили такую задачу — я бы сделал обработку с табличной частью, колонки которой повторяют структуру данных регистра, запросом выбрал бы нужные записи в ТЧ, а ее уже потом приведенным кодом выкинул в XML. Хотя, можно и непосредственно регистр обрабатывать. Почему, собственно, нет? Будет время — посмотрю.
Добавлено:
А лучше использовать универсальную выгрузку/загрузку XML — это задача самое для нее.
(7) Пожалуйста. Рад, что кому-то пригодилось.
Хм, Автор скорее всего не слышах про встроенный сериализатор, который позволяет сделать все тоже — только используя всего две строчки кода.
Хм, Автор скорее всего не слышах про встроенный сериализатор, который позволяет сделать все тоже — только используя всего две строчки кода.
поумничать решили?) автор все слышал, я уверен, для новичков (таких как я) пример в самый раз.
(9) Попробуйте сериализовать внешнюю обработку. Собственно, именно для сохранения реквизитов и ТЧ обработок этот код и писался. То, что можно выгружать и другие объекты БД — это побочный эффект.
Кроме того, не всегда можно обойтись сериализацией. Например, если идёт обмен XML-файлами со сторонней системой. В этом случае надо работать методами объектов Чтение-/ЗаписьXML. Можно, в принципе, и через DOM, но, честно говоря, не знаю, насколько реализация этой технологии в 1С справляется с большими файлами.
(10) Ну чего же поумничать. Просто в последнее время, на этом ресурсе все больше и больше тем которые описаны в типовых книгах 1С…
(11) Согласен, внешнюю обработку сериализовать штатными средствами не получится. Но можно использовать механизм хранения настроек в БД. Но я, если честно, не могу себе представить задачу где обходимо было бы сериализовать внешнюю обработку %)
DOM отлично справляется с довольно крупными файлами. Правда, проблема в том, что не так уж и часто найдешь тех, кто сможет граммотно это использовать со стороны сторонней системы.
(13)
Сохранение настроек средствами платформы, к сожалению, не отличается надёжностью. Хранить же настройки в БД не всегда целесообразно.
Данный механизм может использоваться
1. для надёжного хранения настроек вне базы;
2. если обработка содержит большое количество настроек, ну, например, загрузка данных сложной структуры из XLS-файла: сопоставили ячейки документа данным, обкатали на тестовой базе, сохранили настройки в XLS, перенесли в рабочую;
3. если нескольким пользователям необходимо работать с общим набором настроек;
4. транспорт данных в тех случаях, когда нецелесообразно заморачиваться с конвертацией;
5. внешнее хранение небольших объемов данных.
(14) Надежность хранение настроек в файлах, тоже довольно сомнительный момент. Но в целом Вы правы. Суть понятна. Спасибо.
(14) я сам аналогичным образом использую xml-файлы для сохранения настроек отчетов/обработок, т.к. более надежное хранение, можно передать настройки другому пользователю, на другой комп.
(14) А так сохранить настройки не проще?
(18)Ага, проще конечно. Но не всегда. Реквизиты так не выгрузить; если табличных частей больше одной — потребуется несколько файлов. В общем, каждой задаче — свой инструмент.
Плюсую за простоту и доступность представления информации. Взял себе код на заметку)
а как можно сделать с внешней обработкой, в ней реквизиты и табличные части выгружались???не сохраняя данные обработки, а также как документ.ве дь в обработке не получишь Объект.Метаданные()
(21)Ну почему же? У внешних обработок есть метаданные. Собственно, для обработок этот код и писался. Все работает.