This is a test message to test the length of the message box.
Login
ABAP Quick Ranges and Select-Options
Created by Software-Heroes

ABAP Quick - Ranges and Select Options

772

Ranges and Select Options in ABAP are very similar, yet there are subtle differences in their use in the ABAP OO context. Here we'll look at their modern usage.



In this article, we'll look at the basics of ranges in ABAP, compare ranges with select options, and examine their necessity in modern development.

 

Introduction

The foundation of every classic report in SAP is parameters and select options. Using parameters, a user can define a single value, but with select options, they can define a variety of restrictions. The advantage is that if the select option remains empty, all values are automatically drawn, or the restriction remains empty. In modern development with RAP and ABAP OO, ranges can still be valuable. Therefore, in this article, we'll look at the basics and delve into the details of their use. We will focus primarily on modern development scenarios.

To access the database, we use the ZBS_DCP_APPL table. We created this table and filled it with data in a RAP article on optimizing search helps. We will therefore also use the table and the data in this article.

 

Structure

In this chapter, we will look at the basics and structure of a range. We will also clarify the current differences between a range and a select option.

 

Range

A range always has the same structure in ABAP. This is a table with four columns (SIGN, OPTION, LOW, and HIGH), where Low and High are based on the defined data types. The data types and possible contents of the first two columns are always the same.

 

Select Option

The Select Option is defined in a report and belongs to the report's selection screen. Essentially, this is a range, since the table body corresponds to a range. The addition here is the additional header row that is available.

 

Hint: The header row is an obsolete construct and should no longer be used. Therefore, you can only define and use ranges in classes.

 

Standard Fields

The first two fields, SIGN and OPTION, are standardized and only allow certain values or constants. You can find more information about the permissible values in the DDSIGN and DDOPTION domains as fixed values.

 

Resolution

If we use a range in our code, the standard breaks the range down into a proper statement and performs a corresponding comparison. Let's take this range, for example.

DATA(filter_applications) = VALUE applications( 
  ( sign = 'I' option = 'BT' low = 'ACC_DEF' high = 'ENGINE' )
  ( sign = 'E' option = 'EQ' low = 'CALC' ) ).

 

Now let's perform a SELECT on the data and use the range to limit the data.

SELECT FROM zbs_dcp_appl
  FIELDS *
  WHERE application IN @filter_applications
  INTO TABLE @DATA(result_with_range).

 

ABAP breaks down the range into this query. We could do this manually, but using the standard function saves us a lot of time and performance. This also keeps our code flexible.

SELECT FROM zbs_dcp_appl
  FIELDS *
  WHERE         application BETWEEN 'ACC_DEF' AND 'ENGINE'
        AND NOT application       = 'CALC'
  INTO TABLE @DATA(result_without_range).

 

Usage

In this section, we'll look at its use using various examples. In these examples, however, we'll focus primarily on the modern use of Range.

 

Definition

You can define Range directly or as a type; the RANGE OF addition is available for this purpose. Let's first define a type that we can then use for typing or in method interfaces. In principle, we can then continue working in our code using inline declarations.

TYPES applications TYPE RANGE OF zbs_dcp_appl-application.

DATA(used_type) = VALUE applications( ( sign = 'I' option = 'EQ' low = 'CALC' ) ).

 

If we define a variable locally, we can only use it locally and not actually pass it to an interface.

DATA local TYPE RANGE OF zbs_dcp_appl-application.

local = VALUE #( ( sign = 'I' option = 'EQ' low = 'ENGINE' ) ).

 

Passing

What about passing a select option to a range? For example, we want to pass the values from a report to a class. As you saw in the structure above, with the select option, we must first address the table body and not the header row; otherwise, the compiler will notify us of the incorrect type.

range = select_option[].

 

Creation

In this example, we create a range directly using a SELECT and fill the result into a range, which we can then use directly for further delimitations. This saves us a lot of code for preparing the range. We use literals to create fixed values that then define the range.

SELECT FROM zbs_dcp_appl
  FIELDS 'I'         AS sign,
         'EQ'        AS option,
         application AS low,
         application AS high
  WHERE team = 'BASE_DEV'
  INTO TABLE @DATA(generated_range).

 

For it to be a valid range, LOW and HIGH must have the same type. Therefore, we double-select the Application field. Let's then look at the range in the debugger to get an idea of this method.

 

Delimitation

We can then use the range to define delimitation at various points in our code. We can use it to perform the usual SELECT. You can find examples in the previous sections. Or we can use a range to restrict the data in a loop.

LOOP AT databases INTO DATA(database) WHERE application IN range_filters.
  " ...
ENDLOOP.

 

If you want to compare the contents of a field against multiple values, you can also do this using a range in an IF statement.

IF database-application IN range_filters.
  " ...
ENDIF.

 

Parameters

What about parameters? Parameters via a selection screen or queries against individual fields in program logic are always somewhat complicated in a select. For example, if the field is empty, the select checks against the empty value, which usually no longer produces a result.

SELECT FROM zbs_dcp_appl
  FIELDS *
  WHERE application = @parameter
  INTO TABLE @DATA(data_to_use)

 

The advantage of a range is that once it's empty, it's ignored in the query and all values are retrieved. To do this, we can create a local range, and once the parameter is filled, we add the entry to the range. Otherwise, it remains empty and the parameter is ignored.

DATA optional_filter TYPE applications.

IF parameter IS NOT INITIAL.
  INSERT VALUE #( sign   = 'I'
                  option = 'EQ'
                  low    = parameter ) INTO TABLE optional_filter.
ENDIF.

SELECT FROM zbs_dcp_appl
  FIELDS *
  WHERE application IN @optional_filter
  INTO TABLE @DATA(data_to_use).

 

Standard

Where does the SAP standard use ranges? Here's a prominent example of querying filters in the query class of a custom entity. Using the REQUEST object, we can return the filters as a range that the user has specified via the Fiori app.

TRY.
    DATA(filters) = request->get_filter( )->get_as_ranges( ).
    staging = filters[ name = `STAGING` ]-range[ 1 ]-low.
  CATCH cx_rap_query_filter_no_range.
    staging = 'TEST'.
ENDTRY.

 

In this example, we return a table in which the fields and the corresponding range are stored as rows. Accordingly, in the first step, we search for the row with STAGING and then read the first row of the range to obtain the LOW value.

 

Complete Example

Here is the complete example from today's article. You can find the examples and uses in the various methods in the class.

CLASS zcl_bs_demo_ranges_and_options DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    TYPES applications TYPE RANGE OF zbs_dcp_appl-application.

    METHODS assignment
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS create_via_select
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS definition
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS technical_usage
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS delimitation
      IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.

    METHODS use_with_parameter
      IMPORTING !out       TYPE REF TO if_oo_adt_classrun_out
                !parameter TYPE zbs_dcp_appl-application.
ENDCLASS.


CLASS zcl_bs_demo_ranges_and_options IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    technical_usage( out ).
    definition( out ).
    assignment( out ).
    create_via_select( out ).
    delimitation( out ).
    use_with_parameter( out       = out
                        parameter = 'GENERAL' ).
    use_with_parameter( out       = out
                        parameter = '' ).
  ENDMETHOD.


  METHOD technical_usage.
    DATA(filter_applications) = VALUE applications( ( sign = 'I' option = 'BT' low = 'ACC_DEF' high = 'ENGINE' )
                                                    ( sign = 'E' option = 'EQ' low = 'CALC' ) ).

    SELECT FROM zbs_dcp_appl
      FIELDS *
      WHERE application IN @filter_applications
      INTO TABLE @DATA(result_with_range).

    out->write( result_with_range ).

    SELECT FROM zbs_dcp_appl
      FIELDS *
      WHERE         application BETWEEN 'ACC_DEF' AND 'ENGINE'
            AND NOT application       = 'CALC'
      INTO TABLE @DATA(result_without_range).

    out->write( result_without_range ).
  ENDMETHOD.


  METHOD definition.
    DATA local TYPE RANGE OF zbs_dcp_appl-application.
    local = VALUE #( ( sign = 'I' option = 'EQ' low = 'ENGINE' ) ).
    
    DATA(used_type) = VALUE applications( ( sign = 'I' option = 'EQ' low = 'CALC' ) ).
  ENDMETHOD.


  METHOD assignment.
*    range = select_option[].
  ENDMETHOD.


  METHOD create_via_select.
    SELECT FROM zbs_dcp_appl
      FIELDS 'I'         AS sign,
             'EQ'        AS option,
             application AS low,
             application AS high
      WHERE team = 'BASE_DEV'
      INTO TABLE @DATA(generated_range).

    out->write( generated_range ).

    SELECT FROM zbs_dcp_appl
      FIELDS *
      WHERE application IN @generated_range
      INTO TABLE @DATA(used_range).

    out->write( used_range ).
  ENDMETHOD.


  METHOD delimitation.
    DATA(range_filters) = VALUE applications( ( sign = 'I' option = 'EQ' low = 'CALC' ) ).

    SELECT FROM zbs_dcp_appl
      FIELDS *
      INTO TABLE @DATA(databases).

    LOOP AT databases INTO DATA(database) WHERE application IN range_filters.
      out->write( database ).
    ENDLOOP.

    IF database-application IN range_filters.
      out->write( database ).
    ENDIF.
  ENDMETHOD.


  METHOD use_with_parameter.
    DATA optional_filter TYPE applications.

    IF parameter IS NOT INITIAL.
      INSERT VALUE #( sign   = 'I'
                      option = 'EQ'
                      low    = parameter ) INTO TABLE optional_filter.
    ENDIF.

*    SELECT FROM zbs_dcp_appl
*      FIELDS *
*      WHERE application = @parameter
*      INTO TABLE @DATA(data_to_use).

    SELECT FROM zbs_dcp_appl
      FIELDS *
      WHERE application IN @optional_filter
      INTO TABLE @DATA(data_to_use).

    out->write( data_to_use ).
  ENDMETHOD.
ENDCLASS.

 

Conclusion

The range is still a powerful tool for data retrieval, but also for demarcation within program logic. You should now know the difference between select options and ranges, and you will be able to use ranges effectively in development in the future.

 

Sources:
SAP Help - TYPE RANGE OF


Included topics:
QuickRangeSelect-Option
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP Quick - Generic Query Implementation

Category - ABAP

Tired of the same old query class implementation for custom entities in RAP? It's time for a reusable component.

04/22/2025

ABAP in Practice - String Processing

Category - ABAP

In this practical example we look at the string processing to determine the CDS names in CamelCase and how you can implement this with ABAP.

10/15/2024

ABAP in Practice - Test Driven Development

Category - ABAP

How does TDD actually work in practice and are there simple examples for learning in ABAP? In this exercise we will look at the practical part.

09/24/2024

ABAP in Practice - Merge data sets

Category - ABAP

How do we merge two different data sets in ABAP, especially with regard to Modern ABAP? A practical task for this topic.

09/17/2024

ABAP in Practice - Modern ABAP

Category - ABAP

In this small task we look at existing classic ABAP source code and try to optimize it according to Modern ABAP.

08/27/2024