Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: PeppeC - Dicembre 11, 2018, 10:24:25 pm

Titolo: Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 11, 2018, 10:24:25 pm
Ciao a tutti, sono l'ultimo iscritto al gruppo e mio primo post...
Vorrei sapere come fare a mostrare correttamente un campo di tipo data (datetime) in un DBGRID, perchè quando il campo data non ha nessun valore, viene mostrata una fantomatica data 30/12/99 o 30/12/1899 a seconda della maschera impostata nella proprietà DisplayFormat.
Grazie.
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: nomorelogic - Dicembre 11, 2018, 11:56:27 pm
credo che ti convenga usare l'evento OnGetText dei TDateField

tipo:

Codice: [Seleziona]
uses ... dateutils ...

if Sender.IsNull then
  aText:=DateTimeToStr(DateTimeToUnix(0));

in questo caso viene mostrata una data tipo 00/00/0000, ma se vuoi puoi passare una stringa vuota


Codice: [Seleziona]
if Sender.IsNull then
  aText:='';
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: schumi - Dicembre 12, 2018, 08:58:52 am
sono incappato nello stesso problema anch'io avendo esperienza su FoxPro.
io ho optato per non usare il null ma la data 01/01/1900 come data "vuota", poi nelle griglie imposti la regola per sbiancare la cella.
Lo faccio anche in FoxPro con database diversi dai dbf fox
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 12, 2018, 06:48:39 pm
vi ringrazio per le risposte, dalle quali ho capito solo qual'è l'idea di cosa fare, ma non ho ancora capito come e dove realizzare il tutto. Potreste essere più chiari?
Grazie.
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 13, 2018, 07:57:34 am
aggiornamento...
ho trovato come impostare l'evento onGetText e combinando i due suggerimenti, sia di numerologic che di shumi, sbianco la data solo se uguale a 31/12/1899, mi viene comunque sbiancata tutta la colonna.
Ho verificato che quando la data non è vuota il valore non viene toccato.
Perchè? dove sbaglio?
Help me please.
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: nomorelogic - Dicembre 13, 2018, 08:27:59 am
potresti postare il codice relativo a onGetText e quello dove sbianchi la colonna?
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: Stilgar - Dicembre 13, 2018, 09:26:46 am
Cosa intendi per sbiancare?
Basta restituire una stringa vuota....
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: schumi - Dicembre 13, 2018, 09:56:03 am
magari è una schifezza di sistema, però in una form con un bel griglione usavo PrepareCanvas per mettere grassetto o sfondo colorato in base al dato.
potresti colorare di bianco il carattere che diventerebbe "invisibile".

if condizione then begin
with (Sender As TDBGrid) do
  begin
    Canvas.Font.Color:=clRed; // qua metti lo stesso colore dello sfondo
  end; // with
end ; // IF 
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: nomorelogic - Dicembre 13, 2018, 12:05:20 pm
bisogna vedere cosa vale "condizione", devi filtrare anche per il contenuto del record
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 13, 2018, 12:55:04 pm
ecco parte della procedura
...
procedure TFORM1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
    if column.FieldName = 'MiaData' and column.Field.Value='30/12/1899' then
            Column.Field.OnGetText:=@DBGrid1OnGetText;
   
end;
...
...
procedure TFORM1.DBGrid1OnGetText(Sender: TField; var aText: string;  DisplayText: Boolean);
begin
    aText:='';
end;

Ho provato a spostare tutto su Canvas al posto di DrawCell, ma stesso risultato.
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: Stilgar - Dicembre 13, 2018, 01:00:56 pm
na ... è un pelino sbagliata la logica :)
Mettiamo in fila i bit:Il OnGetText è "statico".Quindi:
Codice: [Seleziona]
      MiaDataField.OnGetText:=@DBGrid1OnGetText;
Lo devi piazzare nel dataset e non nel render della cella.
Poi dentro il gestore della trasformazione metti il controllo che più ti è comodo
Codice: [Seleziona]
procedure TFORM1.DBGrid1OnGetText(Sender: TField; var aText: string;  DisplayText: Boolean);
begin  Sender.isNull or Sender.FieldValue='30/12/1899' then     aText:='';  else   aText := ... formattazione della data come preferisci farla vedere ....
end;




Prova questo approccio:)
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 13, 2018, 06:33:26 pm
Ok grazie a tutti, risolto! che fatica però...
Evidenzio che al livello del DataSet la data vuota ha un valore '00:00:00' quindi è solo successivamente che viene attribuito il valore '31/12/1899'. Forse per somigliare a quanto fatto da Delphi? mah!
Che senso può avere mostrare sempre e comunque una data che senso non ha?
Comunque aver capito questo passaggio sarà utilissimo anche per altro che ho già in testa. Ancora grazie.
Devo fare qualcosa per segnalare che il caso è chiuso?
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: PeppeC - Dicembre 13, 2018, 09:19:22 pm



na ... è un pelino sbagliata la logica :)
Mettiamo in fila i bit:Il OnGetText è "statico".Quindi:
Codice: [Seleziona]
      MiaDataField.OnGetText:=@DBGrid1OnGetText;
Lo devi piazzare nel dataset e non nel render della cella.
Poi dentro il gestore della trasformazione metti il controllo che più ti è comodo
Codice: [Seleziona]
procedure TFORM1.DBGrid1OnGetText(Sender: TField; var aText: string;  DisplayText: Boolean);
begin  Sender.isNull or Sender.FieldValue='30/12/1899' then     aText:='';  else   aText := ... formattazione della data come preferisci farla vedere ....
end;
segnalo a Stilgar che non ero lontano dalla 1^ idea che avevo postato e che fra l'altro non è strettamente necessario  agire al livello del DataSet, perchè anche in DrawColumnCell funziona lo stesso e senza cambiare una virgola.
Questo è quanto immesso al livello della DBGrid e sono convinto che esiste una soluzione più semplice:
Codice: [Seleziona]
procedure TFORM1.DBGRID1DRAWCOLUMNCELL(SENDER: TOBJECT; const RECT: TRECT;
  DATACOL: INTEGER; COLUMN: TCOLUMN; STATE: TGRIDDRAWSTATE);
begin
          if column.Field.DataType=ftDate then
           column.Field.OnGetText:=@NullDateToBlank;
END;
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: Stilgar - Dicembre 13, 2018, 10:10:56 pm
1) sono contento che tu abbia risolto.
2) andare in fase di render a cambiare per ogni riga visibile  della griglia ad ogni update grafico, non lo considero un modo efficiente di usare il tempo cpu. Poi son gusti. Esagui 10 istruzioni di troppo ad ogni ciclo di update. Ripeto son gusti 😉. Già al primo giro hai messo il gestore corretto. Tanto vale farlo una volta solo. Magari a design  time. Quindi nel load dei metadati della form lo applichi e non ci pensi più 😊
3) in informatica esistono almeno 3 soluzioni allo stesso problema. Si seglie a seconda di vari parametri. Uno su tutti:che funzioni 😉
Titolo: Re:Campo database di tipo date con data vuota (blank)
Inserito da: nomorelogic - Dicembre 14, 2018, 12:28:22 am
scusate l'ingresso a gamba tesa :)

un TField è la sorgente del dato, il dato stesso
un TDataSource è il distributore dei dati forniti dal TField
una DbGrid il destinatario del dato che gli viene distribuito dal TDataSource

spesso per ogni tabella (e quindi per ogni campo della tabella) si prevede un solo form con all'interno dei data-control e quindi formattare direttamente dentro alla TDbGrid è anche una soluzione equivalente alle altre.

Mal il DataSource ci ricorda che un campo può essere distribuito a molti db-controls: se mettiamo nella stessa form dove c'è la griglia con il campo data anche un TDbEdit ed un TDbLabel collegati allo stesso campo data allora si vede subito che c'è un problema. Il problema è che la griglia modifica la visualizzazione del DbEdit e della DbLabel oppure
solamente la griglia mostrerà la data "sbiancata", il DbEdit e la DbLabel mostreranno il valore "sporco".

Questo per dire che un DbControl forse non dovrebbe assegnare un puntatore all'evento di un TField in base ad una sua condizione in quanto modificherebbe la visualizzazione di altri DbControl.
In questo caso è ok: c'è solo un DbGrid e la cosa gira e la soluzione è decisamente valida.

Però tenere a mente questo schema penso sia comunque importante in quanto i programmi spesso evolvono ;)