how to use the standard webdynpro component wdr_message_area in custom webdynpro component.i would like to display messages at top of custom webdynpro component using wdr_message_area.
help me....
with regard's
Ravi
how to use the standard webdynpro component wdr_message_area in custom webdynpro component.i would like to display messages at top of custom webdynpro component using wdr_message_area.
help me....
with regard's
Ravi
Easy maintenance of message texts for customer
HI All,
In my project we are maintaining message texts in custom table & global constants in class attributes.
It helps the customer to change their particular application message texts without touching the code.
And it is reusable also.
Workload CHIP (POWL Link List)
Displays categories and links to a personalized selection of worklists in a summary-like format.
Overview
With the CHIP "POWL Link List" you can embedd the navigation part of the original POWL UI into Page Builder.
Configuration
The following parameter need to be set on configuration level (not visible in personalization level):
POWL Application ID: The identifier of your POWL application. Input help available
Configuration Identification: This is the Web Dynpro configuration used by the POWL framework to determine the OBN targets for POWL applications. By default the configuration "POWL_COLLECTOR_DEFAULT_CONFIG" is used, which maps any POWL application to the OBN target "POWL.DISPLAY"
Enable Personalization: By setting this flag you allow the end user to access the personalization features for the POWL navigation area.
Multiple Applications
It is possible to show content from multiple POWL applications within the same CHIP:
Create a new application which acts as group (TA FPB_MAINTAIN_HIER)
Then assign this group application as parent of all your applications
In the configuration of the POWL Link List you select the group application as POWL Application ID.
All child applications of the group will be collected and displayed. Ordering is done automatically.
Navigation
If you only have one Workload CHIP in your role, you only need one navigation information. By default OBN target information BO System "SAP_ERP_Common", BO Name "POWL" and BO Operation "DISPLAY" is used. If you would like to use more than one Workload CHIP within your role, you have to define a component configuration for WD component POWL_COLLECTOR. You then use the configuration in the CHIP configuration identification field.
Step-by-Step
1. Add the POWL Link List CHIP to the page.
2. Configure the CHIP via "Define Link List"
3. Set the title of the CHIP (e.g. "Workload")
4. Save the Page.
Business Graphics can be easily customized at design time, but sometimes customizing parameters are not known until runtime. For example, graph title that includes selection criteria. This is where Business Graphics runtime customization come into play.
During runtime further customizing setting can be made in addition to ones made at design time. This is done using IF_WD_BUSIN_GRAPHICS_MTD_HNDL Business Graphics method handler.
I created a demo application that compares number of occupied and empty seats across airlines for selected flight date range (SAP Flight data model is used). Flight date selection is displayed in graph title
Define flight date range and click on Copy
Voilà
Below are step by step instructions of the demo application implementation:
1. Create ZCL_BUS_GR_DEMO class that implements data retrieval logic
CLASS zcl_bus_gr_rt_cust DEFINITION
PUBLIC
INHERITING FROM cl_wd_component_assistance
FINAL
CREATE PUBLIC .
*"* public components of class ZCL_BUS_GR_RT_CUST
*"* do not include other source files here!!!
PUBLIC SECTION.
TYPES:
BEGIN OF s_sflight,
carrid TYPE s_carr_id,
carrname TYPE s_carrname,
seatsmax TYPE s_seatsmax,
seatsocc TYPE s_seatsocc,
seatsocc_tooltip TYPE string,
seatsempty TYPE i,
seatsempty_tooltip TYPE string,
END OF s_sflight .
TYPES:
t_sflight TYPE STANDARD TABLE OF s_sflight WITH DEFAULT KEY .
TYPES:
t_fldate TYPE RANGE OF s_date .
TYPES:
BEGIN OF s_selection,
fldate TYPE t_fldate,
END OF s_selection .
CLASS-METHODS get_t_sflight
IMPORTING
!it_fldate TYPE t_fldate OPTIONAL
RETURNING
VALUE(rt_sflight) TYPE t_sflight .
*"* protected components of class ZCL_BUS_GR_DEMO
*"* do not include other source files here!!!
PROTECTED SECTION.
*"* private components of class ZCL_BUS_GR_DEMO
*"* do not include other source files here!!!
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bus_gr_rt_cust IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_BUS_GR_RT_CUST=>GET_T_SFLIGHT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_FLDATE TYPE T_FLDATE(optional)
* | [<-()] RT_SFLIGHT TYPE T_SFLIGHT
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_t_sflight.
DATA: w_percent(3) TYPE p DECIMALS 1.
DATA: w_i(13) TYPE c.
DATA: wa_sflight TYPE s_sflight.
SELECT carrid SUM( seatsmax ) AS seatsmax SUM( seatsocc ) AS seatsocc
INTO CORRESPONDING FIELDS OF TABLE rt_sflight
FROM sflight
WHERE fldate IN it_fldate
GROUP BY carrid.
LOOP AT rt_sflight INTO wa_sflight.
wa_sflight-seatsempty = wa_sflight-seatsmax - wa_sflight-seatsocc.
*
SELECT SINGLE carrname
INTO wa_sflight-carrname
FROM scarr
WHERE carrid = wa_sflight-carrid.
IF sy-subrc <> 0.
CLEAR: wa_sflight-carrname.
ENDIF.
*
wa_sflight-seatsocc_tooltip = w_percent = wa_sflight-seatsocc * 100 / wa_sflight-seatsmax.
WRITE: wa_sflight-seatsocc TO w_i.
SHIFT w_i LEFT DELETING LEADING SPACE.
CONCATENATE wa_sflight-carrname cl_abap_char_utilities=>cr_lf 'Occupied' w_i ' (' wa_sflight-seatsocc_tooltip '%)' INTO wa_sflight-seatsocc_tooltip.
REPLACE: 'Occupied' WITH 'Occupied ' INTO wa_sflight-seatsocc_tooltip,
'( ' WITH '(' INTO wa_sflight-seatsocc_tooltip,
' %)' WITH '%)' INTO wa_sflight-seatsocc_tooltip.
*
wa_sflight-seatsempty_tooltip = w_percent = wa_sflight-seatsempty * 100 / wa_sflight-seatsmax.
WRITE: wa_sflight-seatsempty TO w_i.
SHIFT w_i LEFT DELETING LEADING SPACE.
CONCATENATE wa_sflight-carrname cl_abap_char_utilities=>cr_lf 'Empty' w_i ' (' wa_sflight-seatsempty_tooltip '%)' INTO wa_sflight-seatsempty_tooltip.
REPLACE: 'Empty' WITH 'Empty ' INTO wa_sflight-seatsempty_tooltip,
'( ' WITH '(' INTO wa_sflight-seatsempty_tooltip,
' %)' WITH '%)' INTO wa_sflight-seatsempty_tooltip.
*
MODIFY rt_sflight FROM wa_sflight TRANSPORTING seatsocc_tooltip carrname seatsempty seatsempty_tooltip.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
2.1. Create ZBUS_GR_RT_CUST component
2.2. Add ZCL_BUS_GR_RT_CUST assistance class and SELECT_OPTIONS usage of WDR_SELECT_OPTIONS component
3.1. Add SFLIGHT context node to MAIN view with cardinatlity 0..n
3.2. Add CARRID, CARRNAME, SEATSMAX, SEATSOCC, SEATSOCC_TOOLTIP, SEATSEMPTY and SEATSEMPTY_TOOLTIP attributes to SFLIGHT node of types S_CARR_ID, S_CARRNAME, S_SEATSMAX, S_SEATSOCC, STRING, S_SEATSFRE and STRING respectively
4.1. Add CUSTOMIZING node to MAIN view context with cardinality 1..1
4.2. Add XML attribute of type XSTRING to CUSTOMIZING node
5. Define MAIN view layout
5.1. Create 2 trays to arrange screen elements: one for flight date selection and another one for chart.
Set caption texts for the trays to Selection and Business Graphics respectively. Set layout of ROOTUIELEMENTCONTAINER to MatrixLayout. Set Layout Data for both trays to MatrixLayout
5.2. Add VIEWCONTAINER ViewContainerUIElement under TRAY_SELECT_OPTIONS tray
5.3. Add BusinessGraphics element under Business Graphics tray. Map SeriesSource property, set height and width
5.3.1. Add Category element under BusinessGraphics element. Map Description and Tooltip properties of category element.
5.3.2 Add Series element under BusinessGraphics element. Set Label and map pointSource
5.3.3 Update Occupied Point element mapping Label, Tooltip, ValueSource properties
5.3.4. Add Occupied NumericValue element and map its Value property
5.3.5. Add Series element under BusinessGraphics element. Set Label and map pointSource
5.3.6. Update Empty Point element mapping Label, Tooltip, ValueSource properties
5.3.7. Add Empty NumericValue element and map its Value property
5.4. Customize BusinessGraphics element to set chart type to Stacked_Column and show series labels
6. Add SELECT_OPTIONS Componet Use to MAIN view
7. Add SHOW_SELECTION attribute of type STRING to MAIN view
8. Define MAIN view methods
8.1. Define SET_SELECTION method that set default flight date selection
METHOD set_selection.
DATA: field TYPE REF TO data.
DATA: interface TYPE REF TO iwci_wdr_select_options.
DATA select_optionsTYPE ref to if_wd_select_options.
FIELD-SYMBOLS: <field> TYPE ANY.
interface = wd_this->wd_cpifc_select_options( ).
select_options= interface->init_selection_screen( ).
select_options->set_global_options( i_display_btn_cancel = abap_false ).
* Delete Fields
select_options->remove_selection_screen_item( 'FLDATE' ).
* Create Fields
field = select_options->create_range_table( 'S_DATE' ).
ASSIGN field->* TO <field>.
<field> = is_selection-fldate.
select_options->add_selection_field( i_id = 'FLDATE' it_result = field ).
ENDMETHOD.
8.2. Define GET_SELECTION method that reads flight date selection
METHOD get_selection.
DATA: w_fieldnameTYPE fieldname.
DATA: wa_selection_screen_item TYPE if_wd_select_options=>t_selection_screen_item,
wt_selection_screen_item TYPE if_wd_select_options=>tt_selection_screen_item.
DATA: interface_select_options TYPE REF TO iwci_wdr_select_options.
DATA: select_optionsTYPE ref to if_wd_select_options.
DATA: node TYPE REF TO if_wd_context_node.
DATA: component TYPE REF TO if_wd_component_usage.
DATA: interface_alvTYPE REF TO iwci_salv_wd_table.
FIELD-SYMBOLS: <f1> TYPE ANY,
<f2> TYPE ANY.
interface_select_options ?= wd_this->wd_cpifc_select_options( ).
select_options = interface_select_options->init_selection_screen( ).
select_options->get_selection_screen_items(
IMPORTING et_selection_screen_items = wt_selection_screen_item ).
LOOP AT wt_selection_screen_item INTO wa_selection_screen_item.
CONCATENATE 'RS_SELECTION-' wa_selection_screen_item-m_id INTO w_fieldname.
ASSIGN (w_fieldname) TO <f1>.
ASSIGN wa_selection_screen_item-mt_range_table->* TO <f2>.
<f1> = <f2>.
ENDLOOP.
ENDMETHOD.
8.3. Define INITIALIZE_SELECT_OPTIONS method that creates SELECT_OPTIONS component use and set default flight date selection
METHOD initialize_select_options.
DATA: ws_fldate TYPE LINE OF wd_assist->t_fldate.
DATA: ws_selection TYPE wd_assist->s_selection.
DATA: component_usage TYPE REF TO if_wd_component_usage,
interface TYPE REF TO iwci_wdr_select_options.
component_usage = wd_this->wd_cpuse_select_options( ).
IF component_usage->has_active_component( ) IS INITIAL.
component_usage->create_component( ).
ENDIF.
*
interface = wd_this->wd_cpifc_select_options( ).
*
ws_fldate-sign = 'I'.
ws_fldate-option = 'EQ'.
ws_fldate-high = sy-datum.
ws_fldate-low = ws_fldate-high - 365.
APPEND ws_fldate TO ws_selection-fldate.
set_selection( ws_selection ).
ENDMETHOD.
8.4. Define EXECUTE event handler method for ON_EXECUTE event of SELECT_OPTIONS component use. Purpose of this method to get data when user execute the program for specified flight date selection
METHOD execute.
DATA: ws_selection TYPE wd_assist->s_selection.
DATA: wt_sflight TYPE wd_this->elements_sflight.
DATA: node_sflight TYPE REF TO if_wd_context_node.
wd_this->show_selection = abap_true.
ws_selection = get_selection( ).
*
node_sflight = wd_context->get_child_node( wd_this->wdctx_sflight ).
wt_sflight = wd_assist->get_t_sflight( ws_selection-fldate ).
node_sflight->bind_table( wt_sflight ).
ENDMETHOD.
8.5. Define CUSTOMIZE_BUSINESS_GRAPHICS method. What this code is doing:
METHOD customize_business_graphics.
DATA: w_selectionTYPE string.
DATA: w_fldate(10) TYPE c.
DATA: wa_fldateTYPE LINE OF wd_assist->t_fldate.
DATA: ws_selectionTYPE wd_assist->s_selection.
DATA: w_titleTYPE string.
DATA: business_graphicsTYPE REF TO cl_wd_business_graphics.
DATA: busin_graphics_mtd_hndl TYPE REF TO if_wd_busin_graphics_mtd_hndl.
DATA: w_customizing TYPE string VALUE
'<?xml version="1.0" encoding="utf-8" ?>' &
'<SAPChartCustomizing version="2.0">' &
'<Elements>' &
'<ChartElements>' &
'<Title>' &
'<Caption></Caption>' &
'</Title>' &
'</ChartElements>' &
'</Elements>' &
'</SAPChartCustomizing>',
w_customizing_x TYPE xstring.
DATA: out_convTYPE REF TO cl_abap_conv_out_ce.
DATA: node_customizingTYPE REF TO if_wd_context_node.
* Get Selecton
node_customizing = wd_context->get_child_node( wd_this->wdctx_customizing ).
ws_selection = get_selection( ).
IF wd_this->show_selection= abap_true.
IF NOT ws_selection-fldate[] IS INITIAL.
READ TABLE ws_selection-fldateINTO wa_fldateINDEX 1.
WRITE: wa_fldate-low TO w_fldate.
CONCATENATE 'from' w_fldate INTO w_selection SEPARATED BY SPACE.
WRITE: wa_fldate-high TO w_fldate.
CONCATENATE w_selection 'to' w_fldate INTO w_selection SEPARATED BY SPACE.
ENDIF.
wd_this->show_selection= abap_false.
ENDIF.
* Customize Business Graphics
business_graphics ?= ir_view->get_element( 'BUSINESSGRAPHICS' ).
busin_graphics_mtd_hndl ?= business_graphics->_method_handler.
w_title = 'Occupied vs Empty Seats by Airline'.
CONCATENATE w_title cl_abap_char_utilities=>cr_lf w_selection INTO w_title.
CONCATENATE '<Caption>' w_title'</Caption>' INTO w_title.
REPLACE REGEX '<Caption><\/Caption>' IN w_customizing WITH w_title.
out_conv = cl_abap_conv_out_ce=>create( encoding = 'UTF-8' ).
out_conv->convert( exporting data = w_customizing
importing buffer = w_customizing_x).
node_customizing->set_attribute( name = 'XML'
value = w_customizing_x).
busin_graphics_mtd_hndl->clear_direct_customizing( ).
busin_graphics_mtd_hndl->add_direct_customizing(
i_customizing_ctx_path = 'CUSTOMIZING.XML'
i_customizing_ctx_type = if_wd_busin_graphics_mtd_hndl=>mc_add_cust_xml_xstring ).
ENDMETHOD.
Hint: to get customizing XML string template just customize Business Graphic element at design time and look at customizing XML for the component
8.6. Implement WDDOINIT method calling INITIALIZE_SELECT_OPTIONS method
METHOD wddoinit .
initialize_select_options( ).
ENDMETHOD.
8.7. Implement WDDOMODIFVIEW method calling CUSTOMIZE_BUSINESS_GRAPHICS method
METHOD wddomodifyview.
customize_business_graphics( view ).
ENDMETHOD.
9. Embed WND_SELECTION_SCREEN view of SELECT_OPTIONS component use into VIEWCONTAINER element of MAIN view
10. Create ZBUS_GR_RT_CUST application
Original of this article is published on my personal site at oprsteny.com
In this article I'll show you how to retrieve an Excel sheet from SAP DMS (Document management System) where it is stored as "original" in a Document container.
Let's presume that:
DATA: ls_document_data TYPE bapi_doc_draw2, ls_return TYPE bapiret2, lt_document_files TYPE TABLE OF bapi_doc_files2_keys.
FIELD-SYMBOLS:
<ls_document_file> LIKE LINE OF lt_document_files.
* Specify our document key
ls_document_data-documenttype = 'ZTP'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT' EXPORTING input = '3000000000003' IMPORTING OUTPUT = ls_document_data-documentnumber.
ls_document_data-documentversion = '00'.
ls_document_data-documentpart = '000'.
* Read document info
CALL FUNCTION 'BAPI_DOCUMENT_GETLIST2'
EXPORTING select_documentdata = ls_document_data getdocfiles = 'X' IMPORTING return = ls_return TABLES documentfiles = lt_document_files. IF ls_return-type CA 'EA' OR lines( lt_document_files ) = 0.
* RAISE EXCEPTION document_does_not_exist. ENDIF.
* To simplify our example we read just the first file from
* the document container
READ TABLE lt_document_files ASSIGNING <ls_document_file> INDEX 1.
DATA: lt_cvapi_files TYPE TABLE OF cvapi_doc_file, lt_bapi_files TYPE t_bapi_doc_files2, lt_drao TYPE dms_tbl_drao, ls_message TYPE messages, lt_orblk TYPE TABLE OF orblk, lv_excel_xstring TYPE xstring lv_data_size TYPE i.
FIELD-SYMBOLS:
TYPE drao, TYPE orblk.
* Convert BAPI file structure to CVAPI file structure
APPEND <ls_document_file> TO lt_bapi_files.
CALL FUNCTION 'MAP2I_BAPI_FILE2_TO_API_FILE' TABLES bapi_doc_file = lt_bapi_files api_doc_file = lt_cvapi_files.
* Get binary data from system
* Content provider is set to 'TBL'
* -> tabular data filled in lt_drao
CALL FUNCTION 'CVAPI_DOC_CHECKOUTVIEW' EXPORTING pf_dokar = <ls_document_file>-documenttype pf_doknr = <ls_document_file>-documentnumber pf_dokvr = <ls_document_file>-documentversion pf_doktl = <ls_document_file>-documentpart pf_content_provide = 'TBL' IMPORTING psx_message = ls_message TABLES pt_files = lt_cvapi_files ptx_content = lt_drao EXCEPTIONS error_message = 1 OTHERS = 2.
* Get the binary data and its length
LOOP AT lt_drao ASSIGNING <ls_drao>. APPEND INITIAL LINE TO lt_orblk ASSIGNING <ls_orblk>. <ls_orblk> = <ls_drao>-orblk. IF lv_data_size IS INITIAL. lv_data_size = <ls_drao>-orln. ENDIF.
ENDLOOP.
* Convert binary data from itab to xstring
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING input_length = lv_data_size IMPORTING BUFFER = lv_excel_xstring tables binary_tab = lt_orblk.
As we initially presumed - we have a WDY component with one View which contains the OfficeControlof type MS_EXCEL element in the Layout. Now we have to create a context Attribute where we will store the Excel binary data.
If you reached this point, you already know how to read the Excel data, you know how to integrate OfficeControl to the WDY view and bind it to the view's Context attribute. Now we just have to fill the Context attribute with data we've already prepared before - you can put the following piece of code e.g. in the View's WDDOMODIFYVIEW method in case you want to initialize the Excel control in the WDY right from the start
wd_context->set_attribute( EXPORTING value = lv_excel_xstring name = 'XLS_DATA'
).
Now if you try to run your WDY application in browser, you should see the Excel being displayed within the browser window and loaded with data of the XLS sheet from your DMS document.
When using Web Dynpro for ABAP, sometimes we have the need to call other functions or transactions in the SAP system landscape. In the "old days" where everything was done in ABAP and the user was calling the SAP system by using an SAP GUI - this was easy; just call the requried function and a new session was launched in the GUI.
This has changed - several technologies for user UI development are possible, This means that whe could have a switch between technologies inside a Business Process.
The good news is that the NWBC can act as a framwork for this. Using the NWBC we can have an central application we all our SAP functions are processes inside, without having a lot of browser windows popping up etc.
This example shows how to develop a simple Webdynpro application, where the user can enter a Sales Order number and from the Dynpro call transaction VA03 in SAP GUI.
SAP ERP System
Netweaver Business Client (setup and running)
Basic Web Dynpro Knowledge
The goal is reached by using Object-Based Navigation (OBN). OBN is used in Roles (PFCG) to assign an object to a function.
What basically happens is that the OBN call searches the Roles of the user calling a certain function and when found it launches the corresponding transaction (or other function). Because of that we will later se, that the OBN is very tightend to the Roles of the user (but NWBC is anyway)
First of all we create the WebdynPro application. It could be a list of Sales Orders or anything, but in this example it´s just a simple screen with an input field and a button:
This is quite basic: an input field whe the user can enter a Sales Order number and a pushbutton to excute...
The interresting part is the code of the Action of the button:
The onAction event is implemented like this:
First part is done to retrieve the value of the Sales Order from the screen. Second part is the interesting one:
By using the IF_WD_PORTAL_INTEGRATION class we can exceute the call of the Business Transaction. Note! There is no SAP Portal involved here - it works without!
Four parameters are used here:
OBJECT_TYPE: This is the type of object called
OBJECT_VALUE_NAME This is the name of the parameter passed to the call
OBJECT_VALUE This is the value passed from screen
OPERATION This is the operation to call
To fully understand the above coding i will goto the next step right now:
We will have to define a Role (or expand an existing one) in order to give the user the required functionality:
Call PFCG and create a role:
The role consist of a Root folder and a Subfolder (NWBC requires at least one lower level). First "pin" is the Web Dynpro Application created in step one - just basic call of a Web Dynpro application.
Second "pin" is the Sales Order display Transaction VA03. When you press the Other Node Details button you will notice the OBN part below
This is where we apply our OBN part. Press Insert Method button
In here we can use a BOR object as the object. We choose BUS2032 (SalesOrder) and method Display
Next screen is for entering the parameters
This is where we pass the actual value from the screen to the transaction. Parameter ID (first column) is found by entering transaction and get the Scrren field name (F1->technical).
In the second column the value is intered - by using Curly bracktes we tell the system that we vil pass a variable value.
Note: the BOR object used is only for defining the naming of the Object type etc. No BOR object logic are called at runtime! In part 2 i will show how to use a none BOR value...
Now the Role are ready to use!
Save it and assign to a user.
Start NWBC
Execute the Web Dynpro App
Enter Sales Order number and press Button
So: the VA03 are called with a regular SAP GUI interface - no HTML GUI. We have done a Switch between technologies from Web Dynpro ABAP to SAP GUI.
The system was told to call a Business Object called SalesOrder with the method Display (SalesOrder.Display). When that called was executed it searches the Roles assigned to the logged in user for an entry with the OBN assignment SalesOrder.Display.
When found in the Role, it executed the transaction assigned to that menu point and passed the value from the Screen field to the VBAL-VBELN fields in VA03.
Sometimes negotiating on a standard solution with the customer is like waving a red flag to a bull, "Consultant proposes, Customer Disposes" had become a norm in my recent endeavours. Few at times, there is good reason behind their intransigence, but more often than not it is display of effrontery to say that was is there is the best and should continue, but hidden behind the veil is the resistance towards any kind of change.
Rather than pressing your point home, it is better to give in and get things going beofore customers says my way or the highway . We advocating use of HCM processes and forms to standardize all their HR processes did not get their buying. Firstly, they wanted the look and feel exactly as it was and also the functionality, one major bone of contention was to have file upload at different sections in the form as each section will be used by different stakeholder, the standard HCM processes and form framework would not offer such an option as all the attachments are available in only one section at the top, and also then flexibility of making certain attachment available for certain groups is not an option.
In this blog I shall describe how to incorporate file uploads in different sections and load it to the content server, a prequisite being that the content server is configured by doing the basic customizing for the archivelink. if you are unware, then just take a note of the below steps.
1. Create a content repository - here you create a content repository id along with other parameters.
Enter the required details related to the content server.
2. Create a document type and use the document class as * so that you can use any document type.
3. Now link the object type, document type, and the content repository using the below customization view.
Enter the other details as required.
4. Also, ensure that during storage the document type is not copied from document class. Keep the below box unchecked in the customizing.
Once you are done with these quick settings, it is time to a develop a small WDA reusable component. This particular component shall then be placed in different sections of the main component. But before we start to develop WDA we need to small spade work of designing the table to store the required document data.
Design the table to store the following as shown below.
1. The section field is used to identify from which section the document got uploaded
2. The document ID is returned by the archive link after loading the document, it uniquely identifies a document.
3. The unique process id is used here because every form when submitted would give a unique process id, thus we can link the uploaded documents to unique form and sections in the form.
4. File type is the file extension, it needs to be capture as this wll be used while trying to open the document from WDA.
5. Store the file name also
6. Now create a web dynpro component with a very simple view consisting of a upload UI and table UI to display uploaded document details and also delete if not required.
On the load action of the file use the CALL FUNCTION 'CH_SPLIT_FILENAME' to split file name and mimetype so that it can be captured in the z-table.
Then store the read content into the content server by calling ARCHIV_CREATE_TABLE
Store the ls_output-arc_doc_id in the ztable, this is an unique reference to the document store in the content server, this id will help us to retrieve the document back.
Now, on the other hand to open the uploaded file, you can create a handler action to fetch the file and open as a response. Use the FM CALL FUNCTION 'ARCHIVOBJECT_GET_TABLE' as shown below passing the unique document reference number that was generated and stored in the previous step.
You might need to get the correct mime type to be passed to the browser using the below FM and a little bit tweaking using a conversion class to correct the binary information. If you don't use the conversion class you might not be supporting xlsx type files and end up getting error while opening the file, though the file ultimately opens.
then a bit of coding to attach to response and the file shows up on the browser.
Apart from these, you might need to have some interface methods in the component controller to communicate with the parent component, the one of particular importance is the set data method(see below screen shot). This method gets information from the parent component, which helps it to uniquely identify the files that belongs to the process, the section and also store information of the files in the z-table. You can have other interface methods if you need further manipulation of the child component.
Below image you can see how the upload component in used in different sections of the same form.
This is a normal scenario you would come across and I hope this blog will be quite useful at that time .
Thanks for reading and your comments are welcome.
Raghav.
Follow the below step to create an simple WebDynpro Application using Contextual Panel UI
Step 1: Goto T-code : SE80
Step 2: Create New WebDynpro Component "ZCONTEXT_PANEL"
Step 3: After creating component activate the entire Component and controllers. In view, insert Contextual panel UI element
Step 4: Insert view switch element inside contextual panel element
Step 5: Insert free contextual panel to insert other UI element
Step 6: Insert text view in free contextual area
Step 7: Create another contextual panel
Step 8: Insert free contextual area in second contextual panel
Step 9: Insert transparent container inside free contextual area
Step 10: Insert two transparent containers inside main transparent container
Step 11: Insert text view in both transparent containers
Step 12: Create Two Nodes as below
Node1 ‘REP’
Attribute ‘REP’ type String
Node2 ‘VISIBILITY’
Attribute ‘FIRST’ type Boolean
Attribute ‘SECOND’ type Boolean
Step 13: Bind REP node in Item source properties of view switch element and Bind REP attribute in item text properties of view switch element
Step 14: Create method ‘SHOW’for view switch element
Step 15: Bind the attribute first from visibility node to the visibile properties of tc_first element and Bind the attribute Second from visibility node to the visibile properties of tc_second element
Step 16: Use below Code in WDDOINIT
METHOD wddoinit .
DATA : lo_nd_reports TYPE REF TO if_wd_context_node.
DATA : lo_nd_visibility TYPE REF TO if_wd_context_node.
DATA : ls_reports TYPE wd_this->element_rep.
DATA : lt_reports TYPE wd_this->elements_rep.
* Default Graph Show
lo_nd_visibility = wd_context->get_child_node( name = wd_this->wdctx_visibility ).
lo_nd_visibility->set_attribute( name = 'FIRST' value = abap_true ).
lo_nd_visibility->set_attribute( name = 'SECOND' value = abap_false ).
lo_nd_reports = wd_context->get_child_node( name = wd_this->wdctx_rep ).
* Setting the Drop Down & Other Values
ls_reports-rep = 'FIRST'.
APPEND ls_reports TO lt_reports.
ls_reports-rep = 'SECOND'.
APPEND ls_reports TO lt_reports.
lo_nd_reports->bind_table( lt_reports ).
ENDMETHOD.
Step 17: Use below code in Method SHOW
METHOD onactionshow .
DATA lo_nd_reports TYPE REF TO if_wd_context_node.
DATA lo_nd_visibility TYPE REF TO if_wd_context_node.
DATA ls_visibility TYPE wd_this->element_visibility.
lo_nd_reports = wd_context->get_child_node( name = wd_this->wdctx_rep ).
lo_nd_reports->set_lead_selection_index( index = index ).
lo_nd_visibility = wd_context->get_child_node( name = 'VISIBILITY' ).
IF index = 1.
ls_visibility-first = abap_true.
ls_visibility-second = abap_false.
ELSEIF index = 2.
ls_visibility-first = abap_false.
ls_visibility-second = abap_true.
ENDIF.
lo_nd_visibility->set_static_attributes( EXPORTING static_attributes = ls_visibility ).
ENDMETHOD.
Output
Second panel result will be display based on action taken in first contextual panel
Below Steps will help to get the selected record from Business Graph
1. Create an WebDynpro Component, View, Window and application
2. Create context node and attribute as below in View. String type for all the attribute
3. Create Business graph, bind the series and create on Action as below
4. Create Category and bind the property as below
5. Create Series and bind property as below
6. Create Text view to display selected Employee Number
7. Populate the code as below in WDDOINIT
8. Create EVENT_ID parameter in EMP Event handler
9. Populate the below code in EMP Event handler
Output
Before selecting on Chart
After Selecting on Chart, selected part will be marked and the employee number will display below
Regards,
Manikandan S
Hi welcome !!!
I would like to share the code/logic of method GET_TABLE_DATA of interface IF_WD_TABLE_METHOD_HNDL which helps to read the data from a filtered Table in Web Dynpro ABAP.
I have come across few SCN threads where in the requirement for reading filtered table data is left unanswered, as the method GET_TABLE_DATA( ) is not available in interface IF_WD_TABLE_METHOD_HNDL in their systems. I think the method GET_TABLE_DATA is available from SAP_ABA 731.
So, it might be useful if the logic to read the data from a filtered table is available for all.
Basic knowledge of Webdynpro ABAP,& OO ABAP
Create below method.
GET_TABLE_DATA( ) |
---|
Parameters: IO_TBL Importing type ref to CL_WD_TABLE METHOD get_table_data.
DATA elements TYPE wdr_context_element_set. DATA element TYPE REF TO if_wd_context_element. DATA row_data TYPE wdr_table_row_data. DATA last_row_index TYPE i. DATA first_row_index TYPE i. DATA wd_row_arrangement_type_id TYPE guid. DATA wd_row_arrangement TYPE REF TO cl_wd_view_element. DATA first_actual_row TYPE i. DATA fixed_row_count TYPE i. DATA data_source TYPE REF TO if_wd_context_node. DATA row_count TYPE i. DATA selected_elements TYPE wdr_context_element_set. DATA first_row TYPE i. DATA last_row TYPE i value -1. CONSTANTS c_none TYPE guid VALUE ''. CLEAR rt_data. CLEAR selected_elements. row_count = 0. IF data_source IS NOT BOUND. data_source = io_tbl->get_data_source( ). ENDIF. wd_row_arrangement ?= io_tbl->get_row_arrangement( ). IF wd_row_arrangement IS NOT BOUND. wd_row_arrangement = io_tbl->get_master_column( ). ENDIF. IF wd_row_arrangement IS BOUND. wd_row_arrangement_type_id = wd_row_arrangement->_cid. ENDIF. fixed_row_count = io_tbl->get_row_count( ). first_actual_row = io_tbl->get_first_actual_row( ). CASE wd_row_arrangement_type_id. WHEN c_none. selected_elements = data_source->get_selected_elements( ). IF fixed_row_count = -1. row_count = data_source->get_element_count( ) + first_actual_row. ELSE. row_count = fixed_row_count. ENDIF. first_row_index = first_row - first_actual_row. IF last_row = -1 OR last_row > row_count. last_row_index = row_count - first_actual_row. ELSE. last_row_index = last_row - first_actual_row. ENDIF. IF last_row_index >= first_row_index. elements = data_source->get_elements( from = first_row_index to = last_row_index ). ENDIF. LOOP AT elements INTO element. row_data-context_element = element. row_data-level = 0. INSERT row_data INTO TABLE rt_data. ENDLOOP. ENDCASE. ENDMETHOD. |
Let us say, we have created the above method GET_TABLE_DATA in component controller of WD component.
Please refer to the below steps to read data from a filtered table
METHOD wddomodifyview . IF first_time = abap_true. "Note: my_table is the ui name of table in view layout wd_this->go_tbl = view->get_element( 'MY_TABLE' ) ENDIF. ENDMETHOD.
data lt_data type WDR_TABLE_ROW_DATA_TAB. wd_comp_controller->get_table_data( exporting io_tbl = wd_this->go_tbl receiving rt_data = lt_data ).
Thank you for your time and hope content of this blog was helpful.
Your comments / Feedback / suggestions are highly appreciable & always welcome
This document will help you to understand the concept of Dynamic Progress Bar in Web Dynpro ABAP.
Create Web Dynpro Component and create a node with the cardinality of 1.1 and add an attribute with the type of ‘I’
In the View Create two UI elements Timed trigger and Progress indicator and create an action for timed trigger and set the delay how much ever you want here I am setting as 1 and bind the same attribute(here BAR) in progress bar's Display and percent Value.
The event that we are declaring here will get called once the delay time is reached.
Code in the trigger event:
METHOD onactiontrigger .
DATA lo_nd_progress TYPE REF TO if_wd_context_node.
DATA lo_el_progress TYPE REF TO if_wd_context_element.
DATA ls_progress TYPE wd_this->element_progress.
DATA lv_timer TYPE wd_this->element_progress-bar.
lo_nd_progress = wd_context->get_child_node( name = wd_this->wdctx_progress ).
lo_el_progress = lo_nd_progress->get_element( ).
lo_el_progress->get_attribute(
EXPORTING
name = `BAR`
IMPORTING
value = lv_timer ).
lv_timer = lv_timer + 3. "Incrementing the value after each delay set as 1.
lo_nd_progress = wd_context->get_child_node( name = wd_this->wdctx_progress ).
lo_el_progress = lo_nd_progress->get_element( ).
lo_el_progress->set_attribute(
name = `BAR`
value = lv_timer ).
IF lv_timer = 100.
wd_this->fire_to_next_plg( ).
ENDIF.
ENDMETHOD.
Create an application and activate the whole component.
- Gowtham
Hi
I would like to overview about configurations required for 'Employee short profile ' in MSS. Employee short profile is basically used to display employee profile on one click with a separate window when manager wanted to see the employee profile .
1 . Each short profile is associated with one category .category can be created in below view .
Create category - view - V_T77TMCDRCAT
2. For each category map the required fields on short profile . use below view .
Create fields for category - V_T77TMCDRFLDS -
Ex: if short profile must have Employee Group , Employee Status , Hire Date , Org Unit , Personnel Area , Personnel Subarea , Home Phone , Position.
All these must be assigned with category in the view . V_T77TMCDRFLDS
3. Create configuration ID - View : HRTMC_VC_CONF_GRP
Create configuration ID using the view and Create fields to be associated .
Most WebDynpro ALV tutorials show you step by step how to import and setup an ALV component into your project. Add the ALV component to the list of used component in the COMPONENTCONTROLLER properties and add this usage to the display View.
Embed the TABLE View from the ALV component usage into your display View.
And then setup the data to be used by binding a node from the component context to the DATA node in the ALV component INTERFACECONTROLLER.
Admittedly, this is probably the simplest, most direct way of introducing this process; statically defining the binding of the data node. And, not having conducted a poll myself, I would venture to say that for most implementations this is sufficient.
But there is always that one time, that one time where you need to be able to assign and/or reassign that binding at run time. That one time when it is not known at design time which node will be displayed. It may be dependent on user input or data selection or whatever. The point is that you need to dynamically bind a data node to the ALV.
Well, fear not, here’s how it’s done.
In a recent project I needed to display the same set of data at different granularity based on the user’s selection. There are two buttons for the user to choose: one displaying the data as a summary and the other combining it with more detailed line item type data for a more denormalized view. In any case, here’s how I approached it.
First, skip the last step above where the binding is done.
In the VIEW where the ALV is displayed I created a method called SET_DATA_MAPPING. This method takes in a parameter of type IF_WD_ACTION and gets called from the WDDOBEFOREACTION hook method which supplies the value for the ACTION that was triggered thru a reference to the view controller.
Based on the value of the action, I get the child node from the context that represents the data to be displayed. Then, get a reference to the ALV INTERFACECONTROLLER and using its SET_DATA method pass the value of the context node and the binding is done.
This should be enough to now go ahead and setup the properties and display your ALV. There are also methods that handle refreshing the view after, for example, adding or removing records, but we'll tackle does in a different post.
Good luck!
Hello colleagues!
Recently I've got an issue to provide users with ability to select several lines in web dynpro table without pressing Shift or Ctrl buttons.
Standard WD table doesn't provide this. So I had to do some additional customization and development.
At first I've set selection attributes of the table as follows:
Then I've created an action for event onSelect:
METHOD onactionselect.
CHECK new_lead_selection IS BOUND.
new_lead_selection->get_node( )->set_lead_selection_index( 0 ).
new_lead_selection->set_selected( boolc( new_lead_selection->is_selected( ) IS INITIAL ) ).
ENDMETHOD.
In the second line I set the lead selection off, otherwise I've got a permanent selected row in the table.
In the third line i check if the row is already selected. If yes - I deselect it, otherwise I set on the row selection.
The solution is quite simple but I hope It will be useful.
Thanks for the attention!
Raindrops keep falling on my head, a beautiful song and a good metaphor to a programmers life. But if we have a sheer determination and an indomitable spirit to do something we make sure we find the wherewithal to achieve the formidable task.
Sitting on the edge of my seat at my workstation I managed to take a peek outside through the window, It was a wonderful view of the corniche and the vast blue expanse of the Arabian Gulf, the sun shining brightly in the clear sky striking its rays on the placid waters giving it a beautiful glitter, the ships making delible marks on the shimmering blue canvas, while I was in a reverie I was jolted by a bolt from the blue, frankly never witnessed thundering clouds here anytime . I heard some voices saying the users were not happy and comfortable with the NWBC HTML landing page screen on the kiosk, they wanted an ESS on Kiosk which looked like any other kiosk application and easy to navigate. I had concluded it to be a close and shut case and believed it would not raise its ugly head again, but the ball was back in my court. As always, they laid down the rules, they did not want to catch whatever we threw at them. The following were the expectations,
I had to go back to the drawing boards and develop a simple and new application. The intention of the blog is to elaborate only on the last two points, but let me brief on the former three also. To paint a good login screen you just need to copy the class CL_ICF_NW07_LOGIN and manipulate the HTML and CSS code inside those methods and assign this class to your web dynpro ICF node. For the second point, you need to use the new theme designer /UI5/THEME_DESIGNER and copy the standard corbu, make alterations to the theme with an aesthetic touch, this can be bit tricky as you would not know SAP naming conventions, I basically tweaked around the colors and the button sizes. For the third point the only way I found to enlarge the buttons beyond a point is to embed images into the buttons, so I got a good graphic designer to design a few gif buttons representing each application and embedded those gifs.
To achieve the final two points I started off with an approach which had its loop holes, the basic idea was to put a triggered timer on each view of application screen where the various applications are itself either embedded as an iFrame or as an reusable component in the current application. I set the initial value of the logout time by reading the logout time set at the ICF node level, for every event in any of the application screens we reset the logout time to the initial time, and this time is set to the timed trigger, the timed trigger will check after the preset time if the time of last activity and the current time-10 seconds exceeds is the logout time limits, if yes, then it will trigger an exit plug to logoff the application and using the logoff server side java script we clear any SSO cookie.
But here I had hit the wall, it had a fundamental problem. Firstly, I thought, it is not a good idea to use round trips to reset time limits, but the major problem was when user started filling up the reason for leave application leisurely taking longer time than usual, and before he could submit the auto logoff triggered as it had exceeded the inactivity time when fundamentally he was not inactive but keying in the reason. I had to digest the fact that Web Dynpro ABAP will not detect any mouse clicks(other than on certain fields) and also does not detect typing, and this of course was not acceptable and entire approach collapsed like a pack of cards after days of effort.
It is fact that an open source developer and ABAPer cannot see eye to eye and I couldn't concur with him either, they have all the freedom to do what they want but we don't, but he did set me off thinking with his statement "Why are you using server round trips for resetting time, why don't you use java script instead?, you can detect any kind of event using that", we abapers are averse to learning any new language we are comfortable in our coccons but javascript is a must learn as UI5 is based on it, so I decided to give this a shot like a blind shooter.
My initial stumbling block was to make js code to talk to web dynpro even if I managed to write some lines. Some amount of research and I felt I was hitting the right track, sometime back I had come across embedding HTML containers in WDA, and this was the beacon when treading in unknown territory. If we explore Html containers in WDA we find that there is a simple solution to this problem.
So this what I did, firstly create a new view in the application and create an HTML island as an element under the root container, add an HTML event and HTML script as sub elements as shown below.
Figure 1.
The reset_time action method basically creates a count down timer of 10 seconds for user confirmation to logoff or to keep the session.
Figure 2.
In the Logoff view we raise an event which will be listened by any of the current views at that point of time, so basically you will implement handler in all the views for the controller event, one of them shown below.
Figure 3.
The trig_logoff method just calls the exit plug of the current view to get out of the application if user confirms to logout or does not confirm anything within 10 seconds it will log him off.
Coming back to the HTML island, you would have noticed a sub-element HTML script with source parameter zkiosk.js, this is the javascript file which detects all user events be it typing or mouse moving or clicking anywhere in the application. The script file can be loaded to application as a mime object.
if you notice in below table the script basically sets a timer and has a function addCallback which basically registers the events of a document to a timer function, the timer function calls a logout function when time limit expires, the Event is another name for the HTML event RESET_TIME. One more point to note is that you need to create an instance of HTML island and register the script call as shown in figure 5.
Header 3 | ||
---|---|---|
|
Figure 4.
Figure 5.
We are done with the most part of it, now we need to just embed this view in every application embedding view or else this will not function in every screen and can create issues. And a point to note, don't hide the view, if you hide the view the functionality stops working, so the only alternate way is put this view into a tray and collapse the tray and make it un-expandable, see figure 6.
Now as a final piece of the puzzle we need an Java Script at the server side on the ICF node which kicks you out the Logon page again and clear all logon cookies again, this ensure that you enter userid and password again, see Figure 7.
Figure 7.
Application in action.
Logon screen.
landing screen.
Logout prompt after inactivity. Sorry for the typo in message
I hope this blog helps those who encounter a similar requirement, and as a last piece of information this whole thing works only in IE 10 and above, chrome also has some issues.
regards,
Raghavendra Prabhu
Anybody who has developed applications using SAP WD ALV component SALV_WD_TABLE, know’s how many lines of code is required to configure ALV to specific requirements. There’s getting instance of ALV model and then calling all sort of API methods to fine tune standard ALV like- sequence the columns, hide, rename the column header, set lead selection behaviors, set column width, editable ALV or not, set cell editors and many more. For complex scenarios - set cell variant, map column properties with other field value(from context).
Now think of a solution which provides an ALV configurator which can be used to do all the above configurations so that developer doesn’t have to write that boilerplate code. The whole functionality is delegated to an external application. Your ALV instance automatically adjusts itself to the values set in the configurator.
Let’s say during UAT phase of your project - user wants to re-sequence the columns and also update column headings - you just have to make changes in the configurator. This can be done by functional consultant on the project - no developer involved - no source code change.
The architecture of this solution supports abstracting the common ALV functions like - showing record count, custom excel export, etc so that they can be easily provisioned.
Here’s the overview diagram of the solution.
With all said - the implementation is of proto-type (beta) quality and not any where near to production quality. I am making this open source on GITHUB so as to involve WD ABAP community to contribute, provide feedback/suggestions and use freely.
Please raise github issues on the repository for better tracking.
You can find more details in the github repository.
Hi, folks!
Does anybody remember this great blog post Kiss of Death for Web Dynpro Java The Follow-Up Questions? After going through the release notes of S/4 HANA 1511 I can' t help myself but thinking "History repeats itself".
It always starts with ESS/MSS as a playground for new UI technologies - and the beginning of the end for old ones. If the new technology doesn' t prove to be a complete failure, the old frontend passes away in a concerted action of SAP marketing, community evangelists, product management and development.
UI roadmaps are being updated, the community sphere is flooded with happiness and excitement about the new possibilities, new products are released only in the successor technology, old products are rewritten, UI roadmaps are updated again - and suddenly the grumpy old UI is extended maintenance mode.
So - of course no one at SAP will officially admit and there will be (not so?) violent opposition, but let' s face it: as this is exactly what happened many times before and now happens again, it' s time to say goodbye to the old days when everybody could get along with ABAP only and simply paint some web frontend in the Workbench.
Say hello to the new era - we' re all going to be web developers in 5 years from now.
Regards,
Thomas
Scripting in SAP Screen Personas for Web Dynpro ABAP is offered to allow primarily automation of re-occurring or complex steps. With the current release the basic functions are available to automate the current application.
To work with the scripting features inside Web Dynpro ABAP based applications you need to have at least SAP Screen Personas 3.0 SP01 and SAP_UI 750 SP01 installed on your system – otherwise the SAP Screen Personas functions are not enabled for Web Dynpro ABAP based applications. See note 2181980 for more details on the system requirements.
As example we use the product maintenance application from the Enterprise Procurement Model, which is part of each SAP NetWeaver installation. We enhance the application with a new button that will provide a dialog to ask the user for the new product name and will change this accordingly in the application.
The original application (S_EPM_FPM_PD) looks like the following:
After the adjustment the screen should look like the following:
I know there could be more improvements made with the layout capabilities of the Floorplanmanager as well as the SAP Screen Personas functions – but as the focus is on scripting let’s keep it as it is.
Each script is associated with a flavor – thus before we can create a script we need to create a flavor. After the flavor is created we leave the edit mode and switch to scripting mode. There the first action is to create a new script. The scripting engine is based on JavaScript, means nearly all JavaScript syntax can be used – however the access to some global objects may be limited.
The internal structure of the HTML page is controlled by the Web Dynpro ABAP and the Unified Rendering frameworks and by this the structure might change overtime to adopt changed browser behavior. To access the UI elements as seen from the framework a dedicated access is provided inside the scripting engine – do not use the standard objects inside the browser, e.g.
window
or
document
.
Using the global object
session
you have access to a bunch of functions built in to access the screen elements, access helping functions or use the logging. We’ll have all of them in use in the full example later on.
To access now a single element, e.g. the edit button you should start the inspector – this is an interactive tool which allows you to select any screen element that provides some interaction capabilities. While you hover over the element some basic information is displayed in the lower right section of the screen. Once you select the element via click the full available information for the element is shown.
The inspector view shows you all available attributes and methods for the object. Attributes have an indication whether they can be changed or they’re read only. Methods are like functions and can be invoked. As we like to invoke the press function on the button we click on the icon in front of the press entry. This produces a single line of code in which the element is accessed and the method is invoked.
session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_FPM_EDIT_1").Press();
This line re-presents the pattern of using scripting quite well. Access the object with the
session.findById
function (the Id’s are stable) and then access either an attribute or invoke a method.
If you execute this script now, then the application changes into edit mode. However, if you execute the script for a second time you will see no visible change – except an error message on the Logging tab of the scripting area – this is due to the fact that the edit button is on the page but it’s inactive and as a result the press method cannot be called.
Equipped with the knowledge on how to invoke actions on the UI we can complete our script to have the functionality working. The code would look like this:
session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_FPM_EDIT_1").Press(); var sName = session.findById("EPM_PD_OVP_HEADER_FORM_CFG.00.V_FORM.FGRP_8").value; sName = session.utils.prompt("Enter new Product Name", sName ); session.findById("EPM_PD_OVP_HEADER_FORM_CFG.00.V_FORM.FGRP_8").value = sName; session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_SAVE").Press();
The field with the ID
"EPM_PD_OVP_HEADER_FORM_CFG.00.V_FORM.FGRP_8"
is the input field for the product name – in the script we read the current value and exchange it with the input from the user – via the
session.prompt
method. This special method provides an input dialog for simple string values. For more complex inputs please use dedicated new screen elements which can be inserted via the editor.
Now we need to add this script to a new button on the screen to allow users to work with it. For this we quit the scripting mode and switch to edit mode. In there we add a new scripting button, place it in on the screen and assign our newly created script to it.
This covers the first part of using the scripting inside SAP Screen Personas for Web Dynpro ABAP. For using such scripts in a productive environment it’s highly recommended to use logging functions and secure the script with additional checks. Please see the follow up blog for this.
Scripting in SAP Screen Personas for Web Dynpro ABAP is offered to allow primarily automation of re-occurring or complex steps. With the current release the basic functions are available to automate the current application.
To work with the scripting features inside Web Dynpro ABAP based applications you need to have at least SAP Screen Personas 3.0 SP01 and SAP_UI 750 SP01 installed on your system – otherwise the SAP Screen Personas functions are not enabled for Web Dynpro ABAP based applications. See note 2181980 for more details on the system requirements.
In the first part of the blog the initial script was created. This script is working as long as everything runs fine – if there is some obstacle the script may fail at any point, e.g. the user has no edit rights. This should be prevented to not impact the user experience in a bad way.
There are two parts which should be added:
The first part will ensure your script can handle unforeseen situations and the second part will make the support later on easier as meaningful information is either being put into the logging section of the scripting view or into the browser console.
Validation can be added using the attributes of the UI elements, e.g. the enabled attribute or other states which are available. All of these Boolean attributes work as true Boolean values in the scripting – means they can directly be consumed in if clauses. Additionally, the session object has a method idExists– which works much like the findById but instead of giving back the UI element it returns a true/ false whether an element with the given id is currently available.
Logging can be added using the session.utils.log method. This method expects a string message and a severity.
Applying validation and logging to our script it will look probably like this:
// UpdateProductName script // log some information about the environment var sEnvironmentInfo = "User: " + session.info.user + " started UpdateProductName script on server: " + session.info.applicationServer + ", client: " + session.info.client + " in application: " + session.info.applicationConfigId; session.utils.log( sEnvironmentInfo, session.utils.LogLevel.INFO); // check for all needed elements if (!session.idExists("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_FPM_EDIT_1") || !session.idExists("EPM_PD_OVP_HEADER_FORM_CFG.00.V_FORM.FGRP_8") || !session.idExists("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_CANCEL") || !session.idExists("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_SAVE")) { session.utils.log("Not all needed UI elements are on the page - exit processing"); return; } // buffer elements for later usage var oEditButton = session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_FPM_EDIT_1"); var oInputField = session.findById("EPM_PD_OVP_HEADER_FORM_CFG.00.V_FORM.FGRP_8"); var oCancelButton = session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_CANCEL"); var oSaveButton = session.findById("S_EPM_UX_PD_OVP.00.PAGE_HEADER.FPM_CA_TOOLBAR_SAVE"); // try to switch to edit mode if (!oEditButton.enabled) { session.utils.log("Edit button not enabled"); return; } oEditButton.Press(); if (oEditButton.enabled) { session.utils.log("Switch to edit mode failed"); return; } // check if input field is available if (!oInputField.enabled || oInputField.readOnly) { session.utils.log("Input field for product name not open for changes"); return; } var sOldName = oInputField.value; session.utils.log("Old Poduct Name: " + sOldName, session.utils.LogLevel.INFO); var sNewName = session.utils.prompt("Enter a new product name", sOldName); // check for user cancel action or not changed values if (sNewName === null || sNewName === "" || sNewName === sOldName) { session.utils.log("Input canceled by user or name not changed", session.utils.LogLevel.INFO); if (oCancelButton.enabled) { oCancelButton.Press(); } else { session.utils.log("Cancel button not enabled") } return; } // update product name session.utils.log("New Product Name: " + sNewName, session.utils.LogLevel.INFO); oInputField.value = sNewName; if (oSaveButton.enabled) { oSaveButton.Press(); } else { session.utils.log("Save button not enabled"); return; } // after save validation if (!oSaveButton.enabled) { session.utils.log("Data saved", session.utils.LogLevel.INFO); } else { session.utils.log("Changed data could not be saved"); }
The log output after a run from the scripting view.
In case the script is not running from the scripting view the messages could be found in the browser console instead.
Scripting inside SAP Screen Personas for Web Dynpro ABAP offers quite some capabilities for automation – however for more complex scenarios the development of scripts is very similar to application development.
To work with the SAP Screen Personas features inside Web Dynpro ABAP based applications you need to have at least SAP Screen Personas 3.0 SP01 and SAP_UI 750 SP01 installed on your system – otherwise the SAP Screen Personas functions are not enabled for Web Dynpro ABAP based applications. See note 2181980 for more details on the system requirements.
As example we use the product maintenance application from the Enterprise Procurement Model, which is part of each SAP NetWeaver installation. We’ll change a couple of texts in the application in order to meet our understanding.
The original application (S_EPM_FPM_PD) looks like the following:
After the adjustment the screen should look like the following:
I know that such changes as well can be made using the SAP Floorplan Manager based tools – however I’d like to show the capabilities of SAP Screen Personas for Web Dynpro ABAP in this example.
All changes in SAP Screen Personas are associated with a flavor – this we start with the creation of a flavor using the flavor bar on top of the screen. To start the flavor bar click on the blue P on top of the screen - if this is not visible for you, you need to have additional authorisations to use SAP Screen Personas.
At this point in time the application is set into a design mode where all objects can be accessed but the normal application functions, e.g. input of values are deactivated – additionally the SAP Screen Personas editor is shown on the top of the screen.
The editor hosts all functions which are available inside SAP Screen Personas with one note able exception – the change of the text. To change the text of an element the element has to be double clicked.
If the element allows the change of the text a popup window appears in which the text can be changed – the change will be recorded in the current language only. After the change the flavor needs to be saved to see the changed texts later in the running application.
To enable the changed texts in other languages too – SAP Screen Personas offers a translation tool for changes made with SAP Screen Personas inside the administration tools. These tools can be reached in the SAP Screen Personas backend system with transaction code /PERSONAS/ADMIN.