Stampa griglia 3: Comuni

Supponiamo di voler stampare un elenco di record sulla base di una query con delle condizioni specifiche, considerando però solo i «migliori» 100 risultati.

In quest’esempio vedremo come definire la risorsa di stampa relativa ai Dati dei Comuni italiani, filtrati per regione. La stampa verrà lanciata dalla tabella Comune del package GLBL di Sandbox. In particolare, questo esempio ci permetterà di vedere come utilizzare il metodo calcRowHeight per calcolare l’altezza variabile delle righe e come definire una gridstruct che faccia uso di sqlcolumn e columnset, nonché l’utilizzo di limit e order_by nel nostro gridQueryParameters

Definizione della print action

Per prima cosa andiamo a definire la risorsa print che chiamiamo stampa_comuni.py all’interno della cartella resources/tables/_packages/glbl/prodotto/print, esattamente come abbiamo fatto nella Stampa con griglia 1: Fatturato per esercizio .

Richiederemo come parametro solo la Regione. Si noti che in questo caso stiamo effettuando un Override di un package built-in di Genropy, per questo motivo abbiamo ipotizzato di inserire la risorsa in un nostro package, modificando però il percorso della cartella come specificato.

Non essendoci particolari variazioni sui parametri richiesti per la stampa rimandiamo al caso precedente per una trattazione più completa.

Definizione della risorsa html_res

Passiamo a questo punto alla definizione della risorsa html_res che chiamiamo dati_comuni.py all’interno della cartella resources/tables/_packages_glbl/comune/html_res.

Rimandiamo alla Stampa con griglia 1: Fatturato per esercizio per la trattazione della definizione dei parametri della classe Main, dei metodi defineCustomStyles, docHeader, docFooter e outputDocName, che non variano anche in questo caso in modo significativo.

Considerato l’elevato numero di colonne e lo spazio ridotto, nel Main specifichiamo invece page_orientation='H', che imposterà l’orientamento della stampa a orizzontale. Sempre nella classe Main definiamo anche grid_row_height = 5, che indicherà una generica altezza di riga di riferimento che poi andremo a modificare caso per caso con il metodo calcRowHeight. Infine, utilizziamo una totalizzazione per pagina con totalize_mode='page':

class Main(TableScriptToHtml):

  row_table = 'glbl.comune'
  page_width = 200
  page_height = 297
  page_orientation = 'H'
  doc_header_height = 20
  doc_footer_height = 0
  grid_header_height = 5
  grid_row_height = 5
  totalize_footer=True
  totalize_mode='page'

Tramite il metodo gridQueryParameters specifichiamo poi come condizione l’appartenenza alla Regione, limitando il numero di risultati a 100 e ordinandoli per popolazione decrescente:

def gridQueryParameters(self):
      return dict(condition='@sigla_provincia.regione=:regione', condition_regione=self.parameter('regione'),
                      order_by='$popolazione_residente DESC', limit=100)

Si noti che con order_by='$popolazione_residente DESC' specifichiamo la natura decrescente sulla base della quale ordinare i risultati della ricerca, mentre con limit=100 prendiamo di questa selezione solo i primi 100 risultati.

È probabile però che avendo tante colonne e uno spazio ridotto alcuni comuni con nome particolarmente lungo o province con nomi particolarmente lunghi vengano troncate o presentino comunque problemi di visualizzazione. Ecco che ci viene in aiuto il metodo calcRowHeight , che prenderà il valore standard di grid_row_height che abbiamo inserito nel Main e lo modificherà sulla base del «contenuto» (in termini di numero di caratteri) della specifica riga:

def calcRowHeight(self):
      nome_offset = 22
      n_rows_nome_comune = len(self.rowField('denominazione'))//nome_offset + 1
      n_rows_nome_provincia = len(self.rowField('_sigla_provincia_nome'))//nome_offset + 1
      n_rows = max(n_rows_nome_comune, n_rows_nome_provincia)
      height = (self.grid_row_height * n_rows)
      return height

Il metodo ritorna quindi un’altezza dopo aver rapportato la lunghezza in termini di numero di caratteri del campo denominazione o @sigla_provincia.nome a un valore «offset» che impostiamo noi all’interno del metodo. Si noti che questa procedura non è obbligatoria, ma è quella che dal punto di vista pratico ha maggiori probabilità di funzionare nella molteplicità dei casi possibili: è possibile utilizzare anche altre procedure, a patto che venga sempre restituita un’altezza come risultato finale.

Nel metodo gridStruct, infine, utilizziamo sqlcolumn e columnset

def gridStruct(self,struct):
      r = struct.view().rows()
      r.fieldcell('denominazione', mm_width=0, white_space='pre-line')
      com = r.columnset('com', name='DATI COMUNE', background='lightblue', color='white',
                              font_size='14px', font_weight='bold')
      com.fieldcell('@localita.codice_istat', mm_width=15, name='Codice')
      com.fieldcell('@localita.prefisso_tel', mm_width=15, name='Pref.Tel.')
      com.fieldcell('@localita.cap', mm_width=14)

      ...

      prov = r.columnset('prov', name='DATI PROVINCIA', background='lightgreen', color='white',
                              font_size='14px', font_weight='bold')
      prov.fieldcell('sigla_provincia', mm_width=12, name='Sigla')
      prov.fieldcell('@sigla_provincia.nome', mm_width=24, white_space='pre-line')
      prov.fieldcell('@sigla_provincia.codice_istat', mm_width=15, name='Codice')

      ...

      incid = r.columnset('incid', name='INCIDENZA', background='lightcoral', color='white',
                              font_size='14px', font_weight='bold')
      incid.cell('superficie_perc', sqlcolumn="$superficie/@sigla_provincia.tot_superficie*100 AS superficie_perc",
                          format='#,###.00', mm_width=15, name='Sup.%', content_class='aligned_right')
      incid.cell('popolazione_perc', sqlcolumn="$popolazione_residente/@sigla_provincia.numero_abitanti*100 AS popolazione_perc",
                          format='#,###.00', mm_width=15, name='Pop.%', content_class='aligned_right')

Si noti che l’utilizzo della sqlcolumn è in questo caso assolutamente alternativo a una qualsiasi formulaColumn. La discriminante di scelta tra l’una e l’altra è esclusivamente l’utilità o meno al di fuori della specifica stampa: se la colonna calcolata può essere utile anche al di fuori della stampa allora si consiglia l’utilizzo della formulaColumn, se invece, come in questo caso, stiamo effettuando un override di un package built-in di Genropy, ai soli scopi di questa stampa, e non abbiamo intenzione di modificare il model, allora è consigliato l’utilizzo della sqlcolumn


Puoi scaricare i file di stampa qui di seguito e scompattare il file zip direttamente in fatt/resources/tables di Sandbox.


Allegati: