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

图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数据读取到内表后,还需对读取的内表数据遍历和写入到与客户表结构相似的内表中,然后才添加到客户表中,并根据执行的情况输出日志。

开发思路如图所示。

图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 <fs_value>.
  FIELD-SYMBOLS <fs_excel>  LIKE gt_excel.
  LOOP AT gt_excel ASSIGNING <fs_excel>.
    "将cust_stru的第col个字段分配给符号
    ASSIGN COMPONENT <fs_excel>-col OF STRUCTURE cust_stru TO <fs_value>.
    <fs_value> = <fs_excel>-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、部分函数组

2、常用函数模块

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容