如何导出一棵树到Excel?

时间:2019-06-07 07:55:42

标签: sap abap

我必须构造然后将具有4个级别的树导出到excel表中,如下图所示:

expected hierarchy in Excel

我的数据库表中有不同的节点数据,我使用功能RS_TREE_CONSTRUCT制作了树,并使用了功能RS_TREE_LIST_DISPLAY来查看它是否看起来像预期的那样,一切都应该如此,但现在找不到导出它的方式,使它看起来像我在图片上描述的那样。

这些是在我用所需数据填充LT_NODE表之后使用的2个函数:

CALL FUNCTION 'RS_TREE_CONSTRUCT'
    TABLES
      NODETAB            = LT_NODE
    EXCEPTIONS
      TREE_FAILURE       = 1
      ID_NOT_FOUND       = 2
      WRONG_RELATIONSHIP = 3
      OTHERS             = 4.
  IF SY-SUBRC <> 0.
    WRITE 'Error in Tree Construction'.
  ENDIF.
***Display TREE
  CALL FUNCTION 'RS_TREE_LIST_DISPLAY'
    EXPORTING
      CALLBACK_PROGRAM = SY-REPID.

预期结果将如图所示,但实际结果是一张普通表(LT_NODE),该表具有ID,TYPE,NAME,TLEVEL等多个列。

2 个答案:

答案 0 :(得分:0)

标准中没有树ALV的导出选项。自定义编码有很多选择。

  1. 使用abap2xlsxlight weigth xlsx creator创建Excel文件。
  2. 使用XLSX Workbench创建自定义导出到Excel。

答案 1 :(得分:0)

尽管您谈论的是ALV列表树,它非常原始且过时,但我将展示如何使用现代SALV_ALV_TREE控件来做到这一点。

这个想法是借来的from here,所以所有的功劳都归朱文,我刚刚改编并创建了友好的示例。

CLASS lcl_tree DEFINITION.
  PUBLIC SECTION.
    CLASS-DATA: go_alv_tree  TYPE REF TO cl_salv_tree,
                gt_empty_tab TYPE STANDARD TABLE OF spfli,
                gt_full_tab  TYPE STANDARD TABLE OF spfli.
    CLASS-METHODS: create_tree,
                   setup,
                   export_tree,
                   on_user_command FOR EVENT added_function OF cl_salv_events IMPORTING e_salv_function.
ENDCLASS.

CLASS lcl_tree IMPLEMENTATION.
  METHOD export_tree.
    DATA: lr_data  TYPE REF TO data,
          lt_spfli TYPE STANDARD TABLE OF spfli,
          levels   TYPE TABLE OF rsplf_srv_p.

    DATA: lr_zip         TYPE REF TO cl_abap_zip,
          lr_xlnode      TYPE REF TO if_ixml_node,
          lr_xldimension TYPE REF TO if_ixml_node,
          lr_file        TYPE REF TO cl_xml_document,
          lr_xlrows      TYPE REF TO if_ixml_node_list,
          lr_xlrow       TYPE REF TO if_ixml_element,
          lr_xlformat    TYPE REF TO if_ixml_element,
          lr_xlworksheet TYPE REF TO if_ixml_element.

    FIELD-SYMBOLS: <spfli> TYPE spfli.

    DATA(lt_nodes) = go_alv_tree->get_nodes( )->get_all_nodes( ).
    LOOP AT lt_nodes INTO DATA(ls_node).
      DATA(lr_node) = ls_node-node.
      DATA(lv_level) = 0.
      DO.
        TRY.
            lr_node = lr_node->get_parent( ).
            lv_level = lv_level + 1.
          CATCH cx_salv_msg.
            EXIT.
        ENDTRY.
      ENDDO.
      APPEND VALUE rsplf_srv_p( indx = sy-tabix value = lv_level ) TO levels.
      lr_data = ls_node-node->get_data_row( ).
      ASSIGN lr_data->* TO <spfli>.
      APPEND <spfli> TO lt_spfli.
    ENDLOOP.

    cl_salv_table=>factory(
      IMPORTING
        r_salv_table = DATA(lr_table)
      CHANGING
        t_table = lt_spfli ).

    DATA(lv_xlsx) = lr_table->to_xml( if_salv_bs_xml=>c_type_xlsx ).
    CREATE OBJECT lr_zip.
    lr_zip->load( lv_xlsx ).
    lr_zip->get( EXPORTING name = 'xl/worksheets/sheet1.xml' IMPORTING content = DATA(lv_file) ).

    CREATE OBJECT lr_file.
    lr_file->parse_xstring( lv_file ).
* Row elements are under SheetData
    lr_xlnode = lr_file->find_node( 'sheetData' ).
    lr_xlrows = lr_xlnode->get_children( ).

    DO lr_xlrows->get_length( ) TIMES.
      lr_xlrow ?= lr_xlrows->get_item( sy-index - 1 ).
      READ TABLE lt_nodes INTO ls_node INDEX sy-index - 1. "find this row in tree
      IF sy-subrc = 0.
        READ TABLE levels ASSIGNING FIELD-SYMBOL(<line_level>) INDEX sy-index.
* Find the level of the node
        CHECK <line_level>-value - 1 NE 0.
* Assign the level to row
        lr_xlrow->set_attribute( name = 'outlineLevel' value = condense( CONV string( <line_level>-value - 1 ) ) ).
        lr_xlrow->set_attribute( name = 'hidden' value = 'true' ).
      ENDIF.
    ENDDO.

* Create new element in the XML file
    lr_xlworksheet ?= lr_file->find_node( 'worksheet' ).
    DATA(lr_xlsheetpr)   = cl_ixml=>create( )->create_document( )->create_element( name = 'sheetPr' ).
    DATA(lr_xloutlinepr) = cl_ixml=>create( )->create_document( )->create_element( name = 'outlinePr' ).
    lr_xlsheetpr->if_ixml_node~append_child( lr_xloutlinepr ).
    lr_xloutlinepr->set_attribute( name = 'summaryBelow' value = 'false' ).
    lr_xldimension ?= lr_file->find_node( 'dimension' ).
    lr_xlworksheet->if_ixml_node~insert_child( new_child = lr_xlsheetpr ref_child = lr_xldimension ).
* Create xstring and move it to XLSX
    lr_file->render_2_xstring( IMPORTING stream = lv_file ).
    lr_zip->delete( EXPORTING name = 'xl/worksheets/sheet1.xml' ).
    lr_zip->add( EXPORTING name = 'xl/worksheets/sheet1.xml' content = lv_file ).
    lv_xlsx = lr_zip->save( ).

    DATA lv_size   TYPE i.
    DATA lt_bintab TYPE solix_tab.

    CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
      EXPORTING
        buffer        = lv_xlsx
      IMPORTING
        output_length = lv_size
      TABLES
        binary_tab    = lt_bintab.

    CHECK lt_bintab IS NOT INITIAL.
    DATA(p_file) = cl_openxml_helper=>browse_local_file_open( iv_title = 'Save to XLSX File' iv_filename = '' iv_extpattern = 'All files(*.*)|*.*' ).
    cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_size
                                                      filename    = p_file && `.xlsx`
                                                      filetype      = 'BIN'
                                            CHANGING  data_tab   = lt_bintab ).
  ENDMETHOD.

  METHOD create_tree.
    TRY.
        cl_salv_tree=>factory(
          IMPORTING
            r_salv_tree = go_alv_tree
          CHANGING
            t_table     = gt_empty_tab ).
      CATCH cx_salv_error.
        MESSAGE 'ALV creation error' TYPE 'E'.
    ENDTRY.

    DATA(lo_settings) = go_alv_tree->get_tree_settings( ).
    lo_settings->set_hierarchy_size( 50 ).
    lo_settings->set_hierarchy_icon( CONV salv_de_tree_image( icon_tree ) ).
    DATA(lo_nodes) = go_alv_tree->get_nodes( ).

    SELECT * FROM spfli INTO TABLE gt_full_tab ORDER BY carrid.
    LOOP AT gt_full_tab ASSIGNING FIELD-SYMBOL(<fs_line>).
      TRY.
          AT NEW carrid.
            DATA(lo_node) = lo_nodes->add_node( related_node   = ''
                                                relationship   = cl_gui_column_tree=>relat_last_child
                                                data_row       = <fs_line>
                                                row_style      = if_salv_c_tree_style=>emphasized_a
                                                text           = 'Parent node' ).
            DATA(lv_carrid_key) = lo_node->get_key( ).
          ENDAT.
          AT NEW connid.
            lo_node = lo_nodes->add_node( related_node   = lv_carrid_key
                                          relationship   = cl_gui_column_tree=>relat_last_child
                                          data_row       = <fs_line>
                                          row_style      = if_salv_c_tree_style=>emphasized_negative
                                          text           = 'Child node' ).
          ENDAT.
        CATCH cx_salv_msg.
      ENDTRY.
    ENDLOOP.
  ENDMETHOD.                    "create_nodes

  METHOD setup.
    go_alv_tree->set_screen_status( pfstatus  = 'STANDARD_FULLSCREEN' report = 'SAPLSLVC_FULLSCREEN' set_functions =  go_alv_tree->c_functions_all ).
    DATA(lr_functions) = go_alv_tree->get_functions( ).
    lr_functions->set_all( abap_true ).
    DATA(lo_columns) = go_alv_tree->get_columns( ).
    lo_columns->set_optimize( abap_true ).
    DATA(lo_events) = go_alv_tree->get_event( ).
    SET HANDLER on_user_command FOR lo_events.
  ENDMETHOD.

  METHOD on_user_command.
    CASE e_salv_function.
      WHEN '&VEXCEL'.
        export_tree( ).
    ENDCASE.
  ENDMETHOD.
ENDCLASS.

该示例使用SPFLI表构造树,然后将SALV_ALV_TREE转换为CL_SALV_TABLE并捕获OpenXML格式的节点,然后构造XLSX。

手动添加级别/聚合到XLSX ZIP归档文件并更改其属性:outlineLevel和其他属性。

有关OpenXML结构的更多信息,请参见here

在系统上重新创建类后,您可以像这样测试它

START-OF-SELECTION.

 lcl_tree=>create_tree( ).
 lcl_tree=>setup( ).
 lcl_tree=>go_alv_tree->display( ).

通过标准工具栏上的Excel按钮完成导出:

enter image description here

导出结果是此本地Excel树

enter image description here