2014 Jun 06 12:37 PM
Hi All,
I want to copy all existing Z texts created in SO10 to text modules (the ones from TX SMARTFORMS). I have found absolutely no information. Google failed(!).
I decided to write my own report, but I don't know how to create text module. BDC is useless - You can create a text, but without any content (not mentioning translations).
There is class CL_SSF_FB_SMART_FORM. I use it to create text, I fill all necessary data (at least I think so), but after I call method "STORE", I receive text module without any text inside. Caption (element description) isn't populated neither.
How can I create text module using ABAP? Anyone tried it before?
Has anyone used CL_SSF_FB_SMART_FORM?
cheers,
Michał
2014 Jun 08 10:08 AM
Hi,
I tried and kind of succeeded, but trying to get Form Builder to work was not a pleasant experience for me as a beginner... There are a couple of "shortcuts" in the code (external perform to take care of Form Builder boilerplate, and a better Transport Connection may require redefining cl_ssf_fb_smart_form->SET_CORRECTION_REQUEST, and I didn't want to go there)... I hope you can build on it.
The idea of ZCL_SSF_TEXT_MODULE is to set up an Object that uses cl_ssf_fb_smart_form. ZJBTST1 is a Test report to ZCL_SSF_TEXT_MODULE.
Attention: this code can and will overwrite existing Text Modules and SmartForms - no prompts, no nothing!!! Use at own risk.
CLASS zcl_ssf_text_module DEFINITION
PUBLIC
FINAL
CREATE PRIVATE .
PUBLIC SECTION.
CLASS-METHODS create_from_itf_text
IMPORTING
!i_formname TYPE tdsfname DEFAULT 'ZJBTST1'
!i_caption TYPE tdtext DEFAULT 'Argh! Damn you, Form Builder!!'
!i_devclass TYPE devclass DEFAULT '$TMP'
!it_tsftext TYPE tsftext
RETURNING
value(ro_ssf_text_module) TYPE REF TO zcl_ssf_text_module
RAISING
cx_ssf_fb .
METHODS save
RAISING
cx_ssf_fb .
METHODS unlock .
PROTECTED SECTION.
PRIVATE SECTION.
DATA mo_form TYPE REF TO cl_ssf_fb_smart_form .
ENDCLASS.
CLASS ZCL_SSF_TEXT_MODULE IMPLEMENTATION.
METHOD create_from_itf_text.
DATA: lo_ssf_text_module TYPE REF TO zcl_ssf_text_module .
DATA: lo_text_item TYPE REF TO cl_ssf_fb_text_item .
DATA: ls_varheader TYPE ssfvarhdr .
DATA: l_devclass TYPE devclass .
DATA: l_master_language TYPE sylangu .
DATA: l_korrnum TYPE trkorr .
DATA: l_modif_language TYPE sylangu .
CREATE OBJECT lo_ssf_text_module .
* grrr!
CREATE OBJECT lo_ssf_text_module->mo_form .
* try to lock first
lo_ssf_text_module->mo_form->enqueue(
EXPORTING suppress_corr_check = space
language_upd_exit = space
master_language = sy-langu
mode = 'INSERT'
formname = i_formname
IMPORTING devclass = l_devclass
new_master_language = l_master_language
korrnum = l_korrnum
modification_language = l_modif_language
).
* init boilerplate
PERFORM create_default_text
IN PROGRAM saplstxb
CHANGING lo_ssf_text_module->mo_form.
* Take over attributes
lo_ssf_text_module->mo_form->header-formname = i_formname .
lo_ssf_text_module->mo_form->header-caption = i_caption .
lo_ssf_text_module->mo_form->header-devclass = i_devclass .
* get to the Text object
READ TABLE lo_ssf_text_module->mo_form->varheader
INTO ls_varheader INDEX 1 .
lo_text_item ?= ls_varheader-pagetree->obj .
* Take over text
lo_text_item->text[] = it_tsftext[] .
MODIFY lo_ssf_text_module->mo_form->varheader
FROM ls_varheader INDEX 1 .
* Return instance
ro_ssf_text_module = lo_ssf_text_module .
ENDMETHOD. "create_from_itf_text
METHOD save.
DATA: lx_ssf_fb TYPE REF TO cx_ssf_fb .
TRY .
me->mo_form->store(
EXPORTING
im_active = 'X' "Must always be active
im_formname = me->mo_form->header-formname
).
CATCH cx_ssf_fb INTO lx_ssf_fb .
me->unlock( ) .
RAISE EXCEPTION lx_ssf_fb .
ENDTRY .
ENDMETHOD. "save
METHOD unlock.
DATA: lo_ex TYPE REF TO cx_ssf_fb . "useless exception
TRY .
me->mo_form->dequeue( me->mo_form->header-formname ).
CATCH cx_ssf_fb .
SET EXTENDED CHECK OFF .
SET EXTENDED CHECK ON .
ENDTRY .
ENDMETHOD. "unlock
ENDCLASS.
REPORT zjbtst1 .
DATA: go_ssf_text_module TYPE REF TO zcl_ssf_text_module .
DATA: gx_ssf_fb TYPE REF TO cx_ssf_fb .
DATA: gt_text TYPE tsftext .
DATA: gs_text TYPE LINE OF tsftext .
PARAMETERS: p_form TYPE tdsfname DEFAULT 'ZJBTST1' .
INITIALIZATION .
REFRESH gt_text .
gs_text-tdline = |This was a miserable experience.| .
APPEND gs_text TO gt_text .
gs_text-tdline = |System time was: { sy-uzeit TIME = USER }.| .
APPEND gs_text TO gt_text .
START-OF-SELECTION .
TRY .
go_ssf_text_module = zcl_ssf_text_module=>create_from_itf_text(
i_formname = p_form
* i_caption = 'Argh! Damn you, Form Builder!!'
* i_devclass = '$TMP'
it_tsftext = gt_text
).
CATCH cx_ssf_fb INTO gx_ssf_fb .
MESSAGE gx_ssf_fb TYPE 'E' .
ENDTRY .
TRY .
go_ssf_text_module->save( ).
CATCH cx_ssf_fb INTO gx_ssf_fb .
MESSAGE gx_ssf_fb TYPE 'E' .
ENDTRY .
go_ssf_text_module->unlock( ) .
MESSAGE s080(smartforms) WITH p_form .
Attention: this code can and will overwrite existing Text Modules and SmartForms - no prompts, no nothing!!! Use at own risk.
If the thing does not work or you have questions, please do not hesitate to ask.
cheers,
Jānis
2014 Jun 08 10:08 AM
Hi,
I tried and kind of succeeded, but trying to get Form Builder to work was not a pleasant experience for me as a beginner... There are a couple of "shortcuts" in the code (external perform to take care of Form Builder boilerplate, and a better Transport Connection may require redefining cl_ssf_fb_smart_form->SET_CORRECTION_REQUEST, and I didn't want to go there)... I hope you can build on it.
The idea of ZCL_SSF_TEXT_MODULE is to set up an Object that uses cl_ssf_fb_smart_form. ZJBTST1 is a Test report to ZCL_SSF_TEXT_MODULE.
Attention: this code can and will overwrite existing Text Modules and SmartForms - no prompts, no nothing!!! Use at own risk.
CLASS zcl_ssf_text_module DEFINITION
PUBLIC
FINAL
CREATE PRIVATE .
PUBLIC SECTION.
CLASS-METHODS create_from_itf_text
IMPORTING
!i_formname TYPE tdsfname DEFAULT 'ZJBTST1'
!i_caption TYPE tdtext DEFAULT 'Argh! Damn you, Form Builder!!'
!i_devclass TYPE devclass DEFAULT '$TMP'
!it_tsftext TYPE tsftext
RETURNING
value(ro_ssf_text_module) TYPE REF TO zcl_ssf_text_module
RAISING
cx_ssf_fb .
METHODS save
RAISING
cx_ssf_fb .
METHODS unlock .
PROTECTED SECTION.
PRIVATE SECTION.
DATA mo_form TYPE REF TO cl_ssf_fb_smart_form .
ENDCLASS.
CLASS ZCL_SSF_TEXT_MODULE IMPLEMENTATION.
METHOD create_from_itf_text.
DATA: lo_ssf_text_module TYPE REF TO zcl_ssf_text_module .
DATA: lo_text_item TYPE REF TO cl_ssf_fb_text_item .
DATA: ls_varheader TYPE ssfvarhdr .
DATA: l_devclass TYPE devclass .
DATA: l_master_language TYPE sylangu .
DATA: l_korrnum TYPE trkorr .
DATA: l_modif_language TYPE sylangu .
CREATE OBJECT lo_ssf_text_module .
* grrr!
CREATE OBJECT lo_ssf_text_module->mo_form .
* try to lock first
lo_ssf_text_module->mo_form->enqueue(
EXPORTING suppress_corr_check = space
language_upd_exit = space
master_language = sy-langu
mode = 'INSERT'
formname = i_formname
IMPORTING devclass = l_devclass
new_master_language = l_master_language
korrnum = l_korrnum
modification_language = l_modif_language
).
* init boilerplate
PERFORM create_default_text
IN PROGRAM saplstxb
CHANGING lo_ssf_text_module->mo_form.
* Take over attributes
lo_ssf_text_module->mo_form->header-formname = i_formname .
lo_ssf_text_module->mo_form->header-caption = i_caption .
lo_ssf_text_module->mo_form->header-devclass = i_devclass .
* get to the Text object
READ TABLE lo_ssf_text_module->mo_form->varheader
INTO ls_varheader INDEX 1 .
lo_text_item ?= ls_varheader-pagetree->obj .
* Take over text
lo_text_item->text[] = it_tsftext[] .
MODIFY lo_ssf_text_module->mo_form->varheader
FROM ls_varheader INDEX 1 .
* Return instance
ro_ssf_text_module = lo_ssf_text_module .
ENDMETHOD. "create_from_itf_text
METHOD save.
DATA: lx_ssf_fb TYPE REF TO cx_ssf_fb .
TRY .
me->mo_form->store(
EXPORTING
im_active = 'X' "Must always be active
im_formname = me->mo_form->header-formname
).
CATCH cx_ssf_fb INTO lx_ssf_fb .
me->unlock( ) .
RAISE EXCEPTION lx_ssf_fb .
ENDTRY .
ENDMETHOD. "save
METHOD unlock.
DATA: lo_ex TYPE REF TO cx_ssf_fb . "useless exception
TRY .
me->mo_form->dequeue( me->mo_form->header-formname ).
CATCH cx_ssf_fb .
SET EXTENDED CHECK OFF .
SET EXTENDED CHECK ON .
ENDTRY .
ENDMETHOD. "unlock
ENDCLASS.
REPORT zjbtst1 .
DATA: go_ssf_text_module TYPE REF TO zcl_ssf_text_module .
DATA: gx_ssf_fb TYPE REF TO cx_ssf_fb .
DATA: gt_text TYPE tsftext .
DATA: gs_text TYPE LINE OF tsftext .
PARAMETERS: p_form TYPE tdsfname DEFAULT 'ZJBTST1' .
INITIALIZATION .
REFRESH gt_text .
gs_text-tdline = |This was a miserable experience.| .
APPEND gs_text TO gt_text .
gs_text-tdline = |System time was: { sy-uzeit TIME = USER }.| .
APPEND gs_text TO gt_text .
START-OF-SELECTION .
TRY .
go_ssf_text_module = zcl_ssf_text_module=>create_from_itf_text(
i_formname = p_form
* i_caption = 'Argh! Damn you, Form Builder!!'
* i_devclass = '$TMP'
it_tsftext = gt_text
).
CATCH cx_ssf_fb INTO gx_ssf_fb .
MESSAGE gx_ssf_fb TYPE 'E' .
ENDTRY .
TRY .
go_ssf_text_module->save( ).
CATCH cx_ssf_fb INTO gx_ssf_fb .
MESSAGE gx_ssf_fb TYPE 'E' .
ENDTRY .
go_ssf_text_module->unlock( ) .
MESSAGE s080(smartforms) WITH p_form .
Attention: this code can and will overwrite existing Text Modules and SmartForms - no prompts, no nothing!!! Use at own risk.
If the thing does not work or you have questions, please do not hesitate to ask.
cheers,
Jānis
2014 Jun 09 3:42 PM
Hello Jānis.
Thank You for Your help. I've compared Your code with mine and didn't know where is my mistake...
At the end of the day it occurred, that I haven't any. It's just that text is always created with original language 'DE', so when I press 'change', I see empty text as I was always creating text in EN (such a silly oversee).
I don't know why, but no matter what language I give as a "masterlang" in ENQUEUE, it always saves text with original language DE. Do You have any idea how to change it?
And the second challenge is: how to create other languages? I've just started playing with method ENQUEUE of class cl_ssf_fb_smart_form, and with parameter "mode" in method ENQUEUE, we'll see...
2014 Jun 09 8:34 PM
Hi,
There is the language to be passed to the store( ) method as well - if you don't pass it, it seems to be saved in sy-langu... I was able to create Texts in EN and DE when I took over new_master_language to header-masterlang and then passed it on to store( ). I changed my previous post to reflect the code changes.
The languages other than masterlang are probably easiest created using translation functionality in Function group STXBT, namely SSFTR_SET_TEXT. There the guys have "cut the OO crap" and done it directly in stxftxt table... That FM, however, does not let to set the caption...
There probably are good reasons why SAP programmed this stuff the way they did, and I may expect "gratification" too soon when starting to work with code I don't know well... but the more I look at it the more I find SSF code irritating Couple of years ago I was trying to understand if there is easy way to program some kind of search for smartform. Then I pretty soon decided that it's not worth the time investment and started downloading to xml for searching...
cheers
Janis
Message was edited by: Jānis B: ok, I can't change the previous post anymore
METHOD create_from_itf_text.
DATA: lo_ssf_text_module TYPE REF TO zcl_ssf_text_module .
DATA: lo_text_item TYPE REF TO cl_ssf_fb_text_item .
DATA: ls_varheader TYPE ssfvarhdr .
DATA: l_devclass TYPE devclass .
DATA: l_master_language TYPE sylangu .
DATA: l_korrnum TYPE trkorr .
DATA: l_modif_language TYPE sylangu .
CREATE OBJECT lo_ssf_text_module .
* grrr!
CREATE OBJECT lo_ssf_text_module->mo_form .
* try to lock first
lo_ssf_text_module->mo_form->enqueue(
EXPORTING suppress_corr_check = space
language_upd_exit = space
master_language = i_langu
mode = 'INSERT'
formname = i_formname
IMPORTING devclass = l_devclass
new_master_language = l_master_language
korrnum = l_korrnum
modification_language = l_modif_language
).
* init boilerplate
PERFORM create_default_text
IN PROGRAM saplstxb
CHANGING lo_ssf_text_module->mo_form.
* Take over attributes
lo_ssf_text_module->mo_form->header-formname = i_formname .
lo_ssf_text_module->mo_form->header-caption = i_caption .
lo_ssf_text_module->mo_form->header-devclass = i_devclass .
lo_ssf_text_module->mo_form->header-masterlang = l_master_language .
* get to the Text object
READ TABLE lo_ssf_text_module->mo_form->varheader
INTO ls_varheader INDEX 1 .
lo_text_item ?= ls_varheader-pagetree->obj .
* Take over text
lo_text_item->text[] = it_tsftext[] .
MODIFY lo_ssf_text_module->mo_form->varheader
FROM ls_varheader INDEX 1 .
* Return instance
ro_ssf_text_module = lo_ssf_text_module .
ENDMETHOD. "create_from_itf_text
METHOD save.
DATA: lx_ssf_fb TYPE REF TO cx_ssf_fb .
TRY .
me->mo_form->store(
EXPORTING
im_active = 'X' "Must always be active
im_formname = me->mo_form->header-formname
im_language = me->mo_form->header-masterlang
).
CATCH cx_ssf_fb INTO lx_ssf_fb .
me->unlock( ) .
RAISE EXCEPTION lx_ssf_fb .
ENDTRY .
ENDMETHOD. "save
2014 Jun 10 3:42 PM
Hello Jānis.
Thank You very much for Your input, You're great
1) I'm probably as irritated as You ware back there few years ago. It is a crap, but not OO one - if it was the real OO, then we would call maybe 2-3 methods, where first would be constructor, with passing all required details into it, then just call save. Here we have to call some external perform () and methods are very non-intuitive. It's just a pretending of OO.
2) Translation works really nice with SSFTR_SET_TEXT - it's clear and simple, thanks.
3) In general I have all I need to make my text-migration toll, but one thing is open - how to set up a transport request and package. Field KORRNUM is protected, method SET_CORRECTION_REQUEST is also protected, besides it has no input parameters, so in fact I will always get a prompt to give TR.
If it comes to package: even if I set it up manually (HEADER-DEVCLASS) it still prompts to select the package.
Both prompts are called inside of method store(). I have no time to struggle with it anymore.
I find this issue more or less solved, thanks again.