Quantcast
Channel: Tweaks
Viewing all articles
Browse latest Browse all 66

Calculator in SAP using New ABAP Syntax

$
0
0

SAP HANA is Hot. Fiori/UI5 is Cool. OData is Fascinating. But in all these fun, basic ABAP is still thriving. This article is an example of the basic ABCs of ABAP which we need till ABAP does not get extinct (which will never happen) in the future SAP World. 🙂 Darwin’s law of Evolution holds good to ABAPers as well. ABAPers need to evolve and get new tricks of the game in their kitty, if they want to stay ahead in the competition. In this article, I have tried to show case some of the New Syntaxes of ABAP, which makes programming easier and reduces the code footprints.

The context behind this article:

In our SAPYard Technical Telegram Group, where we have more than 2470 active consultants from 6 Continents, one member @imkinnu shared the below image/gif and asked the Question.

Also Check – Sudoku Solver and Generator Tool Using Vanilla SAP ABAP

Question: The result should be printed in Result box instead of the Input text. For example, for Input ‘2+3’ I need the Result ‘5’ to be printed in result box. What i have done is, assigned the Input field ‘IN’ to Result field ‘RES’.

Answer from @Anask (within few seconds. That the beauty of this group):
It treats the variable as string and just copies content of one field to another. You need to split at SIGN and get data into 2 separate fields and then do the operator action. Just use Split and then do the Math operation. Use CASE statement and split based on the sign it contains.

Sample Code:

IF input CS "+".
lv_operator = "+".
ELSEIF input CS "-".
lv_operator = "+".
ELSEIF input CS "*".
lv_operator = "*".
ELSEIF input CS "/".
lv_operator = "/".
ENDIF.

SPLIT lv_input AT lv_operator
INTO lv_operand1
lv_operand2.

I am members of many WhatsApp and Telegram and other groups. But this SAP Technical Group is the most active one where we have tons of discussions every hour. Most Questions get Answered or at least get some ideas for the solution. If you have not joined yet, give it a try. It is safe and secure. And no one can know your mobile number, not even the Admins. You need to have Telegram App installed in your device before you join the group using the below link.

Join SAPYard’s SAP Technical Group.

I thought of helping @imkinnu with my own program. I quickly wrote a simple OOPs Program with New ABAP Syntaxes which I try to write in all my new developments.

Well, I forgot to introduce myself. My name is Stephan Köster. I am one of the Admins of the SAPYard SAP Technical Group. I am an SAP ABAP Developer. I am the founder of Köster Consulting. Please check my website for more information.

Enough of me. Now, lets come back to the topic of the day. If you are a novice of ABAP7.4, some of the points which you need to note in the below SAP Calculator Program are:

1. Inline Data Declaration

DATA(lv_off) = sy-index - 1.
DATA(lv_add) = abap_true.
READ TABLE gt_string_tab ASSIGNING FIELD-SYMBOL(<lv_op>) WITH TABLE KEY table_line = '/'.

2. RAISE exceptions

RAISE missing_number_at_beginning.
RAISE two_operator_not_allowed.
RAISE division_by_zero.
RAISE missing_number_at_end.
RAISE unknown_error.

(Nothing new. Showing for beginners in ABAP)

3. Conversion Function

DATA(lv_result) = CONV labst( <lv_first> / <lv_second> ).
rv_result = CONV #( gt_string_tab[ 1 ] ).
DATA(gv_fieldname) = |RB_CALC{ CONV numc1( sy-index ) }|.
cv_editable = |PA_CALC{ CONV numc1( sy-index ) }|.

4. New Syntax

INSERT |{ lv_result }| INTO gt_string_tab INDEX lv_tabix - 1.

5. Inline Data Declaration in Class Methods

* Call the Class Method to do the calculation

zcl_stkoes_calc=>do_calculation(
EXPORTING
iv_formula = <gv_calc>
RECEIVING
rv_result = DATA(gv_result)
EXCEPTIONS
division_by_zero = 1 " Division By Zero
missing_number_at_beginning = 2 " Missing Number at the beginning
missing_number_at_end = 3 " Missing Number at the end
two_operator_not_allowed = 4 " Two Operator are not allowed
unknown_error = 5 " Unknown Error
OTHERS = 6 ).

Did you check gv_result is declared during the call of the method do_calculation.

Note: We canNOT do similar Inline Data Declaration while calling a Function Module. Only available in Class Method.

6. MESSAGE with SWITCH

MESSAGE |{ SWITCH #( sy-subrc
WHEN 1 THEN |Division by zero|
WHEN 2 THEN |Missing number at the beginning|
WHEN 3 THEN |Missing number at the end|
WHEN 4 THEN |Two operator is not allowed|
WHEN 5 THEN |Unknown Error|
ELSE |Other Error| ) }| TYPE 'S' DISPLAY LIKE 'E'.

Also Check: T-Guard: Transport Dependency Validation Tool

Let me show you, what the Calculator can do. It does the basic +, -, X, / mathematic operations. But the logic and concept which I have put in the class can be extrapolated to many real use case actual project requirements.

I have knowingly used the Macros to make you understand how Macros can still be used. If you feel, macros are not needed, you can do the direct Radio Buttons in the Selection Screen without the Macros.

Sample Input String for the Calculator and their corresponding Results
SAP Calculator in ABAP

Sample Error Handling

Also Read: GPS like tool in SAP using Google Map API

Here is the complete Code which you can try. You can also download the program text file at the bottom of this article.

*&---------------------------------------------------------------------*
*& Report ZSTKOES_CALC
*&---------------------------------------------------------------------*
*& This is a Utilty Program which acts like a Simple Calculator.
*& OOPs Concept along with New ABAP7.4+ Syntaxes are used
*& Feel Free to refer and use it as required
*&---------------------------------------------------------------------*
REPORT zstkoes_calc.

CLASS zcl_stkoes_calc DEFINITION.

PUBLIC SECTION.
CONSTANTS:
BEGIN OF gcs_operators,
div TYPE char1 VALUE '/' ##NO_TEXT,
mod TYPE char3 VALUE 'MOD' ##NO_TEXT,
mul TYPE char1 VALUE '*' ##NO_TEXT,
sub TYPE char1 VALUE '-' ##NO_TEXT,
add TYPE char1 VALUE '+' ##NO_TEXT,
END OF gcs_operators.

CLASS-METHODS:
do_calculation
IMPORTING
VALUE(iv_formula) TYPE string
RETURNING
VALUE(rv_result) TYPE labst
EXCEPTIONS
division_by_zero
missing_number_at_beginning
missing_number_at_end
two_operator_not_allowed
unknown_error.

PRIVATE SECTION.
TYPES:
gtty_string TYPE TABLE OF string.
CLASS-METHODS:
convert_formula_to_string_tab
IMPORTING
VALUE(iv_formula) TYPE string
EXPORTING
VALUE(et_string_tab) TYPE gtty_string
EXCEPTIONS
missing_number_at_beginning
missing_number_at_end
two_operator_not_allowed,

calculate
IMPORTING
VALUE(it_string_tab) TYPE gtty_string
RETURNING
VALUE(rv_result) TYPE labst
EXCEPTIONS
division_by_zero
unknown_error.
ENDCLASS.

CLASS zcl_stkoes_calc IMPLEMENTATION.
METHOD do_calculation.

convert_formula_to_string_tab(
EXPORTING
iv_formula = iv_formula
IMPORTING
et_string_tab = DATA(lt_string_tab)
EXCEPTIONS
missing_number_at_beginning = 1
missing_number_at_end = 2
two_operator_not_allowed = 3 ).

IF sy-subrc EQ 0.
calculate(
EXPORTING
it_string_tab = lt_string_tab
RECEIVING
rv_result = rv_result
EXCEPTIONS
division_by_zero = 4
unknown_error = 5 ).
ENDIF.

IF sy-subrc NE 0.
CASE sy-subrc.
WHEN 1.
RAISE missing_number_at_beginning.
WHEN 2.
RAISE missing_number_at_end.
WHEN 3.
RAISE two_operator_not_allowed.
WHEN 4.
RAISE division_by_zero.
WHEN 5.
RAISE unknown_error.
ENDCASE.
ENDIF.

ENDMETHOD.

METHOD convert_formula_to_string_tab.
FIELD-SYMBOLS:
<lv_value> TYPE string.

CONDENSE iv_formula NO-GAPS.
DATA(lv_off) = 0.
DO.
IF iv_formula+lv_off(1) CN '1234567890'.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE gcs_operators TO FIELD-SYMBOL(<lv_operator>).
IF sy-subrc NE 0.
EXIT.
ENDIF.
DATA(lv_length) = strlen( <lv_operator> ).
IF iv_formula+lv_off(lv_length) EQ <lv_operator>.
IF lv_off EQ 0.
RAISE missing_number_at_beginning.
ELSEIF <lv_value> IS NOT ASSIGNED.
RAISE two_operator_not_allowed.
ENDIF.
UNASSIGN <lv_value>.
APPEND iv_formula+lv_off(lv_length) TO et_string_tab.
ADD lv_length TO lv_off.
EXIT.
ENDIF.
ENDDO.
ELSE.
IF <lv_value> IS NOT ASSIGNED.
APPEND INITIAL LINE TO et_string_tab ASSIGNING <lv_value>.
<lv_value> = iv_formula+lv_off(1).
ELSE.
<lv_value> = |{ <lv_value> }{ iv_formula+lv_off(1) }|.
ENDIF.
ADD 1 TO lv_off.
ENDIF.
IF lv_off EQ strlen( iv_formula ).
EXIT.
ENDIF.
ENDDO.

IF <lv_value> IS NOT ASSIGNED.
RAISE missing_number_at_end.
ENDIF.
ENDMETHOD.

METHOD calculate.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE gcs_operators TO FIELD-SYMBOL(<lv_operator>).
IF sy-subrc NE 0.
EXIT.
ENDIF.

DO.
ASSIGN it_string_tab[ table_line = <lv_operator> ] TO FIELD-SYMBOL(<lv_op>).
IF sy-subrc NE 0.
EXIT.
ENDIF.
DATA(lv_from) = sy-tabix - 1.
DATA(lv_to) = sy-tabix + 1.
READ TABLE it_string_tab ASSIGNING FIELD-SYMBOL(<lv_first>) INDEX lv_from.
READ TABLE it_string_tab ASSIGNING FIELD-SYMBOL(<lv_second>) INDEX lv_to.
IF <lv_first> IS ASSIGNED AND <lv_second> IS ASSIGNED.
TRY.
CASE <lv_operator>.
WHEN '/'.
DATA(lv_result) = CONV labst( <lv_first> / <lv_second> ).
WHEN 'MOD'.
lv_result = <lv_first> MOD <lv_second>.
WHEN '*'.
lv_result = <lv_first> * <lv_second>.
WHEN '-'.
lv_result = <lv_first> - <lv_second>.
WHEN '+'.
lv_result = <lv_first> + <lv_second>.
ENDCASE.
CATCH cx_sy_zerodivide INTO DATA(lo_error).
RAISE division_by_zero.
ENDTRY.
DELETE it_string_tab FROM lv_from TO lv_to.
INSERT |{ lv_result }| INTO it_string_tab INDEX lv_from.
ENDIF.
ENDDO.
ENDDO.

IF lines( it_string_tab ) EQ 1.
rv_result = it_string_tab[ 1 ].
ELSE.
RAISE unknown_error.
ENDIF.
ENDMETHOD.
ENDCLASS.

**--------------------------------------------------------------------*
** Start of Program
**--------------------------------------------------------------------*
* Macro to set one radiobutton as default (can be used only once)
DEFINE calc_default.
SELECTION-SCREEN:
BEGIN OF LINE.
PARAMETERS:
rb_calc&1 RADIOBUTTON GROUP cal DEFAULT 'X' USER-COMMAND calc&1.
SELECTION-SCREEN:
COMMENT 3(14) co_calc&1.
PARAMETERS:
pa_calc&1 TYPE string DEFAULT &2.
SELECTION-SCREEN:
END OF LINE.
END-OF-DEFINITION.

* Macro to create radiobutton without deafult
DEFINE calc.
SELECTION-SCREEN:
BEGIN OF LINE.
PARAMETERS:
rb_calc&1 RADIOBUTTON GROUP cal.
SELECTION-SCREEN:
COMMENT 3(14) co_calc&1.
PARAMETERS:
pa_calc&1 TYPE string DEFAULT &2.
SELECTION-SCREEN:
END OF LINE.
END-OF-DEFINITION.

SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE gt_b01.

* Creating all paramater on SELECTION SCREEN using macro
calc_default 1 '10 + 300 / 100 * 10 - 50'.
calc 2 '+10 + 300 / 100 * 10 - 50'.
calc 3 '10 + 300 / 100 * 10 - 50+'.
calc 4 '10 + 300 / 100 * * 10 - 50'.
calc 5 '10 + 300 / 0 * 10 - 50'.
SELECTION-SCREEN END OF BLOCK b01.

INITIALIZATION.
* Filling all comments and title
co_calc1 = '1. Calculation'.
co_calc2 = '2. Calculation'.
co_calc3 = '3. Calculation'.
co_calc4 = '4. Calculation'.
co_calc5 = '5. Calculation'.
gt_b01 = 'Calculations'.

AT SELECTION-SCREEN OUTPUT.
DATA:
gv_editable TYPE rsscr_name.

* Check which radiobutton is selected
PERFORM get_field_selected_radiobutton CHANGING gv_editable.

* Leave only selected line editable
LOOP AT SCREEN.
IF screen-name(7) EQ 'PA_CALC' AND screen-name NE gv_editable.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.

START-OF-SELECTION.
DATA:
gv_editable TYPE rsscr_name.

* Check which radiobutton is selected
PERFORM get_field_selected_radiobutton CHANGING gv_editable.

* Get the Formular of selected radiobutton
ASSIGN (gv_editable) TO FIELD-SYMBOL(<gv_calc>).
IF <gv_calc> IS ASSIGNED.

* Do the calculation
zcl_stkoes_calc=>do_calculation(
EXPORTING
iv_formula = <gv_calc>
RECEIVING
rv_result = DATA(gv_result)
EXCEPTIONS
division_by_zero = 1 " Division By Zero
missing_number_at_beginning = 2 " Missing Number at the beginning
missing_number_at_end = 3 " Missing Number at the end
two_operator_not_allowed = 4 " Two Operator are not allowed
unknown_error = 5 " Unknown Error
OTHERS = 6 ).

* Handle Errors
IF sy-subrc NE 0.
MESSAGE |{ SWITCH #( sy-subrc
WHEN 1 THEN |Division by zero|
WHEN 2 THEN |Missing number at the beginning|
WHEN 3 THEN |Missing number at the end|
WHEN 4 THEN |Two operator is not allowed|
WHEN 5 THEN |Unknown Error|
ELSE |Other Error| ) }| TYPE 'S' DISPLAY LIKE 'E'.
RETURN.
ENDIF.
ENDIF.

END-OF-SELECTION.

WRITE: gv_result.
*&---------------------------------------------------------------------*
*& Form GET_FIELD_SELECTED_RADIOBUTTON
*&---------------------------------------------------------------------*
* <--CV_EDITABLE PARAMETER of selected radiobutton
*----------------------------------------------------------------------*
FORM get_field_selected_radiobutton CHANGING cv_editable TYPE rsscr_name.
DO.
DATA(lv_fieldname) = |RB_CALC{ CONV numc1( sy-index ) }|.
ASSIGN (lv_fieldname) TO FIELD-SYMBOL(<lv_fieldvalue>).
IF sy-subrc NE 0.
EXIT.
ELSEIF <lv_fieldvalue> EQ abap_true.
cv_editable = |PA_CALC{ CONV numc1( sy-index ) }|.
EXIT.
ENDIF.
ENDDO.

ENDFORM.

Download above program in text file. Calculator Version 1

If you do not want to use Macros for the Radio Buttons, you can download another version of the same program with simpler Selection screen. Calculator Version 2

Output of Version 2 of the SAP ABAP Calculator looks like below.

ABAP Calculator

I hope, this article would motivate you to use the New ABAP Syntax in all your current and future developments. We need to embrace the change and accept it in our daily projects. Change is Progress. 🙂

Very recently, we have started Free Video Courses. Please check our End to End Video Training on SAP OData and Netweaver Gateway.

OData Video Training

Also check our Free Video Course on SAP HANA, HANA DB and ADT.

Free SAP HANA End to End Training

Please Subscribe to our YouTube Channel for more Educative SAP Technical Videos.


Viewing all articles
Browse latest Browse all 66

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>