Office integratie via OPEN XML API 1|
VNSG magazine 2014
Hans Gmelig Meyling NL4B
ABAP - Office integratie via OPEN XML API Office documenten en met name Excel sheets vormen een algemeen middel om data in SAP systemen te krijgen, of er uit te rapporteren. Al eeuwen biedt SAP mogelijkhedenheden om met OLE vanuit SAP te communiceren met MS-Office. In de SCN community zijn ABAP2XLSX en XLSX2ABAP libraries gepubliceerd. In de 7.02 nw releases van SAP zit echter standaard een API om te integreren met Excel, Word en Powerpoint. In deze tip een korte introductie. We richten ons om het behapbaar te houden uitsluitend op Excel import met behulp van de SAP class CL_OPENXML_PACKAGE.
XLSx, PPTx, DOCx, zijn ZIP bestanden Uitgangspunt van dit document is dat we de te lezen Excel sheet in binaire form hebben. Of dat nu met een upload, als payload in een bericht, als attachment in een mail of wat dan ook binnenkomt. Van belang is nu om te weten dat een XLSx bestandje eigenlijk een ZIP file is. We nemen bijvoorbeeld het volgende XLSx bestandje VNSG.xlsx, met daarin één sheet:
Zes cellen dus, A1, A2 en A3 met de waarde van 1, 2 resp 3, en B1, B2 en B3 met de (string!) waarde 1, 2 en 3. Hernoemen we de extensie van het bestand dat we hebben opgeslagen van *.xlsx naar *.zip, dan ziet het er als we het openen met ZIP (of als je het parset in Java, of wat dan ook) als volgt uit:
Office integratie via OPEN XML API 2|
VNSG magazine 2014
Hans Gmelig Meyling NL4B
Als we het simpel houden (kan altijd complexer) zitten de voor ons interessante gegevens in de bestanden /xl/worksheets/sheet1.xml:
en xl/sharedStrings.xml ...
Concreet: we vinden in worksheets\sheet1.xml elementen met naam row/c met attribute r="
" terug. Als attribute "s" van dit element gelijk is aan "1" dan betekent dit een verwijzing naar element volgnummer(row/c/v) in xl/sharedstrings (nb! element 0 is het eerste voorkomen van ...). Daar kunnen we dus wat mee als we inkomende XLSx bestanden ontzippen en de waarde op deze wijze uitlezen.
Office integratie via OPEN XML API 3|
VNSG magazine 2014
Hans Gmelig Meyling NL4B
Voor we verder gaan even een proof of concept voor DOCx bestanden. Bronbestand is HelloWord.docx (vindt FOO lekker):
Is als ZIP gelezen:
Lezen we word/document.xml
Dan toont dat dus hetzelfde concept ...
Office integratie via OPEN XML API 4|
VNSG magazine 2014
Hans Gmelig Meyling NL4B
Verwerking in ABAP Uitgangspunt hebben we al genoteerd, namelijk een binary xString (iv_excel in code hieronder) met de gehele XLSx. De basis begint nu met de factory cl_xlsx_document=>load_package( <xString> ), die een object teruggeeft van het type CL_OPENXML_PACKAGE. data objXLSX type ref to CL_OPENXML_PACKAGE . objXLSX = cl_xlsx_document=>load_package( iv_excel ).
objXLSX is een object met een iterator die de parts teruggeeft, en die parts zijn inderdaad de files die we al eerder terugzagen bij het openen van de zipfile. data lr_part data lr_parts data lv_partcount
type ref to cl_openxml_part. type ref to cl_openxml_partcollection, type i.
lr_parts = objXLSX->get_parts( ). lv_partcount = lr_parts->get_count( ).
lv_partcount = lr_workbook->get_parts( )->get_count( ). do lv_partcount times. sv_index = sy-index - 1. lv_uri = lr_workbook->get_parts( )->get_part( sv_index )-> get_uri( )->get_uri( ).
lv_uri is nu een string die het pad naar het bestand geeft. Er waren er meerdere, maar we waren vooralsnog alleen geïnteresseerd in '/xl/sharedstrings.xml' en '/xl/worksheets/sheet1.xml'. Daar moeten we door te loopen over de iterator de index van bepalen, en dan kunnen we ze lezen. xXmlsheet1
= lr_workbook->get_parts( )->get_part( ) ->get_data( ).
xXmlsharedst = lr_workbook->get_parts( )->get_part( ) ->get_data( ).
xXmlsheet1 en xXmlsharedst zijn hierbij xStrings die we kunnen parsen met de iXML classes. Zonder hier vervelend te willen worden in volledigheid (het is een tip, geen werkinstructie) een snippet voor het lezen van de shared string XML: lr_ixml = cl_ixml=>create( ). lr_ixml_document = lr_ixml->create_document( ). lr_ixml_stream_factory = lr_ixml->create_stream_factory( ). lr_ixml_istream = lr_ixml_stream_factory ->create_istream_xstring( xXmlsharedst ). lr_ixml_parser = lr_ixml->create_parser( document = lr_ixml_document istream = lr_ixml_istream stream_factory = lr_ixml_stream_factory ).
Office integratie via OPEN XML API 5|
VNSG magazine 2014
Hans Gmelig Meyling NL4B
lr_ixml_parser->parse( ). lr_ixml_istream->close( ). if lr_ixml_node_sst is bound. lr_ixml_node_silist = lr_ixml_node_sst->get_children( ). if lr_ixml_node_silist is bound. lv_nrof_sinodes = lr_ixml_node_silist->get_length( ). do lv_nrof_sinodes times. lv_sstidx = sy-index - 1. try. lv_value = lr_ixml_node_silist->get_item( lv_sstidx ) -get_first_child( )->get_value( ). // There it is!! catch cx_root. // any endtry. enddo. endif. endif.
Voor de worksheet zelf is het van hetzelfde laken, maar vergeet niet de waarde te vervangen door de gevonden sharedstring (als er een attribuut 's' was ...)!
Finally Het voorbeeld heb ik teasing en simpel gehouden, maar kan natuurlijk zo complex worden als je zelf wil. En zijn de ABAP2XLSX/XLSX2ABAP libraries hiermee nu overbodig geworden? Het antwoord daarop is dat die een compleet framework bieden, en bijvoorbeeld ook een uitgewerkt concept van styles ondersteunen. Dat kan je natuurlijk zelf gaan maken (kost tijd), en het leren (lees: doorgronden) van een library vergt ook tijd. Het charmante van de CL_OPENXML_PACKAGE is echter de uniformiteit van de oplossing, en de wijze waarop dat een maatwerkoplossing ondersteunt. Ik zou echter niet meer met OLE koppelingen aan de slag gaan. Al was het alleen maar om de specifieke ondersteuning van de SAPGUI die dat vereist. Hans Gmelig Meyling, September 2014
Literatuur, links en notes ABAP2XLSX library van Ivan Femia: SCN Startpage: http://wiki.scn.sap.com/wiki/display/ABAP/abap2xlsx GitHub: https://github.com/ivanfemia/abap2xlsx SCN blog van Benu Mariantony SCN: http://scn.sap.com/docs/DOC-33578