This lecture combines three tools that make expression-oriented ABAP safer and easier to read. LET creates local helper fields, EXACT detects lossy conversions or calculations, and OPTIONAL supplies an initial result when a table line is missing.
1. Why LET exists
Constructor and conditional expressions can become repetitive when the same calculation is needed more than once. A LET expression defines helper fields that exist only inside the surrounding expression.
TYPES: BEGIN OF ty_total,
net TYPE decfloat34,
tax TYPE decfloat34,
gross TYPE decfloat34,
END OF ty_total.
DATA(ls_total) = VALUE ty_total(
LET net = CONV decfloat34( ls_order-net_value )
tax = net * CONV decfloat34( '0.18' )
IN net = net
tax = tax
gross = net + tax ).The helpers net and tax are evaluated before the component assignments and cannot be accessed outside this expression.
2. LET scope and evaluation
- A helper is local to the constructor expression or supported subexpression.
- Its type is derived from the right-hand side, similar to an inline DATA declaration.
- A previously declared helper can be used by a later helper in the same LET block.
- LET is valuable when it improves readability or avoids repeating an expensive calculation.
3. LET in a conditional expression
DATA(lv_category) = COND string(
LET amount = CONV decfloat34( ls_order-net_value )
IN
WHEN amount >= 5000 THEN 'PREMIUM'
WHEN amount >= 1000 THEN 'STANDARD'
ELSE 'BASIC' ).Calculate the value once, give it a meaningful local name and then use it across the branches.
4. LET for a readable string result
DATA(lv_text) = CONV string(
LET order_no = |{ lv_vbeln ALPHA = OUT }|
amount = |{ lv_amount NUMBER = USER DECIMALS = 2 }|
IN |Order { order_no }: { amount } { lv_currency }| ).Keep helpers short and local. If a calculation represents a reusable business rule, move it to a well-named method rather than hiding it inside LET.
5. EXACT versus normal conversion
DATA(lv_decimal) = CONV decfloat34( '125.00' ).
TRY.
DATA(lv_integer) = EXACT i( lv_decimal ).
CATCH cx_sy_conversion_error INTO DATA(lx_conversion).
DATA(lv_reason) = lx_conversion->get_text( ).
ENDTRY.EXACT accepts the conversion only when the value can be represented without loss according to its rules. Fractional rounding, overflow or an invalid representation can raise a conversion exception instead of silently changing the value.
CX_SY_CONVERSION_* subclass depends on the conversion and ABAP release. Catch the documented exception appropriate to your target system; a superclass is used above to keep the example compact.6. EXACT for calculations
TRY.
DATA(lv_result) = EXACT decfloat34(
lv_quantity * lv_unit_price ).
CATCH cx_sy_conversion_error INTO DATA(lx_exact).
"Log and handle the lossless-check failure
ENDTRY.Use EXACT at boundaries where silent rounding or truncation would violate a business rule. Do not replace intentional business rounding; make the chosen rounding rule explicit.
7. OPTIONAL for safe table reads
DATA(ls_customer) = VALUE ty_customer(
lt_customers[ customer_id = iv_customer_id ] OPTIONAL ).
DATA(ls_customer_with_default) = VALUE ty_customer(
lt_customers[ customer_id = iv_customer_id ]
DEFAULT VALUE #(
customer_id = iv_customer_id
name = 'Unknown customer' ) ).If the line is missing, OPTIONAL returns an initial value. DEFAULT returns the explicitly supplied fallback. Without either addition, a missing line can raise CX_SY_ITAB_LINE_NOT_FOUND.
8. OPTIONAL is not an existence flag
An initial structure can be a valid business value. If the caller must distinguish “not found” from “found but initial”, use line_exists, an explicit result flag, or exception handling.
9. Practical combination
DATA(ls_display) = VALUE ty_display(
LET customer = VALUE ty_customer(
lt_customers[ customer_id = iv_customer_id ]
DEFAULT VALUE #( name = 'Unknown customer' ) )
IN customer_name = customer-name
amount_text = |{ lv_amount NUMBER = USER DECIMALS = 2 }| ).This keeps lookup and fallback logic together while the resulting structure stays declarative.
10. Common mistakes
- Using LET for long business logic that belongs in a method.
- Assuming EXACT performs business rounding.
- Ignoring the exception path of an EXACT conversion.
- Using OPTIONAL when an initial line is indistinguishable from “not found”.
- Forgetting that feature availability and exception subclasses vary by release.
11. Practical exercise
- Create a VALUE expression that calculates net, tax and gross using LET.
- Convert three decimals to integers with EXACT: an exact integer, a fractional value and an overflowing value.
- Read a missing table line using OPTIONAL.
- Repeat the read with DEFAULT and a meaningful fallback record.
- Add a flag that explicitly tells the caller whether the original table line existed.
12. Interview quick checks
Can a LET helper be used after the expression?
No. It is scoped to the expression or subexpression in which it is declared.
How is EXACT different from CONV?
CONV performs a normal conversion. EXACT additionally verifies that the conversion or calculation is lossless according to its rules and can raise an exception.
What does OPTIONAL return when a table line is missing?
With VALUE it returns an initial result of the table-expression type; with REF it returns an initial reference.
Official SAP references
- LET Expressions — SAP Keyword Documentation
- EXACT Lossless Operator — SAP Keyword Documentation
- Table Expressions: OPTIONAL and DEFAULT — SAP Keyword Documentation
- Reading Single Lines — SAP Help
Educational examples. Validate syntax availability, exception classes, DDIC types and conversion behavior on your ABAP release.
0 Comments