繁体   English   中英

如何将 ALV 树导出到 excel?

[英]How to export an ALV tree to excel?

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

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 等。

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

  1. 使用abap2xlsx轻量级 xlsx 创建器创建 Excel 文件。
  2. 使用XLSX Workbench创建到 Excel 的自定义导出。

尽管您说的是 ALV 列表树,它非常原始且过时,但我将展示如何使用现代 SALV_ALV_TREE 控件来实现它。

这个想法是从这里借来的所以所有的学分都归功于 Juwin,我只是改编并创建了友好的样本。

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 结构的更多信息。

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

START-OF-SELECTION.

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

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

在此处输入图片说明

导出的结果是这个原生的 Excel 树

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM