Newsgroup: it.comp.lang.delphi
Titolo: Stampa da DBGrid

Sto facendo una proc di stampa da DBGrid e l'ho fatto con QuickReport, ma 
non riesco ad allineare correttamente i titoli delle colonne al loro 
contenuto, soprattutto quando le colonne e i titoli del DBGrid sono 
dichiarati con alignment taCenter.
 
La larghezza della colonna la determino con l'espressione:
DBGrid.Columns[i].width;
 
e per determinare la larghezza del Title ho provato con:
DBGrid.Canvas.TextWidth(AGrid.Columns[i].Title.Caption
 
ma credo di stare usando due unità di misura completamente differenti dati i 
risultati. Pensavo che entrambi esprimessero i 'punti'. Qualcuno mi può 
chiarire ? 
 

 dichiarati con alignment taCenter.
 
Premetto che non uso la DBGrid (preferisco fare tutto a mano e usare una 
griglia normale) quindi prendi tutto con le dovute cautele.
Inoltre io uso il QR 5.06 su delphi seattle.
Per adattare la larghezza delle colonne al contenuto puoi stravolgere questa 
procedura
 
procedure AdjustColumnWidths(DBGrid: TDBGrid);
var
  TotalColumnWidth, ColumnCount, GridClientWidth, Filler, i: Integer;
  Old : Integer;
begin
  ColumnCount := DBGrid.Columns.Count;
  if ColumnCount = 0 then
    Exit;
  for i := 0 to ColumnCount-1 do
      If Not DBGrid.Columns[I].Visible Then ColumnCount:=ColumnCount-1;
  // compute total width used by grid columns and vertical lines if any
  TotalColumnWidth := 0;
  for i := 0 to ColumnCount-1 do
  Begin
    If DBGrid.Columns[I].Visible Then
       TotalColumnWidth := TotalColumnWidth + DBGrid.Columns[i].Width;
  End;
  if dgColLines in DBGrid.Options then
    // include vertical lines in total (one per column)
    TotalColumnWidth := TotalColumnWidth + ColumnCount;
 
  // compute grid client width by excluding vertical scroll bar, grid 
indicator,
  // and grid border
  GridClientWidth := DBGrid.Width - GetSystemMetrics(SM_CXVSCROLL);
  if dgIndicator in DBGrid.Options then begin
    GridClientWidth := GridClientWidth - IndicatorWidth;
    if dgColLines in DBGrid.Options then
      Dec(GridClientWidth);
  end;
  if DBGrid.BorderStyle = bsSingle then begin
    if DBGrid.Ctl3D then // border is sunken (vertical border is 2 pixels 
wide)
      GridClientWidth := GridClientWidth - 4
    else // border is one-dimensional (vertical border is one pixel wide)
      GridClientWidth := GridClientWidth - 2;
  end;
 
  // adjust column widths
  if TotalColumnWidth < GridClientWidth then begin
    Filler := (GridClientWidth - TotalColumnWidth) div ColumnCount;
    for i := 0 to ColumnCount-1 do
    Begin
      If DBGrid.Columns[I].Visible Then
        DBGrid.Columns[i].Width := DBGrid.Columns[i].Width + Filler;
    End;
  end
  else if TotalColumnWidth > GridClientWidth then begin
    Filler := (TotalColumnWidth - GridClientWidth) div ColumnCount;
    if (TotalColumnWidth - GridClientWidth) mod ColumnCount <> 0 then
      Inc(Filler);
    for i := 0 to ColumnCount-1 do
    Begin
      If DBGrid.Columns[I].Visible Then
      Begin
        Old:=DBGrid.Columns[i].Width;
        DBGrid.Columns[i].Width := DBGrid.Columns[i].Width - Filler;
        If DBGrid.Columns[i].Width<0 Then DBGrid.Columns[i].Width:=Old;
      End;
    End;
  end;
end;
 
che, onestamente, non mi ricordo dove l'ho trovata (risale a qualche anno 
fa).
 
Per quanto riguarda la stampa, utilizzando la stringgrid, io procedo in 
questo senso:
Nel report configuro la grafica e le opportune bande, poi quando devo 
stampare il contenuto della griglia utilizzo una qrLoopBand.
 
Sempre per onesta' intellettuale, devo dirti che i miei report sono report 
"elemetari" senza sorta di grouping, calcioli parziali ecc...., inoltre la 
dimensione dei  db e' veramente minimale (qualche decina di migliao di 
record, non milioni)
Il lavoro di preparazione lo svolgo a priori sulla griglia, poi quando 
stampo devo solo preoccuparmi di stampare la griglia.
La decisione di utilizzare la stringgrid invece della dbgrid sta nel fatto 
che le operazioni di filtraggio, ordinamento ecc ecc sono piu' veloci sulla 
prima che non sul db (su cui si deve operare con sql e poi con filter).
Per le mie esigenze va piu' che bene.
 
Ciao
 
Daniele 
 


Che risultati hai ottenuto? 
 
La butto li, tirando a indovinare: la DBGrid ti dice che una colonna 
e' larga 80 pixel. A video a video e' circa 2 cm ma quando vai a stampare
la colonna viene larga 3 millimetri?
 
ciao
Giacomo

Ciao Daniele e grazie per il codice. Purtroppo quella procedura la conoscevo 
già e non funziona affatto, pur essendo pubblicata sul sito Embarcadero. Non 
dimensiona correttamente alla larghezza del contenuto del campo e ha degli 
strani comportamenti quando si ridimensiona la finestra. E' interessante che 
tu preferisci la stringGrid al DBGrid. Ma perchè trovi più semplice il 
filtraggio e l'ordinamento dei campi quando agendo sul dataset un set filter 
e un order by bastano allo scopo ?
Comunque, io cercavo di creare una procedura di stampa un pò universale, nel 
senso che un bottone Stampa potesse accompagnare  un qualsiasi DBGrid con 
qualunque contenuto. Evidentemente la cosa deve essere più complicata di 
quanto io mi renda conto, se questa cosa non c'è.. 
 

 di quanto io mi renda conto, se questa cosa non c'è..
 
Bhe la stampa e' tua, nel senso che a te spetta il compito di gestirla.
Di per se nella funzione di stampa puoi fare quello che vuoi, anche passare 
tutta la griglia o tutto il dataset.
Quello che puo' variare e' la configurazione della griglia (colonne) o il 
dataset.
Nel caso tu hai intenzione di fare una procedura universale, devi anche 
pensare che i dati che andrai a visualizzare nel tuo report siano sempre in 
quell'ordine.
 
Nelle mie due necessita' (stringgrid e dbstringgrid) ho risolto in questi 2 
modi.
1) Nella form di generazione del report, nelle uses indico la unit dove e' 
presente la stringgrid.
    In questo modo ho l'accesso alla griglia e stampo quello che devo.
2) Dato che uso la versione db della griglia e che questa e' legata ad un 
data set, per la stampa leggo direttamente quello e non la griglia.
 
Onestamente, viste le mie scarse necessita' di stampa, non ho mai avuto 
grosse problematiche nei report.
Quindi per poter risolvere il tuo problema dovrebbe risponderti qualcuno con 
piu' esperienza di me.
 
Ciao
 
Daniele 
 

"Daniele"  ha scritto nel messaggio news:odploo$sma$1...@gioia.aioe.org...

Grazie, apprezzo che tu sia disponibile a condividere la tua esperienza. Io 
ormai uso Delphi più per hobby che per altro, pur mantenendo qualche 
applicazione abbastanza corposa. Invece mi pare che il forum non lo sia 
tanto, e oltretutto è scarsamente frequentato. Sarà che non è più il periodo 
di Delphi .. 
 

 di Delphi ..
 
sinceramente, nel mio caso non ho mai utilizzato un qualcosa che stampasse una dbgrid in modo "universale", cioè un metodo unico per qualsiasi dbgrid all'interno dell'applicativo e ti spiego anche i motivi.
Nel mio applicativo l'utente ( mio cognato ) ed i suoi collaboratori non hanno mai avuto necessità di avere su carta il contenuto di una dbgrid anche perchè vi sono dei report ah hoc che stampano i relativi dati, è capitato però un paio di volte che mio cognato volesse al volo su carta alcuni record della dbgrid, in questo caso ha fatto semplicemente un print-screen della videata.
 
Ciao da Enrico Giudici c/o Anthelios

ha scritto nel messaggio 
news:865a5e1d-cc3a-4f1e...@googlegroups.com...

Ma si, più o meno è proprio questa l'esigenza che volevo coprire. E cioè, 
quando una DBGrid è usata per visualizzare un set di dati limitato che a 
volte voglio anche conservare su un foglio di carta. Una stampa dello 
schermo non va bene perchè magari non comprende tutto.  Certo potrei per 
ognuno di questi casi sviluppare un report, ma un dbgrid già fronisce di sè 
i dati da stampare, le testate, le larghezze, etc. Ecco perchè pensavo ad 
una proc generalizzata. 
 

 una proc generalizzata.
 
tieni presente che, nel mio caso, le dbgrid utilizzate all'interno dell'applicativo di mio cognato hanno pochissimi dati, giusto quelli essenziali per far capire a mio cognato o ai suoi collaboratori le info essenziali, oltre a questo (opinione personale), mettendo tanti dati nelle dbgrid si ottiene un peggioramento delle performance sia per recepirle sia nella navigazione. Per mio cognato non ha senso scorrersi tutto all'interno della dbgrid. Ecco perchè quando gli occorre il dettaglio utilizza uno o più report costruiti ad hoc.
 
Ciao da Enrico Giudici c/o Anthelios.

Ciao,
   non si tratta di avere filtrato o meno il database (la griglia serve solo 
per vedere i dati) ma si tratta di cosa vuoi fare con la griglia.
E' quasi impossibile fare un report universale per *qualsiasi* database o 
griglia.
Il perche' e' abbastanza semplice:
Il database puo' avere decine (se non centinaia) di tabelle ognuna con poche 
o decine di colonne (campi).
Se poi fai una select con diverse join su chissa' quali tabelle avrai come 
risultato un dataset con colonne anche create al volo.
 
Mi spieghi come puoi fare un report "universale"  che puoi chiamare in 
chissa' quali punti del tuo programma?
Nel mio caso ho 4 form dove eseguo interrogazioni al database (dove uso 
largamente le join) con 4 report differenti, ognuno dedicato al lavoro che 
e' richiesto.
 
Diverso e' gestire il report sulla griglia che invoca il report.
Tu sai cos'hai nella griglia (hai definito tu le colonne) che NON 
necessariamente rispecchia tutto il record (record di 100 campi, ma 
visualizzati solo 10) e, dato che stai usando una dbgrid, sai che ogni riga 
corrisponde ad un record.
A questo punto scorrendo il dataset ( while not Dataset.eof do) nel tuo 
report visualizzi i dati che hai bisogno (che non sono necessariamente 
quelli esposti nella griglia).
 
Enrico ti ha suggerito bene, se dopo il lavoro sulla griglia hai pochi 
record (righe) e i dati che hai bisogno sono tutti in vista, basta un print 
screen.
 
Dato che usi QuickReport (lo uso anch'io) non riesci ad usare il componente 
TQrGridReport che permette un link ad un dbgrid (io, come gia' detto, non lo 
uso).
 
Ciao
 
Daniele