Come predisporre la stampa di un report (senza conoscere l’RPG)

Il componente H53 fornisce uno strumento per generare file PDF. In questo post vedremo cosa fare per generare un PDF utilizzando gli appositi script di configurazione (SCP_G53)

Esistono sostanzialmente due tipi di stampe generabili tramite script con la H53, quelle che chiameremo “a struttura fissa” e quelle che chiameremo “a struttura dinamica”.

Per Stampe a “struttura fissa”, particolarmente indicate per i moduli elettronici (quali ddt, fattura, conferma ordine, ecc.) intendiamo quel tipo di stampa dove la struttura/forma è predefinita dalla grafica che vorrò avere nel PDF (tramite lo script). Saranno fissi header, footer, loghi, contorni. Se pensiamo ad una fattura abbiamo ben presente che gli spazi nel PDF sono fissati e i dati si devono adeguare e rimanere in questi spazi (il cosiddetto “prefincato“)

Per Stampe a “struttura dinamica”, particolarmente indicate invece per i report gestionali, intendiamo invece un tipo di stampa dove i dati hanno più rilevanza della struttura del PDF, che non può essere definita a priori perché non si conosce cosa dovrà essere stampato.

Ad esempio tutti gli ordini aperti di un cliente, o l’eleco di tutti i pagamenti arrivati in ritardo in un singolo mese, o le opportunità in scadenza fino alla fine dell’anno.

Banalizzando: si tratta di raccogliere in uno script tutte le funzioni che si vogliono stampare

In questo post ci focalizzeremo sul secondo tipo di stampe: quelle a struttura dinamica.

Lo Script

La prima cosa da fare è preparare lo script SCP_G53.

Lo script si compone di 3 parti:

  1. Definizioni Generali
  2. Definizione delle pagine (Struttura del PDF)
    • Header
    • Body
    • Footer
  3. Definizione dei dati (Le funzioni da stampare)

Definizioni Generali

  • Imposto le definizioni di base del PDF, il formato del foglio (A3/A4/…) se deve essere salvato in una particolare cartella con un particolare nome, e tutte le altre informazioni che caratterizzano il PDF in quanto tale.

Nello script vengono già utilizzate le variabili (identificabile da &PA ) che saranno poi impostate nella FUN chiamante nel campo P(), ad esempio P(Nam(report.pdf)) significa che la variabile &Pa.Nam varrà “report.pdf.

::STR.SET Show="&PA.Pre" Format="A4" Orientation="V" Cover="No" PathDir="&PA.Dir" NameFile="&PA.Nam" OpenDoc="&PA.Opn" Temp="No"

Definizioni delle pagine (Struttura del PDF)

  • In base alle definizioni generali dobbiamo impostare la struttura dei PDF che vorremo avere.
::STR.PAG Nam="P01"  La="100" Ha="100"

In questo esempio vogliamo definire una pagina che chiamiamo P01.

Volendo posso impostare uno sfondo/filigrana alla pagina includendo il percorso dove è possibile recuperare il file PDF da utilizzare.

::INC File=\\srv.azienda.com\moduli\Report\FiligranaAzienda1.PDF

La struttura delle sezioni Header/Body/Footer della nostra pagina P01 è simile alla costruzione di una scheda nello script SCP_SCH, dovendo impostare le dimensioni delle righe STR.RIG che compongono la sezione globale STR.BOX. Ogni riga può essere a suo volta composta da una o più colonne STR.COL.

Ogni sezione può essere riempita con Costanti, Funzioni, Immagini, Ecc.

HEADER

Definizione

::STR.BOX Nam="BH1" Sx="03" Sy="02" La="93" Ha="07" Typ="HEADER"
 ::STR.RIG Nam="RH1" Num="45%"
  ::STR.COL Nam="CH1" Dim="60"
   ::BOX A01="A" A02="K" A03="-" A05="K" A07="B" A08="B" Txt="REPORT ACCOUNT" A11="L"
 ::STR.RIG Nam="RH1" Num="35%"
  ::STR.COL Nam="CH1" Dim="60"
   ::BOX A01="A" A02="I" A03="-" A05="I" A07="B" A08="B" Txt="&PA.DesAcc" A11="L"
 ::STR.RIG Nam="RH1" Num="25%"
  ::STR.COL Nam="CH1" Dim="60"
   ::BOX A01="A" A02="A" A03="-" A05="I" A07="B" A08="B" Txt="Data Report:  &D8.OGI00" A11="L"
::STR.RIG Nam="RF0"  Num="20"
  ::STR.COL Nam="CF0"  Dim="100"
   ::LIN A07="A"

Notate la similitudine della definizione di una scheda, in questo esempio è previsto un BOX (STR.BOX) con 4 sezioni orizzontali STR.RIG (come se fossero la 1,2,3,4 di una scheda) ogni sezione è fatta da una colonna (ma potrebbero essere di più) STR.COL

Le prime tre righe sono di testo (::BOX) (due con costanti e una con la variabile della descrizione dell’account), vedete nell’immagine sottostante che ogni sezione ha diverse caratteristiche di font, grandezza, ecc. impostabili tramite i vari paremetri, per i quali potrete contare sull’aiuto del wizard dell’editor di Looc.UP (Ctrl-W).

L’ultima sezione stampa invece una Linea continua nera (::LIN)  di una determinata altezza. L’immagine (in questo caso il logo del Gruppo Sme.UP) viene impostata dal PDF di sfondo impostato precedentemente recuperandolo da: FiligranaAzienda1.PDF

BODY

Nel Body devo definire tutte le possibili forme che utilizzerò poi con i dati e che saranno richiamate successivamente. Non imposto i dati in questa sezione, diciamo che impostiamo le “informazioni di contorno”.

Posso prevedere sezioni/righe di testo, righe dove saranno stampati grafici, immagini, linee, e soprattutto matrici. Ogni ::BOX ha molte proprietà che possono caratterizzarne la sezione.

Definizione

::STR.BOX Nam="B02" Sx="03" Sy="10" La="93" Ha="85"

Titolo sezioni
::STR.RIG Nam="RTI" Num="30"
 ::STR.COL Nam="CC1" Dim="100"   
  ::BOX A01="A" A02="C" A03="B" A04="A" A05="G" A07="-" A08="-" A11="L"

Sezione Matrice con bordi 
::STR.RIG Nam="MATBOR" Num="30" 
 ::STR.COL Nam="CC1" Dim="100"
  ::BOX A01="A" A02="8" A03="-" A04="A" A05="8" A07="A" A10="X" A11="L"

Sezione Matrice con bordi che USA LE LUNGHEZZE DEFINITE NEL SERVIZIO
::STR.RIG Nam="MATSER" Num="30"
 ::STR.COL Nam="CC1" Dim="100"
  ::BOX A01="A" A02="B" A03="-" A04="A" A05="E" A07="J" A10="X" A11="L" A13="1" A14="1"

FOOTER

Definizione

::STR.BOX Nam="BF3" Sx="03" Sy="93" La="95" Ha="05" Typ="FOOTER"
 ::STR.RIG Nam="RF0"  Num="20"
  ::STR.COL Nam="CF0"  Dim="100"
   ::LIN A07="A"
 ::STR.RIG Nam="RF1" Num="90%"
  ::STR.COL Nam="CF2"  Dim="85"
   ::BOX A01="A" A02="9" A03="-" A05="9" A07="B" A08="B" Txt="Questo documento è di proprietà di SME UP S.p.A. e solamente per uso interno.\nNon può essere divulgato o riprodotto. Ogni uso improprio sarà perseguito a termini di legge." A11="L"
  ::STR.COL Nam="CF3"  Dim="15"
   ::BOX A01="A" A02="C" A03="-" A05="C" A07="B" A08="B" Txt="Pagina [NumPag]" A11="R"

Definizione dei dati (Le funzioni da stampare)

Nella definizione dei dati mi devo preoccupare di impostare tutte le funzioni nell’ordine che vorrò nel PDF.

Lo farò utilizzando, richamandole per nome (Nam=…) le varie forme di rappresentazione che ho definito nel Body della pagina che vado a stampare.

Da notare il fatto che è possibile mettere del testo (ad esempio DATI DELL’ACCOUNT) oppure delle FUN (F(EXB ….), che verranno eseguite e incluse sotto forma di tabella.

::EXE Fun="NEW" Met="PAG" Nam="P01"
::EXE Fun="NEW" Met="RIG" Nam="RTI" Txt="DATI DELL'ACCOUNT"
::EXE Fun="NEW" Met="RIG" Nam="MATBOR" Txt="F(EXB;D9COS6_01;ANE.POR) 1(CN;NOM;&PA.CodAcc) INPUT(Par(Con(CNNOM) K01(&PA.CodAcc)))"
::EXE Fun="NEW" Met="RIG" Nam="RTI" Txt="LEAD"
::EXE Fun="NEW" Met="RIG" Nam="MATSER" Txt="F(EXB;REMEAD_01;EBT.K41) 1(CM;£R3;)  INPUT(StrWhe(M§CAEN = '&PA.CodAcc' and M$LAVE < '8') InzDat(M£COEN(&PA.CodAcc)))"

Particolarità

Ciclo DO

Molto utile in caso di report gestionali è la possibilità di impostare un Ciclo DO nello script.

Il ciclo può essere impostato in diversi modi, ma in questo esempio usiamo una FUN di tipo matrice, definita in EXE.DO, che costituirà la base su cui iterare e da cui estrarre i dati usati nelle successive istruzioni di stampa.

Le variabili che devono essere usate dalla funzione interna, recuperate dalla funzione del ciclo vanno indicate in questo modo &CO.C00X, dove X è il numero della colonna dell’XML dove trovo il valore che mi serve. Nell’esempio il campo M$COMM è valorizzato con la colonna 13 della funzione generata dal ciclo.

Tutte le istruzioni contentute tra ::EXE.DO e ::EXE.ENDDO verranno eseguite tante volte quante sono le righe della matrice risultante.

::EXE.DO Pgm="LOA11_01" Mod="SER" Par="F(EXB;B£MARK_21;EST.R04) 1(CN;NOM;&PA.CodAcc)" CExb="1"
  ::EXE Fun="NEW" Met="RIG" Nam="SEZMAT" Txt="F(EXB;LOA13_SE;ESE.SQL) INPUT(select M£COME, M$DECO from brcomn0f WHERE M$COMM = '&CO.C013')"
::EXE.ENDDO
Multipagina

Se fra una funzione e l’altra voglio forzare che riparta da una nuova pagina mi basta scrivere di nuovo la funzionalità NEW PAG dichiarando il nome della pagina con cui ripartire.

Lo script mi permette  anche di poter definire più pagine (PAG) all’interno dello stesso. Nell’esempio abbiamo definito la pagina P01 (con il suo header, body, footer), ma nello stesso script possiamo definire anche altre N pagine (P02, P03, …) se ad esempio voglio avere header/footer diversi a seconda degli argomenti da stampare, oppure se predispongo di avere sempre una pagina di copertina.

Il risultato nella definizione dei dati potrebbe essere questo, dove uso la pagina P01 per le funzioni del capitolo Fatture, e la pagina P02 per le funzioni del capitolo Ordini.

::EXE Fun="NEW" Met="PAG" Nam="P01"
::EXE Fun="NEW" Met="RIG" Nam="RTI" Txt="FATTURE"
::EXE Fun="NEW" Met="RIG" Nam="MATSER" Txt="F(EXB;B£SER_01;DET.FAT)
::EXE Fun="NEW" Met="PAG" Nam="P02"
::EXE Fun="NEW" Met="RIG" Nam="RTI" Txt="ORDINI"
::EXE Fun="NEW" Met="RIG" Nam="MATSER" Txt="F(EXB;B£SER_01;DET.ORD)
Titolo di una Funzione implicito e Matrice generata solo se con dati

Una FUN che non ha dati non genera la griglia e le intestazioni, in modo che se in una stampa prevedo di stampare tante fun, come per esempio l’elenco delle commesse aperte di un cliente, queste si stampano solo se presenti dei dati, anche il titolo di una matrice può essere passato direttamente dal setup dell’xml in modo che anche quello sia stampato solo se esiste la matrice, garantendo di non avere titoli e matrici inutili perchè senza dati.

Ricordo inoltre che tutto il setup di una Funzione, (Ordinamenti, Stili, Totali e tutto quello che nelle schede si mette nel G.SET.MAT) deve arrivare direttamente nell’xml generato dalla stessa FUN, non essendoci la possibilità nel SCP_G53 di impostare, il setup di una matrice.

Funzione per richiamare la stampa

Se voglio richiamare la stampa dello script appena creato da un menu, da un bottone in una scheda, da un flusso, devo utilizzare una FUN fatta in questo modo, passando tutti i parametri con le variabili che sono state impostate nello script.

F(G53;B£SER_43;STR.SIM) 1(MB;SCP_G53;NomeScript) P(Opn(Yes) CodAcc(&OG.K1) DesAcc(&OG.D1) CodCli(&OA.U/NOM/CLI))

Esempio di PDF generati

Esempio Report Verticale
Esempio di Report Orizzontale