DMS attachments can be used to provide additional information, for example: Set of instructions for a work order which the personnel needs to carry out or additional details about purchase order. DMS attachments could be in PDF, word, excel format. DMS attachment is printed in foreground by default. These attachments can be saved on local system or shared folders.
In Plant maintenance user wants to print this DMS attachment and provide it to the personnel who is assigned the work order. These documents can be printed for an individual work order via IW32 menu option order->Print Order or Operation Selection. Work orders can also be printed in mass via transaction IW37N by selecting a bunch of work orders->Menu Option Order->Print Order.
During Mass printing from IW37N user expects the DMS attachments of one work order to be printed along that work order. For example if a user has selected 3 work orders to print, the 1st work order should be printed followed by its attachment(s) then the 2nd work order should print followed by its attachment(s) and then the 3rd work order and its attachment(s)
If DMS attachment is of PDF format, the PDF file takes long to get printed. The PDF files also open in foreground in acrobat reader and close only when the document has been printed out. After printing the PDF file closes however the acrobat reader still remains open.
SAP provides function module CVAPI_DOC_VIEW which takes document details as input for printing. This function module however does not provide any parameter to make the printing process synchronous i.e. if there are multiple attachments move to the 2nd attachment only when 1st one has completed printing or move to printing the the next work order only when all attachments of the preceding work order have been printed.
CALL FUNCTION 'CVAPI_DOC_VIEW'
EXPORTING
pf_dokar = <Doc Type>
pf_doknr = <Doc Number>
pf_dokvr = <Doc Version>
pf_doktl = <Doc Part>
pf_apptp = '3' " app type print = 3
pf_parent = blank
IMPORTING
pfx_file = lv_filename "File path
EXCEPTIONS
error = 1
not_found = 2
no_auth = 3
no_original = 4
OTHERS = 5.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
This can be resolved by using the method cl_gui_frontend_services=>execute to print, by passing the synchronous parameter as X. This however creates another problem. Lets understand this. We read above that PDF files open in acrobat reader and even after the file has been printed the acrobat application still remains open. since we are printing in mass and printing synchronously to maintain the sequence of work order followed by its attachments the program remains hung until the user manually closes the acrobat application.
CALL METHOD cl_gui_frontend_services=>execute
EXPORTING
document = <File path with filename to print>
synchronous = 'X' "until user closes acrobat application further processing does not happen
operation = 'PRINT'
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10.
IF sy-subrc NE 0.
* Implement suitable error handling here
ENDIF.
User is definitely not going to want to do so for every PDF attachment while printing in mass!
To resolve this we decided on sending the DMS attachment(PDF) data to spool. This can be achieved by using the ADS(Adobe Document Services) function modules provided by SAP.
Here goes the sample code. I am sure this will help a lot of us as I searched a lot and could not find solution that wasn’t suggesting to use a third party system.
DATA: it_pdf TYPE STANDARD TABLE OF tline,
lt_lines TYPE STANDARD TABLE OF tline,
lt_binary TYPE STANDARD TABLE OF raw255,
ls_pdf TYPE tline,
ls_binary TYPE raw255,
lv_content TYPE xstring,
lv_length TYPE sy-tabix,
lv_raw TYPE rsrd_rawstring,
lv_spool_id TYPE rspoid,
lv_partname TYPE adspart,
lv_fname_spool TYPE char256,
lv_dest TYPE rspopname,
lv_spool_handle TYPE sytabix.
FIELD-SYMBOLS <fs_x> TYPE x.
*upload the file: could be local system or shared folders
*lv_filename contains the file path with name . this can be found in DRAW table
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = lv_filename
filetype = 'BIN'
IMPORTING
filelength = lv_length
TABLES
data_tab = it_pdf.
*concatenate all data into one string
LOOP AT it_pdf INTO ls_pdf.
ASSIGN ls_pdf TO <fs_x> CASTING.
CONCATENATE lv_content <fs_x> INTO lv_content IN BYTE MODE.
ENDLOOP.
*convert form xstring to binary
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_content
IMPORTING
output_length = lv_length
TABLES
binary_tab = lt_binary.
LOOP AT lt_binary INTO ls_binary.
ASSIGN ls_binary TO <fs_x> CASTING.
CONCATENATE lv_raw <fs_x> INTO lv_raw IN BYTE MODE.
ENDLOOP.
*Open Spool
CALL FUNCTION 'ADS_SR_OPEN'
EXPORTING
dest = 'LCPD' " // your output device
doctype = 'ADSP'
immediate_print = 'X'
auto_delete = 'X'
IMPORTING
handle = lv_spool_handle
spoolid = lv_spool_id
EXCEPTIONS
device_missing = 1
no_such_device = 2
operation_failed = 3
wrong_doctype = 4
wrong_devicetype = 5
OTHERS = 6.
IF sy-subrc NE 0.
ENDIF.
*Reads the content of a part file of an ADS spool
CALL FUNCTION 'ADS_GET_PARTFILE_NAME'
EXPORTING
rqident = lv_spool_id
partnumber = 1
IMPORTING
partname = lv_partname.
CONCATENATE lv_partname '.pdf' INTO lv_fname_spool.
*write binary content to spool
CALL FUNCTION 'ADS_WRITE_TO_FILE'
EXPORTING
filename = lv_fname_spool
buffer = lv_raw
EXCEPTIONS
cannot_open_file = 1
open_dataset_no_authority = 2
open_dataset_internal_error = 3
open_dataset_too_many_files = 4
dataset_cant_close = 5
close_dataset_internal_error = 6
cannot_close_file = 7
cannot_transfer_data = 8
transfer_internal_error = 9
dataset_write_error = 10
OTHERS = 11.
*Write a line in an open ADS spool request
CALL FUNCTION 'ADS_SR_CONFIRM'
EXPORTING
handle = lv_spool_handle
partname = lv_partname
size = lv_length
pages = 1
IMPORTING
new_partname = lv_partname
EXCEPTIONS
handle_not_valid = 1
operation_failed = 2
OTHERS = 3.
*close the spool request
CALL FUNCTION 'ADS_SR_CLOSE'
EXPORTING
handle = lv_spool_handle
EXCEPTIONS
handle_not_valid = 1
operation_failed = 2
OTHERS = 3.
WAIT UP TO 10 SECONDS.
This way we can convert PDF data to spool without opening the acrobat reader. The wait statement allows us to maintain the sequence by waiting for a few seconds to let the PDF document finish printing. the method cl_gui_frontend_services=>execute can still be used to print word/excel files synchronously as these files do not take long to print. The whole code can be called in a loop for printing multiple attachments of same work order.
Original Article:
https://blogs.sap.com/2020/03/13/print-dms-attachments-in-backgroundmass-printing/