"
Supported by

Create RANGEs in DDIC without getting all wound up

I am using RANGEs more and more. I use them at breakfast, lunch, and dinner and outside meal times. It’s like soy sauce. A few spoonfuls and everything is instantly tastier.

But their declaration has always given me some work. For example, I need a ZS_RANGE_ABC structure (with the OPTION, SIGN, LOW, HIGH fields) if I want to use a range of a ZABC field, and then I need an ZT_RANGE_ABC table type that has ZS_ABC as its “row type”. Doing all this manually is quite annoying.

I recently found out that DDIC has a feature that simplifies this process. This simplification consists of automatically maintaining the “row type”. It works like this:

  1. Let’s take it for granted that you have the ZABC data element;
  2. In SE11, insert the name of the RANGE data type at “Data type”: ZT_RANGE_ABC;
  3. Press F5 to create it and select the “table type” option;
  4. Give it a description or else you cannot advance;
  5. (now here comes the trick!!)
  6. In the “Process” menu select the “Define as range table type” option;
  7. (Kaboom! The screen has changed!)
  8. Add ZABC as the “data element”;
  9. Add ZS_RANGE_ABC as the “structured row type” (don’t press “create” yet);
  10. Save;
  11. Have you saved it? Now press “create”;
  12. (the DDIC automatically creates a structure that already has SIGN, OPTION, LOW and HIGH!)
  13. Save and activate the structure as you would with any other structure and go back;
  14. Activate the table type and voilà: you now have a ZT_RANGE_ABC table type that is a RANGE of type ZABC.

Very interesting, wouldn’t you say?

Thank you José Faria for showing me this very handy feature.

Greetings from Abapinho.

10 comentários a “Create RANGEs in DDIC without getting all wound up”

  1. Johnny Diz:

    Nuno,

    Type range of, na declaração do elemento de dados, faz o truque tambem :)

  2. Martin Diz:

    Acho mais facil declarar direto no programa:

    ranges lr_matnr for mara-matnr.

    Só isso…

  3. Nuno Godinho Diz:

    Martin, eu também acho mais fácil declarar directamente no programa, e faço-o sempre que posso.
    Mas se tiveres de passar um RANGE por parâmetro não há como evitar declará-lo como um tipo.
    Ainda assim podes declará-lo como um TYPE na classe.
    Mas se o quiseres retornar de um método (RETURNING) não há volta a dar, tem de estar no DDIC.
    Topas?

    De qualquer forma, se o declarares no programa aconselho-te a fazê-lo na nova sintaxe:
    DATA: xxx TYPE RANGE OF yyy.

    Ou:
    TYPES: ty_xxx TYPE RANGE OF yyy.

  4. Johnny Diz:

    Nuno,

    Não obrigatoriamente…

    Eu criava, amiude, ranges onde apenas indicava qual o campo de referencia, e o returning era um range do tipo “cl_abap_tabledescr”, o que nao obriga a ter de criar um tipo no DDIC.

    Exemplificando:

    METHOD create_range.
    ****Acc Jao Martins – Criação de Range dinamicamente

    DATA:
    gr_structdescr TYPE REF TO cl_abap_structdescr,
    gr_tabledescr TYPE REF TO cl_abap_tabledescr,
    gr_datadescr TYPE REF TO cl_abap_datadescr,
    gr_typedescr TYPE REF TO cl_abap_typedescr,
    gt_components TYPE abap_component_tab,
    gw_component TYPE LINE OF abap_component_tab,
    gr_wa TYPE REF TO data,
    gr_tab TYPE REF TO data.

    FIELD-SYMBOLS: TYPE ANY.
    FIELD-SYMBOLS: TYPE table.

    * Componentes da estrutura -> GT_COMPONENTS
    MOVE ‘SIGN’ TO gw_component-name.
    gw_component-type ?= cl_abap_elemdescr=>get_c( p_length = 1 ).
    INSERT gw_component INTO TABLE gt_components.

    MOVE ‘OPTION’ TO gw_component-name.
    gw_component-type ?= cl_abap_elemdescr=>get_c( p_length = 2 ).
    INSERT gw_component INTO TABLE gt_components.

    MOVE ‘LOW’ TO gw_component-name.
    gw_component-type ?= cl_abap_elemdescr=>describe_by_name( field ).
    INSERT gw_component INTO TABLE gt_components.

    MOVE ‘HIGH’ TO gw_component-name.
    gw_component-type ?= cl_abap_elemdescr=>describe_by_name( field ).
    INSERT gw_component INTO TABLE gt_components.

    * Descrição -> GR_STRUCTDESCR
    gr_structdescr ?= cl_abap_structdescr=>create( gt_components ).

    * WA da estrutura
    CREATE DATA gr_wa TYPE HANDLE gr_structdescr.
    ASSIGN gr_wa->* TO .

    gr_datadescr ?= gr_structdescr.
    gr_tabledescr ?= cl_abap_tabledescr=>create( gr_datadescr ).
    r_val = gr_tabledescr.
    ENDMETHOD.

    Para ler o range:

    * Criar Range baseando-se no tipo – RETURN DO Range
    me->create_range( EXPORTING field = fieldname
    IMPORTING r_val = gr_tabledescr ) .

    ** Criar range dinamica
    CREATE DATA ref_tab TYPE HANDLE gr_tabledescr.

    ASSIGN ref_tab->* TO .

    Abraço

  5. Johnny Diz:

    Nuno,

    Na parte final do meu comentário anterior faltava uma coisa importante.. :)
    FIELD-SYMBOLS: TYPE table.

    ** Criar range dinamica
    CREATE DATA ref_tab TYPE HANDLE gr_tabledescr.

    ASSIGN ref_tab->* TO .//(field symbol )

    Abraço

  6. Custodio Diz:

    Realmente a solucao do Johnny eh correcta. Mas nao consigo ver onde eh mais simples do que criar no dicionario.

  7. Nuno Godinho Diz:

    Bem, Johnny, não duvido de que funcione, mas, caramba, isso parece uma máquina de Rube Goldberg! Ou dito de outra forma, ergues uma montanha para parir um rato :)

    Eu uso e abuso do DDIC. Está lá para isso ;)

  8. Johnny Diz:

    Nuno,

    Sim a primeira vez custa, nao digo que nao, mas o racional que se aplixa é:

    1 – Criar os metodos numa classe
    2 – Herdar estes metodos em qualquer outra classe que crie
    3 – Usar e abusar :)

    em vez de estar a criar N elementos de dados, que no limite ao fim de uns quantos meses ja nem me lembro da existência deles, crio os atraves do metodo..

    Para mim, repito para mim, acho mais simples e practico, mas qualquer uma das maneiras é valida :)

    Abraços

  9. Nilson Diz:

    Nuno, excelente solução.
    Parabéns.

  10. Nuno Godinho Diz:

    Obrigado Nilson. No entanto eu só a divulguei. É SAP standard. Ainda que muito bem escondida :)

Deixe um comentário


About Abapinho
Abapinho runs on WordPress
Articles (RSS) e Comments (RSS).