Servizi informatici per le aziende

Esempi di codice riutilizzabile

Sezioni:

Codice riutilizzabile

Esempio di creazione di una form introduttiva

L'esempio seguente mostra come creare una form introduttiva, chiamata Frm_Presentation, contenente un'immagine di presentazione per il programma. La form deve avere le proprietà seguenti (che possono essere impostate design-time):

BorderStyle := bsNone;
Position := poScreenCenter;

e deve contenere un oggetto TImage ed un oggetto TTimer.

Es.

Esempio

La proprietà Interval dell'oggetto TTimer può essere impostata a design-time ad un tempo a piacere, espresso in millesecondi. L'evento OnTimer dell'oggetto TTimer permette di chiudere la form, una volta trascorso l'intervallo di tempo descritto dalla proprietà Interval prima impostata.

Es.

procedure TFrm_Presentation.Timer1Timer(Sender: TObject);
begin
Close;
end;

Per la visualizzazione della form di presentazione, è sufficiente chiamare la procedura ShowIntro nell'evento OnCreate della form principale del programma stesso.

Es.

procedure ShowIntro;
begin
with TFrm_Presentation.Create(Application) do
begin
ShowModal;
Free;
end; //with
end;

Nel caso in cui si voglia accedere ad un database direttamente dalla form introduttiva, è necessario fare in modo che l'utente inserisca nella form stessa l'identificativo ed, eventualmente, la password.

Es.

Esempio

La form precedente, che chiameremo sempre Frm_Presentation, possiede due oggetti TEdit: la txtUser, per contenere l'identificativo dell'utente, e la txtPwd, per contenere la password. Se si desidera che la password non risulti leggibile in fase di edit, è necessario impostare la proprietà PasswordChar. La form principale del programma deve contenere un oggetto TDatabase, che nell'esempio seguente si chiama dbInterno, al cui evento OnLogin si associa la creazione della form di presentazione e l'assegnazione dei parametri.

Es.

procedure TFrm_Main.dbInternoLogin(Database: TDatabase; LoginParams: TStrings);
begin
Frm_Presentation := TFrm_Presentation.Create(Application);
with Frm_Presentation do
begin
try
begin
txtUser.Text := Copy(Database.Params[0], Pos('=', Database.Params[0])+1, 255);
// La riga di codice precedente copia nella txtUser l'identificativo dell'utente inserito all'ultimo accesso
ShowModal;
if (ModalResult = mrOk) then
begin
LoginParams.Clear;
LoginParams.Add('USER NAME=' + txtUser.Text);
LoginParams.Add('PASSWORD=' + txtPwd.Text);
end; //if
end; //try
finally
Free;
end;
end; //with
end;

Con questa forma di accesso al database, è necessario collegare tutti gli oggetti TDataSet non direttamente all'alias collegato al database, bensì all'oggetto TDatabase posto sulla form principale.

Esempio di creazione di una Form per la specifica di un intervallo

La generica form per la selezione di un intervallo deve avere l'aspetto seguente:

Esempio

Per fare in modo che i due oggetti TDateTimePicker presenti sulla form (dtpDal, dtpAl) contengano la data corrente, è necessario intervenire sulla proprietà Date di entrambi nell'evento OnCreate della form.

Es.

procedure TFrm_SelezionaIntervallo.FormCreate(Sender: TObject);
begin
dtpDal.Date := Date;
dtpAl.Date := Date;
end;

Dopo aver dichiarato nella form principale le variabili globali 'Dal' e ' Al', posso ottenere l'intervallo di tempo inserito dall'utente chiamando, dalla form principale stessa, la funzione GetDalAl.

Es.

function GetDalAl(out Dal, Al: TDate ): Boolean;
begin
Result := FALSE;
with TFrm_SelezionaIntervallo.Create(Application) do
begin
ShowModal;
Dal := dtpDal.Date;
Al := dtpAl.Date;
if (ModalResult = mrOk) then
Result := TRUE;
end;
end;

Esempio di cursore di attesa

L'esempio seguente mostra come salvare il cursore corrente, trasformarlo nel cursore di attesa e quindi ripristinarlo. A questo scopo è necessario dichiarare una variabile di tipo TCursor che memorizzi la forma corrente del cursore.

Es.

procedure TFrm_Calendario.Apridiario1Click(Sender: TObject);
var
Save_Cursor : TCursor;
begin
if (Giorni[iYSel, iXSel,0] <> 0) then
begin
Save_Cursor := Screen.Cursor;
// Salva il cursore corrente
Screen.Cursor := crHourglass;
with TFrm_Diario.Create(Application) do
begin
qStorico.ParamByName('DATA').AsDate := EncodeDate(wAnno, wMwSelDay);
Caption := Caption + DateToStr(qStorico.ParamByName('DATA').AsDate);
qStorico.Active := TRUE;
tStorico.Active := TRUE;
tParti.Active := TRUE;
end;
// Ripristina il cursore precedente
Screen.Cursor := Save_Cursor;
end;
end;

Come ovviare alla mancanza di array dinamici in Delphi 3

Il concetto di array dinamico è introdotto a partire da Delphi 4, un array dinamico è un array che viene dichiarato senza una dimensione iniziale e, al momento della dichiarazione, non viene allocata alcuna porzione di memoria; quest'ultima viene assegnata soltanto al momento dell'esecuzione.

In Delphi 3, per ovviare a questa mancanza, si possono costruire collezione di oggetti con la possibilità di creare e distruggere oggetti all'interno della classe mediante la definizione di funzioni interne.

L'esempio che segue crea la classe TCoefficienteCollection che contiene istanze di oggetti del tipo TCoefficientiItem; questi ultimi possono essere creati o distrutti all'interno della classe stessa, mediante le funzioni Aggiungi e Delete.

Es.

{************************************************
* Definizione dell'oggetto TCoefficientiItem *
************************************************}
type
TCoefficientiItem = class(TCollectionItem)
private
public
iID : Integer; // Identificativo del coefficiente
sDescr : String; // Descrizione parametro
fValore : Real; // Valore del parametro
fPeso : Real; // Peso statistico
end;


{******************************************************
* Definizione dell'oggetto TCoefficienteCollection *
******************************************************}
type
TCoefficienteCollection = class(TCollection)
private
public
// Funzione di creazione dell'oggetto
class function Create: TCoefficienteCollection;
// Funzione di creazione di un item
function Aggiungi: TCoefficientiItem;
// Funzione di cancellazione di un item a partire dal suo identificativo
function Delete(iID: Integer): Boolean;
end;


{***************************************************
* Funzioni della classe TCoefficientiCollection *
***************************************************}


// Funzione di creazione dell'oggetto
class function TCoefficienteCollection.Create: TCoefficienteCollection;
begin
Result := TCoefficienteCollection(TCollection.Create(TCoefficientiItem));
end;


// Funzione di creazione di un item
function TCoefficienteCollection.Aggiungi: TCoefficientiItem;
begin
Result := TCoefficientiItem(Add);
end;


// Funzione di cancellazione di un item a partire dal suo identificativo
function TCoefficienteCollection.Delete(iID: Integer): Boolean;
var
i: Integer;
begin
for i := 0 to Count - 1 do
begin
if (TCoefficientiItem(Items[i]).iID = iID) then
begin
TCoefficientiItem(Items[i]).Free;
Result := TRUE;
Exit;
end; //if
end; //for
Result := FALSE;
end;

Esempio di applicazione di un filtro ad una tabella

I filtri sulle tabelle vengono usati principalmente su database locali; con database client/server è preferibile usare al loro posto query SQL. I filtri nel componente Table sono gestiti in due modi:

  • Attraverso la proprietà Filter.
  • Attraverso l'evento ONFilterRecord.

In entrambi i casi la proprietà Filtered determina se la tabella viene filtrata: se vale True, la tabella applicherà il filtro correntemente in vigore (il contenuto della proprietà Filter o il risultato dell'evento OnFilterRecord); se vale False, il contenuto della proprietà Filter viene ignorato e l'evento OnFilterRecord non viene mai generato.

Un esempio di applicazione di un filtro mediante l'uso della proprietà Filter è il seguente:

with TFrm_Importo.Create(Self) do
begin
Frm_Main.sbMain.Panels[0].Text := 'Inserimento dell''importo';
if (ShowModal = mrOK) then
begin
with Frm_InserimentoFatture.tFatture do
begin
if Filter = '' then
begin
Filtered := False;
Filter := 'importo >= ''' + CurrToStr(Importo1) + ''' AND importo <= ''' + CurrToStr(Importo2) + '''';
Filtered := True;
end //if
else
begin
iLength :=(Length(Filter) - 1);
sFiltro := Copy(Filter, 1, iLength);
Filter := sFiltro + ''' AND importo > ''' + CurrToStr(Importo1) + ''' AND importo < ''' + CurrToStr(Importo2) + '''';
end; //else
end; //with
end; //if
Free;
Frm_Main.sbMain.Panels[0].Text := 'Fatture con importo compreso tra ' + CurrToStr(Importo1) + ' e ' + CurrToStr(Importo2);
end; //with

L'esempio descritto applica un filtro sul campo importo della tabella tFatture; nel caso in cui nella tabella sia già presente un filtro (ramo else), applica il filtro sulla tabella filtrata precedentemente mediante l'operatore logico AND.

Un esempio di applicazione di un filtro mediante l'uso dell'evento OnFilterRecord è il seguente:

procedure Frm_Main.tFattureFilterRecord(DataSet: TDataSet; var Accept: Boolean);
var
Valore: Double;
begin
Valore := tFatture.FieldByName('importo').Value;
Accept := ((Valore > CurrToStr(Importo1)) AND (Valore < CurrToStr(Importo2));
Filtered := True;
end;

L'elemento chiave è il parametro Accept. L'evento OnFilterRecord viene chiamato una volta per ogni riga nella tabella. Il codice precedente imposta Accept a True per ogni riga nella quale il campo importo ha valori compresi tra CurrToStr(Importo1) e CurrToStr(Importo2).

Sia nel caso dell'uso della proprietà Filter che dell'evento OnFilterRecord, la proprietà FilterOptions determina come il filtro verrà applicato. Questa proprietà è un insieme che può contenere uno o entrambi tra foCaseInsensitive e foNoPartialCompare. Di default questa proprietà è un insieme vuoto, il che significa che i filtri distingueranno tra maiuscole e minuscole e permetteranno confronti parziali.

NB: Quando i confronti parziali sono permessi, la specifica di un filtro come:

Filter := 'Autore = M*';

si risolve in un dataset contenente tutti i record nei quali il campo 'Autore' inizia con la lettera M.

Esempio di salvataggio del risultato di un report in formato .dbf

La form seguente permette all'utente di inserire i parametri per la costruzione di un report e la possibilità di salvare il risultato in formato .dbf:

Esempio

Se il report è costruito a partire da una sola query, è sufficiente porre sulla Frm_Main, oltre alla query in questione, un oggetto TBatchMove, un oggetto TSaveDialog, con le proprietà Filter e DefaultExt impostate in modo che il file sia salvato in formato .dbf, ed un oggetto TTable, impostando a design-time la proprietà TableType di quest'ultimo come:

TableType := ttDBase;

L'esempio che segue copia il risultato della query qFlotta nella tabella tScarico, mediante l'oggetto TBatchMove bmCod.

Es.

procedure TFrm_ElencoFlotta.Flotta1Click(Sender: TObject);
var
Save_Cursor: TCursor;
begin
with TFrm_InserisciCodConc.Create(Self) do
begin
if (ShowModal = mrOK) then
begin
if (ckFile.Checked) then
begin
if (SaveDialog.Execute) then
begin
try
tScarico.TableName := SaveDialog.FileName;
Frm_ElencoFlotta.sbFlotta.Panels[0].Text := 'Elenco flotta per Cap';
qFlotta.ParamByName('CODINS').AsString := sCodIns;
Save_Cursor := Screen.Cursor;
Screen.Cursor := crHourglass;
qFlotta.Active := TRUE;
bmCod.Execute;
qFlotta.Active := FALSE;
Screen.Cursor := Save_Cursor;
MessageDlg('Il file é stato salvato con successo nella directory ' + SaveDialog.FileName, mtInformation,[mbOK], 0);
Frm_ElencoFlotta.sbFlotta.Panels[0].Text := '';
except
MessageDlg('Impossibile salvare il file ' + SaveDialog.FileName, mtError, [mbOK], 0);
end; //try
end; //if
end //if
else
begin
with TRep_ElencoFlotta.Create(Self) do
begin
Frm_ElencoFlotta.sbFlotta.Panels[0].Text := 'Elenco flotta per Cap';
qFlotta.ParamByName('CODINS').AsString := sCodIns;
qrlaTitolo.Caption := 'Elenco flotta per Cap';
qFlotta.Active := TRUE;
Preview;
qFlotta.Active := FALSE;
Free;
Frm_ElencoFlotta.sbFlotta.Panels[0].Text := '';
end; //with
end; //else
end; //if
Free;
end; //with
end;

Se invece il report è costituito da più query, è necessario creare run-time una tabella e copiare in essa i risultati delle query. L'esempio che segue crea una tabella tPorsche e copia in essa i risultati delle query qABCMese e qTotABCMese.

Es.

if (ckFile.Checked) then
begin
if (SaveDialog.Execute) then
begin
try
Frm_Main.sbMain.Panels[0].Text := 'Salvataggio in corso del file';
with tPorsche do
begin
TableName := SaveDialog.FileName;
FieldDefs.Clear;
FieldDefs.Add('CasaAuto', ftString, 20, FALSE);
FieldDefs.Add('Imm', ftInteger, 0, FALSE);
FieldDefs.Add('Perc', ftString, 8, FALSE);
CreateTable;
end; //with
qCasaAuto.Active := TRUE;
qABCMese.Active := TRUE;
qTotABCMese.Active := TRUE;
qCasaAuto.First;
qABCMese.First;
qTotABCMese.First;
tPorsche.Active := TRUE;
iSommaTot := 0;
while not qTotABCMese.EOF do
begin
iSommaTot := iSommaTot + qTotABCMese.FieldByName('Imm').AsInteger;
qTotABCMese.Next;
end; //while
Frm_Main.qABCMese.First;
iSommaPor := 0;
while not qCasaAuto.EOF do
begin
with tPorsche do
begin
Append;
FieldByName('CasaAuto').Value := qCasaAuto.FieldByName('DESCRCASA').Value;
qABCMese.First;
iSommaImm := 0;
while not qABCMese.EOF do
begin
if qABCMese.FieldByName('CasaAuto').Value = qCasaAuto.FieldByName('DESCRCASA').Value then
iSommaImm := iSommaImm + qABCMese.FieldByName('Imm').AsInteger;
Frm_Main.qABCMese.Next;
end; //while
FieldByName('Imm').Value := IntToStr(iSommaImm);
FieldByName('Perc').Value := format('%2.2f %%', [(100.0 * iSommaImm) / iSommaTot]);
qCasaAuto.Next;
end; //with
end; //while
Screen.Cursor := Save_Cursor;
MessageDlg('Il file é stato salvato con successo nella directory ' + SaveDialog.File, mtInformation, [mbOK], 0);
Frm_Main.sbMain.Panels[0].Text := '';
qCasaAuto.Active := FALSE;
qABCMese.Active := FALSE;
qTotABCMese.Active := FALSE;
tPorsche.Active := FALSE;
except
Screen.Cursor := Save_Cursor;
MessageDlg('Impossibile salvare il file ' + SaveDialog.FileName, mtError, [mbOK], 0);
qCasaAuto.Active := FALSE;
qABCMese.Active := FALSE;
qTotABCMese.Active := FALSE;
tPorsche.Active := FALSE;
end; //try
end; //if
end; //if