Generischer Excel-Upload

Mit diesem Programm können Sie relativ einfach Daten, die in Excel-Tabellen gespeichert sind, in eine Tabelle geladen werden. Es wird dafür ein Excel-Objekt erzeugt und die Exceltabelle im Hintergrund ausgelesen. Anhand der Eigenschaften der R/3-Tabelle wird ein Subroutinenpool erstellt, der das Einlesen und Speichern vornimmt.

Info

Bei Programmstart muss die Excel-Tabelle angegeben werden sowie die Zeile und Spalte, bei denen angefangen werden soll, die Daten einzulesen.

Zudem muss natürlich auch die Dictionary-Tabelle angegeben werden, in die die Daten gespeichert werden sollen.

Die Daten werden Zeilenweise von links nach rechts eingelesen.

Sobald eine leere Zeile kommt, wird das Einlesen abgebrochen.

Technische Informationen

  • Es wird eine rudimentäre Anpassung der Daten in der Routine GET_VALUE vorgenommen. Dabei wird die Formatierung in der Excel-Tabelle berücksichtigt. Diese Routine sollten Sie an Ihre eigenen Bedürfnisse anpassen.
  • Es wird dynamisch ein Subroutinen-Pool erzeugt. Dieser beinhaltet die Routine “UPLOAD_TABLE”. Sollte die Generierung fehlschlagen, wird der Fehler ausgegeben.
  • Es wird das Makro “_ASCL” benutzt (Add SourceCodeLine), um Quelltext an die interne Tabelle GT_QUELLTEXT zu hängen. Das Makro macht das Erzeugen sehr übersichtlich und bequem. Zudem können Variablen, wie “Programmname” oder “Dictionarytabelle” gleich ersetzt werden.
  • Das Programm erhebt keinen Anspruch auf generelle Fehlerfreiheit! Es beinhaltet alle notwendigen Funktionen, die eine Anpassung an eigene/ spezielle Bedürfnisse einfach machen. 

Quellcode

REPORT ZGUPL.
***********************************************************************
* Generischer Upload von Excel-Tabellen in R/3-Tabellen
***********************************************************************

INCLUDE OLE2INCL.

DATA:
  GV_SPALTE       TYPE I,
  GV_ZEILE        TYPE I,
  GV_FORMAT(30)   TYPE C,
  GV_TYPE         TYPE C,
  GV_VALUE(1000)  TYPE C,
  GV_LINE(1000)   TYPE C,
  GV_LEN          TYPE I,
  GV_TYPE_P(8)    TYPE P DECIMALS 4,
  GV_TYPE_N(100)  TYPE N,
  GV_TYPE_C(100)  TYPE N,

*** Subroutinenpool:
  GV_SUBROUTINEPOOL(30),
  GV_ERR_MESSAGE(200),
  GV_ERR_LINE     TYPE I,
  GT_QUELLTEXT    TYPE STANDARD TABLE OF LINE72,
  GV_QUELLTEXT    TYPE LINE72,
  GT_DD03L        LIKE DD03L OCCURS 0 WITH HEADER LINE,

*** Excel
  h_excel         TYPE ole2_object, ” Excel object
  h_book          TYPE ole2_object, ” list of workbooks
  h_active_window TYPE ole2_object,
  cell_out        TYPE ole2_object,                        ” cell
  cell_in         TYPE ole2_object.                        ” cell

*** Makro
DEFINE _ASCL.
*** Add Source-Code-Line ***
  GV_LINE = &1.
*** Tabellenname ersetzen
  REPLACE ‘%TAB%’ WITH P_R3TAB INTO GV_LINE.
  CONDENSE GV_LINE.
*** Programmname für externen Perform-Aufruf ersetzen
  REPLACE ‘%REPID%’ WITH SY-REPID INTO GV_LINE.
  CONDENSE GV_LINE.
*** ~Tilde durch Leerzeichen ersetzen
  TRANSLATE GV_LINE USING ‘~ ‘.
*** “Doppelte Anführungszeichen durch ‘einfache ersetzen
  TRANSLATE GV_LINE USING ‘””’.
*** Quellcode anhängen
  APPEND GV_LINE TO GT_QUELLTEXT.
END-OF-DEFINITION.

*** Selektionsbild
PARAMETERS:
  P_XLSDAT TYPE LOCALFILE DEFAULT ‘C:temptest.xls’, “Excel-Datei
  P_XLSCOL TYPE N         DEFAULT 1,                  “Start bei Spalte
  P_XLSROW TYPE N         DEFAULT 2,                  “Start bei Zeile
  P_R3TAB  TYPE TABELLE   DEFAULT ‘ZTEST’.            “R3-Tabelle


*** F4-Hilfe für Dateiname
AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_XLSDAT.

  CALL FUNCTION ‘F4_FILENAME’
       EXPORTING
            PROGRAM_NAME  = SYST-CPROG
            DYNPRO_NUMBER = SYST-DYNNR
            FIELD_NAME    = ‘P_XLSDAT’
       IMPORTING
            FILE_NAME     = P_XLSDAT.


*** Programmstart
START-OF-SELECTION.

  SELECT * FROM DD03L INTO TABLE GT_DD03L
   WHERE TABNAME = P_R3TAB.
  IF SY-SUBRC > 0.
    MESSAGE S000(VZ) WITH ‘Tabelle’ P_R3TAB ‘existiert nicht!’.
  ELSE.
    SORT GT_DD03L BY POSITION.
    PERFORM SUBROUTINEPOOL_BUILD.
    PERFORM SUBROUTINEPOOL_START.
  ENDIF.

*———————————————————————*
*       FORM START_EXCEL                                              *
*———————————————————————*

FORM START_EXCEL.

* start Excel
  CREATE OBJECT h_excel ‘EXCEL.APPLICATION’.

* Excel nicht sichtbar ausführen
  SET PROPERTY OF H_EXCEL ‘Visible’ = 0.

* Arbeitsblatt auswählen
  CALL METHOD OF h_excel ‘Workbooks’ = h_book.

* bestehendes File öffnen
  CALL METHOD OF h_book ‘OPEN’
       EXPORTING
          #1 = P_XLSDAT.

ENDFORM.

*———————————————————————*
*       FORM GET_VALUE                                                *
*———————————————————————*

FORM GET_VALUE USING F_ROW F_COL CHANGING F_VALUE.

  DESCRIBE FIELD F_VALUE TYPE GV_TYPE LENGTH GV_LEN.
*———————————————————–
* Zelle, aus der Ergebnis gelesen wird (C1)
  CALL METHOD OF h_excel ‘Cells’ = cell_in
       EXPORTING
          #1 = F_ROW                                        “Zeile
          #2 = F_COL.                                       “Spalte

* Zellinhalt lesen
  GET PROPERTY OF CELL_IN ‘Value’ = GV_VALUE.
  IF GV_VALUE = SPACE.
    CLEAR F_VALUE.
  ELSE.
* Zahlenformat
    GET PROPERTY OF CELL_IN ‘NumberFormat’ = GV_FORMAT.

    CASE GV_TYPE.
      WHEN ‘C’.
        CASE GV_FORMAT.
          WHEN ‘0’.
            GV_TYPE_P = GV_VALUE.
            WRITE GV_TYPE_P TO GV_TYPE_C(GV_LEN)
                            DECIMALS 0 RIGHT-JUSTIFIED.
            IF GV_TYPE_P > 0.
              SHIFT GV_TYPE_C BY 1 PLACES RIGHT.
            ENDIF.
            OVERLAY GV_TYPE_C WITH GV_TYPE_N.
            F_VALUE = GV_TYPE_C.
          WHEN ‘0.0’.
            GV_TYPE_P = GV_VALUE.
            WRITE GV_TYPE_P TO GV_TYPE_C(GV_LEN)
                            DECIMALS 1 RIGHT-JUSTIFIED.
            IF GV_TYPE_P > 0.
              SHIFT GV_TYPE_C BY 1 PLACES RIGHT.
            ENDIF.
            OVERLAY GV_TYPE_C WITH GV_TYPE_N.
            F_VALUE = GV_TYPE_C.
          WHEN ‘0.00’.
            GV_TYPE_P = GV_VALUE.
            WRITE GV_TYPE_P TO GV_TYPE_C(GV_LEN)
                            DECIMALS 2 RIGHT-JUSTIFIED.
            IF GV_TYPE_P > 0.
              SHIFT GV_TYPE_C BY 1 PLACES RIGHT.
            ENDIF.
            OVERLAY GV_TYPE_C WITH GV_TYPE_N.
            F_VALUE = GV_TYPE_C.
          WHEN ‘General’.
            F_VALUE = GV_VALUE.
          WHEN ‘@’. “Text
            IF GV_VALUE CO ‘ .0123456789’.
** Falls eine “Zahl” als “Text” formatiert ist, steht in
** GV_VALUE: “1234.00000”. Dies muss umgewandelt werden in “1234”.
              GV_TYPE_P = GV_VALUE.
              WRITE GV_TYPE_P TO GV_VALUE DECIMALS 0 NO-GROUPING
                                          LEFT-JUSTIFIED.
            ENDIF.
            F_VALUE = GV_VALUE.
          WHEN OTHERS.
            F_VALUE = GV_VALUE.
        ENDCASE.
      WHEN OTHERS.
        F_VALUE = GV_VALUE.
    ENDCASE.
  ENDIF. “Value <> space

ENDFORM.

*———————————————————————*
*       FORM STOPP_EXCEL                                              *
*———————————————————————*

FORM STOPP_EXCEL.

* Excel beenden
*———————————————————————–
* see
http://support.microsoft.com/default.aspx?scid=kb;de;503541
* Close without saving

* get active window
  CALL METHOD OF h_excel ‘ACTIVEWINDOW’ = h_active_window.
* set active_window visible
  SET PROPERTY OF h_active_window ‘VISIBLE’ = 1.
*———————————————————————–

* close active_window without saving
  CALL METHOD OF h_active_window ‘CLOSE’
       EXPORTING #1 = 0.

* close Excel
  CALL METHOD OF h_excel ‘QUIT’.
  FREE OBJECT: h_excel, h_active_window.

ENDFORM.

*———————————————————————*
*       FORM SUBROUTINEPOOL_BUILD                                     *
*———————————————————————*
FORM SUBROUTINEPOOL_BUILD.

  _ASCL:
    ‘REPORT zzz.’,
    ‘FORM UPLOAD_TABLE USING value(f_zeile)’,
    ‘                        value(f_spalte).’,
    ‘DATA gt_itab   LIKE %TAB% OCCURS 0 WITH HEADER LINE.’,
    ‘DATA lv_zeile  TYPE i.’,
    ‘DATA lv_spalte TYPE i.’,
    ‘PERFORM start_excel IN PROGRAM %REPID%.’,
    ‘LV_ZEILE  = f_zeile.’,
    ‘Do.’,
    ‘LV_SPALTE = f_spalte.’,
    ‘NEW-LINE.’,
    ‘CLEAR GT_ITAB.’.
  LOOP AT GT_DD03L.
    CHECK GT_DD03L-DATATYPE <> ‘CLNT’.
    _ASCL:
      ‘PERFORM GET_VALUE in Program %REPID%’,
      ‘USING lv_zeile lv_spalte CHANGING’.
    CONCATENATE ‘GT_ITAB-‘ GT_DD03L-FIELDNAME ‘.’ INTO GV_QUELLTEXT.
    _ASCL GV_QUELLTEXT.
    _ASCL ‘WRITE’.
    _ASCL GV_QUELLTEXT.

    _ASCL ‘ADD 1 TO lv_spalte.’.

  ENDLOOP.
  _ASCL:
    ‘IF GT_ITAB IS INITIAL.’,
    ‘WRITE “Ende….” COLOR col_positive.’,
    ‘EXIT.’,
    ‘ENDIF.’,
    ‘INSERT INTO %TAB% VALUES GT_ITAB.’,
    ‘WRITE sy-subrc COLOR = sy-subrc.’,
    ‘Add 1 to lv_zeile.’,
    ‘Enddo.’,
    ‘PERFORM STOPP_EXCEL IN PROGRAM %REPID%.’,
    ‘ENDFORM.’.

ENDFORM.

*———————————————————————*
*       FORM SUBROUTINEPOOL_START                                     *
*———————————————————————*

FORM SUBROUTINEPOOL_START.

*** Subroutinenpool mit Unterprogramm “UPLOAD_TABLE” generieren
  GENERATE SUBROUTINE POOL GT_QUELLTEXT NAME GV_SUBROUTINEPOOL
           MESSAGE GV_ERR_MESSAGE LINE GV_ERR_LINE.
  IF SY-SUBRC = 0.
*** Unterprogramm aufrufen
    PERFORM UPLOAD_TABLE IN PROGRAM (GV_SUBROUTINEPOOL)
      USING P_XLSROW P_XLSCOL.
  ELSE.
*** fehler
    FORMAT COLOR COL_TOTAL.
    WRITE: / ‘Fehler beim Generieren des Subroutinenpools:’,
           / GV_ERR_MESSAGE,
           / ‘Zeile’, GV_ERR_LINE,
           / ‘Returncode:’, SY-SUBRC.
    ULINE.
    LOOP AT GT_QUELLTEXT INTO GV_QUELLTEXT.
      IF SY-TABIX = GV_ERR_LINE.
        FORMAT COLOR COL_NEGATIVE.
      ELSE.
        FORMAT COLOR OFF.
      ENDIF.
      WRITE / GV_QUELLTEXT.
    ENDLOOP.
  ENDIF.

ENDFORM.

Enno Wulff