Professional Documents
Culture Documents
Applies to:
SAP NetWeaver 7.0 Enhancement Package 2 Onwards
Summary
This document provides a comprehensive introduction about XLSX files and a unified approach to upload
XLSX files into SAP GUI and Webdynpro ABAP. This gives you an overview of the following,
Author Bio
Benu Mariantony - Detail-oriented Senior SAP Technical Consultant with over 5 years' of
experience in SAP ABAP, ABAP Objects, ABAP Webdynpro, HR-ABAP, Interfacing,
ABAP XML Processing (XSLT and Simple Transformations) and upgrade. Skilled in both
the "object" and the classical sides of ABAP stream, focusing on technical arena involved
dynamic programming, design, optimization, and performance tuning. Currently, working
for Solution Manager 7.1, Component Monitoring BI at SAP Labs.
Table of Contents
Overview ........................................................................................................................................................... 3
Openness of Excel (XLSX Format) ............................................................................................................... 4
APIs for Office Applications ............................................................................................................................ 5
XLSX Import How to..................................................................................................................................... 6
Step 1 Read the path of uploaded file ................................................................................................... 6
Step 2 Load the file content..................................................................................................................... 6
Step 3 Loading the Package ................................................................................................................... 7
Step 4 Loading the parts of the Package .............................................................................................. 7
Step 5 Load the XMLs .............................................................................................................................. 7
Step 6 Process the XML Less ABAP More XSLT ......................................................................... 8
Processing the Sheet and Shared String XML .........................................................................................................................9
Overview
Every customer does their data maintenance in Excel and most of the SAP implementation or Support
projects would get a requirement to upload an excel file into SAP system either to store the data in data
dictionary or for reporting Predominantly to display the excel data in ALV/ in table control (in both SAP GUI
and Webdynpro).
Most of our SAP ABAP consultants would have thought about this business scenario and posted a lot of
threads in SCN too ;). I see a lot of SCN responses recommends the consultants to convert excel (XLS) file
to Tab Limited File or Comma Separated File (CSV) and to use GUI_UPLOAD for uploading the data into
internal table. Most of the threads on this subject are left unanswered.
Besides, each ABAP consultants would have tried uploading the data using the following renowned function
modules and somehow managed to complete the requirement. Have a gaze at the disadvantages in the
classical approach in the following tabular representation,
Table 1: This table illustrates the conventional SE37 function modules available to upload the excel file into our
application server.
In addition, the last three function modules are available as part of SAP_APPL component and hence those
are available only for logistics and accounting modules. The chances of using this three function module in
other modules like Solution Manager or CRM or SRM systems are not possible owing to their unavailability.
Furthermore, all the above Function Modules cannot be used in Webdynpro ABAP.
Beyond SAPs technical difficulties, Microsoft excel has its own restrictions as the total number of rows is
limited to 65,536 and the XLS format is stored in Binary format. Owing to all this complexities, until
NetWeaver 7.0, SAP does not offer any standard way to upload Microsofts proprietary excel.
As of NW 7.02 (NetWeaver 7.0 Enhancement Package 2), SAP does support the excel operations (Import/
Export) due to the openness of excel since Microsoft office 2007. Click here to know the difference between
XLS and XLSX files.
Each excel sheet and its cells are parsed as an XML document. Every strings in excel are uniquely stored in
a separate XML document sharedstrings.xml and those indexes are maintained in the respective sheet
XMLs whereas the integer values are maintained in the sheet XML itself. Have a glimpse of it in the following
screenshots,
Figure 2: The topmost view illustrates the schema of sheet XML and shared string XML and the how the mapping takes
place. The lower view is a snapshot captured from the excel file.
Thus, the effort of reading excel is much simplified and now all we need to do is to read multiple XML files
from XLSX package to populate an internal table.
Loads/ creates an XLSX document. This is the API we use in this document
CL_XLSX_DOCUMENT
to load the excel file into ABAP internal table.
CL_DOCX_DOCUMENT Loads/ creates an word document
CL_PPTX_DOCUMENT Loads/ creates presentations.
Table 2: Classes for reading office applications (Excel, document and power point)
The aforesaid steps are applicable for Webdynpro ABAP too by having Upload UI element in place.
This method gets you the path of the selected file in the string variable. You could achieve this using the
static method file_open_dialog in the class cl_gui_frontend_services,
AT SELECTION-SCREEN ON VALUE-REQUEST FOR filename.
This will get you a hexadecimal content. This could be also achieved using the removed GUI class, so called
cl_gui_frontend_services=>fui_upload. As this frontend classes is usable only in SAP GUI based
transactions (not for webdynpro), we use the XML helper class cl_openxml_helper, which could be used both
in SAP GUI programs and webdynpro applications.
Figure 3: The above screenshot refers to the different folder paths where user could locate the required XMLs to
populate the excel rows and columns.
The following code snippet would let you locate the exact XML file.
TRY.
mo_parts = mo_package->get_parts( ).
CATCH cx_openxml_format cx_openxml_not_found.
ENDTRY.
Method Implementation:
METHOD load_xml_data.
DATA lo_xml_part TYPE REF TO cl_openxml_part.
DATA lo_xml_part_uri TYPE REF TO cl_openxml_parturi.
DATA lv_uri TYPE string.
TRY.
lv_uri = mo_parts->get_part( 2 )->get_parts( )->get_part(
iv_xml_index )->get_uri( )->get_uri( ).
XSLT in ABAP: The SAP XSLT processor is already available as part of the kernel since Basis release 6.10
with the specifications defined for the XSLT version 1.0. XSLT has a capability to transform the following,
XML to XML
XML to ABAP Internal Table
ABAP Internal Tale to XML
ABAP Internal Table to ABAP Internal Table
Click here to know more about ABAP XSLT Programming and gaze at the examples too.
To create XSLT Programs in ABAP go to TCode SE80 Right Click on the Package Create Other (1)
Transformation Enter the name of the transformation and choose the type as XSLT.
Figure 4: Captured from SE80 transaction while attempting to create the XSLT transformation.
ENDTRY.
The internal table mt_spfli is the final internal table needs to be passed to the ALV.
Transformation Parameters Remarks
ZBEN_SHARED_STRING_DEL_NAMESP Source Shared String Removes the namespace of
XML Shared String XML. [we are
going to pass this XML as a
Result Shared String
parameter string to the main
XML without namespaces
xslt as passing the XML as a
parameter is forbidden]
ZBEN_XLSX_SHEET_IMPORT Source Sheet XML Processes the sheet data and
shared string data to populate
Parameter Shared
an ABAP internal table.
String XML without
namespace)
Result (LT_SPFLI)
ABAP Internal Table
Table 3: The details of created XSLT Transformation to read the XSLX file
Business Scenario
I have identified two scenarios one for SAP GUI and other for Webdynpro ABAP just to motivate you try out
this unified approach. You could use the same transformation for both the scenarios. Refer the subsequent
sections and try to make out the working scenario by referring to the code snippet showcased in the previous
sections. If you find any difficulties, please go through the complete code (ABAP and XSLT in the last
section)
Figure 5: Selection Screen captured from SAP GUI with a single parameter for uploading the excel file
Step 2: On hitting F8, the uplaoded excel file needs to be processed and display the data in the ALV as
shown below,
Figure 6: ALV which lists the Flight information which has been processed by our classes and transformation.
Figure 7: Webdynpro application with a FileUpload UI element and an button to upload the excel file.
Step 2: Click on Upload XLSX, the fine needs to be processed and displayed.
Figure 8: Webdynpro Table UI element which shows the uploaded data from the excel file.
Transformations
Name ZBEN_XLSX_REMOVE_NAMESPACE
Description Removes the namespaces available in all the nodes of the shared string XML
<xsl:strip-space elements="*"/>
<xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:element name="sst" namespace="">
<xsl:for-each select="ss:sst/ss:si">
<xsl:element name="si" namespace="">
<xsl:element name="t" namespace="">
<xsl:value-of select="ss:t"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Name ZBEN_XLSX_SHEET_IMPORT
Processes the Sheet XML and Shared String XML to populate the Internal Table.
Process Flow:
Description
1. Read the index from the sheet XML
2. Retrieve the cell content by reading the string available in shared string XML
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ss="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:sap="http://www.sap.com/sapxsl" xmlns:asx="http://www.sap.com/abapxml" exclude-
result-prefixes="c" version="1.0">
<xsl:param name="P_SHARED_STRING" select=""/>
<xsl:strip-space elements="*"/>
<xsl:output encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:variable name="V_SHARED_STRING">
<xsl:if test="$P_SHARED_STRING">
<xsl:copy-of select="$P_SHARED_STRING"/>
</xsl:if>
</xsl:variable>
<xsl:template match="/">
<asx:abap version="1.0">
<asx:values>
<LT_SPFLI>
<xsl:for-each select="ss:worksheet/ss:sheetData/ss:row">
<xsl:if test="position() > 1">
<item>
<CARRID>
<xsl:variable name="cell_id" select="concat('A', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</CARRID>
<CONNID>
<xsl:variable name="cell_id" select="concat('B', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</CONNID>
<COUNTRYFR>
<xsl:variable name="cell_id" select="concat('C', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</COUNTRYFR>
<CITYFROM>
<xsl:variable name="cell_id" select="concat('D', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<DEPTIME>
<xsl:variable name="cell_id" select="concat('J', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</DEPTIME>
<ARRTIME>
<xsl:variable name="cell_id" select="concat('K', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</ARRTIME>
<DISTANCE>
<xsl:variable name="cell_id" select="concat('L', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</DISTANCE>
<DISTID>
<xsl:variable name="cell_id" select="concat('M', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</DISTID>
<FLTYPE>
<xsl:variable name="cell_id" select="concat('N', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</FLTYPE>
<PERIOD>
<xsl:variable name="cell_id" select="concat('O', position())"/>
<xsl:variable name="v_index" select="ss:c[@r=$cell_id][@t='s']/ss:v"/>
<xsl:if test="$v_index">
<xsl:value-of select="$V_SHARED_STRING/sst/si[$v_index + 1]/t"/>
</xsl:if>
<xsl:if test="not($v_index)">
<xsl:value-of select="ss:c[@r=$cell_id]/ss:v"/>
</xsl:if>
</PERIOD>
</item>
</xsl:if>
</xsl:for-each>
</LT_SPFLI>
</asx:values>
</asx:abap>
</xsl:template>
</xsl:transform>
*&---------------------------------------------------------------------*
*& Report ZBEN_ALV_XLSX_UPLOAD
*&
*&---------------------------------------------------------------------*
*& Author : Benu Mariantony
*& Date Created : 16-Oct-2012
*& Desc : To upload the xlsx data into ALV grid
*&---------------------------------------------------------------------*
REPORT zben_alv_xlsx_upload.
lv_tmpfilename = cl_openxml_helper=>browse_local_file_open
( iv_title = 'Select XLSX File'
iv_filename = ''
iv_extpattern = 'All files(*.*)|*.*' ).
*----------------------------------------------------------------------*
* CLASS lcl_alv_xlsx_upload DEFINITION
*----------------------------------------------------------------------*
* Class Definitions for Excel Upload
*----------------------------------------------------------------------*
*----------------------------------------------------------------------*
* CLASS lcl_alv_xlsx_upload IMPLEMENTATION
*----------------------------------------------------------------------*
* Class Implementations for Excel Upload
*----------------------------------------------------------------------*
CLASS lcl_alv_xlsx_upload IMPLEMENTATION.
METHOD initialize.
DATA lo_xlsx TYPE REF TO lcl_alv_xlsx_upload.
lv_filename = iv_filename.
load_package( ).
transform_xml_to_abap( ).
ENDMETHOD. "read_xlsx
METHOD load_package.
TRY.
mo_package = cl_xlsx_document=>load_document( iv_data = mv_file_data ).
mo_parts = mo_package->get_parts( ).
CATCH cx_openxml_format cx_openxml_not_found.
ENDTRY.
ENDMETHOD. "load_package
METHOD load_xml_data.
DATA lo_xml_part TYPE REF TO cl_openxml_part.
DATA lo_xml_part_uri TYPE REF TO cl_openxml_parturi.
DATA lx_root TYPE REF TO cx_root.
DATA lv_uri TYPE string.
TRY.
lv_uri = mo_parts->get_part( 2 )->get_parts( )-
>get_part( iv_xml_index )->get_uri( )->get_uri( ).
lo_xml_part_uri = cl_openxml_parturi=>create_from_partname( lv_uri ).
lo_xml_part = mo_package->get_part_by_uri( lo_xml_part_uri ).
rv_xml_data = lo_xml_part->get_data( ).
CATCH cx_openxml_format cx_openxml_not_found.
ENDTRY.
ENDMETHOD. "load_xml_data
METHOD transform_xml_to_abap.
DATA lo_shared_str_dom TYPE REF TO if_ixml_document.
DATA lo_shared_str_nodeset TYPE REF TO if_ixml_node.
DATA lv_shared_str_xml TYPE xstring.
"We will pass the Sheet XML as XSL source and Shared XML as XSL Parameter
"Sheet XML contains just the indexes
"Using those indexes we need to fetch the real data from Shared String XML
"To send the Shared String XML as a XSL parameter we need to remove the
" - namespaces
TRY.
CALL TRANSFORMATION zben_shared_string_del_namesp
SOURCE XML mv_shared_data
RESULT XML lv_shared_str_xml.
"Pass the SHEET XML and Shared String Nodeset to the main transformation
ENDTRY.
ENDMETHOD. "transform_xml_to_abap
METHOD display_alv.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = sy-repid
i_structure_name = 'SPFLI'
TABLES
t_outtab = mt_spfli
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
ENDIF.
ENDMETHOD. "display_alv
ENDCLASS. "lcl_alv_xlsx_upload IMPLEMENTATION
START-OF-SELECTION.
lcl_alv_xlsx_upload=>initialize( iv_filename = filename ).
METHOD onactionupload.
CONSTANTS co_sheet_xml TYPE i VALUE 2.
CONSTANTS co_shared_str_xml TYPE i VALUE 3.
wd_this->load_package( ).
"Read the sheet XML
wd_this->mv_sheet_data = load_xml_data( co_sheet_xml ).
wd_this->transform_xml_to_abap( ).
wd_this->set_table_cotent( ).
ENDMETHOD.
Please note that the methods called in the above action needs to be created in the webdynpro view which is
similar to the ABAP program included above.
METHOD load_package.
TRY.
wd_this->mo_package = cl_xlsx_document=>load_document( iv_data = wd_this-
>mv_file_data ).
wd_this->mo_parts = wd_this->mo_package->get_parts( ).
CATCH cx_openxml_format cx_openxml_not_found.
ENDTRY.
ENDMETHOD.
METHOD load_xml_data.
DATA lo_xml_part TYPE REF TO cl_openxml_part.
DATA lo_xml_part_uri TYPE REF TO cl_openxml_parturi.
DATA lx_root TYPE REF TO cx_root.
DATA lv_uri TYPE string.
TRY.
lv_uri = wd_this->mo_parts->get_part( 2 )->get_parts( )-
>get_part( iv_xml_index )->get_uri( )->get_uri( ).
lo_xml_part_uri = cl_openxml_parturi=>create_from_partname( lv_uri ).
lo_xml_part = wd_this->mo_package->get_part_by_uri( lo_xml_part_uri ).
rv_xml_data = lo_xml_part->get_data( ).
CATCH cx_openxml_format cx_openxml_not_found.
ENDTRY.
ENDMETHOD.
METHOD transform_xml_to_abap.
DATA lo_shared_str_dom TYPE REF TO if_ixml_document.
DATA lo_shared_str_nodeset TYPE REF TO if_ixml_node.
DATA lv_shared_str_xml TYPE xstring.
TRY.
CALL TRANSFORMATION zben_shared_string_del_namesp
SOURCE XML wd_this->mv_shared_data
RESULT XML lv_shared_str_xml.
IF sy-subrc = 0.
lo_shared_str_nodeset = lo_shared_str_dom->clone( ).
ENDIF.
"Pass the SHEET XML and Shared String Nodeset to the main transformation
CALL TRANSFORMATION zben_xlsx_sheet_import
PARAMETERS p_shared_string = lo_shared_str_nodeset
SOURCE XML wd_this->mv_sheet_data
RESULT lt_spfli = wd_this->mt_spfli.
CATCH cx_xslt_exception.
ENDTRY.
ENDMETHOD.
METHOD set_table_cotent.
ENDMETHOD.
I knew that creating a XLSX document from scratch would take a lot of time. If you feel so get the file from
the DDIC itself in the following way,
1. Transaction Code SE16
2. Table Name: SPFLI
3. Execute
4. Upload the ALV output by exporting the data in XLSX format.
Related Content
Reference 1
Reference 2
Reference 3
Copyright
Copyright 2012 SAP AG. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP AG.
The information contained herein may be changed without prior notice.
Some software products marketed by SAP AG and its distributors contain proprietary software components of other software vendors.
Microsoft, Windows, Excel, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation.
IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, System z9, z10, z9,
iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server,
PowerVM, Power Architecture, POWER6+, POWER6, POWER5+, POWER5, POWER, OpenPower, PowerPC, BatchPipes,
BladeCenter, System Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, Parallel Sysplex, MVS/ESA, AIX,
Intelligent Miner, WebSphere, Netfinity, Tivoli and Informix are trademarks or registered trademarks of IBM Corporation.
Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either trademarks or registered trademarks of Adobe Systems
Incorporated in the United States and/or other countries.
Oracle is a registered trademark of Oracle Corporation.
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of
Citrix Systems, Inc.
HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C, World Wide Web Consortium, Massachusetts
Institute of Technology.
Java is a registered trademark of Oracle Corporation.
JavaScript is a registered trademark of Oracle Corporation, used under license for technology invented and implemented by Netscape.
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP Business ByDesign, and other SAP products and services mentioned
herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other countries.
Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and
other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of Business Objects S.A. in the United States and in other countries. Business Objects is an SAP company.
All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document
serves informational purposes only. National product specifications may vary.
These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP
Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or
omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the
express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an
additional warranty.