1. 程式人生 > 實用技巧 >WDA學習(17):WDA excel upload && download

WDA學習(17):WDA excel upload && download

1.10 Excel upload && download

在WDA中實現excel上傳下載。

建立WDA Component,Z_TEST_WDA13。

1.建立Context上下文

建立上傳表節點

建立NODE:NODE_SFLIGHT,型別:SFLIGHT;

上傳檔案資訊節點:

建立NODE:NODE_UPLOAD_DATA

建立Attribute:FILENAME,型別String;

建立Attribute:FILETYPE,型別String;

建立Attribute:DATA,型別XString;

2.建立Layout檢視

建立E_FILEUP,FILEUPLOAD檢視控制元件,上傳檔案選擇操作;

建立E_BUTTON,BUTTON檢視控制元件,上傳動作;

建立E_BUTTON1,BUTTON檢視控制元件,下載動作;

建立E_TABLE,TABLE檢視控制元件,用來顯示上傳結果;

設定上傳按鈕text屬性,建立對應Action;

設定下載按鈕text屬性,建立對應Action;

繫結Context節點,data對應NODE_UPLOAD_DATA-DATA,fileName對應NODE_UPLOAD_DATA-FILENAME,mineType對應NODE_UPLOAD_DATA-FILETYPE;

選擇E_TABLE,右鍵選擇Creat Binding,繫結上下文節點Context;

3.實現Action等方法

實現SHOW_MSG方法

程式碼例項:

method SHOW_MSG .
  "顯示資訊
  DATA: l_current_controller TYPE REF TO if_wd_controller,
        l_message_manager    TYPE REF TO if_wd_message_manager.

  l_current_controller ?= wd_this->wd_get_api( ).
  CALL METHOD l_current_controller->get_message_manager
    RECEIVING
      message_manager 
= l_message_manager. * report message IF msg_type = 'S'. CALL METHOD l_message_manager->report_success EXPORTING message_text = msg. ELSEIF msg_type = 'E'. CALL METHOD l_message_manager->report_error_message EXPORTING message_text = msg. ELSEIF msg_type = 'I'. CALL METHOD l_message_manager->report_message EXPORTING message_text = msg. ENDIF. endmethod.
View Code

實現相應Action方法

建立INIT_SFLIGHT方法,初始化查詢sflight表資訊,並且繫結節點Context。

程式碼例項:

method INIT_SFLIGHT .
  DATA:lo_node TYPE REF TO if_wd_context_node.
  DATA:lt_sflight TYPE wd_this->Elements_node_sflight.
  DATA:ls_sflight LIKE LINE OF lt_sflight.

  "獲取節點
  lo_node = wd_context->get_child_node( name = 'NODE_SFLIGHT' ).
  "查詢資料
  SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_sflight FROM sflight.
  "繫結資料
  lo_node->bind_table( lt_sflight ).
endmethod.

初始化方法呼叫初始化init_sfight

method WDDOINIT .
  init_sflight( ).
endmethod.

實現上傳Action方法

method ONACTIONUPLOAD .
  DATA:lo_node TYPE REF TO if_wd_context_node.
  DATA:lt_node_sflight TYPE wd_this->Elements_node_sflight.
  DATA:ls_node_sflight LIKE LINE OF lt_node_sflight.
  "檔案節點資料
  DATA:ls_node_upload_data TYPE wd_this->Element_node_upload_data.
  "檔案資料
  DATA:lv_file TYPE xstring.

  "excel文件類物件
  DATA:lo_excel TYPE REF TO zcl_excel.
  "excel worksheet類物件
  DATA:lo_worksheet TYPE REF TO zcl_excel_worksheet.
  "異常類
  DATA:lf_cxexcel TYPE REF TO ZCX_EXCEL.
  "上傳excel
  DATA:cl_reader TYPE REF TO zif_excel_reader.
  "excel匯入內表
  TYPES:BEGIN OF s_excel,
      carrid TYPE string,
      connid TYPE string,
      fldate TYPE string,
      price TYPE string,
      currency TYPE string,
      planetype TYPE string,
      seatsmax TYPE string,
      seatsocc TYPE string,
      paymentsum TYPE string,
      END OF s_excel.
  DATA:lt_excel TYPE TABLE OF s_excel.
  DATA:ls_excel LIKE LINE OF lt_excel.
  "讀取行列數
  DATA:col_count TYPE I.
  DATA:row_count TYPE I.
  DATA:col TYPE I.
  DATA:row TYPE I.

  "獲取節點資料
  lo_node = wd_context->get_child_node( name = 'NODE_UPLOAD_DATA').
  lo_node->get_static_attributes( IMPORTING static_attributes = ls_node_upload_data ).
  lv_file = ls_node_upload_data-data.

  "是否選擇上傳檔案
  IF lv_file IS INITIAL.
    "報錯沒有選擇檔案
    wd_comp_controller->show_msg( msg = '請選擇上傳檔案' msg_type = 'E' ).
    RETURN.
  ENDIF.

  TRY.
      CREATE OBJECT lo_excel.
      "cl_reader物件
      CREATE OBJECT cl_reader TYPE zcl_excel_reader_2007.
      "載入檔案
      lo_excel = cl_reader->load( I_EXCEL2007 = lv_file ).
      lo_worksheet = lo_excel->get_active_worksheet( ).

      "獲取行數,列數,去掉首行
      row_count = lo_worksheet->get_highest_row( ) - 1.
      col_count = lo_worksheet->get_highest_column( ).

      DO row_count TIMES.
        row = sy-index + 1.
        CLEAR ls_excel.
        DO col_count TIMES.
          col = sy-index.
          CASE col.
            WHEN 1.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-carrid ).
            WHEN 2.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-connid ).
            WHEN 3.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-fldate ).
            WHEN 4.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-price ).
            WHEN 5.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-currency ).
            WHEN 6.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-planetype ).
            WHEN 7.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-seatsmax ).
            WHEN 8.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-seatsocc ).
            WHEN 9.
              lo_worksheet->get_cell( EXPORTING ip_column = col ip_row = row IMPORTING ep_value = ls_excel-paymentsum ).
          ENDCASE.

        ENDDO.
        APPEND ls_excel TO lt_excel.
      ENDDO.

      "是否上傳資料
      IF lt_excel IS INITIAL.
         wd_comp_controller->show_msg( msg = '上傳excel沒有資料' msg_type = 'E' ).
         RETURN.
      ENDIF.

      "將資料轉換指定型別
      LOOP AT lt_excel INTO ls_excel.
        MOVE-CORRESPONDING ls_excel TO ls_node_sflight.
        APPEND ls_node_sflight TO lt_node_sflight.
      ENDLOOP.

    CATCH ZCX_EXCEL INTO lf_cxexcel.
      "獲取錯誤資訊
      DATA:result TYPE string.
      CALL METHOD lf_cxexcel->IF_MESSAGE~GET_TEXT
        RECEIVING
          result = result.
      wd_comp_controller->show_msg( msg = result msg_type = 'E' ).
  ENDTRY.

  "獲取節點
  lo_node = wd_context->get_child_node( name = 'NODE_SFLIGHT' ).
  "繫結資料
  lo_node->bind_table( lt_node_sflight ).

endmethod.
View Code

實現下載Action方法

method ONACTIONDOWNLOAD .
  DATA:lo_node TYPE REF TO if_wd_context_node.
  DATA:lt_node_sflight TYPE wd_this->Elements_node_sflight.
  DATA:ls_node_sflight LIKE LINE OF lt_node_sflight.

  "excel文件類物件
  DATA:lo_excel TYPE REF TO zcl_excel.
  "excel worksheet類物件
  DATA:lo_worksheet TYPE REF TO zcl_excel_worksheet.
  "異常類
  DATA:lf_cxexcel TYPE REF TO ZCX_EXCEL.
  "style類
  DATA:lo_style TYPE REF TO zcl_excel_style.
  "style的guid,header
  DATA:lv_style_guid TYPE zexcel_cell_style.
  "文字樣式
  DATA:lv_style_guid_text TYPE zexcel_cell_style.
  "列選擇物件
  DATA:lo_column_dimension TYPE REF TO zcl_excel_worksheet_columndime.

  "下載顯示excel轉換
  DATA:cl_writer TYPE REF TO zif_excel_writer.
  DATA:xdata TYPE xstring.
  "列數對應字母
  DATA:col_alpha TYPE zexcel_cell_column_alpha.
  DATA:lv_row TYPE I.
  DATA:lv_column TYPE I.
  FIELD-SYMBOLS:<fs_value> TYPE ANY.

  TYPES:BEGIN OF s_excel,
     name TYPE string,
     desc TYPE string,
    END OF s_excel.
  DATA:out_excel TYPE TABLE OF s_excel.
  DATA:wa_excel LIKE LINE OF out_excel.
  "檔名
  DATA:filename TYPE string.

  "設定檔名
  filename = sy-datum && '.xlsx'.

  "獲取上下文節點資料
  lo_node = wd_context->get_child_node( name = 'NODE_SFLIGHT').
  lo_node->get_static_attributes_table( IMPORTING table = lt_node_sflight  ).

  "建立匯出欄位及描述
  wa_excel-name = 'CARRID'.
  wa_excel-desc = '航班ID'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'CONNID'.
  wa_excel-desc = 'ID'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'FLDATE'.
  wa_excel-desc = '航班日期'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'PRICE'.
  wa_excel-desc = '價格'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'CURRENCY'.
  wa_excel-desc = '幣別'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'PLANETYPE'.
  wa_excel-desc = '型別'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'SEATSMAX'.
  wa_excel-desc = '座位數'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'SEATSOCC'.
  wa_excel-desc = '已佔用'.
  APPEND wa_excel TO out_excel.
  wa_excel-name = 'PAYMENTSUM'.
  wa_excel-desc = '合計'.
  APPEND wa_excel TO out_excel.
  TRY.
      "建立excel物件
      CREATE OBJECT lo_excel.
      "獲得當前worksheet
      lo_worksheet = lo_excel->get_active_worksheet( ).
      "建立一個新style
      lo_style = lo_excel->add_new_style( ).
      "加粗
      lo_style->font->bold = abap_true.
      "字型大小
      lo_style->font->size = 11.
      "填充型別
      lo_style->fill->filltype = zcl_excel_style_fill=>c_fill_solid.
      "前景色
      lo_style->fill->fgcolor-rgb = 'FF66FFCC'.
      "背景色
      lo_style->fill->bgcolor-rgb = 'FF33CCFF'.
      "獲取style的編碼uuid
      lv_style_guid = lo_style->get_guid( ).
      "設定excel表頭
      LOOP AT out_excel INTO wa_excel.
        lv_column = sy-tabix.
        "將列數轉換成對應列字母
        col_alpha = zcl_excel_common=>convert_column2alpha( ip_column = lv_column ).
        lo_worksheet->set_cell( ip_column = col_alpha ip_row = 1 ip_style = lv_style_guid ip_value = wa_excel-desc ).
      ENDLOOP.

      CLEAR lv_column.
      CLEAR lv_row.
      LOOP AT lt_node_sflight INTO ls_node_sflight.
        lv_row = sy-tabix + 1.
        LOOP AT out_excel INTO wa_excel.
          lv_column = sy-tabix.
          "將列數轉換成對應列字母
          col_alpha = zcl_excel_common=>convert_column2alpha( ip_column = lv_column ).
          ASSIGN COMPONENT wa_excel-name OF STRUCTURE ls_node_sflight TO <fs_value>.
          lo_worksheet->set_cell( ip_column = col_alpha ip_row = lv_row ip_value = <fs_value> ).
        ENDLOOP.
      ENDLOOP.

      "cl_writer物件
      CREATE OBJECT cl_writer TYPE zcl_excel_writer_2007.
      xdata = cl_writer->write_file( lo_excel ).
      CALL METHOD cl_wd_runtime_services=>attach_file_to_response(
        EXPORTING
          I_FILENAME      = filename
          I_CONTENT       = xdata
          I_MIME_TYPE     = 'EXCEL'
          I_IN_NEW_WINDOW = abap_false
          I_INPLACE       = abap_false
      ).

    CATCH ZCX_EXCEL INTO lf_cxexcel.
      "獲取錯誤資訊
      DATA:result TYPE String.
      CALL METHOD lf_cxexcel->IF_MESSAGE~GET_TEXT
        RECEIVING
          result = result.
      wd_comp_controller->show_msg( msg = result msg_type = 'E' ).
  ENDTRY.
endmethod.
View Code

4.建立Application

  問題1:上傳日期格式時,匯出的excel顯示為日期格式xxxx/xx/xx,但是上傳時先轉換為文字格式,excel日期資料轉換為文字數字,ABAP並不能識別這個數字,並且轉換為對應日期。

ABAP中日期格式轉換Function:

CONVERT_DATE_TO_INTERNAL:日期轉換MM/DD/YYYY轉換為YYYYMMDD;

Excel中設定日期欄位為文字格式,日期格式:MM/DD/YYYY

程式碼例項:

   LOOP AT lt_excel INTO ls_excel.
        "轉換日期格式為abap內部日期格式
        DATA:lv_date TYPE S_DATE.
        CALL FUNCTION 'CONVERT_DATE_TO_INTERNAL'
          EXPORTING
            DATE_EXTERNAL                  = ls_excel-fldate
          IMPORTING
            DATE_INTERNAL                  = lv_date.
        MOVE-CORRESPONDING ls_excel TO ls_node_sflight.
        ls_node_sflight-fldate = lv_date.
        APPEND ls_node_sflight TO lt_node_sflight.
      ENDLOOP.
View Code

  問題2:匯出時,如果不額外設定,日期欄位自動和Excel的日期格式相匹配。但是再次原文件上傳時,日期格式自動轉換為文字格式時,就會出現問題1。

直接下載時,匯出為日期格式

ABAP中日期格式轉換Function:

CONVERT_DATE_TO_EXTERNAL:日期格式轉換YYYYMMDD轉換為MM/DD/YYYY。

程式碼例項:

IF wa_excel-name = 'FLDATE'.
            "日期格式處理
            DATA:lv_date TYPE S_DATE.
            DATA:lv_date_str TYPE string.
            ASSIGN COMPONENT wa_excel-name OF STRUCTURE ls_node_sflight TO <fs_value>.
            lv_date = <fs_value>.
            CALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL'
             EXPORTING
                DATE_INTERNAL                  = lv_date
             IMPORTING
                DATE_EXTERNAL                  = lv_date_str.
            lo_worksheet->set_cell( ip_column = col_alpha ip_row = lv_row ip_value = lv_date_str ).
          ELSE.
            ASSIGN COMPONENT wa_excel-name OF STRUCTURE ls_node_sflight TO <fs_value>.
            lo_worksheet->set_cell( ip_column = col_alpha ip_row = lv_row ip_value = <fs_value> ).
ENDIF.
View Code

  問題3:上傳錯誤資訊顯示欄位,如果出現條錯誤資訊,那麼錯誤資訊那一欄會很長,錯誤資訊在一行中換行顯示。

1.在NODE_SFLIGHT建立Attribute:MSG,資料型別STRING_TABLE

2.修改Layout,Creat Binding,將MSG加入顯示。

3.修改INIT_SFLIGHT方法,初始化時,設定錯誤資訊顯示效果

method INIT_SFLIGHT .
  DATA:lo_node TYPE REF TO if_wd_context_node.
  DATA:lt_sflight TYPE wd_this->Elements_node_sflight.
  DATA:ls_sflight LIKE LINE OF lt_sflight.
  DATA:lt_msg TYPE STRING_TABLE.
  DATA:ls_msg TYPE string.

  "獲取節點
  lo_node = wd_context->get_child_node( name = 'NODE_SFLIGHT' ).
  "查詢資料
  SELECT * INTO CORRESPONDING FIELDS OF TABLE lt_sflight FROM sflight.
  "初始化,模擬錯誤資訊
  LOOP AT lt_sflight INTO ls_sflight.
    CLEAR lt_msg[].
    ls_msg = '模擬錯誤資訊1;'.
    APPEND ls_msg TO lt_msg.
    ls_msg = '模擬錯誤資訊2;'.
    APPEND ls_msg TO lt_msg.
    ls_sflight-msg = lt_msg.
    MODIFY lt_sflight FROM ls_sflight.
    EXIT.
  ENDLOOP.

  "繫結資料
  lo_node->bind_table( lt_sflight ).
endmethod.
View Code