domingo, 14 de agosto de 2016

SAPUI5 trabalhando com dados offline com jQuery.sap.storage

Como trabalhar com dados offline usando jQuery.sap.storage em apps SAPUI5?

Confira no link do post que fiz na SCN sobre o assunto.


http://scn.sap.com/community/developer-center/front-end/blog/2014/06/29/sapui5-offline-with-jquerysapstorage

SAPUI5 - Upload de arquivos, "slug" com caracteres especiais

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

Hospedando SAPUI5 app no Google Drive

Como hospedar um app SAPUI5 no Google Drive?

Confira no link do post que fiz na SCN sobre o assunto.


http://scn.sap.com/community/portuguese/blog/2014/08/28/hospedando-sapui5-app-no-google-drive

http://scn.sap.com/community/developer-center/front-end/blog/2014/05/28/google-drive-hosting-sapui5-apps

terça-feira, 15 de setembro de 2015

SCN Meetup Porto Alegre 2015 - Sessão de SAPUI5


Screen Shot 2015-09-12 at 6.19.01 PM.png


OpenUI5_text_below.png

Temos o prazer em anunciar o primeiro SCN Meet-Up Porto Alegre. O evento terá como tema o desenvolvimento de aplicações com  SAPUI5.

Será uma sessão única sobre o que é o UI5, particularidades e uso, bem como você poderá acompanhar no estilo CodeJam o desenvolvimento de uma aplicação ao vivo seguindo as melhores práticas recomendadas pela SAP.

O evento será realizado na Fontoura Education no próximo dia 24 de setembro das 19:00 as 22:30.




Participe! Não perca a oportunidade de aprender e conhecer outros profissionais da área em um ambiente informal.



Palestrante

Untitled2.png

Maurcio Lauffer – sim, eu mesmo    =)




Inscrições Abertas
Para se inscrever clique no link -> Inscrição

Local e Data
Onde: Fontoura Education - Av. Protásio Alves, 2561 conj. 603 - Petrópolis - Porto Alegre/RS
Quando: Quinta-feira 24 de setembro de 2015
Horário: 19:00 as 22:30.
Custo: Gratuíto.
Número de Participantes: Max 18 participantes.

Para maiores informações:
Twitter hashtags : #meetuppoa or #scnpoa
Siga-nos no Twitter: @sapinsidetrack e @sitbrazil
Para mais informações send an email to sapinsidetrackbrazil@gmail.com


Realização:
Snap13.jpg


Apoio:

fontoura.png

Maiores informações sobre UI5





Postado originalmente em:


quinta-feira, 16 de outubro de 2014

Desafio DataGeek III: SAP Lumira

A SAP lançou um desafio para toda a comunidade explorar o SAP Lumira.
O desafio é o SAP DataGeek III e você pode conferir todos os detalhes no próprio site:http://www.sap.com/datageek

Também foi postado um vídeo de divulgação no Youtube, o vídeo está sensacional!

O SAP Lumira é uma ferramenta para análise de dados, muito poderosa, com interface simples e intuitiva.
O desafio consiste basicamente em pegar uma massa de dados, analisar e descobrir os segredos e relações que os dados ocultam.

Eu resolvi entrar na brincadeira e descobrir como o SAP Lumira funcionava. Para tanto, decidi analisar os dados do atual Governo do meu estado, Rio Grande do Sul. Usei os dados públicos disponibilizados no Portal Transparência do RS. Baixei os arquivos .CSV e criei os datasets no SAP Lumira para começar a análise.

Completei a tarefa e postei o resultado no blog do SAP Lumira (SAP Lumira) para participar do desafio.
O resultado completo pode ser conferido aqui: Data Geek III Challenge - Analysing Government Expenses and Investments

Ainda dá tempo para participar! O desafio vai até o dia 15 de novembro.
Vá ao site, leia sobre o desafio, baixe o SAP Lumira e comece a brincadeira

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

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:


*&---------------------------------------------------------------------*
*& 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 subject
  gc_email_to TYPE adr6-smtp_addr VALUE 'frodo.baggins@lotr.com', " Valid email
  gc_text TYPE soli VALUE 'Hello world! My first ABAP email with attachment!', " Text used into the email body
  gc_type_raw TYPE so_obj_tp VALUE 'RAW', " Email type
  gc_att_type TYPE soodk-objtp VALUE 'PDF', " Attachment type
  gc_att_subject TYPE sood-objdes VALUE 'Document in PDF'. " Attachment title
DATA:
  gt_text TYPE soli_tab, " Table which contains email body text
  gt_attachment_hex TYPE solix_tab, " Table which contains the attached file
  gv_sent_to_all TYPE os_boolean, " Receive the information if email was sent
  gv_error_message TYPE string, " Used to get the error message
  go_send_request TYPE REF TO cl_bcs, " Email object
  go_recipient TYPE REF TO if_recipient_bcs, " Who will receive the email
  go_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the email
  go_document TYPE REF TO cl_document_bcs, " Email body
  gx_bcs_exception TYPE REF TO cx_bcs.
TRY.
    "Create send request
    go_send_request = cl_bcs=>create_persistent( ).
    "Email FROM...
    go_sender = cl_sapuser_bcs=>create( sy-uname ).
    "Add sender to send request
    go_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 request
    go_send_request->add_recipient(
      EXPORTING
        i_recipient = go_recipient
        i_express = abap_true
    ).
    "Email BODY
    APPEND gc_text TO gt_text.
    go_document = cl_document_bcs=>create_document(
                    i_type = gc_type_raw
                    i_text = gt_text
                    i_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.
    "Attachment
    go_document->add_attachment(
      EXPORTING
        i_attachment_type = gc_att_type
        i_attachment_subject = gc_att_subject
        i_att_content_hex = gt_attachment_hex
    ).
    "Add document to send request
    go_send_request->set_document( go_document ).
    "Send email and get the result
    gv_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 email
    COMMIT WORK.
    "Exception handling
  CATCH 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:




*&---------------------------------------------------------------------*
*& 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 subject
  gc_email_to TYPE adr6-smtp_addr VALUE 'frodo.baggins@lotr.com', " Valid email
  gc_text TYPE soli VALUE 'Hello world! My first ABAP email!', " Text used into the email body
  gc_type_raw TYPE so_obj_tp VALUE 'RAW'. " Email type
DATA:
  gt_text TYPE soli_tab, " Table which contains email body text
  gv_sent_to_all TYPE os_boolean, " Receive the information if email was sent
  gv_error_message TYPE string, " Used to get the error message
  go_send_request TYPE REF TO cl_bcs, " Email object
  go_recipient TYPE REF TO if_recipient_bcs, " Who will receive the email
  go_sender TYPE REF TO cl_sapuser_bcs, " Who is sending the email
  go_document TYPE REF TO cl_document_bcs, " Email body
  gx_bcs_exception TYPE REF TO cx_bcs.
TRY.
    "Create send request
    go_send_request = cl_bcs=>create_persistent( ).
    "Email FROM...
    go_sender = cl_sapuser_bcs=>create( sy-uname ).
    "Add sender to send request
    go_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 request
    go_send_request->add_recipient(
      EXPORTING
        i_recipient = go_recipient
        i_express = abap_true
    ).
    "Email BODY
    APPEND gc_text TO gt_text.
    go_document = cl_document_bcs=>create_document(
                    i_type = gc_type_raw
                    i_text = gt_text
                    i_length = '12'
                    i_subject = gc_subject ).
    "Add document to send request
    go_send_request->set_document( go_document ).
    "Send email and get the result
    gv_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 email
    COMMIT WORK.
    "Exception handling
  CATCH 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.


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.


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.


*&---------------------------------------------------------------------*
*& 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 header
SELECT * UP TO 500 ROWS
  FROM bkpf
  INTO TABLE gt_bkpf.
IF sy-subrc <> 0.
  RETURN.
ENDIF.
"Select items
SELECT *
  FROM bseg
  INTO TABLE gt_bseg
  FOR ALL ENTRIES IN gt_bkpf
  WHERE bukrs = gt_bkpf-bukrs
    AND belnr = gt_bkpf-belnr
    AND gjahr = gt_bkpf-gjahr.
"Looping into header
LOOP 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 SEARCH
  READ TABLE gt_bseg TRANSPORTING NO FIELDS
       WITH KEY bukrs = -bukrs
                belnr = -belnr
                gjahr = -gjahr
       BINARY SEARCH.
  CHECK sy-subrc = 0.
  "Looping into items from index which we got before
  LOOP AT gt_bseg ASSIGNING FROM sy-tabix.
    "Check the table key, if it has changed, leave this looping
    IF -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