Blog

  • SAP ABAP Practice Exercises

    Introduction

    Get ready to enhance your SAP ABAP skills with our comprehensive collection of SAP ABAP practice exercises. Whether you’re a beginner or an experienced developer, our exercises will help you master the intricacies of the ABAP programming language and build robust, scalable and efficient applications. From basic exercises like creating an ABAP report and working with variables, to advanced exercises like creating an OData service and working with BAPI’s, we’ve got something for everyone. Our step-by-step instructions and detailed explanations make it easy for you to follow along and improve your understanding of SAP ABAP. With our practice exercises, you will be able to build professional, high-quality applications and advance your career as an SAP ABAP developer. Optimize your skills, improve your knowledge and get ready to take on any ABAP challenge with our SAP ABAP practice exercises.

    SAP ABAP Basic Exercise

    Here are ten practice exercises for SAP ABAP (ABAP stands for “Advanced Business Application Programming”):

    1. Create a program that displays the current system date and time when run.

    REPORT ZDISPLAY_DATETIME.
    
    DATA: current_date TYPE sy-datum,
          current_time TYPE sy-uzeit.
    
    current_date = sy-datum.
    current_time = sy-uzeit.
    
    WRITE: / 'Current Date:', current_date,
           / 'Current Time:', current_time.
    

     

    2. Create a program that prompts the user for a number, then calculates and displays the square of that number.

    REPORT ZSQUARE_NUMBER.
    
    DATA: num TYPE i,
          result TYPE i.
    
    PARAMETERS: p_num TYPE i.
    
    result = p_num * p_num.
    
    WRITE: / 'The square of', p_num, 'is', result.
    

     

    3. Create a program that reads data from a CSV file and displays it in a table on the screen.

    REPORT ZREAD_CSV.
    
    DATA: it_csv_data TYPE TABLE OF string,
          lv_file_name TYPE string.
    
    PARAMETERS: p_file TYPE string.
    
    lv_file_name = p_file.
    
    CALL METHOD cl_gui_frontend_services=>gui_upload
      EXPORTING
        filename = lv_file_name
      IMPORTING
        filelength = lv_file_len
      CHANGING
        data_tab = it_csv_data.
    
    LOOP AT it_csv_data.
      WRITE: / it_csv_data.
    ENDLOOP.
    

     

    4. Create a program that prompts the user for a customer number and displays the customer’s name, address, and contact information from the SAP database.

    REPORT ZCUSTOMER_DETAILS.
    
    DATA: lv_customer TYPE KNA1-KUNNR,
          lv_name TYPE KNA1-NAME1,
          lv_address TYPE KNA1-STRAS,
          lv_contact TYPE KNA1-TELF1.
    
    PARAMETERS: p_customer TYPE KNA1-KUNNR.
    
    SELECT SINGLE NAME1 STRAS TELF1
      INTO (lv_name, lv_address, lv_contact)
      FROM KNA1
      WHERE KUNNR = p_customer.
    
    WRITE: / 'Customer Name:', lv_name,
           / 'Address:', lv_address,
           / 'Contact:', lv_contact.
    

     

    5. Create a program that generates an invoice for a customer using data from the SAP database.

    REPORT ZINVOICE_GENERATION.
    
    DATA: lv_customer TYPE KNA1-KUNNR,
          lv_invoice TYPE BSEG-BELNR,
          lv_amount TYPE BSEG-DMBTR.
    
    PARAMETERS: p_customer TYPE KNA1-KUNNR.
    
    SELECT SINGLE BELNR DMBTR
      INTO (lv_invoice, lv_amount)
      FROM BSEG
      WHERE KUNNR = p_customer.
    
    WRITE: / 'Invoice:', lv_invoice,
           / 'Amount:', lv_amount.
    

     

    6. Create a program that generates a report showing the sales data for a specific product over a specified time period.

    REPORT ZSALES_DATA.
    
    DATA: lv_product TYPE VBAP-MATNR,
          lv_sales TYPE VBAP-NETWR.
    
    PARAMETERS: p_product TYPE VBAP-MATNR.
    
    SELECT SUM(NETWR)
      INTO lv_sales
      FROM VBAP
      WHERE MATNR = p_product.
    
    WRITE: / 'Total Sales for Product:', p_product, 'is', lv_sales.
    

     

    7. Create a program that allows the user to update the prices of a specific product in the SAP database.

    REPORT ZUPDATE_PRICE.
    
    DATA: lv_product TYPE MARA-MATNR,
          lv_price TYPE MARA-PRDAT.
    
    PARAMETERS: p_product TYPE MARA-MATNR,
                p_price TYPE MARA-PRDAT.
    
    UPDATE MARA SET PRDAT = p_price
      WHERE MATNR = p_product.
    
    WRITE: / 'Price updated for product:', p_product.
    

     

    8. Create a program that generates a report showing the inventory levels of all products in the SAP database.

    REPORT ZINVENTORY_LEVELS.
    
    DATA: lv_product TYPE MARD-MATNR,
          lv_stock TYPE MARD-LABST.
    
    SELECT MATNR, LABST
      INTO (lv_product, lv_stock)
      FROM MARD
      WHERE MATNR IS NOT NULL.
    
    WRITE: / 'Product:', lv_product, 'Stock:', lv_stock.
    ENDLOOP.
    

     

    9. Create a program that allows users to search for and display information about a specific purchase order.

    REPORT ZPO_SEARCH.
    
    DATA: lv_po TYPE EKKO-BELNR,
          lv_vendor TYPE EKKO-LIFNR,
          lv_date TYPE EKKO-BUDAT.
    
    PARAMETERS: p_po TYPE EKKO-BELNR.
    
    SELECT SINGLE BELNR LIFNR BUDAT
      INTO (lv_po, lv_vendor, lv_date)
      FROM EKKO
      WHERE BELNR = p_po.
    
    WRITE: / 'PO:', lv_po,
           / 'Vendor:', lv_vendor,
           / 'Date:', lv_date.
    

     

    10. Create a program that generates a report showing a specific sales area’s revenue over a specified period.

    REPORT ZSALES_AREA_REVENUE.
    
    DATA: lv_sales_area TYPE VBRP-VGBEL,
          lv_revenue TYPE VBRP-NETWR.
    
    PARAMETERS: p_sales_area TYPE VBRP-VGBEL.
    
    SELECT SUM(NETWR)
      INTO lv_revenue
      FROM VBRP
      WHERE VGBEL = p_sales_area.
    
    WRITE: / 'Sales Area:', p_sales_area, 'Revenue:', lv_revenue.
    

     

    Please note that these exercises are basic examples, and it’s recommended to practice on a non-production system, as some of them may require access to specific tables or functionalities unavailable on all systems.

    SAP ABAP Advanced Exercise

    Here is an advanced and complex SAP ABAP exercise:

    Task: Create a program that reads data from a table and creates a report that displays the data in a specific format.

    Sub Tasks:

    1. Create a new ABAP program using the transaction code SE38.

    2. Define the data structure for the table you will be reading from. This should include the fields you will be using in the report.

    3. Use the SELECT statement to read the data from the table and store it in your defined data structure.

    4. Create a report using the data structure and the data you read from the table. Use the LOOP statement to iterate through the data and display it in the report.

    REPORT ZREPORT_FROM_TABLE.
    
    TYPES: BEGIN OF ty_data,
             field1 TYPE string,
             field2 TYPE string,
             field3 TYPE i,
           END OF ty_data.
    
    DATA: it_data TYPE TABLE OF ty_data,
          lv_field1 TYPE string,
          lv_field2 TYPE string,
          lv_field3 TYPE i.
    
    SELECT field1, field2, field3
      INTO (lv_field1, lv_field2, lv_field3)
      FROM your_table
      WHERE your_conditions.
    
    APPEND VALUE #( field1 = lv_field1
                    field2 = lv_field2
                    field3 = lv_field3 ) TO it_data.
    
    LOOP AT it_data.
      WRITE: / it_data-field1, it_data-field2, it_data-field3.
    ENDLOOP.
    

     

    5. Use the SUM and COUNT statements to calculate and display the total number of records and the total value of a specific field in the report.

    DATA: lv_total TYPE i,
          lv_count TYPE i.
    
    SELECT SUM(field3), COUNT(*)
      INTO (lv_total, lv_count)
      FROM your_table
      WHERE your_conditions.
    
    WRITE: / 'Total:', lv_total,
           / 'Count:', lv_count.
    

     

    6. Use the AT NEW and AT END OF statements to create subtotals for specific fields in the report.

    LOOP AT it_data.
      AT NEW field1.
        WRITE: / 'New Field1:', it_data-field1.
      ENDAT.
    
      AT END OF field1.
        WRITE: / 'End of Field1:', it_data-field1.
      ENDAT.
    ENDLOOP.
    

     

    7. Create an interactive ALV grid report using the CLASS CL_SALV_TABLE and the method SET_TABLE_FOR_FIRST_DISPLAY.

    DATA: o_alv TYPE REF TO cl_salv_table.
    
    CALL METHOD cl_salv_table=>factory
      IMPORTING
        r_salv_table = o_alv
      CHANGING
        t_table = it_data.
    
    o_alv->display( ).
    

     

    8. Implement a search functionality that allows users to filter the data based on specific criteria.

    PARAMETERS: p_field TYPE string. SELECT * FROM your_table WHERE field1 = p_field INTO TABLE it_filtered_data.

     

    9. Use the UPDATE and MODIFY statements to allow the user to update the data in the table directly from the report.

    UPDATE your_table SET field1 = 'new_value' WHERE field2 = 'some_condition'.

     

    10. Use the transaction code SE38 to test the program and ensure it works correctly.

    To test, use transaction code SE38 to create and run the report. Make sure your conditions and table names are valid.

    Note: This exercise is complex and assumes that you have a good understanding of ABAP and can use related tools and transactions.

  • SAP Cloud Application Programming Model (CAP) Interview Questions

    Preface – This post is part of the Interview series.

    Introduction

    SAP Cloud Application Programming Model (CAP) is a modern, open-source development framework for building enterprise-grade applications on the SAP Cloud Platform. It enables developers to build and deploy cloud-native applications quickly and easily. As the demand for SAP CAP expertise increases, so does the need for well-versed professionals in this technology. If you’re preparing for an interview for a position related to SAP Cloud Application Programming Model (CAP), it’s important to be familiar with the common interview questions related to this topic. Here we provide a list of SAP CAP interview questions and answers to help you understand the key concepts and ace the interview.

    Basic SAP CAPM Interview Questions

    1. Can you explain the basic architecture of the SAP Cloud Application Programming Model (CAP)?

    Ans. SAP Cloud Application Programming Model (CAP) follows a microservices architecture, dividing the application into small, independently deployable services. It is built on top of the Node.js runtime and uses the Express.js web framework. It also uses the database programming model for data modeling and persistence and uses the OData protocol for data access.

    2. How does SAP CAP differ from traditional development frameworks?

    Ans. SAP CAP is a modern, open-source development framework specifically designed for building enterprise-grade applications on the SAP Cloud Platform. It provides a simplified development experience, improved scalability and security, and built-in support for SAP Cloud Platform services.

    3. Can you explain how SAP CAP handles data modeling and persistence?

    Ans. SAP CAP uses the Database Programming Model (DPM) for data modeling and persistence. It is a type-safe and lightweight data access layer that allows developers to model their data using JavaScript classes. The framework then generates the database schema and automatically handles database operations, such as CRUD operations.

    4. How does SAP CAP support security and user authentication?

    Ans. SAP CAP uses the built-in security features of the SAP Cloud Platform for user authentication and authorization. It supports various authentication mechanisms, such as OAuth 2.0 and SAML. It also includes features for securing data access and communication between services.

    5. Can you explain how SAP CAP handles service consumption and integration with other systems?

    Ans. SAP CAP provides a built-in mechanism for consuming and exposing services. It uses the Open Data Protocol (OData) for data access and supports the creation of OData services and the consumption of existing OData services. It also provides a built-in mechanism for service discovery and binding, making it easy to consume and integrate with other services.

    6. How does SAP CAP support the deployment and scaling of applications?

    Ans. SAP CAP supports the deployment and scaling of applications through the SAP Cloud Platform. It uses the Cloud Foundry environment for deployment and scaling, allowing for easy and automatic scaling of applications based on demand.

    7. Can you explain how SAP CAP handles error handling and logging?

    Ans. SAP CAP provides built-in error handling and logging capabilities. It uses the standard Node.js error handling mechanism and provides a centralized logging service for capturing and analyzing log data.

    8. How does SAP CAP support testing and quality assurance?

    Ans. SAP CAP provides built-in support for testing and quality assurance through the use of standard testing frameworks, such as Jest and Mocha. It also provides a built-in mechanism for running unit and integration tests.

    9. Can you explain how SAP CAP facilitates the development of UI using SAP Fiori?

    Ans. SAP CAP provides built-in support for developing UI using SAP Fiori. It includes a set of predefined UI elements and templates that can be used to create SAP Fiori-compliant UIs. It also includes built-in support for the SAP Fiori Launchpad and SAP Fiori elements.

    10. Can you explain how SAP CAP supports the development of OData services?

    Ans. SAP CAP provides built-in support for the creation of OData services. It includes a set of predefined classes and templates that can be used to create OData services quickly and easily. It also includes built-in support for the OData protocol, including support for OData operations, such as CRUD operations, and support for OData metadata.

    Scenario-Based SAP CAPM Interview Questions

    1. Scenario: A company plans to implement SAP CAPM to manage its capital projects but has concerns about the solution’s scalability.

    • Question: How would you address the company’s concerns about scalability in SAP CAPM?
    • Answer: I would explain that SAP CAPM is built on the SAP Cloud Platform, which provides built-in support for scalability. The platform allows for easy and automatic scaling of applications based on demand, and the microservices architecture of SAP CAPM allows for the independent scaling of individual services. Additionally, the platform also provides built-in monitoring and alerting capabilities to allow for proactive management of scalability issues.

    2. Scenario: A company wants to integrate SAP CAPM with other systems, such as ERP and accounting systems.

    • Question: How would you integrate SAP CAPM with other systems?
    • Answer: I would use SAP Cloud Platform’s built-in integration capabilities, such as the Cloud Integration service, to integrate SAP CAPM with other systems. This would allow for the seamless transfer of data between systems and the automation of processes such as project financials. Additionally, I would use the OData protocol for data access, which SAP CAPM supports, to expose the data to other systems.

    3. Scenario: A company wants to use SAP CAPM for budgeting and forecasting for capital projects.

    • Question: How would you use SAP CAPM for budgeting and forecasting?
    • Answer: I would use SAP CAPM’s built-in budgeting and forecasting capabilities to plan and manage the budget for capital projects. The solution allows for creating budget plans, tracking actual costs, and forecasting future costs. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into budget performance and identify areas for cost savings.

    4. Scenario: A company wants to use SAP CAPM to manage and control risks for capital projects.

    • Question: How would you use SAP CAPM to manage and control risks for capital projects?
    • Answer: I would use SAP CAPM’s built-in risk management capabilities to identify, evaluate, and mitigate risks for capital projects. The solution allows for the creation of risk plans, tracking of risk progress, and reporting on risk performance. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into risk performance and identify areas for risk reduction.

    5. Scenario: A company wants to use SAP CAPM to improve visibility and control of project costs.

    • Question: How would you use SAP CAPM to improve visibility and control of project costs?
    • Answer: I would use SAP CAPM’s built-in cost management capabilities to track and control project costs. The solution allows for the tracking of actual costs, forecasting of future costs, and reporting on cost performance. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into cost performance and identify areas for cost savings.

    6. Scenario: A company wants to use SAP CAPM for resource management for capital projects.

    • Question: How would you use SAP CAPM for resource management for capital projects?
    • Answer: I would use SAP CAPM’s built-in resource management capabilities to plan and manage resources for capital projects. The solution allows for the creation of resource plans, tracking of resource progress, and reporting on resource performance. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into resource performance and identify areas for resource optimization.

    7. Scenario: A company wants to use SAP CAPM for project management for capital projects.

    • Question: How would you use SAP CAPM for project management for capital projects?
    • Answer: I would use SAP CAPM’s built-in project management capabilities to plan, execute and monitor capital projects. The solution allows for creating project plans, tracking progress, and reporting on project performance. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into project performance and identify areas for improvement.

    8. Scenario: A company wants to use SAP CAPM for compliance and policy enforcement for capital projects.

    • Question: How would you use SAP CAPM for compliance and policy enforcement for capital projects?
    • Answer: I would use SAP CAPM’s built-in compliance and policy enforcement capabilities to ensure compliance with company policies and government regulations for capital projects. The solution allows for creating compliance and policy plans, tracking compliance and policy progress, and reporting on compliance and policy performance. Additionally, I would use the built-in reporting and analytics capabilities to gain insights into compliance and policy performance and identify areas for improvement.

     

    Coding-Based SAP CAPM Interview Questions

    1. Question: How do you create an OData service in SAP CAPM?

    • Answer: To create an OData service in SAP CAPM, you can use the built-in @odata.cds and @odata.publish decorators to define the data model and expose it as an OData service. You can also use the .csn file to define the data model and use the .cds file to define the service.

    2. Question: How do you handle data persistence in SAP CAPM?

    • Answer: SAP CAPM uses the Database Programming Model (DPM) for data persistence. To handle data persistence, you can use the built-in .db module to define the data model and handle database operations, such as CRUD operations.

    3. Question: How do you implement user authentication and authorization in SAP CAPM?

    • Answer: SAP CAPM uses the built-in security features of the SAP Cloud Platform for user authentication and authorization. To implement user authentication and authorization, you can use the built-in @authentication and @authorization decorators to define the authentication and authorization flow.

    4. Question: How do you handle errors and exceptions in SAP CAPM?

    • Answer: SAP CAPM uses the standard Node.js error handling mechanism to handle errors and exceptions. You can use the built-in try-catch block to handle errors and exceptions and the .error() function to handle error responses.

    5. Question: How do you implement testing in SAP CAPM?

    • Answer: SAP CAPM provides built-in support for testing using standard frameworks like Jest and Mocha. You can use the .spec.js file to define the test cases and use the .test() function to run the tests.

    6. Question: How do you implement deployment in SAP CAPM?

    • Answer: SAP CAPM supports deployment through the SAP Cloud Platform using the Cloud Foundry environment. To deploy an application, you can use the built-in command-line interface to push the application to the Cloud Foundry environment.

    7. Question: How do you implement logging in SAP CAPM?

    • Answer: SAP CAPM provides built-in support for logging using the .log module. You can use the .log() function to log messages and the built-in logging service to access the log data.

    8. Question: How do you implement integration with other systems in SAP CAPM?

    • Answer: SAP CAPM provides built-in support for integration using the Cloud Integration service and the OData protocol. You can use the built-in .cds file to define the service and use the .odata file to define the OData service.

    9. Question: How do you implement UI development using SAP Fiori in SAP CAPM?

    • Answer: SAP CAPM provides built-in support for UI development using SAP Fiori. You can use the built-in UI elements and templates to create SAP Fiori-compliant UIs and use the built-in support for the SAP Fiori Launchpad and SAP Fiori elements to implement the UI.

    10. Question: How do you implement scalability in SAP CAPM?

    • Answer: SAP CAPM is built on the SAP Cloud Platform, which provides built-in support for scalability. To implement scalability, you can use the Cloud Foundry environment to scale the application based on demand, and the microservices architecture of SAP CAPM allows for the independent scaling of individual services.
  • SAP Concur Interview Questions

    Preface – This post is part of the Interview series.

    Introduction

    SAP Concur is the leading service to manage travel and expense with vendor invoice management tools. In this article, we will explore SAP Concur Interview Questions.

    SAP Concur comes with three major solutions:

    • Concur Expense: To submit an expense from anywhere around the globe
    • Concur Invoice: To automate and integrate your Accounts Payable process
    • Concur Travel: To capture travel details irrespective of booking location

    Apart from the above, SAP Concur offers multiple other solutions and services that can be checked here.

    Basic SAP Concur Interview Questions

    1. Explain SAP Concur.
    2. Explain SAP Concur Mobile App.
    3. What are the services and solutions of SAP Concur?
    4. What are the major features of SAP Concur?
    5. What is the importance of Expense Management?
    6. Explain SAP Concur Expense.
    7. How can we enter expenses in SAP Concur?
    8. Explain ‘Duty of Care.’
    9. Explain ‘Employee Fraud.’
    10. Explain the concept of travel and expense policy.
    11. Explain SAP Concur Travel & Expense.
    12. Explain the invoice management system of SAP Concur.

    All the answers to the above SAP Concur Interview Questions are available here.

    Theoretical SAP Concur Interview Questions

    1. What technology is used to build SAP Concur?

    Ans. SAP Concur is built using various technologies, including Java, JavaScript, and various database technologies, such as SQL and NoSQL. Additionally, it also employs web development frameworks like AngularJS, ReactJS, and others. The platform also uses cloud computing technologies, such as Amazon Web Services (AWS), to provide scalable, secure hosting and deployment options.

    2. How does SAP Concur use SAP HANA services?

    Ans. SAP Concur can use SAP HANA services to provide various benefits, such as improved performance and scalability, real-time data processing, and advanced analytics capabilities. Specifically, SAP Concur can utilize SAP HANA’s in-memory computing capabilities to process and analyze large amounts of data in real time. This can be used to provide users with real-time insights and reports and to support advanced analytics and machine learning algorithms. Additionally, SAP HANA’s built-in data warehousing and modeling capabilities can be used to support data integration and management for SAP Concur.

    Practical Interview Questions

    1. Can you explain how SAP Concur’s expense management system works?

    Ans. SAP Concur’s expense management system allows employees to easily submit and track their expenses while also providing managers with the tools they need to approve, reject, or request additional information on expenses. It also integrates with accounting and ERP systems to automate the reimbursement process.

    2. How does SAP Concur handle compliance and policy enforcement?

    Ans. SAP Concur uses a variety of mechanisms to enforce compliance and policies, such as automated expense rule checks, real-time compliance alerts, and built-in compliance reporting.

    3. Can you explain how SAP Concur’s integrated travel and expense management system works?

    Ans. SAP Concur’s integrated travel and expense management system allows employees to book, manage, and expense their business travel all in one place. It also provides real-time visibility into travel and expense spending, as well as the ability to enforce compliance and travel policies.

    4. How does SAP Concur integrate with other systems, such as ERP and accounting systems?

    Ans. SAP Concur can integrate with other systems through APIs, pre-built connectors, or middleware. This allows for the seamless transfer of data and the automation of processes such as expense reimbursement.

    5. Can you explain how SAP Concur’s receipt capture and receipt matching works?

    Ans. SAP Concur’s receipt capture and receipt matching use OCR technology to automatically extract information from receipts, such as date, vendor, and amount. This information can then be matched to the corresponding expense report, streamlining the expense management process.

    6. How does SAP Concur handle currency conversion and exchange rate management?

    Ans. SAP Concur can handle currency conversion and exchange rate management by automatically converting expenses to the company’s base currency and using daily updated exchange rates.

    7. Can you explain how SAP Concur’s mobile app works?

    Ans. SAP Concur’s mobile app allows users to easily submit expenses, view their expense report status, and approve or reject expenses from their mobile device. It also allows users to capture receipts and create expense reports on the go.

    8. How does SAP Concur handle accounting and financial reporting?

    Ans. SAP Concur can handle accounting and financial reporting by integrating with accounting and ERP systems, such as SAP, Oracle, and Microsoft Dynamics. This allows for the automation of financial processes such as expense reimbursement and the creation of financial reports.

    9. Can you explain how SAP Concur’s reporting and analytics capabilities work?

    Ans. SAP Concur’s reporting and analytics capabilities allow users to create custom reports, analyze spending data, and gain real-time insights into the company’s expenses. It also has built-in compliance reporting capabilities, which can provide compliance and policy enforcement information.

    10. How do SAP Concur’s audit, and compliance features work?

    Ans. SAP Concur’s audit and compliance features include automated expense rule checks, real-time compliance alerts, and built-in compliance reporting. This allows the system to automatically flag potential compliance issues and provide the necessary information for auditing.

    Scenario-Based Concur Interview Questions

    1. Scenario: A company has just implemented SAP Concur for expense management, but employees submit expenses manually.
    • Question: How would you address this issue and encourage employees to use SAP Concur for expense management?
    • Answer: I would first identify the reasons why employees are not using SAP Concur for expense management. It could be that they are unaware of its capabilities or find it difficult to use. Once the reasons are identified, I would create a training program to educate employees on the benefits of using SAP Concur and provide them with the necessary support to get started. I would also conduct regular check-ins with employees to ensure they are comfortable using the system and address any issues they may be experiencing.
    1. Scenario: A company is struggling to control travel expenses, and management wants to know how SAP Concur can help.
    • Question: How would you use SAP Concur to manage and control travel expenses?
    • Answer: I would use SAP Concur’s integrated travel and expense management system to book, manage, and expense business travel. This would provide real-time visibility into travel spending, and allow for the enforcement of compliance and travel policies. Additionally, I would set up expense rules to automatically flag and review expenses that exceed a certain dollar amount or do not comply with company policies. I would also provide employees with training on booking travel within budget and using the expense management system.
    1. Scenario: A company wants to automate and integrate the expense reimbursement process with its accounting system.
    • Question: How would you use SAP Concur to automate the expense reimbursement process and integrate it with an accounting system?
    • Answer: I would use SAP Concur’s pre-built connectors or APIs to integrate the system with the company’s accounting system. This would allow for the seamless transfer of data between the two systems and automate the reimbursement process. I would also set up expense rules to automatically flag and review expenses that need to be reimbursed and ensure that all expenses are coded correctly before they are sent to the accounting system.
    1. Scenario: A company wants to analyze and gain insights into its expense data using SAP Concur.
    • Question: How would you use SAP Concur’s reporting and analytics capabilities to analyze expense data?
    • Answer: I would use SAP Concur’s reporting and analytics capabilities to create custom reports and analyze spending data. I would also set up expense rules to automatically flag and review expenses that exceed a certain dollar amount or do not comply with company policies. This would allow me to gain real-time insights into the company’s expenses and identify areas where cost savings can be made.
    1. Scenario: A company’s compliance department wants to use SAP Concur to ensure compliance with company policies and government regulations.
    • Question: How would you use SAP Concur’s compliance and audit features to ensure compliance with company policies and government regulations?
    • Answer: I would set up expense rules to automatically flag and review expenses that do not comply with company policies or government regulations. I would also use SAP Concur’s real-time compliance alerts to notify the compliance department of any potential issues. Additionally, I would provide the compliance department with access to SAP Concur’s built-in compliance reporting capabilities so that they can easily review and audit expenses.
  • How to Integrate ChatGPT in SAP ABAP

    Introduction

    A general idea of how to integrate ChatGPT with SAP ABAP:

    1. First, you would need to have access to an instance of the ChatGPT model, either through the OpenAI API or by running the model locally.
    2. Next, you would need to create an ABAP program that calls the ChatGPT API and passes it input text, such as a user’s question.
    3. The program would then need to handle the API response and parse the generated text output.
    4. Finally, the program would need to display the generated text in an appropriate format, such as in an SAP GUI screen or in an output file.

    Here’s an example of some code that could be used in an ABAP program to call the OpenAI API and get a response from ChatGPT:

    CALL FUNCTION 'HTTP_POST'
      EXPORTING
        url = 'https://api.openai.com/v1/engines/davinci/completions'
        encoding = 'UTF-8'
      IMPORTING
        response = l_response
      CHANGING
        data = l_data
        headers = l_headers
      EXCEPTIONS
        http_communication_failure = 1
        http_invalid_state = 2
        http_processing_failed = 3
        OTHERS = 4.
    

     

    How to Integrate ChatGPT in SAP ABAP

    As shown in below image, we will follow three simple steps to integrate ChatGPT APIs within SAP ABAP Report.

    Integrate ChatGPT in SAP ABAP

    1. Get API of Open AI

    We have already discussed all the steps involved regarding API creation in this article.

    2. Create ABAP Report

    Go to SE38, and create a new ABAP Report. Create one Input Parameter as shown below:

    ChatGPT ABAP Report

    3. Integrate ChatGPT Call

    Write the given code in your report:

    REPORT ZCHATGPT.
    
    PARAMETERS: l_ques type string.
    
    data: l_response type string,
          l_data type string,
          lv_payload_x type xstring,
          l_max_tokens type i.
    
    "l_ques = 'What is the meaning of life?'. EXAMPLE
    l_max_tokens = 50.
    l_data = '{' && '"prompt":' && '"' && l_ques && '",' && '"max_tokens":' && l_max_tokens && '}'.
    
    CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
    EXPORTING
    text = l_data
    IMPORTING
    buffer = lv_payload_x.
    
       DATA: lo_http_client TYPE REF TO if_http_client.
        DATA: response TYPE string,
              lv_auth  TYPE string.
        CONSTANTS : lv_url TYPE string VALUE 'https://api.openai.com/v1/engines/davinci/completions'.
    
    
          "create HTTP client by url
          CALL METHOD cl_http_client=>create_by_url
            EXPORTING
              url                = lv_url
            IMPORTING
              client             = lo_http_client
            EXCEPTIONS
              argument_not_found = 1
              plugin_not_active  = 2
              internal_error     = 3
              OTHERS             = 4.
    
          IF sy-subrc <> 0.
            "error handling
          ENDIF.
    
          "setting request method
          lo_http_client->request->set_method('POST').
    
          "adding headers
          lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/x-www-form-urlencoded' ).
          lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
          lo_http_client->request->set_header_field( name = 'Authorization' value = 'Bearer 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' ).
    
          lo_http_client->request->set_form_field(
      EXPORTING
        name  = 'prompt'                    " Name of form field
        value =   l_ques   ).
    
    
          "lo_http_client->request->set_data( lv_payload_x ).
    
          "Available Security Schemes for productive API Endpoints
          "OAuth 2.0
    
          CALL METHOD lo_http_client->send
            EXCEPTIONS
              http_communication_failure = 1
              http_invalid_state         = 2
              http_processing_failed     = 3
              http_invalid_timeout       = 4
              OTHERS                     = 5.
    
          IF sy-subrc = 0.
            CALL METHOD lo_http_client->receive
              EXCEPTIONS
                http_communication_failure = 1
                http_invalid_state         = 2
                http_processing_failed     = 3
                OTHERS                     = 5.
          ENDIF.
    
          IF sy-subrc <> 0.
            "error handling
            response = lo_http_client->response->get_cdata( ).
            l_response = response.
          ELSE.
            response = lo_http_client->response->get_cdata( ).
            IF response IS NOT INITIAL.
              l_response = response.
            ELSE.
              l_response = 'Call was successful, but got no response'.
            ENDIF.
          ENDIF.
    
    WRITE l_response.

     

    Code Explanation

    Here, I have added variables l_question and l_max_tokens to hold the user’s question and the maximum token value, respectively. I have then added these values to the l_data variable, which is passed as the data parameter in the HTTP_POST call. The response variable l_response will hold the generated text as a result of the API call.

    Here, I have created an object of class if_http_client and added the headers using the add_header_field method. Then i have passed this object as a parameter ‘manager’ in the ‘HTTP_POST’ call.

    It’s important to note that the format of the data passed to the OpenAI API must be in JSON format, so that’s why I have added the prompt and max_tokens in JSON format in the l_data variable.

    Remember to replace <YOUR_API_KEY> with the API key that you have generated using the Open AI platform.

    Output Screen

    Chat GPT integration with SAP ABAP

    Tutorial Video

    You can watch the video below to learn implementation:

    [embedyt] https://www.youtube.com/watch?v=VvEO2MDpdAc[/embedyt]
  • How to Integrate ChatGPT in SAP UI5

    Preface – This post is part of the UI5 Integration Programs series.

    Introduction

    It is not possible to directly integrate ChatGPT using a CDN (Content Delivery Network) as GPT-3 model is not hosted on any public CDN. GPT-3 is a proprietary model owned by OpenAI, and access to it is provided through the OpenAI API, which requires an API key to use.

    You can use the OpenAI API in your JavaScript application by making HTTP requests to the API endpoint and using the API key. The OpenAI API provides a prompt endpoint that allows you to send a prompt to GPT-3 and receive a response.

    Here’s an example of how you might use the fetch API in JavaScript to send a prompt to GPT-3 and log the response:

    const API_KEY = 'YOUR_API_KEY';
    const prompt = 'What is the meaning of life?';
    
    fetch(`https://api.openai.com/v1/engines/davinci/completions`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${API_KEY}`
        },
        body: JSON.stringify({
            prompt,
            max_tokens: 20
        })
    }).then(response => response.json())
        .then(data => {
        console.log(data.choices[0].text);
    });
    

    How to Integrate ChatGPT in SAP UI5

    As shown in below image, we will follow three simple steps to integrate ChatGPT APIs within SAP UI5 App.

    How to Integrate ChatGPT in SAP UI5

    1. Get API of Open AI

    We have already discussed all the steps involved regarding API creation in this article.

    2. Create UI5 Project

    Use Web IDE or SAP BAS and generate a simple UI5 Application using a generator.

    3. Integrate ChatGPT Call

    We have create a very simple view with input box, button and a text area to show output as shown in below view:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Get Answers from ChatGPT">
                        <content>
                            <VBox>
                                <Input id="idInput"/>
                                <Button text="Get Answer" press="onPressGPT"/>
                                <Text id="idText"/>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    And on the press of Button, we have written the given code in controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
    
            },
    
            onPressGPT: function () {
                var that = this;
                const API_KEY = '';
                var prompt = this.byId("idInput").getValue();
                fetch(`https://api.openai.com/v1/engines/davinci/completions`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': `Bearer ${API_KEY}`
                        },
                        body: JSON.stringify({
                            prompt,
                            max_tokens: 2000
                        })
                    }).then(response => response.json())
                    .then(data => {
                        that.byId("idText").setText(data.choices[0].text);
                    });
            }
        });
    });

    Output

    The Output without pressing the button looks like this:

    UI5 ChatGPT output view

  • Call Transaction Method in SAP BDC

    Introduction

    A Call transaction is a very simple report program. Once you execute and come out of the program, there is no log to cross check.

    Syntax:

    CALL TRANSACTION <transaction code> USING <it_bdcdata>
    MODE ‘A/E/N’
    UPDATE ‘A/S/L’
    MESSAGE INTO <it_msg_details>.

    Here, it_bdcdata represents the internal table that has instructions for one time execution of the t-code. This is the same table that we discussed in the section “SAP BDC Technical Details”. So, this internal table at one moment will hold instructions for only one record.

    Here, we have three different options for MODE. The modes determine the control over screen display.

    • A: It means, while execution of the program, all screens will be displayed. It is best suited for testing purpose as it is a foreground testing.
    • N: It means, while execution of the program, no screens will be shown even in case of success or error. This is best suited for production execution as it is a background job.
    • E: It means, the screens with message will be displayed every time there is an error. This is also used for testing purpose, in case SY-SUBRC fails for method N, and you are not able to identify the position of error.

    Here, we have three different options for UPDATE. The update command signifies Create, Update and delete operation over table/database. And, this UPDATE command provided the control over the sequence of database operations. Like, if data will be saved for all external file one by one, or in parallel.

    • A: It means Asynchronous. It means irrespective of the face that first set of data was processed and data was being saved in db, the next round of data process will start and not wait for the completion of first. This also means for large amount of data, the speed of the program will be faster in this mode. But, also there is a very rare chance of getting errors.
    • S: It means Synchronous. It means, every time the command CALL TRANSACTION is executed, until the data is saved in table and a success SY-SUBRC comes, it will not execute the CALL TRANSACTION for the next set of data. It is preferred in Production mode, as it is error free (Although slower).
    • L: It means Local. This is the command which signifies that the update for entire data (whole excel or csv or txt) will be executed at once, in the end, and only after the “COMMIT WORK” statement. The use case for Local Update or Update Function Module is where you either want all data to updated or none. The best use case is updating header and detail, and if detail or header fails, none of these tables will be updated. You can read more about it here.

    Here, it_msg_details saves all the messages that are produced over the screen (success, warning, information or error).

    Call Transaction Method Flow

    As you can see in the above design flow, the excel will be converted into internal table, and then BDC Codes (CALL TRANSACTION) will be called where <it_bdcdata> will be in form of BDCDATA format with various fields such as Program, DYNPRO, etc including field and value holding data of first row of the excel. Once the database process completes, the next data of the excel will be processed and so on.

    Steps to upload data in SAP system using BDC

    To understand the above process, we will show case a simple example where we will:

    1. Create multiple tables for Employee Data that can be created using a report.

    We have created these tables: zBarry_emp (for employee basic information), zBarry_sal (for employee Salary information) and zBarry_add (for employee address details). The fields are as shown below:

    zBarry_emp

    Field Name Field Type
    EMPID (Key) INT4
    FNAME CHAR20
    LNAME CHAR20
    PHONE CHAR20

    zBarry_sal

    Field Name Field Type
    EMPID (Key) INT4
    SALARY CHAR20

    zBarry_add

    Field Name Field Type
    EMPID (Key) INT4
    CITY CHAR20
    PIN CHAR20
    STATE CHAR20
    COUNTRY CHAR20

    2. The report will be able to take many fields as input.

    Now, we will create a report ZBARRYEMP_REPORT to take multiple inputs via screen and save them in the above tables. The code of the same is shown below:

    REPORT ZBARRYEMP_REPORT.
    Data: ls_emp type ZBARRY_EMP,
          ls_sal type zbarry_sal,
          ls_add type zbarry_add,
          lv_MSG type char20.
    
    PARAMETERS: p_empid TYPE int4,
    p_fname type char20,
    p_lname type char20,
    p_phone type char20,
    p_salary type char20,
    p_city type char20,
    p_pin type char20,
    p_state type char20,
    p_con type char20.
    
    " mapping for Employee Info
    ls_emp-empid = p_empid.
    ls_emp-fname = p_fname.
    ls_emp-lname = p_lname.
    ls_emp-phone = p_phone.
    
    
    " mapping for Employee Salary
    ls_sal-empid = p_empid.
    ls_sal-salary = p_salary.
    
    " mapping for Employee Address
    ls_add-empid = p_empid.
    ls_add-city = p_city.
    ls_add-pin = p_pin.
    ls_add-state = p_state.
    ls_add-country = p_con.
    
    " SQL Operations.
    INSERT ZBARRY_EMP FROM ls_emp.
    If Sy-subrc = 0.
    lv_MSG = 'Create is successful'.
    else.
      lv_MSG = 'Create Failed'.
           Endif.
    
     INSERT ZBARRY_sal FROM ls_sal.
    If Sy-subrc = 0.
    lv_MSG = 'Create is successful'.
    else.
      lv_MSG = 'Create Failed'.
           Endif.
    
      INSERT ZBARRY_add FROM ls_add.
    If Sy-subrc = 0.
    lv_MSG = 'Create is successful'.
    else.
      lv_MSG = 'Create Failed'.
           Endif.
    
           if lv_MSG EQ 'Create Failed'.
             MESSAGE lv_MSG TYPE 'E' DISPLAY LIKE 'E'.
               ENDIF.

     

    Output:

    ABAP Report for BDC

    3. Then, we will create a t-code for our report.

    We will create a T-code “ZMYTCODE” using SE93 for our report “ZBARRYEMP_REPORT”.

    Tcode for BDC

    Steps to Record a transaction code using BDC

    4. Thereafter, we will run a BDC recording (using T-Code SHDB) and get BDCDATA from that recorder.

    Step 1. Go to t-code SHDB and click on “New Recording”

    SHDB New Recording

    Step 2: Provide T-Code, any name for recording and set update mode as “Synchronous”.

    Create Recording SHDB

    Step 3: It will open your Report. Now, provide all the data, and press execute.

    BDC Recorder

    Now click, back to see your BDCDATA, for our example it looks like this:

    INDEX PROGRAM DYNPRO DYNBEGIN FNAM FVAL
    1 T ZMYTCODE
    2 ZBARRYEMP_REPORT 1000 X
    3 BDC_CURSOR P_CON
    4 BDC_OKCODE =ONLI
    5 P_EMPID 12
    6 P_FNAME Rudra
    7 P_LNAME Pandey
    8 P_PHONE 99999999
    9 P_SALARY INR 9999999
    10 P_CITY Mughalsarai
    11 P_PIN 232101
    12 P_STATE Uttar Pradesh
    13 P_CON India
    14 ZBARRYEMP_REPORT 1000 X
    15 BDC_OKCODE /EE
    16 BDC_CURSOR P_EMPID

    Now, here you can see that all our entered data is also recorded in the recording.

    Here BDC_OKCODE “=ONLI” is for our “Execute” button, and BDC_OKCODE = “/EE” is showcasing that we pressed back. We will use the code until we press execute.

    You can test your recording by clicking “Process” button:

    Test BDC

    While testing, do change data with a new set. Before exiting, you must save your recording.

    Steps to Create a BDC Program

    5. Now, we will create a program that accepts excel input and convert that excel into an internal table.

    Step 1: Create a new ABAP report “ZBARRYEMP_BDC” using t-code SE38.

    Step 2: Create the following:

    • local structure of type “bdcdata” where we will map our excel data with bdcdata that we recorded earlier
    • local internal table of type “bdcdata” where we will push our local structure that we have created above
    • local structure and internal table of type “bdcmsgcoll” where we will save the message for every call that we make to the recording
    • local internal table and local structure to hold excel data that we will upload

    We have created the following:

    REPORT ZBARRYEMP_BDC.
    " local structure with combined fields of emp table, salary table and address table
    TYPES: BEGIN OF ls_emp,
      empid type INT4,
      fname type char20,
      lname type char20,
      phone type char20,
      salary type char20,
      city type char20,
      pin type char20,
      state type char20,
      country type char20,
      END OF ls_emp.
    
    DATA: ls_bdcdata TYPE bdcdata,
          ls_msg type bdcmsgcoll.
    
    DATA: lt_bdcdata TYPE TABLE OF bdcdata,
          lt_bdcmsg TYPE TABLE OF bdcmsgcoll,
          lt_bankdata TYPE TABLE OF ls_emp.

     

    Step 3: Now, we will import the excel data using Function Module ‘TEXT_CONVERT_XLS_TO_SAP’ and push it to our internal table it_empdata. You can read more about Excel upload in ABAP here.

    " Uploading Excel and converting it into Interna Table
    TYPE-POOLS truxs.
    PARAMETERS p_file TYPE rlgrap-filename.
    
    DATA : t_upload  TYPE STANDARD TABLE OF ls_emp,
           wa_upload TYPE ls_emp,
           it_type   TYPE truxs_t_text_data.
    
    AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
      CALL FUNCTION 'F4_FILENAME'
        EXPORTING
          field_name = 'p_file'
        IMPORTING
          file_name  = p_file.
    
    START-OF-SELECTION.
      CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
        EXPORTING
          i_tab_raw_data       = it_type
          i_filename           = p_file
        TABLES
          i_tab_converted_data = t_upload[]
        EXCEPTIONS
          conversion_failed    = 1
          OTHERS               = 2.
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 .
      ENDIF.
    
    END-OF-SELECTION.

     

    Step 4: Now in a loop we will keep pushing the bdcdata parameters that is

    • PROGRAM, DYNPRO, DYNBEGIN: These will remain constant for one screen (in our case, constant for whole program as we have only one screen). These will be taken from the BDCDATA that we have generated i.e.
    ZBARRYEMP_REPORT 1000 X
    • FNAM, FVAL: These will hold the key and values (In our case, the keys are the parameters that we used for input in our ABAP report “ZBARRYEMP_REPORT” while the values will be taken from excel upload.
    • The first two fields for a screen are always BDC_CURSOR  and BDC_OKCODE.  The value can be retrieved from the generated BDCDATA. In this case, the values are ‘P_CON ‘ and ‘=ONLI’, respectively.

     

    Step 5: Once the values are taken as per BDCDATA structure, we call the “CALL TRANSACTION” statement. These entire statements will be looped until the operation finishes for the entire excel data.

    The syntax for CALL TRANSACTION is:

    CALL TRANSACTION <transaction code> USING <it_bdcdata>
    MODE ‘A/E/N’
    UPDATE ‘A/S/L’
    MESSAGES INTO <it_msg_details>.

     

    For our example, the above value will become:

    CALL TRANSACTION ‘ZMYTCODE’ USING lt_bdcdata
    MODE ‘N’
    UPDATE ‘S
    MESSAGES INTO lt_bdcmsg.

     

    Step 6: Now upload an excel file with the given format. In our example, we have an excel as shown below:

    Excel format BDC

    Note: Do not include the header. The excel should look like this:

    Excel with Data for BDC

    Once you are done with the ABAP Changes, then run the report, upload the excel file and once the ABAP Report executes, check the table to see if all the records are uploaded or not.

    ABAP Code for BDC Program

    REPORT ZBARRYEMP_BDC.
    " local structure with combined fields of emp table, salary table and address table
    TYPES: BEGIN OF ls_emp,
      empid type int2,
      fname type char20,
      lname type char20,
      phone type char20,
      salary type char20,
      city type char20,
      pin type char20,
      state type char20,
      country type char20,
      END OF ls_emp.
    
    DATA: ls_bdcdata TYPE bdcdata,
          ls_msg type bdcmsgcoll.
    
    DATA: lt_bdcdata TYPE TABLE OF bdcdata,
          lt_bdcmsg TYPE TABLE OF bdcmsgcoll,
          lt_empdata TYPE TABLE OF ls_emp.
    
    " Uploading Excel and converting it into Interna Table
    TYPE-POOLS truxs.
    PARAMETERS p_file TYPE rlgrap-filename.
    
    DATA : t_upload  TYPE STANDARD TABLE OF ls_emp,
           wa_upload TYPE ls_emp,
           it_type   TYPE truxs_t_text_data.
    
    AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
      CALL FUNCTION 'F4_FILENAME'
        EXPORTING
          field_name = 'p_file'
        IMPORTING
          file_name  = p_file.
    
    START-OF-SELECTION.
      CALL FUNCTION 'TEXT_CONVERT_XLS_TO_SAP'
        EXPORTING
          i_tab_raw_data       = it_type
          i_filename           = p_file
        TABLES
          i_tab_converted_data = t_upload[]
        EXCEPTIONS
          conversion_failed    = 1
          OTHERS               = 2.
      IF sy-subrc <> 0.
        MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 .
      ENDIF.
    
      " Loop the above table t_upload[] data until all data is uploaded via BDC
      LOOP AT t_upload into wa_upload.
    * Screen 1 - Field 1 is always BDC_CURSOR
    ls_bdcdata-PROGRAM = 'ZBARRYEMP_REPORT'.
    ls_bdcdata-DYNPRO = '1000'.
    ls_bdcdata-DYNBEGIN = 'X'.
    ls_bdcdata-fnam = 'BDC_CURSOR'.
    ls_bdcdata-fval = 'P_CON'.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 2 - Always BDC_OKCODE
    ls_bdcdata-fnam = 'BDC_OKCODE'.
    ls_bdcdata-fval = '=ONLI'.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 3
    ls_bdcdata-fnam = 'P_EMPID'.
    ls_bdcdata-fval = wa_upload-empid.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 4
    ls_bdcdata-fnam = 'P_FNAME'.
    ls_bdcdata-fval = wa_upload-fname.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 5
    ls_bdcdata-fnam = 'P_LNAME'.
    ls_bdcdata-fval = wa_upload-lname.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 6
    ls_bdcdata-fnam = 'P_PHONE'.
    ls_bdcdata-fval = wa_upload-phone.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 7
    ls_bdcdata-fnam = 'P_SALARY'.
    ls_bdcdata-fval = wa_upload-salary.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 8
    ls_bdcdata-fnam = 'P_CITY'.
    ls_bdcdata-fval = wa_upload-city.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 9
    ls_bdcdata-fnam = 'P_PIN'.
    ls_bdcdata-fval = wa_upload-pin.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 10
    ls_bdcdata-fnam = 'P_STATE'.
    ls_bdcdata-fval = '=ONLI'.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    
    * Screen 1 - Field 10
    ls_bdcdata-fnam = 'P_CON'.
    ls_bdcdata-fval = wa_upload-country.
    APPEND ls_bdcdata to lt_bdcdata.
    CLEAR ls_bdcdata.
    ENDLOOP.
    
    "Call BDC Transaction
    CALL TRANSACTION 'ZMYTCODE' USING lt_bdcdata MODE 'A' UPDATE 'S' MESSAGES INTO lt_bdcmsg.
    CLEAR lt_bdcdata.
    
    END-OF-SELECTION.

     

    Output

    BDC Program Output

  • BDC (Batch Data Communication) in SAP ABAP: Complete Guide

    Introduction

    In SAP environment, suppose you need to upload a data from an external source like an excel sheet. You have a program for the upload already in the system. You will therefore, visit the program or transaction, and then simply open the file location, upload the file, check for errors and that’s it.

    Therefore, these will be the steps that you will follow for a file upload. Suppose, you have Ten Thousand files to be uploaded via the same program. Wouldn’t it be a tedious job? SAP knew it, and hence created something called SAP BDC, which records your upload steps and automatically replicate it for next sets or batches of data. In this article, we will learn everything about SAP BDC with simple examples.

    What is BDC – Batch Data Communication in SAP ABAP?

    SAP BDC stands for Batch Data Communication. It was renamed by SAP to Batch Input, about 20 years ago. Still, the famous name i.e. BDC is used to refer it.

    In terms of definition, Batch Input or BDC are the sets of methods provided by SAP to transfer/migrate data from other SAP or Non SAP Systems.

    Why we need BDC?

    We need Batch Input of BDC for the following reasons:

    1. Data conversion or migration from Non SAP systems (e.g. csv, excel, text) to SAP Systems (e.g. SAP Table). It mostly happen for a new development (Master Data Migration) and SAP Upgradation.

    BDC Process Flow

    2. Automate daily tasks of a user. If the daily task of user is to upload data from a 3rd party to SAP System via T-Code.

    SAP BDC Design

    If you are asked to upload a set of data into database, in single table, you would quickly create a report, with file uploader, and use SQL to push that data into required table. But, if you are asked to upload hundred columns of data into tons of tables, based upon various conditions, based upon a T-Code, then it will be a tedious job.

    BDC solves our problem, by cutting our second task. Our part is to just push the excel until the transaction screen, and the rest is taken care.

    In below image, the usual case would be that you will open a t-code, enter required input and click save. In case of BDC, it creates recording of your upload process and give you the code of the recording. Using the provided code, you can create a program to upload excel and pass the data to that BDC recoded code, and the rest is taken care automatically.

    BDC Design

    SAP BDC Technical Details

    Every time you record your screen, a few fields are auto generated (called BDCDATA) as below:

    • Program Name (PROGRAM): The name of program for the transaction
    • Screen Number (DYNPRO): The screen number is auto generated
    • Field Name (s) [FNAM]: The field name for which value was provided. In case of multiple field, it will be repeated
    • Field Value (s) [FVAL]: For all the above fields, the entered value is recorded here
    • OK Code [BDC_OKCODE]: The event that occurred during recording. Either you pressed Enter or Clicked a button, the code for the same will be captured here
    • DYNBEGIN: This indicates that the new screen has started
    • BDC_CURSOR: It saves the current position of the cursor

    A common example based upon above structure is shown below:

    INDEX PROGRAM DYNPRO DYNBEGIN FNAM FVAL
    1 SAPMM07M 400 X
    2 BDC_CURSOR RM07M-LGORT
    3 BDC_OKCODE /00
    4 MKPF-BLDAT 22.12.2022
    5 MKPF-BUDAT 22.12.2022
    6 RM07M-BWARTWA 413
    7 RM07M-WERKS 2010
    8 RM07M-LGORT HRSL
    9 RM07M-WVERS2 X
    10 SAPMM07M 410 X
    11 BDC_CURSOR MSEG-UMLGO
    12 BDC_OKCODE /00
    13 MSEG-MATNR SLBW
    14 MSEG-ERFMG 20
    15 MSEG-ERFME to
    16 MSEG-WERKS 2010
    17 MSEG-LGORT HRSL
    18 MSEG-CHARG A693264
    19 MSEG-UMLGO HRSL

    You do not have to understand the above code, just check the field names discussed before and how they appear in the BDCDATA generated. You can even check the structure “BDCDATA” in SE11. Also, you can check another SE11 structure BDCMSGCOLL which is used for Collecting messages in the SAP System.

    Note: The recording by SHDB that we will discuss later is a client dependent process, and it has to be saved as a local file in desktop and has to be uploaded the same in to other systems.

    SAP BDC Transaction Codes (Tcode)

    The following T-Codes are used with respect to BDC or Batch Input:

    T-Code Use
    SM35 It is used to run Batch Input Sessions
    SHDB It is used to record a BDC (Batch Input) Session
    BDCUPDATE It is used to check updates in Batch Input

     

    Apart from these, you can find all other relevant T-Codes here.

    Methods of Batch Input or Types of BDC Call

    Now, we have a basic idea of BDC and its terminologies. Now, we will learn how to start with a BDC process. There are two different ways of doing the same. These are:
    1. Call Transaction Method
    2. Classical Batch Input Method or BDC Session Method

    We have discussed each individually in a different article (click them) and created respective programs.

    Error handling in SAP BDC

    There are many reasons due to which your BDC might fail; we will discuss a few issues and errors that are very generic to BDC.

    Important Guidelines for SAP BDC

    Following are the important guidelines in terms of SAP BDC:

    • BDC works by executing t-codes using data uploaded, hence all the data and logic validations are not done in BDC programs but are done in individual t-codes (the reports running behind those t-codes).
    • BDC is suitable for very large amount of data.
    • BDC should be tested in mode A and E, and should be deployed in production in mode N.
    • For different screens you must update the DYNPRO number, else the program will fail.
    • Every time you press enter or click, it is recorded in the BDCDATA. You should write code for every event in your BDC Program.

    Why BDC is not recommended

    BSC is closely associated with screens and t-codes. Every new release of a product in SAP, there might be chance of enhancing the screen; hence making the old BDC becomes non-applicable. Hence, BDC is not recommended for longer run.

    Alternative to SAP BDC

    The alternative to SAP BDC is SAP BAPI. There are several BAPIs that can replace the data transfer of a particular transaction. Even SAP recommends using BDC only in case there are no BAPIs for a t-code.

  • Using models.js in SAP UI5 (to maintain all Global Models)

    Preface – This post is part of the UI5 Programs series.

    What is model.js file in SAP UI5?

    A model in terms of UI5 is a set of data (mostly in JSON format) that can be binded with elements of UI5. For different properties of different elements, the type of model data differs, for example:

    • For the property “visible” of a button, the required model (Data within the model) should be either true or false
    • For the property “text” of a button, the required model (Data within the model) should be a string
    • For the data of the table, the required model should be a JSON data
    • For the data of Drop down, the required model should be JSON data [where one field should act as a key and another as value]
    • For the data of Table count that is shown next to the table name [Example User(90)], the required model (Data within the model) should be a numeric
    • For the data of a Form, the required model should be an Object [with multiple keys and values, where each key will be an element of the form]
    • In case you need to transfer login details to multiple pages, the required model should be an Object [where the key-value pair will save ID and hashed session password/data]

    The model.js in SAP UI5 is a dedicated file to save multiple global variables that can hold data (commonly known as a model) as per requirement.

    The model data refreshes to initial values every time the browser is refreshed; hence it is recommended not to save any data that is required not to be lost during browser refresh.

    The layout of the model.js looks something like this in the folder structure:

    model.js file

    Setting up a Global Model using model.js file in SAP UI5

    There are three steps to using a Global Model.

    1. Create a model object in Model.js file

    The first step is to create a model in model.js file. The model.js file is already created within the model folder of webapp. In case their is no such file, create a file, name it “model.js” with given content:

    sap.ui.define([
        "sap/ui/model/json/JSONModel",
        "sap/ui/Device"
    ], function (JSONModel, Device) {
        "use strict";
    
        return {
    
            createDeviceModel: function () {
                var oModel = new JSONModel(Device);
                oModel.setDefaultBindingMode("OneWay");
                return oModel;
            }
    
        };
    });

    Now, we will add our own code within this file. Let us call it “createAppConfigModel” with given data:

    //app Congiguration model
    createAppConfigModel: function () {
        var appData = {
            "editable": false,
            "count": 0,
            "formData": {},
            "tableData": []
        };
        var oModel = new JSONModel(appData);
        return oModel;
    }

    Now, your Model.js will look like this:

    sap.ui.define([
        "sap/ui/model/json/JSONModel",
        "sap/ui/Device"
    ], function (JSONModel, Device) {
        "use strict";
    
        return {
    
            createDeviceModel: function () {
                var oModel = new JSONModel(Device);
                oModel.setDefaultBindingMode("OneWay");
                return oModel;
            },
            //app Congiguration model
            createAppConfigModel: function () {
                var appData = {
                    "editable": false,
                    "count": 0,
                    "formData": {},
                    "tableData": []
                };
                var oModel = new JSONModel(appData);
                return oModel;
            }
    
        };
    });

     

    2. Configure the Component.js file for the Global Model Object

    In the Component.js file, in case your Model.js file was already there, the model configuration is added like this:

    sap.ui.define([
        "sap/ui/core/UIComponent",
        "sap/ui/Device",
        "YRR/YRR/model/models"
    ], function (UIComponent, Device, models) {
        "use strict";
    
        return UIComponent.extend("YRR.YRR.Component", {
    
            metadata: {
                manifest: "json"
            },
    
            /**
             * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
             * @public
             * @override
             */
            init: function () {
                // call the base component's init function
                UIComponent.prototype.init.apply(this, arguments);
    
                // enable routing
                this.getRouter().initialize();
    
                // set the device model
                this.setModel(models.createDeviceModel(), "device");
    
    
            }
        });
    });

    Here, the model file location is added at the top as “YRR/YRR/model/models” and thereafter in the end the default model is configured using this ” this.setModel(models.createDeviceModel(), “device”);”

    We need to add one more configuration, for our model with this code: “this.setModel(models.createAppConfigModel(), “AppConfig”);”

    Now, the code will look like this:

    sap.ui.define([
        "sap/ui/core/UIComponent",
        "sap/ui/Device",
        "YRR/YRR/model/models"
    ], function (UIComponent, Device, models) {
        "use strict";
    
        return UIComponent.extend("YRR.YRR.Component", {
    
            metadata: {
                manifest: "json"
            },
    
            /**
             * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
             * @public
             * @override
             */
            init: function () {
                // call the base component's init function
                UIComponent.prototype.init.apply(this, arguments);
    
                // enable routing
                this.getRouter().initialize();
    
                // set the device model
                this.setModel(models.createDeviceModel(), "device");
    
                // set the app Config model
                this.setModel(models.createAppConfigModel(), "AppConfig");
    
            }
        });
    });

    That’s it, and we have a global model now.

    3. Using the model in view or Controller

    Now, we can easily access the model in view and controller. Also, we can manipulate the model from the controller.

    How to fetch and change values of a Global Model in SAP UI5?

    To fetch a global model, we need to call the model configuration with the model name we want to access or modify. Let’s assume you need to access the model “count” whose initial value is set as 0.

    var localCount = this.getOwnerComponent().getModel("AppConfig").getProperty("/count");

    The variable “localCount” will now have the value of 0.

    To change the value, we need to call the model configuration with the model name we want to modify. Let’s assume you need to modify the model “count” with a new value as 90.

    this.getOwnerComponent().getModel("AppConfig").setProperty("/count", 90);
    

    In the above step, we have updated the value of the count in the global model.

    How to use Global Model to send values from one page to another?

    To send values from one page to another, you need to perform these steps:

    1. Create a field in the global model that will be used to transfer data

    2. Update the value of the model on the first page, then navigate to the second page

    3. On the second page, get the value of the model

    All these steps are already discussed above in different sections.

    How to bind the global model directly to View?

    To bind a global model directly to the view, you need to perform the following as per the given use cases:

    1. Bind Global Model to a Button Text

    <Button icon="sap-icon://accept" visible="true" text="{AppConfig>/ButtonText}" 
    type="Accept" class="sapUiTinyMarginEnd" press="onAccept"/>

    In this example, we have assumed that the ButtonText is a field in the model having the text value of Button.

    2. Bind Global Model to the visibility of a button

    <Button visible="{=${AppConfig>/OrderType} === 'PO Release' ? true : false}" text="Okay" press="onReleasePO"/>
    <Button visible="{=${AppConfig>/OrderType} === 'Cancel PO Release' ? true : false}" text="Okay" press="onCancelReleasePO"/>

    In this example, Button 1 gets visible if the OrderType has the value ‘PO Release’, else becomes invisible.
    And Button 2 gets visible if the OrderType has the value ‘Cancel PO Release’, else becomes invisible.
    In this way, we can control the visibility of a button based on OrderType with the help of the Global Model.

    3. Bind Global Model to a table [if Model is JSON]

    It is important to have the Model that is being planned to bind with a table to have a format as below:

    {results: [{<JSON Data>}]};

    It means if your model has just an array of data in this form: [{<JSON Data>}] or {“results”: {JSON Data}}
    in both cases, the model binding will fail.

    Controller Code:

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
    
            },
    
            onBeforeRendering: function () {
                var that = this;
                var val = {
                    country_code: 1,
                    country_text: "India"
                };
                var aData = [];
                aData.push(val);
                that.getOwnerComponent().getModel("AppConfig").setProperty("/tableData", {
                    "results": aData
                });
            }
        });
    });

    View Code:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Table Binding">
                        <content>
                            <Table id="idTable" items="{AppConfig>/tableData/results}">
                                <columns>
                                    <Column><Text text="Country Code"/></Column>
                                    <Column><Text text="Country Text"/></Column>
                                </columns>
                                <items>
                                    <ColumnListItem>
                                        <cells>
                                            <Text text="{AppConfig>country_code}"/>
                                            <Text text="{AppConfig>country_text}"/>
                                        </cells>
                                    </ColumnListItem>
                                </items>
                            </Table>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Output:

    Bind Global Model to a table

    4. Bind Global Model to a drop-down [if Model is JSON]

    This process is very much similar to the table code (in the above step). We will use the same controller code but change the view code.

    Controller Code:

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
    
            },
    
            onBeforeRendering: function () {
                var that = this;
                var val1 = {
                    country_code: 1,
                    country_text: "India"
                };
                var val2 = {
                    country_code: 2,
                    country_text: "Germany"
                };
                var aData = [];
                aData.push(val1);
                aData.push(val2);
                that.getOwnerComponent().getModel("AppConfig").setProperty("/tableData", {
                    "results": aData
                });
            }
        });
    });

     

    View Code:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Select a Drop Down">
                        <content>
                            <Select id="idCountrySelect" width="90%" showSecondaryValues="true" items="{AppConfig>/tableData/results}">
                                <core:ListItem key="{AppConfig>country_code}" text="{AppConfig>country_text}"/>
                            </Select>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Output:

    Bind Global Model to a drop-down [if Model is JSON]

    5. Bind Global Model to a form [if Model is an Object]

    The right way to bind a model to a form should be JSON Model binding with the form with the help of form ID. In this example, we will be binding directly with the global model.

    Controller:

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
    
            },
    
            onBeforeRendering: function () {
                var val = {
                    fname: "Rudramani",
                    lname: "Pandey",
                    country: "India",
                    phone: "+91-9999099099"
                };
                this.getOwnerComponent().getModel("AppConfig").setProperty("/formData", val);
            }
        });
    });

     

    View:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Form Binding">
                        <content>
                            <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                                labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                                singleContainerFullSize="false">
                                <f:content>
                                    <core:Title text="Basic Info"/>
                                    <Label text="First Name"/>
                                    <Text text="{AppConfig>/formData/fname}"/>
                                    <Label text="Last Name"/>
                                    <Text text="{AppConfig>/formData/lname}"/>
                                    <Label text="Country"/>
                                    <Text text="{AppConfig>/formData/country}"/>
                                    <Label text="Mobile"/>
                                    <Text text="{AppConfig>/formData/phone}"/>
                                </f:content>
                            </f:SimpleForm>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Output:

    Bind Global Model to a form [if Model is an Object]

    6. Bind Global Model to a text [if Model is an Object]

    It will be exactly like the above. In case you are binding directly with a field then binding will be like:

    <Text text="{AppConfig>/phone}"/>

    In case you are binding the text with an object, and then you need to reach up to your field using ‘/’, like:

    <Text text="{AppConfig>/formData/phone}"/>

     

    7. Changing the Visibility of fields using the Global Model

    In this example, you can use Global Model to change the visibility of multiple fields. This example is exactly similar to Example 2.

    We will just add a condition to the above form, within the view:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Form Binding">
                        <content>
                            <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                                labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                                singleContainerFullSize="false">
                                <f:content>
                                    <core:Title text="Basic Info"/>
                                    <Label text="First Name"/>
                                    <Text text="{AppConfig>/formData/fname}"/>
                                    <Label text="Last Name"/>
                                    <Text text="{AppConfig>/formData/lname}"/>
                                    <Label text="Country"/>
                                    <Text visible="{=${AppConfig>/visible} === true ? true : false}" text="{AppConfig>/formData/country}"/>
                                    <Label text="Mobile"/>
                                    <Text visible="{=${AppConfig>/visible} === true ? true : false}" text="{AppConfig>/formData/phone}"/>
                                </f:content>
                            </f:SimpleForm>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    In case we make the global model field “visible” as true, then the form will load as usual:

    Bind Global Model to a form [if Model is an Object]

    In case, we will make it false, as shown below:

    sap.ui.define([
        "sap/ui/model/json/JSONModel",
        "sap/ui/Device"
    ], function (JSONModel, Device) {
        "use strict";
    
        return {
    
            createDeviceModel: function () {
                var oModel = new JSONModel(Device);
                oModel.setDefaultBindingMode("OneWay");
                return oModel;
            }, //app Congiguration model 
            createAppConfigModel: function () {
                var AppConfig = {
                    "editable": false,
                    "count": 0,
                    "formData": {},
                    "tableData": {},
                    "visible": false
                };
                var oModel = new JSONModel(AppConfig);
                return oModel;
            }
    
        };
    });

    Then the visibility of these two fields will be turned off:

    Changing the Visibility of fields using the Global Model

    In order to change the value of the global field “visible”, we will write the following code in the controller:

    this.getOwnerComponent().getModel("AppConfig").setProperty("/vsible", false);

     

    8. Making a form Editable and Non-Editable using the Global Model

    To toggle the form Editable and Non-editable, we add a field “editable” in the model, then change the same in the controller based upon the current state [if true, then change it to false and vice-versa] and thereafter bind the same in the editable field.

    Model File:

    sap.ui.define([
        "sap/ui/model/json/JSONModel",
        "sap/ui/Device"
    ], function (JSONModel, Device) {
        "use strict";
    
        return {
    
            createDeviceModel: function () {
                var oModel = new JSONModel(Device);
                oModel.setDefaultBindingMode("OneWay");
                return oModel;
            }, //app Congiguration model 
            createAppConfigModel: function () {
                var AppConfig = {
                    "editable": false,
                    "count": 0,
                    "formData": {},
                    "tableData": {},
                    "visible": false
                };
                var oModel = new JSONModel(AppConfig);
                return oModel;
            }
    
        };
    });

    Controller File:

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
    
            },
    
            onPressToggle: function () {
                var editable = this.getOwnerComponent().getModel("AppConfig").getProperty("/editable");
                if (editable) {
                    this.getOwnerComponent().getModel("AppConfig").setProperty("/editable", false);
                } else {
                    this.getOwnerComponent().getModel("AppConfig").setProperty("/editable", true);
                }
            }
        });
    });

    View File:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml" xmlns:l="sap.ui.layout" xmlns:f="sap.ui.layout.form">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Form Binding">
                        <content>
                            <VBox>
                                <Button text="Toggle Visibilty" press="onPressToggle"/>
                            <f:SimpleForm id="idSFormPlatesOvp" editable="false" layout="ResponsiveGridLayout" labelSpanXL="4" labelSpanL="4" labelSpanM="4"
                                labelSpanS="12" adjustLabelSpan="false" emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="3" columnsL="1" columnsM="1"
                                singleContainerFullSize="false">
                                <f:content>
                                    <core:Title text="Basic Info"/>
                                    <Label text="First Name"/>
                                    <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/fname}"/>
                                    <Label text="Last Name"/>
                                    <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/lname}"/>
                                    <Label text="Country"/>
                                    <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/country}"/>
                                    <Label text="Mobile"/>
                                    <Input editable="{=${AppConfig>/editable} === true ? true : false}" value="{AppConfig>/formData/phone}"/>
                                </f:content>
                            </f:SimpleForm>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

  • Using formatter.js in SAP UI5 (In View and Controller)

    Preface – This post is part of the UI5 Programs series.

    What is a formatter in UI5?

    A formatter in UI5 is a model that is created to store functions. Each function is used to format the data into a specific format. Generally, it is used to perform the following:

    • Format Data to a specific type (dd/mm/yyyy or something else)
    • Convert values from single character [‘X’, ”] to [Yes, No]
    • Convert values from single characters to icons
    • Format timestamp and time (DD.MM.YYYY:HH:MM:SS)
    • Format Decimal (from 3 decimals to 2 decimals)
    • Remove Decimal Zero (All zeroes after Decimal)
    • Remove leading zeroes from the number

    Guidelines for using formatter

    Formatter is treated just like another function and thus has the same guidelines that are followed by other functions:

    1. A formatter should always return something back
    2. A formatter should have preconditions to fail-safe the formating
    3. A formatter should not return invalid data that can dump the View binding
    4. A formatter should use i18n for all its hard-coded texts
    5. A formatter should be placed in the Model folder with the name “formatter.js”
    6. A formatter should have comments before every function determining the input parameters and output data information

    A blank formatter looks something like this:

    sap.ui.define([], function() {
        "use strict";
    
        return {
    // All your formatted functions like below
    /**
    * Returns Timestamp 
     * @public
     * @param {string} sValue the number string to be timestamp formatted
    * @returns {string} sValue in DD-MM-YYYY: HH:MM:SS
    */
    timestampUnit: function(sValue) {
                if (!sValue) {
                    return "";
                }
                var timestamp = new Date(sValue.seconds * 1000);
                return timestamp;
    },
    
        };
    
    });

     

    Making formatter Global to the Entire App

    To make your formatter Global to the entire app, you need to add it to the BaseController.js file. This will make it accessible to all other pages.

    Adding formatter in Controller

    To add a formatter to a controller file, you need to add it in the definition part and then make the field formatter global. The code is as below:

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "YRR/YRR/model/formatter",
    ], function (Controller, formatter,
        ) {
        "use strict";
    
        return BaseController.extend("YRR.YRR.controller.Main", {
    
            formatter: formatter,
            onInit: function () {
    
                                        }
        });
    });

    In the above code, you can see we defined the formatter and specified the exact location. And then, just above the onInit function, we have reassigned it to a global field.

    Using formatter in Controller

    Formatter functions are just like other functions and can be called or initiated with ‘this’ keywords.

    this.formatter.getLocalTime(<pass your field here>)

    In the above statement, this.formatter will call the formatter file. getLocalTime is the name of the function. <pass your fields here> is the placeholder for all the fields that your function ‘getLocalTime’ requires.

    Using formatter in View

    Passing one value in formatter

    To pass a single value in formatter, we replace the text binding with formatter binding, as shown below:

    <Text text="{ path : 'LineItem', formatter: '.formatter.removeZero' }"/>

    In the above code, the path is the field name that is used for binding. And the formatter has the name of the formatter file followed by the function name.

    Passing multiple values in formatter

    <Text text="{ parts : [{path: 'OrdQty'},{path: 'QtyConversion'}], formatter: '.formatter.calculateMultiply' }"/>
    

    In the above code, we have passed multiple values into our formatter using the object ‘parts’ which itself has multiple objects in the form of {path: ‘<field name>’}

    Examples of Formatter

    1. Get Local Time

    getLocalTime: function(sValue) {
                if (sValue) {
                    var dateString = sValue;
                    var year = +dateString.substring(0, 4);
                    var month = +dateString.substring(4, 6);
                    var day = +dateString.substring(6, 8);
                    var date = new Date(year, month - 1, day);
                    var months = ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"];
                    var todate = date.getDate();
                    var tomonth = date.getMonth();
                    var monthText = months[tomonth];
                    var toyear = date.getFullYear();
                    if (month < 10 && month > 0) {
                        month = '0' + month.toString();
                    }
                    if (todate < 10 && todate > 0) {
                        todate = '0' + todate.toString();
                    }
                    var original_date = todate + '.' + month + '.' + toyear;
                    if (original_date == '30.0.1899') {
                        return '';
                    } else {
                        return original_date;
                    }
                } else {
                    return "";
                }
            }

    2. Remove Leading Zeros

    removeZero: function(sValue) {
        if (sValue) {
            sValue = sValue.replace(/^0+/, '');
            return sValue;
        } else {
            return '';
        }
    }

    3. Remove Decimal Zeros

    removedecimalZero: function(sValue) {
        if (sValue) {
            sValue = parseInt(sValue);
            sValue = sValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
            if (sValue == '0') {
                return '0';
            } else {
                return sValue;
            }
    
        } else {
            return '0';
        }
    }

    4. Format Decimal Numbers

    formatDecimal: function(sValue) {
        if (sValue) {
            if (sValue == '0.000') {
                return '';
            } else {
                sValue = parseFloat(sValue).toFixed(2);
                return sValue;
            }
    
        } else {
            return '';
        }
    }

    5. Format Custom Icons

    customIcon: function(sValue) {
        if (sValue === "X") {
            return 'sap-icon://message-success';
        } else {
            return '';
        }
    }

    6. Formatting Currency

    This formatting is for adding commas ‘,’ as per currency type, and adding currency signs with numbers.

    currency: function(sValue) {
        if (sValue) {
            // Create our number formatter.
            var formatter = new Intl.NumberFormat('en-US', {
                style: 'currency',
                currency: 'SAR'
            });
    
            return (formatter.format(sValue)); /* $2,500.00 */
        } else {
            return '';
        }
    },

    7. Rounding a Number

    roundNum: function(sValue) {
            if (sValue) {
                sValue = parseFloat(sValue).toFixed(2);
                sValue = Math.round(sValue);
                sValue = sValue.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
                return sValue;
            } else {
                return '';
            }
        },

     

  • Using i18n.properties in SAP UI5 (View, Controller, Adding comment in i18n)

    Preface – This post is part of the UI5 Programs series.

    What is i18n?

    i18n, which stands for internationalization, are Translatable Texts, all in a single place. It means a developer should keep all the texts of their app within i18n so that, in case it is required to have another version of the app with a different language, then all together, a copy of i18n can be made, and those texts can be converted into another language at once.

    Suppose you have only one version that too in English; then you just need a single i18n file. In case you have multiple languages like English (Britsh and US separate), German and French. Then you will need to have these i18n files:

    • i18n.properties [default]
    • i18n_en.properties [for English – British]
    • i18n_en_US.properties [for English – US]
    • i18n_de.properties [for German]
    • i18n_fr.properties [for French]

    Once you create these files, you need to add them in Manifest as a resource bundle. Then, within a controller, you need to use them as per the language of the browser. You can also provide your own language switcher drop-down like this:

    Language Switcher

    In case the app is deployed over Fiori, and then you can take the language set within Fiori:

    Fiori Language Settings

    Guidelines of writing i18n

    You can write the entire i18n file in the form of key= value as shown below, where the key will be then added overview and controller, and the value will be the one shown over UI.

    title=Admin Panel
    appTitle=Admin Panel
    appDescription=Admin Panel for SAP
    id=User ID
    pass=Password
    version=Ver 2.3.0

    Which will look like this in the code editor:

    i18n sample

    But, SAP UI5 suggests the following as the guidelines for writing i18n in a correct and standardized way:

    1. All the keys should be written in a lowercase
    2. The values of i18n can contain parameters like {0}, {1}, {2}, … [This can be used for special dynamic conditions]
    3. For special characters, use Unicode escape sequences
    4. Add comments using ‘#’ before sets of texts that are for certain category like:
      #XMSG: title of App
      title=Admin App
      appTitle=Admin App
      appDescription=Admin App
      
      #XMSG: App Version for Local Use
      appVersion=Version 2.0.14
      
      #XMSG: Not Found texts
      NotFound=Not Found
      NotFound.text=Sorry, but the requested resource is not available.
      NotFound.description=Please check the URL and try again.
      noDataDescriptiont=No data found. Try adjusting the filter settings or check your service.
      
      #XFLD: Form Texts
      COUNTRY=Country
      ServiceType=Service Type
      InOut=Inbound/Outbound
      GroupID=Group ID
      In=Inbound
      Out=Outbound
      

       

    Adding i18n in Manifest File

    Majorly, i18n is preconfigured within the manifest file. Anyhow, you can configure like shown below [it will be within “sap.ui5” object]:

    "models": {
        "i18n": {
            "type": "sap.ui.model.resource.ResourceModel",
            "settings": {
                "bundleName": "YRR.YRR.i18n.i18n"
            }
        }
    }

     

    Using i18n in View

    To use i18n in UI5 View (once it is already set as above in the manifest file), you need to just specify the value in the i18n file and use it for texts using the named model call, i.e. {i18n>text} where text is the key in i18n file with a value against it, like text = This is a text.

    To understand better, we will specify everything in different sections and showcase the output:

    i18n Content

    title=Admin Panel
    appTitle=YRR
    appDescription=App Description
    id=User ID
    pass=Password
    fieldsMandatory=All the fields are mandatory.
    version=Ver 2.3.0

    View Content

    <tnt:header>
    <tnt:ToolHeader>
    <Button id="sideNavigationToggleButton" icon="sap-icon://menu2" type="Transparent" press="onCollapseExpandPress">
    <layoutData>
    <OverflowToolbarLayoutData priority="NeverOverflow"/>
    </layoutData>
    </Button>
    <ToolbarSpacer/>
    <core:Icon src="sap-icon://vehicle-repair"></core:Icon>
    <Text text="{i18n>title}" wrapping="false">
    <layoutData>
    <OverflowToolbarLayoutData priority="Disappear"/>
    </layoutData>
    </Text>
    <ToolbarSpacer/>
    <Button text="Download User Excel" icon="sap-icon://excel-attachment" type="Transparent" press="onSelectExtendedUser"/>
    <Text text="{i18n>version}" wrapping="false"/>
    <!--<Button icon="sap-icon://bell" press="handleMessagePopoverPress"/>-->
    </tnt:ToolHeader>
    </tnt:header>

    Output

    i18n Example

    As you can see, we have binded the title and version with i18n, but the button text ‘Download Excel’ is hardcoded.

    Using i18n in Controller

    To get i18n data in View, you can use the global model that was specified within the manifest. For Controller too, we fetch the same model. You can either fetch everytime you need it, or make it global for that controller by specifying the following within onInit function:

    // Bundle for i18n 
    this.oBundle = this.getOwnerComponent().getModel("i18n").getResourceBundle();

    Once you have specified the above

    Showing Message from i18n in MessageBox

    Now, we will use the above bundle to fetch a text from our i18n:

    // read msg from i18n model
    sMsg = that.oBundle.getText("fieldsMandatory");
    MessageBox.error(sMsg);

    Now, the MessageBox will load the message from i18n, and you don’t have to hardcode the text within the controller.

    Messagebox message from i18n