Карта в 1С: ключ API, координаты адресов и показ точек на форме
Содержание
Загрузить карту в 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). Порядок такой:
- Войдите под Яндекс ID организации, а не под личным аккаунтом сотрудника. Иначе при увольнении ключ уйдёт вместе с ним.
- Подключите продукт «JavaScript API и HTTP Геокодер».
- Скопируйте выданный ключ — строку из букв и цифр с дефисами.
- Через 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"];
Возврат Результат;
КонецФункции
Три приёма, на которых чаще всего спотыкаются:
- Порядок координат. Геокодер Яндекса отдаёт в поле
posсначала долготу, потом широту. А метка в JavaScript API по умолчанию ждёт[широта, долгота]. Перепутаете — офис из Москвы окажется в Сомали. - Точность ответа. Поле
precisionпоказывает, насколько геокодер уверен:exact— точный дом,number— дом с похожим номером,near— соседний дом,street— только улица,other— населённый пункт или хуже. Сохраняйте его в отдельный реквизит и проверяйте вручную всё, что нижеnear. - Чистота адреса. Геокодер лучше понимает адрес с городом в начале: «Казань, ул. Баумана, 15». Индекс, «офис 305» и «вход со двора» мешают — обрезайте их перед запросом. Если адреса в базе уже заполнены по ФИАС через адресный классификатор, качество результата заметно выше.
Ручная проверка спорных точек
Спорные адреса удобно разбирать списком: отбор по реквизиту Точность со значениями street и other. Пользователь открывает элемент, двигает метку на карте вручную, и новые координаты сохраняются. Как принять клик из карты обратно в 1С — в разделе про форму.
Загрузка точек и зон из файлов GeoJSON, KML и CSV
Если точки уже есть в файле, геокодировать ничего не нужно. Типичные источники: конструктор карт Яндекса, QGIS, выгрузка из сервиса доставки, таблица от логиста.
| Формат | Как устроен | Чем читать в 1С | Порядок координат |
|---|---|---|---|
| GeoJSON | JSON, массив features с геометрией и свойствами | ЧтениеJSON + ПрочитатьJSON | долгота, широта |
| KML | XML, элементы 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-кодом страницы. Сделайте так:
- В Конфигураторе (или в расширении) создайте общий макет
КартаHTMLтипа «Текстовый документ». - Вставьте в макет шаблон страницы — он ниже.
- На форму добавьте реквизит
ТекстКартытипаСтрокабез ограничения длины. Перетащите его на форму и выберите вид элемента «Поле HTML-документа». - Растяните поле по ширине и высоте формы, иначе карта будет полоской в несколько пикселей.
- В
ПриСозданииНаСервереподставьте в шаблон ключ и точки.
Шаблон страницы для макета:
<!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: слои, контуры регионов, точки и подписи. Подложки с улицами в нём нет, зато он работает без интернета и без ключей.
Где пригодится:
- 📊 Раскраска регионов по выручке, числу клиентов, долгу.
- 🏭 Схема складов и филиалов компании.
- 🔌 Рабочие места без выхода в интернет.
Создают схему в Конфигураторе: Файл → Новый → Географическая схема. Контуры рисуют вручную или переносят из готовых схем. Готовую схему сохраняют макетом конфигурации. Данные к объектам схемы привязывают программно через объектную модель типа ГеографическаяСхема и показывают на форме в поле географической схемы.
Для учёта точек доставки по реальным адресам географическая схема не подходит: она не знает улиц и не геокодирует адреса. Её ниша — аналитика по территориям.
Автообновление координат по расписанию
Когда новые адреса появляются каждый день, геокодировать их вручную незачем. Заведите регламентное задание:
- В Конфигураторе добавьте регламентное задание
ГеокодированиеАдресов. В качестве метода укажите экспортную процедуру общего серверного модуля. - Процедура выбирает до 200 элементов без координат (
Широта = 0), вызываетКоординатыПоАдресуи записывает результат. - На каждый адрес — своя попытка: ошибка одного не должна останавливать всю пачку. Неудачные адреса помечайте, чтобы не запрашивать их снова каждую ночь.
- Расписание — раз в сутки ночью. Лимит в 200 адресов за запуск защищает суточную квоту ключа, которую расходует ещё и показ карты.
- В конфигурациях на БСП включите задание и проверьте его журнал в
Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания.
Что учесть:
- 🖥 Файловая база. Регламентные задания выполняются, только пока в базе открыт хотя бы один клиентский сеанс. Для ночного запуска нужен клиент-сервер или компьютер, на котором 1С остаётся открытой.
- ✏️ Смена адреса. Обнуляйте координаты при изменении адреса в
ПередЗаписьюобъекта. Тогда задание само пересчитает точку. - 🌍 Прокси. Если сервер 1С выходит в интернет через прокси, передайте объект
ИнтернетПроксив конструкторHTTPСоединение. Без этого геокодер вернёт ошибку соединения. - 📈 Контроль лимита. Код ответа 403 от геокодера обычно означает неверный или неактивный ключ либо исчерпанную квоту. Пишите такие ответы в журнал регистрации и останавливайте пачку, не долбя сервис дальше.