Вывод объектов на карту в 1С Предприятие: от адреса до интерфейса
Содержание
Карту в 1С делают двумя разными инструментами, и выбор зависит от задачи. Если нужно показать агрегаты по регионам России (продажи, остатки, точки присутствия) — подойдёт встроенный объект «Географическая схема», он работает без интернета и внешних ключей. Если нужны конкретные адреса контрагентов, улицы, маршруты и зоны доставки — карту подключают снаружи, через поле HTML-документа и JavaScript-API Яндекс.Карт или Google Maps.
Адреса в базе хранятся текстом, а карте нужны координаты. Поэтому между «адрес из справочника» и «точка на карте» всегда стоит один шаг — геокодирование: превращение строки адреса в пару «широта, долгота» через HTTP-запрос к сервису геокодера. Ниже — как это собрать целиком на управляемых формах платформы 8.3 в интерфейсе «Такси».
Какой инструмент выбрать и что подготовить
Сначала определитесь со способом — от этого зависит весь остальной код.
- 🗺️ Географическая схема — родной объект платформы. Кладётся на форму как поле, источник данных — файл разметки с расширением
.geo(карта регионов РФ, мира, отдельных областей). Удобна для картограмм: закрасить регионы по сумме продаж, показать пузыри по городам. Уличных адресов и спутниковых слоёв не умеет. - 🌐 Внешняя карта (Яндекс/Google) — HTML с JavaScript в поле HTML-документа. Умеет всё: точные адреса, метки, кластеры, маршруты, полигоны зон. Требует интернет на клиенте и API-ключ сервиса.
Для отчёта «выручка по субъектам РФ» берите географическую схему — это пять минут без ключей. Для «показать на карте всех клиентов и построить маршрут курьера» — только внешнюю карту.
Что нужно подготовить до кода:
- Источник точек — реквизит или справочник с адресами либо уже готовыми координатами. Если координат нет, добавьте в справочник (например, «Контрагенты» или «Склады») два реквизита типа
Числос достаточной точностью:ШиротаиДолгота. - Для внешней карты — API-ключ. У Яндекса ключи оформляются в кабинете разработчика, причём ключ для JavaScript-API и ключ для HTTP-геокодера — разные. Храните их в константах или в справочнике настроек, а не в коде модуля.
- Проверьте, что на клиентских машинах есть доступ в интернет к доменам сервиса — через прокси многие организации его режут.
.geo, без интернета и ключей. Раскраска регионов по значению.Географическая схема без интернета
Самый быстрый результат, если хватает уровня «регион».
- На управляемую форму добавьте реквизит типа «Географическая схема» и выведите одноимённое поле.
- В конфигураторе или программно загрузите в неё разметку:
ГеографическаяСхема.Прочитать(ИмяФайлаGeo). Файлы разметки регионов России идут в составе демо-конфигураций и в поставке платформы. - Разметка состоит из серий и слоёв. Серия — это ваш показатель (например, «Выручка»), объект серии — конкретный регион. Значения расставляются в цикле по данным запроса.
Пример заливки значений по регионам из результата запроса:
Схема = Элементы.ПолеГеоСхемы.ЗначениеПоля;
ВыборкаРегионов = РезультатЗапроса.Выбрать();
Пока ВыборкаРегионов.Следующий() Цикл
Объект = Схема.НайтиОбъект(ВыборкаРегионов.КодРегиона);
Если Объект <> Неопределено Тогда
Объект.УстановитьЗначение("Выручка", ВыборкаРегионов.Сумма);
КонецЕсли;
КонецЦикла;
Названия методов разметки зависят от версии файла .geo; если точного имени не знаете, читайте структуру схемы в отладчике, а не угадывайте. Главное — механика: нашли объект-регион по коду, присвоили ему число, платформа раскрасила.
Географическая схема не требует согласования с Яндексом и не отправляет данные наружу — это её сильная сторона для внутренней аналитики.
Настройка HTTP-соединения к геокодеру
Для внешней карты всё начинается с получения координат. Геокодер — это HTTP-сервис: вы отправляете адрес строкой, получаете JSON с координатами.
Соединение по HTTPS собирается через HTTPСоединение с защищённым соединением OpenSSL. Адрес обязательно кодируется в URL — иначе пробелы и кириллица сломают запрос.
Функция ЗапроситьГеокодер(Адрес, Ключ)
Защита = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение("geocode-maps.yandex.ru", 443, , , , 30, Защита);
Ресурс = "/1.x/?apikey=" + Ключ
+ "&format=json&results=1&geocode="
+ КодироватьСтроку(Адрес, СпособКодированияСтроки.КодировкаURL);
Запрос = Новый HTTPЗапрос(Ресурс);
Попытка
Ответ = Соединение.Получить(Запрос);
Исключение
Возврат Неопределено; // нет сети, таймаут, недоступен хост
КонецПопытки;
Если Ответ.КодСостояния <> 200 Тогда
Возврат Неопределено; // 403 — неверный ключ, 429 — превышен лимит
КонецЕсли;
Возврат Ответ.ПолучитьТелоКакСтроку();
КонецФункции
Разберём параметры:
30в конструкторе — таймаут в секундах. Без него зависший сервис подвесит весь сеанс пользователя.КодСостояниявсегда проверяйте.403— чаще всего неверный или непривязанный к домену ключ,429— вы упёрлись в суточный лимит запросов.- Геокодер — платный коммерческий сервис с лимитами. Не ставьте вызов геокодера в цикл по всему справочнику без задержки и кэширования — ключ заблокируют за превышение.
Запрос к геокодеру выполняется на сервере 1С (&НаСервере), а не на клиенте: на клиенте HTTPСоединение работать может, но ключ и интернет-доступ логичнее держать на стороне сервера.
Геокодирование: из адреса в координаты
Ответ геокодера — вложенный JSON. Нужные координаты лежат глубоко, но путь к ним стабильный.
Функция КоординатыИзОтвета(ТелоСтрокой)
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТелоСтрокой);
Данные = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
Коллекция = Данные["response"]["GeoObjectCollection"]["featureMember"];
Если Коллекция.Количество() = 0 Тогда
Возврат Неопределено; // адрес не распознан
КонецЕсли;
Поз = Коллекция[0]["GeoObject"]["Point"]["pos"]; // строка "долгота широта"
Части = СтрРазделить(Поз, " ", Ложь);
Результат = Новый Структура;
Результат.Вставить("Долгота", Число(Части[0]));
Результат.Вставить("Широта", Число(Части[1]));
Возврат Результат;
КонецФункции
Три момента, на которых спотыкаются чаще всего:
- 📍 В поле
posгеокодер отдаёт координаты в порядке «долгота широта» (сначала X, потом Y). А вот JavaScript-API карты принимает их наоборот — «широта долгота». Перепутаете — метка уедет в другое полушарие. - Пустой
featureMemberозначает, что адрес не распознан. Такой адрес нужно пометить и дать оператору поправить вручную, а не писать в базу нули. Число(Части[0])корректно читает дробь с точкой, потому что геокодер отдаёт формат с десятичной точкой, а не запятой.
Полученные широту и долготу сохраните в реквизиты справочника. Тогда повторное построение карты пойдёт без обращения к сети — координаты уже в базе.
Отображение карты в поле HTML-документа
Теперь выводим точки. На форму кладётся поле HTML-документа, связанное с реквизитом формы типа Строка неограниченной длины (назовём его HTMLКарты). В этот реквизит пишется готовая HTML-страница с картой.
Самый надёжный способ передать точки в карту — сразу вставить их в JavaScript как массив при формировании HTML-строки на сервере. Без хрупких мостов между 1С и DOM.
&НаСервере
Процедура СформироватьКарту(ТочкиJSON)
Макет = "<!DOCTYPE html><html><head><meta charset='utf-8'>
|<script src='https://api-maps.yandex.ru/2.1/?apikey=КЛЮЧ&lang=ru_RU'></script>
|<style>html,body,#map{width:100%;height:100%;margin:0}</style></head>
|<body><div id='map'></div><script>
|var points = %1;
|ymaps.ready(function(){
| var map = new ymaps.Map('map', {center:[55.76,37.64], zoom:10});
| points.forEach(function(p){
| map.geoObjects.add(new ymaps.Placemark([p.lat, p.lon], {balloonContent:p.name}));
| });
|});
|</script></body></html>";
HTMLКарты = СтрШаблон(Макет, ТочкиJSON);
КонецПроцедуры
Здесь ТочкиJSON — это строка вида [{"lat":55.75,"lon":37.61,"name":"Склад №1"}], которую вы собираете из справочника через ЗаписьJSON. Обратите внимание: в метку Placemark координаты идут как [lat, lon] — тот самый обратный порядок относительно геокодера.
Чтобы карта подхватила изменения, после записи строки платформа сама перерисует поле HTML-документа. Если нужно реагировать на готовность страницы (например, дождаться загрузки API перед вызовом), используйте событие поля «Документ сформирован».
Чтобы метки не слипались при сотнях точек, подключайте кластеризатор Яндекса (ymaps.Clusterer) — он сам группирует близкие метки в бабл с числом.
Для Google Maps схема та же: меняется только адрес подключаемого скрипта и имена классов (google.maps.Map, google.maps.Marker). Выбор между Яндексом и Google обычно диктует география бизнеса и условия лицензий API.
Маршруты и зоны доставки
Две самые частые надстройки над картой — маршрут между точками и полигон зоны обслуживания.
Маршрут строится мультимаршрутизатором. Передаёте массив точек (адресами или координатами), API сам прокладывает путь и считает расстояние и время.
var route = new ymaps.multiRouter.MultiRoute(
{ referencePoints: [[55.75,37.61],[55.80,37.55]], params:{routingMode:'auto'} },
{ boundsAutoApply: true }
);
map.geoObjects.add(route);
Расстояние и длительность доступны в модели маршрута после его построения — их удобно сохранить в документ «Доставка» для расчёта стоимости.
Зона доставки — это полигон. Координаты вершин зоны вы задаёте один раз (обвели район на карте) и храните в базе. Проверку «попал ли адрес клиента в зону» выполняет геометрия полигона на стороне JS, а в 1С возвращается только результат — номер зоны или признак «вне зоны».
var zone = new ymaps.Polygon([[[55.70,37.50],[55.80,37.50],[55.80,37.70]]],
{}, {fillColor:'#1C7C5422', strokeWidth:2});
map.geoObjects.add(zone);
Для склада и курьерской логистики этого хватает: метки заказов, зоны ответственности, маршрут объезда на день.
Производительность и обработка ошибок
Карта на реальных данных упирается в два ограничения — лимиты геокодера и объём точек в браузере.
Кэшируйте координаты. Геокодируйте адрес один раз при записи элемента справочника, а не при каждом открытии карты. Если адрес не менялся — берите готовые широту и долготу из реквизитов. Это убирает 95% обращений к платному сервису.
Пакетное геокодирование делайте фоном. Массовую простановку координат по справочнику выносите в фоновое задание с паузой между запросами и счётчиком обработанных. Так вы не превысите суточный лимит и не подвесите пользователя.
Ограничивайте число меток. Несколько тысяч Placemark в браузере тормозят отрисовку. Для больших наборов включайте кластеризатор или грузите только точки, попавшие в текущую видимую область карты.
Типичные ответы геокодера и что с ними делать:
| Код / симптом | Причина | Что делать |
|---|---|---|
403 Forbidden | Ключ неверный или не привязан к домену/сервису | Проверить ключ в кабинете, убедиться, что это ключ геокодера, а не JS-API |
429 Too Many Requests | Превышен суточный лимит запросов | Включить кэш координат, разнести запросы во времени |
Пустой featureMember | Адрес не распознан | Пометить адрес на ручную проверку оператором |
| Метка не там, где адрес | Перепутан порядок координат | Геокодер даёт «долгота широта», карта ждёт «широта долгота» |
| Пустое поле HTML | Нет интернета на клиенте или прокси режет домены API | Проверить доступ к доменам карты с рабочей станции |
Если карта вообще не рисуется и в поле HTML пусто — почти всегда дело не в коде 1С, а в сети: закрыт доступ к домену API-карт или не загрузился скрипт. Откройте адрес скрипта в браузере на той же машине.
Нужен ли платный ключ, чтобы показать карту в 1С?
Почему метка встаёт не на тот адрес?
pos возвращает «долгота широта», а JavaScript-API карты принимает «широта долгота». При переносе значения нужно менять местами.Где лучше хранить координаты — считать каждый раз или в базе?
Можно ли построить карту в толстом клиенте или только в тонком?
Как показать не точки, а территории — например, продажи по областям?
.geo. Внешние карты для картограмм по регионам избыточны, а схема раскрасит области по значению показателя без ключей и интернета.