on 08-05-2008 2:10 PM
Hi All,
I have a simple table on my web dynpro which displays a list of work orders and was just wondering if anyone can tell me the easiest way to send this list to a printer. Cant use the internet print button as the table only displays 10 rows at a time and there could be many more than this.
I was going to do it using the the Adobe LiveCycle Designer and and creating a adobe form but have just found out that needs the JAVA stack and we dont currently have that installed on our server. So while i look into wether we can get that installed does anyone know a simple way i could achieve the printing of these table rows!
Regards
Mart
I've done a simple little solution before where I just force the output of the internal table bound to the table UI element using the ALV Function Modules. I had originally written a little BSP utility class to do this - hence the importing parameters being the BSP structure for the Iterator or the column definitions and the BSP message object, but those are all things easy to adapt. I would drop the interator logic altogether and change the CL_BSP_MESSAGES object to the Web Dynpro Message Object. Here is the source code:
METHOD print.
****Method Parameters
*@78\QImporting@ ITAB TYPE REF TO DATA
*@78\QImporting@ ITERATOR TYPE REF TO IF_HTMLB_TABLEVIEW_ITERATOR OPTIONAL For Table Looping and Filtering
*@78\QImporting@ COL_DEF TYPE TABLEVIEWCONTROLTAB OPTIONAL STABLEVIEWCOLUMN
*@78\QImporting@ PRINT_OPTIONS TYPE SFPPRIP Form Processing: Print Parameters
*@78\QImporting@ MESSAGES TYPE REF TO CL_BSP_MESSAGES Business Server Pages (BSP) Messages
FIELD-SYMBOLS: <tab> TYPE table.
ASSIGN itab->* TO <tab>.
****This sample uses the new ALV Object Model - Only available in WebAS 640+
****It will have to be changed (perhaps to use field catalogs and REUSE_ALV)
****in WebAS 620
DATA: table TYPE REF TO cl_salv_table.
DATA: print_parameters TYPE pri_params,
valid_flag(1) TYPE c.
****Convert the Input Print Parameters (Designed for Adobe Forms)
****Into the ABAP List format
CALL FUNCTION 'GET_PRINT_PARAMETERS'
EXPORTING
authority = print_options-authority
copies = print_options-copies
cover_page = print_options-cover
data_set = print_options-dataset
department = print_options-division
destination = print_options-dest
expiration = print_options-lifetime
immediately = print_options-reqimm
layout = 'X_65_255'
list_name = print_options-suffix2
list_text = print_options-covtitle
new_list_id = print_options-reqnew
no_dialog = abap_true
receiver = print_options-receiver
release = print_options-reqdel
IMPORTING
out_parameters = print_parameters
valid = valid_flag
EXCEPTIONS
archive_info_not_found = 1
invalid_print_params = 2
invalid_archive_params = 3
OTHERS = 4.
IF sy-subrc <> 0 OR valid_flag NE abap_true.
messages->add_message2( condition = 'print'
message = 'Invalid Print Parameters'(e01) ).
RETURN.
ENDIF.
****Start List Processing with our Print Parameters
NEW-PAGE PRINT ON PARAMETERS print_parameters
NO DIALOG.
****Create the ALV Object Model
DATA: salv_msg TYPE REF TO cx_salv_msg.
DATA: error_string TYPE string.
TRY.
cl_salv_table=>factory(
EXPORTING
list_display = abap_true
IMPORTING
r_salv_table = table
CHANGING
t_table = <tab> ).
CATCH cx_salv_msg INTO salv_msg.
messages->add_message_from_exception( condition = 'print'
exception = salv_msg ).
EXIT.
ENDTRY.
****Process the Column Definitions
DATA: columns TYPE REF TO cl_salv_columns_table.
****Get a reference to the columns object and set the optimize width.
columns = table->get_columns( ).
columns->set_optimize( abap_false ).
DATA: l_col_def TYPE tableviewcontroltab.
DATA: iterator_error TYPE REF TO cx_sy_dyn_call_illegal_method.
****We have an iterator Class - Process it and get a columun defintion table
IF col_def IS INITIAL AND
iterator IS NOT INITIAL.
DATA: p_overwrites TYPE tableviewoverwritetab.
TRY.
iterator->get_column_definitions(
EXPORTING
p_tableview_id = 'itab'
CHANGING
p_column_definitions = l_col_def
p_overwrites = p_overwrites ).
CATCH cx_sy_dyn_call_illegal_method INTO iterator_error.
messages->add_message_from_exception( condition = 'print'
exception = iterator_error ).
EXIT.
ENDTRY.
*****User supplied a column definition table directly - us it
ELSEIF col_def IS NOT INITIAL.
l_col_def = col_def.
ENDIF.
****Adjust our column definition (otherwise know as Field Catalog) by the
****Iterator or Column Dfinition table.
IF l_col_def IS NOT INITIAL.
DATA: scrtext_l TYPE scrtext_l,
scrtext_m TYPE scrtext_m,
scrtext_s TYPE scrtext_s,
tooltip TYPE lvc_tip.
DATA: col TYPE salv_t_column_ref.
FIELD-SYMBOLS: <wa_col> LIKE LINE OF col,
<wa_col_def> LIKE LINE OF l_col_def.
****Get a listing of all columns
col = columns->get( ).
****Loop through all the columsn
LOOP AT col ASSIGNING <wa_col>.
****Read to see if the current columns is in our Iterator
READ TABLE l_col_def ASSIGNING <wa_col_def>
WITH KEY columnname = <wa_col>-columnname.
IF sy-subrc = 0.
****Field is in the iterator - set it visible.
<wa_col>-r_column->set_visible( abap_true ).
****Is there an override title in the Iterator - if yes
****use it for all the column headers of the output
IF <wa_col_def>-title IS NOT INITIAL.
scrtext_l = <wa_col_def>-title.
scrtext_m = <wa_col_def>-title.
scrtext_s = <wa_col_def>-title.
<wa_col>-r_column->set_long_text( scrtext_l ).
<wa_col>-r_column->set_medium_text( scrtext_m ).
<wa_col>-r_column->set_short_text( scrtext_s ).
ENDIF.
****Is there an override tooltip in the Interator - if yes
****ues it for the tooltip of the output (actually meaningless
****for only printing - but hey you never know what you might
****use this for in the future :)
IF <wa_col_def>-tooltipheader IS NOT INITIAL.
tooltip = <wa_col_def>-tooltipheader.
<wa_col>-r_column->set_tooltip( tooltip ).
ENDIF.
ELSE.
****Field is not in the Iterator - Hide it in the output
<wa_col>-r_column->set_visible( abap_false ).
ENDIF.
ENDLOOP.
ENDIF.
****Set the ALV to display (forces printing in the Dark = background or BSP)
table->display( ).
NEW-PAGE PRINT OFF.
messages->add_message2( condition = 'print'
message = 'Print Output is complete'(i01)
messagetype = 'I' ).
ENDMETHOD.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
One suggestion however, if you want to allow some sort of frontend printing; still send the list to the spool just not with print immediate. Then use the old function modules to conver the Spool Output to PDF. You can then display the PDF via WD and they can print it using their desktop printing. Converting the Spool to PDF will be a lot easier than design an Adobe Form to do your printing.
Hi there,
Me again, sorry about this but cant seem to work out what values im supposed to put into cl_wd_runtime_services=>attach_file_to_response. Do i need to actually create a pdf file on the users PC from the spool or can i do it without. plus what is the i_content parameter for?
Regards
Mart
cl_wd_runtime_services=>attach_file_to_response(
exporting
i_filename = 'alv_export.pdf'
i_content = l_string_pdf
i_mime_type = 'application/pdf'
i_in_new_window = abap_false
i_inplace = abap_false ).
>Do i need to actually create a pdf file on the users PC from the spool or can i do it without. plus what is the i_content parameter for?
i_content is the binary string with the content of the "file" you want to push to the client. After you convert the spool to the PDF you will have an internal table with the data that represents the PDF. Conver that internal table to a variable of type XSTRING. I like to use the conversion function modules in the SCMS_CONV function group. That is what you pass to this class method.
Hi Thomas,
I have now got it so that it tries to open the file but unfortunately once in the pdf reader it say the file has not been decoded correctly, Would it be possible to have a quick look at my code and let me know where i have gone wrong. My guess is that the problem will either be me using the wrong conversion FM or the wrong value in the 'INPUT_LENGTH' parameter for FM 'SCMS_BINARY_TO_XSTRING' or maybe even the i_mime_type paremeter should not be 'application/pdf'.
Cheers
Mart
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = gd_spool_nr
no_dialog = c_no
dst_device = c_device
IMPORTING
pdf_bytecount = gd_bytecount
TABLES
pdf = it_pdf_output.
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
INPUT_LENGTH = gd_bytecount
IMPORTING
BUFFER = l_string_pdf
TABLES
BINARY_TAB = it_pdf_output.
cl_wd_runtime_services=>attach_file_to_response(
exporting
i_filename = 'table_data.pdf'
i_content = l_string_pdf
i_mime_type = 'application/pdf'
i_in_new_window = abap_false
i_inplace = abap_false ).
Sorry I had forgotten about the very strange format that CONVERT_ABAPSPOOLJOB_2_PDF returns the data in. It is sort of binary data stored in a character field. If you do a direct translation on it (especially if you assume it is a binary table), then it corrupts the data. I haven't ran into this problem in years, mainly because when I was a customer I created one generic class method to solve it and then used it all over the place.
Here is a nice solution from Durairaj Athavan Raja:
LOOP AT witab INTO itab .
TRANSLATE itab USING ' ~'.
CONCATENATE output itab INTO output IN CHARACTER MODE.
ENDLOOP.
TRANSLATE output USING '~ ' .
witab is the PDF table returned from CONVERT_ABAPSPOOLJOB_2_PDF and output is a STRING. You can then use the SCMS function module to conver from a string to a binary string.
Thanks again for the quick responce,
unfortunately i am still getting the same not decoded correctly message:-( see code below) also I am presuming the i_filename = 'alv_export.pdf' statement is just a ramdom name and does not have to already exist anywhere?
Regards
Mart
DATA: it_pdf_output type STANDARD TABLE OF tline initial size 0,
wa_pdf_output like LINE OF it_pdf_output.
data: output type string.
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = gd_spool_nr
no_dialog = c_no
* dst_device = c_device
* IMPORTING
* pdf_bytecount = gd_bytecount
TABLES
pdf = it_pdf_output.
LOOP AT it_pdf_output INTO wa_pdf_output .
TRANSLATE wa_pdf_output USING ' ~'.
CONCATENATE output wa_pdf_output INTO output IN CHARACTER MODE.
ENDLOOP.
TRANSLATE output USING '~ ' .
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
TEXT = output
* MIMETYPE =
* ENCODING =
IMPORTING
BUFFER = l_string_pdf
* EXCEPTIONS
* FAILED = 1
* OTHERS = 2
.
cl_wd_runtime_services=>attach_file_to_response(
exporting
i_filename = 'alv_export.pdf'
i_content = l_string_pdf
i_mime_type = 'application/pdf'
i_in_new_window = abap_false
i_inplace = abap_false ).
Hi Thomas,
sorry me again, have had a bit of a play and have added the following code so that it now emails the spool to out with a PDF attachment and this seems to work ok, and sends the text in a pdf document ok. This means the problem must be something to do with the string to Xstring SCMS function module or cl_wd_runtime_services=>attach_file_to_response itsself and was just wondering if you had any ideas what i am doing wrong. No probs if not just thought id check before i move onto another method:-), which will probably be a call to a BSP html page to display the data in a printable format!
Regards
Mart
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = gd_spool_nr
no_dialog = c_no
* dst_device = c_device
IMPORTING
pdf_bytecount = gd_bytecount
TABLES
pdf = it_pdf_output.
* Transfer the 132-long strings to 255-long strings
LOOP AT it_pdf_output INTO wa_pdf_output.
TRANSLATE wa_pdf_output USING ' ~'.
CONCATENATE gd_buffer wa_pdf_output INTO gd_buffer.
ENDLOOP.
TRANSLATE gd_buffer USING '~ '.
DO.
wa_mess_att = gd_buffer.
APPEND wa_mess_att to it_mess_att.
SHIFT gd_buffer LEFT BY 255 PLACES.
IF gd_buffer IS INITIAL.
EXIT.
ENDIF.
ENDDO.
************************SEND EMAIL
DESCRIBE TABLE it_mess_att LINES gd_recsize.
CHECK gd_recsize > 0.
* Default subject matter
gd_subject = 'Subject'.
* gd_attachment_desc = 'Attachname'.
* CONCATENATE 'attach_name' ' ' INTO gd_attachment_name.
wa_mess_bod = 'Message Body text, line 1'.
APPEND wa_mess_att to it_mess_bod.
wa_mess_bod = 'Message Body text, line 2...'.
APPEND wa_mess_bod to it_mess_bod.
DATA: ld_error TYPE sy-subrc,
ld_reciever TYPE sy-subrc,
ld_mtitle type sodocchgi1-obj_descr,
ld_email type somlreci1-receiver,
ld_format TYPE so_obj_tp ,
ld_attdescription TYPE so_obj_nam ,
ld_attfilename TYPE so_obj_des ,
ld_sender_address type soextreci1-receiver,
ld_sender_address_type type soextreci1-adr_typ,
ld_receiver type sy-subrc.
data: t_packing_list type STANDARD TABLE OF sopcklsti1 ,
wa_packing_list like line of t_packing_list,
t_contents type STANDARD TABLE OF solisti1,
t_receivers type STANDARD TABLE OF somlreci1 ,
wa_receivers like LINE OF t_receivers,
t_attachment type STANDARD TABLE OF SOLISTI1 ,
t_object_header type STANDARD TABLE OF solisti1 ,
w_cnt type i,
w_sent_all(1) type c,
w_doc_data type sodocchgi1.
ld_email = gd_email.
ld_mtitle = 'Example .xls documnet attachment'.
ld_format = 'PDF'.
ld_attdescription = 'Attachname'.
* ld_attfilename = p_filename.
ld_sender_address = gd_email.
ld_sender_address_type = 'INT'.
* Fill the document data.
w_doc_data-doc_size = 1.
* Populate the subject/generic message attributes
w_doc_data-obj_langu = sy-langu.
w_doc_data-obj_name = 'SAPRPT'.
w_doc_data-obj_descr = ld_mtitle .
w_doc_data-sensitivty = 'F'.
* Fill the document data and get size of attachment
CLEAR w_doc_data.
READ TABLE it_mess_att into wa_mess_att INDEX w_cnt.
w_doc_data-doc_size =
( w_cnt - 1 ) * 255 + STRLEN( wa_mess_att ).
w_doc_data-obj_langu = sy-langu.
w_doc_data-obj_name = 'SAPRPT'.
w_doc_data-obj_descr = ld_mtitle.
w_doc_data-sensitivty = 'F'.
CLEAR t_attachment.
REFRESH t_attachment.
t_attachment[] = it_mess_att[].
* Describe the body of the message
CLEAR wa_packing_list.
REFRESH t_packing_list.
wa_packing_list-transf_bin = space.
wa_packing_list-head_start = 1.
wa_packing_list-head_num = 0.
wa_packing_list-body_start = 1.
DESCRIBE TABLE it_mess_bod LINES wa_packing_list-body_num.
wa_packing_list-doc_type = 'RAW'.
APPEND wa_packing_list to t_packing_list.
* Create attachment notification
wa_packing_list-transf_bin = 'X'.
wa_packing_list-head_start = 1.
wa_packing_list-head_num = 1.
wa_packing_list-body_start = 1.
DESCRIBE TABLE t_attachment LINES wa_packing_list-body_num.
wa_packing_list-doc_type = ld_format.
wa_packing_list-obj_descr = ld_attdescription.
wa_packing_list-obj_name = ld_attfilename.
wa_packing_list-doc_size = wa_packing_list-body_num * 255.
APPEND wa_packing_list to t_packing_list.
* Add the recipients email address
CLEAR wa_receivers.
REFRESH t_receivers.
wa_receivers-receiver = ld_email.
wa_receivers-rec_type = 'U'.
wa_receivers-com_type = 'INT'.
wa_receivers-notif_del = 'X'.
wa_receivers-notif_ndel = 'X'.
APPEND wa_receivers to t_receivers.
CALL FUNCTION 'SO_DOCUMENT_SEND_API1'
EXPORTING
document_data = w_doc_data
put_in_outbox = 'X'
sender_address = ld_sender_address
sender_address_type = ld_sender_address_type
commit_work = 'X'
IMPORTING
sent_to_all = w_sent_all
TABLES
packing_list = t_packing_list
contents_bin = t_attachment
contents_txt = it_mess_bod
receivers = t_receivers
EXCEPTIONS
too_many_receivers = 1
document_not_sent = 2
document_type_not_exist = 3
operation_no_authorization = 4
parameter_error = 5
x_error = 6
enqueue_error = 7
OTHERS = 8.
* Populate zerror return code
ld_error = sy-subrc.
* Populate zreceiver return code
LOOP AT t_receivers INTO wa_receivers.
ld_receiver = wa_receivers-retrn_code.
ENDLOOP.
***********************SEND EMAIL
>unfortunately i am still getting the same not decoded correctly message:-( see code below) also I am presuming the i_filename = 'alv_export.pdf' statement is just a ramdom name and does not have to already exist anywhere?
The filename supplied doesn't have to exist. It is just used as the proposal in the Save/Open Dialog. I just tested this same code sample in my system and it works just fine. Are you using Adobe Acrobat to view the file? You aren't using some 3rd party PDF reader by any chance? I don't really see any significant differences between my code and what you posted. Here is my coding:
METHOD onactionsubmit .
DATA lo_nd_spool_input TYPE REF TO if_wd_context_node.
DATA lo_el_spool_input TYPE REF TO if_wd_context_element.
DATA ls_spool_input TYPE wd_this->element_spool_input.
DATA lv_spool_id TYPE wd_this->element_spool_input-spool_id.
lo_nd_spool_input = wd_context->get_child_node( name = wd_this->wdctx_spool_input ).
lo_el_spool_input = lo_nd_spool_input->get_element( ).
lo_el_spool_input->get_attribute(
EXPORTING
name = `SPOOL_ID`
IMPORTING
value = lv_spool_id ).
data pdf_bytecount type i.
data pdf type STANDARD TABLE OF tline.
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = lv_spool_id
* NO_DIALOG = NO_DIALOG
* DST_DEVICE = DST_DEVICE
* PDF_DESTINATION = PDF_DESTINATION
IMPORTING
PDF_BYTECOUNT = PDF_BYTECOUNT
* PDF_SPOOLID = PDF_SPOOLID
* LIST_PAGECOUNT = LIST_PAGECOUNT
* BTC_JOBNAME = BTC_JOBNAME
* BTC_JOBCOUNT = BTC_JOBCOUNT
TABLES
PDF = PDF
EXCEPTIONS
ERR_NO_ABAP_SPOOLJOB = 1
ERR_NO_SPOOLJOB = 2
ERR_NO_PERMISSION = 3
ERR_CONV_NOT_POSSIBLE = 4
ERR_BAD_DESTDEVICE = 5
USER_CANCELLED = 6
ERR_SPOOLERROR = 7
ERR_TEMSEERROR = 8
ERR_BTCJOB_OPEN_FAILED = 9
ERR_BTCJOB_SUBMIT_FAILED = 10
ERR_BTCJOB_CLOSE_FAILED = 11
OTHERS = 12.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
data x_pdf type xstring.
data output type string.
data itab LIKE LINE OF pdf.
LOOP AT pdf INTO itab .
TRANSLATE itab USING ' ~'.
CONCATENATE output itab INTO output IN CHARACTER MODE.
ENDLOOP.
TRANSLATE output USING '~ ' .
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = output
* MIMETYPE = ' '
* ENCODING = ENCODING
IMPORTING
BUFFER = x_pdf
* EXCEPTIONS
* FAILED = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
cl_wd_runtime_services=>attach_file_to_response(
i_filename = 'table_data.pdf'
i_content = x_pdf
i_mime_type = 'application/pdf'
* i_in_new_window = ABAP_FALSE
* i_inplace = ABAP_FALSE
).
ENDMETHOD.
Admittedly the translate to retain the spaces during the concatenation is a little bit of a hack. If I remember right what I had done when I was a customer was to cast the data to binary to retain the spaces before the concatenate. I recreated this logic just now and tested it and it does work as well. You might try it.
DATA x_pdf TYPE xstring.
DATA output TYPE string.
DATA itab LIKE LINE OF pdf.
FIELD-SYMBOLS <wa_pdf> TYPE x.
FIELD-SYMBOLS:
<tab_line> TYPE ANY,
<text> TYPE x.
DATA:
encoding TYPE abap_encoding,
convout TYPE REF TO cl_abap_conv_out_ce,
text_len TYPE i.
encoding = '4110'.
CALL METHOD cl_abap_conv_out_ce=>create
EXPORTING
encoding = encoding
RECEIVING
conv = convout.
LOOP AT pdf ASSIGNING <tab_line>.
ASSIGN COMPONENT 0 OF STRUCTURE <tab_line> TO <text> CASTING TYPE x.
text_len = XSTRLEN( <text> ).
CALL METHOD convout->write
EXPORTING
n = text_len
data = <text>.
ENDLOOP.
CALL METHOD convout->get_buffer
RECEIVING
buffer = x_pdf.
Here is a link where you can download my component via SAPlink:
http://abap-sdn-examples-tpj.googlecode.com/files/WDYN_ZSPOOL_2_PDF.slnk
I assume that you are addressing me, although that is one of the most interesting misspellings of my name I have ever seen.
This thread is full of the source code one could use to both send table based data to the print spooler and then then covert it for sending via email attachment. Not sure what else you would need.
User | Count |
---|---|
83 | |
10 | |
10 | |
9 | |
7 | |
6 | |
5 | |
5 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.