Geocode Business Partner with Google Maps

h4. Create Database Table for Geocoding Data I’ve put all development objects together in the Package ZBPGOOGLEMAP: Here I’ve created also the DB Table ZBPGEOCODE which will contain the Geocode information for a Business Partner (BP). To detect changes on the BP I also save Street, Street No., Postal Code and City in this table.
h4. Create Persistent class for Geocoding Data A long time ago I’ve read Thomas Jung (/people/thomas.jung/blog)’s Weblog on “[ABAP Persistent Classes: Coding without SQL | ABAP Persistent Classes: Coding without SQL]” but never tried it on my own. But here I’ve done it and created the Class ZCL_BPGEOCODE which is from Class Type “Persistent class”. All the rest is described in detail in the mentioned Blog. Be aware that you have to use the DB Table ZBPGEOCODE.
h4. Transform Google KML to ABAP I did not attend the ABAP Online Meet-up on Simple Transformations (Fifth ABAP Online Meet-up: Simple Transformations) but it inspired me to use this to transform the return of the Geocoding HTTP Request (http://www.google.com/apis/maps/documentation/#Geocoding_HTTP_Request) into an ABAP Structure. To test the Transformation I first downloaded the result of this request to my local drive: http://maps.google.com/maps/geo?q=Neurottstr.+15a,+Walldorf,+DE&output=xml&key=… h3. Implement the BSP * event handler for checking and processing user input and * for defining navigation DATA: ls_addressdata TYPE bapibus1006_address. IF NOT bp IS INITIAL. * Get leading zeros for BP Number CALL FUNCTION ‘BAPI_BUPA_GET_NUMBERS’ EXPORTING businesspartner = bp IMPORTING businesspartnerout = bp. * Get BP’s default address CALL FUNCTION ‘BAPI_BUPA_ADDRESS_GETDETAIL’ EXPORTING businesspartner = bp IMPORTING addressdata = ls_addressdata. * Prepare the address to display in marker CONCATENATE ls_addressdata-street ls_addressdata-house_no ‘ ‘ ls_addressdata-postl_cod1 ls_addressdata-city INTO address SEPARATED BY space. * Prepare the address as a Google Maps destination CONCATENATE ls_addressdata-street ls_addressdata-house_no ‘,’ ls_addressdata-postl_cod1 ls_addressdata-city INTO mapadd SEPARATED BY ‘%20’. * Get Users Address as the from address data: USER_ADDRESS type ADDR3_VAL. CALL FUNCTION ‘SUSR_USER_ADDRESS_READ’ EXPORTING user_name = sy-uname IMPORTING USER_ADDRESS = USER_ADDRESS. CONCATENATE USER_ADDRESS-street USER_ADDRESS-house_num1 ‘,’ USER_ADDRESS-post_code1 USER_ADDRESS-city1 INTO fromadd SEPARATED BY ‘%20’. * Check if Geocoding for address already exists DATA: geocode TYPE zbpgeocode. DATA: connection TYPE REF TO zcl_bpgeocode, agent TYPE REF TO zca_bpgeocode. DATA: exc TYPE REF TO cx_root, getgeocode TYPE flag, updategeocode TYPE flag. agent = zca_bpgeocode=>agent. TRY. * Get Persistence Object by Key connection = agent->get_persistent( i_partner = bp ). * Has the Address been changed? IF ls_addressdata-street = connection->get_street( ) AND ls_addressdata-house_no = connection->get_house_no( ) AND ls_addressdata-postl_cod1 = connection->get_postl_cod1( ) AND ls_addressdata-city = connection->get_city( ). geocode-lon = connection->get_lon( ). geocode-lat = connection->get_lat( ). geocode-alt = connection->get_alt( ). ELSE. * Address was changed and needs to be updated getgeocode = ‘X’. updategeocode = ‘X’. ENDIF. * Object does not exist. So we have to get the geocode CATCH cx_root INTO exc. getgeocode = ‘X’. ENDTRY. IF getgeocode = ‘X’. * HTTP Client according to * BSP: Create a weather magnet using xml feed from weather.com DATA: client TYPE REF TO if_http_client, url TYPE string, c_xml TYPE string. * Build URL to call Googe Maps Geocoding url = ‘http://maps.google.com/maps/geo?q=‘. IF NOT ls_addressdata-house_no IS INITIAL. CONCATENATE url ls_addressdata-house_no ‘+’ INTO url. ENDIF. CONCATENATE url ls_addressdata-street ‘,’ INTO url. CONCATENATE url ls_addressdata-postl_cod1 ‘,’ ls_addressdata-city ‘,’ ls_addressdata-countryiso ‘&output=xml’ ‘&key=…’ INTO url. ****Create the HTTP client CALL METHOD cl_http_client=>create_by_url EXPORTING url = url IMPORTING client = client EXCEPTIONS OTHERS = 1. client->send( ). client->receive( ). ****Get the response content in Character format c_xml = client->response->get_cdata( ). ****Transform XML to ABAP Values CALL TRANSFORMATION zgoogle_geocode_to_abap SOURCE XML c_xml RESULT geocode = geocode. IF NOT geocode IS INITIAL. MOVE-CORRESPONDING ls_addressdata TO geocode. geocode-partner = bp. geocode-erzet = sy-uzeit. geocode-erdat = sy-datum. IF updategeocode = ‘X’. * Update Persistent Object connection->set_erzet( geocode-erzet ). connection->set_erdat( geocode-erdat ). connection->set_lon( geocode-lon ). connection->set_lat( geocode-lat ). connection->set_alt( geocode-alt ). connection->set_street( geocode-street ). connection->set_house_no( geocode-house_no ). connection->set_postl_cod1( geocode-postl_cod1 ). connection->set_city( geocode-city ). COMMIT WORK. ELSE. * Create Persistent Object TRY. connection = agent->create_persistent( i_partner = geocode-partner i_erdat = geocode-erdat i_erzet = geocode-erzet i_lon = geocode-lon i_lat = geocode-lat i_alt = geocode-alt i_street = geocode-street i_house_no = geocode-house_no i_postl_cod1 = geocode-postl_cod1 i_city = geocode-city ). COMMIT WORK. ENDTRY. ENDIF. ENDIF. ENDIF. ENDIF. * Only fill Mapcenter if geocode is valid IF NOT geocode IS INITIAL. DATA: lat type string, lon type string. * Prepere Latitude for Javascript IF geocode-lat < 0. geocode-lat = geocode-lat * -1. lat = geocode-lat. CONCATENATE ‘-‘ lat INTO lat. ELSE. lat = geocode-lat. ENDIF. * Prepere Longitude for Javascript IF geocode-lon < 0. geocode-lon = geocode-lon * -1. lon = geocode-lon. CONCATENATE ‘-‘ lon INTO lon. ELSE. lon = geocode-lon. ENDIF. CONCATENATE lat ‘,’ lon INTO mapcenter. ENDIF. Also here insert your own key to the generated URL. The result is this little BSP Application which provides a Map with a marker where our Business Partner is located.: After the extension suggested by Ranjan Kumar (https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.sdnbusinesscard?u=rm2di2raa5snpbq80kwe1g%3d%3d) the layout is now:
When you click on the “Directions” Link you see what Google suggests me to drive home.
Regards
Raja
What can I say...You always surprise me! -:D
Your blog is really great...On my of implementation projects...A company tried to do something like that for the IS-U system...But they didn't get even close to you...At first I tought that they work was great...After watching what can be done by mixing Google Maps and SAP...I just don't want to see those guys again..hehehe....Thanx for open my eyes to such a great application!
Greetings,
Blag.
thanks for that amazing comment. Perhaps when they tried to do it the Google Maps API was not avaliable?
Regards
Gregor
GMaps API is here for quite long time, however GMaps _Geocoding_ API was released less then week ago.
Hence Eddy and me stick with Yahoo Maps for "SDN World" (that includes geocoding from the very first day).
VS
will try to do the same with Yahoo Maps the next weekend. I like their interface because of the support of the mouse weel.
Regards
Gregor
Bravo!
you're like an "innovation machine" throwing out great ideas. Meanwhile I'm having troubles implementing all your solutions. Pls slow down 😉
Regards
Wolfgang
thx for sharing this veeeery nice example.
I immediately had a look at it myself and observed the following which is worth mentioning: Your detailed example addresses suggest a quality of address data which isn't met in general.
E.g, in Austria, you can't search for street names. Moreover, if you enter "Karlsplatz, Wien" or "Karlsplatz, Vienna" (which is the most central point in Vienna, Austria)it doesn't even give you some general geocodes for Vienna, Austria but it returns you NULL (that is 602 in the http request).
Now, the quality doesn't seem to be the same even for a city like, say, barcelona as in your example. what works for one street doesn't necessarily work for another street.
Well, that's definitely not your fault, but I think one has to be aware of that and maybe adopt your examples for the very likely probability, that a given BP adress returns NULL from the geocoding part.
regards,
anton
I've noticed this problem during my test. The best results I've got for Germany and the US. I will try Yahoo Maps and perhaps Map24 if they give better results.
Regards
Gregor
I have wroked in a GIS project before, with basic concepts of geocoding i found this blog really interesting.
Greetings,
Ashutosh Rastogi
Hi Gregor,<br/><br/> I have enhanced the functionality a little bit by adding Driving Directions to this application. I have added the following lines to the BSP Page:<br/><br/>GEvent.addListener(marker, "click", function() {<br/> marker.openInfoWindowHtml("<%= address %> <br/> [Directions | http://maps.google.com/maps?saddr=<%= fromadd%>&daddr=<%= mapadd%>]");<br/> });<br/> marker.openInfoWindowHtml("<%= address %> <br/> [Directions | http://maps.google.com/maps?saddr=<%= fromadd%>&daddr=<%= mapadd%>]");<br/> }<br/><br/>I had to add 2 additional Attributes (fromadd, mapadd) to the BSP Page as well.<br/><br/>Basically what this does is provide a Directions hyperlink in the Google Maps Balloon....<br/><br/>Thanks,<br/><br/>Ranjan
I've updated my Blog with your suggestion. I read the fromadd from the actual Users Company address. For more info have a look in the OnInputProcessing Event Handler.
Regards
Gregor
I implemented your blog and I got some strange results: I hope you can help me!
when I launch the application I get the first html page, where I enter BP number. Afterwards I get another html page, in which I can see just BP form.
But if I look at the html code, I've got all the informations I need from google maps.
In addition, I can tell you I'm calling my (your) BSP application from a private website of a company. But if I copy the same html page in a local page and I call it with a browser, gmaps is called correctly and the map is correctly shown!
But the page is exactly the same!!! Could it be that google blocks map visualization if I call it from inside a private company website?
Otherwise it can be a matter of checking events in BSP... but I'm quite sure I followed your blog properly.
Thank you in advance,
Sandro Cuzzolin
have you registered your Server with the full qualified hostname and do you use this hostname also in the application? Perhaps you have to the the Parameter icm/host_name_full as described in OSS Note 434918. Also Check that URL which is created in the Model Access Class uses the FQDN.
Regards
Gregor
Ciao,
AndreA
your Blogs are really amazing.
I tried to implement the same but ended up with some issues. I followed the same procedure as mentioned in your blog but when i ran the BSP Application the map appeared to be greyed out (not able to view the map). I debugged the program and found the values for business partner being fetched properly and everything was fine in it, but i don't know why it does'nt work.
Suggestion on this from your side would be greatly appreciated if there are any Basic Customizing to be done or any steps missing which I should have done.
Keep your great work going. expecting some wonderful blogs like this in future too.
Thanks,
Prashanth