При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью вывести адрес контрагента не одной длинной строкой, а в виде отдельных колонок: Индекс, Город, Улица, Дом. В современных конфигурациях 1С (таких как Управление нашей фирмой или Бухгалтерия предприятия 3.0) адрес хранится в виде сложной XML-строки или JSON-объекта. Просто вытащить эти данные запросом невозможно. В этой статье мы подробно разберем несколько эффективных способов решения этой задачи.
Прежде чем приступать к реализации, проанализируем, как 1С хранит контактную информацию. В регистре сведений КонтактнаяИнформация (или в табличных частях объектов) есть поле ЗначенияПолей. В нем содержится подробная структура адреса. Рассмотрим пример такой строки:
<КонтактнаяИнформация xmlns="http://www.v8.1c.ru/ssl/contactinfo">
<Состав xsi:type="Адрес" Страна="РОССИЯ">
<Состав xsi:type="АдресРФ">
<СубъектРФ>Москва г</СубъектРФ>
<Улица>Хлебозаводский проезд</Улица>
<ДопАдрЭл><Номер Тип="1010" Значение="7"/></ДопАдрЭл>
</Состав>
</Состав>
</КонтактнаяИнформация>
Наша задача — извлечь из этой иерархии нужные нам теги и представить их в плоской таблице отчета.
Этот метод наиболее удобен, если вам нужно добавить всего пару полей в отчет. Мы воспользуемся возможностью СКД вызывать функции общих модулей. Разберем по шагам, как это настроить:
Город.УправлениеКонтактнойИнформацией.Пример выражения для вычисляемого поля:
УправлениеКонтактнойИнформацией.СоставАдресаИзXML(ЗначенияПолей).Город
Важный нюанс: Прямой вызов через точку может не сработать, если функция возвращает Структуру, а не конкретное значение. В таком случае в общем модуле (лучше создать свой с признаком "Вызов сервера") следует написать небольшую "обертку":
Функция ПолучитьГородИзXML(ЗначенияПолей) Экспорт
СтруктураАдреса = УправлениеКонтактнойИнформацией.АдресИзXML(ЗначенияПолей);
Возврат СтруктураАдреса.Город;
КонецФункции
Проанализируем производительность этого метода: при большом количестве строк в отчете (тысячи контрагентов) вызов функции для каждой строки может замедлить формирование. Поэтому для больших отчетов рекомендуется использовать второй метод.
Рассмотрим более профессиональный и быстрый способ. Мы создадим в СКД второй набор данных, который заполним в коде модуля отчета. Это позволит нам один раз обработать массив всех адресов и передать готовую таблицу в компоновку.
Разберем алгоритм реализации:
ТаблицаАдресов) опишем колонки: Ссылка, Город, Улица, Дом.Ссылка (или Контрагент).Теперь перейдем в модуль отчета и используем процедуру ПриКомпоновкеРезультата. Выясним, как программно передать данные:
Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// 1. Получаем данные основным запросом
Схема = ПолучитьМакетКомпоновки();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Макет = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
// 2. Извлекаем ссылки контрагентов для получения их адресов
// Здесь можно использовать временную таблицу или просто запрос к контактной информации
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, ЗначенияПолей ИЗ РегистрСведений.КонтактнаяИнформация ГДЕ Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)");
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// 3. Используем встроенный механизм БСП для массового разбора
ТаблицаДляСКД = Новый ТаблицаЗначений;
ТаблицаДляСКД.Колонки.Добавить("Ссылка");
ТаблицаДляСКД.Колонки.Добавить("Город");
ТаблицаДляСКД.Колонки.Добавить("Улица");
Для Каждого Строка Из ТаблицаДанных Цикл
НоваяСтр = ТаблицаДляСКД.Добавить();
НоваяСтр.Ссылка = Строка.Ссылка;
// Разбираем XML штатными средствами
ДанныеАдреса = УправлениеКонтактнойИнформацией.АдресИзXML(Строка.ЗначенияПолей);
НоваяСтр.Город = ДанныеАдреса.Город;
НоваяСтр.Улица = ДанныеАдреса.Улица;
КонецЦикла;
// 4. Передаем таблицу в СКД
ВнешниеНаборы = Новый Структура;
ВнешниеНаборы.Вставить("ТаблицаАдресов", ТаблицаДляСКД);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(Макет, ВнешниеНаборы, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(Результат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Посмотрим на современные реалии: в последних версиях платформы 1С и БСП произошел переход на формат JSON для хранения контактной информации. Если вы обнаружили, что в поле ЗначенияПолей данные начинаются с фигурных скобок {, значит, используется JSON.
Для разбора такой строки в СКД следует использовать функцию:
УправлениеКонтактнойИнформациейСлужебный.СтруктураАдресаИзJSON(СтрокаJSON)
Проанализируем ситуацию: если ваша база данных достаточно старая, но обновлялась, в ней могут присутствовать адреса как в формате XML, так и в формате JSON. Чтобы отчет работал стабильно, рекомендуется использовать универсальный метод БСП:
УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВФорматеJSON(ЗначенияПолей)
Эта функция определит формат источника и приведет его к единому виду, который затем легко превратить в структуру. Для быстрого поиска и изучения нужных процедур библиотеки пригодится справочник по методам БСП.
Существует еще один способ, который не требует парсинга строк. Если в базе ведется строгий учет по ФИАС (ГАР), то в таблице контактной информации хранятся идентификаторы адресных объектов (GUID). В этом случае мы можем в запросе СКД напрямую соединиться с таблицами адресного классификатора.
Рассмотрим структуру связей:
РегистрСведений.КонтактнаяИнформация к основному объекту.КонтактнаяИнформация.Идентификатор с таблицей Справочник.АдресныеОбъекты (или соответствующей виртуальной таблицей классификатора).Этот метод считается самым правильным с точки зрения архитектуры данных, так как он исключает ошибки ручного ввода и всегда возвращает актуальные названия согласно официальному классификатору.
Мы проанализировали основные способы разложения адреса в СКД. Подведем итоги:
УправлениеКонтактнойИнформацией), чтобы ваш код не "сломался" при очередном обновлении конфигурации.Использование предложенных подходов позволит вам создавать профессиональные отчеты с детальной адресной информацией, сохраняя при этом высокую скорость работы системы.