воскресенье, 8 апреля 2018 г.

Узнаём адрес доставки у Яндекс

При работе с клиентами могут возникать проблемы с правильным определением адреса.

Менеджеры могут неправильно расслышать название города, улицы, номер дома.
А люди мало знакомые с географией и орфографией будут записывать адрес так как слышат.
Это в свою очередь может привести к доставке товара не по адресу, и ,как следствие, к потере клиента.
Электронные таблицы - удобный инструмент обработки заказов. Почему бы не сделать его ещё удобнее, подключив дополнительные возможности по проверке адресов клиента.
Яндекс предлагает широкие возможности использования сервисов, а особый интерес вызывает API карт. Как и любой, уважающий себя API, у него есть Java Script Api, чем грех не воспользоваться, прочитав условия использования.
В примерах приложений Яндекс есть как раз то что нам нужно - пример. Его и возьмём за основу.
Допустим у нас в таблице есть столбец с адресом доставки.

Нам необходима кнопка Получить адрес, к которой сможем привязать выполнение скрипта.
Сам скрипт -

function yandexMap() {
var cell=SpreadsheetApp.getActiveSheet().getActiveCell();
  if (cell.getColumn()!=11){ //здесь 11 - номер столбца с адресом
    SpreadsheetApp.getActive().toast("Необходимо выбрать столбец с адресом доставки", "Ошибка", 20)
    return;
  }
  var html = HtmlService.createHtmlOutputFromFile('yandexMap');
  SpreadsheetApp.getUi() 
      .showModalDialog(html, 'Проверка адреса');
}

function getAdress(adress){
  var cell=SpreadsheetApp.getActiveRange();
  cell.setValue(adress)
}

И это - весь скрипт. 
Волшебство начнётся когда мы создадим новый html файл там же в скриптах. Назвать его необходимо yandexMap.html  и конечно же заполнить:

<!DOCTYPE html>
<html>
<head>
    <title>Проверка при вводе адреса доставки</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
    <script src="https://yandex.st/jquery/2.2.3/jquery.min.js" type="text/javascript"></script>
    <script >
    ymaps.ready(init);

function init() {
    // Подключаем поисковые подсказки к полю ввода.
    var suggestView = new ymaps.SuggestView('suggest'),
        map,
        placemark;
    // При клике по кнопке запускаем верификацию введёных данных.
    $('#button').bind('click', function (e) {
        geocode();
    });
    function geocode() {
        // Забираем запрос из поля ввода.
        var request = $('#suggest').val();
        // Геокодируем введённые данные.
        ymaps.geocode(request).then(function (res) {
            var obj = res.geoObjects.get(0),
                error, hint;
            if (obj) {
                // Об оценке точности ответа геокодера можно прочитать тут: https://tech.yandex.ru/maps/doc/geocoder/desc/reference/precision-docpage/
                switch (obj.properties.get('metaDataProperty.GeocoderMetaData.precision')) {
                    case 'exact':
                        break;
                    case 'number':
                    case 'near':
                    case 'range':
                        error = 'Неточный адрес, требуется уточнение';
                        hint = 'Уточните номер дома';
                        break;
                    case 'street':
                        error = 'Неполный адрес, требуется уточнение';
                        hint = 'Уточните номер дома';
                        break;
                    case 'other':
                    default:
                        error = 'Неточный адрес, требуется уточнение';
                        hint = 'Уточните адрес';
                }
            } else {
                error = 'Адрес не найден';
                hint = 'Уточните адрес';
            }
            // Если геокодер возвращает пустой массив или неточный результат, то показываем ошибку.
            if (error) {
                showError(error);
                showMessage(hint);
            } else {
                showResult(obj);
            }
        }, function (e) {
            console.log(e)
        })
    }
    function showResult(obj) {
        // Удаляем сообщение об ошибке, если найденный адрес совпадает с поисковым запросом.
        $('#suggest').removeClass('input_error');
        $('#notice').css('display', 'none');
        var mapContainer = $('#map'),
        bounds = obj.properties.get('boundedBy'),
        // Рассчитываем видимую область для текущего положения пользователя.
            mapState = ymaps.util.bounds.getCenterAndZoom(
                bounds,
                [mapContainer.width(), mapContainer.height()]
            ),
        // Сохраняем полный адрес для сообщения под картой.
            address = [ obj.getAddressLine()].join(', '),
        // Сохраняем укороченный адрес для подписи метки.
            shortAddress = [obj.getThoroughfare(), obj.getPremiseNumber(), obj.getPremise()].join(' ');
        // Убираем контролы с карты.
        mapState.controls = [];
        // Создаём карту.
        createMap(mapState, shortAddress);
        // Выводим сообщение под картой.
        showMessage(address);
        google.script.run.getAdress(address);
    }
    function showError(message) {
        $('#notice').text(message);
        $('#suggest').addClass('input_error');
        $('#notice').css('display', 'block');
        // Удаляем карту.
        if (map) {
            map.destroy();
            map = null;
        }
    }
    function createMap(state, caption) {
        // Если карта еще не была создана, то создадим ее и добавим метку с адресом.
        if (!map) {
            map = new ymaps.Map('map', state);
            placemark = new ymaps.Placemark(
                map.getCenter(), {
                    iconCaption: caption,
                    balloonContent: caption
                }, {
                    preset: 'islands#redDotIconWithCaption'
                });
            map.geoObjects.add(placemark);
            // Если карта есть, то выставляем новый центр карты и меняем данные и позицию метки в соответствии с найденным адресом.
        } else {
            map.setCenter(state.center, state.zoom);
            placemark.geometry.setCoordinates(state.center);
            placemark.properties.set({iconCaption: caption, balloonContent: caption});
        }
    }
    function showMessage(message) {
        $('#message').text(message);
    }
}
</script>
    <style>
        html, body {
            position: relative;
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            font-size: 13px;
            font-family: sans-serif;
            overflow: hidden;
        }
        #messageHeader {
            height: 20px;
        }
        #footer {
            width: 376px;
            background-color: #f2f2ef;
            padding: 12px;
        }
        #message {
            height: 76px;
        }
        #map {
            height: 160px;
            width: 376px;
            margin: 0px 12px 18px 12px;
            position: relative;
        }
        #header {
            height: 28px;
            width: 376px;
            margin: 12px 10px 12px 12px;
        }
        #button {
            display: inline-block;
            font-size: 11px;
            color: rgb(68,68,68);
            text-decoration: none;
            user-select: none;
            padding: .2em 0.6em;
            outline: none;
            border: 1px solid rgba(0,0,0,.1);
            border-radius: 2px;
            background: rgb(245,245,245) linear-gradient(#f4f4f4, #f1f1f1);
            transition: all .218s ease 0s;
            height: 28px;
            width: 74px;
        }
        #button:hover {
            color: rgb(24,24,24);
            border: 1px solid rgb(198,198,198);
            background: #f7f7f7 linear-gradient(#f7f7f7, #f1f1f1);
            box-shadow: 0 1px 2px rgba(0,0,0,.1);
        }
        #button:active {
            color: rgb(51,51,51);
            border: 1px solid rgb(204,204,204);
            background: rgb(238,238,238) linear-gradient(rgb(238,238,238), rgb(224,224,224));
            box-shadow: 0 1px 2px rgba(0,0,0,.1) inset;
        }
        .input {
            height: 18px;
            margin-right: 10px;
            width: 277px;
            padding: 4px;
            border: 1px solid #999;
            border-radius: 3px;
            box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0);
            transition: .17s linear;
        }
       .input:focus {
            outline: none;
            border: 1px solid #fdd734;
            box-shadow: 0 0 1px 1px #fdd734;
        }
        .input_error, .input_error:focus {
            outline: none;
            border: 1px solid #f33;
            box-shadow: 0 0 1px 1px #f33;
        }
        #notice {
            position: absolute;
            left: 22px;
            margin: 0px;
            top: 44px;
            color: #f33;
            display: none;
        }
    </style>
</head>
<body>
<div id="header">
    <input type="text" id="suggest" class="input" placeholder="Введите адрес">
    <button type="submit" id="button">Проверить</button>
</div>
<p id="notice">Адрес не найден</p>
<div id="map"></div>
<div id="footer">
    <div id="message"></div>
</div>
</body>
</html>
Весь код был взят из примера яндекс, немного переработан чтобы уместить всё в одном файле, и самую малость изменён вывод адреса.
Остаётся на кнопку назначить скрипт yandexMap().
Получать адрес доставки таблица будет из вывода окна по нажатии на кнопку Проверить. Если введённый адрес существует (по мнению яндекс), то он будет копироваться в текущую ячейку.

Всё - теперь проверкой правильности адреса будет заниматься сам Яндекс:).

5 комментариев:

  1. Доброго времени суток
    Ругается на строчку - синтаксическая ошибка
    var cell=SpreadsheetApp.getActiveRange();

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Большое спасибо за замечание.
      Должно быть
      cell=SpreadsheetApp.getActiveSheet().getActiveCell();

      В статье поправил.

      Удалить
    2. К сожалению ошибка вновь возникает , могу я вам отправить пример документа?
      Также сейчас ищу на форумах подобные решения , увы в написании кода не селён

      Удалить
    3. Благодарю , теперь всё работает =)

      Удалить