Карта в 1С: ключ API, координаты адресов и показ точек на форме

· 10 мин

Содержание

Загрузить карту в 1С 8.3 можно тремя способами: встроить онлайн-карту (Яндекс Карты, OpenStreetMap, 2ГИС) в поле HTML-документа на форме, загрузить точки и границы из файлов GeoJSON или KML в справочник, или нарисовать офлайн-схему штатным объектом платформы «Географическая схема». Для большинства задач — склады, клиенты, точки доставки — нужен первый вариант плюс геокодирование адресов.

Схема всегда одна: адрес превращается в координаты (широта и долгота), координаты хранятся в реквизитах справочника, а форма с картой рисует по ним метки. Ниже — код для каждого звена и настройки, без которых карта не заработает.

Подготовка: что нужно до загрузки карты

Сначала решите, откуда брать подложку и координаты. От этого зависят ключи, лимиты и код.

ИсточникЧто даётКлючОграничения
Яндекс Карты (JavaScript API и HTTP Геокодер)Подложка, метки, маршруты, точный поиск по российским адресамНуженСуточный лимит бесплатных запросов, условия лицензии
OpenStreetMap + LeafletПодложка и меткиНе нуженГеокодер Nominatim — не чаще 1 запроса в секунду
2ГИС APIПодложка, справочник организацийНуженСвои тарифы и условия
Географическая схема 1СВекторная схема регионов без интернетаНе нуженПодложки улиц нет, контуры рисуете сами

Что проверить перед стартом:

  • 🌐 Интернет на машинах пользователей. Онлайн-карту загружает поле HTML-документа на клиенте, а геокодер вызывает сервер 1С. Доступ к домену карт нужен в обоих местах.
  • 🗂 Где хранить координаты. Добавьте в справочник (контрагенты, склады, адреса доставки) два реквизита Широта и Долгота типа Число(10,6). Шести знаков после запятой хватает с запасом: это точность около 10 см.
  • 🔐 Права на доработку. Реквизиты, общий макет и форма добавляются в Конфигураторе. В типовой конфигурации на поддержке удобнее делать это расширением, чтобы не снимать конфигурацию с поддержки.
  • 🧾 Условия поставщика карт. Бесплатные тарифы обычно запрещают коммерческое использование или хранение результатов геокодирования. Прочтите лицензию до того, как заполните тысячи адресов.
Какой вариант карты вам нужен?

Ключ API: регистрация и безопасное хранение

Для Яндекс Карт ключ получают в кабинете разработчика Яндекса (developer.tech.yandex.ru). Порядок такой:

  1. Войдите под Яндекс ID организации, а не под личным аккаунтом сотрудника. Иначе при увольнении ключ уйдёт вместе с ним.
  2. Подключите продукт «JavaScript API и HTTP Геокодер».
  3. Скопируйте выданный ключ — строку из букв и цифр с дефисами.
  4. Через 15–30 минут ключ активируется. До этого карта может показывать ошибку ключа.

Один ключ покрывает и показ карты, и геокодирование. Но лимиты считаются суммарно: каждое открытие формы с картой и каждый запрос координат расходуют квоту.

Где держать ключ в 1С

Ключ не вписывают прямо в модуль или макет. Варианты:

  • Константа КлючЯндексКарт (тип Строка(100)). Просто, но ключ видит каждый, у кого есть право чтения константы.
  • Безопасное хранилище — если конфигурация построена на БСП, используйте ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище и ПрочитатьДанныеИзБезопасногоХранилища. Данные оттуда читаются только в привилегированном режиме на сервере.

Ключ для JavaScript API всё равно попадает в HTML-страницу на клиенте, и опытный пользователь его увидит. Поэтому заведите отдельный ключ под 1С. Если он утечёт, вы отзовёте его, не трогая ключ сайта.

Геокодирование: как превратить адрес в координаты

Геокодер получает текст адреса и возвращает точку. Запрос выполняется на сервере 1С через HTTPСоединение. Вот рабочая функция для общего серверного модуля:

Функция КоординатыПоАдресу(Адрес, КлючAPI) Экспорт

    Результат = Новый Структура("Широта, Долгота, Точность", 0, 0, "");

    Соединение = Новый HTTPСоединение("geocode-maps.yandex.ru", 443,,,, 30,
        Новый ЗащищенноеСоединениеOpenSSL);
    Ресурс = "/1.x/?format=json&results=1&apikey=" + КлючAPI
        + "&geocode=" + КодироватьСтроку(Адрес, СпособКодированияСтроки.КодировкаURL);
    Ответ = Соединение.Получить(Новый HTTPЗапрос(Ресурс));

    Если Ответ.КодСостояния <> 200 Тогда
        ВызватьИсключение СтрШаблон("Геокодер вернул код %1", Ответ.КодСостояния);
    КонецЕсли;

    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    Данные = ПрочитатьJSON(Чтение, Истина); // Истина — читать в Соответствие
    Чтение.Закрыть();

    Найдено = Данные["response"]["GeoObjectCollection"]["featureMember"];
    Если Найдено.Количество() = 0 Тогда
        Возврат Неопределено; // адрес не найден
    КонецЕсли;

    ГеоОбъект = Найдено[0]["GeoObject"];
    Части = СтрРазделить(ГеоОбъект["Point"]["pos"], " "); // "долгота широта"
    Результат.Долгота = Число(Части[0]);
    Результат.Широта  = Число(Части[1]);
    Результат.Точность = ГеоОбъект["metaDataProperty"]["GeocoderMetaData"]["precision"];

    Возврат Результат;

КонецФункции

Три приёма, на которых чаще всего спотыкаются:

  1. Порядок координат. Геокодер Яндекса отдаёт в поле pos сначала долготу, потом широту. А метка в JavaScript API по умолчанию ждёт [широта, долгота]. Перепутаете — офис из Москвы окажется в Сомали.
  2. Точность ответа. Поле precision показывает, насколько геокодер уверен: exact — точный дом, number — дом с похожим номером, near — соседний дом, street — только улица, other — населённый пункт или хуже. Сохраняйте его в отдельный реквизит и проверяйте вручную всё, что ниже near.
  3. Чистота адреса. Геокодер лучше понимает адрес с городом в начале: «Казань, ул. Баумана, 15». Индекс, «офис 305» и «вход со двора» мешают — обрезайте их перед запросом. Если адреса в базе уже заполнены по ФИАС через адресный классификатор, качество результата заметно выше.

Ручная проверка спорных точек

Спорные адреса удобно разбирать списком: отбор по реквизиту Точность со значениями street и other. Пользователь открывает элемент, двигает метку на карте вручную, и новые координаты сохраняются. Как принять клик из карты обратно в 1С — в разделе про форму.

Загрузка точек и зон из файлов GeoJSON, KML и CSV

Если точки уже есть в файле, геокодировать ничего не нужно. Типичные источники: конструктор карт Яндекса, QGIS, выгрузка из сервиса доставки, таблица от логиста.

ФорматКак устроенЧем читать в 1СПорядок координат
GeoJSONJSON, массив features с геометрией и свойствамиЧтениеJSON + ПрочитатьJSONдолгота, широта
KMLXML, элементы Placemark → Point → coordinatesЧтениеXML или ПостроительDOMдолгота, широта, высота
CSV / ExcelСтроки с колонками адреса или координатЧтениеТекста, ТабличныйДокументкак в колонках файла

Пример загрузки точек из GeoJSON. Файл пользователь передаёт с клиента во временное хранилище, функция получает его адрес:

&НаСервереБезКонтекста
Функция ЗагрузитьТочкиИзGeoJSON(АдресФайла)

    ИмяФайла = ПолучитьИмяВременногоФайла("geojson");
    ПолучитьИзВременногоХранилища(АдресФайла).Записать(ИмяФайла);

    Чтение = Новый ЧтениеJSON;
    Чтение.ОткрытьФайл(ИмяФайла, КодировкаТекста.UTF8);
    Данные = ПрочитатьJSON(Чтение, Истина);
    Чтение.Закрыть();
    УдалитьФайлы(ИмяФайла);

    Загружено = 0;
    Для Каждого Объект Из Данные["features"] Цикл
        Геометрия = Объект["geometry"];
        Если Геометрия = Неопределено Или Геометрия["type"] <> "Point" Тогда
            Продолжить;
        КонецЕсли;
        Координаты = Геометрия["coordinates"]; // [долгота, широта]
        Свойства = Объект["properties"];
        Имя = ?(Свойства = Неопределено, Неопределено, Свойства["name"]);

        Элемент = Справочники.ТочкиНаКарте.СоздатьЭлемент();
        Элемент.Наименование = ?(Имя = Неопределено, "Без названия", Строка(Имя));
        Элемент.Долгота = Координаты[0];
        Элемент.Широта  = Координаты[1];
        Элемент.Записать();
        Загружено = Загружено + 1;
    КонецЦикла;

    Возврат Загружено;

КонецФункции

Второй параметр ПрочитатьJSON (Истина) важен: ключи GeoJSON читаются в Соответствие. В Структуру прочитались бы не все — ключ с дефисом или с цифры в начале не годится в имя свойства.

Зоны доставки и границы

Полигоны (Polygon, MultiPolygon) построчно раскладывать не нужно. Сохраните геометрию целиком строкой JSON в реквизит Строка неограниченной длины. Форма с картой отдаст её в JavaScript как есть, а код на странице нарисует многоугольник.

Перед повторной загрузкой того же файла ищите элемент по внешнему идентификатору из properties (например, id), а не создавайте новый. Иначе каждая загрузка удвоит справочник.

Карта на форме 1С через поле HTML-документа

Онлайн-карта показывается в элементе формы «Поле HTML-документа». Его реквизит — строка с HTML-кодом страницы. Сделайте так:

  1. В Конфигураторе (или в расширении) создайте общий макет КартаHTML типа «Текстовый документ».
  2. Вставьте в макет шаблон страницы — он ниже.
  3. На форму добавьте реквизит ТекстКарты типа Строка без ограничения длины. Перетащите его на форму и выберите вид элемента «Поле HTML-документа».
  4. Растяните поле по ширине и высоте формы, иначе карта будет полоской в несколько пикселей.
  5. В ПриСозданииНаСервере подставьте в шаблон ключ и точки.

Шаблон страницы для макета:

<!DOCTYPE html>
<html><head><meta charset="utf-8">
<script src="https://api-maps.yandex.ru/2.1/?apikey=%APIKEY%&lang=ru_RU"></script>
<style>html, body, #map { width:100%; height:100%; margin:0; padding:0; }</style>
</head><body>
<div id="map"></div>
<a id="bridge" href="#" style="display:none"></a>
<script>
var points = %POINTS%;
ymaps.ready(function () {
  var map = new ymaps.Map('map', { center: [55.75, 37.62], zoom: 10 });
  points.forEach(function (p) {
    var mark = new ymaps.Placemark([p.lat, p.lon], { hintContent: p.name, balloonContent: p.name });
    mark.events.add('click', function () {
      var b = document.getElementById('bridge');
      b.setAttribute('data-id', p.id);
      b.click();
    });
    map.geoObjects.add(mark);
  });
  if (points.length > 0) {
    map.setBounds(map.geoObjects.getBounds(), { checkZoomRange: true });
  }
});
</script>
</body></html>

Серверная часть формы собирает массив точек и подставляет его в шаблон:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    Запрос = Новый Запрос("ВЫБРАТЬ Т.Ссылка, Т.Наименование, Т.Широта, Т.Долгота
        |ИЗ Справочник.ТочкиНаКарте КАК Т
        |ГДЕ Т.Широта <> 0 И НЕ Т.ПометкаУдаления");
    Выборка = Запрос.Выполнить().Выбрать();

    Точки = Новый Массив;
    Пока Выборка.Следующий() Цикл
        Точки.Добавить(Новый Структура("id, name, lat, lon",
            Строка(Выборка.Ссылка.УникальныйИдентификатор()),
            Выборка.Наименование, Выборка.Широта, Выборка.Долгота));
    КонецЦикла;

    Запись = Новый ЗаписьJSON;
    Запись.УстановитьСтроку();
    ЗаписатьJSON(Запись, Точки);

    Шаблон = ПолучитьОбщийМакет("КартаHTML").ПолучитьТекст();
    Шаблон = СтрЗаменить(Шаблон, "%APIKEY%", Константы.КлючЯндексКарт.Получить());
    ТекстКарты = СтрЗаменить(Шаблон, "%POINTS%", Запись.Закрыть());

КонецПроцедуры

Клик по метке: как открыть элемент справочника

Метка «нажимает» скрытую ссылку bridge, а 1С ловит это в обработчике ПриНажатии поля HTML-документа:

&НаКлиенте
Процедура ТекстКартыПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)

    Источник = ДанныеСобытия.Element;
    Если Источник = Неопределено Или Источник.id <> "bridge" Тогда
        Возврат;
    КонецЕсли;
    СтандартнаяОбработка = Ложь;
    ПоказатьЗначение(, СсылкаПоИдентификатору(Источник.getAttribute("data-id")));

КонецПроцедуры

&НаСервереБезКонтекста
Функция СсылкаПоИдентификатору(Идентификатор)
    Возврат Справочники.ТочкиНаКарте.ПолучитьСсылку(Новый УникальныйИдентификатор(Идентификатор));
КонецФункции

Тот же мост работает и для ручной правки: сделайте метку перетаскиваемой (draggable: true в опциях Placemark), а по событию dragend кладите новые координаты в атрибуты bridge и нажимайте его.

Если карта на форме пустая или белая, проверьте по порядку: открывается ли api-maps.yandex.ru в браузере на этом компьютере, активирован ли ключ, растянуто ли поле. На Windows в старых версиях платформы поле HTML-документа работало на движке Internet Explorer, и современный JavaScript API в нём не запускается. Помогает обновление платформы.

Географическая схема: карта в 1С без интернета

У платформы есть собственный объект для карт — «Географическая схема». Это векторный документ формата *.geo: слои, контуры регионов, точки и подписи. Подложки с улицами в нём нет, зато он работает без интернета и без ключей.

Где пригодится:

  • 📊 Раскраска регионов по выручке, числу клиентов, долгу.
  • 🏭 Схема складов и филиалов компании.
  • 🔌 Рабочие места без выхода в интернет.

Создают схему в Конфигураторе: Файл → Новый → Географическая схема. Контуры рисуют вручную или переносят из готовых схем. Готовую схему сохраняют макетом конфигурации. Данные к объектам схемы привязывают программно через объектную модель типа ГеографическаяСхема и показывают на форме в поле географической схемы.

Для учёта точек доставки по реальным адресам географическая схема не подходит: она не знает улиц и не геокодирует адреса. Её ниша — аналитика по территориям.

Автообновление координат по расписанию

Когда новые адреса появляются каждый день, геокодировать их вручную незачем. Заведите регламентное задание:

  1. В Конфигураторе добавьте регламентное задание ГеокодированиеАдресов. В качестве метода укажите экспортную процедуру общего серверного модуля.
  2. Процедура выбирает до 200 элементов без координат (Широта = 0), вызывает КоординатыПоАдресу и записывает результат.
  3. На каждый адрес — своя попытка: ошибка одного не должна останавливать всю пачку. Неудачные адреса помечайте, чтобы не запрашивать их снова каждую ночь.
  4. Расписание — раз в сутки ночью. Лимит в 200 адресов за запуск защищает суточную квоту ключа, которую расходует ещё и показ карты.
  5. В конфигурациях на БСП включите задание и проверьте его журнал в Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания.

Что учесть:

  • 🖥 Файловая база. Регламентные задания выполняются, только пока в базе открыт хотя бы один клиентский сеанс. Для ночного запуска нужен клиент-сервер или компьютер, на котором 1С остаётся открытой.
  • ✏️ Смена адреса. Обнуляйте координаты при изменении адреса в ПередЗаписью объекта. Тогда задание само пересчитает точку.
  • 🌍 Прокси. Если сервер 1С выходит в интернет через прокси, передайте объект ИнтернетПрокси в конструктор HTTPСоединение. Без этого геокодер вернёт ошибку соединения.
  • 📈 Контроль лимита. Код ответа 403 от геокодера обычно означает неверный или неактивный ключ либо исчерпанную квоту. Пишите такие ответы в журнал регистрации и останавливайте пачку, не долбя сервис дальше.
Перед запуском автогеокодирования
Выполнено: 0 / 6

Частые вопросы

Работает ли карта в веб-клиенте и тонком клиенте одинаково?
Поле HTML-документа есть в обоих. В веб-клиенте страница работает внутри браузера пользователя, поэтому скрипт карты грузится его средствами. Обработку клика по метке проверьте на том клиенте, где будут работать пользователи.
Можно ли использовать OpenStreetMap вместо Яндекса?
Да. В шаблон подключают библиотеку Leaflet и слой плиток OSM, ключ не нужен. Для геокодирования есть Nominatim, но его правила требуют не больше одного запроса в секунду и указания своего User-Agent, для массовой загрузки адресов он не годится.
Почему все метки оказались в одной точке или в океане?
Почти всегда перепутан порядок координат. GeoJSON, KML и поле pos геокодера Яндекса хранят долготу первой, а метка Яндекс Карт ждёт широту первой.
Можно ли проложить маршрут для курьера прямо в форме 1С?
Да, JavaScript API Яндекса умеет строить маршрут по нескольким точкам на стороне страницы. Учтите, что маршрутизация может требовать платного тарифа: уточните это в кабинете разработчика до разработки.
Сколько точек выдержит одна карта?
Сотни меток отображаются без проблем. Для тысяч включите кластеризацию меток в JavaScript API (ymaps.Clusterer) или показывайте только точки, отобранные по региону или менеджеру.