PDA

Visualizza la versione completa : [delphi] varriabile integer in label


123delphi321
13-05-2004, 19:58
Ciao a tutti,

ho una variabile SUM il cui valore e' il risultato di una somma.
devo visualizzare questo valore in una label o in una edit, ma lo devo visualizare con l'opportuno formato (separatore migliaia float e 3 decimali)...: ,0.000

non riesco ad attribuire tale formato alla label e/o campo edit.


grazie


okkkk
ho risolto cosi:

Edit2.Text := FormatFloat(',0.000',sum);
ho fatto bene? o no?

grazie

alka
13-05-2004, 21:01
Credo che il formato corretto sia #,##0.000, ad ogni modo per provare se è quello giusto basta creare velocemente un'applicazione vuota e mostrare all'interno di una Label o di una casella di messaggio il valore stringa ottenuto dalla formattazione con FormatFloat: se il numero appare come desiderato, allora bene, altrimenti occorre apportare modifiche.

Per le indicazioni complete sulla specificazione di una maschera di formato, posizionati su FormatFloat e premi F1 per richiamare la Guida in linea di Delphi.

Ciao! :ciauz:

123delphi321
14-05-2004, 00:23
funziona bene in questo modo

Edit2.Text := FormatFloat(',0.000',sum);

praticamente utilizzo questa tecnica x visualizzare i totali di una dbgrid:

una volta eseguita la query mi scorro tutta dbgrid:


var
sum:single;
begin
....
....
sum := 0;
with JvDBGrid1.DataSource.DataSet do
begin
JvDBGrid1.DataSource.DataSet.FindFirst;
while not Eof do
begin
sum:= sum + FieldByName('TOTALE').AsFloat;
Next ;
end;
end;
Label7.Caption := FormatFloat(',0.000',sum);


il TOTALE e' un field NUMERIC(9,3).
la variabile sum l'avrei voluta dichiarare float...ma nn ci sono riuscito, poi ho trovato su internet un esempio che la dichiarava single e l'ho copiato.

adesso io vorrei aggiornare la label ad ogni cambiamento della colonna TOTALE, pertanto ho pensato di agire sull'evento EditChange della dbgrid ed intercettare i cambiamenti dei valori....

il problema che resta e' quello di aggiornare la label non riesco a convertire la caption ad un valore float x sommare le differenze.

avevo anke pensato di memorizare il valore FLOAT della caption nel label.Tag ma il tag accetta solo numeri interi, ho provato a converire: int(sum*1000)....ma anke in questo caso ottengo una variabile diversa da Integer.

grazie

ps.sempre girando su internet, ho trovato delle dbgrid professionali che hanno delle buone funzioni di Footer, ma purtroppo non ne ho trovata alcuna sharewere. tutte a pagamento.

ma voi come fate a visualizzare i totali delle colonne di una dbgrid?

ri-grazie

AlbertoPicca
14-05-2004, 08:19
Io, prima di tutto, cambierei la dichiarazione della tua variabile Sum da Single a Variant.

Gli eventi legati ai controlli visuali a volte possono dare dei problemi, cosa che mi capita spesso proprio con le DBGrid.

Devi tenere in considerazione che non é possibile scandire, ogni volta che viene modificato un valore, tutti i record della tabella per ottenere la somma di ogni campo.

Procederei in questo modo:
1- Subito dopo l'apertura della tabella o del dataSet richiami una
funzione che ti restiuisce la somma della colonna interessata.
2- All'evento OnValidate legato al campo implementerei una procedura che sottrae alla variabile somma il vecchio valore della tupla e somma il nuovo valore.
Puoi usare il metodo OldValue e NewValue legati alla classe TFields

Ti suggerisco un procedimento del genere solo per ridurre i tempi necessari a far scorrerre tutti i record.

Presumo possa essere una soluzione accettabile...
:ciauz:

alka
14-05-2004, 09:41
Originariamente inviato da 123delphi321
la variabile sum l'avrei voluta dichiarare float...ma nn ci sono riuscito, poi ho trovato su internet un esempio che la dichiarava single e l'ho copiato.
Il metodo AsFloat del campo (TField) restituisce un valore di tipo Double, pertanto puoi usare questo valore per dichiarare la tua variabile temporanea.


Originariamente inviato da 123delphi321
il problema che resta e' quello di aggiornare la label non riesco a convertire la caption ad un valore float x sommare le differenze.
Al di là del fatto che tu riesca o meno a convertire la Caption, credo che il modo di procedere sia sbagliato comunque a livello concettuale: è meglio se introduci un campo privato di tipo Double nella tua Form che contenga il valore del totale che viene poi convertito per essere visualizzato nella Caption della Label apposita. Quando è necessario modificare il totale, operi direttamente sulla variabile e, alla fine del calcolo, ne visualizzi di nuovo il valore sull'etichetta.
Usare la Caption della Label per memorizzare un valore convertendo e riconvertendolo ancora è uno spreco di CPU, di precisione e soprattutto è una pratica prona ad errori.


Originariamente inviato da 123delphi321
ps.sempre girando su internet, ho trovato delle dbgrid professionali che hanno delle buone funzioni di Footer, ma purtroppo non ne ho trovata alcuna sharewere. tutte a pagamento.
Le griglie non sono sempre così semplici da fare, e probabilmente chi studia qualche mese per implementare funzionalità vuole essere - giustamente - remunerato. :)

Comunque, anche shareware è una licenza che prevede il pagamento.

Le migliori griglie che conosco, decisamente celebri, sono quelle di DevExpress (http://www.devexpress.com/?section=/Products/VCL/ExQuantumGrid).


Originariamente inviato da 123delphi321
ma voi come fate a visualizzare i totali delle colonne di una dbgrid?
Io appoggio quasi totalmente le mie applicazioni legate ai dati sul componente TClientDataSet che supporta l'uso di campi aggregati: si tratta di campi definiti a designtime che contengono un valore calcolato basato sull'elaborazione di tutti i campi ai quali viene applicata una formula come la media, oppure la somma, ecc. ecc.

Quando apporto modifiche ai dati, nei campi aggregati trovo già il valore aggiornato che il componente provvede a ricalcolare in piena autonomia basandosi sui record che tiene memorizzati nel suo buffer interno. ;)

alka
14-05-2004, 09:56
Originariamente inviato da AlbertoPicca
Io, prima di tutto, cambierei la dichiarazione della tua variabile Sum da Single a Variant.

Perchè? :)

Il tipo Variant influisce negativamente sulle prestazioni dell'applicazione, poichè si tratta di un dato il cui tipo viene definito a runtime e pertanto è soggetto ad elaborazioni particolari e aggiuntive che quindi richiedono maggiore CPU.

Possono essere usati comodamente in altre occasioni, ma siccome qui si parla in modo particolare di effettuare un calcolo il più rapidamente possibile, se si potessero escludere, le escluderei e sceglierei invece di usare direttamente il tipo Double, che è lo stesso tipo usato dal metodo AsFloat di TField.


Originariamente inviato da AlbertoPicca
Devi tenere in considerazione che non é possibile scandire, ogni volta che viene modificato un valore, tutti i record della tabella per ottenere la somma di ogni campo.
Sì, trovo che sia un pochino pesante, soprattutto quando i record diventano parecchi.


Originariamente inviato da AlbertoPicca
Procederei in questo modo:
1- Subito dopo l'apertura della tabella o del dataSet richiami una
funzione che ti restiuisce la somma della colonna interessata.
2- All'evento OnValidate legato al campo implementerei una procedura che sottrae alla variabile somma il vecchio valore della tupla e somma il nuovo valore.
Puoi usare il metodo OldValue e NewValue legati alla classe TFields.
Concettualmente, credo che sia un buon metodo per evitare pesanti elaborazioni, ma può generare parecchi errori di calcolo.
L'evento OnValidate esegue una validazione lato client personalizzata del campo. Il fatto che l'evento OnValidate non generi alcuna eccezione (che è il modo usato dallo sviluppatore per rifiutare il valore del campo) non significa che poi tale valore venga accettato dal database; se il database lo rifiuta, allora ci si trova con un dato inapplicabile che viene ripristinato al valore precedente, mentre il totale si riferisce ancora al valore di cui si è tentata l'impostazione. Insomma, credo che sia molto rischioso...

Secondo me, gli unici modi per ottenere una simile funzionalità in modo sicuro sono:

a) usare un componente TClientDataSet che supporta l'uso di campi aggregati (Aggregates) ed è in grado di fornire una simile funzionalità (poichè incorpora sia la tabella dei dati, sia la tabella con le modifiche, pertanto possiede tutte le informazioni storiche per poter giungere al risultato corretto dell'elaborazione);

b) eseguire una query con l'istruzione SQL SUM quando viene eseguita la CommitRetaining della transazione per ottenere il valore aggiornato della somma del campo interessato direttamente dal server.

123delphi321
14-05-2004, 10:47
a) usare un componente TClientDataSet che supporta l'uso di campi aggregati (Aggregates) ed è in grado di fornire una simile funzionalità (poichè incorpora sia la tabella dei dati, sia la tabella con le modifiche, pertanto possiede tutte le informazioni storiche per poter giungere al risultato corretto dell'elaborazione);

per utilizzare questi campi devo inserire ui nuovo componente TClientDataset o e' possibile creare questo campo sull IBClientDataset?

In effetti se aggiungo un campo al IBClientDataset ho la possibilita di scegliere tipo Aggregate ma non riesco a inserire questo field nella lista dei campi della dbgrid.

d'altra parte ho provato ad inserire il nuovo componente Tclientdataset a cui, secondo la mia logica, dovrei associare il mio IBdataset al fine di poter attenere i fields su cui operare...
quindi, tasto dx sul componente e seleziono assign Local Data e subito mi appare una finestra da cui posso selezionare la mia fonte di dati. se seleziono una IBtable riesco a visualizzarne i field, se invece seleziono il mio IBDataset ottengo come risultato:Operation not Applicable


se hai 'un minuto' (si fa x dire 1 minuto)...potresti spiegarmelo x favore
grazie

alka
14-05-2004, 15:46
Il componente TClientDataSet ha una miriade di funzionalità interessanti, quindi non me la sento di avviare in questa sede una discussione di tutte le operazioni e gli accorgimenti di cui si deve tener conto per poterlo far funzionare con un DataSet; inoltre, si dovrebbe parlare anche di un altro componente, il DataProvider, quindi il discorso si complica, soprattutto pensando allo scopo finale che è quello di ottenere la somma di un campo.

Ad ogni modo, dando una rapida occhiata al componente IBClientDataSet, pare che sia possibile definire campi aggregati, anche se non conosco a sufficienza il campo per fornire informazioni dettagliate.

Il componente accetta una query CommandText per definire lo statement SQL di reperimento dei dati. Facendo doppio clic sul componente, appare il consueto Field Editor che permette, dal menu "New Field" che appare cliccando con il tasto destro, di aggiungere campi aggregati (Aggregates).

La proprietà AggregateActive del componente va impostata a True per attivare il calcolo sui campi. Per ciascun campo aggregato, va definita l'espressione di calcolo all'interno della proprietà Expression; selezionando la proprietà e premendo F1, appare la Guida in linea con qualche esempio a riguardo.

Non so se quel tipo di campo è associabile ad un Data Control, ma puoi tentare di ispezionarne il valore da codice e visualizzarlo all'interno di un'etichetta.

Purtroppo, non ho tempo a sufficienza per fare ulteriori prove, predispormi un database e soprattutto studiare il funzionamento del componente IBClientDataSet; tra l'altro, non sono in possesso di informazioni se non quelle che posso leggere e intuire dalla Guida in linea di Delphi. :bhò:

Ciao! :ciauz:

123delphi321
15-05-2004, 17:07
...riEsco a visualizzare i valori dei campi aggregares in delle label,...ma non in una griglia.

visualizzando il mio IBClientDataset nella DBgrid vedo che posso modificare cancellare e aggiungere record nel dataset....

ma ho provato ad applicare il metodo applyUpdates....solo che nn riesco a farlo funzionare.

ho cercato documentazione su internet (con google) riguardo al componente IBClientDataset ma ne ho trovata pochissima x non dire nulla.
mi sapete indicare dove cercare?

non so,..ma forse sto andando oltre complicandomi il lavoro.

il mio scopo finale e' quello di visualizzare i totali dei record (articoli di fattura) che visualizzo e modifico in una dbgrid,...anke per poi stamparli in una futura stampa quale la fattura.

mi consigliate una maniera diversa per il calcolo di questi totali?

grazie
f

alka
15-05-2004, 18:35
Originariamente inviato da 123delphi321
non so,..ma forse sto andando oltre complicandomi il lavoro.
E' quello che penso anche io. ;)


Originariamente inviato da 123delphi321
il mio scopo finale e' quello di visualizzare i totali dei record (articoli di fattura) che visualizzo e modifico in una dbgrid,...anke per poi stamparli in una futura stampa quale la fattura.
mi consigliate una maniera diversa per il calcolo di questi totali?

In definitiva, ti serve sapere l'importo totale della fattura, giusto?

A questo punto, riduci i tuoi sforzi e costruisci una stored procedure che, dato l'ID della fattura, ti calcoli il totale tenendo conto dei record inseriti; il totale viene restituito attraverso un parametro di output previsto dalla procedura e viene visualizzato a video.

Ogni volta che inserisci un record (e fai il Post), esegui nuovamente la stored procedure.

Loading