*---------------------------------------------------------------------*
*                        Z _ B J H _ E X C E L                        *
*                                                                     *
*                  Autor: Bernd Haase (BJH Software)                  *
*---------------------------------------------------------------------*
* Beispielprogramm, um von SAP Microsoft-Excel aufzurufen und ein     *
* Datenblatt der Tabelle mit Werten vorzubelegen. Zu Testzwecken      *
* sollen einige Felder der Positionen einer Bestellung angezeigt      *
* werden, die zuvor über Parameter selektiert wurden.                 *
*---------------------------------------------------------------------*
* (X) Excel_out                                                       *
*---------------------------------------------------------------------*
* 04.02.2004 BHaa: Programm erstellt                                  *
* 30.05.2005 BHaa: Bildschirmanzeige oder Hintergrundprozeß           *
*---------------------------------------------------------------------*
REPORT  z_bjh_excel .

TABLES:
 ekpo.             "Einkaufsbelegposition

DATA:
 wa_ekpo LIKE ekpo,

 itab_ekpo LIKE TABLE OF ekpo,

 anzahl(5) TYPE n,
 wa_wert(3) TYPE p DECIMALS 2.

*---------------------------------------------------------------------*
*                                                                     *
*                 A u s w a h l b i l d s c h i r m                   *
*                                                                     *
*---------------------------------------------------------------------*
* Eingabe der Bestellnummer
SELECTION-SCREEN: BEGIN OF BLOCK a1 WITH FRAME TITLE text-901.
PARAMETERS:
* Bestellnummer
 pmebeln LIKE ekpo-ebeln,
* Bildschirmanzeige (zeigt Excel am Bildschirm)
 pmx_bild RADIOBUTTON GROUP grp1 DEFAULT 'X',
* Hintergrund (es wird eine Datei gespeichert)
 pmx_job  RADIOBUTTON GROUP grp1,
* Dateiname (nur bei Hintergrundprozeß)
 pmout LIKE rlgrap-filename.
SELECTION-SCREEN: END OF BLOCK a1.

INITIALIZATION.
 pmout = 'c:/bjh/sap_excel.xls'.

***********************************************************************
*                                                                     *
*                     P R O G R A M M S T A R T                       *
*                                                                     *
***********************************************************************
START-OF-SELECTION.

* alle Positionen der ausgewählten Bestellung einlesen
 SELECT * FROM ekpo INTO wa_ekpo
 WHERE ebeln = pmebeln.
   APPEND wa_ekpo TO itab_ekpo.
 ENDSELECT.

* ermitteln, ob überhaupt Werte / Datensätze gefunden wurden und
* entsprechend weiter verzweigen
 DESCRIBE TABLE itab_ekpo LINES anzahl.

 IF anzahl = 0.
   WRITE: / 'Keine Positionen zur Bestellung', pmebeln, 'gefunden'.
 ELSE.
   PERFORM upro-excel.
 ENDIF.

END-OF-SELECTION.
 EXIT.

*---------------------------------------------------------------------*
*                              E X C E L                              *
*---------------------------------------------------------------------*
* Vorbesetzen und Füllen der Datenfelder einer Excel-Tabelle, alle    *
* Aktionen im Hintergrund.                                            *
*---------------------------------------------------------------------*
FORM upro-excel.

* Include-Baustein für OLE-Verarbeitungen
 INCLUDE ole2incl.

*******
* OLE *
*******
* globale Variablen für OLE-Call
 STATICS:
   excel       TYPE ole2_object,
   application TYPE ole2_object,
   books       TYPE ole2_object,
   book        TYPE ole2_object,
   sheet       TYPE ole2_object,
   cell        TYPE ole2_object,
   column      TYPE ole2_object.

* Zeilen- und Spaltenzähler innerhalb der Excel-Tabelle
 DATA:
   zeile        TYPE i,
   sp           TYPE i,
   chr_zeile(5) TYPE n,
   formel(80)   TYPE c.

* MS Excel ausführen mit OLE und Daten exportieren
 CREATE OBJECT excel 'EXCEL.SHEET'.
 IF sy-subrc <> 0.
* MS Excel konnte nicht per OLE gestartet werden
* Nachrichtenklasse und Fehlercode anpassen, als Platzhalter definiert
   MESSAGE ID 'SU' TYPE 'E' NUMBER '000' WITH text-001.

   EXIT.
 ENDIF.

 GET PROPERTY   OF excel 'Application'     = application.
* Hintergrund oder Bildschirmanzeige
 IF pmx_job = 'X'.
   SET PROPERTY OF application 'VISIBLE'   = 0.        "0 = unsichtbar
 ELSE.
   SET PROPERTY OF application 'Visible'   = 1.        "1 = sichtbar
 ENDIF.
 CALL METHOD    OF application 'Workbooks' = books.
* Wert muß an die vorherige Variable anknüpfen
 CALL METHOD    OF books       'Add'       = book.

* Das erste Datenblatt nehmen für die Kopfdaten
* die Anweisung 'No Flush' verhindert die direkte Ausführung des Befehls
* und generiert eine Queue mit allen Befehlen. Diese Queue wird über die
* Funktion 'Flush' ausgeführt.

* sheet = 1 bezeichnet das erste Datenblatt unter Excel
 CALL METHOD OF book 'Worksheets' = sheet NO FLUSH
                     EXPORTING #1 = 1.
* Namen des Datenblattes der Tabelle setzen
 SET PROPERTY OF sheet 'Name' = 'Bestellpositionen' no flush.

*---------------------------------------------------------------------*
* Überschriften einpflegen                                            *
* diese sollen in der zweiten Zeile stehen, beginnend mit der ersten  *
* Spalte und dann fortlaufend (fix/fest programmiert)                 *
* Exporting #1 = Zeile, #2=Spalte, Wertzuweisung über Set Property    *
*---------------------------------------------------------------------*
 zeile = 2.
 MOVE 1 TO sp.

 PERFORM upro-excel_w USING sheet cell zeile sp 'Bestellnummer'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Bestellposition'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Materialnummer'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Menge'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Bestellmengeneinheit'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Nettobestellwert'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Bruttobestellwert'.
 PERFORM upro-excel_w USING sheet cell zeile sp 'Prozentwert'.

*---------------------------------------------------------------------*
* Daten zeilenweise aufbereiten und einpflegen
* Daten werden ab Zeile 4 eingefügt, Spaltenzuordnung entsprechend der*
* Überschrift im Block zuvor
*---------------------------------------------------------------------*
 zeile = 3.

 LOOP AT itab_ekpo INTO wa_ekpo.
   ADD 1 TO zeile.
   MOVE 1 TO sp.

* Bestellnummer
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-ebeln.
* Bestellposition
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-ebelp.
* Materialnummer
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-matnr.
* Menge
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-menge.
* Bestellmengeneinheit
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-meins.
* Nettobestellwert
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-netwr.
* Bruttobestellwert
   PERFORM upro-excel_w USING sheet cell zeile sp wa_ekpo-brtwr.

* Summe (im Beispiel: wieviel Prozent bildet der Nettowert gegenüber
* dem Bruttowert)
   chr_zeile = zeile.
* bei Formel bitte die englischen Schreibweisen verwenden
   CONCATENATE '=SUM(F'    chr_zeile
               '* 100 / G' chr_zeile
               ')'
               INTO formel.
   CONDENSE formel.
   PERFORM upro-excel_w USING sheet cell zeile sp formel.

* Spaltenzähler wieder zu einen zurück, dieser soll auf das eben
* berechnete Ergebnis zeigen (Unterprogramm erhöht immer)
   SUBTRACT 1 FROM sp.
* um den Wert der Berechnung wieder zurückzuholen, wird nun umgekehrt
* verfahren und aus der Tabelle gelesen. Die übergebene Variable bleibt
* ohne weitere Nutzung, es soll nur das Verfahren erläutert werden
   PERFORM upro-excel_l
           USING sheet cell zeile sp wa_wert.
 ENDLOOP.

* optimale Weite der Spalten, im Beispiel wird dieses die Breite der
* Überschriften sein.
 CALL METHOD OF sheet 'Columns' = column NO FLUSH.
 FREE OBJECT sheet  NO FLUSH.
 CALL METHOD OF column 'Autofit' NO FLUSH.
 FREE OBJECT column NO FLUSH.

* für Hintergrundverarbeitung, Excelliste sichern und Excel verlassen
 IF pmx_job = 'X'.
   CALL METHOD OF book  'SaveAs' EXPORTING #1 = pmout.
   CALL METHOD OF books 'CLOSE'.
   CALL METHOD OF excel 'QUIT'.
 ENDIF.

* starten der Export-Queue über function call
 CALL FUNCTION 'FLUSH'.

* alle OLE-Objekte plattmachen in der entgegengesetzten Reihenfolge
* wie sie geöffnet wurden, LIFO-Prinzip
 FREE OBJECT: book, books, application, excel.

ENDFORM.

*---------------------------------------------------------------------*
*                       E X C E L _ W E R T E                         *
*---------------------------------------------------------------------*
* =>] sheet:                                                          *
* =>] cell:                                                           *
* =>] zeile:  Zeile, in welcher Excel den Wert ablegen soll           *
* <=> spalte: Spalte für den Wert, wird im Upro erhöht                *
* =>] wert:   Zelleninhalt,welcher an Reihe/Spalte gesetzt werden soll*
*---------------------------------------------------------------------*
FORM upro-excel_w
    USING sheet       TYPE ole2_object
          cell        TYPE ole2_object
          value(p_zeile)
                p_spalte
          value(p_wert).

 DATA:
   h_font TYPE ole2_object.

 CALL METHOD OF sheet 'Cells' = cell NO FLUSH
                EXPORTING #1 = p_zeile
                          #2 = p_spalte.

* Eigenschaften zur Excel-Zelle setzen
 SET PROPERTY OF cell 'Value' = p_wert no flush.

 GET PROPERTY OF cell 'Font'  = h_font.
* 1=Fettdruck oder 0=Normal
 SET PROPERTY OF h_font 'Bold'       = 1.
* Farben: 1=Schwarz, 2=weiss, 3=rot, 4=grün, 5=blau, 6=gelb      *
 SET PROPERTY OF h_font 'ColorIndex' = 4.
 SET PROPERTY OF h_font 'Size'       = 12.

* FREE OBJECT cell NO FLUSH.

 ADD 1 TO p_spalte.

ENDFORM.

*---------------------------------------------------------------------*
*                 E X C E L _ W E R T E _ L E S E N                   *
*---------------------------------------------------------------------*
* den Wert zu einer Zelle (Reihe / Spalte) einlesen und bekommen, um  *
* diesen dann anderswo weiterverarbeiten zu können                    *
*---------------------------------------------------------------------*
* ]=> p_wert: Wert, welcher in der Zelle zu der Reihe / Spalte        *
*             gespeichert ist                                         *
*---------------------------------------------------------------------*
FORM upro-excel_l
    USING sheet       TYPE ole2_object
          cell        TYPE ole2_object
          value(p_zeile)
                p_spalte
                p_wert.

 CALL METHOD OF sheet 'Cells' = cell NO FLUSH
                EXPORTING #1 = p_zeile
                          #2 = p_spalte.

 GET PROPERTY OF cell 'VALUE' = p_wert.

 ADD 1 TO p_spalte.

ENDFORM.

*---------------------------------------------------------------------*
* Zum Schluß noch ein paar Helferlein                                 *
*---------------------------------------------------------------------*
* Textformatierung. Um sicher zu gehen, daß eine Zahl als Text auch
* wirklich geschrieben wird und nicht als E-Zahl ('1.23E05'), sind 3
* Methodiken anwendbar

* 1.) Formatierung
*CALL METHOD OF excel 'COLUMNS' = columnObj
*     EXPORTING #1 = 2.                     "betroffene Spalte
*SET PROPERTY OF columnObj 'ColumnWidth' = 10.
*SET PROPERTY OF columnObj 'NumberFormat' = '@'.

* 2.) ab und an kann Schritt 1 nicht immer erfolgreich sein. Wenn nicht,
* sollten Sie es mit Hochkomma um die Zahl versuchen und diese dann
* übergeben

* 3.) wenn alle Daten geschrieben sind, kann auch mit der Markierfunk-
* tion versucht werden, Herr des problems zu werden

FORM f_copy_paste_special
    USING excel
          p_start_reihe
          p_end_reihe
          p_spalte.

*******
* OLE *
*******
* globale Variablen für OLE-Call
 STATICS:
   von_zelle TYPE ole2_object,
   bis_zelle TYPE ole2_object,
   range     TYPE ole2_object.

* Startpunkt setzen
 CALL METHOD OF excel 'CELLS' = von_zelle
      EXPORTING
           #1 = p_start_reihe
           #2 = p_spalte.

* Endpunkt setzen (es wird nur eine Spalte markiert
 CALL METHOD OF excel 'CELLS' = bis_zelle
      EXPORTING
           #1 = p_end_reihe
           #2 = p_spalte.

* den Bereich einstellen
 CALL METHOD OF excel 'RANGE' = range
      EXPORTING
           #1 = von_zelle
           #2 = bis_zelle.

* auswählen, kopieren und einfügen
 CALL METHOD OF range 'SELECT'.
 CALL METHOD OF range 'COPY'.
 CALL METHOD OF range 'PASTESPECIAL'
      EXPORTING
           #1 = 12. "paste value and format
*           #2 =
*           #3 = 'FALSE'
*           #4 = 'FALSE'.

 FREE OBJECT: von_zelle, bis_zelle, range.

ENDFORM.

***** Ende *****
* Copyright BJH Software, Datei überarbeitet am: 11.6.2005