Как в СКД разложить адрес на составляющие: город, улица, дом

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов в системе компоновки данных (СКД) программисты часто сталкиваются с необходимостью вывести адрес контрагента не одной длинной строкой, а в виде отдельных колонок: Индекс, Город, Улица, Дом. В современных конфигурациях 1С (таких как Управление нашей фирмой или Бухгалтерия предприятия 3.0) адрес хранится в виде сложной XML-строки или JSON-объекта. Просто вытащить эти данные запросом невозможно. В этой статье мы подробно разберем несколько эффективных способов решения этой задачи.

Понимание структуры хранения адреса

Прежде чем приступать к реализации, проанализируем, как 1С хранит контактную информацию. В регистре сведений КонтактнаяИнформация (или в табличных частях объектов) есть поле ЗначенияПолей. В нем содержится подробная структура адреса. Рассмотрим пример такой строки:


<КонтактнаяИнформация xmlns="http://www.v8.1c.ru/ssl/contactinfo">
  <Состав xsi:type="Адрес" Страна="РОССИЯ">
    <Состав xsi:type="АдресРФ">
      <СубъектРФ>Москва г</СубъектРФ>
      <Улица>Хлебозаводский проезд</Улица>
      <ДопАдрЭл><Номер Тип="1010" Значение="7"/></ДопАдрЭл>
    </Состав>
  </Состав>
</КонтактнаяИнформация>

Наша задача — извлечь из этой иерархии нужные нам теги и представить их в плоской таблице отчета.

Метод 1: Использование вычисляемых полей и функций БСП

Этот метод наиболее удобен, если вам нужно добавить всего пару полей в отчет. Мы воспользуемся возможностью СКД вызывать функции общих модулей. Разберем по шагам, как это настроить:

  1. Откроем схему компоновки данных и перейдем на закладку Вычисляемые поля.
  2. Добавим новое поле, например, Город.
  3. В колонке "Выражение" укажем вызов функции. В типовых конфигурациях на базе БСП (Библиотека стандартных подсистем) для этого хорошо подходит модуль УправлениеКонтактнойИнформацией.

Пример выражения для вычисляемого поля:

УправлениеКонтактнойИнформацией.СоставАдресаИзXML(ЗначенияПолей).Город

Важный нюанс: Прямой вызов через точку может не сработать, если функция возвращает Структуру, а не конкретное значение. В таком случае в общем модуле (лучше создать свой с признаком "Вызов сервера") следует написать небольшую "обертку":


Функция ПолучитьГородИзXML(ЗначенияПолей) Экспорт
    СтруктураАдреса = УправлениеКонтактнойИнформацией.АдресИзXML(ЗначенияПолей);
    Возврат СтруктураАдреса.Город;
КонецФункции

Проанализируем производительность этого метода: при большом количестве строк в отчете (тысячи контрагентов) вызов функции для каждой строки может замедлить формирование. Поэтому для больших отчетов рекомендуется использовать второй метод.

Метод 2: Набор данных «Объект» и программная подготовка таблицы

Рассмотрим более профессиональный и быстрый способ. Мы создадим в СКД второй набор данных, который заполним в коде модуля отчета. Это позволит нам один раз обработать массив всех адресов и передать готовую таблицу в компоновку.

Разберем алгоритм реализации:

  1. В схеме СКД создадим Набор данных - запрос (основной) и Набор данных - объект (дополнительный).
  2. В наборе данных "Объект" (назовем его ТаблицаАдресов) опишем колонки: Ссылка, Город, Улица, Дом.
  3. На закладке Связи наборов данных свяжем их по полю Ссылка (или Контрагент).

Теперь перейдем в модуль отчета и используем процедуру ПриКомпоновкеРезультата. Выясним, как программно передать данные:


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Получаем данные основным запросом
    Схема = ПолучитьМакетКомпоновки();
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    Макет = КомпоновщикМакета.Выполнить(Схема, КомпоновщикНастроек.ПолучитьНастройки(), ДанныеРасшифровки);
    
    // 2. Извлекаем ссылки контрагентов для получения их адресов
    // Здесь можно использовать временную таблицу или просто запрос к контактной информации
    Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, ЗначенияПолей ИЗ РегистрСведений.КонтактнаяИнформация ГДЕ Тип = ЗНАЧЕНИЕ(Перечисление.ТипыКонтактнойИнформации.Адрес)");
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // 3. Используем встроенный механизм БСП для массового разбора
    ТаблицаДляСКД = Новый ТаблицаЗначений;
    ТаблицаДляСКД.Колонки.Добавить("Ссылка");
    ТаблицаДляСКД.Колонки.Добавить("Город");
    ТаблицаДляСКД.Колонки.Добавить("Улица");
    
    Для Каждого Строка Из ТаблицаДанных Цикл
        НоваяСтр = ТаблицаДляСКД.Добавить();
        НоваяСтр.Ссылка = Строка.Ссылка;
        
        // Разбираем XML штатными средствами
        ДанныеАдреса = УправлениеКонтактнойИнформацией.АдресИзXML(Строка.ЗначенияПолей);
        НоваяСтр.Город = ДанныеАдреса.Город;
        НоваяСтр.Улица = ДанныеАдреса.Улица;
    КонецЦикла;

    // 4. Передаем таблицу в СКД
    ВнешниеНаборы = Новый Структура;
    ВнешниеНаборы.Вставить("ТаблицаАдресов", ТаблицаДляСКД);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(Макет, ВнешниеНаборы, ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Метод 3: Работа с JSON (для новых версий БСП)

Посмотрим на современные реалии: в последних версиях платформы 1С и БСП произошел переход на формат JSON для хранения контактной информации. Если вы обнаружили, что в поле ЗначенияПолей данные начинаются с фигурных скобок {, значит, используется JSON.

Для разбора такой строки в СКД следует использовать функцию:

УправлениеКонтактнойИнформациейСлужебный.СтруктураАдресаИзJSON(СтрокаJSON)

Проанализируем ситуацию: если ваша база данных достаточно старая, но обновлялась, в ней могут присутствовать адреса как в формате XML, так и в формате JSON. Чтобы отчет работал стабильно, рекомендуется использовать универсальный метод БСП:

УправлениеКонтактнойИнформацией.КонтактнаяИнформацияВФорматеJSON(ЗначенияПолей)

Эта функция определит формат источника и приведет его к единому виду, который затем легко превратить в структуру. Для быстрого поиска и изучения нужных процедур библиотеки пригодится справочник по методам БСП.

Оптимизация через виртуальные таблицы ФИАС

Существует еще один способ, который не требует парсинга строк. Если в базе ведется строгий учет по ФИАС (ГАР), то в таблице контактной информации хранятся идентификаторы адресных объектов (GUID). В этом случае мы можем в запросе СКД напрямую соединиться с таблицами адресного классификатора.

Рассмотрим структуру связей:

Этот метод считается самым правильным с точки зрения архитектуры данных, так как он исключает ошибки ручного ввода и всегда возвращает актуальные названия согласно официальному классификатору.

Итоги и рекомендации

Мы проанализировали основные способы разложения адреса в СКД. Подведем итоги:

Использование предложенных подходов позволит вам создавать профессиональные отчеты с детальной адресной информацией, сохраняя при этом высокую скорость работы системы.

← На главную