Como fazer upload de arquivos com caracteres especiais usando SAPUI5 e SAP Gateway?
Confira no link do post que fiz na SCN sobre o assunto.
http://scn.sap.com/community/portuguese/technology/blog/2015/09/29/sapui5--upload-de-arquivos-slug-com-caracteres-especiais
http://scn.sap.com/community/developer-center/front-end/blog/2015/12/22/sapui5--upload-file-slug-with-special-characters
Mostrando postagens com marcador ABAP. Mostrar todas as postagens
Mostrando postagens com marcador ABAP. Mostrar todas as postagens
domingo, 14 de agosto de 2016
segunda-feira, 18 de agosto de 2014
O ALV mais fácil do universo!
Tem ABAP que ainda faz ALV com função. Alguns têm fobia de ALV OO, outros nem sabem que existe.
Já ouvi muita gente falando "descobri uma forma nova de fazer ALV, demora mais e é mais difícil porque usa objetos, mas fica melhor".
Bom, tem um jeito ainda mais fácil de fazer ALV OO. Basta usar a classe CL_SALV_TABLE.
Nunca foi tão fácil...
Veja o exemplo abaixo:
SAP Inside Track 2014 – São Leopoldo/RS
O SAP Inside Track é um evento mundial da SAP para troca de experiências e conhecimento. Não bastasse o fato de poder aprender muita coisa nova, o evento é de graça, basta inscrever-se no site: http://shar.es/1nG2eB
No evento deste ano que ocorrerá no SAP Labs, em São Leopoldo/RS, teremos sessões sobre SAP HANA (muita coisa de HANA!), SAPUI5, SAP HCM e Success Factors, SAP MES e Match Insights (o famoso sistema que a Seleção da Alemnha usa).
O evento estará muito bom! Para quem não puder comparecer, o evento será transmitido ao vivo online pelo SAP Connect.
Confira a agenda completa: http://scn.sap.com/docs/DOC-57267
No evento deste ano que ocorrerá no SAP Labs, em São Leopoldo/RS, teremos sessões sobre SAP HANA (muita coisa de HANA!), SAPUI5, SAP HCM e Success Factors, SAP MES e Match Insights (o famoso sistema que a Seleção da Alemnha usa).
O evento estará muito bom! Para quem não puder comparecer, o evento será transmitido ao vivo online pelo SAP Connect.
Confira a agenda completa: http://scn.sap.com/docs/DOC-57267
quarta-feira, 7 de maio de 2014
Enviar email com anexos usando classe standard CL_BCS
Enviar email usando a classe CL_BCS é muito fácil, correto?
Mas e enviar email com arquivos anexos? Tem como fazer com a CL_BCS?
Sim, tem como e é barbada também. Precisamos apenas de um método a mais para anexar arquivos no nosso email. Ah, e claro, precisamos preencher uma tabela interna com o conteúdo do arquivo que será anexado ao email.
Segue exemplo abaixo:
Easy like a sunday morning...
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Email/send_email_with_attachment.abap
Mas e enviar email com arquivos anexos? Tem como fazer com a CL_BCS?
Sim, tem como e é barbada também. Precisamos apenas de um método a mais para anexar arquivos no nosso email. Ah, e claro, precisamos preencher uma tabela interna com o conteúdo do arquivo que será anexado ao email.
Segue exemplo abaixo:
*&---------------------------------------------------------------------**& Report ZSEND_EMAIL_ATTACHMENT*&*&---------------------------------------------------------------------**& ABAP Sample Code*& Send email with attachments using CL_BCS*&*& Maurício Lauffer - Brazil - 04.16.2014*& http://www.linkedin.com/in/mauriciolauffer*&*& This sample explains how to send an email with attachment*& using class: CL_BCS*&*&---------------------------------------------------------------------*REPORT zsend_email_attachment.CONSTANTS:gc_subject TYPE so_obj_des VALUE 'ABAP Email (attachment) with CL_BCS', " Email subjectgc_email_to TYPE adr6-smtp_addr VALUE 'frodo.baggins@lotr.com', " Valid emailgc_text TYPE soli VALUE 'Hello world! My first ABAP email with attachment!', " Text used into the email bodygc_type_raw TYPE so_obj_tp VALUE 'RAW', " Email typegc_att_type TYPE soodk-objtp VALUE 'PDF', " Attachment typegc_att_subject TYPE sood-objdes VALUE 'Document in PDF'. " Attachment titleDATA:gt_text TYPE soli_tab, " Table which contains email body textgt_attachment_hex TYPE solix_tab, " Table which contains the attached filegv_sent_to_all TYPE os_boolean, " Receive the information if email was sentgv_error_message TYPE string, " Used to get the error messagego_send_request TYPE REF TO cl_bcs, " Email objectgo_recipient TYPE REF TO if_recipient_bcs, " Who will receive the emailgo_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the emailgo_document TYPE REF TO cl_document_bcs, " Email bodygx_bcs_exception TYPE REF TO cx_bcs.TRY."Create send requestgo_send_request = cl_bcs=>create_persistent( )."Email FROM...go_sender = cl_sapuser_bcs=>create( sy-uname )."Add sender to send requestgo_send_request->set_sender( i_sender = go_sender )."Email TO...go_recipient = cl_cam_address_bcs=>create_internet_address( gc_email_to )."Add recipient to send requestgo_send_request->add_recipient(EXPORTINGi_recipient = go_recipienti_express = abap_true)."Email BODYAPPEND gc_text TO gt_text.go_document = cl_document_bcs=>create_document(i_type = gc_type_rawi_text = gt_texti_length = '12'i_subject = gc_subject )."You should populate the table gt_attachment_hex"with the binary data from your file!"For example: gt_attachment_hex = binary_data_from_file."Attachmentgo_document->add_attachment(EXPORTINGi_attachment_type = gc_att_typei_attachment_subject = gc_att_subjecti_att_content_hex = gt_attachment_hex)."Add document to send requestgo_send_request->set_document( go_document )."Send email and get the resultgv_sent_to_all = go_send_request->send( i_with_error_screen = abap_true ).IF gv_sent_to_all = abap_true.WRITE 'Email sent!'.ENDIF."Commit to send emailCOMMIT WORK."Exception handlingCATCH cx_bcs INTO gx_bcs_exception.gv_error_message = gx_bcs_exception->get_text( ).WRITE gv_error_message.ENDTRY.
Easy like a sunday morning...
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Email/send_email_with_attachment.abap
quinta-feira, 17 de abril de 2014
Enviar email usando classe standard CL_BCS
Para enviar email com um programa ABAP é muito fácil, basta utilizar uma classe standard da SAP, a classe CL_BCS.
Ela é uma classe simples de utilizar, até mesmo para aqueles que ainda não estão acostumados com OO (ainda existe???).
Bom, vamos ao exemplo:
Agora é copiar/colar e começar a brincar.
Barbadinha!
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Email/send_email.abap
Ela é uma classe simples de utilizar, até mesmo para aqueles que ainda não estão acostumados com OO (ainda existe???).
Bom, vamos ao exemplo:
*&---------------------------------------------------------------------**& Report ZSEND_EMAIL*&*&---------------------------------------------------------------------**& ABAP Sample Code*& Send email with CL_BCS*&*& Maurício Lauffer - Brazil - 04.15.2014*& http://www.linkedin.com/in/mauriciolauffer*&*& This sample explains how to send an email using class: CL_BCS*&*&---------------------------------------------------------------------*REPORT zsend_email.CONSTANTS:gc_subject TYPE so_obj_des VALUE 'ABAP Email with CL_BCS', " Email subjectgc_email_to TYPE adr6-smtp_addr VALUE 'frodo.baggins@lotr.com', " Valid emailgc_text TYPE soli VALUE 'Hello world! My first ABAP email!', " Text used into the email bodygc_type_raw TYPE so_obj_tp VALUE 'RAW'. " Email typeDATA:gt_text TYPE soli_tab, " Table which contains email body textgv_sent_to_all TYPE os_boolean, " Receive the information if email was sentgv_error_message TYPE string, " Used to get the error messagego_send_request TYPE REF TO cl_bcs, " Email objectgo_recipient TYPE REF TO if_recipient_bcs, " Who will receive the emailgo_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the emailgo_document TYPE REF TO cl_document_bcs, " Email bodygx_bcs_exception TYPE REF TO cx_bcs.TRY."Create send requestgo_send_request = cl_bcs=>create_persistent( )."Email FROM...go_sender = cl_sapuser_bcs=>create( sy-uname )."Add sender to send requestgo_send_request->set_sender( i_sender = go_sender )."Email TO...go_recipient = cl_cam_address_bcs=>create_internet_address( gc_email_to )."Add recipient to send requestgo_send_request->add_recipient(EXPORTINGi_recipient = go_recipienti_express = abap_true)."Email BODYAPPEND gc_text TO gt_text.go_document = cl_document_bcs=>create_document(i_type = gc_type_rawi_text = gt_texti_length = '12'i_subject = gc_subject )."Add document to send requestgo_send_request->set_document( go_document )."Send email and get the resultgv_sent_to_all = go_send_request->send( i_with_error_screen = abap_true ).IF gv_sent_to_all = abap_true.WRITE 'Email sent!'.ENDIF."Commit to send emailCOMMIT WORK."Exception handlingCATCH cx_bcs INTO gx_bcs_exception.gv_error_message = gx_bcs_exception->get_text( ).WRITE gv_error_message.ENDTRY.
Agora é copiar/colar e começar a brincar.
Barbadinha!
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Email/send_email.abap
quarta-feira, 1 de agosto de 2012
Boas práticas para LOOP AT aninhados
Muitas vezes é necessário escrevermos códigos que leiam tabelas internas em sequência, sendo necessário diversos LOOPs. O comum é utilizarmos uma estrutura encadeada de LOOP AT dentro de LOOP AT. Como no exemplo abaixo:
REPORT zlooping.
DATA:
lt_bkpf TYPE STANDARD TABLE OF bkpf,
lt_bseg TYPE STANDARD TABLE OF bseg,
ls_bkpf TYPE bkpf,
ls_bseg TYPE bseg.
"Looping cabeçalho
LOOP AT lt_bkpf INTO ls_bkpf.
"Looping item
LOOP AT lt_bseg INTO ls_bseg WHERE bukrs = ls_bkpf-bukrs
AND belnr = ls_bkpf-belnr
AND gjahr = ls_bkpf-gjahr.
"Faz alguma coisa
"Faz outra coisa
ENDLOOP.
ENDLOOP.
REPORT zlooping.
DATA:
lt_bkpf TYPE STANDARD TABLE OF bkpf,
lt_bseg TYPE STANDARD TABLE OF bseg,
ls_bkpf TYPE bkpf,
ls_bseg TYPE bseg.
"Looping cabeçalho
LOOP AT lt_bkpf INTO ls_bkpf.
"Looping item
LOOP AT lt_bseg INTO ls_bseg WHERE bukrs = ls_bkpf-bukrs
AND belnr = ls_bkpf-belnr
AND gjahr = ls_bkpf-gjahr.
"Faz alguma coisa
"Faz outra coisa
ENDLOOP.
ENDLOOP.
Há algo errado no código acima? Não absolutamente nada de errado. Ele irá fazer exatamente o que queremos fazer. Looping na BKPF seguido de looping na BSEG.
Agora digamos que na BKPF tem 10 registros e na BSEG 100. Provavelmente nosso looping seria rápido o bastante para não notarmos qualquer degradação do desempenho. Porém, imaginamos agora que nossa BKPF tem 100 registros e nossa BSEG 1000. Muito provavelmente o programa irá demorar um bocado para ser executado, pois serão muitas iterações. O programa lerá a BKPF 100 vezes e para cada iteração na BKPF a BSEG será lida 1000 vezes! Exatamente, a cada laço o programa sempre lerá TODA a BSEG. Neste caso, 100.000 iterações na BSEG.
Mas como podemos resolver esta questão de desempenho? De que forma podemos fazer uma sequência de loopings sem usar o LOOP AT + WHERE?
Abaixo segue uma forma de fazer com que seus loopings não fiquem tão demorados:
REPORT zlooping.
DATA:
lt_bkpf TYPE STANDARD TABLE OF bkpf,
lt_bseg TYPE STANDARD TABLE OF bseg,
ls_bkpf TYPE bkpf,
ls_bseg TYPE bseg.
"Ordenar para BINARY SEARCH
SORT:
lt_bkpf BY bukrs belnr gjahr,
lt_bseg BY bukrs belnr gjahr buzei.
"Looping cabeçalho
LOOP AT lt_bkpf INTO ls_bkpf.
"Pega índice do registro (sy-tabix)
READ TABLE lt_bseg
WITH KEY bukrs = ls_bkpf-bukrs
belnr = ls_bkpf-belnr
gjahr = ls_bkpf-gjahr
TRANSPORTING NO FIELDS
BINARY SEARCH.
"Verifica se encontrou registro
CHECK sy-subrc = 0.
"Looping item
LOOP AT lt_bseg INTO ls_bseg FROM sy-tabix.
"Verifica se chave do registro mudou, se sim, sai do looping no item
IF ls_bkpf-bukrs <> ls_bseg-bukrs
OR ls_bkpf-belnr <> ls_bseg-belnr
OR ls_bkpf-gjahr <> ls_bseg-gjahr.
EXIT.
ENDIF.
"Faz alguma coisa
"Faz outra coisa
ENDLOOP.
ENDLOOP.
REPORT zlooping.
DATA:
lt_bkpf TYPE STANDARD TABLE OF bkpf,
lt_bseg TYPE STANDARD TABLE OF bseg,
ls_bkpf TYPE bkpf,
ls_bseg TYPE bseg.
"Ordenar para BINARY SEARCH
SORT:
lt_bkpf BY bukrs belnr gjahr,
lt_bseg BY bukrs belnr gjahr buzei.
"Looping cabeçalho
LOOP AT lt_bkpf INTO ls_bkpf.
"Pega índice do registro (sy-tabix)
READ TABLE lt_bseg
WITH KEY bukrs = ls_bkpf-bukrs
belnr = ls_bkpf-belnr
gjahr = ls_bkpf-gjahr
TRANSPORTING NO FIELDS
BINARY SEARCH.
"Verifica se encontrou registro
CHECK sy-subrc = 0.
"Looping item
LOOP AT lt_bseg INTO ls_bseg FROM sy-tabix.
"Verifica se chave do registro mudou, se sim, sai do looping no item
IF ls_bkpf-bukrs <> ls_bseg-bukrs
OR ls_bkpf-belnr <> ls_bseg-belnr
OR ls_bkpf-gjahr <> ls_bseg-gjahr.
EXIT.
ENDIF.
"Faz alguma coisa
"Faz outra coisa
ENDLOOP.
ENDLOOP.
Basicamente a mudança se dá na utilização de índices para leitura da tabela interna.
O grande segredo aqui é a utilização do SORT e do READ TABLE com BINARY SEARCH. Utilizar BINARY SEARCH significa que a leitura na tabela interna não será sequêncial, ou seja, não irá ler uma linha de cada vez até terminar de ler todos os registros, a leitura será binária (leia sobre os riscos: http://agilpioneiro.wordpress.com/2012/04/02/binary-search-uma-roleta-russa-com-o-tambor-cheio).
Resumindo, não precisamos e não vamos ler a BSEG inteira, iremos ler a partir do primeiro registro encontrado para a chave informada até a chave do item mudar, quando não for mais a mesma chave do cabeçalho saí do looping no item e vai para o próximo registro do cabeçalho. Simples não?
E, para ficar melhor ainda, ao invés de utilizar o LOOP AT tabela INTO workarea, utilize LOOP AT tabela ASSIGNING fieldsymbol. Aqui teremos um ganho de desempenho, pois ao invés de copiar todo o registro para uma workarea iremos utilizar um ponteiro que indica a posição da linha da tabela na memória. Sempre que possível utilize ponteiros (FIELD-SYMBOL) para ler suas tabelas internas. Sempre haverá ganho de desempenho.
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Performance/nested_looping.abap
*&---------------------------------------------------------------------**& Report ZNESTED_LOOPING*&*&---------------------------------------------------------------------**& ABAP Sample Code*& Performance in nested looping*&*& Maurício Lauffer - Brazil - 08.01.2012*& http://www.linkedin.com/in/mauriciolauffer*&*& This sample explains how to use nested looping with performance*&*&---------------------------------------------------------------------*REPORT znested_looping.DATA:gt_bkpf TYPE STANDARD TABLE OF bkpf,gt_bseg TYPE STANDARD TABLE OF bseg.FIELD-SYMBOLS:TYPE bkpf, TYPE bseg. "Select headerSELECT * UP TO 500 ROWSFROM bkpfINTO TABLE gt_bkpf.IF sy-subrc <> 0.RETURN.ENDIF."Select itemsSELECT *FROM bsegINTO TABLE gt_bsegFOR ALL ENTRIES IN gt_bkpfWHERE bukrs = gt_bkpf-bukrsAND belnr = gt_bkpf-belnrAND gjahr = gt_bkpf-gjahr."Looping into headerLOOP AT gt_bkpf ASSIGNING. "Get index (sy-tabix) for the first occurrence"You must guarantee that the table is sorted by the keys used in BINARY SEARCHREAD TABLE gt_bseg TRANSPORTING NO FIELDSWITH KEY bukrs =-bukrs belnr =-belnr gjahr =-gjahr BINARY SEARCH.CHECK sy-subrc = 0."Looping into items from index which we got beforeLOOP AT gt_bseg ASSIGNINGFROM sy-tabix. "Check the table key, if it has changed, leave this loopingIF-bukrs <> -bukrs OR-belnr <> -belnr OR-gjahr <> -gjahr. EXIT.ENDIF."Do stuff...ENDLOOP.ENDLOOP.
Link do código no GitHub:
https://github.com/mauriciolauffer/ABAP/blob/master/Performance/nested_looping.abap
sexta-feira, 13 de janeiro de 2012
Projetos Open Source
O blog ABAP101 criou uma ótima oportunidade para ABAPers que estão começando, e não sabem onde treinar suas novas técnicas, poderem brincar um pouco mais sério. Para os mais antigos também é uma boa oportunidade de aprender novos truques.
São projetos open source com características de projetos reais. Prazos, tarefas delegadas, padrões e tudo mais que tem direito. Segue o link para aqueles que sempre têm interesse em aprender um pouco mais.
São projetos open source com características de projetos reais. Prazos, tarefas delegadas, padrões e tudo mais que tem direito. Segue o link para aqueles que sempre têm interesse em aprender um pouco mais.
segunda-feira, 10 de janeiro de 2011
Limitar o número de registros de um SELECT (ABAP Open SQL)
É comum necessitarmos limitar o número de registros retornados de um SELECT, seja qual for o banco de dados que estejamos utilizando.
Suponhamos que precisamos apenas de 10 linhas e que na tabela tenha mais do que 10 registros.
No Microsoft SQL Server utilizaríamos:
SELECT TOP 10 * FROM table.
No MySQL:
SELECT * FROM table LIMIT 0, 10.
E utilizando ABAP Open SQL no SAP:
SELECT * UP TO 10 ROWS FROM table INTO TABLE it_table.
Suponhamos que precisamos apenas de 10 linhas e que na tabela tenha mais do que 10 registros.
No Microsoft SQL Server utilizaríamos:
SELECT TOP 10 * FROM table.
No MySQL:
SELECT * FROM table LIMIT 0, 10.
E utilizando ABAP Open SQL no SAP:
SELECT * UP TO 10 ROWS FROM table INTO TABLE it_table.
sábado, 14 de agosto de 2010
Tipos de dados standards no ABAP
Os tipos de dados standards no ABAP, predefinidos pela SAP, são divididos em dois grupos: tipos completos e tipos incompletos. Os tipos completos possuem o comprimento da variável fixo não podendo ser alterado. Nos tipos incompletos o comprimento da variável deve ser informado.
Tipos completos:
Tipos incompletos:
Os tipos I, F e P são os únicos tipos numéricos. Todos os outros tipos são alfanuméricos.
Tipos completos:
- D - tipo para data, formato YYYYMMDD, comprimento 8 (fixo);
- T - tipo para tempo, formato HHMMSS, comprimento 6 (fixo);
- I - tipo para inteiros, comprimento 4 (fixo);
- F - tipo para número em ponto flutuante, comprimento 8 (fixo);
- STRING - tipo para caracteres de comprimento dinâmico;
- XSTRING - tipo para hexadecimal de comprimento dinâmico.
Tipos incompletos:
- C - tipo para caracter;
- N - tipo para caracter numérico;
- X - tipo para hexadecimal;
- P - tipo para número embalado, o número de casas decimais também pode ser especificado.
Os tipos I, F e P são os únicos tipos numéricos. Todos os outros tipos são alfanuméricos.
Assinar:
Postagens (Atom)