View Full Version : [VBA Access] Come fare per visualizzare in casella di testo una query SQL
Salve a tutti.
Mi sono imbarcato nell'impresa di creare un database di gestione di una videoteca (non è un esercizio o un compito: è una cosa vera!).
Il cliente m'ha chiesto di creargli, tra le tante opzioni, una maschera per poter lui modificare le note per un cliente (sono note personali es. "deve dare 5€", "contattarlo al num. xxx" ecc.). Io ho fatto così: nella tabella "clienti" ho messo un campo Testo "note", occupando tutti e 255 i caratteri disponibili. Nella maschera ho messo un elenco (casella di riepilogo) che mi visualizzasse certi campi della tabella clienti (non tutti, perchè nella maschera era inutile averli tutti) e poi ho creato una casella di testo che, nella mia idea, doveva funzionare così: cliccando con un pulsante (o direttamente sull'elenco) mi visualizzava la nota relativa al cliente selezionato in elenco nella casella di testo, e tramite la casella stessa io potevo modificare la nota e con un altro pulsante mandarla al record appartenente e sostituirla.
Purtroppo, se faccio:
Testo12.Value = "SELECT clienti.note FROM clienti WHERE clienti.numtessera=[Inserisci numero tessera del cliente:];"
la casella di testo mi visualizza "SELECT clienti.note FROM clienti WHERE clienti.numtessera=[Inserisci numero tessera del cliente:];" invece di svolgermi la query.
Come posso fare? :help:
Nella maschera ho messo un elenco (casella di riepilogo) che mi visualizzasse certi campi della tabella clienti (non tutti, perchè nella maschera era inutile averli tutti) e poi ho creato una casella di testo che, nella mia idea, doveva funzionare così: cliccando con un pulsante (o direttamente sull'elenco) mi visualizzava la nota relativa al cliente selezionato in elenco nella casella di testo, e tramite la casella stessa io potevo modificare la nota e con un altro pulsante mandarla al record appartenente e sostituirla.
La tua idea può essere implementata in un modo relativamente facile.
Crei una query di selezione parametrica ( SELECT + 1 Parametro - numtessera ), una query di aggiornamento, sempre parametrica ( UPDATE + 2 Parametri numtessera e nuove_note )...
Con un pulsante metti in una textbox le note da visualizzare per quel dato cliente ( numtessera deve essere ovviamente campo univoco nel db ), con un altro pulsante aggiorni le note per quel cliente con eventuali modifiche.
Se ti interessa questa soluzione ti faccio un piccolo esempio in VBA... ;)
@Marco: grazie per l'interessamento. :)
Se fosse possibile un esempio scritto te ne sarei grato, perchè non ho capito bene cosa scrivere.
P.S. se per numtessera, univoco intendi che non ce ne sono 2 uguali: sì, lo è, grazie al fatto che è tipo Contatore.
@Marco: grazie per l'interessamento. :)
Se fosse possibile un esempio scritto te ne sarei grato, perchè non ho capito bene cosa scrivere.
P.S. se per numtessera, univoco intendi che non ce ne sono 2 uguali: sì, lo è, grazie al fatto che è tipo Contatore.
Detto fatto.
Anzitutto un consiglio : numtessera io NON lo farei contatore, casomai faccio un ID chiave primaria e contatore, mentre numtessera campo univoco, ossia "indicizzato : SI (duplicati non ammessi)".
Creo una query di selezione che chiamo "Query_Select" parametrica :
SELECT T_Clienti.numtessera, T_Clienti.note
FROM T_Clienti
WHERE (((T_Clienti.numtessera)=[Inserire Numero Tessera]));
Creo una query di aggiornamento "Query_Update" parametrica :
UPDATE T_Clienti SET T_Clienti.[note] = [Inserire Note]
WHERE T_Clienti.numtessera=[Inserire Numero Tessera];
Intanto arriva fin qui... ;)
Le sto creando adesso. :)
Ma come mai non mettere numtessera come contatore? Non ho bisogno di modificarla o metterla personalizzata. Mi deve soltanto conteggiare i clienti, anche nel caso in cui qualcuno volesse disiscriversi.
Piccolo OT: nella stessa maschera di modifica delle note, ho messo una casella di riepilogo ad una riga per visualizzare le stesse (senza modificarle). Non riesco, però, a creare la barra di scorrimento nel caso di note troppo lunghe! Così mi si visualizzano tagliate. Ho provato creando dello spazio, modificando la larghezza delle colonne, ma niente... Dove sbaglio?
Allora :
1. Non è mai consigliabile lasciare gestire con un banale contatore un DATO. Prendila come regola generale per DB più complessi di questo. Spesso i codici delle tessere sono fatti da un numero fisso di caratteri alfanumerici, perciò ti consigliavo di creare una PK "ID" contatore o addirittura avere numtessera come PK... Ma se va bene a te, e per un DB così semplice, nessun problema.
2. Le barre di scorrimento ( ACCESS 2003 ) su un controllo txt le attivi da
- proprietà / Formato / Barre Scorrimento > Verticale, e poi
- Allineam. barra di scorrimento > Da destra ( o sinistra ).
3. Il tuo DB adesso contiene le due query che ti ho postato, perciò crea una maschera come questa ( poi adatterai il mio esempio alle tue necessità... ) :
- ogni controllo deve avere il nome che gli ho dato io, sennò il codice VBA non funzionerà !
- una textbox "txtNum" non associata.
- una textbox "txtNote" non associata.
- un pulsante "cmdSelect".
- un pulsante "cmdUpdate".
4. Codice per Click su cmdSelect :
Private Sub cmdSelect_Click()
Dim numTessera As String
txtNum.SetFocus
numTessera = txtNum.Text
Dim QD As QueryDef
Set QD = CurrentDb.QueryDefs("Query_Select")
QD.Parameters("Inserire Numero Tessera") = numTessera
Dim RS As Recordset
Set RS = QD.OpenRecordset
MsgBox RS.RecordCount
txtNote.SetFocus
txtNote.Text = RS("note").Value
RS.Close
QD.Close
Set RS = Nothing
Set QD = Nothing
End Sub
5. Codice per Click su cmdUpdate :
Private Sub cmdUpdate_Click()
Dim numTessera As String
txtNum.SetFocus
numTessera = txtNum.Text
Dim nuoveNote As String
txtNote.SetFocus
nuoveNote = txtNote.Text
Dim QD As QueryDef
Set QD = CurrentDb.QueryDefs("Query_Update")
QD.Parameters("Inserire Numero Tessera") = numTessera
QD.Parameters("Inserire Note") = nuoveNote
QD.Execute
QD.Close
Set QD = Nothing
End Sub
L'esempio funziona così :
- Scrivi un codice numtessera nella txtNum.
- Premi il pulsante cmdSelect e nella txtNote ti trovi le note di quel cliente.
- Modifica qualcosa nelle note > Premi cmdUpdate e applichi le modifiche.
6. Pagare birra... :D
Grazie mille, ma ho dei problemi:
1. La soluzione delle barre di scorrimento non va, perchè non c'è l'opzione Barre di scorrimento (e quindi poi la selezione Verticale). Sarà perchè è Access 2002 (ovvero XP)?
2. Nei codici dei pulsanti non mi riconosce la dichiarazione "QueryDef": ho cercato nella lista, e in effetti non c'è! Ho provato a togliere "Option Explicit", così da poter provare il codice cancellando la dichiarazione, ma sulla riga "Set RS = QD.OpenRecordset" mi dà errore di runtime 13, ovvero "Tipo non corrispondente". :muro:
E' perchè devo modificare qualche campo, nel caso tu l'avessi scritto diverso da quello che ho io in tabella?
P.S. mi spieghi, se possibile, brevemente, cosa hai scritto? Ci sono comandi che non conosco... :p
1. La soluzione delle barre di scorrimento non va, perchè non c'è l'opzione Barre di scorrimento (e quindi poi la selezione Verticale). Sarà perchè è Access 2002 (ovvero XP)?
2. Nei codici dei pulsanti non mi riconosce la dichiarazione "QueryDef": ho cercato nella lista, e in effetti non c'è! Ho provato a togliere "Option Explicit", così da poter provare il codice cancellando la dichiarazione, ma sulla riga "Set RS = QD.OpenRecordset" mi dà errore di runtime 13, ovvero "Tipo non corrispondente". :muro:
E' perchè devo modificare qualche campo, nel caso tu l'avessi scritto diverso da quello che ho io in tabella?
Devi prima cercare di replicare il mio esempio, adattandoti ad usare i nomi che uso io sennò non ne esci più. Poi lo adatterai...
1. Purtroppo Office XP è quello che conosco meno in assoluto. Sono passato direttamente dal 2000 al 2003 ( e francamente l'esistenza della versione XP non me la spiego proprio... ). Se non ci sono le barre, non ci sono e basta. Mi sa che c'è poco da fare. Direi che a 2008 inoltrato è legittimo pretendere che il cliente sia aggiornato almeno alla v.2003 ( la migliore per gli sviluppatori, 2007 a parte ).
2. Per il problema su RS, QueryDef ecc... entra nell'editor VBA della maschera :
>> Menu / Strumenti / Riferimenti >>
controlla che sia attivo "Microsoft Activex data objects 2.* library"...
Per le barre: WOW!
Per il fatto che ho la versione XP, l'ho lasciata perchè non m'ha mai dato problemi. Per la 2003, sapevo fosse più pesante, per questo non l'ho messa. Il fatto di dover gestire e creare DB m'è venuta solo da poco.
Comunque: i riferimenti non funzionano, ho provato le librerie dalla 2.0 alla 2.8. Nulla. Vedo se ho qualcos'altro disattivato.
Ho risolto il fatto dell'errore!
Dovevo attivare la libreria "Microsoft DAO 3.6 Object Library" e metterla la prima di tutti come priorità! (senza quest'ultima opzione, non funzionava! :eek: )
Ho risolto il fatto dell'errore!
Dovevo attivare la libreria "Microsoft DAO 3.6 Object Library" e metterla la prima di tutti come priorità! (senza quest'ultima opzione, non funzionava! :eek: )
Perchè, quella non l'avevi già attiva ? Io con Access 2003 solo ad installarlo ho già tutti i riferimenti di base impostati !
Se puoi, passa a Office 2003. Non so chi ti abbia detto che è più pesante di XP. Per me è velocissimo.
Quindi tutto ok con la mia soluzione ?
Non so perchè la libreria non fosse attiva. :confused:
Devo dirti GRAZIE perchè mi hai risolto un problemone! :p
Ho adattato il codice a quello che mi serviva, ho aggiunto qualcosa e adesso è perfetto. ;)
Adesso non mi resta che sbattere su un'altra maschera... Ho un pulsante che non mi funziona e non capisco il perchè. Guarda il codice:
Dim db As ADODB.Connection
Set db = CurrentProject.Connection()
Dim tabdvd As ADODB.Recordset
Set tabdvd = New ADODB.Recordset
tabdvd.LockType = adLockOptimistic
tabdvd.Open "dvd", db
Dim response1 As String
If Testo1.Value = "" Or Testo14.Value = "" Then
MsgBox "Non hai inserito il titolo del DVD!", vbExclamation, "Attenzione!"
Else
If Testo3.Value = "" Or Testo5.Value = "" Then
response1 = MsgBox("Non hai inserito il nome del regista o quello degli attori: continuare comunque?", vbYesNo, "Attenzione!")
If response1 = vbYes Then
tabdvd.AddNew
tabdvd!titolo = UCase(Testo1.Value)
tabdvd!genere = CasellaCombinata1.Value
tabdvd!supporto = CasellaCombinata2.Value
tabdvd!regista = Testo3.Value
tabdvd!attore = Testo5.Value
tabdvd!prezzo = Testo12.Value
tabdvd!numcopie = Testo14.Value
tabdvd.Update
tabdvd.Close
MsgBox "Perfetto, hai aggiunto il DVD con successo!", vbInformation, "Operazione completata"
End If
End If
End If
Perchè non mi entra in nessun IF?
Dim db As ADODB.Connection
Set db = CurrentProject.Connection()
Dim tabdvd As ADODB.Recordset
Set tabdvd = New ADODB.Recordset
tabdvd.LockType = adLockOptimistic
tabdvd.Open "dvd", db
Dim response1 As String
If Testo1.Value = "" Or Testo14.Value = "" Then
MsgBox "Non hai inserito il titolo del DVD!", vbExclamation, "Attenzione!"
Else
If Testo3.Value = "" Or Testo5.Value = "" Then
response1 = MsgBox("Non hai inserito il nome del regista o quello degli attori: continuare comunque?", vbYesNo, "Attenzione!")
If response1 = vbYes Then
tabdvd.AddNew
tabdvd!titolo = UCase(Testo1.Value)
tabdvd!genere = CasellaCombinata1.Value
tabdvd!supporto = CasellaCombinata2.Value
tabdvd!regista = Testo3.Value
tabdvd!attore = Testo5.Value
tabdvd!prezzo = Testo12.Value
tabdvd!numcopie = Testo14.Value
tabdvd.Update
tabdvd.Close
MsgBox "Perfetto, hai aggiunto il DVD con successo!", vbInformation, "Operazione completata"
End If
End If
End If
Intanto vedo parecchie cose che non mi piacciono, in particolare :
1. Il modo corretto per verificare che una textbox non contenga una stringa vuota ( che comunque è una stringa ) è il confronto con la sua proprietà .Text. Tu invece usi .Value dappertutto...
2. il result di una msgbox ( vbYes, vbNo, ecc... ) va registrato come Variant, non come String.
Intanto vedo parecchie cose che non mi piacciono, in particolare :
1. Il modo corretto per verificare che una textbox non contenga una stringa vuota ( che comunque è una stringa ) è il confronto con la sua proprietà .Text. Tu invece usi .Value dappertutto...
2. il result di una msgbox ( vbYes, vbNo, ecc... ) va registrato come Variant, non come String.
Eh... In base a quello che mi hanno insegnato! :rolleyes:
Vedo di modificare il tutto... ;)
Scusa se ritorno dopo tanto tempo.
Allora: ho lasciato ".value" perchè con il ".text" aveva problemi. E funziona bene comunque.
Adesso ho una domanda: il cliente m'ha chiesto che, quando aggiunge un nuovo DVD alla tabella tramite apposita maschera, venga visualizzato il codice che il DVD assume dopo essere stato inserito nella tabella, che sarebbe il campo "numprog", che è Contatore.
Quando clicco sul pulsante "Aggiungi DVD", quale codice devo mettere per vedere che numprog prende? Devo spostarmi sull'ultimo record e prendere il contenuto di quel campo? Se sì, come si fa? :p
Adesso ho una domanda: il cliente m'ha chiesto che, quando aggiunge un nuovo DVD alla tabella tramite apposita maschera, venga visualizzato il codice che il DVD assume dopo essere stato inserito nella tabella, che sarebbe il campo "numprog", che è Contatore.
Quando clicco sul pulsante "Aggiungi DVD", quale codice devo mettere per vedere che numprog prende? Devo spostarmi sull'ultimo record e prendere il contenuto di quel campo? Se sì, come si fa? :p
Elementare Watson, appena dopo il codice che esegue l'inserimento fai partire una SELECT sul massimo valore attuale del contatore "numprog" ( il RecordSet in questione avrà sempre e solo 1 valore... ) :
SELECT MAX(T_DVD.numprog)
FROM T_DVD;
ammettendo che la tabella si chiami, appunto "T_DVD"... ;)
Grazie mille!
Il codice è esatto, ho creato la query "max_numprog" ma non so come farla partire! :p
Io faccio:
Dim w As Integer, z As String
z = "SELECT * FROM max_numprog;"
w = Val(z)
E mi dà sempre 0, cioè come se non ci fossero numeri nella stringa.
Dove sbaglio?
Non funzionerà mai così, e poi che senso ha fare una Select su una Query già creata ?
Se usi una Stored Query "max_numprog" :
SELECT MAX(T_DVD.numprog) AS [max]
FROM T_DVD;
E poi il valore che ritorna lo mettiamo in una variabile Long :
Dim max As Long
max = 0
Dim QDmax As QueryDef
Set QDmax = CurrentDb.QueryDefs("max_numprog")
Dim RSmax As Recordset
Set RSmax = QDmax.OpenRecordset
max = CLng(RSmax("max").Value)
RSmax.Close
QDmax.Close
Set RSmax = Nothing
Set QDmax = Nothing
Pensavo fosse chiaro, dai post precedenti... :D ;) .
Erano, ma non per me. Ma chi me l'ha fatto fare di imbarcarmi in quest'impresa... :doh:
Grazie mille ancora una volta. Adesso è tutto perfetto. :)
Ma chi me l'ha fatto fare di imbarcarmi in quest'impresa... :doh:
E perchè mai ? Il miglior modo per iniziare è porsi un problema reale, per quanto circoscritto, e tentare di risolverlo... :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.