SAP HCM 全网最详细历史工资导入解决方案


导读

历史工资结果:系统工资结果有几种方式,每个方式都有他特定的业务场景,今天使用的方式更多的考虑业务人员的角度,如果快速的收集数据并导入数据。目前开发的程序有三个,一个导入SAP标准表数据(万能导入程序),一个是整理T558B、一个是整理T558D数据,第一个是通过abap程序,因为能重复利用,另外两个是python编写的一次性程序。

作者:vivi,来源:osinnovation

1 主数据

导入工资结果主要是T558B、T558D,T558B是记录员工时间记录信息,例如工资核算12个月,那么就需要再系统导入12条数据。下图介绍下几个重要的字段,payty如果是奖金就填写A,如果是工资为空即可,paydt是工资的支付日期,permo是工资发放周期(例如本月发本月工资,发上月工资等)。如果是年终奖不需要填写,pabrj是工资发放年度,pabrp是发放月份,fpbeg是发放月的第一天,fpend是发放月的最后一天,seqnr_cd是工资的序号,是个流水号。

图片

T588D是根据seqnr与t588bseqnr_cd关联,然后就是多条工资项目,导入模版是多条存储方式,对产品设计角度而言没毛病,因为可以适配不同的企业,但是对于业务人员,想从列转到行的其实操作不是很方便,所以通过一个python写一个脚本把列转换成行。

图片

2 SCHEMA拷贝

因为标准提供一个版本,我们只需要复制对应的版本,然后稍微调整一下即可,我就是复制XLK0,我只要修改两个地方,一个是主数据的校验,不需要维护税相关信息,一个是RT表写入的时候有相关的序号。

图片

图片

3 自定义程序

①导入t558d与t558b的程序,导入模版第一行是表的字段名称,第二行是开始导入数据。因为叫万能程序,所以原则上可以导入任何表。

PARAMETER: P_TABLE(20).PARAMETER: p_file LIKE rlgrap-filename DEFAULT 'C:\config.xls'.SELECTION-SCREEN ULINE /1(70).SELECTION-SCREEN COMMENT /1(70) TEXT-001.SELECTION-SCREEN COMMENT /1(70) TEXT-002.tables: t510.data: it_t510 like table of t510 WITH HEADER LINE .DATA: dy_table TYPE REF TO data,  dy_line  TYPE REF TO data,      dy2_table type ref to data,      dy2_line  TYPE REF TO data,  ifc TYPE lvc_t_fcat,  xfc TYPE lvc_s_fcat.FIELD-SYMBOLS: <dyn_table> TYPE STANDARD TABLE,      <dyn_table_ori> TYPE STANDARD TABLE,  <dyn_wa>,      <DYN_WA_ORI>,  <dyn_field>,  <fs>,      <FS_ORI>.data: begin of it_header occurs 0,     col like ALSMEX_TABLINE-COL,     field(20),     end of it_header.AT SELECTION-SCREEN on value-request for p_file.  perform help_l_path.AT SELECTION-SCREEN.*  AUTHORITY-CHECK OBJECT 'Z_TABLE'*           ID 'TABLE' FIELD P_TABLE*           ID 'ACTVT' FIELD '02'.*   IF SY-SUBRC <> 0.*     MESSAGE E016(ZHXII) WITH P_TABLE.*   ENDIF.start-of-selection.  perform define_itab.  perform get_xls.  perform update_table.*&---------------------------------------------------------------------**&      Form  DEFINE_ITAB*&---------------------------------------------------------------------**       text*----------------------------------------------------------------------*FORM DEFINE_ITAB .  DATA: IT_FIELDS TYPE TABLE OF  DFIES WITH HEADER LINE.  data: l_tabname TYPE DDOBJNAME.  l_tabname = P_TABLE.  CALL FUNCTION 'DDIF_FIELDINFO_GET'    EXPORTING      TABNAME        = L_TABNAME    TABLES      DFIES_TAB      = It_fields[]*     FIXED_VALUES   =    EXCEPTIONS      NOT_FOUND      = 1      INTERNAL_ERROR = 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.  loop at it_fields.    break ibm_yangjf.    move-corresponding it_fields to xfc.    XFC-INTLEN = IT_FIELDS-LENG.    if it_fields-FIELDNAME = 'BETRG'.      xfc-intlen = 11.    endif.    append xfc to ifc.  endloop.  CALL METHOD cl_alv_table_create=>create_dynamic_table    EXPORTING      it_fieldcatalog = ifc    IMPORTING      ep_table        = dy_table.  CALL METHOD cl_alv_table_create=>create_dynamic_table    EXPORTING      it_fieldcatalog = ifc    IMPORTING      ep_table        = dy2_table.  assign dy_table->* to <dyn_table>.  assign dy2_table->* to <dyn_table_ori>.  CREATE DATA dy_line LIKE LINE OF <dyn_table>.  CREATE DATA dy2_line LIKE LINE OF <dyn_table_ori>.*同理设定指针  ASSIGN dy_line->* TO <dyn_wa>.  ASSIGN dy2_line->* TO <dyn_wa_ori>.ENDFORM.                    " DEFINE_ITAB*&---------------------------------------------------------------------**&      Form  GET_XLS*&---------------------------------------------------------------------**       text*----------------------------------------------------------------------*FORM GET_XLS .  DATA: l_intern   TYPE alsmex_tabline OCCURS 0 WITH HEADER LINE.  DATA: c_row        TYPE i VALUE 1,        c_col        TYPE i VALUE 1,        l_index    TYPE i,        l_msg(60)  TYPE c,        g_mod     TYPE d,        l_row(5)   TYPE n,        LI_LEN TYPE INT2,        L_CSTR(4).  CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'    EXPORTING      filename                = P_FILE      i_begin_col             = C_COL      i_begin_row             = C_ROW      i_end_col               = 50      i_end_row               = 9999    TABLES      intern                  = l_intern    EXCEPTIONS      inconsistent_parameters = 1      upload_ole              = 2      OTHERS                  = 3.  SORT l_intern BY row col.  l_row = c_row.  LOOP AT l_intern.    if l_intern-row = 1.      it_header-col = l_intern-col.      it_header-field = l_intern-VALUE.      append it_header.    else.      MOVE l_intern-col TO l_index.      read table it_header index l_index.      if sy-subrc = 0.        ASSIGN COMPONENT it_header-field OF STRUCTURE <dyn_wa> TO <fs>.        if sy-subrc = 0.          MOVE l_intern-value TO <fs>.        endif.      endif.      AT END OF row.        append <dyn_wa> to <dyn_table>.        IF P_TABLE = 'T510'.          MOVE-CORRESPONDING <DYN_WA> TO IT_T510.          APPEND IT_T510.        ENDIF.        clear <dyn_wa>.*          it_RECORD-rowno = l_row.*          APPEND it_RECORD.        g_mod = l_row MOD 100.        IF g_mod = 0.*          CONCATENATE c_progress0 l_row INTO l_msg SEPARATED BY space.*            progress_indicator: l_msg.        ENDIF.        l_row = l_row + 1.*          CLEAR  it_RECORD.      ENDAT.    ENDIF.  ENDLOOP.*删除空行ENDFORM.                    " GET_XLS*&---------------------------------------------------------------------**&      Form  help_l_path*&---------------------------------------------------------------------**       text*----------------------------------------------------------------------*FORM help_l_path.  DATA: l_help.  DATA: repid LIKE  d020s-prog,        dynnr LIKE sy-dynnr.  DATA: dynpread LIKE dynpread OCCURS 50 WITH HEADER LINE.  repid = sy-repid.  dynnr = sy-dynnr.  REFRESH dynpread.  dynpread-fieldname  = 'P_FILE'.  dynpread-stepl      = '0'.  APPEND dynpread.  CALL FUNCTION 'DYNP_VALUES_READ'    EXPORTING      dyname     = repid      dynumb     = dynnr    TABLES      dynpfields = dynpread.*  l_maske = ',*.*,'.  l_help = p_file+1(1).  IF l_help = ':'.*    l_def_path = l_path.  ENDIF.  LOOP AT dynpread. ENDLOOP.*  FILENAME = DYNPREAD-FIELDVALUE.  p_file = dynpread-fieldvalue.  IF p_file EQ space.*    CONCATENATE p_file '*.XLS' INTO p_file.    CONCATENATE P_FILE '*.TXT' INTO P_FILE.  ENDIF.  CALL FUNCTION 'WS_FILENAME_GET'    EXPORTING      def_filename     = p_file      def_path         = '\'      mask             = ',*.*'      mode             = 'O'      title            = text-104    IMPORTING      filename         = p_file    EXCEPTIONS      inv_winsys       = 01      no_batch         = 02      selection_cancel = 03      selection_error  = 04.  IF sy-subrc = 0.*    G_STEP = C_TOVALIDATE.  ENDIF. " okENDFORM.                    "HELP_L_PATH*&---------------------------------------------------------------------**&      Form  UPDATE_TABLE*&---------------------------------------------------------------------**       text*----------------------------------------------------------------------**  -->  p1        text*  <--  p2        text*----------------------------------------------------------------------*FORM UPDATE_TABLE .  if p_table = 'T510'.    MODIFY (P_TABLE) FROM TABLE IT_T510.  ELSE.    modify (p_table) from table <dyn_table>.  ENDIF.  IF SY-SUBRC = 0.    WRITE:/ '提交成功'.  ENDIF.ENDFORM.                    " UPDATE_TABLE

② 列转行程序

import pandas as pdimport numpy as np# 读取Excel文件file_path = 'E:\onedriver\OneDrive\Desktop\T558B2.xls'sheet2 = pd.read_excel(file_path, sheet_name='Sheet2', header=0)# 1. 提取列名(从第三列开始)columns_to_unpivot = sheet2.columns[2:].tolist()# 2. 按人员编号分组生成新序号sheet2['新序号'] = sheet2.groupby('人员编号').cumcount() + 1# 3. 行转列处理melted = pd.melt(    sheet2,    id_vars=['人员编号', '新序号'],    value_vars=columns_to_unpivot,      var_name='项目',    value_name='值')# 4. 排序并选择需要的列result = melted[['人员编号', '新序号', '项目', '值']]result = result.sort_values(by=['人员编号', '新序号', '项目']).reset_index(drop=True)# 5. 保存结果到新Excel文件(避免修改原文件)output_path = 'T558B2_processed.xlsx'with pd.ExcelWriter(output_path) as writer:    result.to_excel(writer, sheet_name='Sheet2', index=False)    # 创建空Sheet3    pd.DataFrame().to_excel(writer, sheet_name='Sheet3', index=False)print(f"处理完成!结果已保存到: {output_path}")print(f"原始数据行数: {len(sheet2)}")print(f"处理后数据行数: {len(result)}")print("处理后的数据结构:")print(result.head(8))  # 显示前8行作为示例

例如下面这个例子

图片

图片

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wl8511

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值