Newsgroup: it.comp.lang.delphi
Titolo: Questa è più difficile

Sembra semplice, ma non riesco a risolverla. Ho una istruzione cosě:
Content.Text:= Sql_Query1;
 
dove Sql_Query1 č una costante contenente il testo della query.
Ho una stringList con tutti i nomi di queste const con i nomi delle varie 
queries.
Ma la seguente istruzione non funziona, come sospettavo:
 
Content.Text:= ListQueries.Items[ListQueries.ItemIndex];
 
Nel vecchio Clipper bastava prefissare ListQueries con un &.
Ma adesso c'č un modo di farlo (con Delphi 2007) ?
 
 

 
 
??? Una TStringList non ha Items[] ma Strings[] e non ha ItemIndex ma 
IndexOf.
 
Puoi precisare cosa ti aspettavi e cosa, invece, ottieni?
 
Grazie.
 
 

Scusa, scusa, non è una stringlist, ma una ListBox. Ma il concetto è che 
ogni elemento contiene il nome di una costante il ci contenuto è il testo 
della query. In sostanza vorrei accedere al testo della query, invece che 
usando direttamente il nome della query, usando una variabile che contiene 
il nome della query.
Cioè:
 
const Query1 = 'Select * from DB'
 
   queryContent:= Query1;                      // mette in queryContent il 
testo sopra
 
Vorrei fare:
strNomeQuery:= 'Query1';
 
queryContent:= strNomeQuery;          // non mette il testo, ma il nome !!
 
La domanda è: c'è un modo per indirizzare la costante, cioè il testo della 
query ?
 
 
"Luigis"  ha scritto nel messaggio news:rp5j35$p2l$1...@gioia.aioe.org...


 
var
   strNomeQuery: string;
begin
   ListBox1.Clear;
   ListBox1.Items.Add('Query1=select * from DB');
   ListBox1.Items.Add('Query2=select * from DB2');
   ListBox1.Items.Add('Query3=select * from DB3');
 
   strNomeQuery := 'Query1';
   ShowMessage(ListBox1.Items.Values[strNomeQuery]);
end;
 
Ciao.

Ciao,
 
Il 19/11/2020 13:59, Stark ha scritto:

Questo funziona, forse fara' venire la pelle d'oca a qualcuno ma su 
piedi fa quello che cerchi tu
 
unit Unit3;
 
interface
 
uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
System.Classes, Vcl.Graphics,
   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
 
Const Str1 = 'Query 1';
       Str2 = 'Query 2';
       Str3 = 'Query 3';
 
type
   TForm3 = class(TForm)
     ListBox1: TListBox;
     Edit1: TEdit;
     procedure FormCreate(Sender: TObject);
     procedure ListBox1Click(Sender: TObject);
   private
     { Private declarations }
   public
     { Public declarations }
   end;
 
var
   Form3: TForm3;
 
   StrContext : String;
 
   AllStrings : Array of String = [Str1,Str2,Str3];
 
implementation
 
{$R *.dfm}
 
procedure TForm3.FormCreate(Sender: TObject);
begin
   listbox1.Items.Clear;
   listbox1.Items.Add('Stringa1');
   listbox1.Items.Add('Stringa2');
   listbox1.Items.Add('Stringa3');
   listbox1.itemindex:=0;
   Edit1.text:=Allstrings[listbox1.ItemIndex];
end;
 
procedure TForm3.ListBox1Click(Sender: TObject);
begin
   Edit1.text:=Allstrings[listbox1.ItemIndex];
end;
 
end.
 
E' un punto di partenza.
Nel senso che puoi creare un file esterno (Query.txt o simili) dove 
mettere tutte le query che utilizzi.
Anziche' un array usa una TStringList dove caricare tutte le query cosi' 
hai tutto nella string list e sostituisci con quella ...
 
Codice modificato ... cosi' puoi lavorare con l'array o con le liste.
Io preferirei la lista perche' li hai la possibilita', molto agevole, di 
inserire nuove query o eliminare quelle che non ti servono; In piu' le 
puoi tenere fuori dal programma in bel file di testo da riliggere quando 
ti pare.
 
unit Unit3;
 
interface
 
uses
   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
System.Classes, Vcl.Graphics,
   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
 
Const Str1 = 'Query 1';
       Str2 = 'Query 2';
       Str3 = 'Query 3';
 
       Str4 ='StringList Query1';
       Str5 ='StringList Query2';
       Str6 ='StringList Query3';
 
type
   TForm3 = class(TForm)
     ListBox1: TListBox;
     Edit1: TEdit;
     Label1: TLabel;
     Edit2: TEdit;
     procedure FormCreate(Sender: TObject);
     procedure ListBox1Click(Sender: TObject);
     procedure FormClose(Sender: TObject; var Action: TCloseAction);
     procedure ListBox1KeyDown(Sender: TObject; var Key: Word;
       Shift: TShiftState);
   private
     { Private declarations }
 
      TheList : TStringList;
 
   public
     { Public declarations }
   end;
 
var
   Form3: TForm3;
 
   StrContext : String;
 
   AllStrings : Array of String = [Str1,Str2,Str3];
 
implementation
 
{$R *.dfm}
 
procedure TForm3.FormCreate(Sender: TObject);
begin
   listbox1.Items.Clear;
   listbox1.Items.Add('Stringa1');
   listbox1.Items.Add('Stringa2');
   listbox1.Items.Add('Stringa3');
   listbox1.itemindex:=0;
   Edit1.text:=Allstrings[listbox1.ItemIndex];
 
   TheList:=TStringList.Create;
   // Qui puoi caricare con TheString.LoadFromFile() o Stream ecc...
   Thelist.Add(Str4);
   TheList.Add(Str5);
   TheList.Add(Str6);
   Edit2.Text:=TheList.Strings[ListBox1.ItemIndex];
end;
 
procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   // Qui puoi salvare con TheList.SaveToFile()...
   FreeAndNil(TheList);
end;
 
procedure TForm3.ListBox1Click(Sender: TObject);
begin
   Edit1.text:=Allstrings[listbox1.ItemIndex];
   Edit2.Text:=TheList.Strings[ListBox1.ItemIndex];
end;
 
procedure TForm3.ListBox1KeyDown(Sender: TObject; var Key: Word;
   Shift: TShiftState);
begin
   if(key=vk_Down) or (Key=VK_Up) then
   begin
     ListBox1Click(Sender);
   end;
end;
 
end.
 
Spero siati sia utile !!!
 
Ciao
 
Daniele
 
PS: mica tanto difficile 3 minuti ... eheheheh
 

OK, vi ringrazio entrambi dell'aiuto e credo che dovrò optare per la 
soluzione che suggerite. Io pensavo di poter usare solo una listBox con i 
nomi delle costanti (per poter scegliere la query da eseguire).
Supponiamo di avere due costanti:
 
const query1 = 'Select * from ....'
const query2 = 'Select * from ....'
 
e un listBiox con due elementi:
query1
query2'
 
Se avessi scelto dalla listBox l'elemento query1, mi illudevo di poter avere 
disponibile direttamente "il contenuto" della costante query1 (e cioè Select 
from ....).
Avevo memoria che in ambiente Clipper (che voi che siete giovani non 
conoscerete) c'era una espressione che poteva usarsi che consisteva nel 
prefissare una variabile con un segno "&", e in questo caso la istruzione:
&query1
avrebbe rappresentato, non la stringa 'query1',  bensì il contenuto della 
costante query1 e cioè 'Select * from ...'
 
Non so se sono riuscito a spiegarmi ...
 
 
 
"Stark"  ha scritto nel messaggio news:rp5q8b$9vf$1...@gioia.aioe.org...


 query2
 
Cosi' al volo, hai preso in considerazione una TStringGrid ?
Piu' o meno puoi mimare la listbox, due colonne, una con la stringa che 
vuoi far vedere (Query1), nella seconda la query (Select * from MyTable).
La seconda colonna la nascondi (StringGrid1.Colwidths[NumCol] := -1) e 
quando selezioni la riga corrispondente leggi il valore della colonna 
nascosta.
Per rendere piu' vicino alla listbox il risultato grafico, puoi 
nascondere anche la linea tra le righe.
Questo con la standard, ma ci sono molte griglie free in giro molto ben 
fatte (per esempio la scalabium)
 
Credo sia un buon compromesso ....
 
Ciao
 
Daniele

Non so come ringraziarti per i tentativi che fai per aiutarmi. A questo 
punto, io ho capito: uno, che non c'è modo per fare quello che pensavo, e 
due, che non sono riuscito a farvi capire pienamente il mio obiettivo.
Giusto per puntigliosità e per non concludere che non so proprio spiegarmi, 
tento ancora una volta.
 
Supponi che hai una unit il cui unico scopo è di raccogliere tutte le query 
sql che usi in una applicazione (nel mio caso si chiama unitSql.pas). Le 
query le ho definite qui in tante  const  (const qryCalcoloSaldo = 'Select 
sum(importo)...').
 
Per testare le query, io uso un programmino (TestQuery.dpr) che mi sono 
scritto io. Come faccio per catturare il testo della query che voglio 
provare? Fino ad ora ho semplicemente copiato con Ctrl-C  la parte tra gli 
apici dalla unitSql, trasferendola con Ctrl-V nel memo di nome StringaSelect 
del programmino di test.
 
Dopo un pò, ho cominciato a pensare a come evitare il copia e incolla senza 
però toccare unitSql.
Semplificando, supponiamo che qryCalcoloSaldo sia l'unica query definita. Se 
unitSql fosse conosciuto dal mio programmino (mettendolo negli uses), potrei 
mettere un bottone, al cui click potrei scrivere:
 
StringaSelect:= qryCalcoloSaldo;
 
e in StringaSelect avrei il testo della const qryCalcoloSaldo (cioè avrei 
accesso al contenuto della const che potrei eseguire per farne il test).
 
Se mi hai seguito fin qui senza romperti, avrai capito come mi è venuta 
l'idea di creare una lista da cui cercare la query da eseguire. Per altre 
ragioni, avevo già una lista dei nomi e quindi mi sono chiesto se con quella 
informazione, avrei potuto scrivere una istruzione simile a quella sopra per 
acchiappare il testo della query. Come ti ho detto, in ambiente Clipper, che 
era un dialetto dBase, sarebbe stato facile. Sarebbe bastato scrivere quella 
istruzione così:
StringaSelect:= &ListaNOMIQuery (1)    (lascia perdere la sintassi)
e in StringaSelect non avrei avuto il NOME della query, ma il CONTENUTO 
della const con il nome in ListaNOMIQuery (1)
 
Se in Pascal non c'è niente di simile, andare a creare una lista con tutti i 
testi delle query (molti mooolto lunghi), non mi sembra che valga la pena. 
Continuerò con il copia e incolla.
Dimmi solo se stavolta mi sono spiegato ..
 
"Daniele"  ha scritto nel messaggio news:rpbjg8$4s7$1...@gioia.aioe.org...


Ciao,
credo sia impossibile replicare in Delphi il funzionamento del & in Clipper (ricordi lontani...)
 
In pratica consisteva nell'accedere al contenuto della variabile tramite il suo nome, anteponendo il carattere &
 
In Delphi si avvicina il concetto di puntatore, ma non otterresti comunque quanto proposto.
Potresti quindi utilizzare una lista di puntatori... ma si complica il tutto...
 
L'unico modo che "forse" e ripeto "forse" si avvicina, è utilizzare le TStringList mediante l'accesso con la proprietà Values
 
Potresti così caricare nella lista (la chiamerò da qui in avanti Lst) le query nella forma 
     calcoloSaldo = select * from ...
 
All'interno della lista è presente proprio la sequenza chiave = valore per ogni singolo elemento.
Ogni elemento è poi separato dagli altri con i caratteri a capo (#13#10)... è pur sempre una lista di stringhe
 
L'assegnazione si può anche fare direttamente così:
    Lst.Values['calcoloSaldo'] := 'select * from ...';
 
Successivamente potresti accedere alla lista utilizzando questo comando:
    Lst.Values['calcoloSaldo'] 
 
Potresti anche definire una costante
const
    _calcolo_saldo = 'calcoloSaldo';
 
e accedere alla lista con
    Lst.Values[ _calcolo_saldo_ ] := ...
oppure
    value := Lst.Values[ _calcolo_saldo_ ];
 
 
Detto chiaramente, non si avvicina neppure lontanamente al funzionamento di Clipper!!!
 
Alessandro

Grazie Alessandro, ma la soluzione richiede una modifica nella unit che oggi 
contiene le query che non vorrei fare e., come tu stesso dici, non si 
avvicina nemmeno lontanamente al funzionamento alla 'Clipper, che invece mi 
avrebbe permesso di non modificare nulla.'
 
"Alessandro B."  ha scritto nel messaggio 
news:2469a0d4-3ce4-4835...@googlegroups.com...


> Content.Text:= Sql_Query1; 
 
io a suo tempo avevo aggirato il problema creando una tabella con un campo text che conteneva il testo delle query da richiamare

 spiegarmi, tento ancora una volta.
 
Onestamente parlando (meglio dire scrivendo) non so quale sia il 
problema. E' abbastanza ovvio che in C++ puoi fare cose che in delphi 
non puoi fare, e cosi' e' anche per altri linguaggi.
Ora hai diversi esempi, strategie e quant'altro per poter gestire 
stringhe e query.
A titolo personale (ma non solo dato che lo fanno anche molti programmi 
tra cui DBeaver) le query mettile in un file esterno e NON in una unit 
cosi' da poterle gestire a piacimento; al bisogno carichi il file.
 
Hai tutto nelle tue mani, aggiornaci su come hai risolto.
 
ciao
 
Daniele
 
 

In un'altra applicazione in effetti ho usato un file esterno, un file .ini 
per l'esattezza, il quale però ha degli inconvenienti anche lui. Il primo, 
banale ma non tanto, è che quando lo apri all'esterno la tua query appare 
poco leggibile se non illeggibile. E la seconda è che se il testo è al di 
spora di 1047 caratteri (o circa lì), non la carica se non usando dei 
trucchi. Io ho parecchie query che, per calcolare tanti dati tutti in una 
volta, hanno molte join e superano il limite.
Al che mi vengono due domande. La prima: che file usi per mantenere 
all'esterno le tue query? La seconda: sarebbe meglio che invece di tanti 
join facessi tante query?
 
"Daniele"  ha scritto nel messaggio news:rpfv9k$1u3l$1...@gioia.aioe.org...


 cosi' da poterle gestire a piacimento; al bisogno carichi il file. 
appunto la mia soluzione (forse mi sono spiegato male) di un record con un campo text che contiene il testo della query e un campo di descrizione e di ricerca evita di avere una miriade di file esterni alla procedura e magari che vengano modificati più o meno involontariamente dagli operatori

Giusto, ma cosa intendi per un campo testo? Come fai a sapere la lunghezza 
della query ? O intendi un campo memo ? E quanto può essere grande? Mi 
faccio queste domande perchè io uso dbf (BDE/dBase)
 
"brunello"  ha scritto nel messaggio 
news:35fda40d-7196-422f...@googlegroups.com...


 faccio queste domande perchè io uso dbf (BDE/dBase) 
 
ovvio un campo meme scusa ma l'abitudine con sql server i campi memo si chiamano text

 grande? Mi faccio queste domande perchè io uso dbf (BDE/dBase)
 
Stark devi renderla semplice senza troppi problemi.
Hai molte possibilita', ma se non vuoi seguirle e' una tua opzione ....
Una string puo' contenere una miriade di caratteri quindi questo non e' 
un problema.
La lista delle tue query la puoi mwettere in un DB, ovvero in una 
tabella nuova del DB; Meglio ancora fai una tabella in un db diverso dal 
tuo cosi' da non "sporcare" la base dati altrui (scelta consigliata).
La tabella ha due campi
 
IDQuery : String dove metti il nome che vuoi far vedere nella list box
Query : Memo dove metti tutta la tua query
 
Poi salvi, modifichi come vuoi il tuo DB con la query.
 
A te la scelta di cosa vuoi implementare; ti abbiamo dato tutto per 
regionarci sopra, array, liste, record, db ecc.... scegli tu ...
 
Non e' difficile ....
 
Ciao
 
Daniele
 
 
 
 

Pe cominciare ad usare qualcosa di diverso da dBase, che database consigli? 
So che tu usi Firebird, vero? Ma come accesso ai dati in ambiente D2007 ? 
Altra alternativa che non mi dispiacerebbe sarebbe Sqlite, ma ho guardato 
DISQLite3 e ho notato che l'ultima data di aggiornamento risale al 2014, dal 
che desumo che non sia il caso di adottarlo.
 
"Daniele"  ha scritto nel messaggio news:rpiku9$ict$1...@gioia.aioe.org...


 adottarlo.
 
Queste sono sempre domande la cui risposta non e' semplice perche' 
"personale".
In alcuni programmi uso firebird perche' e' un db di terze parti.
Non ci sono problemi e per lavorarci con le versioni piu' recenti di 
delphi trovi firedac (librerie multi DB).
A titolo personale, e' da anni che uso le librerie TurboDB, sono 
commerciali e costicchiano ma tieni presente che sono completemente 
compatibili con il vecchio dbe della borland e la sua implementazione e' 
quasi trasparente.
Inoltre supporta le versioni da D6 a Sidney.
 
Visto che stai usando Delphi 2007, forse e' il caso che ti avvicini di 
piu' verso il 10.4, magari con una community version .....
 
Ciao
 
Daniele