Dieser Artikel beschreibt, wie man mehrere PDF Dokumente in ABAP zu einem Dokument zusammenführen kann. Dabei stammt ein Dokument aus dem KPRO Dokumentenmanagement (oder GOS). Das zweite Dokument wird mittels ADS erstellt.
Ausgangssituation und Hintergrund
Auf einem PDF Formular wird auf der Rückseite eine Zeichnung im TIF Format ausgegeben. Dazu wurde der XSTRING des Bildes aus dem KPRO gelesen und an das Formular übergeben. Hier wurde mittels eines Grafikknoten das Bild ausgegeben.
Neuere Zeichnungen liegen aber nicht mehr im TIF Format vor, sondern als 2D PDF. Zwar lässt sich auch bei dem PDF Dokument der XSTRING aus dem KPRO lesen, die Daten werden von dem Grafikknoten aber nicht korrekt interpretiert. Folglich bleibt die Rückseite des Dokuments leer.
Anforderung
Das bestehende PDF Dokument (Zeichnung) soll an das neu erzeugte PDF angehangen werden.
Lösung
Um das Problem zu lösen, kann das bestehende PDF und das neu erstellte mittels der Klasse cl_rspo_pdf_merge in ein Dokument vereint werden. Um dies zu erreichen, sind folgende Schritte erforderlich:
Job Öffnen
Beim Öffnen des Druckjobs muss das Feld GETPDF der Struktur IE_OUTPUTPARAMS gesetzt werden. Dies führt dazu, dass das Dokument nicht an den Drucker übergeben wird, sondern die binären Daten des PDF an das aufrufende Programm
METHOD job_open.
DATA: ls_outputpar TYPE sfpoutputparams.
ls_outputpar-copies = gv_copies.
ls_outputpar-dataset = gv_dataset.
ls_outputpar-suffix1 = gv_suffix1.
ls_outputpar-suffix2 = gv_suffix2.
ls_outputpar-title = gv_sptitle.
ls_outputpar-covtitle = gv_sptitle.
ls_outputpar-lifetime = gv_lifetime.
ls_outputpar-getpdf = abap_true. " Daten des PDF zurückgeben
ls_outputpar-reqdel = gv_del_print. " Löschen nach Ausgabe
ls_outputpar-reqnew = gv_sp_new. " Neuer Spoolauftrag
ls_outputpar-reqfinal = gv_sp_final. " Auftrag ist abgeschlossen
ls_outputpar-dest = gv_dest. " Ausgabegerät
ls_outputpar-reqimm = gv_sp_immed_print. " Sofortdruck
IF gv_show_dialog = gc_show_dialog.
ls_outputpar-nodialog = abap_false.
ls_outputpar-preview = abap_true.
ELSE.
* falls Ausgabegerät nicht gefüllt ist -> Benutzerdialog einschalten
IF ls_outputpar-dest IS INITIAL.
ls_outputpar-nodialog = abap_false. "Benutzerdialog einschalten
ls_outputpar-preview = abap_true. "Vorschau
ELSE.
ls_outputpar-nodialog = abap_true.
ls_outputpar-preview = abap_false.
ENDIF.
ENDIF.
CALL FUNCTION 'FP_JOB_OPEN'
CHANGING
ie_outputparams = ls_outputpar
EXCEPTIONS
cancel = 1
usage_error = 2
system_error = 3
internal_error = 4
OTHERS = 5.
IF sy-subrc <> 0.
...
ENDIF.
ENDMETHOD.
Dokument erstellen lassen
Nun wird mittels Aufruf des Formularbausteins, wie gewohnt, das Dokument erstellt. Wichtig ist hier, dass der Import Parameter /1bcdwb/formoutput entgegen nimmt. In dem Feld pdf stehen nun die binären Daten des erstellten PDF.
Anschließend wird mit der Klasse CL_RSPO_PDF_MERGE das erstellte PDF mit den Binärdaten des bereits bestehenden PDF (Zeichnung) kombiniert. Dazu wird die zunächst die Methode ADD_DOCUMENT aufgerufen. Nachdem alle Dokumente eingefügt wurden, wird die Methode MERGE_DOCUMENTS genutzt. Diese liefert die Binärdaten des neuen, kombinierten Dokuments zurück.
METHOD call_function_module.
DATA: lv_error_string TYPE string,
ls_output TYPE fpformoutput,
lv_merge type xstring.
* generierten FuBa aufrufen: PDF ausgeben
CALL FUNCTION gv_fmname
EXPORTING
/1bcdwb/docparams = gs_docparams
p_pardata_head = gs_pardata_head
p_pardata_target = gs_pardata_target
p_partxt = gs_partxt
p_docinfo = gs_docinfo
IMPORTING
/1bcdwb/formoutput = ls_output
EXCEPTIONS
usage_error = 1
system_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc NE 0.
CALL FUNCTION 'FP_GET_LAST_ADS_ERRSTR'
IMPORTING
e_adserrstr = lv_error_string.
ENDIF.
DATA(lo_cl_merge) = NEW cl_rspo_pdf_merge( ).
lo_cl_merge->add_document( ls_output-pdf ).
lo_cl_merge->add_document( gs_pardata_head-drawing ).
lo_cl_merge->merge_documents( IMPORTING merged_document = lv_merge ).
me->print_merged_pdf( lv_merge ).
ENDIF.
ENDMETHOD.
Drucken des kombinierten Dokuments
Das kombinierte Dokument muss nun an den Drucker gesendet werden. Da wir im ersten Schritt die Ausgabe an den Drucker verhindert haben, geschieht dies nicht mehr automatisch. Dazu habe ich folgende Methode erstellt. Zunächst wird ein neuer, leerer Spoolauftrag erzeugt. Anschließend wird der Dateipfad zu dem Spoolauftrag ermittelt, die Datei geöffnet und mit den Binärdaten des kombinierten PDF befüllt.
Mit Abschließen des Spoolauftrags mittels ADS_SR_CLOSE wird die Ausgabe an den Drucker gesendet.
METHOD print_merged_pdf.
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.
" Nur wenn Dateiinhalt vorliegt Dokument ausgeben
IF iv_content IS NOT INITIAL.
" ADS Spoolauftrag öffnen
CALL FUNCTION 'ADS_SR_OPEN'
EXPORTING
dest = me->gv_dest
suffix1 = me->gv_suffix1
suffix2 = me->gv_suffix2
titleline = conv RSPOTITLE( gv_sptitle )
doctype = 'ADSP'
copies = conv RSPOCOPIES( me->gv_copies )
immediate_print = me->gv_sp_immed_print
auto_delete = me->gv_del_print
IMPORTING
handle = lv_handle
spoolid = lv_spoolid
partname = lv_partname
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_ads_error
EXPORTING
textid = zcx_ads_error=>zcx_ads_error_form_open.
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 Spooldatei
OPEN DATASET lv_dstfile FOR OUTPUT IN BINARY MODE.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_ads_error
EXPORTING
textid = zcx_ads_error=>zcx_ads_error.
ENDIF.
TRANSFER iv_content TO lv_dstfile.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_ads_error
EXPORTING
textid = zcx_ads_error=>zcx_ads_error.
ENDIF.
CLOSE DATASET lv_dstfile.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_ads_error
EXPORTING
textid = zcx_ads_error=>zcx_ads_error.
ENDIF.
lv_pages = 2.
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.
...
ENDIF.
" Spoolauftrag abschließen
CALL FUNCTION 'ADS_SR_CLOSE'
EXPORTING
handle = lv_handle
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_ads_error
EXPORTING
textid = zcx_ads_error=>zcx_ads_error_form_close.
ENDIF.
ENDIF.
ENDMETHOD.
Verweise
https://blogs.sap.com/2019/06/01/convert-images-into-pdf-and-merge-with-an-existing-adobe-forms/