树状展开BOM以及保存到本地

SAP系统中有很多BOM的打开方式,平铺、多级以及反查的方式多以结构的形式[在前面关于物料清单中也提到过https://blog.csdn.net/qq_55841727/article/details/145442562?fromshare=blogdetail&sharetype=blogdetail&sharerId=145442562&sharerefer=PC&sharesource=qq_55841727&sharefrom=from_link]。SAP 4HANA里面有一个以树状打开的功能BOM浏览器:CSMB

边上小按钮的堆栈可以查看到历史查询的BOM物料,进入结构以后可以看到树状的分布,每一阶层都可以打开(参数要输入完整)。右击可以更方便快捷的展开或者收起,也能跳转到cs11。

值得注意的是:这里自带的打印保存下来的PDF是最后你展开的状态,并不能保存到层次结构到本地。

那想要从系统中保存可展开可复制的树状结构呢

可以通过要使用BOM多级展开函数 CS_BOM_EXPL_MAT_V2,该函数按物料+工厂+用途+有效期等条件,展开标准物料 BOM,可单层/多层,返回组件明细,是 PP / CO / 报表开发里最常用的 BOM 展开入口:

复制代码
CALL FUNCTION 'CS_BOM_EXPL_MAT_V2'
        EXPORTING
          capid                 = 'PP01' "bom类型
          datuv                 = sy-datum "datua "有效期
          mdmps                 = ''  " 限制字段:限制BOM只展1层,但下层是虚拟件的则再往下展开一层,默认为空不限制
          mehrs                 = ''  " 重要字段:BOM多级展开,默认为空,只展开一层 多阶展开 'X'-多阶; ''-单阶
          mtnrv                 = mtnrv " 必须字段:物料号
          werks                 = werks " 必须字段:工厂号
          stlal                 = '01' "ls_mast-stlal
          emeng                 = 1
          stpst                 = 0
*      importing
*         topmat                = ls_topmat
*         DSTST                 =
        TABLES
          stb                   = lt_stpox    " 必须接收的表:BOM展开明细
*         matcat                = lt_matcat    " 父级物料清单:参与BOM展开的父级物料清单,即含有组件的物料
        EXCEPTIONS
          alt_not_found         = 1
          call_invalid          = 2
          material_not_found    = 3
          missing_authorization = 4
          no_bom_found          = 5
          no_plant_data         = 6
          no_suitable_bom_found = 7
          conversion_error      = 8
          OTHERS                = 9.

      IF sy-subrc <> 0.
* Implement suitable error handling here
      ENDIF.

调用后,该BOM展开明细会存储到内表中,再对数据的进一步处理。

  • mdmps 限制字段:限制BOM只展1层,但下层是虚拟件的则再往下展开一层,默认为空不限制。
  • mehrs 重要字段:BOM多级展开,默认为空,只展开一层 多阶展开 'X'-多阶; ' '-单阶。
  • stpox这个结构是 把 STPO 的字段和一些附加信息(如层级、路径、计算数量、价格等)打包在一起,方便使用。

首先在ALV显示界面显示树状结构,初始化 ALV 树控件,设置其外观和功能(包括标准按钮和自定义按钮),绑定事件处理类,最后将树展示在屏幕上。

总初始化与调用如下:

复制代码
form frm_salv_tree .
*1. 容器懒加载:只有当容器未被创建时才执行,防止屏幕多次刷新导致重复创建报错
  if gr_container is not bound.
    if cl_salv_tree=>is_offline( ) eq if_salv_c_bool_sap=>false.
      create object gr_container
        exporting
          container_name = 'TREE1'. "在屏幕上创建一个自定义容器,容器名称为 TREE1
    endif.

*2.创建 ALV 树实例
    try.    
        cl_salv_tree=>factory(
          exporting
            r_container  = gr_container
          importing
            r_salv_tree = gr_tree
          changing
            t_table      = gt_stpo_alv ). 
      catch cx_salv_no_new_data_allowed cX_SALV_ERROR.
        exit.
    endtry.
*3. 构建树形层级关系(调用后面的 Form)
    perform create_tree. "注意:对于树形 ALV,上面实例传入的内表通常是扁平结构的数据,真正的层级关系是在 create_tree 中通过设置节点父子关系建立的

    data: lr_functions type ref to cl_salv_functions_tree,
          l_text       type string,
          l_icon       type string.


    lr_functions = gr_tree->get_functions( ).
    lr_functions->set_all( 'X' ).

    data: lr_columns type ref to cl_salv_columns_tree.

    lr_columns = gr_tree->get_columns( ).
    lr_columns->set_optimize( if_salv_c_bool_sap=>true  )."列宽自适应

*4.设置布局属性
    gr_tree->get_tree_settings( )->set_hierarchy_size_in_pixel( if_salv_c_bool_sap=>true ).
    perform set_columns_technical using lr_columns. "注意 这个调用的FORM主要控制字段对应列的显示和格式(这里不细展开了)

*5.自定义按钮,导出可触发用户事件
    try.
        l_text = 'Excel导出'.
        l_icon = icon_xls.
        lr_functions->add_function(
          name     = 'EXPORT'
          icon     = l_icon
          text     = l_text
          tooltip  = l_text
          position = if_salv_c_function_position=>right_of_salv_functions )." 放在标准按钮右侧
      catch cx_salv_wrong_call cx_salv_existing.
    endtry.


    gr_tree->set_screen_status(
      pfstatus      =  'ZPPGS9000'  "设置 GUI
      report        =  sy-repid
      set_functions =  gr_tree->c_functions_all ).

*6.注册事件处理
    data: lr_events type ref to cl_salv_events_tree.

    lr_events = gr_tree->get_event( ).

    create object gr_events.
     " 绑定各种事件到 gr_events 类的对应方法上
    set handler gr_events->on_user_command for lr_events.
    set handler gr_events->on_before_salv_function for lr_events.
    set handler gr_events->on_after_salv_function for lr_events.
    set handler gr_events->on_double_click for lr_events.
    set handler gr_events->on_link_click for lr_events.
*7.将构建好的 ALV 树显示在屏幕上
    gr_tree->display( ).

  endif.

endform.

要将前面从BOM关联的数据表中将扁平的数据组装成父子节点:

复制代码
form create_tree .
  perform frm_build_header. " 设置表头
  perform frm_add_nodes.    " 添加节点
endform.

form frm_build_header .
  data: settings type ref to cl_salv_tree_settings.
  settings = gr_tree->get_tree_settings( ).
  " 设置左侧树形层级列的标题
  settings->set_hierarchy_header( 'BOM层次/备选物料清单' ).
  " 设置鼠标悬停提示
  settings->set_hierarchy_tooltip( 'ToolTip' ).
  " 设置层级列的宽度
  settings->set_hierarchy_size( 40 ).
  
  " 获取当前程序的标题,并设置为整个 ALV 树的顶部大标题
  data: title type salv_de_tree_text.
  title = sy-title.
  settings->set_header( title ).
endform.

form frm_add_nodes .
  " l1~l10 相当于10个书签,分别记录最近一次遍历到的 1~10 层节点的 KEY
  data: l1 type lvc_nkey,l2 type lvc_nkey,l3 type lvc_nkey,l4 type lvc_nkey,
        l5 type lvc_nkey,l6 type lvc_nkey,l7 type lvc_nkey,l8 type lvc_nkey,
        l9 type lvc_nkey,l10 type lvc_nkey,
        l_key      type lvc_nkey,  " 当前节点的父节点 KEY
        l_last_key type lvc_nkey.  " 新创建的节点自身的 KEY

  loop at gt_stb into data(gs_stb).
    " 根据当前行的层级,决定它的父节点是谁
    case gs_stb-stufe .
      when '0'. l_key = ''.  " 0层是顶层,没有父亲
      when '1'. l_key = l1.  " 1层的父亲是上次记录的0层书签(l1)
      when '2'. l_key = l2.  " 2层的父亲是上次记录的1层书签(l2)
      " ... 依此类推
    endcase.

    " 调用 Form 在树上创建该节点
    perform frm_add_complete_line using  gs_stb l_key changing l_last_key.

    " 把刚刚创建的节点 KEY 记录到对应层级的书签中
    case gs_stb-stufe .
      when '0'. l1 = l_last_key. " 如果刚创建的是0层,把它的KEY存入l1,以后1层找爸爸就用它
      when '1'. l2 = l_last_key. " 如果刚创建的是1层,把它的KEY存入l2,以后2层找爸爸就用它
      " ... 依此类推
    endcase.
    modify gt_stb from gs_stb .
  endloop.
endform.

form frm_add_complete_line  using    ps_data structure gs_alv p_relat_key changing p_l_last_key.
  data: nodes type ref to cl_salv_nodes,
        node  type ref to cl_salv_node.
  data: lv_idnrk type stpox-idnrk.
  data: l_node_text type lvc_value.

  nodes = gr_tree->get_nodes( ).
  
  " 去除前导零
  call function 'CONVERSION_EXIT_MATN1_OUTPUT'
    exporting input  = ps_data-idnrk
    importing output = lv_idnrk.
  l_node_text = lv_idnrk.
  condense l_node_text no-gaps. " 去除空格

  try.
      " 核心:添加节点到 ALV 树
      node = nodes->add_node( 
          related_node = p_relat_key                 " 指定父节点
          data_row     = ps_data                     " 绑定该行的内表数据(用于右侧列显示)
          text         = l_node_text                 " 显示在左侧树形结构上的文本(物料号)
          relationship = cl_gui_column_tree=>relat_last_child ). " 挂载为父节点的最后一个子节点

      " 获取系统分配给这个新节点的唯一 KEY,返回给外层做"书签"
      p_l_last_key = node->get_key( ).
    catch cx_salv_msg.
  endtry.
endform.

导出excel到本地:

复制代码
form show_function_info  using i_function type salv_de_function.
  case i_function.
    when 'EXPORT'. " 
      perform frm_export_data.
    when others.
  endcase.
endform.

form frm_export_data .
  " 调用自定义的 Excel 模板导出函数 
  call function 'ZXLWB_CALLFORM'
    exporting
      iv_formname        = 'Z_BOM_TREE'   " 指定在 SMW0 中上传的 Excel 模板名称
      iv_context_ref     = gr_tree        " 传入了整个 ALV 树对象!
    exceptions
      process_terminated = 1
      others             = 2.
  if sy-subrc <> 0.
    message id sy-msgid type sy-msgty number sy-msgno
          with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 raising process_terminated .
  endif.
endform.

最后ALV显示结果:

excel表导出结果:

相关推荐
Henry-SAP3 小时前
BOM层级传递与MRP计划生成实战解析
人工智能·sap·erp
Henry-SAP14 小时前
SAP MRP核心概念与学习路线解析
人工智能·sap
ERP面壁者2 天前
WTEW的操作记录
sap
爱喝水的鱼丶3 天前
SAP-ABAP:数据类型与数据对象(8篇) 第七篇:进阶优化篇——基于类型与对象特征的性能优化技巧
运维·数据库·学习·性能优化·sap·abap·开发交流
爱喝水的鱼丶4 天前
SAP-ABAP:数据类型与数据对象(8篇) 第四篇:关系映射篇——从类型定义到对象实例的转化逻辑
开发语言·数据库·学习·sap·abap
爱喝水的鱼丶5 天前
SAP-ABAP:ABAP函数 NUMBER_GET_NEXT 详解:从编号范围对象获取下一个编号
运维·数据库·学习·sap·abap
爱喝水的鱼丶5 天前
SAP-ABAP:数据类型与数据对象 第二篇:底层逻辑篇——数据类型的分类体系与底层存储原理
运维·开发语言·学习·sap·abap
HeathlX7 天前
SAP-BTP :(7)RAP-EML
abap
爱喝水的鱼丶8 天前
SAP-ABAP:新手入门篇——从0到1写出你的第一个ABAP Hello World程序并完成调试运行
运维·服务器·数据库·学习·sap·abap