Grid¶
Chiamiamo grid della stampa, la griglia che riporta i dati un certo numero di righe.
La grid è suddivisa a sua volta in 3 parti principali
grid_header: una riga speciale che contiene le intestazioni di tutte le colonne della griglia.
grid_body: il contenuto vero e proprio, cioè le N righe contenenti i dati.
grid_footer: una riga speciale ed opzionale che mostra i totali delle colonne numeriche.
L’altezza di grid_header e grid_footer si può specificare, espressa in millimetri attraverso gli attributi di classe
grid_header_height
grid_footer_height
E se essa dovesse essere calcolata, in funzione dei dati o di opzioni fornite al lancio della stampa, si possono implementare i metodi hook
calcGridHeaderHeight
calcGridFooterHeight
I quali dovranno ritornare un valore numerico riferito all’altezza in millmetri.
Per quanto riguarda il grid_body
, l’unico attributo da assegnare è grid_row_height
, il cui valore di default è 5.
Anche in questo caso esiste un metodo hook per modificare in modo dinamico l’altezza della riga: il metodo calcRowHeight
Il riempimento della griglia¶
Per riempire le righe della griglia, ovvero il grid_body
, occorre prima di tutto fare il necessario per caricare i dati della griglia .
Dopodiché a meno di particolari necessità il ciclo sui dati delle righe, riempirà la griglia secondo la definizione fornita dal metodo gridStruct .
Override di prepareRow¶
Se tuttavia, la riga della griglia richiede una gestione totalmente custom è possobile ridefinire il metodo hook prepareRow
, il quale viene chiamato ad ogni iterazione del ciclo sulle righe nei dati e riceve l’elemento row da riepire.
Tutti i dati della riga saranno in disponibili in self.rowData
.
L’implementazione standard di prepareRow
non fa altro che definire un elemento cell
per ogni colonna definita dal metodo gridStruct e riempirla con i dati letti in self.rowData
.
Personalizzare una cella¶
Secondo il funzionamento standard in ogni cella viene semplicemente inserito il valore del dato che gli corrisponde. Ma può capitare la necessità di dover personalizzare il contenuto di una singola cella.
Supponiamo di dover mostrare in cella corrispondente ad una colonna numerica, il valore numerico se fosse positivo ed una certa immagine se negativo. In questo caso lo sviluppatore dovrebbe avere la possibilità di fare qualcosa del genere:
if self.rowData['importo'] >=0 :
row.cell(self.rowData['importo'])
else:
row.cell().img(src='negativo.jpg')
In tal caso posso definire il metodo
renderGridCell_importo
, ovvero definire un metodo che concateni nella sua signature il prefisso renderGridCell
con il nome della colonna di cui voglio personalizzare la cella.
Tutti i metodi di tipo renderGridCell
ricevono i seguenti parametri
col
: il nome della colonnarowData
: l’oggetto di tipo dict contenente i dati della rigaparentRow
: ovvero l’elementorow
sul quale dovrò attaccare la cella personalizzataAltri parametri di
cell
tra cuimm_width
,cell_content
,align_class
, etc.
Ma all’interno di una cella personalizzata posso anche annidare un nuovo layout con al suo interno altre righe.
Ad esempio in una stampa di righe di anagrafica, desidero che nella colonna telefono sia contenuto in un piccolo layout innestato in tutti i numeri di telefono del record, presentandoli uno sotto l’altro. O ancora, se il campo note supera un certo numero di caratteri avrà un font-size più piccolo o sarà addirittura troncato, altrimenti seguirà lo stile di default.
All’interno di un metodo renderGridCell
personalizzato dovremo aggiungere l’elemento cell ed eventuali altri layout e row annidate.
def renderGridCell_note(self, col = None, rowData = None, parentRow = None, **cell_kwargs):
cell_kwargs['width'] = cell_kwargs.pop('mm_width',None)
cell = parentRow.cell(overflow='hidden', **cell_kwargs)
noteLayout = cell.layout(name='ivaL', border_width=0, style='text-indent:1mm;')
if not rowData.get('dati'):
return
for dato in rowData['dati'].values():
r = noteLayout.row()
note_text = dato.get('note') or ''
fsize=''
if len(note_text) > 30:
fsize ='font-size:6pt;'
if len(note_text)>40:
note_text = '{n}...'.format(n=note_text[:40])
r.cell(note_text, style=fsize)
Il metodo calcRowHeight¶
Abbiamo anticipato l’esistenza di un metodo di hook che serve a modificare l’altezza della riga, pre-impostata dall’attributo grid_row_height
Il metodo calcRowHeight
è essenziale nel caso in cui una riga abbia delle celle possono contenere a loro volta più righe o che devono espandersi in altezza a seconda del loro contenuto.
In questi casi bisogna implementare tale metodo, che non riceve alcun parametro. I dati di riga presenti in self.rowData
saranno a disposizione per stabilire quanto aggiungere all’altezza della riga.
import math
from gnr.core.gnrstring import weightedLen
def calcRowHeight(self):
desc_offset = 50 if self.page_orientation=='V' else 100
n_rows = math.ceil(weightedLen(self.rowField('descrizione'), upper_coeff=1.3)/desc_offset)
height = (self.grid_row_height * n_rows)
return height
Suggerimento
Nell’esempio proposto si fa uso del metodo weightedLen
, che si occupa di stimare la lunghezza «pesata» di una stringa, dando un maggior peso alle lettere maiuscole (upper_coeff) ed eventualmente uno inferiore alle minuscole (lower_coeff). Non è obbligatorio fare uso di questa tecnica, tuttavia è consigliata dal momento che non esiste una scienza esatta nella stima dell’ingombro di una stringa partendo dal numero di caratteri.