Add a Custom Screen on Purchase Requisition Header (2024)

I had saw some threads/posts in SAP forums, they were asking for the solutions on how to adding a custom screen/tab on the purchase requisition. But just as my knowledge, SAP has not provided any user-exit/Badi/SMOD for enhancing the screen of header part of purchase requisition.

And as we also know, purchase requisition database designing is different from other businesses object documents. A general designing of database table for business documents should commonly have Header and Items, some has Schedule Lines. For example, EKKO and EKPO for purchase order, VBAK and VBAP for sales order, BKPF and BSEG for FI documents……

For purchase requisition, it seems that the data is stored on item level, we only have EBAN for purchase requisition (other database table is not taken into account in this blog, for example account assignment table EBKN).

No standard enhancement and even no database design for purchase requisition header. Well, it seems that it is not possible to adding a custom screen for purchase requisition header level.

Some years ago we really cannot do it unless we put lots of effort on changing standard program. Of course this approach is hardly acceptable.

So, in case of receiving a requirement on making a custom header for purchase requisition or adding a new screen on header level, generally we will take an alternative solution, for example, add a custom screen tab on purchase item level, users can input header data on item level and the data should be item-dependent or item-independent, or even design a new application program to achieve the requirements.

But now, thanks for the new generation of enhancement technique, we can achieve the requirement by the implicit enhancement, and plus some SMOD/CMOD enhancement and Badi.

In this document, I would like to share two solutions on how to make a custom header for purchase requisition. Actually, I like the first one(And I think most of you too)

The result of the idea is we have an enhancement function for purchase requisition, but I hope the idea can also provide us a new thinking for other similar enhancement requirements.

1. A glance and investigation on purchase requisition application

As everyone knows, the transactions for purchase requisition generally include ME51N, ME52N, ME53N, ME54N. For these transactions, the triggered program is RM_MEREQ_GUI (See SE93).
Add a Custom Screen on Purchase Requisition Header (1)

In source code of triggered program RM_MEREQ_GUI, the function module MEGUI_MAINTAIN is invoked. This function module is a component of function group MEGUI (User interface for purchasing document). As the description of MEGUI, all the components related to user interface of purchasing documents are integrated into/by this function group, for example, screens, GUI statuses (In my opinion, MEGUI is just like the View of MVC pattern).

For the purchase requisition application, the main screen is 0014 of program SAPLMEGUI (or function group MEGUI), and GUI Status is REQ of program SAPLMEGUI (or function group MEGUI).
Add a Custom Screen on Purchase Requisition Header (2)
Add a Custom Screen on Purchase Requisition Header (3)

Generally, there only a Texts subscreen on the tabstrip. If you press F1 help on the screen field, you will find the program of screen editor is different from the program of the main screen.
By debugging, I found the function module MEGUI_BUILD_REQ_HEADER_PLUGIN is used for integrated to components of tabstrip, and the text editor is plus to tabstrip in this function module.
Add a Custom Screen on Purchase Requisition Header (4)
When I investigate the program at this point, I believe we can add a new subscreen (or more than one) onto the tabstrip by adopting the similar approach. (Yes, this is my idea on first solution)

Alsoby debugging, I found the application GUI Status is set in method PBO of class CL_WINDOW_MM (Inheriting from class CL_COMPOSITE_SCREEN_VIEW_MM), and the GUI Status is determined by method EXCLUDING_FUNCTIONS. The attributes DYNPRO and PROG indicate the current screen and program.
Add a Custom Screen on Purchase Requisition Header (5)
Add a Custom Screen on Purchase Requisition Header (6)
Add a Custom Screen on Purchase Requisition Header (7)

OK, I believe some people have got another idea on the solution now.

Yes, we can develop a new custom program and insert a GUI Status as the program component, and we also add a new button, saying Custom Header, into the Application Toolbar of the GUI Status. Then we can replace the original standard GUI status (l_pfstatus) and its program (l_pfprogram) by our custom objects. The best replacing position, of cause, should be located at the end of method EXCLUDING_FUNCTIONS, and everyone knows we can do it by implicit enhancement.

It is better to copy the standard GUI Status REQ to our new custom GUI Status, so that we can preserve the original buttons and menus (Actually, this is very important. Otherwise we will lose lots of functionalities when processing a purchase requisition).

But don’t forget that application program needs to response the new button.

By debugging, I found there have a method IF_COMMAND_MM~EXECUTE of local class LCL_DOCUMENT_CMD in function group MEGUI, which is the responder of users’ command.

Thanks the new generation enhancement technique again, we can place an implicit enhancement at the end of this method, so that the program can response the user command.

Beside the function group MEGUI, there has a function group MEREQ inside the whole application. This function group plays the role of processing purchase requisition document; it just looks like the Model of MVC pattern. There have lots of local classes in this function group; I would like to mention two local classes, which are involved in my document.

The local class LCL_REQ_HEADER is the model of purchase requisition header; it contains the processing logic on purchase requisition header. And another local class LCL_INSTANCE_FACTORY, a factory class for purchase requisition, is used for handling the core functionalities of purchase requisition, for example, post.

Of cause, we also have SMOD/Badi enhancements for processing purchase requisition; some of them will be involved in my document.

2. An enhancement demo step-by-step

My demo business requirement is: Users want to add two subscreens on the tabstrip of purchase requisition header, one is used for storing the related sales data of PR, another is used for storing procurement planning data of the PR.

2.1 Step 1 – Create a Database table for custom header of purchase requisition:

Create a new database table in SE11 ABAP dictionary. In my case, the database table is ZEBAN_HEADER.
Add a Custom Screen on Purchase Requisition Header (8)

2.2 Step 2 – Add a public method ZZGET_NEXT_SUBVIEW_COUNT into class CL_TABSTRIP_VIEW_MM.

Add a Custom Screen on Purchase Requisition Header (9)
Add a Custom Screen on Purchase Requisition Header (10)

METHOD ZZGET_NEXT_SUBVIEW_COUNT . RE_COUNT = LINES( SUBVIEWS ) + 1.ENDMETHOD.

This method is used for counting the subview (subscreen) of the tabstrip

2.3 Step 3 –Create a function group as the core processing logic of the enhancement, and at the meantime, it also provides subscreens.

In my case, the function group is ZME51N_HEADER_ENHM. Below is the code of the TOP INCLUDE.
Add a Custom Screen on Purchase Requisition Header (11)

*Start ************common components for two solution************TABLES: zeban_header.DATA: g_original_changed_flag TYPE flag.DATA: ok-code TYPE syucomm.DATA: g_trtyp TYPE trtyp. "H = Create, V = Change, A = Display*End ************common components for two solution*************Start ************only for first solution************TYPE-POOLS mmmfd.DATA: processed_model TYPE REF TO if_model_mm.INCLUDE lmeviewsf01.INCLUDE lzme51n_header_enhmcls.*End ************only for first solution************

There have two INCLUDE programs in the TOP. I believe lots of ABAP programmers are familiar with LMEVIEWSF01, which is used in enhancements on purchase order subscreens.

LZME51N_HEADER_ENHMCLS is a program file to store the class of our enhancement.

*&---------------------------------------------------------------------**& Include LZME51N_HEADER_ENHMCLS*&---------------------------------------------------------------------*CLASS lcl_custom_header DEFINITION INHERITING FROM cl_foreign_application_view_mm. PUBLIC SECTION. METHODS: constructor IMPORTING im_dynpro TYPE sy-dynnr im_prog TYPE sy-repid im_priority TYPE i OPTIONAL im_foreign_prog TYPE sy-repid im_foreign_dynpro TYPE sy-dynnr im_metafield TYPE mmpur_metafield. PROTECTED SECTION. METHODS: build_dynpro_fields REDEFINITION. METHODS: transport_from_model REDEFINITION. PRIVATE SECTION. DATA: custom_metafield TYPE mmpur_metafield.ENDCLASS. "lcl_custom_header DEFINITION*----------------------------------------------------------------------** CLASS lcl_custom_header IMPLEMENTATION*----------------------------------------------------------------------***----------------------------------------------------------------------*CLASS lcl_custom_header IMPLEMENTATION. METHOD constructor. CALL METHOD super->constructor EXPORTING im_dynpro = im_dynpro im_prog = im_prog im_priority = im_priority im_foreign_prog = im_foreign_prog im_foreign_dynpro = im_foreign_dynpro. custom_metafield = im_metafield. ENDMETHOD. "CONSTRUCTOR METHOD build_dynpro_fields. DATA: l_dynpro_entry LIKE LINE OF my_dynpro_fields. l_dynpro_entry-metafield = custom_metafield. INSERT l_dynpro_entry INTO TABLE my_dynpro_fields. ENDMETHOD. "BUILD_DYNPRO_FIELDS METHOD transport_from_model. foreign_application_ok = mmpur_yes.* set model to function group processed_model = my_model. ENDMETHOD. "transport_from_modelENDCLASS. "lcl_custom_header IMPLEMENTATION

2.4 Step 4 – Create 3 subscreens for tabstrip subscreen of PR header.

Screen NumberDescriptionPurpose
9899Subscreen ContainerUsed for the screen container of other two subscreens
9900Subscreen – SalesUsed for displaying/inputting the related sales data of PR
9901Subscreen – ProcumentUsed for displaying/inputting the related procurement data of PR

Subscreen 9899:
Add a Custom Screen on Purchase Requisition Header (12)
Add a Custom Screen on Purchase Requisition Header (13)

PROCESS BEFORE OUTPUT. MODULE EVENT_PBO. MODULE EVENT_PBO_PREPARE. CALL SUBSCREEN CUSTOMSUBSCREEN INCLUDING CALL_PROG CALL_SUBSCREEN.PROCESS AFTER INPUT. MODULE EVENT_PAI_PREPARE. CALL SUBSCREEN CUSTOMSUBSCREEN. MODULE EVENT_PAI.

Above PBO and PAI modules are located at the INCLUDE program LMEVIEWSF01.

Subscreen 9900:

Add a Custom Screen on Purchase Requisition Header (14)

Add a Custom Screen on Purchase Requisition Header (15)

The fields on 9900 are getting from custom table ZEBAN_HEADER (We had declared it in the TOP INCLUDE program by TABLES statement).

Sales Document – ZEBAN_HEADER-VBELN

Customer PO – ZEBAN_HEADER-BSTKD

Sales budget Number – ZEBAN_HEADER-SBUDGET
Add a Custom Screen on Purchase Requisition Header (16)

PROCESS BEFORE OUTPUT. MODULE modify_custom_screen.*PROCESS AFTER INPUT.

Add a Custom Screen on Purchase Requisition Header (17)

*----------------------------------------------------------------------****INCLUDE LZME51N_HEADER_ENHMO01.*----------------------------------------------------------------------**&---------------------------------------------------------------------**& Module MODIFY_CUSTOM_SCREEN OUTPUT*&---------------------------------------------------------------------** text*----------------------------------------------------------------------*MODULE modify_custom_screen OUTPUT. IF processed_model IS BOUND. CLEAR g_trtyp. PERFORM get_transaction_type IN PROGRAM saplmereq IF FOUND USING processed_model CHANGING g_trtyp. ELSE. g_trtyp = 'A'. ENDIF. LOOP AT SCREEN. IF g_trtyp = 'A'. screen-input = '0'. ELSE. screen-input = '1'. ENDIF. MODIFY SCREEN. ENDLOOP.ENDMODULE. " MODIFY_CUSTOM_SCREEN OUTPUT

Subscreen 9901:

Add a Custom Screen on Purchase Requisition Header (18)

The fields on 9901 are getting from custom table ZEBAN_HEADER:

Procurement Plan – ZEBAN_HEADER-PPLAN

Country – ZEBAN_HEADER-LAND1

Region – ZEBAN_HEADER-REGIO
Add a Custom Screen on Purchase Requisition Header (19)
The PBO module of 9901 is same as 9900, I don’t demonstrate at here again.

2.5 Step 5 – Insert an INCLUDE program LZME51N_HEADER_ENHMF01 into function group ZME51N_HEADER_ENHM. This INCLUDE program used for storing the subroutines of the function group.
Add a Custom Screen on Purchase Requisition Header (20)

*&---------------------------------------------------------------------**& Include LZME51N_HEADER_ENHMF01*&---------------------------------------------------------------------**&---------------------------------------------------------------------**& Form ADD_SUBSCREN*&---------------------------------------------------------------------*FORM add_subscren USING value(u_tab_subscreen) type sydynnr value(u_tab_label) type clike value(u_tab_header_text) type clike uo_model_holder TYPE REF TO CL_TABSTRIP_VIEW_MM. DATA: lo_custom_view TYPE REF TO lcl_custom_header. DATA: l_label_text TYPE string40, l_header_text TYPE string40, l_structure TYPE tabname VALUE 'ZEBAN_HEADER'. DATA: l_repid TYPE syrepid VALUE 'SAPLZME51N_HEADER_ENHM'. l_label_text = u_tab_label. l_header_text = u_tab_header_text. CREATE OBJECT lo_custom_view EXPORTING im_dynpro = '9899' "subscreen container im_prog = l_repid im_foreign_prog = l_repid im_foreign_dynpro = u_tab_subscreen im_metafield = mmmfd_header_userexit. IF lo_custom_view IS BOUND. CALL METHOD lo_custom_view->set_label( l_label_text ). CALL METHOD lo_custom_view->set_name( l_header_text ). CALL METHOD lo_custom_view->set_struct_name( im_struct_name = l_structure im_application = 'REQ' ). CALL METHOD uo_model_holder->add EXPORTING im_screen_view = lo_custom_view im_position = uo_model_holder->zzget_next_subview_count( ). SET HANDLER lo_custom_view->if_observer_mm~handle_subject_changed FOR uo_model_holder. SET HANDLER uo_model_holder->if_observer_mm~handle_subject_changed FOR lo_custom_view. ENDIF.ENDFORM. " ADD_SUBSCREN

2.6 Step 6 – Insert below function modules into the function group ZME51N_HEADER_ENHM.
Add a Custom Screen on Purchase Requisition Header (21)

And please set ZPR_HEADER_CUSTOM_SAVE_CORE as the update module.

FUNCTION zpr_check_transaction_state .*"----------------------------------------------------------------------*"*"Local Interface:*" IMPORTING*" REFERENCE(IM_BANFN) TYPE BANFN*" CHANGING*" REFERENCE(CH_CHANGED) TYPE FLAG OPTIONAL*"---------------------------------------------------------------------- DATA: l_count TYPE i. DATA: ls_custom_header TYPE zeban_header. g_original_changed_flag = ch_changed. "backup the original 'changed' indicator CHECK ch_changed IS INITIAL. SELECT COUNT( * ) INTO l_count FROM eban WHERE banfn = im_banfn. CHECK l_count >= 1.*THE PROCESSED PR IS EXISTED IN DB SELECT SINGLE * INTO ls_custom_header FROM zeban_header WHERE banfn = im_banfn. IF ls_custom_header-vbeln <> zeban_header-vbeln OR ls_custom_header-bstkd <> zeban_header-bstkd OR ls_custom_header-sbudget <> zeban_header-sbudget OR ls_custom_header-pplan <> zeban_header-pplan OR ls_custom_header-land1 <> zeban_header-land1 OR ls_custom_header-regio <> zeban_header-regio.* THE CUSTOM FIELDS IN RUNTIME IS DIFFERENT FROM DB* THE PR HAS BEEN CHANGED ch_changed = 'X'. ENDIF.ENDFUNCTION.
FUNCTION zpr_custom_header_tab_add.*"----------------------------------------------------------------------*"*"Local Interface:*" IMPORTING*" REFERENCE(IM_O_MODEL_HOLDER) TYPE REF TO CL_TABSTRIP_VIEW_MM*"----------------------------------------------------------------------*add subscreen for sales PERFORM add_subscren USING '9900' 'Custom Header- Sales' "tab label 'ADDITIONAN HEADER - Sales' "header text im_o_model_holder.*add subscreen for procurement PERFORM add_subscren USING '9901' 'Custom Header- Procurement' "tab label 'ADDITIONAN HEADER - Procurement' "header text im_o_model_holder.ENDFUNCTION.
FUNCTION zpr_export_buffer.*"----------------------------------------------------------------------*" EXPORTING*" REFERENCE(EX_BANFN) TYPE BANFN*" REFERENCE(EX_ORIGINAL_CHANGED) TYPE FLAG*"---------------------------------------------------------------------- ex_banfn = zeban_header-banfn. ex_original_changed = g_original_changed_flag. CLEAR g_original_changed_flag.ENDFUNCTION.
FUNCTION zpr_header_custom_save.*"----------------------------------------------------------------------*"*"Local Interface:*" IMPORTING*" REFERENCE(IM_BANFN) TYPE BANFN*"---------------------------------------------------------------------- DATA: l_changed TYPE flag. DATA: l_count TYPE i. SELECT COUNT( * ) INTO l_count FROM eban WHERE banfn = im_banfn. IF l_count >= 1.* not create mode* we need to check if data has been changed CALL FUNCTION 'ZPR_CHECK_TRANSACTION_STATE' EXPORTING im_banfn = im_banfn CHANGING ch_changed = l_changed. CHECK l_changed IS NOT INITIAL. ENDIF. zeban_header-banfn = im_banfn. CALL FUNCTION 'ZPR_HEADER_CUSTOM_SAVE_CORE' IN UPDATE TASK EXPORTING im_s_header = zeban_header.ENDFUNCTION.
FUNCTION zpr_header_custom_save_core.*"----------------------------------------------------------------------*" IMPORTING*" VALUE(IM_S_HEADER) TYPE ZEBAN_HEADER*"----------------------------------------------------------------------*please set this module as update moduleMODIFY zeban_header FROM IM_S_HEADER.ENDFUNCTION.
FUNCTION zpr_open.*"----------------------------------------------------------------------*" IMPORTING*" REFERENCE(IO_HEADER) TYPE REF TO IF_PURCHASE_REQUISITION*"---------------------------------------------------------------------- DATA: ls_header TYPE mereq_header. DATA: l_count TYPE i. CLEAR zeban_header. clear g_original_changed_flag. ls_header = io_header->get_data( ). SELECT COUNT( * ) INTO l_count FROM eban WHERE banfn = ls_header-banfn. CHECK l_count >= 1.*THE PROCESSED PR IS EXISTED IN DB SELECT SINGLE * FROM zeban_header WHERE banfn = ls_header-banfn. IF sy-subrc <> 0. zeban_header-banfn = ls_header-banfn. ENDIF.ENDFUNCTION.

2.7 Step 7 – Apply implicit enhancement implementation to add the new subscreens onto the tabstrip of PR header
Add a Custom Screen on Purchase Requisition Header (22)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Function Module MEGUI_BUILD_REQ_HEADER_PLUGIN, End A*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 1 ZPR_CUSTOM_TAB_MEGUI. "active versionif sy-uname = 'CHENGANGRONG' AND ( SY-TCODE = 'ME51N' OR SY-TCODE = 'ME52N' OR SY-TCODE = 'ME53N' OR SY-TCODE = 'ME54N' ).CALL FUNCTION 'ZPR_CUSTOM_HEADER_TAB_ADD' EXPORTING IM_O_MODEL_HOLDER = header_view.ENDIF.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

Once the above steps are done, you can see the two subscreens are appearing on the tabstrip of PR header.
Add a Custom Screen on Purchase Requisition Header (23)

2.8 Step 8 – Add an implicit enhancement into method if_purchase_requisition~get_transaction_state
The method is a component of local class LCL_REQ_HEADER in function group MEREQ, and located at INCLUDE program LMEREQF12.

Based on the exporting parameter of the method, we know that this method is used for returning the transaction states of the purchase requisition, for example, whether the purchase requisition has been changed.
Add a Custom Screen on Purchase Requisition Header (24)

Why do we need to add this enhancement?

When users just change the data in the enhanced custom header screen but leave the standard data unchanged (EBAN, EBKN, TEXT, etc), the application will not recognize the changing of the document. So application will not trigger the saving process for the document.

In this case we need to overwrite the changed indicator of LCL_REQ_HEADER, so that the program can recognize and accept the changing of the document.

Because it has a CHECK statement in the method, we need to add the implicit enhancement at the beginning of the method; otherwise the implemented codes will be skipped under certain circ*mstance (for example, Create Mode, ME51N), see below screenshot.
Add a Custom Screen on Purchase Requisition Header (25)

So the enhancement is below:
Add a Custom Screen on Purchase Requisition Header (26)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class LCL_REQ_HEADER, Interface IF_PURCHASE_REQUISITION, Method GET_TRANSACTION_STATE, Start A*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 1 ZPR_CUSTOM_TAB_MEREQ. "active versionif sy-uname = 'CHENGANGRONG' AND SY-DYNNR = '0014' AND ( SY-TCODE = 'ME51N' OR SY-TCODE = 'ME52N' OR SY-TCODE = 'ME53N' OR SY-TCODE = 'ME54N' ).IF my_state->changed IS INITIAL.CALL FUNCTION 'ZPR_CHECK_TRANSACTION_STATE' EXPORTING im_banfn = my_state->header-banfn CHANGING CH_CHANGED = my_state->changed.ENDIF.endif.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

2.9 Step 9 – Implement the Badi ME_PROCESS_REQ_CUST, and then insert below codes into the method OPEN (It is easy to understand that application need to initialize and read the custom header data when a new purchase requisition is opened).

In my case, the Badi implementation is ZME_PROCESS_REQ_CUST .
Add a Custom Screen on Purchase Requisition Header (27)

Add a Custom Screen on Purchase Requisition Header (28)

METHOD if_ex_me_process_req_cust~open. IF sy-uname = 'CHENGANGRONG' AND ( sy-tcode = 'ME51N' OR sy-tcode = 'ME52N' OR sy-tcode = 'ME53N' OR sy-tcode = 'ME54N' ). CALL FUNCTION 'ZPR_OPEN' EXPORTING io_header = im_header. ENDIF.ENDMETHOD.

2.10 Step 10 – Saving custom header data for purchase requisition.

I use the EXIT function module EXIT_SAPLMEREQ_008 as saving position of the custom header data (The SMOD enhancement is MEREQ001, it is a common enhancement, so that I would not explain the CMOD project in detail).

Maybe someone will ask me why do not put the saving process at method POST of Badi ME_PROCESS_REQ_CUST.

Actually I had tried but it doesn’t work in some case. For example, if user just changes the custom header data but leave the standard data unchanged (EBAN, EBKN, TEXT, etc), the application would not trigger the implemented POST method of ME_PROCESS_REQ_CUST. So I have to make the enhancement position at EXIT_SAPLMEREQ_008.
Add a Custom Screen on Purchase Requisition Header (29)

 IF sy-uname = 'CHENGANGRONG' AND sy-dynnr = '0014' AND ( sy-tcode = 'ME51N' OR sy-tcode = 'ME52N' OR sy-tcode = 'ME53N' OR sy-tcode = 'ME54N' ). CALL FUNCTION 'ZPR_HEADER_CUSTOM_SAVE' EXPORTING im_banfn = im_banfn_new. ENDIF.

2.11 Step 11 – Add a new public method zzcustom_after_post into local class LCL_REQ_HEADER.

Once we implement the custom header screen on purchase requisition, the system behaviors of change mode (ME52N) will have some difference from the original behaviors after saving the PR document.

The original behavior: the system will alternate the transaction type from change mode to display mode (my_state->trtyp). And changed indicator my_state->changed will be reset to SPACE. (see at the last of method implementation prepare_post of local class lcl_req_header in INCLUDE program LMEREQF08)
Add a Custom Screen on Purchase Requisition Header (30)

New behavior of our implementation: If user only changes custom header data but leave standard data unchanged (EBAN, EBKN, TEXT, etc), the method prepare_post will raise an exception no_changes before reset of the changed indicator and alternation of transaction type. In this case the purchase requisition will leave to changed state and change mode after saving the PR document. This is different from the original system behavior.
Add a Custom Screen on Purchase Requisition Header (31)

To overcome the gap between original behavior and new behavior, we need to have a method to set the transaction type and changed indicator as what it is in standard behavior after the document is saved. So I introduce the new method zzcustom_after_post for local class LCL_REQ_HEADER.

In the definition part of LCL_REQ_HEADER (INCLUDE program LMEREQF07 of function group MEREQ), I make such implicit enhancement:
Add a Custom Screen on Purchase Requisition Header (32)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class LCL_REQ_HEADER, Vor den PUBLIC-Methoden S*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 2 ZPR_CUSTOM_TAB_MEREQ. "active versionMETHODS: zzcustom_after_post.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

And in the implementation part of LCL_REQ_HEADER (INCLUDE program LMEREQF08 of function group MEREQ), I make such implicit enhancement:
Add a Custom Screen on Purchase Requisition Header (33)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class LCL_REQ_HEADER, End S*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 3 ZPR_CUSTOM_TAB_MEREQ. "active versionMETHOD zzcustom_after_post. me->my_state->trtyp = me->my_state->aktyp = anz. me->my_state->changed = mmpur_no.ENDMETHOD.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

And please see Step 12 on how we using the new enhancement method.

2.12 Step 12 – Add an implicit enhancement at the POST method of local class LCL_INSTANCE_FACTORY.
The POST method of local class LCL_INSTANCE_FACTORY is located at INCLUDE program LMEREQF06 of function group MEREQ.

Just as I had mentioned at above some steps, if user only change the custom header data but leave standard data unchanged (EBAN, EBKN, TEXT, etc), the application will not recognize the changing of the document.

Although we had added an implicit enhancement at Step 8 for replacing the changed indicator of the document, the application still doesn’t trigger the commit work, if no any standard data is changed.

If you have noticed that the custom function module ZPR_HEADER_CUSTOM_SAVE, which we place at EXIT function EXIT_SAPLMEREQ_008, is just a normal function module. But inside the function module there have another FM ZPR_HEADER_CUSTOM_SAVE_CORE is invoked by update task:
Add a Custom Screen on Purchase Requisition Header (34)

So we have to take a solution for triggering the commit work in case of standard data unchanged.

At last, by debugging, I found the best implementation position is at the end of POST method of LCL_INSTANCE_FACTORY.
Add a Custom Screen on Purchase Requisition Header (35)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class LCL_INSTANCE_FACTORY, Method POST, End A*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 4 ZPR_CUSTOM_TAB_MEREQ. "active version DATA: l_zzehm_banfn TYPE banfn. DATA: ls_zzehm_hashed_entry TYPE hash_table_entry. data: l_zzhm_original_changed type flag. IF sy-uname = 'CHENGANGRONG' AND sy-dynnr = '0014' AND ( sy-tcode = 'ME51N' OR sy-tcode = 'ME52N' OR sy-tcode = 'ME53N' OR sy-tcode = 'ME54N' ). CALL FUNCTION 'ZPR_EXPORT_BUFFER' IMPORTING ex_banfn = l_zzehm_banfn ex_original_changed = l_zzhm_original_changed. IF l_zzhm_original_changed IS INITIAL.* no changed for PR data(standard DB data)* program would not execute commit at previous step* in this case, we have to execute commit so that* the FM ZPR_HEADER_CUSTOM_SAVE_CORE can be submit to commit* (see FM EXIT_SAPLMEREQ_008 and ZPR_HEADER_CUSTOM_SAVE) IF im_no_commit EQ mmpur_no AND im_wait EQ cl_mmpur_constants=>no . COMMIT WORK. ELSEIF im_no_commit EQ mmpur_no AND im_wait EQ cl_mmpur_constants=>yes . COMMIT WORK AND WAIT. ENDIF. ENDIF. READ TABLE my_hash_table INTO ls_zzehm_hashed_entry WITH KEY banf = l_zzehm_banfn. IF sy-subrc = 0.* resume the changed indicator for header state ls_zzehm_hashed_entry-header->zzcustom_after_post( ). ENDIF. ENDIF.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

And now you will see the method zzcustom_after_post is called after the commit, so that the changed indicator and transaction type are reset.

2.13 Step 13 – Add an implicit enhancement at the end of LMEREQFXX. In the enhancement, insert an INCLUDE program ZZMEREQ_ENHANCEMENT.
Add a Custom Screen on Purchase Requisition Header (36)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Include LMEREQFXX, End S*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 5 ZPR_CUSTOM_TAB_MEREQ. "active versioninclude ZZMEREQ_ENHANCEMENT.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

The INCLUDE program ZZMEREQ_ENHANCEMENT has below codes:

*&---------------------------------------------------------------------**& Include ZZMEREQ_ENHANCEMENT*&---------------------------------------------------------------------*FORM get_transaction_type USING uo_model TYPE REF TO if_model_mm CHANGING c_trtyp TYPE trtyp. DATA: lo_req_header TYPE REF TO lcl_req_header. mmpur_dynamic_cast lo_req_header uo_model. CHECK NOT lo_req_header IS INITIAL. c_trtyp = lo_req_header->my_state->trtyp.ENDFORM. "get_transaction_type

The subroutine get_transaction_type is used for returning the transaction type of processed PR. This subroutine will be called at the PBO module MODIFY_CUSTOM_SCREEN of function group ZME51N_HEADER_ENHM.

If we have no this subroutine, the subscreens PBO can’t get the transaction type of PR, that means we can’t modify INPUT attribute of the subscreen fields by different transactions types (please see PBO module MODIFY_CUSTOM_SCREEN).

Well , the first solution is finished. We can see there have tow custom subscreens on the tabstrip of the PR header.
Add a Custom Screen on Purchase Requisition Header (37)

Although I really like the first solution, I would like to show you my second solution.
The demo requirement of second solution is: User want to have a button (In my case is Custom Header) on application toolbar of PR screen. If the button is clicked, a dialog box screen is generated and, the custom header data can be display/input on the screen.
Add a Custom Screen on Purchase Requisition Header (38)
This second solution will have lots of common part with the first solution, I only demonstrate the necessary steps for this solution.

2.1 Step 1 – Insert below declaration into TOP INCLUDE of function group ZME51N_HEADER_ENHM.

In my case, the function group is ZME51N_HEADER_ENHM. Below is the code of the TOP INCLUDE.
Add a Custom Screen on Purchase Requisition Header (39)

*Start************only for second solution************DATA: gs_header_backup TYPE zeban_header.DATA: main_okcode TYPE syucomm. "OKCODE FROM PR APPLICATION*End ************only for second solution************

2.2 Step 2 – Create a GUI Status for replacing the original standard GUI status REQ of SAPLMEGUI. And do not forget to copy/adjust the buttons from standard GUI status REQ of SAPLMEGUI.
Add a Custom Screen on Purchase Requisition Header (40)
Add a Custom Screen on Purchase Requisition Header (41)
Add a Custom Screen on Purchase Requisition Header (42)
Add a Custom Screen on Purchase Requisition Header (43)
After adjusting the new GUI Status REQ from standard GUI Status REQ of SAPLMEGUI, we need to add a new button into the application toolbar, so that we can develop the logic for generating the custom header screen. In my case, the function code of new button is ZCUSTOM, and also input the related icon text and preferred icon name.
Add a Custom Screen on Purchase Requisition Header (44)

2.3 Step 3 – Create a dialog box screen for custom header of purchase requisition.

I would not demonstrate the screen creation in detail, since it is just a common development technique. And do not forget to create a dialog box GUI Status and title for this new screen.
Add a Custom Screen on Purchase Requisition Header (45)
Add a Custom Screen on Purchase Requisition Header (46)
Add a Custom Screen on Purchase Requisition Header (47)
Add the STATUS_0001 module into the INCLUDE file LZME51N_HEADER_ENHMO01 of PBO modules .

Add a Custom Screen on Purchase Requisition Header (48)

*&---------------------------------------------------------------------**& Module STATUS_0001 OUTPUT*&---------------------------------------------------------------------** text*----------------------------------------------------------------------*MODULE status_0001 OUTPUT. SET PF-STATUS 'CUSTOM_DYN'. SET TITLEBAR 'CUSTOM_DYN_TITLE'. LOOP AT SCREEN. IF screen-name = 'ZEBAN_HEADER-VBELN'. IF g_trtyp = 'A'.* display mode, input not possible screen-input = '0'. ELSE.* change or create mode, input activated screen-input = '1'. ENDIF. ENDIF. MODIFY SCREEN. ENDLOOP.ENDMODULE. " STATUS_0001 OUTPUT

Add PAI module USER_COMMAND_0001 to the INCLUDE fileLZME51N_HEADER_ENHMI01

Add a Custom Screen on Purchase Requisition Header (49)

*----------------------------------------------------------------------****INCLUDE LZME51N_HEADER_ENHMI01.*----------------------------------------------------------------------**&---------------------------------------------------------------------**& Module USER_COMMAND_0001 INPUT*&---------------------------------------------------------------------** text*----------------------------------------------------------------------*MODULE user_command_0001 INPUT. CASE okcode. WHEN 'OK'. GS_HEADER_BACKUP = ZEBAN_HEADER. WHEN 'EXIT'. ZEBAN_HEADER = GS_HEADER_BACKUP. ENDCASE. SET SCREEN 0. LEAVE SCREEN.ENDMODULE. " USER_COMMAND_0001 INPUT

In my case, the dialog box GUI Status for the screen 0001 is CUSTOM_DYN, and the GUI title is CUSTOM_DYN_TITLE.
Add a Custom Screen on Purchase Requisition Header (50)
Add a Custom Screen on Purchase Requisition Header (51)

2.4 Step 4 – Inserta new function module ZPR_HEADER_CUSTOM_SCREEN_CALL into function group ZME51N_HEADER_ENHM.
Add a Custom Screen on Purchase Requisition Header (52)

FUNCTION zpr_header_custom_screen_call.*"----------------------------------------------------------------------*" IMPORTING*" REFERENCE(IM_O_MODEL) TYPE REF TO IF_MODEL_MM*" REFERENCE(IM_TRTYP) TYPE TRTYP*"---------------------------------------------------------------------- DATA: l_changed TYPE flag. DATA: lo_processing_req TYPE REF TO if_purchase_requisition. lo_processing_req ?= im_o_model. g_trtyp = im_trtyp. CHECK lo_processing_req IS BOUND. lo_processing_req->get_transaction_state( IMPORTING ex_changed = l_changed ). IF g_trtyp = 'H' AND l_changed = space.*create mode but no data is inputted*a blank purchase requisition MESSAGE 'Please input the PR data first......' TYPE 'S' DISPLAY LIKE 'E'. EXIT. ENDIF. main_okcode = sy-ucomm. gs_header_backup = zeban_header. CALL SCREEN '0001' STARTING AT 25 6 ENDING AT 88 10. sy-ucomm = main_okcode.ENDFUNCTION.

2.5 Step 5 – Apply implicit enhancement implementation to replace the original standard GUI Status REQ of program SAPLMEGUI

Add a Custom Screen on Purchase Requisition Header (53)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class CL_COMPOSITE_SCREEN_VIEW_MM, Method EXCLUDING_FUNCTIONS, End A*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 1 ZPR_CUSTOM_TAB_COMP_SCREEN. "active versionIF sy-uname = 'CHENGANGRONG' AND sy-dynnr = '0014' AND ( sy-tcode = 'ME51N' OR sy-tcode = 'ME52N' OR sy-tcode = 'ME53N' OR sy-tcode = 'ME54N' ). IF dynpro = '0014' AND prog = 'SAPLMEGUI'. ch_pfprogram = 'SAPLZME51N_HEADER_ENHM'. ch_pfstatus = 'REQ'. ENDIF.ENDIF.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

Once we have above implementation, a new button will appear on the application tool bar of purchase requisition applications (ME51N/ME52N/ME53N/ME54N).
Add a Custom Screen on Purchase Requisition Header (54)

2.6 Step 6 – make the Custom Header button functioning.
The methodif_command_mm~executeof local classlcl_document_cmdof programSAPLMEGUIwill response the user actions. We can put an implicit enhancement at the end of this method, so that the program can response the user command on the main screen of purchase requisition.

In my demo case, if user click Custom Header button, then program will call a dialog box screen 0001 in the enhancement function groupZME51N_HEADER_ENHM.

At the implementation section ofif_command_mm~execute of local class lcl_document_cmd(locate at INCLUDE programLMEGUICJL), I put below implicit enhancement at the end of the method:
Add a Custom Screen on Purchase Requisition Header (55)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class LCL_DOCUMENT_CMD, Interface IF_COMMAND_MM, Method EXECUTE, End A*$*$-Start: (1)---------------------------------------------------------------------------------$*$*ENHANCEMENT 3 ZPR_CUSTOM_TAB_MEGUI. "active version DATA: ls_zzenhm_doc_info TYPE mepo_document, lt_zzenhm_doc_info TYPE mepo_documents, l_zzenhm_model type ref to if_model_mm. CHECK sy-uname = 'CHENGANGRONG' AND sy-dynnr = '0014' AND ( sy-tcode = 'ME51N' OR sy-tcode = 'ME52N' OR sy-tcode = 'ME53N' OR sy-tcode = 'ME54N' ). IF l_transaction IS NOT BOUND. l_transaction = l_appl->my_trmgr->get_current( ). CHECK l_transaction IS BOUND. ENDIF. l_transaction->get_info( IMPORTING ex_documents = lt_zzenhm_doc_info ex_aggregate = l_zzenhm_model ). READ TABLE lt_zzenhm_doc_info INTO ls_zzenhm_doc_info INDEX 1. CHECK sy-subrc = 0. CASE im_fcode. WHEN 'ZCUSTOM'. CALL FUNCTION 'ZPR_HEADER_CUSTOM_SCREEN_CALL' EXPORTING im_o_model = l_zzenhm_model im_trtyp = ls_zzenhm_doc_info-trtyp. ENDCASE.ENDENHANCEMENT.*$*$-End: (1)---------------------------------------------------------------------------------$*$*

When this step had been done, the custom header screen can be generated when the Custom Header button is clicked.
Add a Custom Screen on Purchase Requisition Header (56)

Since most of other processes are same as the first solution (for example, save the custom PR header data), so I do not show it any more.

Well, the demo is finished. Thanks for looking my works.

Add a Custom Screen on Purchase Requisition Header (2024)

FAQs

How do I add a custom field to screen in SAP? ›

Create a project using CMOD including your enhancement. Create the append structure with new fields. Go to the desired function group and create a subscreen with the new fields. Write PBO and PAI for the subscreen, if required.

How do I create a custom screen in standard screen in SAP? ›

Custom subscreen on standard Transaction EEDM09, EEDM10 and EEDM11
  1. TABLE: Include structure CI_EUIHEAD with necessary fields (ZZNAME1 and ZZMOB) in the standard table EUIHEAD.
  2. Create a Module Pool Program 'SAPMZTEST' with screen number '800 '.
  3. Go to transaction SE19 and create implementation Class 'ZCL_IM_ISU_EDM_POD'
24 Jan 2014

How do you add custom fields in ME51N at item level? ›

This is done via customizing. Call transaction spro and then go down the path Materials Management -> Purchasing -> Purchase Requisition -> Define Screen Layout at Document Level and there view the details on the transaction you want to customize. You need to uncheck the "Display" checkbox for your field.

How do I add a custom field to a standard screen? ›

Add a custom field to a screen
  1. Select > Issues.
  2. Under FIELDS, click Custom fields.
  3. Find the custom field and click > Associate to Screens. ...
  4. Check the screens on which you want to display this custom field.

How do I add a custom field in VA01 in SAP? ›

Add A New Field in VA01 Header
  1. Step1: Append a new field where the data has to be stored. ...
  2. Step2: If we want to add any fields, we can use the screen number 8309 in program name SAPMV45A for header.
  3. Step3: In the layout, you can design the screen how it has to be displayed.
1 Feb 2019

Top Articles
Latest Posts
Article information

Author: Edmund Hettinger DC

Last Updated:

Views: 5830

Rating: 4.8 / 5 (58 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Edmund Hettinger DC

Birthday: 1994-08-17

Address: 2033 Gerhold Pine, Port Jocelyn, VA 12101-5654

Phone: +8524399971620

Job: Central Manufacturing Supervisor

Hobby: Jogging, Metalworking, Tai chi, Shopping, Puzzles, Rock climbing, Crocheting

Introduction: My name is Edmund Hettinger DC, I am a adventurous, colorful, gifted, determined, precious, open, colorful person who loves writing and wants to share my knowledge and understanding with you.