Debug oltre ogni limite

Senza un po’ di sana pratica di debug, nessuno può dirsi uno sviluppatore ABAP..

Ecco qui un trucchetto molto utile, quando ad esempio non si riesce a entrare in debug con il classico /H, come nel caso di una popup oppure di un menu contestuale al tasto destro del mouse.

Si crea un file di testo (privo di estensione) con il seguente codice:

*********************
[FUNCTION]
Command=/HS
Title=Debugger
Type=SystemCommand
*Type=Report
*Type=Transaction
********************* LOOK AT MESS DS-016

Tale file va poi messo in luogo comodo come il desktop; al momento di debaggare l’impossibile è sufficiente trascinare il file sul modo sap aperto che si desidera approfondire. E buon F5 a tutti.

Posted under ABAP

This post was written by Alberto on aprile 1, 2010

Tags:

Tutto quello che c’è dentro un report

Purtroppo è facile creare report mastodontici pieni di include, chiamate a funzioni, moduli PAI e PBO… E almeno una volta nella vita può capitare di dover andare a ripescare tutti questi elementi, anche solo per  avere la certezza che una CR contenga tutto il necessario.

In questo ci viene d’aiuto il report standard RSINCL00, tramite il quale, dato il nome di un report da analizzare, possiamo ricavare di tutto e di più: oggetti interni, chiamate esterne, operazioni tabelle interne e operazioni database.

Posted under ABAP

This post was written by Alberto on dicembre 15, 2009

AA(A) – Creazione Cespiti

Ci troviamo nel fantastico mondo dei cespiti (detti anche fixed assets) e vorremmo procedere alla creazione da report, sentendoci superiori agli inaffidabili batch input.

Ecco qui uno schema pratico tramite bapi:

-Qualche dichiarazione:

DATA:  ls_general_data TYPE bapi1022_feglg001,
 ls_key TYPE bapi1022_key,
 ls_general_data_x TYPE bapi1022_feglg001x,
 ls_inventory TYPE bapi1022_feglg011,
 ls_inventory_x TYPE bapi1022_feglg011x,
 ls_posting_information TYPE bapi1022_feglg002,
 ls_posting_information_x TYPE bapi1022_feglg002x,
 ls_time_dependent_data TYPE bapi1022_feglg003,
 ls_time_dependent_data_x TYPE bapi1022_feglg003x,
 ls_allocations TYPE bapi1022_feglg004,
 ls_allocations_x TYPE bapi1022_feglg004x,
 ls_origin TYPE bapi1022_feglg009,
 ls_origin_x TYPE bapi1022_feglg009x,
 ls_invest_acct_assignmnt TYPE bapi1022_feglg010,
 ls_invest_acct_assignmnt_x TYPE bapi1022_feglg010x,
 ls_real_estate TYPE bapi1022_feglg007,
 ls_real_estate_x TYPE bapi1022_feglg007x,
 ls_return TYPE bapiret2.


Fondamentalmente è sufficiente compilare nel modo giusto le strutture sopracitate con i dati giusti al posto giusto, e poi richiamare la seguente bapi (ricordarsi di riempire sia le strutture con i dati, che le rispettive strutture flag con gli ‘X’ corrispondenti..)

 
 CALL FUNCTION 'BAPI_FIXEDASSET_CREATE1'
 EXPORTING
 key = ls_key
 createsubnumber             =        createsub
 postcap               = postcap
 *       testrun              = 'X'           "TEST
 generaldata          = ls_general_data
 generaldatax         = ls_general_data_x
 *       inventory            = ls_inventory
 *       inventoryx           = ls_inventory_x
 postinginformation   = ls_posting_information
 postinginformationx  = ls_posting_information_x
 timedependentdata    = ls_time_dependent_data
 timedependentdatax   = ls_time_dependent_data_x
 allocations          = ls_allocations
 allocationsx         = ls_allocations_x
 origin               = ls_origin
 originx              = ls_origin_x
 *       investacctassignmnt  = ls_invest_acct_assignmnt
 *       investacctassignmntx = ls_invest_acct_assignmnt_x
 *       realestate           = ls_real_estate
 *       realestatex          = ls_real_estate_x
 IMPORTING
 assetcreated         = ps_ls_asset_created
 return = ls_return.

 IF ls_return-type = 'S'.
 COMMIT WORK AND WAIT.
 ELSE.
 CLEAR: ps_ls_asset_created.
 ps_ws_error = ls_return-message.
 ENDIF. 


A seconda del customizing e della classe cespiti possono accadere diverse cose.

Sicuramente i campi ls_key-companycode (società/BUKRS) e ls_general_data-assetclass (classe cespiti/ANKL) sono obbligatori.

A seconda del customizing, per ogni classe cespiti abbiamo range di numerazione diversi:

- Se il range è esterno, sarà necessario compilare anche il campo Numero Cespite ( ls_key-ASSET ) e il campo Numero Cespite Secondario ( ls_key-SUBNUMBER)

- Altrimenti se c’è numerazione interna, è necessario pescare sull’ANLA l’ultimo numero generato per la classe cespite desiderata.

Comunque ricordiamoci che se vogliamo generare un cespite secondario, è necessario flaggare il parametro CREATESUBNUMBER.

Se vogliamo creare un cespite a partire da oggetti già esistenti, possono essere utili le funzioni *MAP* del gruppo funzioni 1022, pescando i dati dalle anagrafiche ANLA e ANLZ e mapparli nelle strutture ad hoc della bapi.

Buon divertimento!


Posted under AA - cespiti, ABAP, BAPI

This post was written by Alberto on luglio 27, 2009

Tags: ,

Log per all’interno di un report custom SAP (visualizzabile da SLG1).

Questi sono i passi da seguire per inserire il log standard all’interno di un report custom SAP.
Il log una volta creato sarà visualizzabile tramite la transazione SLG1.

  • 1) Creazione tramite la transazione SLG0 di un nuovo “tipo oggetto” di log.
  • 2) Inizializzazione variabili
    * Dati per log tramite SLG0
    data: gs_log type bal_s_log,
    gs_log_handle type balloghndl,
    gt_log_handle type bal_t_logh,
    gs_msg type bal_s_msg,
    gt_new_lognumbers type bal_t_lgnm.
  • 3) Chiamata a function BAL_LOG_CREATE all’inizio dell’esecuzione.
  • 4) Aggiunta di messaggi al log tramite la function BAL_LOG_MSG_ADD.
  • 5) Come ultimo step del report inserire la function BAL_DB_SAVE che sostanzialmente effettua un commit dei messaggi di log aggiunti.
  • 6) Una volta eseguito il report si possono verificare i risultati dalla transazione SLG1.

Posted under ABAP, Blog, function

This post was written by Alberto on gennaio 8, 2009

Tags: ,

Spedire mail con allegato

Ecco come spedire in modo automatico mail con diverse impostazioni. Utilizziamo la funzione standard SO_NEW_DOCUMENT_ATT_SEND_API1, non proprio ben commentata.

Ecco dell’ottimo sample code commentato come si deve .

Cominciamo con un po’ di definizioni

DATA: lt_att_content_hex TYPE TABLE OF solix,
lf_lines  TYPE i,
la_mailpack TYPE sopcklsti1,
lt_mailpack TYPE TABLE OF sopcklsti1,
la_maildata TYPE sodocchgi1,
lt_receiver TYPE TABLE OF somlreci1,
ls_receiver TYPE somlreci1,
lt_mailhead TYPE TABLE OF solisti1,
ls_mailhead TYPE solisti1,
lt_mailtxt  TYPE TABLE OF solisti1,
ls_mailtxt TYPE solisti1.

Qui ci sta l’oggetto della mail:

la_maildata-obj_name = 'nome oggetto'.
la_maildata-obj_descr = 'Invio OdA'.

Qui mettiamo il testo della mail: da notare la necessità di ricavare la  lunghezza del testo

ls_mailtxt = 'vd. allegato'.
APPEND ls_mailtxt TO lt_mailtxt.

DESCRIBE TABLE lt_mailtxt LINES lf_lines.
READ TABLE lt_mailtxt INTO ls_mailtxt INDEX lf_lines.

la_maildata-doc_size = ( lf_lines - 1 ) * 255 + STRLEN( ls_mailtxt ).

CLEAR la_mailpack-transf_bin.
la_mailpack-head_start = 1.
la_mailpack-head_num = 0.
la_mailpack-body_start = 1.
la_mailpack-body_num = lf_lines.
la_mailpack-doc_type = 'RAW'.
APPEND la_mailpack TO lt_mailpack.

Aggiungiamo i destinatari della mail

ls_receiver-receiver = 'ciccio@pasticcio.it'.
ls_receiver-rec_type = 'U'. "tipo indirizzo->mail
APPEND ls_receiver TO lt_receiver.

Ora da qualche parte, per esempio nella generazione di un pdf, abbiamo riempito la tabellina lt_att_content_hex del sorgente binario dell’allegato desiderato.

DESCRIBE TABLE lt_att_content_hex LINES lf_lines.
la_maildata-doc_size = lf_lines * 255."( lf_lines - 1 ) * 255 + STRLEN( ls_mailtxt ).

la_mailpack-transf_bin = 'X'.
la_mailpack-head_start = 1.
la_mailpack-head_num = 0.
la_mailpack-body_start = 1.
la_mailpack-doc_type = 'PDF'.
la_mailpack-body_num = lf_lines.
la_mailpack-doc_size = lf_lines * 255.
la_mailpack-obj_descr = 'the allegat'.
la_mailpack-obj_name = 'Allegato'.
APPEND la_mailpack TO lt_mailpack.

Possiamo allo stesso modo aggiungere altri allegati, ora lanciamo la mail:

CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
EXPORTING
document_data = la_maildata
put_in_outbox = 'X'
commit_work = 'X'
TABLES
packing_list = lt_mailpack
contents_txt = lt_mailtxt
contents_hex = lt_att_content_hex
receivers = lt_receiver .

Ora se tutto è andato bene, possiamo andare nella SOST per vedere l’anteprima della mail generata e inviata a seconda della configurazione.

Mi raccomando, occhio allo spam!!!

Posted under ABAP, function

This post was written by Alberto on dicembre 16, 2008

Debug su USER EXIT

Nelle user exit non è consentito inserire break-point.
Se è necessario effettuare il debug esiste una semplice tecnica:
si inserisce il seguente codice prima della parte di programma che si vuole analizzare, ovviamente mettendo al posto di username il proprio user.

if sy-uname = 'mio_username'.
data: pippo type char1.
do.
check pippo EQ 'X'.
exit.
enddo.
ENDIF.

Una volta lanciata la transazione che scatena la exit:

  • 1) si lancia la transazione SM50
  • 2) si seleziona la riga che rappresenta il processo.
  • 3) dal menu : Programma/sessione-> Programma-> Debugging.

A questo punto basta modificare a mano il valore della variabile pippo a ‘X’ e
diventa quindi possibile debuggare il programma passo passo.

Posted under ABAP

This post was written by Damiano on dicembre 10, 2008

Tags: , ,

PDF nelle Web-Dynpro – parte 2

Precedentemente abbiamo avuto cura di riempire un attributo del context con il sorgente esadecimale del pdf.
Ora pensiamo al layout:

  • creiamo una view che chiamiamo V_PDF, in cui inseriamo un unico elemento, di tipo InteractiveForm; nel context mappiamo dal ComponentController il nodo contenente il PDF;
  • Nella view dove vogliamo inserire il PDF inseriamo un elemento di tipo ViewContainerUIElement;
  • Nella window clicchiamo con il tasto destro nelle view principale dove vediamo il tale ViewContainerUIElement e includiamo la V_PDF;
  • Infine è buona norma, per non impallare il browser, togliere il flag dalla proprietà “Enabled” del ViewContainerUIElement;

A questo punto il gioco è fatto; al momento del riempimento del nodo PDF, verrà riempita la sottoschermata con il nostro documento visualizzato tramite un’istanza del nostro PDF Viewer preferito.

Posted under ABAP, web dynpro

This post was written by Alberto on novembre 27, 2008

Trovare una BADI

TROVARE UNA BADI IN UN MINUTO

1. Andare alla transazione SE24 e inserire CL_EXITHANDLER come classe.
2. In ‘Display’ mode, andare al tab ‘Methods’.
3. Doppio click sul metodo ‘Get Instance’ per visualizzare il codice sorgente.
4. Mettere un breakpoint nella ‘CALL METHOD cl_exithandler=>get_class_name_by_interface’.
5. Lanciare la tua transazione.
6. Lo screen si fermerá sul breakpoint del punto 4.
7. Guardare il valore del parametro ‘EXIT_NAME’. Ci sará il nome della BADI per questa transazione.

Posted under ABAP, BADI

This post was written by Damiano on novembre 25, 2008

PDF nelle Web-Dynpro – parte 1

Come utilizzare le Web-Dynpro per visualizzare PDF, che possono provenire da smartforms oppure da file salvati nel server?
Lo vedremo ora.
Come prima cosa è necessario ricavare il sorgente esadecimale del PDF. Nel context costruiamo un nodo di cardinalità 1 che chiamiamo PDF, con un attributo SOURCE di tipo XSTRING.
Se non abbiamo a disposizione il sorgente del PDF, utilizziamo lo smartform nel seguente modo:

 DATA:
 lv_function_name        TYPE rs38l_fnam,
 ls_control_parameters   TYPE ssfctrlop,
 ls_output_options       TYPE ssfcompop,
 ls_document_output_info TYPE ssfcrespd,
 ls_job_output_info      TYPE ssfcrescl,
 ls_job_output_options   TYPE ssfcresop.
DATA:
 lt_pdf_lines             TYPE TABLE OF tline,
 lv_bin_filesize          TYPE i,
 lv_mimetype(30)          TYPE c.
ls_control_parameters-getotf = 'X'.
 ls_output_options-tdimmed = space.
 ls_output_options-tdnewid = space.
 ls_control_parameters-no_dialog = 'X'.
CALL FUNCTION lv_function_name
 EXPORTING
 control_parameters   = ls_control_parameters
 output_options       = ls_output_options
 *     ... = ...
 IMPORTING
 document_output_info = ls_document_output_info
 job_output_info      = ls_job_output_info
 job_output_options   = ls_job_output_options
 EXCEPTIONS
 FORMATTING_ERROR     = 1
 INTERNAL_ERROR       = 2
 SEND_ERROR           = 3
 USER_CANCELED        = 4
 OTHERS               = 5.
CALL FUNCTION 'CONVERT_OTF'
 EXPORTING
 format                = 'PDF'
 IMPORTING
 bin_filesize          = lv_bin_filesize
 bin_file              = lv_source
 TABLES
 otf                   = ls_job_output_info-otfdata
 lines                 = lt_pdf_lines
 EXCEPTIONS
 err_max_linewidth     = 1
 err_format            = 2
 ERR_CONV_NOT_POSSIBLE = 3
 ERR_BAD_OTF           = 4.

A questo punto in LV_SOURCE abbiamo il sorgente del PDF (sempre che non ci siano stati errori, che è meglio gestire… ma ne parleremo un’altra volta)

Alla prossima puntata per vedere come visualizzare l’anteprima…

Posted under ABAP, web dynpro

This post was written by Alberto on ottobre 10, 2008

Select Options How-To

Il tema di oggi è riempire a codice una tabellina di selezioni da fornire per esempio a una function.
La struttura consigliata per la tabella è la RSDSSELOPT (invece di definirci ogni volta il tipo adatto…), formata da:

SIGN(1): ‘I’ per i valori da includere, ‘E’ per quelli da escludere;

OPTION(2): l’operatore per la selezione, EQ, GT, LT, NE,…

LOW (45): il primo di valore per il confronto;

HIGH(45) :l’unico facoltativo, si usa insieme a LOW per definire un range di valori.

E con questo… buone select a tutti!

Posted under ABAP

This post was written by Alberto on giugno 16, 2008