La stampa di una fattura in Access

Recentemente mi è stato chiesto come stampare una fattura su più pagine in Access. Vi propongo la mia soluzione. In primo luogo cerchiamo di capire come sia strutturato il database che utilizzeremo, se qualcuno vuole svolgere l’esercizio. Supponiamo di partire da un database con le seguenti tabelle:

relationships

Possiamo leggere le relazioni così:

Customers 1-N (ossia uno a molti) con Orders
Employees 1-N con Orders
Orders 1-N con Order_Details
Products 1-N con Order_Details.

Dobbiamo creare un report per la stampa della fattura. Da un certo punto di vista, non esiste alcun problema e appare tutto facile: è sufficiente creare una query che includa i campi provenienti dalle diverse tabelle e basare il report su questa query, raggruppando il report per OrderNumber. Lo si può creare anche usando la creazione guidata, ma sorge un problema. Qualora si stampi su un foglio prestampato, dobbiamo far comparire i valori di riepilogo a piè pagina sempre nella stessa zona. La soluzione predisposta da Access, tuttavia, non serve allo scopo. Inoltre, se volessimo ripetere il totale dell’ordine su tutte le pagine, non riusciamo. Iniziamo a creare il report, successivamente lo modificheremo. Creiamo la nostra query di origine record del report:

  • da Customers: prendiamo i campi CustFirstName, CustLastName, CustStreetAddress, CustCity
  • da Orders: OrderNumber, OrderDate, ShipDate
  • da Order_Details: QuotedPrice, QuantityOrdered e un campo calcolato [SalesAmount] che restituisca il totale della riga come [QuantityOrdered]*[QuotedPrice]
  • da Employees: un campo calcolato [Employee] che restituisca il nome completo dell’impiegato [EmpLastName] & “, ” & [EmpFirstName]

Ora creiamo un report aggiungendo un raggruppamento per OrderNumber (per indicazioni su come procedere guarda il video su youtube) e con una sezione intestazione e una sezione piè di pagina. Nell’intestazione riportiamo i dati relativi alla “testata”: i dati provenienti dalle tabelle Customers, Orders e Employees. Nel corpo del report inseriamo i dati provenienti dalla tabella Order_Details. Infine nel piè di pagina inseriamo un campo calcolato che ci restituisca il totale dell’ordine come somma di SalesAmount. Sarà sufficiente creare una casella di testo e come origine controllo scrivere: =Somma([SalesAmount]).

Perfetto, non così difficile. E allora dov’è il problema? Il totale dell’ordine non sarà mai posizionato esattamente nello stesso punto della nostra pagina e non potremo determinare noi a quale altezza sarà stampato, perciò volendo stampare l’ordine su un foglio prestampato, non riusciremo mai a collocarlo esattamente al posto giusto. Inoltre, il secondo problema è che se il nostro ordine ha molte righe dettaglio che si distribuiscono su più pagine, il piè di pagina dell’ordine sarà stampato solo sull’ultima e perciò il totale dell’ordine non sarà ripetuto su tutte le pagine dell’ordine (come spesso invece si vuole che accada).

La soluzione? Come al solito pochi ritocchi e il gioco è fatto. Arriveremo a questo risultato (vedi esempio in PDF della fattura su più pagine).

Vediamo insieme come procedere. Dal punto di vista della progettazione del report non cambia molto rispetto a prima. La modifica è una sola:

  • collocheremo la casella di testo con il totale dell’ordine nel piè di pagina del report (e non nel piè di pagina di OrderNumber). Chiameremo la casella di testo txtTotale

Attenzione a: 1) chiamare txtOrderNumber la casella di testo con OrderNumber presente nell’intestazione di OrderNumber e 2) a impostare un salto pagina dopo la sezione nel piè di pagina di OrderNumber (sotto Formato la proprietà Interruzione di pagina deve essere impostata a Dopo la sezione).

Il report in struttura sarà simile a questo:

report_multipageinvoice

Ora manca soltanto di visualizzare nella casella di testo txtTotale il totale dell’ordine. La funzione che utilizziamo è la DSum, che ha 3 argomenti: il campo di cui calcolare la somma, la tabella o query dove cercare il campo, un eventuale filtro. Nel nostro caso l’origine controllo sarà:

=DSum("SalesAmount";"selAll"; "OrderNumber=" & Me.txtOrderNumber)

ossia: calcola la somma di SalesAmount che trovi nella query selAll, filtrando le righe in base al valore di txtOrderNumber. In tal modo otteniamo a piè pagina di ogni ordine il relativo totale dell’ordine, che si ripeterà su tutte le eventuali pagine dell’ordine e sarà sempre stampato nella stessa posizione.

Naturalmente nel piè pagina sarà possibile aggiungere altre caselle di testo in cui visualizzare per esempio il totale delle spese di trasporto o il corriere, o il conteggio degli articoli ordinati ecc.