ABAP

Problem

Aus SAP heraus soll ein bestehendes PDF Dokument gedruckt werden. Das Dokument wurde nicht mittels Adobe Forms Service erstellt, sondern z.B.: über Dienste zum Objekt an einen Materialstammsatz abgelegt.

Auf dieser Seite ist beschrieben, wie ein PDF Dokument, welches im SAP Dokumentenmanagementsystem abgelegt ist oder mittels GUI_UPLOAD hochgeladen wurde, mittels ABAP ausgedruckt werden kann.

Das Beispielprogramm stammt nicht von mir, sondern aus der SAP Community. In dem Beitrag gibt es noch weitere Hinweise: https://archive.sap.com/discussions/thread/2114729

Ich habe lange nach einer passenden Lösung gesucht und hatte beim experimentieren Probleme mit dem Papierformat. Daher habe ich mich entschieden, diesen kurzen Artikel zu verfassen.

Hinweis

Beim Erstellen des PDF Dokuments muss darauf geachtet werden, dass es exakt DIN A4 Format hat. Andernfalls kommt es zu Problemen beim Drucken. Wird beispielsweise ein PowerPoint Dokument als PDF exportiert, wird als Papierformat 250mm x 190mm übernommen. Wird das Dokument von SAP auf den Drucker ausgegeben, wird der manuelle Papierschacht gewählt, da es kein Standard DIN Format ist.

Wird hingegen das PowerPoint Dokument als PDF gedruckt (z.B. PDFCreator) und hier fest A4 als Papierformat hinterlegt, kann das so erzeugte Dokument erfolgreich ausgegeben werden.

 

Lösung

*-----------------------------------------------------------------------------
* Drucken von bestehenden PDF Dokumenten (z.B. Dienste zum Objekt)
* direkt aus SAP heraus https://archive.sap.com/discussions/thread/2114729
*-----------------------------------------------------------------------------

    REPORT  z_print_pdf.

    TYPE-POOLS: abap, srmgs.

    PARAMETERS: p_prnds LIKE tsp01-rqdest OBLIGATORY DEFAULT 'LOCL',
                p_fname TYPE file_table-filename OBLIGATORY LOWER CASE,
                p_ncopi TYPE rspocopies OBLIGATORY DEFAULT '1',
                p_immed AS CHECKBOX.

*-----------------------------------------------------------------------------
* AT SELECTION-SCREEN ON VALUE REQUEST
*-----------------------------------------------------------------------------
    AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_fname.

      DATA: lv_rc     TYPE i,
            lv_filter TYPE string.

      DATA: lt_files TYPE filetable.

      FIELD-SYMBOLS: <fs_file> LIKE LINE OF lt_files.

      CONCATENATE 'PDF (*.pdf)|*.pdf|' cl_gui_frontend_services=>filetype_all INTO lv_filter.

      CALL METHOD cl_gui_frontend_services=>file_open_dialog
        EXPORTING
          file_filter = lv_filter
        CHANGING
          file_table  = lt_files
          rc          = lv_rc
        EXCEPTIONS
          OTHERS      = 1.
      IF sy-subrc NE 0 AND lv_rc EQ 0.
        MESSAGE 'Error' TYPE 'E' DISPLAY LIKE 'S'.
      ENDIF.
      READ TABLE lt_files ASSIGNING <fs_file> INDEX 1.
      IF sy-subrc EQ 0.
        p_fname = <fs_file>-filename.
      ENDIF.

*-----------------------------------------------------------------------------
* AT SELECTION-SCREEN
*-----------------------------------------------------------------------------

    AT SELECTION-SCREEN.

      DATA: lv_name   TYPE string,
            lv_result TYPE boolean.

      lv_name = p_fname.
      CALL METHOD cl_gui_frontend_services=>file_exist
        EXPORTING
          file   = lv_name
        RECEIVING
          result = lv_result
        EXCEPTIONS
          OTHERS = 1.
      IF sy-subrc NE 0.
        MESSAGE 'Bad file!' TYPE 'E' DISPLAY LIKE 'S'.
      ENDIF.

      IF lv_result NE abap_true.
        MESSAGE 'Bad file!' TYPE 'E' DISPLAY LIKE 'S'.
      ENDIF.

*-----------------------------------------------------------------------------
* START-OF-SELECTION
*-----------------------------------------------------------------------------
    START-OF-SELECTION.


      PERFORM process.

*-----------------------------------------------------------------------------
* PROCESS
*-----------------------------------------------------------------------------

    FORM process.

      DATA: lv_name    TYPE string,
            lv_size    TYPE i,
            lv_data    TYPE xstring,
            lv_retcode TYPE i.

      DATA: lt_file TYPE srmgs_bin_content.

      " Hochladen der Datei
      lv_name = p_fname.
      CALL METHOD cl_gui_frontend_services=>gui_upload
        EXPORTING
          filename   = lv_name
          filetype   = 'BIN'
        IMPORTING
          filelength = lv_size
        CHANGING
          data_tab   = lt_file
        EXCEPTIONS
          OTHERS     = 1.
      IF sy-subrc NE 0.
        MESSAGE 'Read file error!' TYPE 'E' DISPLAY LIKE 'S'.
      ENDIF.

      " Übertragen nach Hex String
      CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
        EXPORTING
          input_length = lv_size
        IMPORTING
          buffer       = lv_data
        TABLES
          binary_tab   = lt_file
        EXCEPTIONS
          failed       = 1
          OTHERS       = 2.
      IF sy-subrc NE 0.
        MESSAGE 'Binary conversion error!' TYPE 'E' DISPLAY LIKE 'S'.
      ENDIF.

      PERFORM print USING p_prnds lv_data CHANGING lv_retcode.
      IF lv_retcode EQ 0.
        WRITE: / 'Print OK' COLOR COL_POSITIVE.
      ELSE.
        WRITE: / 'Print ERROR' COLOR COL_NEGATIVE.
      ENDIF.

    ENDFORM.                    " PROCESS

*-----------------------------------------------------------------------------
* PROCESS
*-----------------------------------------------------------------------------

    FORM print USING    iv_prndst  TYPE rspopname
                        iv_content TYPE xstring
               CHANGING ev_retcode TYPE i.

      DATA: lv_handle    TYPE sy-tabix,
            lv_spoolid   TYPE rspoid,
            lv_partname  TYPE adspart,
            lv_globaldir TYPE text1024,
            lv_dstfile   TYPE text1024,
            lv_filesize  TYPE i,
            lv_pages     TYPE i.

      CLEAR: ev_retcode.

      " ADS Spoolauftrag öffnen
      CALL FUNCTION 'ADS_SR_OPEN'
        EXPORTING
          dest            = iv_prndst
          doctype         = 'ADSP'
          copies          = p_ncopi
          immediate_print = p_immed
          auto_delete     = ' '
        IMPORTING
          handle          = lv_handle
          spoolid         = lv_spoolid
          partname        = lv_partname
        EXCEPTIONS
          OTHERS          = 1.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

      " ADS Spool Pfad ermitteln
      CALL FUNCTION 'ADS_GET_PATH'
        IMPORTING
          ads_path = lv_globaldir.

      CONCATENATE lv_globaldir '/' lv_partname '.pdf' INTO lv_dstfile.

      " Übertragen der Daten in die neue Spoolfile
      OPEN DATASET lv_dstfile FOR OUTPUT IN BINARY MODE.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

      TRANSFER iv_content TO lv_dstfile.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

      CLOSE DATASET lv_dstfile.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

lv_pages = 1.

      lv_filesize = xstrlen( iv_content ).
      CALL FUNCTION 'ADS_SR_CONFIRM'
        EXPORTING
          handle   = lv_handle
          partname = lv_partname
          size     = lv_filesize
          pages    = lv_pages
          no_pdf   = ' '
        EXCEPTIONS
          OTHERS   = 1.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

      " Spoolauftrag abschließen
      CALL FUNCTION 'ADS_SR_CLOSE'
        EXPORTING
          handle = lv_handle
        EXCEPTIONS
          OTHERS = 1.
      IF sy-subrc NE 0.
        ev_retcode = 4.
        RETURN.
      ENDIF.

    ENDFORM.                    " PRINT

 

Wie in dem vorherigen Beispiel beschrieben, kann über die SharePoint API auch ein Listenelement erstellt werden. Dazu wird ein HTTP Post Methodenaufruf verwendet. Dieser Aufruf erwartet im Header zwingend die Angabe eines X-RequestDigest. Dieser Wert kann mit der API /_api/contextinfo ermittelt werden.

Das folgende Beispiel zeigt, wie man ein Listenelement aus SAP heraus erstellen kann.
... weiterlesen

Hier war es lange still, Zeit für einen neuen Beitrag. Das Thema hat mich einige Stunden gekostet. Ich hoffe es hilft dem ein oder anderen.

SharePoint bietet eine umfassende REST-API mit CRUD (Create Read Update Delete) Methoden an. Mit dieser API können z.B. Listenelemente gelesen und erstellt werden. Diese lässt sich auch in ABAP verwenden.

... weiterlesen

Die Texte einer BSP Applikation werden in dem Online Text Repository gespeichert (OTR) Dabei werden zwei Arten von Texten unterschieden, Kurztexte (max. 255 Zeichen) und Langtexte.

OTR

Das Online Text Repository dient zum Speichern und Verwalten von Texten. Die Texte können wiederverwendbar sein. Es können aber auch Texte abgelegt werden, die nicht wiederverwendet werden können. Jeder Text erhält eine eindeutige ID (GUID)

Kurztexte

Kurztexte sind maximal 255 Zeichen lang und können in anderen Applikationen wiederverwendet werden.

Anlegen

Aus dem Web Application Builder heraus lassen sich die verfügbaren Standardtexte anzeigen

Zudem können hier neue Texte erstellt werden.

Jeder Text erhält dabei einen eindeutigen Alias, über den er wiederverwendet werden kann.

Einbinden

Eingebunden wird der Text über seinen Alias Namen

<htmlb:group id    = "BASIC_DATA"
             title = "<%= OTR(SOTR_VOCABULARY_BASIC/BASIC_DATA) %>" >

Übersetzen

Zur Übersetzung kann die Transaktion SOTR_EDIT verwendet werden. Dazu einen Kurztext im Änderungsmodus öffnen und dann über Springen -> Übersetzung in die Übersetzung verzweigen.

Langtexte

Langtexte können länger als 255 Zeichen sein, sie werden aber nicht wiederverwendet. Außerdem sollte der Gebrauch von Langtexten sparsam verwendet werden (siehe weiter unten).

Anlegen/Einbinden

Das Anlegen und Einbinden erfolgt in einem Schritt. Zunächst muss der Text in einem <OTR> Tag eingebunden werden. Der Text wird hier in der Originalsprache abgelegt. Durch Aktivieren der Seite wird der Text automatisch im OTR angelegt, intern wird der (nach wie vor sichtbare Text) durch die GUID des OTR Textes ersetzt.

<htmlb:textView text = "<otr>Hier steht der ganz wichtige Text</otr>" />

Wird der Text nun nochmals im Original geändert und die Seite aktiviert, wird ein neuer OTR Text abgelegt. Dies führt zu zahlreichen, verwaisten Einträgen, wenn z.B. Rechtschreibfehler korrigiert werden.

Um einen fehlerhaften Eintrag zu korrigieren, muss man die SOTR_EDIT verwenden. AUF KEINEN FALL den fehlerhaften Eintrag in der BSP Applikation innerhalb des <OTR> Tags korrigieren.

Übersetzen

Die Übersetzung erfolgt direkt aus dem Web Application Builder.

Nur über diesen Weg ist eine korrekte Übersetzung gewährleistet. Wird die Übersetzung im SOTR_EDIT vorgenommen, kann der Verwendungsnachweis verloren gehen, wenn der Originaltext angepasst wird. Dies führt zu einem Verlust der Übersetzung.

Die Performance beim Datenzugriff per Table Expression entspricht dem Zugriff per READ Statement. Werden jedoch mehrere Komponenten einer Zeile benötigt und erfolgt der Zugriff auf jede Komponente einzeln, so erhöht sich die Laufzeit etwa um den Faktor [Anzahl angeforderter Komponenten]. Werden drei Komponenten einzeln gelesen, verdreifacht sich die Laufzeit. ... weiterlesen