Odata 从作为XSTRING提供的XLSX读取数据

Odata 从作为XSTRING提供的XLSX读取数据,odata,abap,class-method,function-module,Odata,Abap,Class Method,Function Module,Excel文件(.xlsx)上载到前端,即UI5 Fiori 文件内容以XSTRING格式通过ODATA到达SAP ABAP后端 我需要将该XSTRING存储到一个内部表中,然后再存储到一个DDIC表中。假设Excel有5列,那么我想将5列的数据存储在DDIC表中相应的列中 我尝试过各种功能模块,如: SCMS_XSTRING_到_二进制文件 SCMS_二进制_到_字符串 以及以下类和方法: cl_bcs_convert=>原始_到_字符串 cl_soap_xml_helper=>xstr

Excel文件(
.xlsx
)上载到前端,即UI5 Fiori

文件内容以XSTRING格式通过ODATA到达SAP ABAP后端

我需要将该XSTRING存储到一个内部表中,然后再存储到一个DDIC表中。假设Excel有5列,那么我想将5列的数据存储在DDIC表中相应的列中

我尝试过各种功能模块,如:

  • SCMS_XSTRING_到_二进制文件
  • SCMS_二进制_到_字符串
以及以下类和方法

  • cl_bcs_convert=>原始_到_字符串
  • cl_soap_xml_helper=>xstring_to_字符串
但是没有人能够将XSTRING转换为STRING

您能建议使用哪种功能模块或类/方法来解决此问题吗?

为了更舒适,请使用

如果您不能或不想使用,也可以自己解析Excel文件。xlsx文件基本上是以不同文件结尾的.zip文件。使用
cl\u abap\u zip->load
打开您收到的
xstring
,使用
->get
从zip中提取单个文件。然后,使用XML解析器(如
cl_ixml
或转换)来解析文件的XML内容


请注意,Excel的XML是一种复杂的文件格式,有多个文件共同构成工作表。有关详细信息,请参阅Microsoft的。解释这一点并非易事,因此使用abap2xlsx通常会让您更开心。

abap2xlsx是实现这一点最强大、功能最丰富的方法,正如Florian所说,它支持样式、图表和复杂表格,但由于系统限制,它可能并不总是可用,在系统或其他任何地方安装自定义软件包的限制

下面是如何在不使用自定义框架的情况下使用纯标准实现这一点的方法

由于Netweaver 7.02 SAP本机支持开放式Microsoft格式,并提供用于处理这些格式的类:
CL\u XLSX\u DOCUMENT
CL\u DOCX\u DOCUMENT
CL\u PPTX\u DOCUMENT
,因此abap2xlsx也是在这些类上构建的,是的。因此,让我们开始重新设计车轮

XLSX文件是一个OpenXML文件归档,其中最有趣的是:
sheet1.xml
sharedStrings.xml
。让我们基于
MARC
表字段构建一个示例

现在,您希望将此表传输到具有相同结构的内部表。这些步骤将是:

  • 从XLSX存档中提取所需文件
  • 阅读
    sheet1.xml中的工作表结构
  • sharedStrings.xml
  • 将它们映射到一起,并将结果写入内部表
  • 下面是处理该作业的示例类,我使用
    cl\u openxml\u helper
    applet加载XLSX,但是您可以以任何方式接收XSTRINGed XLSX

    CLASS xlsx_reader DEFINITION.
      PUBLIC SECTION.
    
        TYPES: BEGIN OF ty_marc,
                 matnr TYPE char20,
                 werks TYPE char20,
                 disls TYPE char20,
                 ekgrp TYPE char20,
                 dismm TYPE char20,
               END OF ty_marc,
               tt_marc TYPE STANDARD TABLE OF ty_marc WITH EMPTY KEY.
    
        METHODS: read RETURNING VALUE(tab) TYPE tt_marc,
                 extract_xml IMPORTING index   TYPE i
                                       xstring TYPE xstring
                 RETURNING VALUE(rv_xml_data)  TYPE xstring.
    ENDCLASS.
    
    CLASS xlsx_reader IMPLEMENTATION.
      METHOD read.
        TYPES: BEGIN OF ty_row,
                     value TYPE string,
                     index TYPE abap_bool,
                   END OF ty_row,
                   BEGIN OF ty_worksheet,
                     row_id TYPE i,
                     row    TYPE TABLE OF ty_row WITH EMPTY KEY,
                   END OF ty_worksheet,
                   BEGIN OF ty_si,
                     t TYPE string,
                   END OF ty_si.
    
        DATA: data  TYPE TABLE OF ty_si,
              sheet TYPE TABLE OF ty_worksheet.
    
        TRY.
            DATA(xstring_xlsx)  = cl_openxml_helper=>load_local_file( 'C:\marc.xlsx' ).
          CATCH cx_openxml_not_found.
        ENDTRY.
    
        "Read the sheet XML
        DATA(xml_sheet) = extract_xml( EXPORTING xstring = xstring_xlsx iv_xml_index = 2 ).
        "Read the data XML
        DATA(xml_data)  = extract_xml( EXPORTING xstring = xstring_xlsx iv_xml_index = 3 ).
    
        TRY.
    * transforming structure into ABAP
            CALL TRANSFORMATION zsheet
              SOURCE XML xml_sheet
              RESULT root = sheet.
    * transforming data into ABAP
            CALL TRANSFORMATION zxlsx_data
              SOURCE XML xml_data
              RESULT root = data.
    
          CATCH cx_xslt_exception.
          CATCH cx_st_match_element.
          CATCH cx_st_ref_access.
        ENDTRY.
    * mapping structure and data
        LOOP AT sheet ASSIGNING FIELD-SYMBOL(<fs_row>).
          APPEND INITIAL LINE TO tab ASSIGNING FIELD-SYMBOL(<line>).
          LOOP AT <fs_row>-row ASSIGNING FIELD-SYMBOL(<fs_cell>).
            ASSIGN COMPONENT sy-tabix OF STRUCTURE <line> TO FIELD-SYMBOL(<fs_field>).
            CHECK sy-subrc = 0.
            <fs_field> = COND #( WHEN <fs_cell>-index = abap_false THEN <fs_cell>-value ELSE VALUE #( data[ <fs_cell>-value + 1 ]-t OPTIONAL ) ).
          ENDLOOP.
        ENDLOOP.
      ENDMETHOD.
    
      METHOD extract_xml.
        TRY.
            DATA(lo_package) = cl_xlsx_document=>load_document( iv_data = xstring ).
            DATA(lo_parts)      = lo_package->get_parts( ).
            CHECK lo_parts IS BOUND AND lo_package IS BOUND.
            DATA(lv_uri) = lo_parts->get_part( 2 )->get_parts( )->get_part( index )->get_uri( )->get_uri( ).
            DATA(lo_xml_part)     = lo_package->get_part_by_uri( cl_openxml_parturi=>create_from_partname( lv_uri ) ).
            rv_xml_data     = lo_xml_part->get_data( ).
          CATCH cx_openxml_format cx_openxml_not_found.
        ENDTRY.
      ENDMETHOD.
    ENDCLASS.
    

    代码很容易解释,但让我们注意几点:

    • 文件
      sheet1.xml
      在每个单元格中包含一个特殊属性
      t
      ,该属性表示该值应被视为文本或对
      sharedStrings.xml的引用
    • 我使用了两个简单的转换,但也可以使用XSLT,这可能允许您将所有XML内容简化为单个转换
    • 我故意使用generic
      char20
      类型来处理标题。如果要保留本机类型,则无法读取表头(跳过
      sheet
      循环中的第一行),因为您将收到类型冲突和转储。如果您收到的表没有标题,则可以使用本机类型声明结构
    • 如果您不想使用转换,那么是您的朋友。您也可以使用类解析XML,但是ST转换要快得多
    • 通过一些额外的努力,您可以使这个代码段动态化,并用任何结构解析XLSX

    您可以阅读有关此方法的更多信息。

    您好,Sandra,我无法将XSTRING直接存储到数据库中,这不是我的要求。我从前端获得的XSTRING是一个Excel文件(.xlsx)。我的实际需求是将excel的XSTRING(.xlsx)存储到一个内部表中。假设Excel有5列,那么我想将5列的数据存储在DDIC表中相应的列中。哦,好吧,如果不解释您首先收到的内容,这是行不通的。你可能想看看这个博客:你的意思是你的问题是从XLSX文件中提取文本吗?为此,您必须使用。你好,桑德拉,感谢您的及时回复和指导。是的,我的要求是从Excel文件中提取文本,并将文本存储在DDIC表的相应列中。示例:假设Excel有5列,那么我想将5列的数据存储在DDIC表中相应的列中。我去了ABAP2XLSX的GitHub,甚至按照他们的指导在我们的系统中安装了它,克隆了ABAP2XLSX,但他们的类和方法都没有在我们的系统中创建。所以,我在寻找其他的方法。
    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates" template="main">
      <tt:root name="root"/>
      <tt:template name="main">
        <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x14ac=
    "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision" xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2" xmlns:xr3=
    "http://schemas.microsoft.com/office/spreadsheetml/2016/revision3">
          <tt:skip count="4"/>
          <sheetData>
            <tt:loop name="row" ref="root">
              <row>
                <tt:attribute name="r" value-ref="row_id"/>
                <tt:loop name="cells" ref="$row.ROW">
                  <c>
                    <tt:cond><tt:attribute name="t" value-ref="index"/><tt:assign to-ref="index" val="C('X')"/></tt:cond>
                    <v><tt:value ref="value"/></v>
                  </c>
                </tt:loop>
              </row>
            </tt:loop>
          </sheetData>
          <tt:skip count="2"/>
        </worksheet>
      </tt:template>
    </tt:transform>
    
    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates" template="main">
      <tt:root name="ROOT"/>
      <tt:template name="main">
          <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
            <tt:loop name="line" ref=".ROOT">
              <si>
                <t>
                  <tt:value ref="t"/>
                </t>
              </si>
            </tt:loop>
          </sst>
      </tt:template>
    </tt:transform>
    
    START-OF-SELECTION.
    
      DATA(reader) = NEW xlsx_reader( ).
      DATA(marc)   = reader->read( ).