Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member229729
Active Participant
2,384


Author                : Ramani Nagarajan

Title                     : Dynamic tray selection while printing forms through ABAP Code

Requirement

We all know that, any forms can be printed on the required Tray by setting the appropriate value to the "Resource Name" field in the design screen of the form and be activated.

But the current requirement is to set the "Resource-Name" attribute of both Smartforms (or) SAPScript dynamically just before the form is printed.

This article explains how to set it dynamically !!

Printing the forms on the required tray

Incase of Smart forms, currently there are 2 ways to print the forms on the required tray as below:

  1. By assigning the "Resource Name" attribute field on the Smartforms designer with the below values:


TRY01  for Tray-1

     TRY02  for Tray-2


     and so on  up to 9


   2. Or, by changing the default tray on the SPAD transaction



Incase of SAPScript, the above said point-1 is the only way



Challenges

There is no dynamic value assignment capability available for the field "Resource Name" on both the forms.   Owing to the best practice, an alternative way to be discovered for assigning the tray values at run time before the printing, instead of Hardcoding or changing the SPAD settings (incase of Smartforms).

Proposed solution

Upon exploring the SAP approach on the "Form printing", it is found that, the Print-Attribute entered in the design time of both Smartforms & SAPScript are Exported to Memory database table as below:

Incase of SAPScript    :      STXL(xx)

Incase of Smartforms  :      STXFCONTR(sf)

Below given is the screen shot of the Import Procedure being done by the Standard coding of SAP:



And the print routine, imports the Print Attributes from the above memory database table and assign it to printing.

Logic for proposed solution

  1. Import the relevant print attribute of the concerned form

  2. Keep a local copy of it

  3. Lock the Memory Database Table record

  4. Change the Resource Name with the required TRAY on the imported internal table

  5. Export the above modified internal table back to the Memory Database Table

  6. Call the Form Printing routine

  7. Export the Local Copy of internal tables from Step(2) back to the Memory Database Table

  8. Unlock the Memory Database Table


Code Snippet:

The complete code written on a Class named as "ZCL_PRNTR_ATTRIBUTE" is attached for reference.

There are 5 methods implemented as below:

  1. OPEN_FORM

  2. CLOSE_SMARTFORM

  3. CLOSE_SAPSCRIPT

  4. WRITE_SMARFORM

  5. WRITE_SAPSCRIPT

  6. REFRESH_MEMORY


Following steps are to be written in the Driver-Program in the same sequence:

(1) OPEN_FORM is the main form which is to be called through the Driver Program.

(2) <Existing print routine>  --> No change in these

(3) CLOSE_SMARTFORM or CLOSE_SAPSCRIPT is to be called

Note: Methods (4),(5),(6) are executed internally through other methods.  Hence, we do not need to call them.




How to invoke the coding?

Here is the screen shot for calling procedure through Driver-program:


Note: Highlighted rows are our new methods.
Class: ZCL_PRNTER_ATTRIBUTES
-------------------------------------------------------------
class-pool .
class ZCL_PRNTER_ATTRIBUTES definition
public
final
create public .

public section.

types:
tty_paragraphs TYPE STANDARD TABLE OF itcdp .
types:
tty_tabs TYPE STANDARD TABLE OF itcdq .
types:
tty_strings TYPE STANDARD TABLE OF itcds .
types:
tty_tx_lines TYPE STANDARD TABLE OF tline .
types:
tty_windows TYPE STANDARD TABLE OF itctw .
types:
tty_page TYPE STANDARD TABLE OF itctg .
types:
tty_page_windows TYPE STANDARD TABLE OF itcth .
types:
tty_elements TYPE STANDARD TABLE OF itcce .
types:
tty_fonts TYPE STANDARD TABLE OF itcfg .

class-data GV_HEADER type SSFFORMHD .
class-data GV_REFTAB type TSFREF .
class-data GT_DOCSTRUC type TSFDOCSTRC .
class-data GT_TABDEF type TSFTABDEF .
class-data GT_FIELDS type TSFFIELDS .
class-data GV_SCR_HEADER type THEAD .
class-data GV_SCR_FORM_HEADER type ITCTA .
class-data GT_PARAGRAPHS type TTY_PARAGRAPHS .
class-data GT_TABS type TTY_TABS .
class-data GT_STRINGS type TTY_STRINGS .
class-data GT_FORM_LINES type TTY_TX_LINES .
class-data GT_WINDOWS type TTY_WINDOWS .
class-data GT_PAGE type TTY_PAGE .
class-data GT_PAGE_WINDOWS type TTY_PAGE_WINDOWS .
class-data GT_ELEMENTS type TTY_ELEMENTS .
class-data GT_FONTS type TTY_FONTS .

class-methods OPEN_FORM
importing
!I_SMARTFORM type TDSFNAME default ' '
!I_SCRIPTFORM type TDFORM default ' '
!IS_NAST type NAST optional .
class-methods WRITE_SMARTFORM
importing
!I_TRAYNUMBER type CHAR05
!I_FORMNAME type TDSFNAME .
class-methods WRITE_SAPSCRIPT
importing
!I_TRAYNUMBER type CHAR05
!I_FORMNAME type TDSFNAME
!IS_NAST type NAST .
class-methods CLOSE_SMARTFORM
importing
!I_FORMNAME type TDSFNAME .
class-methods CLOSE_SAPSCRIPT
importing
!I_SAPSCRIPT_NAME type TDFORM
!I_DEVICE type RSPOPNAME
!I_NAST type NAST optional .
class-methods REFRESH_MEMORY
importing
!I_FORMNAME type TDSFNAME .

protected section.

private section.
endclass. "ZCL_PRNTER_ATTRIBUTES definition

*"* local class implementation

METHOD close_sapscript.
CONSTANTS:
lc_form TYPE char04 value 'FORM',
lc_d TYPE c value 'D'.

DATA: lvpatype TYPE rspoptype.

DATA: BEGIN OF stxl_id,
tdobject TYPE stxl-tdobject,
tdname TYPE stxl-tdname,
tdid TYPE stxl-tdid,
tdspras TYPE stxl-tdspras,
END OF stxl_id.

DATA: lv_tdobj TYPE stxl-tdobject,
lv_tdnam TYPE stxl-tdname,
lv_tdid TYPE stxl-tdid,
lv_tdspr TYPE stxl-tdspras.
CHECK i_nast-ztray is not initial.
SELECT SINGLE patype INTO lvpatype FROM tsp03 WHERE padest = i_device.
IF sy-subrc EQ 0.
CLEAR stxl_id.
stxl_id-tdobject = lc_form.
stxl_id-tdspras = lc_d.
stxl_id-tdname(16) = i_sapscript_name.
stxl_id-tdname+16(8) = lvpatype.
if i_nast-spras is not initial.
stxl_id-tdname+24(1) = i_nast-spras.
else.
stxl_id-tdname+24(1) = sy-langu.
endif.
stxl_id-tdname+30(10) = sy-opsys.
stxl_id-tdid = sy-saprl.
ENDIF.

MOVE: lc_form TO lv_tdobj,
i_sapscript_name TO lv_tdnam,
sy-saprl TO lv_tdid,
sy-langu TO lv_tdspr.

* Revoking the status back to memory table with the Previous/ORIGINAL values
EXPORT
header = gv_scr_header
form_header = gv_scr_form_header
form_lines = gt_form_lines[]
paragraphs = gt_paragraphs[]
tabs = gt_tabs[]
strings = gt_strings[]
windows = gt_windows[]
pages = gt_page[]
page_windows = gt_page_windows[]
elements = gt_elements[]
fonts = gt_fonts[]
TO DATABASE stxl(xx) ID stxl_id.

COMMIT WORK AND WAIT.

* Unlock the SapScript record on the Memory Database
CALL FUNCTION 'DEQUEUE_EZRTSTXL'
EXPORTING
relid = 'XX'
tdobject = lv_tdobj
tdname = lv_tdnam
tdid = lv_tdid
tdspras = lv_tdspr.

ENDMETHOD.

METHOD close_smartform.
DATA: BEGIN OF l_fullname,
form TYPE tdsfname,
vari TYPE tdvariant,
actv TYPE tdbool,
END OF l_fullname.

l_fullname-form = i_formname.
l_fullname-actv = 'X'.

check gv_header is not initial.
* Exporting back with the old values of the table
EXPORT header = gv_header
reftab = gv_reftab
docstruc = gt_docstruc
tabdef = gt_tabdef
fields = gt_fields
TO DATABASE stxfcontr(sf)
ID l_fullname .

COMMIT WORK AND WAIT.
* Unlock the table
CALL FUNCTION 'DEQUEUE_EZSTXFCONTR'
EXPORTING
relid = 'X'
formname = l_fullname-form
actv = l_fullname-actv.


* Clear all the global variables
CLEAR: gv_header,
gv_reftab.
REFRESH: gt_docstruc,
gt_tabdef,
gt_fields.
ENDMETHOD.

METHOD open_form.
CONSTANTS:
c_try TYPE char03 VALUE 'TRY'.

DATA: w_traysel TYPE ztprint_forms,
w_form TYPE tdsfname,
w_devicetype TYPE rspolname,
w_trayno(2) TYPE n,
w_resource TYPE char05.
CLEAR gv_header.
IF i_scriptform IS NOT INITIAL.
MOVE i_scriptform TO w_form.
ENDIF.
IF i_smartform IS NOT INITIAL.
MOVE i_smartform TO w_form.
ENDIF.

CALL FUNCTION 'CONVERSION_EXIT_SPDEV_OUTPUT'
EXPORTING
input = is_nast-ldest
IMPORTING
output = w_devicetype.


IF is_nast-ztray IS NOT INITIAL.
MOVE is_nast-ztray TO w_trayno.
ELSE.
SELECT SINGLE *
FROM ztprint_forms INTO w_traysel
WHERE form = w_form
AND device = w_devicetype.
IF sy-subrc EQ 0.
MOVE w_traysel-tray TO w_trayno.
ENDIF.
ENDIF.
IF w_trayno IS NOT INITIAL.
CONCATENATE c_try w_trayno INTO w_resource.
ELSE.
CLEAR w_resource.
ENDIF.

CHECK w_resource is not initial.

IF i_smartform IS NOT INITIAL.
* Begin of change by Ramani for dec:8888004074
CALL METHOD zcl_prnter_attributes=>refresh_memory
EXPORTING
i_formname = i_smartform
.
* End of change by Ramani for dec:8888004074
CALL METHOD zcl_prnter_attributes=>write_smartform
EXPORTING
i_traynumber = w_resource
i_formname = w_form.
EXIT.
ENDIF.
IF i_scriptform IS NOT INITIAL.
CALL METHOD zcl_prnter_attributes=>write_sapscript
EXPORTING
i_traynumber = w_resource
i_formname = w_form
is_nast = is_nast.

EXIT.
ENDIF.
ENDMETHOD.

* Begin of insert by Ramani for dec:8888004074
METHOD refresh_memory.

DATA: lf_fm_name TYPE rs38l_fnam,
w_counter TYPE i,
w_fm_length TYPE i,
w_formname TYPE char50,
w_str1 TYPE char50,
w_str2 TYPE char50.
CONSTANTS:
lc_lbrkt TYPE c VALUE '(',
lc_rbrkt TYPE c VALUE ')',
lc_slash TYPE c VALUE '/',
lc_sapl TYPE char04 VALUE 'SAPL',
lc_header TYPE char07 VALUE '%HEADER'.
FIELD-SYMBOLS:
<header> TYPE ssfformhd,
<fs> TYPE ANY.

* Get the function-module name of the Smartform:
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = i_formname
IMPORTING
fm_name = lf_fm_name
EXCEPTIONS
no_form = 1
no_function_module = 2
OTHERS = 3.

CLEAR: w_counter.

* Splitting the smartform function-module into two strings:
DO.
w_counter = sy-index - 1.
IF lf_fm_name+w_counter(1) = lc_slash.
IF w_counter > 1.
w_counter = sy-index.
EXIT.
ENDIF.
ENDIF.
ENDDO.

w_str1 = lf_fm_name+0(w_counter).
w_fm_length = STRLEN( lf_fm_name ).
w_str2 = lf_fm_name+w_counter(w_fm_length).

* Attaching the SAPL string:
CONCATENATE lc_lbrkt w_str1
lc_sapl
w_str2
lc_rbrkt
lc_header
INTO w_formname.

CONDENSE w_formname.

* Clearing the stack variable:
ASSIGN (w_formname) TO <header>.

CHECK <header> IS ASSIGNED.
CLEAR: <header>.
UNASSIGN <header>.

ENDMETHOD.
* End of change by Ramani for dec:8888004074

METHOD write_sapscript.

DATA: wa_page TYPE itctg.
DATA: header TYPE thead.
DATA: form_header TYPE itcta.
DATA: paragraphs TYPE TABLE OF itcdp.
DATA: tabs TYPE TABLE OF itcdq.
DATA: strings TYPE TABLE OF itcds.
DATA: windows TYPE TABLE OF itctw.
DATA: pages TYPE TABLE OF itctg.
DATA: page_windows TYPE TABLE OF itcth.
DATA: form_lines TYPE TABLE OF tline.
DATA: elements TYPE TABLE OF itcce.
DATA: fonts TYPE TABLE OF itcfg.
DATA: lvpatype TYPE rspoptype,
lvpvers TYPE tsp0a-pvers.
DATA: BEGIN OF stxl_id,
tdobject TYPE stxl-tdobject,
tdname TYPE stxl-tdname,
tdid TYPE stxl-tdid,
tdspras TYPE stxl-tdspras,
END OF stxl_id.

DATA: lv_tdobj TYPE stxl-tdobject,
lv_tdnam TYPE stxl-tdname,
lv_tdid TYPE stxl-tdid,
lv_tdspr TYPE stxl-tdspras.
DATA: form TYPE itcta-tdform.
DATA: results TYPE itcrs . "#EC NEEDED

SELECT SINGLE patype INTO lvpatype FROM tsp03 WHERE padest = is_nast-ldest.
IF sy-subrc EQ 0.
CLEAR stxl_id.
stxl_id-tdobject = 'FORM'.
stxl_id-tdspras = 'D'.
stxl_id-tdname(16) = i_formname.
stxl_id-tdname+16(8) = lvpatype.
stxl_id-tdname+24(1) = is_nast-spras.
stxl_id-tdname+30(10) = sy-opsys.
stxl_id-tdid = sy-saprl.
ENDIF.

MOVE: 'FORM' TO lv_tdobj,
i_formname TO lv_tdnam,
sy-saprl TO lv_tdid,
sy-langu TO lv_tdspr.


CALL FUNCTION 'ENQUEUE_EZRTSTXL'
EXPORTING
mode_stxl = 'E'
mandt = sy-mandt
relid = 'XX'
tdobject = lv_tdobj
tdname = lv_tdnam
tdid = lv_tdid
tdspras = lv_tdspr
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.

IF sy-subrc EQ 0.

IMPORT
header TO header
form_header TO form_header
form_lines TO form_lines
paragraphs TO paragraphs
tabs TO tabs
strings TO strings
windows TO windows
pages TO pages
page_windows TO page_windows
elements TO elements
fonts TO fonts
FROM DATABASE stxl(xx) ID stxl_id.


form = i_formname.
IF sy-subrc NE 0 OR header IS INITIAL.
REFRESH pages.
CALL FUNCTION 'GENERATE_FORM'
EXPORTING
printer = lvpatype
form = form
language = is_nast-spras
IMPORTING
form_header = form_header
header = header
RESULT = results
TABLES
paragraphs = paragraphs
tabs = tabs
strings = strings
windows = windows
pages = pages
page_windows = page_windows
form_lines = form_lines
elements = elements
fonts = fonts.

SELECT SINGLE pvers FROM tsp0a INTO lvpvers WHERE patype = lvpatype.
form_header-pvers = lvpvers.
form_header-tdversion = 0.

ENDIF.

gv_scr_header = header.
gv_scr_form_header = form_header.
gt_form_lines[] = form_lines.
gt_paragraphs[] = paragraphs.
gt_tabs[] = tabs.
gt_strings[] = strings.
gt_windows[] = windows.
gt_page[] = pages.
gt_page_windows[] = page_windows.
gt_elements[] = elements.
gt_fonts[] = fonts.


* Update the Pages with the TRAYS
LOOP AT pages INTO wa_page.
wa_page-tdpaperres = i_traynumber.
MODIFY pages FROM wa_page.
ENDLOOP.
* Print the SAP Script
ENDIF.

CALL FUNCTION 'ENQUEUE_EZRTSTXL'
EXPORTING
mode_stxl = 'E'
mandt = sy-mandt
relid = 'XX'
tdobject = lv_tdobj
tdname = lv_tdnam
tdid = lv_tdid
tdspras = lv_tdspr.

* Setting the changed Tray Settings with the Memory Table
EXPORT
header FROM header
form_header FROM form_header
form_lines FROM form_lines[]
paragraphs FROM paragraphs[]
tabs FROM tabs[]
strings FROM strings[]
windows FROM windows[]
pages FROM pages[]
page_windows FROM page_windows[]
elements FROM elements[]
fonts FROM fonts[]
TO DATABASE stxl(xx) ID stxl_id.

COMMIT WORK AND WAIT.

ENDMETHOD.

METHOD write_smartform.
DATA: BEGIN OF l_fullname,
form TYPE tdsfname,
vari TYPE tdvariant,
actv TYPE tdbool,
END OF l_fullname.

DATA: l_header TYPE ssfformhd,
l_reftab TYPE tsfref,
l_docstruc TYPE TABLE OF ssfdocstrc,
l_tabdef TYPE tsftabdef,
l_fields TYPE tsffields,
w_docstruc TYPE ssfdocstrc.


l_fullname-form = i_formname.
l_fullname-actv = 'X'.

IMPORT header = l_header
reftab = l_reftab
docstruc = l_docstruc
tabdef = l_tabdef
fields = l_fields
FROM DATABASE stxfcontr(sf)
ID l_fullname .


gv_header = l_header.
gv_reftab = l_reftab.
gt_docstruc[] = l_docstruc.
gt_tabdef[] = l_tabdef.
gt_fields[] = l_fields.



LOOP AT l_docstruc INTO w_docstruc.
w_docstruc-tdpaperres = i_traynumber.
MODIFY l_docstruc FROM w_docstruc.
ENDLOOP.

CALL FUNCTION 'ENQUEUE_EZSTXFCONTR'
EXPORTING
mode_stxfcontr = 'E'
relid = 'SF'
formname = l_fullname-form
actv = l_fullname-actv
x_relid = ' '
x_formname = ' '
x_vari = ' '
x_actv = ' '
_scope = '2'
_wait = ' '
_collect = ' '
EXCEPTIONS
foreign_lock = 1
system_failure = 2
OTHERS = 3.
IF sy-subrc = 0.
EXPORT header = l_header
reftab = l_reftab
docstruc = l_docstruc
tabdef = l_tabdef
fields = l_fields
TO DATABASE stxfcontr(sf)
ID l_fullname .

COMMIT WORK AND WAIT.
ENDIF.
ENDMETHOD.
endclass. "ZCL_PRNTER_ATTRIBUTES implementation


How to utilize the attached code?
The code is a generic code, which can be used anywhere.  Hence, anyone can copy the code and use it.

**Caution:

During testing, please, let the driver program run the sequence as cited above fully.

Once the OPEN_FORM method is run, CLOSE_SMARTFORM/ CLOSE_SAPSCRIPT method also should be executed  sequentially.  Hence, do not abort the execution half the way.   This would leave the current print attribute values with the Memory Database Table.  To reset the values, we have to re-activate the Smartforms / SapScript by changing the Resourse-Name to blank.

Thanks for reading it!!

Ramani Nagarajan

7 Comments
Labels in this area