Translate this blog

sexta-feira, 26 de abril de 2013

Enviar email via ABAP usando HTML / Sending email thru ABAP using HTML - Part II


 Português  Dando continuidade ao assunto do post anterior sobre envio de emails, para os programadores que se preocupam mais com os detalhes, podemos formatar o corpo do email usando HTML. Infelizmente não podemos usar Style Sheets para formatação CSS, mas ao menos podemos formatar usando o CSS em cada tag.

Basicamente, grande parte da estrutura de código do post anterior não se altera. Apenas o parâmetro na linha 25 i_type deve receber o valor 'HTM' (i_type = 'HTM') e as linhas 12 a 16, que preenchem a tabela responsável pelo conteúdo do email, devem ser substituídas pelo código fonte deste post.

No código abaixo temos um exemplo de formatação HTML usada no corpo do email:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
  APPEND:
  '<html><body>' TO lt_text,
  '<table><tr><td>ola</td></tr></table>' TO lt_text,
  '<p></p>' TO lt_text,
  '<table style="border:2px dotted red;' TO lt_text,
  'border-spacing:0; border-collapse:collapse;">' TO lt_text,
  '<tr><td style="border:2pxdottedred;">' TO lt_text,
  '  Lin 1 - Col 1  </td>' TO lt_text,
  '<td style="border:2px dotted red;">' TO lt_text,
  '  Lin 1 - Col 2  </td></tr>' TO lt_text,
  '<tr><td style="border:2px dotted red;">' TO lt_text,
  '  Lin 2 - Col 1  </td>' TO lt_text,
  '<td style="border:2px dotted red;">' TO lt_text,
  '  Lin 2 - Col 2  </td></tr>' TO lt_text,
  '</table></body></html>' TO lt_text.

Da mesma forma como visto anteriormente, você pode checar o status do email na transação SOST. Clicando em 'Exibir documento' (icone dos óculos), o corpo do email será exibido.

A formatação do exemplo acima terá a seguinte cara:

quarta-feira, 24 de abril de 2013

Enviar email via ABAP / Sending email thru ABAP - Part I


 Português  Após pesquisas no Google e auxílio de alguns colegas de trabalho, identifiquei e escolhi a melhor forma, na minha opinião, de mandar emails pelo SAP através de códigos de programação. Se você sabe HTML da até pra formatá-lo!

Neste primeiro momento farei uma demonstração com texto simples para o envio de emails, não utilizando estrutura HTML.

Segue o código explicativo:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  DATA: lt_text TYPE bcsy_text,"Conterá o conteúdo do email
       ls_text TYPE soli,"Work Area de lt_text
       lv_sent TYPE os_boolean."Receberá a confirmação de envio
 
*Variáveis para enviar o email
  DATA: go_request TYPE REF TO cl_bcs,
       go_document TYPE REF TO cl_document_bcs,
       go_sender TYPE REF TO cl_sapuser_bcs,
       go_recipient TYPE REF TO if_recipient_bcs,
       go_exception TYPE REF TO cx_bcs.
 
*Preenchendo o conteúdo do email
 ls_text = 'Essa é a primeira linha de conteúdo do email'.
  APPEND ls_text TO lt_text.
 ls_text = 'Essa é a segunda linha...'.
  APPEND ls_text TO lt_text.
 
*É necessário o tratamento de erros com try...catch
  TRY.
*Método utilizado para criar um pedido de envio persistente
     go_request = cl_bcs=>create_persistent().
 
*Monta e adiciona a estrutura do e-mail
     co_document = cl_document_bcs=>create_document(
       i_type = 'RAW'
       i_text = lt_text
       i_language = sy-langu"P - Português
       i_subject = 'Assunto do email').
     co_request->set_document(co_document).
 
*Remetente do e-mail
*obs: por default, o envio é feito pelo usuário logado.
*Caso queira alterar, adicione esse método:
     go_sender = cl_sapuser_bcs=>create( 'RISHIDA').
      CALL METHOD go_request->set_sender
        EXPORTING
         i_sender = go_sender.
 
*Adicionando o destinatário ao e-mail
     go_recipient =
     cl_cam_address_bcs=>create_internet_address( 'ab@cd.com').
      CALL METHOD go_request->add_recipient
        EXPORTING
         i_recipient = go_recipient
         i_express   = 'X'.
 
*Marca o envio como imediato ('X') ou não (space)
      CALL METHOD co_request->set_send_immediately( 'X').
 
*Envia email, e retorna true ('X') ou false ('') na lv_sent
      CALL METHOD go_request->send(
        EXPORTING
         i_with_error_screen = 'X'
        RECEIVING
         result = lv_sent).
      COMMIT WORK.
 
    CATCH cx_bcs INTO go_exception.
*Tratamento do erro try... catch
  ENDTRY.

Se as configurações de envio de email estiverem certas o email será enviado ao destinatário corretamente. Você pode checar o status do email na transação SOST.

segunda-feira, 22 de abril de 2013

Select usando apenas variáveis / Select into variables


 Português  As vezes necessitamos selecionar informações do banco de dados para pegar poucas informações, que não necessitaria ser criada uma tabela interna ou mesmo estrutura/Work Area para tal. Se tivermos as variáveis já declaradas no programa e o procedimento for simples, não existe motivo de declarar mais variáveis e ocupar mais memória.
Abaixo segue um exemplo de como fazer um SELECT populando apenas variáveis:
01
02
03
04
05
06
07
08
09
10
  DATA: lv_val1 TYPE i,
       lv_val2 TYPE i.
 
*Digamos que a tabela ZTAB tenha10 campos,
*mas precisamos apenas de2 deles
  SELECT SINGLE val1 val2
    FROM ztab
    INTO (lv_var1, lv_var2)
    WHERE type = 'exemplo'.

quinta-feira, 18 de abril de 2013

Acessar uma variável em memória / Access a variable in memory ( Field Symbol - Part IV )


 Português  Neste post mostrarei mais uma forma de utilização dos ponteiros. Como havia comentado anteriormente, em alguns casos necessitamos de informações geradas em tempo de execução no programa e que não teríamos acesso a elas de outra forma ou mesmo para não necessitarmos acessar o banco de dados para obter esta informação. Mas este processo necessita de uma habilidade do seu executor: saber debugar. A estrutura que devemos usar para referenciar um campo do programa é essa: (nome_do_programa)-campo. Algumas vezes podemos descobrir estas informações apenas apertando a tecla F1 na tela que estamos trabalhando, mas muitas outras vezes não é tão simples assim.
Para testar se estamos pegando o campo certo podemos usar esta estrutura nas linhas de variáveis e verificar se elas existem ou não, se aquele é mesmo o campo que necessitamos. Abaixo temos uma sequência de imagens que identificam aonde estão os campos do programa e como capturamos o campo durante a função debug no SAP:

Após apertar F1 e selecionar os dados técnicos do campo, temos a seguinte tela:
O campo nº 1 é o nome do programa e o nº 2 é o campo/estrutura que precisamos.

Se não funcionar, precisamos identificar o campo debugando o mesmo. Com o nome do programa, podemos tentar identificar a variável global que representa aquele campo ou mesmo buscá-lo na opção de variáveis globais do debugger.

Ao debugar um programa identificamos esta tela:
O campo nº 1 indica o nome do programa.

Com a informação do programa, clicamos na aba variables 1 e digitamos (nome_do_programa)-campo:
O campo poderá ser referenciado e o conteúdo do mesmo é TAXBRA.

Após esta verificação podemos utiliza-la no programa com o ponteiro. Abaixo temos o exemplo da utilização prática:
01
02
03
04
05
06
07
08
09
  FIELD-SYMBOLS: <fs_tax>.
 
*Referenciamos o programa e o nome ao ponteiro
  ASSIGN ('(SAPLJ1BCONDTAX)J_1BTAXCODEV-KALSM') TO <fs_tax>.
  IF <fs_tax> IS ASSIGNED.
    WRITE <fs_tax>.
  ENDIF.
*Mostrará o mesmo valor que vimos no debugger, TAXBRA

segunda-feira, 15 de abril de 2013

Modificar tabelas internas com Field Symbol / Modify internal tables with Field Symbol ( Field Symbol - Part III )


 Português  Quando comecei a aprender ABAP, me deparei com as tais das tabelas transparentes e tabelas internas. Para quem não conhece, aqui vai uma breve (e pobre) explicação: tabela transparente detém a informação do SAP, são as tabelas que compõe o banco de dados; tabela interna são as que utilizamos nos programas, para obter informações, montar relatórios ou até mesmo modificar o conteúdo das tabelas transparentes.

Com as tabelas internas, vieram as estruturas/Work Areas, Header Lines, e suas maneiras específicas de utilização. Foquei na explicação das estruturas/Work Areas, pois o Header Line estava se tornando obsoleto pela SAP, mas sua utilização ainda é possível (corrijam-me se estiver errado sobre essas infos!).

As Work Areas são estruturas declaradas com a mesma estrutura da tabela que queremos manipular. Fazendo um looping em uma tabela por exemplo, cada linha pode ser lida com auxílio desta Work Area, modificada e, se for o caso, alterar o conteúdo da tabela interna (e também da tabela transparente). No caso de se manter as informações da tabela interna é necessário uma linha de comando para efetuar esse processo, que no caso é: MODIFY ... INDEX ...

Quando aprendi sobre o Field Symbol, fiquei com preguiça de usá-lo... Mas com o tempo me convenci que deveria usar, tanto pra melhorar performance, quanto para expandir meu conhecimento. Como dito antes, é um baita recurso pois não necessita do comando MODIFY..., você simplesmente altera a informação como se estivesse lidando com a linha diretamente da tabela!

Abaixo temos um exemplo prático, onde mostro duas formas distintas de se fazer a mesma operação:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
*Suponhamos que neste momento a tabela it_mara tenha10 linhas
  DATA: ls_mara TYPE mara.
  FIELD-SYMBOLS: <fs_mara> TYPE mara.
 
*Usando Work Area para alterar dados da tabela interna
  LOOP AT it_mara INTO ls_mara.
   ls_mara-ersda = '2013.04.15'.
    MODIFY it_mara FROM ls_mara INDEX sy-tabix.
  ENDLOOP.
 
*Usando Field Symbol p/ alterar dados da tabela interna
  LOOP AT it_mara ASSIGNING <fs_mara>.
   <fs_mara>-ersd> = '2013.04.15'.
  ENDLOOP.

Visualmente podemos notar a facilidade e a economia de esforço é empregada com a utilização de ponteiros na atualização em massa de uma informação em tabelas internas. Lembrando que também é possível utilizar este recurso com o comando READ TABLE...

sexta-feira, 12 de abril de 2013

Acessar uma variável usando seu nome / Access a variable using its name ( Field Symbol - Part II )


 Português  Dando continuidade ao assunto "ponteiros"... Em ABAP contamos com um recurso que, na minha opinião, é extremamente interessante: uma palavra pode ser usada para referenciar uma variável. Declarando uma variável do tipo char e atribuindo a ela o nome de outra variável ou simplesmente escrevendo o nome de uma variável já declarada no programa é possível usar esta palavra referenciando-a ao ponteiro.

Bom... Nada como um exemplo prático pra exemplificar:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
*Primeiro exemplo ---------------------------------------
  DATA: var_1 TYPE i VALUE 10.
  FIELD-SYMBOLS: <fs_pont>.
*Apontando o nome da variável
  ASSIGN ('VAR_1') TO <fs_pont>.
  IF <fs_pont> IS ASSIGNED.
    WRITE <fs_pont>.
  ENDIF.
*Mostrará o valor10
 
*Segundo exemplo ---------------------------------------
  DATA: var_2 TYPE string VALUE 'VAR_1'.
*Comando para remover o apontamento da var_1
  UNASSIGN <fs_pont>.
*Apontando o conteúdo da variável var_2(VAR_1)
  ASSIGN (var_2) TO <fs_pont>.
  IF <fs_pont> IS ASSIGNED.
    WRITE <fs_pont>.
  ENDIF.
*Mostrará o valor10, conteúdo da variável var_1

Com esse exemplo, observamos que o nome de uma variável pode ser usado para referenciar um ponteiro, fazendo com que o ponteiro assuma o valor daquela variável (primeiro exemplo), assim como quando utilizamos o conteúdo de uma variável para referenciar outra (segundo exemplo). Neste segundo caso temos que utilizar os parênteses, fazendo com que a interpretação seja baseada no conteúdo da variável e não apontar para a variável (var_2) em si.
Assim como no caso do post anterior, toda alteração feita no ponteiro terá efeito diretamente na variável a qual ela está sendo apontada, que no exemplo é a var_1.

quinta-feira, 11 de abril de 2013

Usando Field Symbol em ABAP / Using Field Symbol in ABAP ( Field Symbol Part I )


 Português  A definição de ponteiro para alguns programadores é um tanto quanto complexa. Uma variável que armazena o endereço de memória de outra variável... Parece inútil isso, não parece? Porque não utilizar simplesmente a própria variável?

O motivo é simples: é um ótimo recurso e, em alguns casos, indispensável!

Levando em consideração o mundo SAP, com suas inúmeras transações interligadas, todos seus Enhancements e User-Exits para executarmos parametrizações, chamar uma variável armazenada em memória durante a execução de um programa pode salvar muitas vidas e projetos também... A ideia e utilização de Field Symbol parecem complexas pra quem não conhece ou nunca ouviu falar, mas não é!

Primeiramente darei um exemplo simples e prático da sua utilização e continuarei postando outras dicas sobre o assunto:

01
02
03
04
05
06
07
08
09
10
11
12
*Variável que será referenciada
  DATA: lv_pont TYPE string VALUE 'Hello World!'.
*Variável ponteiro
  FIELD-SYMBOLS: <fs_pont>.
 
*Referenciando o ponteiro à variável
  ASSIGN lv_pont TO <fs_pont>.
*Testando se o ponteiro foi referenciado
  IF <fs_pont> IS ASSIGNED.
   <fs_pont> = 'Good bye World!'.
  ENDIF.

No final a variável lv_pont terá o seguinte valor: 'Good bye World!' e não mais 'Hello World!'.
Podemos concluir que qualquer alteração feita ao ponteiro afetará a variável que foi referenciada e vice-versa.

Operações matemáticas em ABAP / Mathematical operations in ABAP


 Português  Explorando um pouco a peculiaridade da linguagem ABAP, apresento algumas formas de executar operações matemáticas:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  DATA lv_val TYPE i VALUE 4.
 
*CONTADOR
 lv_val = lv_val + 1.
*É equivalente a...
  ADD 1 TO lv_val.
*Resultado:5
 
 lv_val = 4.
*SUBTRATOR
 lv_val = lv_val - 1.
*É equivalente a...
  SUBTRACT 1 FROM lv_val.
*Resultado:3
 
 lv_val = 4.
*MULTIPLICADOR
 lv_val = lv_val * 2.
*É equivalente a...
  MULTIPLY lv_val BY 2.
*Resultado:8
 
 lv_val = 4.
*DIVISOR
 lv_val = lv_val / 2.
*É equivalente a...
  DIVIDE lv_val BY 2.
*Resultado:2

Começando...

 Português  "Existem mil maneiras de se preparar Neston, invente a sua!" - diria um "merchan" famoso e um professor meu da época da faculdade... Mas realmente, programação é muito pessoal e pode ser escrita de inúmeras formas. Algumas maneiras de efetuar um looping, outras tantas de se validar um dado. Mas além da lógica pura existe a peculiaridade envolvida na linguagem de programação utilizada. Levando em consideração estes dois cenários, cabe ao desenvolvedor explorar os recursos que a linguagem nos proporciona e as melhores formas de resolver um problema.

O pai da informação (Google) disponibiliza um arsenal de informações compartilhadas entre milhões de pessoas. Algumas inúteis, outras nem tanto (afinal, cabe a cada um julgar o que é relevante para si). Partindo deste princípio, a partir deste momento estou compartilhando o que aprendi ao longo do tempo em programação. Aos que acessarem este "canal" e aos que utilizarem algum post para alguma dúvida que surgir ao longo do tempo, sejam bem vindos.

"Não tenha medo de compartilhar conhecimento, tenha medo de não aprender coisas novas" - Eu mesmo hehehe