05模块化编程,A5-读取Excel数据到客户表

05模块化编程,A5-读取Excel数据到客户表_第1张图片
图5-A4 读取Excel数据到客户表

需求分析:

1、具体需求

本《读取Excel数据到客户表》有如下需求:

  1. 初始界面中可从本地电脑中选择Excel格式文件;
  2. 执行后,可将Excel中的数据写入到客户表(ZTCUSTOMER)中,同时显示写入日志。

2、开发分析

要达成本实践目标,主要通过功能函数,实现Excel文件的打开和数据的读取,分析有如下:

  1. 通过功能函数功能函数“WS_FILENAME_GET”可以选择文件,并在选择时可以过滤格式(本实践只读取Excel格式的文件);
  2. 功能函数“ALSM_EXCEL_TO_INTERNAL_TABLE”则可将指定Excel文件的指定范围(行列的开始结束)的数据读取到内表中,此内表由3个字段组成:ROW(行)、COL(列)、VALUE(值),即Excel数据读取到内表后,内表记录了每行每列的值,其结构与客户表是不同的;
  3. 因此在将Excel数据读取到内表后,还需对读取的内表数据遍历和写入到与客户表结构相似的内表中,然后才添加到客户表中,并根据执行的情况输出日志。

开发思路如图所示。

05模块化编程,A5-读取Excel数据到客户表_第2张图片
图5- 15 读取Excel数据开发思路

实践步骤:

本实践将会需要建立2个程序,一个是要在其他程序中包含的Include程序,另一个是输出列表数据的程序;2个程序都可以通过程序编辑器(SE38)即可完成,编写的代码将有如下几部分组成,按开发人员风格不同,其组成部分并非强制一致。

No 部分 说明
1 程序声明 声明本程序执行后是否包含标准标题,数据输出宽度和每页的行数量为多少
2 对象定义 定义要使用的结构等,以在程序执行过程中获得和输出数据
3 屏幕事件 调用子程序以能在界面中点击按钮选择Excel文件
4 获取和输出数据 调用通过子程序以实现Excel文件数据的获取和输出
5 子程序定义 定义子程序,并通过功能模块实现Excel文件的选择、文件数据的获取以及输出

1、程序声明

程序声明部分的代码如下:

REPORT zu0505_read_cust_from_excel NO STANDARD PAGE HEADING
       LINE-SIZE 120 LINE-COUNT 80.

通过如上代码,设定了此程序输出不使用标准页眉,页面宽度120个字符,页面高度为80行。

2、对象定义

对象定义部分的代码如下:

******对象定义*****
TYPES:BEGIN OF cust_mode,
        customerid   TYPE ztcustomer-customerid,
        customername TYPE ztcustomer-customername,
        contact      TYPE ztcustomer-contact,
        cphone       TYPE ztcustomer-cphone,
        cfax         TYPE ztcustomer-cfax,
        country      TYPE ztcustomer-country,
        city         TYPE ztcustomer-city,
        region       TYPE ztcustomer-region,
        address      TYPE ztcustomer-address,
        zipcode      TYPE ztcustomer-zipcode,
      END OF cust_mode.
DATA: cust_stru   TYPE cust_mode,
      cust_itab   TYPE TABLE OF cust_mode,
      gt_excel    TYPE TABLE OF alsmex_tabline WITH HEADER LINE,
      ztcust_stru TYPE ztcustomer.
PARAMETERS: p_file TYPE  rlgrap-filename MODIF ID m01.

如上代码,定义了一个类型cust_mode,并以此类型定义了一个结构cust_stru和一个内表cust_itab以获得和处理数据;并参考alsmex_tabline定义了一个含工作区的内表gt_excel以存储读取的Excel数据;同时参考了客户表ztcustomer定义两个一个结构ztcust_stru以将内表gt_excel的数据进行转换,以最终存储到ztcustomer表中。

最后,通过PARAMETERS,参考rlgrap-filename定义了变量p_file对应读取的Excel文件。

3、屏幕事件

屏幕事件部分的代码如下:

*&----------------------------------------------------------------------*
*& AT SELECTION-SCREEN 选择文件选择框时事件
*&----------------------------------------------------------------------*
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  PERFORM get_filename.

通过AT SELECTION-SCREEN ON事件,定义了当p_file字段发生请求时,执行其后的代码块;而本实践是希望能选择Excel文件进行后续数据的读取,因此,通过调用子例程get_filename以选择Excel文件,此子例程的定义在随后的《5、子程序定义》部分实现。

4、获取和输出数据

获取和输出数据部分的代码如下:

*&----------------------------------------------------------------------*
*& START-OF-SELECTION
*&----------------------------------------------------------------------*
START-OF-SELECTION.
  PERFORM read_excel.
  PERFORM output_data.

通过START-OF-SELECTION事件,定义了在选择Excel文件并点击执行后的操作,其中分别通过调用子程序read_excel和output_data,读取Excel文件中的数据和将数据写入到客户表及输出日志。

5、子程序定义

本实践包含了3个子程序,包括get_filename(选择Excel文件)、read_excel(读取Excel文件数据)和output_data(数据写入客户表及输出日志)。

1)get_filename(选择Excel文件)

本子程序的代码如下:

*&---------------------------------------------------------------------*
*&      FORM  GET_FILENAME
*&---------------------------------------------------------------------*
*       获得文件名称
*----------------------------------------------------------------------*
FORM get_filename.
  TRY.
      CALL FUNCTION 'WS_FILENAME_GET'
        EXPORTING
          mask             = ',Excel Files,*.xls*,CSV Files,*.csv,All files,*.*.'
          mode             = 'O'
        IMPORTING
          filename         = p_file
        EXCEPTIONS
          inv_winsys       = 01
          no_batch         = 02
          selection_cancel = 03
          selection_error  = 04.
  ENDTRY.
  IF p_file EQ ''.
    MESSAGE s050(zu03_mclass01) WITH '未选择文件!' DISPLAY LIKE 'E'.
  ENDIF.
ENDFORM.

如上代码调用了功能模块“WS_FILENAME_GET”以选择Excel文件并将文件名赋值给p_file,以待后续读取和处理数据;其中通过参数“mask”可以根据后缀过滤选择的格式,如如上代码,Excel文件的后缀为xls,CSV文件的后缀为.csv。

2)read_excel(读取Excel文件数据)

本子程序的代码如下:

*&---------------------------------------------------------------------*
*&      FORM  READ_EXCEL
*&---------------------------------------------------------------------*
*       获得文件名称
*----------------------------------------------------------------------*
FORM  read_excel.
  TRY.
      CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE'
        EXPORTING
          filename                = p_file
          i_begin_col             = 1
          i_begin_row             = 2
          i_end_col               = 100
          i_end_row               = 100
        TABLES
          intern                  = gt_excel
        EXCEPTIONS
          inconsistent_parameters = 1
          upload_ole              = 2
          OTHERS                  = 3.
      IF sy-subrc <> 0.
        MESSAGE s050(zu03_mclass01) WITH '文件打开失败,请注意是否文件已在进程中打开!'
                                    DISPLAY LIKE 'E'.
        LEAVE LIST-PROCESSING.
      ENDIF.
  ENDTRY.
  SORT gt_excel BY row col.

  FIELD-SYMBOLS .
  FIELD-SYMBOLS   LIKE gt_excel.
  LOOP AT gt_excel ASSIGNING .
    "将cust_stru的第col个字段分配给符号
    ASSIGN COMPONENT -col OF STRUCTURE cust_stru TO .
     = -value.    "对结构的字段进行赋值
    AT END OF row.
      APPEND cust_stru TO cust_itab.
      CLEAR cust_stru.
    ENDAT.
  ENDLOOP.
ENDFORM.

通过如上代码,定义了一个名为read_excel的子程序,此子程序首先通过调用功能模块“ALSM_EXCEL_TO_INTERNAL_TABLE”,根据屏幕事件中获得的文件名称(p_file),按指定行列范围,读取数据并存储于gt_excel中。

由于内表gt_excel的结构跟ztcustomer表的结构不同,不能直接append给ztcustomer表,因此在读取数据到gt_excel后,先将数据写入结构cust_stru中。而写入数据的方法可有不同,此处则通过ASSIGN COMPONENT 语句,将结构的各个字段分配给符号,随后对符号进行赋值,以指定结构的各个字段值;另外也可通过for语句,遍历gt_excel每行(row)的数据,按列(col)顺序将值(value)赋给cust_stru的各个字段。

每行数据读取到cust_stru后,是可以直接将数据插入(INSERT INTO)到客户表ztcustomer中的,而本实践中先append到内表cust_itab中,随后再遍历插入数据到客户表及输出日志。

3)output_data(数据写入客户表及输出日志)

本子程序的代码如下:

*&---------------------------------------------------------------------*
*&      FORM  OUTPUT_DATA
*&---------------------------------------------------------------------*
*       输出数据
*----------------------------------------------------------------------*
FORM output_data.
  WRITE:/5 '读取数据和导入日志如下:',
        /5(110) sy-uline,
        /5(3) '序号',  (8) '客户编号', (15) '客户名称',
          (8) '联系人',(10) '电话', (10) '传真',
          (6) '传真',  (6) '城市', (6) '区域',
          (10) '地址', (6) '邮编', (6) '日志',
        /5(110) sy-uline.
  LOOP AT cust_itab INTO cust_stru.
    WRITE:/5(3) sy-tabix, (8) cust_stru-customerid, (15) cust_stru-customername,
        (8) cust_stru-contact, (10) cust_stru-cphone, (10) cust_stru-cfax,
        (6) cust_stru-country, (6) cust_stru-city, (6) cust_stru-region,
        (10) cust_stru-address, (6) cust_stru-zipcode.
    TRY.
        MOVE-CORRESPONDING cust_stru TO ztcust_stru.
        INSERT INTO ztcustomer VALUES ztcust_stru.
    ENDTRY.
    IF sy-subrc = 0.
      WRITE:'已添加' INVERSE ON COLOR COL_POSITIVE.
    ELSE.
      WRITE:'已存在' INVERSE ON COLOR COL_GROUP.
    ENDIF.
  ENDLOOP.
ENDFORM.

通过如上代码,定义了一个名为output_data的子程序,在其中,首先通过WRITE语句输出标题信息;然后通过LOOP AT遍历cust_itab数据,输出各记录的内容,然后将数据插入到客户表中;最后根据执行的结果(成功则sy-subrc为0),输出日志。

将如上5部分代码合成一起,则可以实现本实践的需求。

本实践小结:常用功能函数

1、部分函数组

05模块化编程,A5-读取Excel数据到客户表_第3张图片

2、常用函数模块

05模块化编程,A5-读取Excel数据到客户表_第4张图片

你可能感兴趣的:(05模块化编程,A5-读取Excel数据到客户表)