├── README.md ├── src └── images │ ├── cl_abap_behv_aux.png │ ├── Criticality_in_CDS.png │ ├── Session_Variables.jpg │ ├── Enable_LongText_In_CDS.jpg │ ├── Get_Decision_Note_Comments.jpg │ ├── Inline_Actions_in_Object_Page_Sections.gif │ ├── Filter_List_Reports_by_Child_Entity_Fields.gif │ ├── Grouping_Actions_as_Menu_Button_using_Annotations.mp4 │ └── Enable_Search_on_the_child_entity_fields_in_the_list_report.gif ├── ABAP on HANA └── Session_Variable.md ├── Workflow └── Get_Decision_Note_Comments.md ├── CDS ├── Enable_Long_Text.md ├── Filter_List_Reports_by_Child_Entity_Fields.md ├── Enable_Search_on_the_child_entity_fields_in_list_report.md ├── Criticality.abap ├── hide_fields_actions.abap ├── Inline_Actions_in_Object_Page_Sections.md ├── CDS_System_Generate_Series.abap └── Grouping_Actions_as_Menu_Button_using_Annotations.md ├── ABAP New Syntax ├── range_table.abap ├── segment_function.abap ├── add_leading_zeros_using_string_template(WIDTH).abap ├── CL_ABAP_STRUCT_UTILITIES.abap ├── return_statement.abap ├── step_keyword.abap ├── string_templates.abap ├── Corresponding_with_lookup_table.abap └── Group_Internal_Table_Data.abap ├── UI5 └── PDF(Base64)_Popup.js ├── Email ├── Validate_Email_address.abap └── Send_Internal_Table_as_Excel_Attachment.abap ├── ABAP RAP ├── Default_Function_RAP.abap ├── with_full_data.md ├── cl_abap_behv_aux.md ├── static_default _factory_action.abap ├── Show Fields in the Create Popup as Optional in RAP.abap ├── Hide_Fields_Based_on_Other_Field_Value_Immediately.abap ├── Display Message Strip by Default in Object Page.abap └── Download_Adobe_Form_in_RAP.abap ├── File Handling ├── Create_CSV_File_Using_CL_CSV_FACTORY.abap └── Read_Excel_data_using_XCO_Libaray.abap ├── ABAP SQL ├── Structure_Indicators.abap ├── STRING_AGG_Function.abap ├── COALESCE_Function.abap └── window_functions.abap ├── Fiori └── Construct_FLP_URL.abap ├── JSON └── JSON_Conversion_in_ABAP.abap └── ZIP └── Download_Multiple_Adobe_Form_as_ZIP_file.abap /README.md: -------------------------------------------------------------------------------- 1 | # ABAP Library 2 | This repository represents my personal ABAP codes 3 | -------------------------------------------------------------------------------- /src/images/cl_abap_behv_aux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/cl_abap_behv_aux.png -------------------------------------------------------------------------------- /src/images/Criticality_in_CDS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Criticality_in_CDS.png -------------------------------------------------------------------------------- /src/images/Session_Variables.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Session_Variables.jpg -------------------------------------------------------------------------------- /src/images/Enable_LongText_In_CDS.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Enable_LongText_In_CDS.jpg -------------------------------------------------------------------------------- /src/images/Get_Decision_Note_Comments.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Get_Decision_Note_Comments.jpg -------------------------------------------------------------------------------- /src/images/Inline_Actions_in_Object_Page_Sections.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Inline_Actions_in_Object_Page_Sections.gif -------------------------------------------------------------------------------- /src/images/Filter_List_Reports_by_Child_Entity_Fields.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Filter_List_Reports_by_Child_Entity_Fields.gif -------------------------------------------------------------------------------- /src/images/Grouping_Actions_as_Menu_Button_using_Annotations.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Grouping_Actions_as_Menu_Button_using_Annotations.mp4 -------------------------------------------------------------------------------- /src/images/Enable_Search_on_the_child_entity_fields_in_the_list_report.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharathi1294/abap_library/HEAD/src/images/Enable_Search_on_the_child_entity_fields_in_the_list_report.gif -------------------------------------------------------------------------------- /ABAP on HANA/Session_Variable.md: -------------------------------------------------------------------------------- 1 | # Session Variables in ABAP, CDS, AMDP 2 | 3 | In ABAP, we often used session variables. However, what would be their equivalent in AMDP or CDS? 4 | Here's a list of commonly used session variables in ABAP and their equivalent in AMDP/CDS 5 | 6 | ![Session Variables](../src/images/Session_Variables.jpg) -------------------------------------------------------------------------------- /Workflow/Get_Decision_Note_Comments.md: -------------------------------------------------------------------------------- 1 | # Get the decision note (approver comments) 2 | Try out this CDS/Class if you need to get the decision note (approver comments) from the work item. 3 | 4 | `1. I_WorkflowTaskResultComment`\ 5 | `2. CL_WAPI_DECISION_COMMENT_QUERY` 6 | 7 | Note: If you have this CDS in your system and if you want to retrieve old/completed work item notes, then execute the below report(If required) RSWW_SET_WORKITEM_COMMENTS. 8 | 9 | ![Decision Note](../src/images/Get_Decision_Note_Comments.jpg) 10 | 11 | -------------------------------------------------------------------------------- /CDS/Enable_Long_Text.md: -------------------------------------------------------------------------------- 1 | # Enable Long Text in CDS 2 | Here's a useful CDS annotation that enables long text/multiline text functionality. If you want to create or display long text fields in your RAP application, you can easily achieve this by using the `@UI.multiLineText` annotation. 3 | 4 | Additionally, if you want to display the long text as a separate tab in your application, you can create a new facet (with type `IDENTIFICATION_REFERENCE` or `FIELDGROUP_REFERENCE`) that references your long text field. 5 | 6 | ![Long Text Example](../src/images/Enable_LongText_In_CDS.jpg) -------------------------------------------------------------------------------- /CDS/Filter_List_Reports_by_Child_Entity_Fields.md: -------------------------------------------------------------------------------- 1 | # Filter List Reports by Child Entity Fields 2 | 3 | Have you ever wanted to filter a list report based on a field from a child entity? For example, filtering travel records by the AirlineID from the associated _Booking entity? 4 | 5 | You can achieve this by adding the following annotation to the root CDS view metadata extensions (e.g., Travel):\ 6 | 7 | `@𝗨𝗜.𝘀𝗲𝗹𝗲𝗰𝘁𝗶𝗼𝗻𝗙𝗶𝗲𝗹𝗱: [{ 𝗲𝗹𝗲𝗺𝗲𝗻𝘁: '_𝗕𝗼𝗼𝗸𝗶𝗻𝗴.𝗔𝗶𝗿𝗹𝗶𝗻𝗲𝗜𝗗', 𝗽𝗼𝘀𝗶𝘁𝗶𝗼𝗻: 𝟱𝟬 }]`\ 8 | `_𝗕𝗼𝗼𝗸𝗶𝗻𝗴;` 9 | 10 | I tested this in the BTP ABAP Environment, and it works perfectly but only with OData V4. 11 | 12 | ![Filter_List_Reports_by_Child_Entity_Fields ](../src/images/Filter_List_Reports_by_Child_Entity_Fields.gif) -------------------------------------------------------------------------------- /ABAP New Syntax/range_table.abap: -------------------------------------------------------------------------------- 1 | "Old way 2 | DATA: lr_salesorder TYPE RANGE OF vbeln. 3 | SELECT vbeln FROM vbak WHERE kunnr = '0000000272' INTO TABLE @DATA(lt_customers_orders). 4 | "Loop 5 | LOOP AT lt_customers_orders INTO DATA(ls_customer_order). 6 | ".... 7 | ENDLOOP. 8 | "For 9 | lr_salesorder = VALUE #( FOR ls_order IN lt_customers_orders ( 10 | sign = 'I' 11 | option = 'EQ' 12 | low = ls_order-vbeln ) ). 13 | 14 | "New way 15 | SELECT FROM vbak 16 | FIELDS 'I' AS sign, 17 | 'EQ' AS option, 18 | vbeln AS low, 19 | CAST( @space AS CHAR( 10 ) ) AS high 20 | WHERE kunnr = '0000000272' 21 | INTO TABLE @DATA(lr_salesorder). 22 | 23 | "Logic with lr_saleorder 24 | -------------------------------------------------------------------------------- /UI5/PDF(Base64)_Popup.js: -------------------------------------------------------------------------------- 1 | //Display Base64 PDF in Popup 2 | showPdfPopup: function(Base64Pdf) { 3 | var base64EncodedPDF = Base64Pdf; 4 | var decodedPdfContent = atob(base64EncodedPDF); 5 | var byteArray = new Uint8Array(decodedPdfContent.length); 6 | for (var i = 0; i < decodedPdfContent.length; i++) { 7 | byteArray[i] = decodedPdfContent.charCodeAt(i); 8 | } 9 | var blob = new Blob([byteArray.buffer], { 10 | type: 'application/pdf' 11 | }); 12 | var _pdfurl = URL.createObjectURL(blob); 13 | this._PDFViewer = new sap.m.PDFViewer({ 14 | title: "Title", 15 | source: _pdfurl, 16 | width:"50%", 17 | showDownloadButton: false 18 | }); 19 | jQuery.sap.addUrlWhitelist("blob"); 20 | 21 | this._PDFViewer.open(); 22 | } 23 | 24 | //Call method 25 | this.showPdfPopup("your base64 string" ); -------------------------------------------------------------------------------- /Email/Validate_Email_address.abap: -------------------------------------------------------------------------------- 1 | * Validates whether a string is a valid mail address (according to RFC 5322 Standard) 2 | CLASS lcl_email DEFINITION. 3 | PUBLIC SECTION. 4 | CLASS-METHODS: validate IMPORTING iv_email TYPE string 5 | RETURNING VALUE(rv_valid) TYPE abap_bool. 6 | ENDCLASS. 7 | 8 | CLASS lcl_email IMPLEMENTATION. 9 | METHOD validate. 10 | TRY. 11 | cl_bcs_email_address=>validate( iv_full_email = iv_email ). 12 | rv_valid = abap_true. 13 | CATCH cx_address_bcs INTO DATA(lx_address). 14 | rv_valid = abap_false. 15 | ENDTRY. 16 | ENDMETHOD. 17 | ENDCLASS. 18 | 19 | * Test the email address 20 | IF lcl_email=>validate( iv_email = 'anyemailaddress@gmail.com' ). 21 | "Valid Email Address 22 | ELSE. 23 | "Invalid Email address 24 | ENDIF. 25 | -------------------------------------------------------------------------------- /CDS/Enable_Search_on_the_child_entity_fields_in_list_report.md: -------------------------------------------------------------------------------- 1 | # 𝗘𝗻𝗮𝗯𝗹𝗲 𝗦𝗲𝗮𝗿𝗰𝗵 𝗼𝗻 𝗖𝗵𝗶𝗹𝗱 𝗘𝗻𝘁𝗶𝘁𝘆 𝗙𝗶𝗲𝗹𝗱𝘀 𝗶𝗻 𝗟𝗶𝘀𝘁 𝗥𝗲𝗽𝗼𝗿𝘁 2 | 3 | If you want to make fields from an child entity available in the global search(List Report), Just follow these steps to achieve. 4 | 5 | In your Root Entity, mark the exposed child entity with the annotation:\ 6 | `@𝗦𝗲𝗮𝗿𝗰𝗵.𝗱𝗲𝗳𝗮𝘂𝗹𝘁𝗦𝗲𝗮𝗿𝗰𝗵𝗘𝗹𝗲𝗺𝗲𝗻𝘁: 𝘁𝗿𝘂𝗲`\ 7 | `_𝗕𝗼𝗼𝗸𝗶𝗻𝗴;` 8 | 9 | In the child entity, specify the fields you want to be searchable:\ 10 | `@𝗦𝗲𝗮𝗿𝗰𝗵.𝗱𝗲𝗳𝗮𝘂𝗹𝘁𝗦𝗲𝗮𝗿𝗰𝗵𝗘𝗹𝗲𝗺𝗲𝗻𝘁: 𝘁𝗿𝘂𝗲`\ 11 | `𝗖𝗮𝗿𝗿𝗶𝗲𝗿𝗡𝗮𝗺𝗲;` 12 | 13 | You can also enhance the search experience by enabling fuzzy search settings. Once this is done, the relevant fields will be included in the global search. 14 | 15 | ![Enable_Search_on_the_child_entity_fields_in_the_list_report ](../src/images/Enable_Search_on_the_child_entity_fields_in_the_list_report.gif) -------------------------------------------------------------------------------- /ABAP RAP/Default_Function_RAP.abap: -------------------------------------------------------------------------------- 1 | "Step 1: Define a default function in your Behavior Definition (BDEF) 2 | define behavior for ZR_ROOT_ENTITY alias Travel 3 | .... 4 | { 5 | ... 6 | create{ default function GetDefaultsForCreate; } 7 | 8 | } 9 | 10 | "Step 2: Implement the logic in the behavior class 11 | METHOD GetDefaultsForCreate. 12 | result = VALUE #( FOR key IN keys ( 13 | %cid = key-%cid 14 | %param = VALUE #( CurrencyCode = 'INR' 15 | BeginDate = cl_abap_context_info=>get_system_date( ) 16 | OverallStatus = 'O' ) ) ). 17 | ENDMETHOD. 18 | 19 | "Step 3: Use the function in your Projection BDEF(If you defined) 20 | projection; 21 | strict(2); 22 | 23 | define behavior for ZC_ROOT_ENTITY alias Travel 24 | ... 25 | { 26 | ... 27 | use function GetDefaultsForCreate; 28 | } 29 | 30 | "Step 4: That’s it! Now when you try to create a new record, the values will be pre-filled automatically 31 | -------------------------------------------------------------------------------- /ABAP RAP/with_full_data.md: -------------------------------------------------------------------------------- 1 | The additions `𝘄𝗶𝘁𝗵 𝗮𝗱𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝘀𝗮𝘃𝗲` and `𝘄𝗶𝘁𝗵 𝘂𝗻𝗺𝗮𝗻𝗮𝗴𝗲𝗱 𝘀𝗮𝘃𝗲` can be used to enhance or to replace the default save sequence in a managed RAP BO. 2 | Both additions require a reimplementation of the `𝘀𝗮𝘃𝗲_𝗺𝗼𝗱𝗶𝗳𝗶𝗲𝗱` method of the RAP saver class. 3 | 4 | When the `𝘀𝗮𝘃𝗲_𝗺𝗼𝗱𝗶𝗳𝗶𝗲𝗱` method called we will receive only changed fields value in the update method. 5 | In scenarios where all fields, not only changed fields, are required for further processing, the addition `𝘄𝗶𝘁𝗵 𝗳𝘂𝗹𝗹 𝗱𝗮𝘁𝗮` can be used. 6 | By doing this, the RAP BO consumer avoids having to do an extra READ operation. 7 | 8 | `..𝘄𝗶𝘁𝗵 𝗮𝗱𝗱𝗶𝘁𝗶𝗼𝗻𝗮𝗹 𝘀𝗮𝘃𝗲 𝘄𝗶𝘁𝗵 𝗳𝘂𝗹𝗹 𝗱𝗮𝘁𝗮` 9 | `..𝘄𝗶𝘁𝗵 𝘂𝗻𝗺𝗮𝗻𝗮𝗴𝗲𝗱 𝘀𝗮𝘃𝗲 𝘄𝗶𝘁𝗵 𝗳𝘂𝗹𝗹 𝗱𝗮𝘁𝗮` 10 | 11 | Note: 12 | The fields of the component group `%𝗰𝗼𝗻𝘁𝗿𝗼𝗹` are not affected by this. Still, only the changed fields of %𝗰𝗼𝗻𝘁𝗿𝗼𝗹 are flagged. 13 | 14 | For More Info. 15 | https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbdl_saving.htm -------------------------------------------------------------------------------- /ABAP RAP/cl_abap_behv_aux.md: -------------------------------------------------------------------------------- 1 | # The usage of the class 𝗰𝗹_𝗮𝗯𝗮𝗽_𝗯𝗲𝗵𝘃_𝗮𝘂𝘅. 2 | 3 | Recently, I came across a scenario I’d like to share. I had a BDEF named `R_SomeName`, and on top of that, I created two projections: one for the `UI (C_SomeName)` and another for the `API (A_SomeName)`. 4 | 5 | Now, here's the interesting part: `R_SomeName` contains some validations and determinations. For the time being, I only want these to execute when the call is coming from the UI, not from the API. 6 | 7 | So, how can we distinguish whether the call originates from the UI or the API? This is where the class `𝗰𝗹_𝗮𝗯𝗮𝗽_𝗯𝗲𝗵𝘃_𝗮𝘂𝘅` comes in handy: 8 | 9 | `𝗰𝗹_𝗮𝗯𝗮𝗽_𝗯𝗲𝗵𝘃_𝗮𝘂𝘅=>𝗴𝗲𝘁_𝗰𝘂𝗿𝗿𝗲𝗻𝘁_𝗰𝗼𝗻𝘁𝗲𝘅𝘁( 𝗜𝗠𝗣𝗢𝗥𝗧𝗜𝗡𝗚 𝗳𝗿𝗼𝗺_𝗽𝗿𝗼𝗷𝗲𝗰𝘁𝗶𝗼𝗻 = 𝗗𝗔𝗧𝗔(𝗹𝘃_𝗽𝗿𝗼𝗷) ).` 10 | 11 | The lv_proj variable will hold the name of the calling projection `C_SomeName` if the call is from the UI or `A_SomeName` if it’s from the API. Based on this, you can conditionally execute logic in the handler class of `R_SomeName`. 12 | 13 | ![cl_abap_behv_aux ](../src/images/cl_abap_behv_aux.png) -------------------------------------------------------------------------------- /CDS/Criticality.abap: -------------------------------------------------------------------------------- 1 | Highlight Line Items and Columns Based on Criticality 2 | "Step 1: Derive the CriticalityCode Based on OverallStatus 3 | define root view entity ZR_ROOT_ENTITY 4 | { 5 | ... 6 | OverallStatus, 7 | case $projection.OverallStatus 8 | when 'A' then 3 // 3 - Green 9 | when 'X' then 1 // 2 - Red 10 | when 'O' then 2 // 1 - Yellow 11 | else 0 // 0 - Neutral 12 | end as CriticalityCode 13 | } 14 | "Step 2: Expose CriticalityCode in the Projection View 15 | define root view entity ZC_ROOT_ENTITY 16 | provider contract transactional_query 17 | as projection on ZR_ROOT_ENTITY 18 | { 19 | ... 20 | OverallStatus, 21 | CriticalityCode 22 | } 23 | "Step 3: Annotate in Metadata Extension 24 | @UI.lineItem: [{ criticality: 'CriticalityCode' }] 25 | annotate view ZC_ROOT_ENTITY with { 26 | .... 27 | @UI: { lineItem: [{position: 10, importance: #HIGH, criticality: 'CriticalityCode', criticalityRepresentation: #WITH_ICON }] } 28 | OverallStatus; 29 | } 30 | 31 | "Step 4: That's it. see the result - src/images/Criticality_in_CDS.png -------------------------------------------------------------------------------- /ABAP New Syntax/segment_function.abap: -------------------------------------------------------------------------------- 1 | "Segment - This function returns the occurrence of a segment of the argument text specified by index 2 | 3 | "index: Number of segment 4 | "sep: Substring specified is searched and used as limit 5 | "Hallo 6 | DATA(segment1) = segment( val = `Hallo,world,123` index = 1 sep = `,` ). 7 | 8 | "123 9 | DATA(segment2) = segment( val = `Hallo,world,123` index = -1 sep = `,` ). 10 | 11 | "world 12 | DATA(segment3) = segment( val = `Hallo
world
123` index = 2 sep = `
` ). 13 | 14 | "space: Each individual character is searched and used as limit 15 | DATA(to_be_segmented) = `a/b#c d.e`. 16 | 17 | "b 18 | DATA(segment4) = segment( val = `a/b#c d.e` index = 2 space = `. #/` ). 19 | 20 | DATA segment_tab TYPE string_table. 21 | DO. 22 | TRY. 23 | INSERT segment( val = to_be_segmented 24 | index = sy-index 25 | space = `. #/` ) INTO TABLE segment_tab. 26 | CATCH cx_sy_strg_par_val. 27 | EXIT. 28 | ENDTRY. 29 | ENDDO. 30 | 31 | *Content of segment_tab 32 | *a 33 | *b 34 | *c 35 | *d 36 | *e -------------------------------------------------------------------------------- /CDS/hide_fields_actions.abap: -------------------------------------------------------------------------------- 1 | "New field in the CDS View 2 | case when EmployeeStatus = 'RETIRED' 3 | then cast( 'X' as abap_boolean preserving type ) 4 | else cast( '' as abap_boolean preserving type ) 5 | end as HideCourseList 6 | 7 | "Metadata Extensions 8 | "Hide Facet in the Object Page 9 | @UI.facet: [{ type: #LINEITEM_REFERENCE, 10 | position: 20, 11 | id: 'CourseData', 12 | label: 'Courses', 13 | targetElement: '_Courses', 14 | purpose: #STANDARD, 15 | hidden: #(HideCourseList) } 16 | 17 | "Hide Standard Operations in the object page - Avaialble from S4HANA 2023+ 18 | @UI.createHidden: #(HideCourseList) 19 | @UI.updateHidden: #(HideCourseList) 20 | @UI.deleteHidden: #(HideCourseList) 21 | annotate entity ..... 22 | with 23 | 24 | "Hide Field 25 | @UI.hidden: #(HideCourseList) 26 | field_name; 27 | 28 | "Hide field from Facet Group 29 | @UI.identification: [{ hidden: #(HideCourseList) }] 30 | field_name; 31 | 32 | @UI.fieldGroup: [{ hidden: #(HideCourseList) }] 33 | field_name; 34 | 35 | "Etc,. 36 | -------------------------------------------------------------------------------- /File Handling/Create_CSV_File_Using_CL_CSV_FACTORY.abap: -------------------------------------------------------------------------------- 1 | SELECT FROM vbak 2 | FIELDS vbeln, vbtyp, erdat 3 | INTO TABLE @DATA(lt_test) 4 | UP TO 10 ROWS. 5 | 6 | "Simple CSV generation with header: 7 | DATA(lv_xstring_v1) = cl_csv_factory=>new_writer( 8 | )->set_delimiter( ';' 9 | )->set_write_header( abap_true 10 | )->write( REF #( lt_test ) ). 11 | 12 | "CSV generation with custom headers and field formatting: 13 | DATA(lv_xstring_v2) = cl_csv_factory=>new_writer( 14 | )->set_delimiter( ';' 15 | )->set_write_header( abap_true 16 | )->write( 17 | itab_ref = REF #( lt_test ) 18 | fieldcatalog = VALUE if_csv_field_catalog=>ty_t_fieldcatalog( 19 | ( fieldname = 'VBELN' header_text = |Sales Order| ) 20 | ( fieldname = 'VBTYP' header_text = |Sales Document Type| ) 21 | ( fieldname = 'ERDAT' header_text = |Created On| format = cl_csv_field_format=>date_iso ) ) ). 22 | -------------------------------------------------------------------------------- /ABAP New Syntax/add_leading_zeros_using_string_template(WIDTH).abap: -------------------------------------------------------------------------------- 1 | *If you are using string templates(with ALPHA) to add leading zeros, just have a look at the use of the WIDTH keyword. 2 | *It may be useful where we need to add dynamic number of leading zeros for the same input 3 | CLASS lcl_add_leading_zeros DEFINITION 4 | CREATE PUBLIC. 5 | PUBLIC SECTION. 6 | CLASS-METHODS: add_leading_zeros 7 | IMPORTING iv_input TYPE string 8 | iv_length TYPE int4 9 | RETURNING VALUE(rv_output) TYPE string. 10 | ENDCLASS. 11 | 12 | CLASS lcl_add_leading_zeros IMPLEMENTATION. 13 | METHOD add_leading_zeros. 14 | rv_output = |{ iv_input ALPHA = IN WIDTH = iv_length }|. 15 | ENDMETHOD. 16 | ENDCLASS. 17 | 18 | START-OF-SELECTION. 19 | DATA(lv_input) = '123'. 20 | "-> Convert input as a sales order number - VBELN (10) 21 | DATA(lv_so) = lcl_add_leading_zeros=>add_leading_zeros( iv_input = lv_input iv_length = 10 ). 22 | "Output - 0000000123 23 | "-> Convert input as a contract number - RANL (13) 24 | DATA(lv_cn) = lcl_add_leading_zeros=>add_leading_zeros( iv_input = lv_input iv_length = 13 ). 25 | "Output - 0000000000123 26 | -------------------------------------------------------------------------------- /ABAP SQL/Structure_Indicators.abap: -------------------------------------------------------------------------------- 1 | "𝗔𝗕𝗔𝗣 𝗦𝗤𝗟: 𝗜𝗻𝗱𝗶𝗰𝗮𝘁𝗼𝗿 𝗦𝘁𝗿𝘂𝗰𝘁𝘂𝗿𝗲𝘀 2 | "If you've worked with RAP, you might be familiar with the %𝗰𝗼𝗻𝘁𝗿𝗼𝗹 component group. 3 | "This structure contains all key and data fields as components, represented as flags. 4 | "It is used to determine which fields are provided to Create/Update during CREATE or UPDATE operations using EML. 5 | 6 | "A similar concept exists in ABAP SQL with 𝗦𝗤𝗟 𝗜𝗻𝗱𝗶𝗰𝗮𝘁𝗼𝗿𝘀. 7 | "These indicators are useful for partially updating a database table by setting specific fields. 8 | 9 | * Data structure with additional set indicator 10 | TYPES: ty_sflight TYPE sflight WITH INDICATORS set_ind. 11 | DATA: it_sflight TYPE STANDARD TABLE OF ty_sflight WITH DEFAULT KEY. 12 | 13 | SELECT FROM sflight 14 | FIELDS carrid, connid, fldate, price 15 | WHERE carrid = 'AA' 16 | AND connid = '0017' 17 | AND fldate = '20230929' 18 | INTO CORRESPONDING FIELDS OF TABLE @it_sflight. 19 | 20 | * Update Price 21 | LOOP AT it_sflight ASSIGNING FIELD-SYMBOL(). 22 | -price = '100'. 23 | -set_ind-price = '01'. 24 | ENDLOOP. 25 | 26 | * Only update the columns with Set-Indicator='01' 27 | UPDATE sflight FROM TABLE @it_sflight INDICATORS SET STRUCTURE set_ind. -------------------------------------------------------------------------------- /ABAP New Syntax/CL_ABAP_STRUCT_UTILITIES.abap: -------------------------------------------------------------------------------- 1 | TYPES: BEGIN OF ty_user, 2 | user_id1 TYPE buname, 3 | user_id2 TYPE buname, 4 | user_id3 TYPE buname, 5 | user_id4 TYPE buname, 6 | user_id5 TYPE buname, 7 | END OF ty_user, 8 | BEGIN OF ty_users, 9 | user_id TYPE buname, 10 | END OF ty_users, 11 | tt_users TYPE TABLE OF ty_users WITH EMPTY KEY. 12 | 13 | DATA(ls_user) = VALUE ty_user( user_id1 = 'USER1' user_id2 = 'USER2' user_id3 = '' user_id4 = 'USER4' user_id5 = 'USER5' ). 14 | ASSIGN ls_user TO FIELD-SYMBOL(). 15 | 16 | DATA(lt_users) = REDUCE tt_users( INIT _users TYPE tt_users 17 | FOR comp IN cl_abap_struct_utilities=>filled_components( ls_user ) 18 | NEXT _users = VALUE #( BASE _users ( user_id = -(comp-name) ) ) ). 19 | 20 | "Other useful methods, 21 | " 1. cl_abap_struct_utilities=>filled_components_c( ) 22 | " 2. cl_abap_struct_utilities=>filled_components_x( ) 23 | 24 | "https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENCL_ABAP_STRUCT_UTILITIES.html 25 | "https://github.com/SAP-samples/abap-cheat-sheets/blob/main/22_Released_ABAP_Classes.md#information-about-non-initial-structure-components 26 | -------------------------------------------------------------------------------- /ABAP New Syntax/return_statement.abap: -------------------------------------------------------------------------------- 1 | *In ABAP, the 𝗥𝗘𝗧𝗨𝗥𝗡 statement has been used to exit a procedure, such as a method or a function module. 2 | *Unlike many other programming languages where 𝗿𝗲𝘁𝘂𝗿𝗻 is used to pass a value back from a function, earlier versions of ABAP did not support this functionality. 3 | *However, starting with ABAP 7.58, the 𝗥𝗘𝗧𝗨𝗥𝗡 statement can now be used to return a value directly from a method. 4 | *Note: This applies only to methods that have a returning parameter. 5 | CLASS lcl_demo DEFINITION. 6 | PUBLIC SECTION. 7 | CLASS-METHODS: 8 | return RETURNING VALUE(rv_value) TYPE text100, 9 | return_with_value RETURNING VALUE(rv_value) TYPE text100, 10 | return_structure RETURNING VALUE(rs_vbak) TYPE vbak, 11 | return_table RETURNING VALUE(rt_table) TYPE tt_vbak. 12 | ENDCLASS. 13 | 14 | CLASS lcl_demo IMPLEMENTATION. 15 | METHOD return. 16 | rv_value = 'Something'. 17 | RETURN. 18 | ENDMETHOD. 19 | 20 | METHOD return_with_value. 21 | RETURN 'something'. 22 | ENDMETHOD. 23 | 24 | METHOD return_structure. 25 | RETURN VALUE #( vbeln = '1' erdat = '20231212' ). 26 | ENDMETHOD. 27 | 28 | METHOD return_table. 29 | RETURN VALUE #( ( vbeln = '1' erdat = '20231212' ) 30 | ( vbeln = '2' erdat = '20231212' ) ). 31 | ENDMETHOD. 32 | ENDCLASS. -------------------------------------------------------------------------------- /CDS/Inline_Actions_in_Object_Page_Sections.md: -------------------------------------------------------------------------------- 1 | # 𝗔𝗰𝘁𝗶𝗼𝗻𝘀/𝗜𝗻𝗹𝗶𝗻𝗲 𝗔𝗰𝘁𝗶𝗼𝗻𝘀 𝗶𝗻 𝗢𝗯𝗷𝗲𝗰𝘁 𝗣𝗮𝗴𝗲 𝗦𝗲𝗰𝘁𝗶𝗼𝗻𝘀 2 | 3 | Have you ever faced a scenario where you wanted to add RAP actions specific to a section of the Object Page,not the entire page? If yes, this is for you! 4 | 5 | You can achieve this by leveraging `@𝗨𝗜.𝗳𝗮𝗰𝗲𝘁` and `@𝗨𝗜.𝗳𝗶𝗲𝗹𝗱𝗚𝗿𝗼𝘂𝗽` annotations. It’s also possible to add inline actions using the 𝗶𝗻𝗹𝗶𝗻𝗲: 𝘁𝗿𝘂𝗲 property( available from SAP S/4HANA 2023 and in the latest public cloud versions). 6 | 7 | Use Case Example: A colleague recently had a requirement to add a section-specific action to reset certain data, placing the action inside the relevant section made the UX cleaner and more intuitive. 8 | 9 | `@UI.facet: [ {`\ 10 | `label: 'General Information',`\ 11 | `id: 'GeneralInfo',`\ 12 | `purpose: #STANDARD,`\ 13 | `position: 10 ,`\ 14 | `type: #FIELDGROUP_REFERENCE,`\ 15 | `targetQualifier: 'generalInfo'`\ 16 | `} ]` 17 | 18 | `@UI.fieldGroup: [{`\ 19 | `qualifier: 'generalInfo',`\ 20 | `type: #FOR_ACTION,`\ 21 | `position: 10,`\ 22 | `dataAction: 'formAction',`\ 23 | `inline: true,` //Action will be placed inside the section\ 24 | `label: 'Reset Data(Form Action)',`\ 25 | `emphasized: true }]`\ 26 | `element;` 27 | 28 | ![Inline_Actions_in_Object_Page_Sections ](../src/images/Inline_Actions_in_Object_Page_Sections.gif) 29 | -------------------------------------------------------------------------------- /ABAP New Syntax/step_keyword.abap: -------------------------------------------------------------------------------- 1 | "𝗦𝗧𝗘𝗣 𝗞𝗲𝘆𝘄𝗼𝗿𝗱 𝗶𝗻 𝗔𝗕𝗔𝗣 2 | "The 𝗦𝗧𝗘𝗣 keyword in ABAP simplifies working with loops when you want to skip odd or even indices. 3 | "Previously, this was achieved using 𝘀𝘆-𝘁𝗮𝗯𝗶𝘅, but with STEP, you can directly control both the step size and the loop's direction, making the process more straightforward and efficient. 4 | "Here is a small example, 5 | 6 | TYPES: tt_numbers TYPE TABLE OF int8 WITH EMPTY KEY. 7 | DATA(lt_numbers) = VALUE tt_numbers( FOR i = 1 THEN i + 1 WHILE i < 11 ( CONV #( i ) ) ). 8 | 9 | "Step with Positive number -> Forward 10 | LOOP AT lt_numbers INTO DATA(forward_num) STEP 2. 11 | WRITE:/ forward_num. 12 | ENDLOOP. 13 | DATA(lt_step_forward) = VALUE tt_numbers( FOR num in lt_numbers STEP 2 ( num ) ). 14 | "Output -> 1,3,5,7,9 15 | 16 | "Step with Negative Number -> Backword 17 | LOOP at lt_numbers INTO DATA(backword_num) STEP -2. 18 | WRITE:/ backword_num. 19 | ENDLOOP. 20 | DATA(lt_step_backward) = VALUE tt_numbers( FOR num in lt_numbers STEP -2 ( num ) ). 21 | "Output -> 10,8,6,4,2 22 | 23 | "Step with From and To 24 | LOOP AT lt_numbers INTO DATA(from_to_index) FROM 6 STEP -1. 25 | WRITE:/ from_to_index. 26 | ENDLOOP. 27 | DATA(lt_step_from_to) = VALUE tt_numbers( FOR num in lt_numbers FROM 6 STEP -1 ( num ) ). 28 | "Outpu -> 6,5,4,3,2,1 29 | 30 | "Step can be used in 31 | "LINES OF jtab [FROM idx1] [TO idx2] [STEP n] [USING KEY keyname] 32 | -------------------------------------------------------------------------------- /Fiori/Construct_FLP_URL.abap: -------------------------------------------------------------------------------- 1 | "Are you manually constructing FLP URLs? then try out this class 𝗖𝗟_𝗟𝗦𝗔𝗣𝗜_𝗠𝗔𝗡𝗔𝗚𝗘𝗥 to simplify that. 2 | "You will need it in case you want to 3 | 4 | ".. Launch Fiori apps from GUI. 5 | ".. Generate a Dynamic Fiori URL by using using Semantic Objects, Actions, and Parameters. 6 | ".. Share specific Fiori app links via email. 7 | ".. Call Transaction, etc,. 8 | 9 | 10 | DATA(lo_lsapi) = cl_lsapi_manager=>get_instance( ). 11 | 12 | "Create URL to Access Fiori Apps 13 | DATA(lv_flp_app_url) = cl_lsapi_manager=>create_flp_url( 14 | object = 'MaintenanceObject' "Fiori Intent Semantic Object Value 15 | action = 'listFunctionalLocStructure' "Fiori Intent Action Value 16 | system_alias = 'LOCAL' "SM59 Based System Alias of Fiori Front End Server 17 | parameters = VALUE #( name = 'DY_TPLNR' value = '0001' ) 18 | ). 19 | 20 | "Create URL to Access Transaction Code 21 | DATA(lv_tcode_url) = cl_lsapi_manager=>create_flp_url( 22 | system_alias = 'LOCAL' "SM59 Based System Alias of Fiori Frontend Server 23 | parameters = VALUE #( ( name = 'DY_TPLNR' value = '0001' ) ) "Parameters in hash part of URL 24 | transaction = 'IH01' "Transaction Code 25 | ). 26 | 27 | "Ways to OPEN/Navigate to URL 28 | lo_lsapi->navigate( 29 | location = lv_flp_app_url 30 | mode = lo_lsapi->gc_s_navigation_mode-inplace 31 | ). 32 | 33 | cl_lsapi_manager=>open_url( url = lv_tcode_url ). -------------------------------------------------------------------------------- /ABAP SQL/STRING_AGG_Function.abap: -------------------------------------------------------------------------------- 1 | *In ABAP, the STRING_AGG function is used to concatenate values from multiple rows into a single string, with a specified delimiter. 2 | *Here is a small example, this table have a customer id and course name, want to aggregate all course name for each customer id into a single string, separated by commas. 3 | *this can be easily achieved through STRING_AGG function. 4 | *Note: STRING_AGG concatenates the results of an SQL expression in one line (type SSTRING, length 1333). 5 | *If the string is longer than 1333 characters, an exception (CX_SY_OPEN_SQL_DB) is thrown. 6 | *The limitation to 1333 characters can be bypassed by the function TO_CLOB. This is available in ABAP SQL from ABAP 7.54+. 7 | 8 | TYPES: BEGIN OF ty_employee, 9 | employee_id TYPE pernr_d, 10 | course_name TYPE text100, 11 | END OF ty_employee, 12 | tt_employee TYPE TABLE OF ty_employee WITH EMPTY KEY. 13 | 14 | DATA(lt_employees) = VALUE tt_employee( 15 | ( employee_id = '1' course_name = 'ABAP' ) 16 | ( employee_id = '1' course_name = 'UI5' ) 17 | ( employee_id = '1' course_name = 'Fiori' ) 18 | ( employee_id = '2' course_name = 'ABAP' ) 19 | ( employee_id = '2' course_name = 'UI5' ) ). 20 | 21 | SELECT FROM @lt_employees AS employees 22 | FIELDS employee_id, 23 | to_clob( STRING_AGG( course_name, ',' ) ) AS courses 24 | GROUP BY employee_id 25 | INTO TABLE @DATA(lt_emp_courses). 26 | 27 | "Output 28 | *EMPLOYEE_ID COURSES 29 | *00000001 ABAP, UI5, Fiori 30 | *00000002 ABAP, UI5 -------------------------------------------------------------------------------- /CDS/CDS_System_Generate_Series.abap: -------------------------------------------------------------------------------- 1 | "Here are some useful standard CDS system entities for 𝗴𝗲𝗻𝗲𝗿𝗮𝘁𝗶𝗻𝗴 𝘀𝗲𝗿𝗶𝗲𝘀, which can be quite handy in various scenarios: 2 | 3 | "1.SERIES_GENERATE_DATE -> Generate Dates 4 | SELECT * FROM series_generate_date( step = 1, 5 | from_value = '20250101', 6 | to_value = '20250130' ) 7 | ORDER BY element_number 8 | INTO TABLE @DATA(date_series_gen). 9 | 10 | "2.SERIES_GENERATE_INTEGER - Generate Integer 11 | SELECT * FROM series_generate_integer( step = 1, 12 | from_value = 1, 13 | to_value = 100 ) 14 | ORDER BY element_number 15 | INTO TABLE @DATA(integer_series_gen). 16 | 17 | "3. SERIES_GENERATE_TIME - Generate Time 18 | DATA(time) = cl_demo_date_time=>get_user_time( ). 19 | DATA(seconds_added) = time + 20. 20 | 21 | SELECT * FROM series_generate_time( step = 2, 22 | from_value = @time, 23 | to_value = @seconds_added ) 24 | ORDER BY element_number 25 | INTO TABLE @DATA(time_series_gen). 26 | 27 | "4.SERIES_GENERATE_TIMESTAMP - Generate Timestamp 28 | DATA(ts_from) = utclong_current( ). 29 | DATA(ts_to) = utclong_add( val = ts_from seconds = 10 ). 30 | 31 | SELECT * FROM series_generate_timestamp( step = 2, 32 | from_value = @ts_from, 33 | to_value = @ts_to ) 34 | ORDER BY element_number 35 | INTO TABLE @DATA(timestamp_series_gen). 36 | 37 | -------------------------------------------------------------------------------- /ABAP SQL/COALESCE_Function.abap: -------------------------------------------------------------------------------- 1 | *The COALESCE function takes a list of at least two (and up to 255) arguments (arg1, arg2, ..., argn). 2 | *It returns the first non-null value from the list, or the last argument if all are null. 3 | 4 | DATA(lt_salesorders) = VALUE tt_salesorder( 5 | ( salesorder = '1' netvalue = '100.00' customer = 'CUST_1' ) 6 | ( salesorder = '2' netvalue = '100.00' customer = 'CUST_2' ) 7 | ( salesorder = '3' netvalue = '100.00' customer = 'CUST_3' ) 8 | ). 9 | 10 | DATA(lt_customer_one) = VALUE tt_customer( 11 | ( customer = 'CUST_1' customername = 'Customer 1' addressid = 1 ) 12 | ). 13 | 14 | DATA(lt_customer_two) = VALUE tt_customer( 15 | ( customer = 'CUST_2' customername = 'Customer 2' addressid = 2 ) 16 | ). 17 | 18 | DATA(lt_customer_address) = VALUE tt_customer_address( 19 | ( addressid = 1 address = 'Sitheri, Cuddalore' ) 20 | ( addressid = 2 address = 'Velluvadi, Perambalur' ) 21 | ). 22 | 23 | SELECT FROM @lt_salesorders AS a 24 | LEFT OUTER JOIN @lt_customer_one AS b ON b~customer = a~customer 25 | LEFT OUTER JOIN @lt_customer_two AS c ON c~customer = a~customer 26 | LEFT OUTER JOIN @lt_customer_address AS d ON d~addressid = COALESCE( b~addressid, c~addressid ) 27 | FIELDS a~salesorder, 28 | a~netvalue, 29 | a~customer, 30 | COALESCE( b~customername, c~customername ) AS customername, 31 | d~address AS customeraddress 32 | INTO TABLE @DATA(lt_salesorders_with_customer). 33 | 34 | "Output 35 | *SALESORDER NETVALUE CUSTOMER CUSTOMERNAME CUSTOMERADDRESS 36 | *1 100.0 CUST_1 Customer 1 Sitheri, Cuddalore 37 | *2 100.0 CUST_2 Customer 2 Velluvadi, Perambalur 38 | *3 100.0 CUST_3 -------------------------------------------------------------------------------- /ABAP New Syntax/string_templates.abap: -------------------------------------------------------------------------------- 1 | "String Templates 2 | "ALPHA(IN/OUT) 3 | DATA(lv_vbeln) = CONV vbeln( '1' ). 4 | lv_vbeln = |{ lv_vbeln ALPHA = IN }|. "-> 0000000001 5 | lv_vbeln = |{ lv_vbeln ALPHA = OUT }|. "-> 1 6 | 7 | "WIDTH 8 | DATA(lv_vbeln_with_extra_zeros) = |{ lv_vbeln ALPHA = IN WIDTH = 15 }|. "->000000000000001 9 | 10 | "CURRENCY 11 | DATA(lv_amount) = 123456. 12 | DATA(lv_inr) = |{ lv_amount CURRENCY = 'INR' }|. "1234.56 13 | DATA(lv_omr) = |{ lv_amount CURRENCY = 'OMR' }|. "123.456 14 | 15 | "NUMBER 16 | DATA(lv_number) = 12345678. 17 | DATA(lv_user_specific) = |{ lv_number NUMBER = USER }|. "12.345.678 18 | SET COUNTRY 'US'. 19 | DATA(lv_env) = |{ lv_number NUMBER = ENVIRONMENT }|. "12,345,678 20 | 21 | "DATE -> Same we have for TIME,TIMESTAMP 22 | DATA(lv_date) = sy-datum. 23 | DATA(lv_user_date) = |{ lv_date DATE = USER }|. "20.01.2025 24 | DATA(lv_iso_date) = |{ lv_date DATE = ISO }|. "2025-01-20 25 | 26 | "DECIMAL 27 | DATA(lv_decimal) = CONV f( `1234.456877` ). 28 | DATA(lv_3_decimal) = |{ lv_decimal DECIMALS = 3 }|. "1234.457 29 | 30 | "CASE 31 | DATA(lv_name) = `Bharathi S`. 32 | DATA(lv_uppercase) = |{ lv_name CASE = UPPER }|. "BHARATHI S" 33 | DATA(lv_lowercase) = |{ lv_name CASE = LOWER }|. "bharathi s" 34 | 35 | "SIGN 36 | DATA(lv_sign) = 123. 37 | DATA(lv_plus_sign) = |{ lv_sign SIGN = LEFTPLUS }|. "+123 38 | DATA(lv_right_plus_sign) = |{ lv_sign SIGN = RIGHTPLUS }|. "123+ 39 | 40 | "ALIGN 41 | DATA(lv_text) = '1'. 42 | DATA(lv_align_right) = |{ lv_text ALIGN = RIGHT WIDTH = 5 }|." 1 43 | 44 | "PAD 45 | DATA(lv_pad) = |{ lv_text ALIGN = RIGHT WIDTH = 5 PAD = '_' }|."____1 46 | 47 | "https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcompute_string_format_options.htm 48 | -------------------------------------------------------------------------------- /ABAP New Syntax/Corresponding_with_lookup_table.abap: -------------------------------------------------------------------------------- 1 | "𝗖𝗢𝗥𝗥𝗘𝗦𝗣𝗢𝗡𝗗𝗜𝗡𝗚 𝘄𝗶𝘁𝗵 𝗹𝗼𝗼𝗸𝘂𝗽 𝘁𝗮𝗯𝗹𝗲. 2 | "The CORRESPONDING operator can be used to create a new data object from a structured data object, such as an internal table or structure, by copying the values of fields with matching names. 3 | "Additionally, the operator can perform a lookup on another internal table to populate specific field values. 4 | 5 | TYPES: BEGIN OF ty_employee, 6 | emp_id TYPE pernr_d, 7 | emp_name TYPE text100, 8 | manager_id TYPE pernr_d, 9 | manager_name TYPE text100, 10 | emp_position TYPE text100, 11 | END OF ty_employee, 12 | tt_employee TYPE TABLE OF ty_employee WITH EMPTY KEY, 13 | BEGIN OF ty_manager, 14 | mgr_id TYPE pernr_d, 15 | mgr_name TYPE text100, 16 | END OF ty_manager. 17 | 18 | DATA lt_managers TYPE HASHED TABLE OF ty_manager WITH UNIQUE KEY mgr_id. 19 | DATA lt_employees TYPE tt_employee. 20 | DATA lt_emp_with_mgr_name TYPE tt_employee. 21 | 22 | "Employee data w/o manager name 23 | lt_employees = VALUE #( 24 | ( emp_id = '1' emp_name = 'Name 1' emp_position = 'DEV_1' manager_id = '1' ) 25 | ( emp_id = '2' emp_name = 'Name 2' emp_position = 'DEV_2' manager_id = '2' ) ). 26 | 27 | "Manager data - Lookup Table 28 | lt_managers = VALUE #( 29 | ( mgr_id = '1' mgr_name = 'Manager 1' ) 30 | ( mgr_id = '2' mgr_name = 'Manager 2' ) ). 31 | 32 | "Employee data with manager name from lookup table 33 | lt_emp_with_mgr_name = CORRESPONDING #( lt_employees 34 | FROM lt_managers USING manager_id 35 | MAPPING manager_name = mgr_name ). 36 | 37 | "Output 38 | "EMP_ID EMP_NAME MANAGER_ID MANAGER_NAME EMP_POSITION 39 | "00000001 Name 1 00000001 Manager 1 DEV_1 40 | "00000002 Name 2 00000002 Manager 2 DEV_2 -------------------------------------------------------------------------------- /ABAP RAP/static_default _factory_action.abap: -------------------------------------------------------------------------------- 1 | "Step 1 – Define static default factory action in R_* BDEF 2 | define behavior for ZR_ROOT alias ROOT 3 | { 4 | create; 5 | update; 6 | delete; 7 | 8 | static default factory action createCustomer parameter ZD_CustomerData [1]; 9 | } 10 | "Here, createCustomer will be triggered instead of the standard create. 11 | 12 | "Step 2 – Create abstract entity for action parameters 13 | @EndUserText.label: 'Customer Data' 14 | define abstract entity ZD_CustomerData 15 | { 16 | @EndUserText.label: 'Customer ID' 17 | CustomerId : int4; 18 | 19 | @EndUserText.label: 'First Name' 20 | FirstName : abap.char(20); 21 | 22 | @EndUserText.label: 'Last Name' 23 | LastName : abap.char(20); 24 | } 25 | "This entity defines the parameters passed to the static action. 26 | 27 | "Step 3 – Implement custom logic in the action handler 28 | METHOD createCustomer. 29 | CHECK keys IS NOT INITIAL. 30 | 31 | MODIFY ENTITIES OF ZR_Root IN LOCAL MODE 32 | ENTITY Root 33 | CREATE FIELDS ( id Fname Lname Age ) 34 | WITH VALUE #( 35 | FOR key IN keys ( 36 | %cid = key-%cid 37 | %is_draft = key-%param-%is_draft 38 | Id = key-%param-CustomerId 39 | Fname = key-%param-FirstName 40 | Lname = key-%param-LastName 41 | Age = 25 42 | ) 43 | ) 44 | MAPPED mapped 45 | FAILED failed 46 | REPORTED reported. 47 | ENDMETHOD. 48 | "Here, the incoming parameters are mapped to the entity fields before creation. 49 | 50 | "Step 4 – Expose the action in ZC_* (projection) BDEF 51 | define behavior for ZC_Root alias Root 52 | { 53 | use create; 54 | use update; 55 | use delete; 56 | 57 | use action createCustomer; 58 | } 59 | "This makes the action available in the projection layer. 60 | 61 | "Result 62 | "When the Create button is clicked in the SAP Fiori Elements UI: 63 | "The createCustomer static default factory action is triggered automatically. 64 | "Custom parameter handling and default value logic are executed before entity creation. 65 | "The standard create operation is bypassed (even if enabled). 66 | -------------------------------------------------------------------------------- /CDS/Grouping_Actions_as_Menu_Button_using_Annotations.md: -------------------------------------------------------------------------------- 1 | # Grouping Actions as Menu Button using Annotations 2 | 3 | While exploring, one annotation caught my eye: `#𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡_𝗚𝗥𝗢𝗨𝗣`. I looked into it further and found that it allows you to group multiple actions under a single menu! This is particularly helpful when you want to group actions either on the List Report or the Object Page. 4 | 5 | For example, here I’ve grouped two actions (acceptTravel and rejectTravel) under a single menu labeled "Change Status":\ 6 | 7 | `@𝗨𝗜: {`\ 8 | `𝗹𝗶𝗻𝗲𝗜𝘁𝗲𝗺: [`\ 9 | `{ 𝗽𝗼𝘀𝗶𝘁𝗶𝗼𝗻: 𝟭𝟬, 𝗶𝗺𝗽𝗼𝗿𝘁𝗮𝗻𝗰𝗲: #𝗛𝗜𝗚𝗛 },`\ 10 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡_𝗚𝗥𝗢𝗨𝗣, 𝗹𝗮𝗯𝗲𝗹: '𝗖𝗵𝗮𝗻𝗴𝗲 𝗦𝘁𝗮𝘁𝘂𝘀', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: ``'𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' },`\ 11 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡, 𝗱𝗮𝘁𝗮𝗔𝗰𝘁𝗶𝗼𝗻: '𝗮𝗰𝗰𝗲𝗽𝘁𝗧𝗿𝗮𝘃𝗲𝗹', 𝗹𝗮𝗯𝗲𝗹: '𝗔𝗰𝗰𝗲𝗽𝘁 ``𝗧𝗿𝗮𝘃𝗲𝗹', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: '𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' },`\ 12 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡, 𝗱𝗮𝘁𝗮𝗔𝗰𝘁𝗶𝗼𝗻: '𝗿𝗲𝗷𝗲𝗰𝘁𝗧𝗿𝗮𝘃𝗲𝗹', 𝗹𝗮𝗯𝗲𝗹: '𝗥𝗲𝗷𝗲𝗰𝘁 ``𝗧𝗿𝗮𝘃𝗲𝗹', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: '𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' }`\ 13 | `],`\ 14 | `𝗶𝗱𝗲𝗻𝘁𝗶𝗳𝗶𝗰𝗮𝘁𝗶𝗼𝗻: [`\ 15 | `{ 𝗽𝗼𝘀𝗶𝘁𝗶𝗼𝗻: 𝟭𝟬, 𝗹𝗮𝗯𝗲𝗹: '𝗧𝗿𝗮𝘃𝗲𝗹 𝗜𝗗' },`\ 16 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡_𝗚𝗥𝗢𝗨𝗣, 𝗹𝗮𝗯𝗲𝗹: '𝗖𝗵𝗮𝗻𝗴𝗲 𝗦𝘁𝗮𝘁𝘂𝘀', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: ``'𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' },`\ 17 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡, 𝗱𝗮𝘁𝗮𝗔𝗰𝘁𝗶𝗼𝗻: '𝗮𝗰𝗰𝗲𝗽𝘁𝗧𝗿𝗮𝘃𝗲𝗹', 𝗹𝗮𝗯𝗲𝗹: '𝗔𝗰𝗰𝗲𝗽𝘁 ``𝗧𝗿𝗮𝘃𝗲𝗹', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: '𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' },`\ 18 | `{ 𝘁𝘆𝗽𝗲: #𝗙𝗢𝗥_𝗔𝗖𝗧𝗜𝗢𝗡, 𝗱𝗮𝘁𝗮𝗔𝗰𝘁𝗶𝗼𝗻: '𝗿𝗲𝗷𝗲𝗰𝘁𝗧𝗿𝗮𝘃𝗲𝗹', 𝗹𝗮𝗯𝗲𝗹: '𝗥𝗲𝗷𝗲𝗰𝘁 ``𝗧𝗿𝗮𝘃𝗲𝗹', 𝗮𝗰𝘁𝗶𝗼𝗻𝗚𝗿𝗼𝘂𝗽𝗜𝗱: '𝗺𝗲𝗻𝘂-𝗖𝗵𝗮𝗻𝗴𝗲𝗦𝘁𝗮𝘁𝘂𝘀' }`\ 19 | `]`\ 20 | `}` 21 | 22 | Note: I tried this in SAP BTP, ABAP Environment, and it works great! I believe this should also be available in SAP S/4HANA Public Cloud Latest version. For Private Cloud availability, I’ll check and share more once I have the details. 23 | 24 | ![Grouping_Actions_as_Menu_Button_using_Annotations ](../src/images/Grouping_Actions_as_Menu_Button_using_Annotations.mp4) -------------------------------------------------------------------------------- /ABAP RAP/Show Fields in the Create Popup as Optional in RAP.abap: -------------------------------------------------------------------------------- 1 | "Show Fields in the Create Popup as Optional in RAP 2 | "Step 1 : Add temporary fields to show in the create popup. These will later be copied to the actual fields. 3 | define root view entity ZR_ROOT_ENTITY as select from zcustomer { 4 | key id as Id, 5 | fname as Fname, 6 | lname as Lname, 7 | 8 | @EndUserText.label: 'First Name' 9 | $projection.Fname as Fname_D, 10 | 11 | @EndUserText.label: 'Last Name' 12 | $projection.Lname as Lname_D 13 | } 14 | 15 | "Step 2: If you have a projection (C_ view), include the temporary fields but hide them from filters and line items. 16 | define root view entity ZC_ROOT_ENTITY 17 | provider contract transactional_query 18 | as projection on ZR_ROOT_ENTITY { 19 | key Id, 20 | Fname, 21 | Lname, 22 | 23 | @Consumption.filter.hidden: true 24 | @UI.lineItem: [{ hidden: true }] 25 | Fname_D, 26 | 27 | @Consumption.filter.hidden: true 28 | @UI.lineItem: [{ hidden: true }] 29 | Lname_D 30 | } 31 | 32 | "Step 3: Mark the temporary fields as read-only on update. Use a determination to copy their values to the actual fields on create. 33 | define behavior for ZR_ROOT_ENTITY 34 | ... 35 | { 36 | field ( mandatory : create ) Id; 37 | 38 | field ( readonly : update ) Fname_D, Lname_D; 39 | 40 | determination setNames on modify { create; } 41 | } 42 | 43 | "Step 4: Copy temporary field values (Fname_D, Lname_D) to actual fields (Fname, Lname) during creation. 44 | METHOD setNames. 45 | READ ENTITIES OF ZR_ROOT_ENTITY IN LOCAL MODE 46 | ENTITY ZR_ROOT_ENTITY 47 | FIELDS ( Fname_D Lname_D ) 48 | WITH CORRESPONDING #( keys ) 49 | RESULT DATA(lt_result). 50 | 51 | lt_update = VALUE #( FOR lw IN lt_result ( 52 | %tky = lw-%tky 53 | Fname = lw-Fname_D 54 | Lname = lw-Lname_D 55 | %control = VALUE #( Fname = if_abap_behv=>mk-on 56 | Lname = if_abap_behv=>mk-on ) 57 | )). 58 | 59 | MODIFY ENTITIES OF ZR_ROOT_ENTITY IN LOCAL MODE 60 | ENTITY ZR_ROOT_ENTITY 61 | UPDATE FROM lt_update 62 | REPORTED DATA(ls_reported) 63 | FAILED DATA(ls_failed). 64 | ENDMETHOD. 65 | 66 | "Step 5: Result On create, popup shows 3 fields: Id (required), Fname_D, and Lname_D (optional). 67 | "After creation, actual fields Fname and Lname are filled and can be edited on the object page. 68 | -------------------------------------------------------------------------------- /ABAP New Syntax/Group_Internal_Table_Data.abap: -------------------------------------------------------------------------------- 1 | *To group internal table data and process it based on specific fields, older statements like AT NEW and AT END OF within loops were commonly used. 2 | *However, these statements are now obsolete. 3 | *But now, the new ABAP Syntax 𝗟𝗢𝗢𝗣 𝗔𝗧 𝗚𝗥𝗢𝗨𝗣 or 𝗙𝗢𝗥 𝗚𝗥𝗢𝗨𝗣𝗦 𝗢𝗙 used to achieve the same functionality. 4 | 5 | DATA(lt_courses) = VALUE tt_course ( 6 | ( employee_id = '1' course_id = '1' course_name = 'ABAP' amount = '1000' ) 7 | ( employee_id = '1' course_id = '2' course_name = 'UI5' amount = '2000' ) 8 | ( employee_id = '1' course_id = '3' course_name = 'Fiori' amount = '3000' ) 9 | ( employee_id = '2' course_id = '1' course_name = 'ABAP' amount = '1000' ) 10 | ( employee_id = '2' course_id = '2' course_name = 'UI5' amount = '2000' ) 11 | ( employee_id = '2' course_id = '3' course_name = 'Fiori' amount = '3000' ) 12 | ( employee_id = '3' course_id = '1' course_name = 'ABAP' amount = '1000' ) 13 | ). 14 | 15 | "Loop At Group and For in Group 16 | DATA(lt_employee_w_loop) = VALUE tt_employee( ). 17 | 18 | LOOP AT lt_courses INTO DATA(wa) 19 | GROUP BY ( employee_id = wa-employee_id 20 | size = GROUP SIZE 21 | index = GROUP INDEX ) 22 | ASSIGNING FIELD-SYMBOL(). 23 | 24 | DATA(ls_employee) = VALUE ty_employee( 25 | employee_id = -employee_id 26 | no_of_courses = -size 27 | total_amount = 0 ). 28 | 29 | "Option 1 30 | LOOP AT GROUP ASSIGNING FIELD-SYMBOL(). 31 | ls_employee-total_amount += -amount. 32 | ENDLOOP. 33 | 34 | "Option 2 35 | ls_employee-total_amount = REDUCE #( 36 | INIT amount = 0 37 | FOR IN GROUP 38 | NEXT amount = amount + -amount 39 | ). 40 | 41 | APPEND ls_employee TO lt_employee_w_loop. 42 | ENDLOOP. 43 | 44 | "For in Group 45 | DATA(lt_employee_w_for) = VALUE tt_employee( 46 | FOR GROUPS course OF wa IN lt_courses 47 | GROUP BY ( employee_id = wa-employee_id 48 | size = GROUP SIZE 49 | index = GROUP INDEX ) 50 | ( employee_id = course-employee_id 51 | no_of_courses = course-size 52 | total_amount = REDUCE #( 53 | INIT amount = 0 54 | FOR member IN GROUP course 55 | NEXT amount = amount + member-amount 56 | ) 57 | ) 58 | ). 59 | 60 | "Output 61 | "EMPLOYEE_ID NO_OF_COURSES TOTAL_AMOUNT 62 | "00000001 3 6000 63 | "00000002 3 6000 64 | "00000003 1 1000 -------------------------------------------------------------------------------- /ABAP RAP/Hide_Fields_Based_on_Other_Field_Value_Immediately.abap: -------------------------------------------------------------------------------- 1 | *Use Case: Dynamically Hide Fields Based on EmployeeType Immediately Upon Change* 2 | 3 | "Step 1: Add a Derived Field in the Root Entity ZR_SB_EMP_DATA 4 | 5 | define root view entity ZR_SB_EMP_DATA 6 | as select from zsb_emp_data as EmployeeData 7 | { 8 | ..., 9 | EmployeeType, 10 | case EmployeeType 11 | when 'FT' then cast( 'X' as abap_boolean preserving type ) 12 | else cast( '' as abap_boolean preserving type ) 13 | end as IsFullTimeEmployee 14 | } 15 | 16 | "This derived field IsFullTimeEmployee is used to control visibility logic based on EmployeeType. 17 | 18 | "Step 2: Expose the Field in Your Projection View 19 | 20 | define root view entity ZC_SB_EMP_DATA 21 | provider contract transactional_query 22 | as projection on ZR_SB_EMP_DATA 23 | { 24 | ..., 25 | EmployeeType, 26 | IsFullTimeEmployee 27 | } 28 | 29 | "Step 3: Apply the Visibility Annotation to Your Target Field. Use the @UI.hidden annotation to conditionally hide the field (e.g., MobileNumber) based on IsFullTimeEmployee. 30 | 31 | annotate view ZC_SB_EMP_DATA with 32 | { 33 | ..., 34 | @UI.hidden: #( IsFullTimeEmployee ) 35 | MobileNumber; 36 | } 37 | 38 | "Step 4: Add a Determination in the Root BDEF to Recalculate the Boolean Field on Change, Also declare a side effect to notify the UI of the dependent field update. 39 | 40 | define behavior for ZR_SB_EMP_DATA alias EmployeeData 41 | ... 42 | { 43 | ... 44 | determination setVisibility on modify { field EmployeeType; } 45 | side effects { field EmployeeType affects field IsFullTimeEmployee; } 46 | } 47 | 48 | "Step 5: Implement the Determination Logic to Update IsFullTimeEmployee immediately when EmployeeType changes. 49 | 50 | METHOD setVisibility. 51 | DATA: lt_update TYPE TABLE FOR UPDATE zr_sb_emp_data. 52 | 53 | READ ENTITIES OF zr_sb_emp_data IN LOCAL MODE 54 | ENTITY EmployeeData 55 | FIELDS ( EmployeeType ) 56 | WITH CORRESPONDING #( keys ) 57 | RESULT DATA(lt_employee_data). 58 | 59 | lt_update = VALUE #( FOR ls_employee IN lt_employee_data ( 60 | %tky = ls_employee-%tky 61 | IsFullTimeEmployee = xsdbool( ls_employee-EmployeeType = 'FT' ) 62 | %control = VALUE #( IsFullTimeEmployee = if_abap_behv=>mk-on ) ) ). 63 | 64 | MODIFY ENTITIES OF zr_sb_emp_data IN LOCAL MODE 65 | ENTITY EmployeeData 66 | UPDATE FROM lt_update 67 | REPORTED DATA(lt_reported). 68 | 69 | reported = CORRESPONDING #( DEEP lt_reported ). 70 | ENDMETHOD. 71 | 72 | "Step 6: Enable Side Effects in the Projection BDEF 73 | 74 | use side effects; 75 | define behavior for ZC_SB_EMP_DATA alias EmployeeData 76 | { 77 | ... 78 | } 79 | 80 | "Step 7: That’s it! Now, the field (e.g., MobileNumber) will be shown or hidden immediately based on the selected EmployeeType value without requiring a page reload. 81 | "PT - Part Time Employee 82 | "FT - Full Time Employee 83 | -------------------------------------------------------------------------------- /JSON/JSON_Conversion_in_ABAP.abap: -------------------------------------------------------------------------------- 1 | TYPES: BEGIN OF ty_emp_type, 2 | employeeid TYPE c LENGTH 3, 3 | employeename TYPE c LENGTH 20, 4 | employeeage TYPE c LENGTH 3, 5 | employeemobilenumber TYPE c LENGTH 10, 6 | END OF ty_emp_type, 7 | tt_emp_tab_type TYPE TABLE OF ty_emp_type WITH EMPTY KEY. 8 | 9 | DATA(emp_tab) = VALUE #( 10 | ( employeeid = '1' employeename = 'Bharathi S' employeeage = '24' employeemobilenumber = '1234567890' ) 11 | ( employeeid = '2' employeename = 'Siva S' employeeage = '24' employeemobilenumber = '1234567890' ) 12 | ( employeeid = '3' employeename = 'Sasi S' employeeage = '24' employeemobilenumber = '1234567890' ) ). 13 | 14 | * Table to JSON 15 | DATA(lv_emp_table_to_json) = /ui2/cl_json=>serialize( 16 | data = emp_tab 17 | format_output = abap_true 18 | pretty_name = /ui2/cl_json=>pretty_mode-camel_case ). "none,low_case,camel_case,extended, user, user_low_case 19 | 20 | * JSON to table (with different column names) 21 | TYPES: BEGIN OF ty_emp_type_map, 22 | empid TYPE c LENGTH 3, 23 | empname TYPE c LENGTH 20, 24 | empage TYPE c LENGTH 3, 25 | empmobnumber TYPE c LENGTH 10, 26 | END OF ty_emp_type_map, 27 | tt_emp_tab_type_map TYPE TABLE OF ty_emp_type_map WITH EMPTY KEY. 28 | 29 | DATA(lt_emp_data_from_json_map) = VALUE tt_emp_tab_type_map( ). 30 | /ui2/cl_json=>deserialize( 31 | EXPORTING 32 | json = lv_emp_table_to_json 33 | name_mappings = VALUE #( ( abap = 'EMPID' json = 'EMPLOYEEID' ) 34 | ( abap = 'EMPNAME' json = 'EMPLOYEENAME' ) 35 | ( abap = 'EMPAGE' json = 'EMPLOYEEAGE' ) 36 | ( abap = 'EMPMOBNUMBER' json = 'EMPLOYEEMOBILENUMBER' ) ) 37 | CHANGING 38 | data = lt_emp_data_from_json_map ). 39 | 40 | * JSON to table 41 | DATA(lt_emp_data_from_json) = VALUE tt_emp_tab_type( ). 42 | /ui2/cl_json=>deserialize( 43 | EXPORTING 44 | json = lv_emp_table_to_json 45 | CHANGING 46 | data = lt_emp_data_from_json 47 | ). 48 | 49 | * Conversion Exists 50 | TYPES: BEGIN OF ty_customer_data, 51 | customerId TYPE kunnr, 52 | language TYPE spras, 53 | END OF ty_customer_data. 54 | DATA(ls_sales_data) = VALUE ty_customer_data( language = 'E' customerid = '1' ). 55 | DATA(lv_json_Sales_data) = /ui2/cl_json=>serialize( 56 | data = ls_sales_data 57 | conversion_exits = abap_true ). 58 | "E -> Will be changed into EN 59 | 60 | * Unknown type 61 | DATA(lv_unknown_json) = `[ { "EmployeeId":"1", "EmployeeName":"Saranya S" },` && 62 | `{ "EmployeeId":"2", "EmployeeName":"Saran S" }]`. 63 | DATA(lr_emp_data) = /ui2/cl_json=>generate( json = lv_unknown_json ). 64 | " This can be accessed by lr_emp_data->* 65 | -------------------------------------------------------------------------------- /File Handling/Read_Excel_data_using_XCO_Libaray.abap: -------------------------------------------------------------------------------- 1 | DATA: lv_rc TYPE i. 2 | DATA: lt_files TYPE filetable. 3 | DATA: lv_action TYPE i. 4 | DATA: lt_bin_data TYPE w3mimetabtype. 5 | 6 | PARAMETERS: p_file TYPE ibipparms-path OBLIGATORY. 7 | 8 | AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file. 9 | cl_gui_frontend_services=>file_open_dialog( EXPORTING file_filter = |xlsx (*.xlsx)\|*.xlsx\|{ cl_gui_frontend_services=>filetype_all }| 10 | CHANGING file_table = lt_files 11 | rc = lv_rc 12 | user_action = lv_action ). 13 | 14 | p_file = |{ lt_files[ 1 ]-filename }|. 15 | START-OF-SELECTION. 16 | * Excel upload 17 | cl_gui_frontend_services=>gui_upload( EXPORTING filename = CONV #( p_file ) 18 | filetype = 'BIN' 19 | IMPORTING filelength = DATA(lv_filesize) 20 | CHANGING data_tab = lt_bin_data ). 21 | 22 | * Convert Binary Data to XSTRING - We can use CL_BCS_CONVERT to convert the binary data to XSTRING 23 | DATA(lv_excel_data) = cl_bcs_convert=>solix_to_xstring( it_solix = lt_bin_data ). 24 | 25 | * Get the read access to the Excel file using XCO Library 26 | DATA(lo_xl) = xco_cp_xlsx=>document->for_file_content( lv_excel_data )->read_access( ). 27 | 28 | * Read the Excel file 29 | *-> Reading the first sheet 30 | DATA(lo_sheet_by_position) = lo_xl->get_workbook( )->worksheet->at_position( 1 ). 31 | *-> Reading using Sheet name 32 | DATA(lo_sheet_by_name) = lo_xl->get_workbook( )->worksheet->for_name( 'Employees' ). 33 | 34 | IF NOT lo_sheet_by_position->exists( ). 35 | RETURN. "Sheet does not exist 36 | ENDIF. 37 | 38 | * Read all data from the sheet 39 | DATA(lo_sel_pattern_all) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->get_pattern( ). 40 | 41 | * Read data from specific rows and columns 42 | *-> From column(A) to column(C) 43 | DATA(lo_sel_pattern_col) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( 44 | )->from_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'A' ) 45 | )->to_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'C' ) 46 | )->get_pattern( ). 47 | *-> From row(2) to row(5) 48 | DATA(lo_sel_pattern_row) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( 49 | )->from_row( xco_cp_xlsx=>coordinate->for_numeric_value( 2 ) 50 | )->to_row( xco_cp_xlsx=>coordinate->for_numeric_value( 5 ) 51 | )->get_pattern( ). 52 | *-> Both Row and Column 53 | DATA(lo_sel_pattern_both) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( 54 | )->from_row( xco_cp_xlsx=>coordinate->for_numeric_value( 2 ) 55 | )->to_row( xco_cp_xlsx=>coordinate->for_numeric_value( 5 ) 56 | )->from_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'A' ) 57 | )->to_column( xco_cp_xlsx=>coordinate->for_alphabetic_value( 'C' ) 58 | )->get_pattern( ). 59 | 60 | TYPES: BEGIN OF ty_employee, 61 | employee_id TYPE string, 62 | employee_name TYPE string, 63 | mobile_number TYPE string, 64 | date_of_birth TYPE string, 65 | END OF ty_employee. 66 | DATA: lt_employees TYPE TABLE OF ty_employee WITH EMPTY KEY. 67 | 68 | * Fill the internal table by using the selection patterns 69 | DATA(o_result) = lo_sheet_by_position->select( lo_sel_pattern_all " lo_sel_pattern_col, lo_sel_pattern_row, (lo_sel_pattern_both 70 | )->row_stream( 71 | )->operation->write_to( REF #( lt_employees ) 72 | )->set_value_transformation( xco_cp_xlsx_read_access=>value_transformation->string_value 73 | )->execute( ). 74 | -------------------------------------------------------------------------------- /ABAP RAP/Display Message Strip by Default in Object Page.abap: -------------------------------------------------------------------------------- 1 | "Display Message Strip by Default in Object Page using Instance Features 2 | "Step 1 – Add actions in Metadata Extensions 3 | annotate view YR_TRAVELTP with 4 | { 5 | @UI.identification: [ 6 | { type: #FOR_ACTION, label: 'Accept', dataAction: 'AcceptTravel', position: 10 }, 7 | { type: #FOR_ACTION, label: 'Reject', dataAction: 'RejectTravel', position: 20 } 8 | ] 9 | .... 10 | } 11 | 12 | 13 | "Step 2 – Update the Behavior Definition (BDEF) 14 | define behavior for YR_TRAVELTP alias Travel 15 | ..... 16 | { 17 | ..... 18 | update ( features : instance ); 19 | field ( features : instance ) OverallStatus; 20 | draft action ( features : instance ) Edit; 21 | 22 | action ( features : instance ) AcceptTravel result [1] $self; 23 | action ( features : instance ) RejectTravel result [1] $self; 24 | .... 25 | } 26 | 27 | 28 | "Step 3 – Implement Logic in the Behavior Implementation (BIL) 29 | METHOD AcceptTravel. 30 | MODIFY ENTITIES OF YR_TRAVELTP IN LOCAL MODE 31 | ENTITY Travel 32 | UPDATE FIELDS ( OverallStatus ) 33 | WITH VALUE #( FOR key IN keys ( %tky = key-%tky OverallStatus = 'A' ) ). 34 | 35 | READ ENTITIES OF YR_TRAVELTP IN LOCAL MODE 36 | ENTITY Travel 37 | ALL FIELDS 38 | WITH CORRESPONDING #( keys ) 39 | RESULT DATA(travels). 40 | 41 | result = VALUE #( FOR travel IN travels ( %tky = travel-%tky %param = travel ) ). 42 | ENDMETHOD. 43 | 44 | METHOD RejectTravel. 45 | MODIFY ENTITIES OF YR_TRAVELTP IN LOCAL MODE 46 | ENTITY Travel 47 | UPDATE FIELDS ( OverallStatus ) 48 | WITH VALUE #( FOR key IN keys ( %tky = key-%tky OverallStatus = 'X' ) ). 49 | 50 | READ ENTITIES OF YR_TRAVELTP IN LOCAL MODE 51 | ENTITY Travel 52 | ALL FIELDS 53 | WITH CORRESPONDING #( keys ) 54 | RESULT DATA(travels). 55 | 56 | result = VALUE #( FOR travel IN travels ( %tky = travel-%tky %param = travel ) ). 57 | ENDMETHOD. 58 | 59 | METHOD get_instance_features. 60 | READ ENTITIES OF YR_TRAVELTP IN LOCAL MODE 61 | ENTITY Travel 62 | ALL FIELDS 63 | WITH CORRESPONDING #( keys ) 64 | RESULT DATA(travels). 65 | 66 | LOOP AT travels ASSIGNING FIELD-SYMBOL(). 67 | reported-travel = VALUE #( BASE reported-travel ( %tky = -%tky %state_area = 'DEFAULT_MESSAGE' ) ). 68 | 69 | IF -EndDate < cl_abap_context_info=>get_system_date( ) AND -EndDate IS NOT INITIAL. 70 | DATA(is_travel_completed) = abap_true. 71 | reported-travel = VALUE #( BASE reported-travel ( 72 | %tky = -%tky 73 | %state_area = 'DEFAULT_MESSAGE' 74 | %msg = new_message_with_text( 75 | severity = if_abap_behv_message=>severity-information 76 | text = 'Travel completed' ) ) ). 77 | 78 | ELSEIF -OverallStatus = 'A'. 79 | reported-travel = VALUE #( BASE reported-travel ( 80 | %tky = -%tky 81 | %state_area = 'DEFAULT_MESSAGE' 82 | %msg = new_message_with_text( 83 | severity = if_abap_behv_message=>severity-success 84 | text = 'Travel Accepted' ) ) ). 85 | 86 | ELSEIF -OverallStatus = 'X'. 87 | reported-travel = VALUE #( BASE reported-travel ( 88 | %tky = -%tky 89 | %state_area = 'DEFAULT_MESSAGE' 90 | %msg = new_message_with_text( 91 | severity = if_abap_behv_message=>severity-error 92 | text = 'Travel Rejected' ) ) ). 93 | ENDIF. 94 | 95 | result = VALUE #( BASE result 96 | ( %tky = -%tky 97 | %update = COND #( WHEN is_travel_completed = abap_true 98 | THEN if_abap_behv=>fc-o-disabled 99 | ELSE if_abap_behv=>fc-o-enabled ) 100 | %action = VALUE #( 101 | Edit = COND #( WHEN is_travel_completed = abap_true 102 | THEN if_abap_behv=>fc-o-disabled 103 | ELSE if_abap_behv=>fc-o-enabled ) 104 | AcceptTravel = COND #( WHEN is_travel_completed = abap_true OR -OverallStatus = 'A' 105 | THEN if_abap_behv=>fc-o-disabled 106 | ELSE if_abap_behv=>fc-o-enabled ) 107 | RejectTravel = COND #( WHEN is_travel_completed = abap_true OR -OverallStatus = 'X' 108 | THEN if_abap_behv=>fc-o-disabled 109 | ELSE if_abap_behv=>fc-o-enabled ) ) ) ). 110 | ENDLOOP. 111 | ENDMETHOD. 112 | 113 | "Step 4 – Expose the actions in the projection BDEF YC_TRAVELTP (if not already exposed) 114 | "Step 5 – Test and See the Result 115 | "When you open the Object Page, the relevant message strip will appear automatically based on the travel status — Completed, Accepted, or Rejected. 116 | -------------------------------------------------------------------------------- /Email/Send_Internal_Table_as_Excel_Attachment.abap: -------------------------------------------------------------------------------- 1 | CLASS lcl_email_with_excel DEFINITION. 2 | PUBLIC SECTION. 3 | METHODS send_email. 4 | 5 | PRIVATE SECTION. 6 | TYPES: BEGIN OF ty_employee, 7 | emp_id TYPE pernr_d, 8 | emp_name TYPE text100, 9 | manager_id TYPE pernr_d, 10 | manager_name TYPE text100, 11 | emp_position TYPE text100, 12 | END OF ty_employee, 13 | tt_employee TYPE TABLE OF ty_employee WITH EMPTY KEY. 14 | 15 | TYPES: BEGIN OF ty_column, 16 | column_name TYPE text30, 17 | column_text TYPE text40, 18 | END OF ty_column, 19 | tt_columns TYPE TABLE OF ty_column WITH EMPTY KEY. 20 | CLASS-DATA mt_emloyees TYPE tt_employee. 21 | CLASS-DATA mt_columns TYPE tt_columns. 22 | 23 | METHODS load_data. 24 | METHODS convert_itab_to_xls_xstring RETURNING VALUE(rv_xstring) TYPE xstring. 25 | ENDCLASS. 26 | 27 | CLASS lcl_email_with_excel IMPLEMENTATION. 28 | METHOD load_data. 29 | mt_emloyees = VALUE #( ( emp_id = '1' emp_name = 'Name 1' emp_position = 'DEV_1' manager_id = '1' manager_name = 'Manager 1' ) 30 | ( emp_id = '2' emp_name = 'Name 2' emp_position = 'DEV_2' manager_id = '2' manager_name = 'Manager 2' ) ). 31 | 32 | mt_columns = VALUE #( ( column_name = 'EMP_ID' column_text = 'Employee ID' ) 33 | ( column_name = 'EMP_NAME' column_text = 'Employee Name' ) 34 | ( column_name = 'EMP_POSITION' column_text = 'Employee Position' ) 35 | ( column_name = 'MANAGER_ID' column_text = 'Manager ID' ) 36 | ( column_name = 'MANAGER_NAME' column_text = 'Manager Name' ) ). 37 | ENDMETHOD. 38 | 39 | METHOD convert_itab_to_xls_xstring. 40 | TRY. 41 | cl_salv_table=>factory( 42 | EXPORTING 43 | list_display = abap_false 44 | IMPORTING 45 | r_salv_table = DATA(lo_salv_table) 46 | CHANGING 47 | t_table = mt_emloyees ). 48 | 49 | LOOP AT mt_columns ASSIGNING FIELD-SYMBOL(). 50 | DATA(lo_column) = lo_salv_table->get_columns( )->get_column( -column_name ). 51 | lo_column->set_long_text( -column_text ). 52 | lo_column->set_medium_text( CONV #( -column_text ) ). 53 | lo_column->set_short_text( CONV #( -column_text ) ). 54 | ENDLOOP. 55 | 56 | DATA(lt_fcat) = cl_salv_controller_metadata=>get_lvc_fieldcatalog( 57 | r_columns = lo_salv_table->get_columns( ) 58 | r_aggregations = lo_salv_table->get_aggregations( ) ). 59 | CATCH cx_salv_msg INTO DATA(lx_mail). 60 | MESSAGE lx_mail TYPE 'E'. 61 | ENDTRY. 62 | 63 | "Option - 1 64 | "rv_xstring = lo_salv_table->to_xml( xml_type = if_salv_bs_xml=>c_type_xlsx ). 65 | "RETURN. 66 | 67 | "Option - 2 68 | cl_salv_bs_lex=>export_from_result_data_table( 69 | EXPORTING 70 | is_format = if_salv_bs_lex_format=>mc_format_xlsx 71 | ir_result_data_table = cl_salv_ex_util=>factory_result_data_table( 72 | r_data = REF #( mt_emloyees ) 73 | t_fieldcatalog = lt_fcat ) 74 | IMPORTING 75 | er_result_file = rv_xstring ). 76 | ENDMETHOD. 77 | 78 | METHOD send_email. 79 | 80 | TRY. 81 | load_data( ). 82 | 83 | DATA(lo_mail) = cl_bcs=>create_persistent( ). 84 | DATA(lo_sender_address) = cl_cam_address_bcs=>create_internet_address( 85 | i_address_string = CONV #( 'sender@gmail.com' ) ). 86 | lo_mail->set_sender( lo_sender_address ). 87 | 88 | DATA(recipient_address) = cl_cam_address_bcs=>create_internet_address( 89 | i_address_string = CONV #( 'receiver@gmail.com' ) ). 90 | lo_mail->add_recipient( i_recipient = recipient_address ). 91 | 92 | DATA(lo_document) = cl_document_bcs=>create_document( 93 | i_type = 'htm' 94 | i_subject = `Excel Attachment` 95 | i_text = VALUE #( ( CONV #( 'Excel Attachment' ) ) ) 96 | i_sender = lo_sender_address ). 97 | 98 | DATA(lv_excel_data) = convert_itab_to_xls_xstring( ). 99 | lo_document->add_attachment( 100 | i_attachment_type = 'XLS' 101 | i_attachment_subject = 'Employee Table' 102 | i_attachment_size = CONV #( xstrlen( lv_excel_data ) ) 103 | i_att_content_hex = cl_bcs_convert=>xstring_to_solix( lv_excel_data ) ). 104 | 105 | lo_mail->set_document( lo_document ). 106 | 107 | lo_mail->set_send_immediately( abap_true ). 108 | 109 | DATA(lv_send_success) = lo_mail->send( ). 110 | 111 | COMMIT WORK. 112 | 113 | CATCH cx_send_req_bcs cx_address_bcs cx_document_bcs INTO DATA(lx_mail). 114 | MESSAGE lx_mail TYPE 'E'. 115 | ENDTRY. 116 | ENDMETHOD. 117 | ENDCLASS. 118 | 119 | START-OF-SELECTION. 120 | DATA(lo_mail) = NEW lcl_email_with_excel( ). 121 | lo_mail->send_email( ). -------------------------------------------------------------------------------- /ZIP/Download_Multiple_Adobe_Form_as_ZIP_file.abap: -------------------------------------------------------------------------------- 1 | CLASS lcl_sb_zip DEFINITION 2 | CREATE PUBLIC . 3 | PUBLIC SECTION. 4 | TYPES: 5 | tt_customerid TYPE TABLE OF s_customer WITH EMPTY KEY . 6 | METHODS get_form 7 | IMPORTING 8 | !iv_customer_id TYPE s_customer 9 | RETURNING 10 | VALUE(rv_pdf) TYPE fpcontent . 11 | METHODS build_zip 12 | IMPORTING VALUE(it_customers_id) TYPE tt_customerid 13 | RETURNING VALUE(rv_zip_file) TYPE xstring. 14 | METHODS download_zip IMPORTING VALUE(iv_zip_file) TYPE xstring. 15 | METHODS send_email IMPORTING VALUE(iv_zip_file) TYPE xstring. 16 | PROTECTED SECTION. 17 | PRIVATE SECTION. 18 | METHODS get_customer_data 19 | IMPORTING 20 | !iv_customer_id TYPE s_customer 21 | EXPORTING 22 | !customer_detail TYPE scustom 23 | !bookings TYPE ty_bookings 24 | !connections TYPE ty_connections . 25 | ENDCLASS. 26 | 27 | CLASS lcl_sb_zip IMPLEMENTATION. 28 | METHOD get_customer_data. 29 | 30 | SELECT SINGLE FROM scustom 31 | FIELDS * 32 | WHERE id = @iv_customer_id 33 | INTO @customer_detail. 34 | SELECT FROM bookings 35 | FIELDS * 36 | WHERE customid = @iv_customer_id 37 | INTO TABLE @bookings. 38 | IF lines( bookings ) > 0. 39 | SELECT * FROM spfli INTO TABLE @connections 40 | FOR ALL ENTRIES IN @bookings 41 | WHERE carrid = @bookings-carrid 42 | AND connid = @bookings-connid. 43 | ENDIF. 44 | 45 | ENDMETHOD. 46 | 47 | METHOD get_form. 48 | 49 | DATA(lv_form_name) = CONV tdsfname( 'FP_TEST_03' ). 50 | DATA(lv_form_fm_name) = VALUE rs38l_fnam( ). 51 | DATA(ls_docparams) = VALUE sfpdocparams( ). 52 | DATA(ls_outputparams) = VALUE sfpoutputparams( ). 53 | DATA(ls_formoutput) = VALUE fpformoutput( ). 54 | * Get data 55 | get_customer_data( 56 | EXPORTING 57 | iv_customer_id = iv_customer_id 58 | IMPORTING 59 | customer_detail = DATA(customer) 60 | bookings = DATA(bookings) 61 | connections = DATA(connections) ). 62 | * get name of the generated function module 63 | TRY. 64 | CALL FUNCTION 'FP_FUNCTION_MODULE_NAME' 65 | EXPORTING 66 | i_name = lv_form_name 67 | IMPORTING 68 | e_funcname = lv_form_fm_name. 69 | CATCH cx_fp_api INTO DATA(lx_fp_api). 70 | MESSAGE ID lx_fp_api->msgid TYPE lx_fp_api->msgty 71 | NUMBER lx_fp_api->msgno 72 | WITH lx_fp_api->msgv1 lx_fp_api->msgv2 73 | lx_fp_api->msgv3 lx_fp_api->msgv4. 74 | RETURN. 75 | ENDTRY. 76 | * Set output parameters and open spool job 77 | ls_outputparams-nodialog = 'X'. " no print preview 78 | ls_outputparams-getpdf = 'X'. " request PDF 79 | CALL FUNCTION 'FP_JOB_OPEN' 80 | CHANGING 81 | ie_outputparams = ls_outputparams 82 | EXCEPTIONS 83 | cancel = 1 84 | usage_error = 2 85 | system_error = 3 86 | internal_error = 4 87 | OTHERS = 5. 88 | IF sy-subrc <> 0. 89 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 90 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 91 | RETURN. 92 | ENDIF. 93 | * Now call the generated function module 94 | CALL FUNCTION lv_form_fm_name 95 | EXPORTING 96 | /1bcdwb/docparams = ls_docparams 97 | customer = customer 98 | bookings = bookings 99 | connections = connections 100 | IMPORTING 101 | /1bcdwb/formoutput = ls_formoutput 102 | EXCEPTIONS 103 | usage_error = 1 104 | system_error = 2 105 | internal_error = 3 106 | OTHERS = 4. 107 | IF sy-subrc <> 0. 108 | RETURN. 109 | ENDIF. 110 | * Close spool job 111 | CALL FUNCTION 'FP_JOB_CLOSE' 112 | EXCEPTIONS 113 | usage_error = 1 114 | system_error = 2 115 | internal_error = 3 116 | OTHERS = 4. 117 | IF sy-subrc <> 0. 118 | RETURN. 119 | ENDIF. 120 | rv_pdf = ls_formoutput-pdf. 121 | ENDMETHOD. 122 | 123 | METHOD build_zip. 124 | DATA(lo_zip) = NEW cl_abap_zip( ). 125 | LOOP AT it_customers_id ASSIGNING FIELD-SYMBOL(). 126 | lo_zip->add( name = |{ }.pdf| 127 | content = get_form( ) ). 128 | ENDLOOP. 129 | rv_zip_file = lo_zip->save( ). 130 | ENDMETHOD. 131 | 132 | METHOD download_zip. 133 | DATA(lv_file_path) = VALUE string( ). 134 | DATA(lv_file_name) = VALUE string( ). 135 | DATA(lv_path) = VALUE string( ). 136 | DATA(lv_user_action) = VALUE i( ). 137 | 138 | cl_gui_frontend_services=>file_save_dialog( 139 | EXPORTING 140 | default_extension = 'zip' 141 | CHANGING 142 | fullpath = lv_file_path 143 | filename = lv_file_name 144 | path = lv_path 145 | user_action = lv_user_action 146 | EXCEPTIONS 147 | cntl_error = 1 148 | error_no_gui = 2 149 | not_supported_by_gui = 3 150 | invalid_default_file_name = 4 151 | OTHERS = 5 ). 152 | 153 | IF lv_user_action <> cl_gui_frontend_services=>action_ok. 154 | RETURN. 155 | ENDIF. 156 | 157 | DATA(lt_binary_tab) = VALUE solix_tab( ). 158 | 159 | lt_binary_tab = cl_bcs_convert=>xstring_to_solix( iv_zip_file ). 160 | 161 | CALL METHOD cl_gui_frontend_services=>gui_download 162 | EXPORTING 163 | filename = lv_file_path 164 | filetype = 'BIN' 165 | CHANGING 166 | data_tab = lt_binary_tab 167 | EXCEPTIONS 168 | file_write_error = 1 169 | no_batch = 2 170 | gui_refuse_filetransfer = 3 171 | invalid_type = 4 172 | no_authority = 5 173 | unknown_error = 6 174 | header_not_allowed = 7 175 | separator_not_allowed = 8 176 | filesize_not_allowed = 9 177 | header_too_long = 10 178 | dp_error_create = 11 179 | dp_error_send = 12 180 | dp_error_write = 13 181 | unknown_dp_error = 14 182 | access_denied = 15 183 | dp_out_of_memory = 16 184 | disk_full = 17 185 | dp_timeout = 18 186 | file_not_found = 19 187 | dataprovider_exception = 20 188 | control_flush_error = 21 189 | not_supported_by_gui = 22 190 | error_no_gui = 23 191 | OTHERS = 24. 192 | ENDMETHOD. 193 | 194 | METHOD send_email. 195 | TRY. 196 | DATA(lo_mail) = cl_bcs=>create_persistent( ). 197 | DATA(lo_sender_address) = cl_cam_address_bcs=>create_internet_address( 198 | i_address_string = CONV #( 'sender@gmail.com' ) ). 199 | lo_mail->set_sender( lo_sender_address ). 200 | 201 | DATA(recipient_address) = cl_cam_address_bcs=>create_internet_address( 202 | i_address_string = CONV #( 'receiver@gmail.com' ) ). 203 | lo_mail->add_recipient( i_recipient = recipient_address ). 204 | 205 | DATA(lo_document) = cl_document_bcs=>create_document( 206 | i_type = 'htm' 207 | i_subject = `ZIP File Attachment` 208 | i_text = VALUE #( ( CONV #( 'ZIP File Attachment' ) ) ) 209 | i_sender = lo_sender_address ). 210 | 211 | lo_document->add_attachment( i_attachment_type = 'ZIP' 212 | i_attachment_subject = 'Zip_File' 213 | i_attachment_size = CONV #( xstrlen( iv_zip_file ) ) 214 | i_att_content_hex = cl_bcs_convert=>xstring_to_solix( iv_zip_file ) ). 215 | lo_mail->set_document( lo_document ). 216 | 217 | lo_mail->set_send_immediately( abap_true ). 218 | DATA(lv_send_success) = lo_mail->send( ). 219 | COMMIT WORK. 220 | CATCH cx_send_req_bcs cx_address_bcs cx_document_bcs INTO DATA(lx_mail). 221 | MESSAGE lx_mail TYPE 'E'. 222 | ENDTRY. 223 | ENDMETHOD. 224 | 225 | ENDCLASS. 226 | 227 | START-OF-SELECTION. 228 | DATA(lo_zip) = NEW lcl_sb_zip( ). 229 | DATA(lv_zip_data) = lo_zip->build_zip( it_customers_id = VALUE #( ( CONV #( 00000001 ) ) 230 | ( CONV #( 00000002 ) ) ) ). 231 | lo_zip->download_zip( lv_zip_data ). 232 | lo_zip->send_email( lv_zip_data ). -------------------------------------------------------------------------------- /ABAP SQL/window_functions.abap: -------------------------------------------------------------------------------- 1 | CLASS zcl_sql_window_functions DEFINITION 2 | PUBLIC 3 | FINAL 4 | CREATE PUBLIC . 5 | PUBLIC SECTION. 6 | INTERFACES if_oo_adt_classrun . 7 | TYPES: BEGIN OF ty_students, 8 | student_id TYPE int4, 9 | student_name TYPE c LENGTH 40, 10 | dep_name TYPE c LENGTH 40, 11 | score TYPE int4, 12 | END OF ty_students. 13 | DATA: lt_students TYPE TABLE OF ty_students WITH DEFAULT KEY. 14 | METHODS: constructor. 15 | PROTECTED SECTION. 16 | PRIVATE SECTION. 17 | ENDCLASS. 18 | 19 | CLASS zcl_sql_window_functions IMPLEMENTATION. 20 | METHOD constructor. 21 | lt_students = VALUE #( ( student_id = 1 student_name = 'Bharathi S' dep_name = 'IT' score = 90 ) 22 | ( student_id = 2 student_name = 'Dhakshan' dep_name = 'CSE' score = 87 ) 23 | ( student_id = 3 student_name = 'Shroy' dep_name = 'EEE' score = 95 ) 24 | ( student_id = 4 student_name = 'Bhuvi' dep_name = 'EEE' score = 78 ) 25 | ( student_id = 5 student_name = 'Thara' dep_name = 'IT' score = 85 ) 26 | ( student_id = 6 student_name = 'Anish' dep_name = 'EEE' score = 95 ) 27 | ( student_id = 7 student_name = 'Aravind' dep_name = 'MECH' score = 91 ) 28 | ( student_id = 8 student_name = 'Mohan' dep_name = 'CSE' score = 82 ) 29 | ( student_id = 9 student_name = 'Saurabh' dep_name = 'IT' score = 92 ) 30 | ( student_id = 10 student_name = 'Rohan' dep_name = 'CSE' score = 65 ) 31 | ( student_id = 11 student_name = 'Surya' dep_name = 'MECH' score = 72 ) 32 | ( student_id = 12 student_name = 'Boopalan' dep_name = 'MECH' score = 67 ) 33 | ( student_id = 13 student_name = 'Shasank' dep_name = 'CSE' score = 75 ) 34 | ( student_id = 14 student_name = 'Kaviya' dep_name = 'EEE' score = 90 ) ). 35 | ENDMETHOD. 36 | 37 | METHOD if_oo_adt_classrun~main. 38 | SELECT FROM @lt_students AS lt_students 39 | FIELDS student_id, 40 | student_name, 41 | dep_name, 42 | score, 43 | 44 | " note: If partition by is not mentioned whole data will be considered as a single result set 45 | SUM( score ) OVER( ) AS total_score, 46 | MAX( score ) OVER( ) AS maximum_score, 47 | MIN( score ) OVER( ) AS mininum_score, 48 | CAST( AVG( score ) OVER( ) AS INT4 ) AS average_score, 49 | 50 | SUM( score ) OVER( PARTITION BY dep_name ORDER BY dep_name ASCENDING ) AS dep_total_score, 51 | MIN( score ) OVER( PARTITION BY dep_name ORDER BY dep_name ASCENDING ) AS dep_min_score, 52 | MAX( score ) OVER( PARTITION BY dep_name ORDER BY dep_name ASCENDING ) AS dep_max_score, 53 | CAST( AVG( score ) OVER( PARTITION BY dep_name ORDER BY dep_name ASCENDING ) AS INT4 ) AS dep_avg_score, 54 | 55 | ROW_NUMBER( ) OVER( ORDER BY student_name ) AS name_serial_number, 56 | RANK( ) OVER( PARTITION BY dep_name ORDER BY score DESCENDING ) AS dep_wise_rank_with_gaps, 57 | DENSE_RANK( ) OVER( PARTITION BY dep_name ORDER BY score DESCENDING ) AS dep_wise_rank_wo_gaps, 58 | 59 | LAG( score ) OVER( PARTITION BY dep_name ORDER BY score ) AS prev_score_by_dept, 60 | LEAD( score ) OVER( PARTITION BY dep_name ORDER BY score ) AS next_score_by_dept, 61 | 62 | SUM( score ) OVER( ORDER BY student_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS cumulative_sum, 63 | SUM( score ) OVER( ORDER BY student_id ) AS running_sum, 64 | 65 | FIRST_VALUE( student_id ) OVER( PARTITION BY dep_name ORDER BY score DESCENDING ) AS top_perfomer_dep_wise, 66 | LAST_VALUE( student_id ) OVER( PARTITION BY dep_name ORDER BY score DESCENDING ) AS low_perfomer_dep_wise, 67 | 68 | NTILE( 3 ) OVER( ORDER BY score ) AS group_students_by_3_levels 69 | 70 | ORDER BY dep_name, score DESCENDING 71 | INTO TABLE @DATA(lt_result) 72 | . 73 | out->write( lt_result ). 74 | ENDMETHOD. 75 | ENDCLASS. 76 | 77 | 78 | " Output 79 | *STUDENT_ID STUDENT_NAME DEP_NAME SCORE TOTAL_SCORE MAXIMUM_SCORE MININUM_SCORE AVERAGE_SCORE DEP_TOTAL_SCORE DEP_MIN_SCORE DEP_MAX_SCORE DEP_AVG_SCORE NAME_SERIAL_NUMBER DEP_WISE_RANK_WITH_GAPS DEP_WISE_RANK_WO_GAPS PREV_SCORE_BY_DEPT NEXT_SCORE_BY_DEPT CUMULATIVE_SUM RUNNING_SUM TOP_PERFOMER_DEP_WISE LOW_PERFOMER_DEP_WISE GROUP_STUDENTS_BY_3_LEVELS 80 | *2 Dhakshan CSE 87 1164 95 65 83 309 65 87 77 6 1 1 82 0 177 177 2 2 2 81 | *8 Mohan CSE 82 1164 95 65 83 309 65 87 77 8 2 2 75 87 703 703 2 8 2 82 | *13 Shasank CSE 75 1164 95 65 83 309 65 87 77 11 3 3 65 82 1074 1074 2 13 1 83 | *10 Rohan CSE 65 1164 95 65 83 309 65 87 77 9 4 4 0 75 860 860 2 10 1 84 | *3 Shroy EEE 95 1164 95 65 83 358 78 95 89 12 1 1 95 0 272 272 6 3 3 85 | *6 Anish EEE 95 1164 95 65 83 358 78 95 89 1 1 1 90 95 530 530 6 3 3 86 | *14 Kaviya EEE 90 1164 95 65 83 358 78 95 89 7 3 2 78 95 1164 1164 6 14 2 87 | *4 Bhuvi EEE 78 1164 95 65 83 358 78 95 89 4 4 3 0 90 350 350 6 4 1 88 | *9 Saurabh IT 92 1164 95 65 83 267 85 92 89 10 1 1 90 0 795 795 9 9 3 89 | *1 Bharathi S IT 90 1164 95 65 83 267 85 92 89 3 2 2 85 92 90 90 9 1 2 90 | *5 Thara IT 85 1164 95 65 83 267 85 92 89 14 3 3 0 90 435 435 9 5 2 91 | *7 Aravind MECH 91 1164 95 65 83 230 67 91 76 2 1 1 72 0 621 621 7 7 3 92 | *11 Surya MECH 72 1164 95 65 83 230 67 91 76 13 2 2 67 91 932 932 7 11 1 93 | *12 Boopalan MECH 67 1164 95 65 83 230 67 91 76 5 3 3 0 72 999 999 7 12 1 -------------------------------------------------------------------------------- /ABAP RAP/Download_Adobe_Form_in_RAP.abap: -------------------------------------------------------------------------------- 1 | "D𝗼𝘄𝗻𝗹𝗼𝗮𝗱𝗶𝗻𝗴 𝗔𝗱𝗼𝗯𝗲 𝗳𝗼𝗿𝗺𝘀 𝗼𝗿 𝗮𝗻𝘆 𝗳𝗶𝗹𝗲𝘀 𝗶𝗻 𝗥𝗔𝗣. 2 | "if you’ve tried this before, you might have noticed that methods like 𝗚𝗨𝗜_𝗗𝗢𝗪𝗡𝗟𝗢𝗔𝗗 or 𝗰𝗹_𝗴𝘂𝗶_𝗳𝗿𝗼𝗻𝘁𝗲𝗻𝗱_𝘀𝗲𝗿𝘃𝗶𝗰𝗲𝘀=>𝗴𝘂𝗶_𝗱𝗼𝘄𝗻𝗹𝗼𝗮𝗱 don’t work in RAP. 3 | "So, what’s the alternative? This can be achieved using streams (file upload) in RAP, combined with some additional logic. 4 | "Here are the two approaches I followed in my example: 5 | 6 | "1. 𝗖𝗿𝗲𝗮𝘁𝗲 𝗮𝗻 𝗮𝗰𝘁𝗶𝗼𝗻 to populate your stream fields with form data. 7 | "2. Use a 𝘃𝗶𝗿𝘁𝘂𝗮𝗹 𝗲𝗹𝗲𝗺𝗲𝗻𝘁 to fill your stream fields (not recommended, as it may trigger your Adobe form method multiple times). 8 | "Note: Ensure that your stream fields (attachment fields) are set to read-only,since it's getting filled through our logic. For the below Example I’ve created on OdataV4 – UI 9 | 10 | "1. Create a Table 11 | @EndUserText.label : 'Employee DATA' 12 | @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 13 | @AbapCatalog.tableCategory : #TRANSPARENT 14 | @AbapCatalog.deliveryClass : #A 15 | @AbapCatalog.dataMaintenance : #RESTRICTED 16 | define table zsb_emp_file_det { 17 | 18 | key client : abap.clnt not null; 19 | key employeeid : pernr_d not null; 20 | employeename : text100; 21 | attachment : /dmo/attachment; 22 | mimetype : /dmo/mime_type; 23 | filename : /dmo/filename; 24 | local_created_by : abp_creation_user; 25 | local_created_at : abp_creation_tstmpl; 26 | local_last_changed_by : abp_locinst_lastchange_user; 27 | local_last_changed_at : abp_locinst_lastchange_tstmpl; 28 | last_changed_at : abp_lastchange_tstmpl; 29 | } 30 | 31 | 32 | "2. Create a Root Entity 33 | @AccessControl.authorizationCheck: #CHECK 34 | @Metadata.allowExtensions: true 35 | @EndUserText.label: '###GENERATED Core Data Service Entity' 36 | @ObjectModel.sapObjectNodeType.name: 'Zsb_Emp_File_DET' 37 | define root view entity ZR_SB_EMP_FILE_DET 38 | as select from zsb_emp_file_det 39 | { 40 | key employeeid as Employeeid, 41 | employeename as Employeename, 42 | @Semantics.largeObject:{ fileName: 'Filename',mimeType: 'Mimetype',contentDispositionPreference: #ATTACHMENT } 43 | attachment as Attachment, 44 | @Semantics.mimeType: true 45 | mimetype as Mimetype, 46 | filename as Filename, 47 | @Semantics.user.createdBy: true 48 | local_created_by as LocalCreatedBy, 49 | @Semantics.systemDateTime.createdAt: true 50 | local_created_at as LocalCreatedAt, 51 | @Semantics.user.localInstanceLastChangedBy: true 52 | local_last_changed_by as LocalLastChangedBy, 53 | @Semantics.systemDateTime.localInstanceLastChangedAt: true 54 | local_last_changed_at as LocalLastChangedAt, 55 | @Semantics.systemDateTime.lastChangedAt: true 56 | last_changed_at as LastChangedAt 57 | 58 | } 59 | 60 | "3. Create a Projection View 61 | @ObjectModel.sapObjectNodeType.name: 'Zsb_Emp_File_DET' 62 | define root view entity ZC_SB_EMP_FILE_DET 63 | provider contract transactional_query 64 | as projection on ZR_SB_EMP_FILE_DET 65 | { 66 | key Employeeid, 67 | Employeename, 68 | LocalCreatedBy, 69 | LocalCreatedAt, 70 | LocalLastChangedBy, 71 | LocalLastChangedAt, 72 | LastChangedAt, 73 | 74 | Attachment, 75 | Mimetype, 76 | Filename, 77 | 78 | @Semantics.largeObject:{ fileName: 'vfilename', mimeType: 'vmimetype', contentDispositionPreference: #ATTACHMENT } 79 | @ObjectModel.virtualElement: true 80 | @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_FILE_VIRTUAL' 81 | virtual vattachment : /dmo/attachment, 82 | 83 | @ObjectModel.virtualElement: true 84 | @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_FILE_VIRTUAL' 85 | @Semantics.mimeType: true 86 | virtual vmimetype : /dmo/mime_type, 87 | 88 | @ObjectModel.virtualElement: true 89 | @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_FILE_VIRTUAL' 90 | virtual vfilename : /dmo/filename 91 | 92 | } 93 | 94 | "4. Metadata Extensions 95 | @Metadata.layer: #CORE 96 | @UI.headerInfo.title.type: #STANDARD 97 | @UI.headerInfo.title.value: 'Employeeid' 98 | @UI.headerInfo.description.type: #STANDARD 99 | @UI.headerInfo.description.value: 'Employeeid' 100 | annotate view ZC_SB_EMP_FILE_DET with 101 | { 102 | @UI.facet: [ { 103 | label: 'General Information', 104 | id: 'GeneralInfo', 105 | purpose: #STANDARD, 106 | position: 10 , 107 | type: #IDENTIFICATION_REFERENCE 108 | } ] 109 | @UI.identification: [ { position: 10,label: 'Employee Id' }, 110 | { type: #FOR_ACTION, dataAction: 'downloadForm', label: 'Download Adobe Form' } ] 111 | @UI.lineItem: [ { position: 10,label: 'Employee Id' } ] 112 | @UI.selectionField: [ { position: 10 } ] 113 | Employeeid; 114 | 115 | @UI.identification: [ { position: 20, label :'Employee Name' } ] 116 | @UI.lineItem: [ { position: 20, label: 'Employee Name' } ] 117 | Employeename; 118 | 119 | @UI.identification: [ { position: 30, label: 'Attachment(Based on Action)' } ] 120 | Attachment; 121 | 122 | @UI.identification: [ { position: 30, label: 'Attachment(Based on Virtual Element)' } ] 123 | vattachment; 124 | 125 | @UI.hidden: true 126 | Mimetype; 127 | @UI.hidden: true 128 | Filename; 129 | } 130 | 131 | 132 | "5. Behaviour Defination 133 | managed implementation in class ZBP_R_SB_EMP_FILE_DET unique; 134 | strict ( 2 ); 135 | with draft; 136 | define behavior for ZR_SB_EMP_FILE_DET alias ZrSbEmpFileDet 137 | persistent table ZSB_EMP_FILE_DET 138 | draft table ZSB_EMP_FLE_DT_D 139 | etag master LocalLastChangedAt 140 | lock master total etag LastChangedAt 141 | authorization master( global ) 142 | 143 | { 144 | 145 | field( mandatory : create, readonly : update ) Employeeid; 146 | field ( readonly ) 147 | LocalCreatedBy, 148 | LocalCreatedAt, 149 | LocalLastChangedBy, 150 | LocalLastChangedAt, 151 | LastChangedAt; 152 | 153 | field ( readonly ) Attachment; 154 | action downloadForm result [0..1] $self; 155 | 156 | create; 157 | update; 158 | delete; 159 | 160 | draft action Activate optimized; 161 | draft action Discard; 162 | draft action Edit; 163 | draft action Resume; 164 | draft determine action Prepare; 165 | 166 | mapping for ZSB_EMP_FILE_DET 167 | { 168 | Employeeid = employeeid; 169 | Employeename = employeename; 170 | Attachment = attachment; 171 | Mimetype = mimetype; 172 | Filename = filename; 173 | LocalCreatedBy = local_created_by; 174 | LocalCreatedAt = local_created_at; 175 | LocalLastChangedBy = local_last_changed_by; 176 | LocalLastChangedAt = local_last_changed_at; 177 | LastChangedAt = last_changed_at; 178 | } 179 | } 180 | 181 | "6. Behaviour Implementation - Action code 182 | METHOD downloadForm. 183 | 184 | DATA: lt_update TYPE TABLE FOR UPDATE zr_sb_emp_file_det. 185 | 186 | lt_update = VALUE #( for key in keys ( 187 | %tky = key-%tky 188 | Attachment = NEW ZCL_SB_FORM( )->get_form( key-Employeeid ) "This logic added in the below 189 | Filename = |Adobe_Form.pdf| 190 | Mimetype = 'APPLICATION/PDF' 191 | %control = VALUE #( Attachment = if_abap_behv=>mk-on 192 | Filename = if_abap_behv=>mk-on 193 | Mimetype = if_abap_behv=>mk-on ) 194 | ) ). 195 | 196 | MODIFY ENTITIES OF zr_sb_emp_file_det IN LOCAL MODE 197 | ENTITY ZrSbEmpFileDet 198 | UPDATE FROM lt_update 199 | REPORTED DATA(lt_update_reported) 200 | FAILED DATA(lt_update_failed). 201 | 202 | READ ENTITIES OF zr_sb_emp_file_det IN LOCAL MODE 203 | ENTITY ZrSbEmpFileDet 204 | ALL FIELDS WITH CORRESPONDING #( keys ) 205 | RESULT DATA(lt_result). 206 | 207 | result = VALUE #( for ls_result in lt_result ( 208 | %tky = ls_result-%tky 209 | %param = CORRESPONDING #( ls_result ) ) ). 210 | 211 | ENDMETHOD. 212 | 213 | "7. Behaviour Projection 214 | projection; 215 | strict ( 2 ); 216 | use draft; 217 | define behavior for ZC_SB_EMP_FILE_DET alias ZcSbEmpFileDet 218 | use etag 219 | 220 | { 221 | use create; 222 | use update; 223 | use delete; 224 | 225 | use action downloadForm; 226 | 227 | use action Edit; 228 | use action Activate; 229 | use action Discard; 230 | use action Resume; 231 | use action Prepare; 232 | } 233 | 234 | "8. Service Definition and Service Binding 235 | @EndUserText: { 236 | label: 'Service Definition for ZC_SB_EMP_FILE_DET' 237 | } 238 | @ObjectModel: { 239 | leadingEntity: { 240 | name: 'ZC_SB_EMP_FILE_DET' 241 | } 242 | } 243 | define service ZUI_SB_EMP_FILE_DET_O4 { 244 | expose ZC_SB_EMP_FILE_DET; 245 | } 246 | * Create a service binding with OData V4 - UI 247 | 248 | "9. Vitrual Element calculation Class - 249 | CLASS zcl_file_virtual DEFINITION 250 | PUBLIC 251 | FINAL 252 | CREATE PUBLIC. 253 | 254 | PUBLIC SECTION. 255 | 256 | INTERFACES if_sadl_exit . 257 | INTERFACES if_sadl_exit_calc_element_read . 258 | PROTECTED SECTION. 259 | PRIVATE SECTION. 260 | ENDCLASS. 261 | 262 | 263 | CLASS zcl_file_virtual IMPLEMENTATION. 264 | METHOD if_sadl_exit_calc_element_read~calculate. 265 | DATA : lt_emp_data TYPE TABLE OF zc_sb_emp_file_det. 266 | lt_emp_data = CORRESPONDING #( it_original_data ). 267 | 268 | LOOP AT lt_emp_data ASSIGNING FIELD-SYMBOL(). 269 | -vattachment = NEW ZCL_SB_FORM( )->get_form( -Employeeid ). "This logic added in the below 270 | -vfilename = |Adobe_Form.pdf|. 271 | -vmimetype = 'APPLICATION/PDF' . 272 | ENDLOOP. 273 | 274 | ct_calculated_data = CORRESPONDING #( lt_emp_data ). 275 | ENDMETHOD. 276 | 277 | 278 | METHOD if_sadl_exit_calc_element_read~get_calculation_info. 279 | ENDMETHOD. 280 | ENDCLASS. 281 | 282 | "Code to get Adobe form as Xstring: 283 | 284 | CLASS zcl_sb_form DEFINITION 285 | PUBLIC 286 | CREATE PUBLIC . 287 | PUBLIC SECTION. 288 | METHODS get_form 289 | IMPORTING 290 | !iv_customer_id TYPE s_customer 291 | RETURNING 292 | VALUE(rv_pdf) TYPE fpcontent . 293 | PROTECTED SECTION. 294 | PRIVATE SECTION. 295 | METHODS get_customer_data 296 | IMPORTING 297 | !iv_customer_id TYPE s_customer 298 | EXPORTING 299 | !customer_detail TYPE scustom 300 | !bookings TYPE ty_bookings 301 | !connections TYPE ty_connections . 302 | ENDCLASS. 303 | 304 | 305 | 306 | CLASS zcl_sb_form IMPLEMENTATION. 307 | 308 | 309 | METHOD get_customer_data. 310 | 311 | SELECT SINGLE FROM scustom 312 | FIELDS * 313 | WHERE id = @iv_customer_id 314 | INTO @customer_detail. 315 | SELECT FROM bookings 316 | FIELDS * 317 | WHERE customid = @iv_customer_id 318 | INTO TABLE @bookings. 319 | IF lines( bookings ) > 0. 320 | SELECT * FROM spfli INTO TABLE @connections 321 | FOR ALL ENTRIES IN @bookings 322 | WHERE carrid = @bookings-carrid 323 | AND connid = @bookings-connid. 324 | ENDIF. 325 | 326 | ENDMETHOD. 327 | 328 | 329 | METHOD get_form. 330 | 331 | DATA(lv_form_name) = CONV tdsfname( 'FP_TEST_03' ). 332 | DATA(lv_form_fm_name) = VALUE rs38l_fnam( ). 333 | DATA(ls_docparams) = VALUE sfpdocparams( ). 334 | DATA(ls_outputparams) = VALUE sfpoutputparams( ). 335 | DATA(ls_formoutput) = VALUE fpformoutput( ). 336 | * Get data 337 | get_customer_data( 338 | EXPORTING 339 | iv_customer_id = iv_customer_id 340 | IMPORTING 341 | customer_detail = DATA(customer) 342 | bookings = DATA(bookings) 343 | connections = DATA(connections) ). 344 | * get name of the generated function module 345 | TRY. 346 | CALL FUNCTION 'FP_FUNCTION_MODULE_NAME' 347 | EXPORTING 348 | i_name = lv_form_name 349 | IMPORTING 350 | e_funcname = lv_form_fm_name. 351 | CATCH cx_fp_api INTO DATA(lx_fp_api). 352 | MESSAGE ID lx_fp_api->msgid TYPE lx_fp_api->msgty 353 | NUMBER lx_fp_api->msgno 354 | WITH lx_fp_api->msgv1 lx_fp_api->msgv2 355 | lx_fp_api->msgv3 lx_fp_api->msgv4. 356 | RETURN. 357 | ENDTRY. 358 | * Set output parameters and open spool job 359 | ls_outputparams-nodialog = 'X'. " no print preview 360 | ls_outputparams-getpdf = 'X'. " request PDF 361 | CALL FUNCTION 'FP_JOB_OPEN' 362 | CHANGING 363 | ie_outputparams = ls_outputparams 364 | EXCEPTIONS 365 | cancel = 1 366 | usage_error = 2 367 | system_error = 3 368 | internal_error = 4 369 | OTHERS = 5. 370 | IF sy-subrc <> 0. 371 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 372 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 373 | RETURN. 374 | ENDIF. 375 | * Now call the generated function module 376 | CALL FUNCTION lv_form_fm_name 377 | EXPORTING 378 | /1bcdwb/docparams = ls_docparams 379 | customer = customer 380 | bookings = bookings 381 | connections = connections 382 | IMPORTING 383 | /1bcdwb/formoutput = ls_formoutput 384 | EXCEPTIONS 385 | usage_error = 1 386 | system_error = 2 387 | internal_error = 3 388 | OTHERS = 4. 389 | IF sy-subrc <> 0. 390 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 391 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 392 | RETURN. 393 | ENDIF. 394 | * Close spool job 395 | CALL FUNCTION 'FP_JOB_CLOSE' 396 | EXCEPTIONS 397 | usage_error = 1 398 | system_error = 2 399 | internal_error = 3 400 | OTHERS = 4. 401 | IF sy-subrc <> 0. 402 | MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 403 | WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. 404 | RETURN. 405 | ENDIF. 406 | rv_pdf = ls_formoutput-pdf. 407 | ENDMETHOD. 408 | ENDCLASS. --------------------------------------------------------------------------------