SAP Number Range 简析

目录

前言

一、基础使用

1. 根据年度流水

2. 根据子对象(如公司代码等)分别流水

3. 延伸-根据月度流水

 4. 生成间隔对应的维护事务代码

二、知识点

1. 跳号

2. 剩余号码警告

3. 外部给号

4. 查看缓存中的号码

5. 组页签配置


前言

Number Ranger Object 是在 SAP 系统中创建并包含一组已定义的唯一字符串的对象。 应用程序可以使用Number Ranger Object为数据库记录提供唯一Key。

这里是一些Number Ranger 的一些使用技巧和知识点,仅供参考。


一、基础使用

1. 根据年度流水

        勾选截止年份标识

                  

        按照年份分别维护对应号码段间隔

        

        

        获取时,年份字段传参

        

        测试

        

        

2. 根据子对象(如公司代码等)分别流水

        填写子对象对应数据元素

        

        维护时会分别维护各个子对象下的间隔

        

        

        

        代码传参

        

        

        

3. 延伸-根据月度流水

        第一种:子对象为年月,或者按年流水,子对象为月份。

        需要维护每个月份的号码段间隔,间隔的维护可以手动导入,也可以在获取流水号时判断如果当前月份无对应间隔维护时,自动生成.文末有附间隔导入对应程序,可供参考.

        第二种:按月份清空NR状态 ,可在每月1号的凌晨清空当前号码段间隔

        参考函数NUMBER_RANGE_INTERVAL_INIT

        PS:也可以延伸出其它一些各种需求的流水号形式,相对来说虽然比较麻烦,但是还是优于通过自建表或者最大值+1的处理方式.。

 4. 生成间隔对应的维护事务代码

        在号码段编辑页面,输入编号范围事务,会在保存的时候自动生成对应事务码用来维护号码段间隔,这样就很方便。

二、知识点

1. 跳号

        跳号的原因:

        其一:服务器会将固定数目的流水号缓存下来,如果重启应用程序服务器实例,则缓存丢失,导致号码丢失.

        其二: 先获取的号码没有commit,后获取的号码commit了(不绝对)

        解决:可以设置无缓冲,或者设置并行缓存

注:

1.  RSSNR0S1 可在并行缓存时查看未分配的号码

2. 无缓冲可能会减慢号码段流水号的获取速度,特别是多服务器的场景下

2. 剩余号码警告

        早期的一些文档会写成到达多少百分比,而不是剩余

        

        

3. 外部给号

        

        勾选外部编号,表示该号码段中号码为外部提供,使用NUMBER_CHECK检查是否在范围内,该检查不检查是否使用等情况。(此时不能使用函数获取下一个流水号)

4. 查看缓存中的号码

        

        

        可以查看系统中目前号码段的缓存数据,可以结合debug解决部分主键重复的dump问题

5. 组页签配置

        可以理解为将号码段配置根据组表字段分组,不常用,感兴趣的可以查看官方文档

        示例号码段: TEST2,TEST5,TEST6,TEST7,TEST8


 附1:官方帮助文档地址:SAP Help Portalhttps://help.sap.com/viewer/5db4c2a406234b6995553939c79da063/7.5.3/en-US/48d58f50982b424be10000000a421937.html

附2:号码段间隔导入程序

*&---------------------------------------------------------------------*
*& Report ZR_IMPORT_NUMRANGE
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zr_import_numrange.

*  ALV 参数
DATA: gt_fieldcat TYPE lvc_t_fcat, "字段目录内表
      gs_fieldcat TYPE lvc_s_fcat, "字段目录工作区
      gs_layout   TYPE lvc_s_layo. "用于定义ALV表单的相关格式、属性

* 声明OLE变量
DATA: gs_excel    TYPE ole2_object,
      gs_sheet    TYPE ole2_object,
      gs_cellhead TYPE ole2_object,
      gs_cell1    TYPE ole2_object,
      gs_cell2    TYPE ole2_object,
      gs_range    TYPE ole2_object,
      gs_workbook TYPE ole2_object.

DATA: gt_tab       TYPE TABLE OF alsmex_tabline,
      gs_tab       TYPE alsmex_tabline,
      gv_col_count TYPE i.
DATA: gv_count  TYPE i,
      gv_length TYPE i.

DATA: gr_table TYPE REF TO data,
      gr_line  TYPE REF TO data.

*&---------------------------------------------------------------------*
* 指针定义
*&---------------------------------------------------------------------*
FIELD-SYMBOLS: <gt_table> TYPE STANDARD TABLE,
               <gs_area>  TYPE any,
               <gs_field> TYPE any,
               <gs_struc> TYPE any.

*&---------------------------------------------------------------------*
* 选择屏幕
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS:p_fn     LIKE rlgrap-filename DEFAULT 'C:\' OBLIGATORY MODIF ID ty1. "文件路径
PARAMETERS:p_object TYPE tnro-object OBLIGATORY DEFAULT 'Z*' MODIF ID ty1.
SELECTION-SCREEN END OF BLOCK b1.
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-002.
PARAMETERS: p_r1 RADIOBUTTON GROUP r1 DEFAULT 'X' USER-COMMAND uc1,
            p_r2 RADIOBUTTON GROUP r1.
SELECTION-SCREEN END OF BLOCK b2.

*&---------------------------------------------------------------------*
* 初始化
*&---------------------------------------------------------------------*
INITIALIZATION.

*&--------------------------------------------------------------------*
*  选择屏幕开始                                    *
*&--------------------------------------------------------------------*
AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    CASE screen-group1.
      WHEN 'TY1'.
        IF p_r1 = 'X'.
          screen-active = '1'.
        ELSE.
          screen-active = '0'.
        ENDIF.
    ENDCASE.
    MODIFY SCREEN.
  ENDLOOP.

AT SELECTION-SCREEN.
  CLEAR sy-ucomm.
*&---------------------------------------------------------------------*
* 选择屏幕搜索帮助
*&---------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_fn.
  PERFORM frm_get_fn.                                     "取主数据文件路径

*&---------------------------------------------------------------------*
* 执行选择屏幕
*&---------------------------------------------------------------------*
START-OF-SELECTION.

  PERFORM frm_create_dynamic_table.                      " 创建动态内表

  IF p_r1 = 'X'." 数据上载

    PERFORM frm_upload_data.                               "上传文件到内表

* 设置输出格式
    PERFORM frm_set_layout.

* 显示ALV
    PERFORM frm_display_alv.

  ENDIF.

  IF p_r2 = 'X'." 模板下载
    PERFORM frm_download.
  ENDIF.

END-OF-SELECTION.
*&------------------------------------------------------------------------*
*&      Form  FRM_GET_FN
*&------------------------------------------------------------------------*
*       text
*&---------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_get_fn .
  CALL FUNCTION 'KD_GET_FILENAME_ON_F4'
    CHANGING
      file_name = p_fn.
ENDFORM.                    " FRM_GET_FN
*&------------------------------------------------------------------------*
*&      Form  FRM_CREATE_DYNAMIC_TABLE
*&------------------------------------------------------------------------*
*       text
*&---------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_create_dynamic_table .

  DATA: lv_col_pos TYPE i.
  DATA: lr_tabdescr TYPE REF TO cl_abap_structdescr,
        lt_dfies    TYPE ddfields,
        ls_dfies    TYPE dfies.

  lr_tabdescr ?= cl_abap_structdescr=>describe_by_name( 'INRIV' ).
  lt_dfies = cl_salv_data_descr=>read_structdescr( lr_tabdescr ).
  LOOP AT lt_dfies INTO ls_dfies.
    MOVE-CORRESPONDING ls_dfies TO gs_fieldcat.
    APPEND gs_fieldcat TO gt_fieldcat.
    CLEAR gs_fieldcat.
  ENDLOOP.

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog = gt_fieldcat
    IMPORTING
      ep_table        = gr_table.

  ASSIGN gr_table->* TO <gt_table>.


ENDFORM.
*&------------------------------------------------------------------------*
*&      Form  FRM_UPLOAD_DATA
*&------------------------------------------------------------------------*
*       数据上传
*&---------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_upload_data .

  DATA: lt_return TYPE bapiret2_t.

  gv_col_count = lines( gt_fieldcat ).
  CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
    EXPORTING
      filename                = p_fn
      i_begin_col             = 1
      i_begin_row             = 1
      i_end_col               = gv_col_count
      i_end_row               = 5000
*     sheet_name              = 1
    TABLES
      intern                  = gt_tab
    EXCEPTIONS
      inconsistent_parameters = 1
      upload_ole              = 2
      OTHERS                  = 3.
  IF sy-subrc = 0.
    DELETE gt_tab WHERE row = 1.  "删除字段名行

    LOOP AT gt_tab INTO gs_tab.
      AT NEW row.
        APPEND INITIAL LINE TO <gt_table> ASSIGNING <gs_struc>.
      ENDAT.
      ASSIGN COMPONENT gs_tab-col OF STRUCTURE <gs_struc> TO <gs_field>.
      IF sy-subrc = 0.
        <gs_field> = gs_tab-value.
      ENDIF.
    ENDLOOP.
  ENDIF.

ENDFORM.                    " FRM_UPLOAD_DATA
*&------------------------------------------------------------------------*
*&      Form  FRM_INPUT_DATA
*&------------------------------------------------------------------------*
*       数据更新
*&---------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_input_data .

  DATA: lv_error_occured   TYPE char1,
        lv_warning_occured TYPE char1.

  DATA: lt_error_iv  TYPE TABLE OF inriv,
        lt_intervals TYPE TABLE OF inriv,
        ls_intervals TYPE inriv.

  DATA: lt_interval_have TYPE STANDARD TABLE OF inriv,
        ls_interval_have TYPE inriv.

  CALL FUNCTION 'NUMBER_RANGE_INTERVAL_LIST'
    EXPORTING
      object                     = p_object
    TABLES
      interval                   = lt_interval_have
    EXCEPTIONS
      nr_range_nr1_not_found     = 1
      nr_range_nr1_not_intern    = 2
      nr_range_nr2_must_be_space = 3
      nr_range_nr2_not_extern    = 4
      nr_range_nr2_not_found     = 5
      object_not_found           = 6
      subobject_must_be_space    = 7
      subobject_not_found        = 8
      OTHERS                     = 9.

  MOVE-CORRESPONDING <gt_table> TO lt_intervals.

  LOOP AT lt_interval_have INTO ls_interval_have.
    READ TABLE lt_intervals INTO ls_intervals WITH KEY subobject = ls_interval_have-subobject
                                                      nrrangenr = ls_interval_have-nrrangenr
                                                      toyear = ls_interval_have-toyear.
    IF sy-subrc = 0.
      IF ls_intervals-procind <> 'D'.
        ls_intervals-procind = 'U'.
        MODIFY lt_intervals FROM ls_intervals INDEX sy-tabix.
      ENDIF.
    ELSE.
      APPEND ls_interval_have TO lt_intervals.
    ENDIF.
  ENDLOOP.

  CALL FUNCTION 'NUMBER_RANGE_UPDATE_INIT'
    EXPORTING
      object           = p_object
    EXCEPTIONS
      object_not_found = 1.
  IF sy-subrc <> 0.
    MESSAGE ID  sy-msgid TYPE sy-msgty NUMBER sy-msgno
                  WITH  sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
  CALL FUNCTION 'NUMBER_RANGE_INTERVAL_UPDATE'
    EXPORTING
      object          = p_object
*     subobject       = P_subobject
    IMPORTING
*     error           = lt_error
      error_occured   = lv_error_occured
      warning_occured = lv_warning_occured
    TABLES
      error_iv        = lt_error_iv
      interval        = lt_intervals.
  IF lv_error_occured = space.

    CALL FUNCTION 'NUMBER_RANGE_UPDATE_CLOSE'
      EXPORTING
        object          = p_object
      EXCEPTIONS
        no_changes_made = 1.  "#EC *

    COMMIT WORK AND WAIT.

    MESSAGE 'Number range import sucesss' TYPE 'S'.
  ELSE.
    MESSAGE 'Number range import ERROR' TYPE 'S' DISPLAY LIKE 'E'.
  ENDIF.

ENDFORM.

*&------------------------------------------------------------------------*
*&      Form  FRM_DOWNLOAD
*&------------------------------------------------------------------------*
*       模板下载
*&---------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*&---------------------------------------------------------------------*
FORM frm_download .

  DATA: lv_filename TYPE string, "下载文件名
        lv_wintitle TYPE string, "下载对话框标题名
        lv_filepath TYPE string, "文件路径
        lv_fullpath TYPE string. "全文件路径
  DATA lv_pos TYPE dd03l-position .

  CALL METHOD cl_gui_frontend_services=>file_save_dialog
    EXPORTING
      window_title = lv_wintitle     "对话框的标题
      file_filter  = '.xls'          "文件的filter
    CHANGING
      filename     = lv_filename      "保存的文件名
      path         = lv_filepath      "文件路径
      fullpath     = lv_fullpath      "全文件路径
*     USER_ACTION  =
    EXCEPTIONS
      cntl_error   = 1
      error_no_gui = 2
      OTHERS       = 3.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
  IF lv_fullpath IS NOT INITIAL.

    " 保存模版
    PERFORM frm_save_excel USING lv_fullpath.

    MESSAGE s208(00) WITH TEXT-011.
  ENDIF.
ENDFORM.                    " FRM_DOWNLOAD

*----------------------------------------------------------------------*
* *设置输出格式
*----------------------------------------------------------------------*
FORM frm_set_layout.

  CLEAR gs_layout.
  gs_layout-sel_mode = 'A'.   "设置行模式"
  gs_layout-cwidth_opt = 'X'.  "优化列宽设置"
  gs_layout-zebra = 'X'.       "设置斑马线"

ENDFORM.

*----------------------------------------------------------------------*
* **显示ALV
*----------------------------------------------------------------------*
FORM frm_display_alv.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = sy-repid           "当前程序
      is_layout_lvc            = gs_layout          "界面格式"
      it_fieldcat_lvc          = gt_fieldcat        "字段属性"
      i_callback_pf_status_set = 'SET_PF_STATUS'    "状态
      i_callback_user_command  = 'ALV_USER_COMMAND' "控制指令
    TABLES
      t_outtab                 = <gt_table>.

ENDFORM.

*----------------------------------------------------------------------*
*  响应触发事件
*----------------------------------------------------------------------*
FORM alv_user_command USING pv_ucomm LIKE sy-ucomm
      ps_selfield TYPE slis_selfield.

  DATA: lo_ref_grid TYPE REF TO cl_gui_alv_grid.

  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_ref_grid. "获取全局变量
  CALL METHOD lo_ref_grid->check_changed_data."获取响应事件
  ps_selfield-refresh = 'X'.

  CASE pv_ucomm."用户操作事件
    WHEN '&IMPORT'."导入
      PERFORM frm_input_data.
      CALL METHOD lo_ref_grid->check_changed_data."获取响应事件
      ps_selfield-refresh = 'X'.
    WHEN OTHERS.
  ENDCASE.

ENDFORM.

**定义界面状态栏
FORM set_pf_status
       USING pt_extab TYPE slis_t_extab.
  "参照程序 SAPLKKBL 里面的 STANDARD_FULLSCREEN
  SET PF-STATUS 'STANDARD'."自定义状态名称
ENDFORM.

*&------使用OLE操作EXCEL填充数据并导出
FORM frm_save_excel USING pv_fullpath TYPE string.

*  启动excel
  CREATE OBJECT gs_excel 'EXCEL.APPLICATION'.
  IF sy-subrc <> 0 .
    WRITE: / 'ERROR'.
    STOP.
  ENDIF.
*  启动工作簿
  CALL METHOD OF
    gs_excel
      'WORKBOOKS' = gs_workbook.
*  使excel不可视
  SET PROPERTY OF gs_excel 'VISIBLE' = 0.
*  建立worksheet
  SET PROPERTY OF gs_excel 'SHEETSINNEWWORKBOOK' = 1.          "如果是读取excel文件中的内容 则是直接打开工作簿第一页
  CALL METHOD OF
    gs_workbook
    'ADD'.
* 激活SHEET
  CALL METHOD OF
      gs_excel
      'WORKSHEETS' = gs_sheet
    EXPORTING
      #1           = 1.

  LOOP AT gt_fieldcat INTO gs_fieldcat.
    gv_count  = gv_count + 1.
    gv_length = gs_fieldcat-intlen.

    PERFORM frm_set_property USING gv_count gv_length.

    CALL METHOD OF gs_sheet 'Cells' = gs_cellhead EXPORTING #1 = 1 #2 = gv_count.
    SET PROPERTY OF gs_cellhead 'value' =  gs_fieldcat-scrtext_l.
  ENDLOOP.

* 存入文件
  GET PROPERTY OF gs_excel 'ACTIVESHEET' = gs_sheet.
  GET PROPERTY OF gs_excel 'ACTIVEWORKBOOK' = gs_workbook.
  WAIT UP TO 1 SECONDS.
  CALL METHOD OF
    gs_sheet
    'SAVEAS'
    EXPORTING
      #1 = pv_fullpath
      #2 = 1.    "将excel文件保存为 FN1   路径
  CALL METHOD OF gs_workbook 'CLOSE'. "关闭工作区
  CALL METHOD OF gs_excel 'QUIT'. " 退出excel

* 释放操作
  FREE OBJECT gs_sheet.
  FREE OBJECT gs_workbook.
  FREE OBJECT gs_excel.
  FREE OBJECT gs_range.
  FREE OBJECT gs_cellhead.

ENDFORM.

FORM frm_set_property USING pv_col TYPE i pv_length TYPE i.

  DATA lv_str TYPE string.
*  设置单元格格式带前导零
  CALL METHOD OF
      gs_sheet
      'Cells' = gs_cell1
    EXPORTING
      #1      = 2
      #2      = pv_col.  "起始单元格
  CALL METHOD OF
      gs_sheet
      'Cells' = gs_cell2
    EXPORTING
      #1      = 999
      #2      = pv_col.  "结束单元格
  CALL METHOD OF
      gs_sheet
      'gs_range' = gs_range
    EXPORTING
      #1      = gs_cell1
      #2      = gs_cell2. "设置区域(从3行1列 到 999行1列)
  DO pv_length TIMES.
    CONCATENATE lv_str '0' INTO lv_str.
  ENDDO.
  SET PROPERTY OF gs_range 'NumberFormatLocal' = lv_str."设置单元格格式

ENDFORM.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值