Get Latitude and Longitude of any place using Google Map API in SAP

SAP surprises us every day. Even after working for more than a decade, a new project or client will have some requirements which are unique and you need out of the box thinking and solution. The below post is a similar requirement where a client wanted to know the Geo Coordinates of any given place. He thought Google Map is free and readily available, so why not use it in SAP with ease.

Check below, if the user enters any address, he should get the latitude and longitude of that place.

Isn’t it a cool requirement?

How can we achieve this?

Simple, connect to Google Map Service (read API), scan through its content string and find your data. It needs some reading through the string, but this is really effective and easy solution.

Check this steps (detailed code is available at the end of the article below)

Concatenate your input address with the Google Maps API web address to get the client data.

Request the data. Check your cases (lower/upper) of the methods (they might be case sensitive).

Send the request.

Receive the response from Google API.

Now, you have the string content. Just look through the string at the right place and get the latitude/longitude information.

<location>  </location> are the opening and closing tag. We need to find the latitudes and longitudes in between these two tags.

Similarly <lat> </lat> and <lng> </lng> are the opening and closing tags for Latitude and Longitude respectively.

This is one example of the content file received from Google API. Looking at the data, it is very clear, where we can find the coordinates.

Also, he would show, how to open the two addresses in Google Map and show the distance in the browser. Please stay tuned.

And our code not only works for India address, it works for any address in the world. Let’s check an address in USA.

You can validate the coordinates in Google Map manually.

Here is the code snippet used for this post.

*-----------------------------------------------------------------------
* Author :    For www.sapspot.com
* Title  :    Get Latitude and Longitude of a place from Google API
*-----------------------------------------------------------------------
* Change History :
* Author         DATE       REQUEST#     DESCRIPTION
*--------------- ---------- ----------- -------------------------------
* SAPSPOT  05/22/2016              Intial Development
*-----------------------------------------------------------------------
REPORT  zsapspot_google_api NO STANDARD PAGE HEADING
                                   LINE-COUNT 132.
*&---------------------------------------------------------------------*
*& TYPE-POOLS
*&---------------------------------------------------------------------*
TYPE-POOLS: truxs, slis.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
PARAMETERS : p_add_f  TYPE c LENGTH 50.
 
*&---------------------------------------------------------------------*
*& Types and Data
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_dest,
         place_f TYPE c LENGTH 50,
         lat_f   TYPE c LENGTH 20,
         lng_f   TYPE c LENGTH 20,
       END OF ty_dest.
 
DATA: gt_dest     TYPE STANDARD TABLE OF ty_dest.
 
 
*&---------------------------------------------------------------------*
*& Start of Selection
*&---------------------------------------------------------------------*
START-OF-SELECTION .
 
* Get longitude and latitude
  PERFORM get_long_lat.
 
*&---------------------------------------------------------------------*
*& End of Selection
*&---------------------------------------------------------------------*
END-OF-SELECTION .
 
* Show Latitute and Longitude
  PERFORM display_lat_longitude.
*&---------------------------------------------------------------------*
*& Sub Routines
*&---------------------------------------------------------------------*
FORM get_long_lat .
 
  DATA:
    lv_http_client TYPE REF TO if_http_client,
    lv_content     TYPE string.
 
* Creation of new IF_HTTP_Client object
  PERFORM create_http_client CHANGING lv_http_client.
 
* Request and Get
  PERFORM http_client_request_get_method USING lv_http_client.
 
* Send the request
  PERFORM http_client_send USING lv_http_client.
 
* Retrieve the result
  PERFORM http_client_receive USING lv_http_client CHANGING lv_content.
 
* Get the actual coordinate using the content string
  PERFORM get_coordinates USING lv_content.
 
ENDFORM. " get_long_lat
*&---------------------------------------------------------------------*
*&      Form  CREATE_HTTP_CLIENT
*&---------------------------------------------------------------------*
*       Create HTTP Client
*----------------------------------------------------------------------*
FORM create_http_client CHANGING p_http_client TYPE REF TO if_http_client.
 
  DATA: lv_http_url TYPE string.
 
* Prepare the url of the address
  CONCATENATE
    'http://maps.google.com/maps/api/geocode/xml?address='
    p_add_f
    INTO lv_http_url .
 
* Get client from url
  CALL METHOD cl_http_client=>create_by_url
    EXPORTING
      url                = lv_http_url
    IMPORTING
      client             = p_http_client
    EXCEPTIONS
      argument_not_found = 1
      plugin_not_active  = 2
      internal_error     = 3
      OTHERS             = 4.
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_REQUEST_GET_METHOD
*&---------------------------------------------------------------------*
*       Request and Get Method
*----------------------------------------------------------------------*
FORM http_client_request_get_method USING p_http_client TYPE REF TO if_http_client..
* Request and Get
  p_http_client->request->set_header_field( name = '~request_method' value = 'GET' ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_SEND
*&---------------------------------------------------------------------*
*       Send request
*----------------------------------------------------------------------*
FORM http_client_send USING p_http_client TYPE REF TO if_http_client.
* Send the request
  p_http_client->send( ).
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  HTTP_CLIENT_RECEIVE
*&---------------------------------------------------------------------*
*       Get the string content
*----------------------------------------------------------------------*
FORM http_client_receive  USING    p_http_client TYPE REF TO if_http_client
                          CHANGING p_p_content   TYPE string.
* Reterive the result
  CALL METHOD p_http_client->receive
    EXCEPTIONS
      http_communication_failure = 1
      http_invalid_state         = 2
      http_processing_failed     = 3
      OTHERS                     = 4.
  p_p_content = p_http_client->response->get_cdata( ).
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_COORDINATES
*&---------------------------------------------------------------------*
*       Get Latitute Longitude Coordinate
*----------------------------------------------------------------------*
FORM get_coordinates  USING    p_p_content TYPE string.
 
* Local data declaration
  DATA: lv_url  TYPE c LENGTH 255,
        ls_dest TYPE ty_dest,
        moff    TYPE syst-tabix,
        moff1   TYPE syst-tabix,
        lv_len  TYPE syst-tabix,
        lv_lat  TYPE c LENGTH 20,
        lv_lng  TYPE c LENGTH 20.
 
*&---------------------------------------------------------------------*
*& Processing string
*&---------------------------------------------------------------------*
  DO .
* Find <location> text in the content string
    FIND '<location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
 
    IF sy-subrc = 0 .
* <location> is a 10 character string, hence adding 10
      moff = moff + 10 .
 
* Find closing tag </location> text in the content string
      FIND '</location>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <location> and </location>
      lv_len = moff1 - moff .
 
* We have seen the API string contet, so we know <lat> </lat> <lng> </lng> are there between
* <location> and </location>
*--------------------------------------------------------------------*
* ---------------Find latitude
*--------------------------------------------------------------------*
* Find string <lat>
      FIND '<lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
* <lat> is a 5 character string, hence adding 5
        moff = moff + 5 .
 
* Find closing tag </lat> text in the content string
        FIND '</lat>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <lat> and </lat>
        lv_len = moff1 - moff .
 
* Characters between <lat> </lat> will have the latitude coorniate
        lv_lat = p_p_content+moff(lv_len) .
 
* From place address
        ls_dest-place_f = p_add_f .
 
* Keep latitude in structure
        ls_dest-lat_f = lv_lat.
 
      ENDIF.
 
*--------------------------------------------------------------------*
* ---------------Find longitude
*--------------------------------------------------------------------*
* Find string <lng>
      FIND '<lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff .
      IF sy-subrc = 0 .
 
* <lng> is a 5 character string, hence adding 5
        moff = moff + 5 .
 
* Find closing tag </lng> text in the content string
        FIND '</lng>' IN SECTION OFFSET moff OF p_p_content IGNORING CASE MATCH OFFSET moff1 .
 
* Find the length of string between tag <lng> and </lng>
        lv_len = moff1 - moff .
 
* Characters between <lng> </lng> will have the latitude coorniate
        lv_lng = p_p_content+moff(lv_len) .
 
* Keep longitude in structure
        ls_dest-lng_f = lv_lng.
 
      ENDIF.
    ELSE.
 
      EXIT.
 
    ENDIF.
 
  ENDDO .
 
* Put in internal table to display later
  APPEND ls_dest TO gt_dest.
  CLEAR:ls_dest .
 
ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_LAT_LONGITUDE
*&---------------------------------------------------------------------*
*       Display Latitude and Longitude
*----------------------------------------------------------------------*
FORM display_lat_longitude .
 
  DATA:
    lr_alv       TYPE REF TO cl_salv_table,
    lr_columns   TYPE REF TO cl_salv_columns_table,
    lr_column    TYPE REF TO cl_salv_column,
    lr_functions TYPE REF TO cl_salv_functions_list,
    lr_display   TYPE REF TO cl_salv_display_settings,
    lr_layout    TYPE REF TO cl_salv_layout,
    ls_key       TYPE salv_s_layout_key,
    lr_sorts     TYPE REF TO cl_salv_sorts.
 
  " Check to make sure the internal table has data.
  IF lines( gt_dest ) > 0.
 
    TRY.
*       Create ALV instance
*       Use CALL METHOD since this is a static method
        CALL METHOD cl_salv_table=>factory
          IMPORTING
            r_salv_table = lr_alv
          CHANGING
            t_table      = gt_dest.
 
*       Get functions object and then set all the functions to be allowed
        lr_functions = lr_alv->get_functions( ).
        lr_functions->set_all( ).
 
        lr_columns = lr_alv->get_columns( ).
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'PLACE_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Place Name'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LAT_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Latitude'.
 
        CALL METHOD lr_columns->get_column
          EXPORTING
            columnname = 'LNG_F'
          RECEIVING
            value      = lr_column.
        CALL METHOD lr_column->set_short_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_medium_text
          EXPORTING
            value = ''.
        CALL METHOD lr_column->set_long_text
          EXPORTING
            value = 'Longitude'.
 
        lr_columns->set_optimize( ).
 
*       Set sort column
        lr_sorts = lr_alv->get_sorts( ).
        lr_sorts->clear( ).
 
*       This code is to get the layout, save the layout and display the layout
        lr_layout = lr_alv->get_layout( ).
        ls_key-report = sy-repid.
        lr_layout->set_key( ls_key ).
        lr_layout->set_default( ' ' ).
        lr_layout->set_save_restriction( cl_salv_layout=>restrict_none ).
 
        lr_display = lr_alv->get_display_settings( ).
        lr_display->set_striped_pattern( cl_salv_display_settings=>true ).
 
*       Now display the report as an ALV grid
        lr_alv->display( ).
 
      CATCH cx_salv_msg.
        WRITE: 'Error displaying grid CX_SALV_MSG!'(001).
 
      CATCH cx_salv_not_found.
        WRITE: 'Error displaying grid CX_SALV_NOT_FOUND!'(002).
 
      CATCH cx_salv_data_error.
        WRITE: 'Error displaying grid CX_SALV_DATA_ERROR!'(003).
 
      CATCH cx_salv_existing.
        WRITE: 'Error displaying grid CX_SALV_EXISTING!'(004).
 
    ENDTRY.
 
  ELSE.
    MESSAGE 'No data to display' TYPE 'I'.
    LEAVE LIST-PROCESSING.
 
  ENDIF.
 
ENDFORM.