"
Apoiado por:

Artigos etiquetados com ‘estilo’

O que diz uma mensagem?

postit

Queres obter o texto de uma mensagem da qual só sabes o ID e o número e não sabes como? Aprende aqui:


DATA texto TYPE string.
MESSAGE ID '00' TYPE 'E' NUMBER '163' WITH '123' INTO texto.

É só isto. Agora do lado de dentro da variável texto encontras o seguinte texto:

“O mandante 123 não existe no sistema”

Obrigado a Peteris B pela foto.

O Abapinho saúda-vos.

Automatizar catálogo de campos de ALV

lixo

Às vezes pergunto-me qual será, no mundo, a percentagem de código ABAP desnecessário. Um exemplo paradigmático de como se pode desperdiçar tempo a escrever código que não serve para nada e só prejudica é a tão frequente definição das descrições dos campos de uma ALV directamente em ABAP.

Ler o resto do artigo »

Adeus DESCRIBE TABLE. Já vais tarde.

quatroemlinha

Durante doze anos
Quando quis contar
As linhas de uma itab
Fazia o que todos fazem:
DESCRIBE TABLE itab LINES linhas.

Até que outro dia
Vi uma coisa que,
Parece mentira,
Nunca antes vira:
LINES( itab ).

Dá no mesmo
E sem ter de declarar
O raio da variável.

Assim, em vez de:


DATA: linhas TYPE i.
DESCRIBE TABLE itabl LINES linhas.
IF linhas = 42.
  WRITE 'A tua tabela é a verdade'.
ENDIF.

Basta fazer:


IF LINES( itbl ) = 42.
  WRITE 'A tua tabela é a verdade'.
ENDIF.

É a prova de que
Se a SAP quisesse
Fazia um esforço
E o ABAP seria
Uma coisa fixe.

Mas parece que não quer
E o ABAP que se lixe.

Merda de poema. Foi o que se arranjou.

O Abapinho saúda-vos.

A mensagem travesti

Travesti

Nos módulos AT SELECTION-SCREEN de um REPORT é-te possível lançar mensagens de erro e voltar ao ecrã de selecção. Mas uma vez que passes do START-OF-SELECTION, se lançares uma mensagem de erro, o programa termina. A solução para dar um erro e, ainda assim, regressar ao ecrã de selecção, é travestir a mensagem:


START-OF-SELECTION.
  IF condicao_desejada.
    MESSAGE S001(00) with 'Erro!' DISPLAY LIKE 'E'.
    EXIT.
  ENDIF.
  WRITE 'Olá, eu sou o resto do programa'.

A mensagem do tipo S mascarou-se de E. Parece que É, mas não É.

Se experimentares vais ver que o sistema dá erro mas não sai completamente do programa; Volta ao ecrã de selecção e não corre o resto do programa (por causa do EXIT).

Obrigado Sérgio Lopes pela dica.

(E obrigado Tiago Celestino pela foto)

O Abapinho saúda-vos.

O circunlóquio do VALUE CHECK

rodeios

Nunca te aconteceu esbarrares com uma coisa no ABAP que parece que é mas não é? A documentação diz que é, tudo indica que assim seja, e depois afinal não é.

Provavelmente já precisaste de, ao definir um parâmetro no ecrã de selecção de um relatório, limitar as possibilidades do que o utilizador pode introduzir aos valores disponíveis no tipo de dados desse parâmetro, certo? Para isto existe o VALUE CHECK. Parece simples. Por exemplo, presumia-se que isto funcionasse:


PARAMETERS: P_BUKRS LIKE T001-BUKRS OBLIGATORY VALUE CHECK.

Vais a ver e não funciona.

O campo T001-BUKRS é do tipo BUKRS que é do domínio BUKRS que por sua vez tem definida a tabela de valores T001 para a qual BUKRS é a única chave primária. Mesmo assim, pateticamente, isto não funciona. Não funciona porque, por alguma razão lamentável, ao contrário do que faria sentido e se subentende na documentação, o VALUE CHECK não tem em conta o domínio do campo que valida. Pelo contrário, para este funcionar é preciso que o campo referido tenha uma chave externa para a tabela de valores.

Portanto, no nosso caso, embora a tabela que contém a lista de valores possíveis do BUKRS seja a T001, para o VALUE CHECK funcionar temos antes de fazer referência a uma outra tabela qualquer que tenha a T001 definida como chave externa. Como por exemplo, a T001K:


PARAMETERS: P_BUKRS LIKE T001K-BUKRS OBLIGATORY VALUE CHECK.

E assim já funciona.

Em resumo: conhecendo já tu a tabela com os valores possíveis, em vez de a poderes usar, tens de ir procurar outra que a defina como chave externa. É complicar o simples com rodeios. Um retórico chamar-lhe-ia circunlóquio. Eu chamo-lhe estupidez. Aposto que é um bug que a SAP decidiu orgulhosamente ignorar para sempre.

Obrigado Luís Rocha pela dica.

O Abapinho saúda-vos.

De pé ó vítimas da fome

lili

Classes. Sempre as houve entre as pessoas. Mas no ABAP ainda há poucos que as tenham em conta. Se ser classicista na sociedade pode resultar em pedantismo, no ABAP, a única luta de classes é a que alguns travam para que estas sejam mais usadas.

Há dois tipos de classes: as globais e as locais. As globais são criadas na transacção SE24. As locais, que por sinal dou por mim a usar cada vez mais, são feitas declarativamente na SE38. Se soubermos que a nossa classe vai ser usada amiúde, faz sentido criá-la global. Se, pelo contrário, a classe for particular a um programa, não há porque fazer dela um objecto autónomo, bastando assim criá-la local ao programa que a vai usar.

Não é impossível que uma classe local se venha mais tarde a revelar útil noutro sítio. A hipótese mais estúpida, ainda que não inédita, é copiar o código de um programa para outro. Outra hipótese é colocá-la num “include” partilhado pelos vários programas que a usem. Mas mesmo isto também foleiro. Se é usada em mais que um sítio, ficará sempre mellhor como objecto global da SE24.

Os senhores da SAP, pensando já na possibilidade de uma classe local se emancipar, criaram uma ferramenta para isto. Funciona assim:

  1. Vai à SE24
  2. No menu “Tipo de objecto” escolhe a opção “Importar” e depois “classe local de programa”
  3. Escolhe o programa
  4. Aparece uma lista das classes locais desse programa
  5. scolhe as classes locais que queres tornar globais
  6. Dá-lhes um nome
  7. E pimbas

Se esta ferramenta não te parecer útil, vai comprar o livro ABAP para totós.

O Abapinho saúda-vos.

SPLIT INTO TABLE

corta_fiambre

Aqui vos mostro uma forma criativa de preencher uma tabela interna com constantes que aprendi num programa standard. Imagina que querias criar uma tabela interna com os seguintes tipos de documento financeiro:

AB
AF
CH
DG
DZ
EX
F3
F4.

A forma mais convencional seria assim:


DATA: t_blart TYPE STANDARD TABLE OF blart,
      wa_blart LIKE LINE OF t_blart.

wa_blart = 'AB'.
APPEND wa_blart TO t_blart.
wa_blart = 'AF'.
APPEND wa_blart TO t_blart.
wa_blart = 'CH'.
APPEND wa_blart TO t_blart.
wa_blart = 'DG'.
APPEND wa_blart TO t_blart.
wa_blart = 'DZ'.
APPEND wa_blart TO t_blart.
wa_blart = 'EX'.
APPEND wa_blart TO t_blart.
wa_blart = 'F3'.
APPEND wa_blart TO t_blart.
wa_blart = 'F4'.
APPEND wa_blart TO t_blart.

Mas há uma forma muito mais sintética e curiosa:


DATA: lv_blart_list TYPE string,
      t_blart TYPE STANDARD TABLE OF blart,
      wa_blart LIKE LINE OF t_blart.

lv_blart_list = 'AB AF CH DG DZ EX F3 F4'.
SPLIT lv_blart_list AT space INTO TABLE t_blart.

O preenchimento da tabela é feito em apenas 2 linhas, bem menos que as 16 da forma convencional.

Fica aqui mais um exemplo copiado do standard que é interessante por ter dois níveis:


l_action_list = 'A01 A02 A03 A04'.
SPLIT l_action_list AT ' ' INTO TABLE lt_action.
LOOP AT lt_action INTO l_action.
  CASE l_action.
    WHEN 'A01'. l_refdoc_list = 'R01 R02 R03 R04 R05 R06 R14'.
    WHEN 'A02'. l_refdoc_list = 'R07 R08 R10 R12'.
    WHEN 'A03'. l_refdoc_list = 'R07 R08 R10 R11 R12 R13'.
    WHEN 'A04'. l_refdoc_list = 'R09'.
  ENDCASE.
  SPLIT l_refdoc_list AT ' ' INTO TABLE lt_refdoc.
  LOOP AT lt_refdoc INTO l_refdoc.
    ls_cust-action = l_action.
    ls_cust-refdoc = l_refdoc.
    APPEND ls_cust TO t_cust.
  ENDLOOP.
ENDLOOP.

O Abapinho saúda-vos.

Parâmetros não parametrizáveis

baloico

Volta não volta aparece um cliente que pede a um funcional que pede a um programador que crie um parâmetro protegido contra escrita no ecrã de selecção de um programa. É um bocado cretino visto que a ideia dos parâmetros é serem parametrizáveis.

Mas enfim, vê-se de tudo.

Os clientes têm tanta imaginação que a SAP devia criar um módulo de cinema, SAP CI, especialmente para eles poderem realizar os tantos filmes que lhes vão na cabeça. Estou certo de que se criariam grandes sucessos de ficção científica. E muitas comédias também.

Bem, caso alguém te peça para fazer isto, faz-se assim:


REPORT ZTEST1.
PARAMETERS: nao_mexe LIKE mara-matnr DEFAULT '220705' MODIF ID ro.

AT SELECTION-SCREEN OUTPUT.
  LOOP AT SCREEN.
    IF SCREEN-GROUP1 = 'RO' .
      SCREEN-INPUT = '0'.
      MODIFY SCREEN.
    ENDIF.
  ENDLOOP.

START-OF-SELECTION.
  WRITE: / nao_mexe.

Agora falando mais a sério, a ideia de proteger parâmetros contra escrita é interessante se isso depender dos valores de outros parâmetros. Por exemplo, se o pisco “gravar ficheiro” estiver ligado, permite introduzir o nome do ficheiro, caso contrário, este último fica protegido contra escrita. Fica a sugestão. É só adicionar ao código as condições desejadas.

O Abapinho saúda-vos.

CASE de pernas para o ar

this_side_up

Qual é a tua cor preferida?


SELECTION-SCREEN BEGIN OF BLOCK b1.
PARAMETERS: p_azul BUTTONGROUP GROUP COR DEFAULT 'X',
            p_verde BUTTONGROUP GROUP COR,
            p_roxo BUTTONGROUP GROUP COR.
SELECTION-SCREEN END OF BLOCK b1.

Se respondeste azul sobrevives e podes atravessar a ponte.

De qualquer das formas, em ABAP costuma fazer-se o seguinte para descobrir a cor que o utilizador escolheu:


IF p_azul = 'X'.
  lv_cor = 'AZUL'.
ELSE IF p_verde = 'X'.
  lv_cor = 'VERDE'.
ELSE IF p_roxo = 'X'.
  lv_cor = 'ROXO'.
ENDIF.

Mas há uma forma curiosa e muito mais elegante de conseguir o mesmo. É aquilo a que se pode chamar de CASE de pernas para o ar:


CASE 'X'.
  WHEN p_azul.
    lv_cor = 'AZUL'.
  WHEN p_verde.
    lv_cor = 'VERDE'.
  WHEN p_roxo.
    lv_cor = 'ROXO'.
ENDCASE.

E esta, heim?

(Obrigado ao itspaulkelly pela foto.)

O Abapinho saúda-vos.

As funções *_SINGLE_READ

select_single

Quando se quer obter um único registo de uma tabela da base de dados é costume usar-se o SELECT SINGLE que, como toda a gente sabe, na sua forma mais básica reza assim:


SELECT SINGLE *
  FROM KNA1
  WHERE KUNNR = '1234567890'.

Ler o resto do artigo »


Acerca do Abapinho
O Abapinho é suportado pelo WordPress
Artigos (RSS) e Comentários (RSS).