Accesso ai dati

annuncio pubblicitario
METODOLOGIE di ‘Accesso ai dati’
La gestione dei dati organizzati in archivi risulta più facile ed efficace attraverso l'utilizzo dei
database o basi di dati. Nei database gli archivi sono rappresentati da tabelle formate da righe e colonne: le
righe corrispondono ai record dell'archivio e le colonne ai campi del record.
I prodotti software per la gestione dei database, detti DBMS (Data Base Management System), per
esempio Access per Windows, semplificano l'attività dell'utente nelle operazioni di inserimento, modifica e
cancellazione dei dati, attraverso l'uso di interfacce grafiche amichevoli; inoltre i dati possono essere
ritrovati facilmente con le interrogazioni ai database (query) senza dover specificare i percorsi, le modalità
di accesso e le operazioni.
La gestione di un database creato con Access (file con estensione .mdb), o con altri prodotti software
per la gestione dei database, in ambiente Visual Basic, e non solo, è resa possibile attraverso l’uso di
apposite librerie di oggetti e specifici meccanismi di collegamento dei programmi applicativi ai database.
Vediamo, in ordine cronologico, le metodologie più utilizzate.
ODBC
I DBMS hanno, solitamente, un formato proprietario per la memorizzazione e l'acceso dei dati: è
necessario utilizzare driver e funzioni specifici per ciascun tipo di database. È, tuttavia, possibile accedere
ai dati memorizzati in database di tipo diverso (Access, SQL Server, Oracle ecc.) usando una collezione di
funzioni (API – Application Programmino Interface) nota con il nome di Open Database Connectivity
(ODBC). Questo è uno standard, sviluppato da Microsoft nel 1992, che fornisce istruzioni e funzioni per
l’accesso ai dati memorizzati nei differenti tipi di database e che possono essere richiamate da programmi
scritti in vari linguaggi di programmazione (Java, C++, Visual Basic, VBA ecc.). Sono disponibili librerie
ODBC (i cosiddetti ODBC driver) per quasi tutti i tipi di database.
ODBC permette di connettersi a un database locale o remoto. Microsoft ha creato questa tecnologia
per fornire un mezzo con cui sia possibile accedere a molti database diversi (quali dBASE, Microsoft
FoxPro, Microsoft Access, Microsoft SQL Server, Oracle e persino file di testo delimitati da virgole)
mediante una modalità unica (uso di API comuni). Il computer sul quale viene eseguita l'applicazione si
connette a una DLL (Dynamically Linked Library), chiamata ODBC Driver Manager, che invia i comandi a
(e recupera i dati da) un driver ODBC specifico per il particolare database che si desidera usare. La sfida di
ODBC, quindi, consiste nel fornire un'interfaccia comune a tutti questi diversi database. In teoria potete
creare un'applicazione che utilizza ODBC per accedere a un database di Access e poi adattarla a un database
di SQL Server cambiando semplicemente il driver ODBC sottostante ed, eventualmente, alcune istruzioni nel
codice sorgente. Ciò è possibile in quanto tutti i comandi inviati al database sono istruzioni SQL standard. In
pratica il driver ODBC tenta di convertire al meglio i comandi SQL standard nel "dialetto SQL" del
particolare database.
ODBC è efficiente, almeno in confronto a molte altre tecniche di accesso ai dati. Usare ODBC,
tuttavia non è semplice, specialmente per i programmatori Visual Basic. L'insieme delle funzioni di ODBC
è molto complesso e, se si commette un errore, spesso l'applicazione termina con un errore fatale. Per
questo motivo pochi programmatori Visual Basic scrivono applicazioni che chiamano direttamente le funzioni ODBC. Sono disponibili altre tecniche di accesso ai dati che possono usare i driver ODBC come strati
intermedi e che permettono comunque di eseguire chiamate API dirette.
Anche se non si utilizzeranno direttamente le chiamate all'API di ODBC nei programmi Visual
Basic, è utile conoscere alcuni concetti di base sui quali si fonda questa tecnologia. Un concetto con il quale
probabilmente si ha a che fare anche lavorando con ADO è il DSN (Data Source Name o nome di origine
dati). Un DSN è un insieme di valori di cui un'applicazione ha bisogno per connettersi correttamente a un
database. Un DSN tipicamente include il nome del driver ODBC che desiderate usare, il nome della
macchina che ospita il database server (se lavorate con motori client-server quali SQL Server o Oracle), il
nome o il percorso dello specifico database, il timeout della connessione (cioè il numero di secondi dopo i
quali, durante un tentativo di connessione, il driver ODBC abbandona e restituisce un errore
all’applicazione chiamante), i1 nome della workstation e dell'applicazione chiamante e cosi via.
E’ possibile creare un DSN in molti modi, all'interno o all'esterno dell'ambiente Visual Basic 6.
Un'applet di Control Panel (Pannello di controllo) permette di creare DSN e impostare altri valori di
configurazione ODBC. Potete scegliere tra diversi tipi di DSN: un DSN utente è memorizzato nel Registry
di sistema, può essere usato solo dall’utente corrente e non può essere condiviso con altri utenti; un DSN di
sistema è anch'esso memorizzato nel registro di configurazione ma è visibile a tutti gli altri utenti; un DSN
su file è memorizzato in un fìle dsn e può essere condiviso da tutti gli utenti (se il corretto driver ODBC è
installato sulle loro macchine). Poichè i DSN su file possono essere facilmente copiati su altre macchine,
essi facilitano la fase di installazione; d'altra parte l'applicazione deve sapere dove è posizionato il DSN e
quindi il codice deve fornire il percorso completo del file .dsn, che deve essere memorizzato da qualche
parte (per esempio in un file INI). I DSN utente e di sistema non presentano questo problema.
L'utilizzo dei DSN non è obbligatorio; quando si lavora con ODBC potete fornire direttamente nel
vostro codice tutte le informazioni necessarie per la connessione (il nome del driver, il nome e il percorso
del database e cosi via); si tratta delle cosiddette connessioni DSN-less (o "senza DSN"), che sono
normalmente più efficienti perchè il driver ODBC non deve accedere al Registry di sistema o a un file
DSN; le tecniche DSN-less richiedono però un maggiore lavoro da parte dello sviluppatore.
OLE DB
Da tempo le librerie ODBC non sono più sufficienti per accedere ai database e, per questo motivo,
Microsoft, nel 1997, decise di introdurre la nuova interfaccia OLE-DB provider per consentire l'accesso ai
dati di qualunque tipo.
OLE DB è una tecnologia di accesso ai dati a basso livello con la quale Microsoft ha inteso sostituire
ODBC come mezzo principale per la connessione al database. La controparte OLE DB dei driver ODBC
sono i provider OLE DB, che costituiscono iI collegamento tra applicazioni e database. Sebbene OLE DB
sia una tecnologia relativamente recente, esistono provider OLE DB per la maggior parte dei più diffusi
database e altri verranno presto commercializzati. Nonostante l'apparente somiglianza, le tecnologie ODBC
e OLE DB sono profondamente diverse: in primo luogo OLE DB il basa su COM (Common Object Model),
un'architettura capace di poter gestire grandi quantità di dati in rete; in secondo luogo OLE DB permette
di connettersi a qualunque tipo di origine dati; non solo ai database relazionali e ISAM (Indexed
Sequentlal Access Mode) che rappresentano il naturale campo di applicazione del driver ODBC.
Usando i provider OLE DB si possono elaborare i dati contenuti in messaggi e-mail, pagine
HTML, fogli di calcolo, file di testo, ecc. Visual Basic 6 offre provider per Microsoft Jet, SQL Server,
FoxPro, file di testo e database Oracle. Altri provider OLE DB possono essere scaricati dal sito Web di
Microsoft o acquistati da altri produttori.
Nella transizione tra i mondi ODBC e OLE DB potete usare uno speciale provider OLE DB, chiamato
MSDASQL, che funziona come un "ponte" verso qualunque origine dati ODBC. Invece di connettervi
direttamente al database, potete usare questo speciale provider per connettervi a un driver ODBC, che a sua
volta legge e scrive i dati nel database. Questo livello aggiuntivo presenta naturalmente un costo in termini
di prestazioni; ma potreste considerarlo come una soluzione di breve periodo per un problema che
scomparirà quando saranno disponibili più provider.
ADO
OLE DB è un'interfaccia di basso livello a cui i linguaggi di alto livello come Visual Basic non
possono accedere, o almeno non possono farlo con facilità. Inoltre, per utilizzare le librerie fornite
dall'interfaccia OLEDB si possono usare solo alcuni linguaggi di programmazione, tra cui C++, Visual
Basic. Per ovviare a questa limitazione, Microsoft ha introdotto un ulteriore strato software denominato
ActiveX Data Objects (ADO) che permette di utilizzare anche altri linguaggi di programmazione più
semplici.
ADO, quindi, è l'Interfaccia di alto livello per OLE DB; si basa su OLE DB ma fornisce funzioni che
non sono direttamente disponibili in OLE DB o che richiederebbero la scrittura di codice particolarmente
sofisticato. ADO permette di eseguire query e connessioni asincrone oltre che aggiornamenti batch. ADO,
rispetto ad altri oggetti precedenti, aggiunge nuove funzionalità, quali Recordset basati su file, Recordset
gerarchici e cosi via.
ADO nasce per fornire un meccanismo universale di accesso ai dati grazie a una gerarchia di oggetti
(ADO object model) che possono essere manipolati all'interno dei programmi scritti nel linguaggio di
programmazione preferito. ADO consiste di pochi oggetti che possono essere combinati in molti modi.
Un'altra importante caratteristica di ADO è la possibilità di utilizzare questa tecnologia dall'interno
delle pagine HTML oppure all'Interno di una pagina ASP (Active Server Page), ospitata su Internet
Information Server in esecuzione su un server.
Visual Basic include molti strumenti e programmi di utilità per creare applicazioni ADO in modo
veloce ed efficiente. Esso consente, tra l’altro, di accedere alle tabelle di un database attraverso l’oggetto
visuale Adodc della Casella degli strumenti. Per consentire l'accesso ai dati contenuti nelle tabelle di un
database, occorre effettuare alcune impostazioni
preliminari di connessione ai dati.
APPLICAZIONE
La figura a lato riepiloga i diversi metodi di
accesso alle origini dati in Visual Basic 6; come si
può vedere i vari metodi differiscono
notevolmente nel numero di livelli che esistono tra
l'applicazione e il database al quale si connette. La
nostra attenzione sarà concentrata sulla tecnologia
ADO, perché le altre tecnologie saranno nel tempo
sostituite da ADO.
Altri
Controlli
Controllo ADO
(Adodc 6.0)
ADO 2.x - Libreria
ODBC Driver Manager
(SQL Standard)
“Kagera”
Driver ODBC specifico
Provider OLE
DB
DATABASE
La seguente tabella riporta, in sintesi, alcuni esempi di modalità di connessione ad un database.
1 caso
Elementi utilizzati
Controllo ADODC
ADO 6.0
“Kagera”
ODBC Specifico
Codice per la connessione
 Si inderisce l’oggetto adodc sul form
 adodc1.ConnectionString = "DSN=nome DSN"
 adodc1.CommandType = adCmdTable|adCmdUnknown
 adodc1.RecordSource = "nomeatbella|query"
 Set Text1.DataSource = adodc1 ‘ binding dei dati
2 caso
(connessione con
DSN)
Controllo ADODC
ADO 6.0
Provider OLE DB
 Text1.DataField = “nomecampo”
 Si inderisce l’oggetto adodc sul form
 adodc1.ConnectionString = "PROVIDER=Microsoft.Jet.OLEDB.4.0;” _
“DATA SOURCE=percorso file.MDB"
 adodc1.CommandType = adCmdTable|adCmdUnknown
(senza DSN)
 adodc1.RecordSource = "nomeatbella|query"
 Set Text1.DataSource = adodc1 ‘ binding dei dati
3 caso
ADO non visuale
“Kagera”
ODBC Specifico
(con DSN)
 Text1.DataField = “nomecampo”
‘Dichiarazioni generali
Dim ado1 As ADODB.Connection
Dim rs1 As ADODB.Recordset
Private Sub Form_Load()
Set ado1 = New ADODB.Connection
Ado1.Open "DSN=nomeDSN"
Set rs1 = New ADODB.Recordset
Rs1.Open "tabella|query", ado1, adOpenStatic, adLockOptimistic
Visualizza
End Sub
Private Sub Visualizza()
‘ per ogni text o label:
Text1.Text = rs1!nomecampo oppure Text1.Text = rs1(“nomecampo”)
End Sub
4 caso
ADO non visuale
Provider OLE DB
Private Sub Salva()
‘ per ogni text o label:
rs1!nomecampo = Text1.Text oppure rs1(“nomecampo”) = Text1.Text
End Sub
‘Dichiarazioni generali
Dim ado1 As ADODB.Connection
Dim rs1 As ADODB.Recordset
(senza DSN)
Private Sub Form_Load()
Set ado1 = New ADODB.Connection
Ado1.Open = "PROVIDER=Microsoft.Jet.OLEDB.4.0;” _
“DATA SOURCE=percorso file.MDB"
Set rs1 = New ADODB.Recordset
Rs1.Open "tabella|query", ado1, adOpenStatic, adLockOptimistic
Visualizza
End Sub
Private Sub Visualizza()
‘ per ogni text o label:
Text1.Text = rs1!nomecampo oppure Text1.Text = rs1(“nomecampo”)
End Sub
Private Sub Salva()
‘ per ogni text o label:
rs1!nomecampo = Text1.Text oppure rs1(“nomecampo”) = Text1.Text
End Sub
La creazione del “DSN”
La procedura per creare una sorgente di dati (DSN) è descritta nei seguenti passaggi:
1. Dal menu Start|Impostazioni|Pannello di Controllo, scegliere Strumenti di amministrazione e poi
Origine dati (ODBC): si apre la finestra di dialogo ODBC Data Source Administrator
2. Selezionare la scheda User DSN, System DSN o File DSN a seconda del tipo di DSN da creare e
cliccare su Aggiungi
3. Nella successiva finestra di dialogo, scegliere il Driver in base al tipo di Database da utilizzare (nel
nostro caso: Microsoft Access Driver) e cliccare su Fine
4. Nell’ultima finestra di dialogo che si apre (Configurazione ODBC per Microsoft Access) (diversa per
ogni tipo di database), inserire il Nome Origine Dati e, tramite il pulsante Seleziona, selezionare cartella
e file .mdb contenente il database di Access e fare click su OK
La nuova sorgente dati (DSN) viene aggiunta
alle altre DSN.
L’oggetto ADODC
L'ambiente Visual Basic consente di
accedere con facilità alle tabelle di database
creato con Access (file con estensione .mdb), o
con altri prodotti software per la gestione dei
database, attraverso il controllo ADODC.
Questo controllo non fa parte degli oggetti
standard, per cui non è automaticamente
presente nella casella degli strumenti e quindi è
necessario aggiungerlo; attraverso il menu di
Visual Basic Progetto|Componenti (vedi figura a
lato), selezionare Microsoft ADO Data Control
6.0 (OLEDB), spuntando la casella corrispondente, e cliccare sul pulsante Applica: a questo punto sulla
casella degli strumenti comparirà l’oggetto Adodc. Nel form occorre inserire tanti controlli di tipo Adodc
quante sono le tabelle che si vogliono utilizzare nel form.
Le informazioni principali da fornire a ciascun adodc sono:
 Il database da utilizzare (proprietà ConnectionString, che indica tutte le informazioni per
l’individuazione del file di Access (avente estensione .mdb) (come ad esempio il DSN) (Tipo dato: oggetto
Adodc);
 La modalità di determinazione dell’insieme di record o RecordSet (proprietà CommandType):
Tabella, Query o Stored Procedure (adCmdTable, adCmdText, adCmdStoredProc o adCmdUnknown) (Tipo
dato: Numerico).;
 il nome della tabella contenuta nel database (proprietà
RecordSource). Può essere il nome di una tabella (adCmdTable)
o di una Query (adCmdText) (Tipo dato: Stringa).
Dopo aver assegnato il corretto valore alla proprietà
ConnectionString, in fase di progettazione, in corrispondenza
della scelta della proprietà RecordSource, si può trovare l'elenco
delle tabelle contenute nel database tra le quali è possibile
effettuare la scelta.
Il RecordSource può anche essere il nome di una query
già esistente nel database.
Per ricordare all'utente il nome dell'archivio sul quale si
intende operare, si può far comparire un nome significativo per
la tabella, assegnando un valore alla proprietà Caption del
controllo Adodc.
Se vogliamo inserire|modificare|cancellare|visualizzare dati in alcuni campi della tabella, inseriamo
nel form alcune caselle di testo e/o etichette e associamo a ciascuna di esse il campo corrispondente della
tabella. Questa operazione è chiamata Binding e gli oggetti che lo permettono sono detti di tipo DataBound
o Data-Aware.
Le proprietà da specificare per ciascuna delle caselle di testo sono:
• proprietà DataSource, che indica il controllo Adodc a cui il campo si riferisce (si può scegliere tra
l'elenco proposto)
• proprietà DataField, che indica il campo da associare alla casella di testo o etichetta (dopo aver
definito la proprietà DataSource; si può scegliere nell'elenco dei campi proposto.
È anche opportuno, per migliorare l'interfaccia grafica per l'utente, inserire una label di intestazione
per il form e le label vicino alle caselle di testo o etichette collegate al database per ricordare il significato
dei campi corrispondenti.
Nel caso si vogliano prelevare dati da una tabella ed inserirli in una tabella collegata (associazione 1
a Molti), è possibile inserire sul form un tipo di casella combinata: controllo DataCombo. Anche questo
controllo non è tra quelli standard, per cui è necessario aggiungerlo alla stessa maniera dell’oggetto Adodc,
tramite il menu Progetto|Componenti, scegliendo poi l’oggetto Microsoft Data Bound List Controls 6.0.
Facendo riferimento all’esempio a lato,
vediamo quali sono tutte le proprietà fondamentali
dell’oggetto:
• proprietà DataSource, che indica il
controllo Adodc a cui il campo si riferisce (si può
scegliere tra l'elenco proposto) (es.: adoVendite)
• proprietà DataField, che indica il campo
associato alla casella combinata (es.:CodArt, cioè la
chiave esterna della tabella dipendente)
• proprietà RowSource, che indica il
controllo Adodc a cui si riferisce il campo che viene
elencato nella lista (si può scegliere tra l'elenco proposto) (es.: adoArticoli)
• proprietà ListField, che indica il campo i cui
valori vengono elencati nella lista (si può scegliere tra
l'elenco proposto) (es.: DescrArticolo)
• proprietà BoundColumn, che indica il campo
(della tabella principale) i cui valori vengono registrati nel
campo della tabella secondariaelencati nella lista (si può
scegliere tra l'elenco proposto) (es.: CodArticolo, cioè la
chiave primaria della tabella primaria).
Tutti i valori delle proprietà degli oggetti presenti
sul form possono essere assegnati in fase di progettazione
oppure in fase di esecuzione, p.es. nell’evento Load del
form contenente gli oggetti Adodc.
A questo scopo si riporta un esempio.
Private Sub Form_Load()
adoVendite.ConnectionString = "DSN=Esempio"
adoVendite.CommandType = adCmdTable
adoVendite.RecordSource = "Vendite"
adoArticolo.ConnectionString = "DSN=Esempio"
adoArticoli.CommandType = adCmdTable
adoArticoli.RecordSource = "Articoli"
SET dcboArticoli.RowSource = adoVendite
dcboArticoli.ListField = "DescrArticolo"
SET dcboArticoli.DataSource = adoArticoli
dcboArticoli.DataField = "CodArt"
dcboArticoli.BoundColumn = "CodArticolo"
SET txt_Data.DataSource = adoArticoli
Txt_Data.DataField = "Data Vendita"
SET txt_Prezzo.DataSource = adoArticoli
Txt_Prezzo.DataField = "Prezzo"
SET txt_Quantita.DataSource = adoArticoli
Txt_Quantita.DataField = "Data Vendita"
End Sub
L’oggetto ADODB
E’, possibile utilizzare l’oggetto la tecnologia ADO senza l’utilizzo di controlli visuali come l’Adodc. In
tale caso è necessario indicare al progetto VBasic di fare riferimento agli oggetti presenti nella libreria
ADO. I passi da effettuare sono i seguenti
1. Creare un riferimento alla libreria
DLL
Dal menu Progetto, scegliere
Riferimenti… Nella finestra di
dialogo che appare, selezionare la
libreria Microsoft ActiveX data
Objects 2.X Library (dove la è un
numero che indica la sottoversione);
2. Creazione oggetti di Connessione e
Recordset
Nel programma creare due oggetti:
uno per attivare la connesione al
database e l’altro per gestire i dati (tabelle, query, ecc). Per esempio, nelle dichiarazioni generali:
‘Dichiarazioni generali
Dim ado1 As ADODB.Connection
Dim rs1 As ADODB.Recordset
e nell’evento Load del Form:
Set ado1 = New ADODB.Connection
Set rs1 = New ADODB.Recordset
3. Attivazione della connessione e Apertura del Recordset.
Nell’evento Form_Load, p. es.:
Ado1.Open = "PROVIDER=Microsoft.Jet.OLEDB.4.0;” _
“DATA SOURCE=percorso file.MDB"
Rs1.Open "tabella|query", ado1, adOpenStatic, adLockOptimistic, tipoComando
4. Visualizzare i dati presenti nel record della tabella del database
‘ per ogni text o label:
Text1.Text = rs1!nomecampo oppure Text1.Text = rs1(“nomecampo”)
5. Inserire dati nel record della tabella del database
‘ per ogni text o label:
rs1!nomecampo = Text1.Text oppure rs1(“nomecampo”) = Text1.Text
6. Chiudere Recordset e Connection
Ado1.Close
Rs1.Close
7. Distruggere gli oggetti Connection e Recordset
Set ado1 = Nothing
Set rs1 = Nothing
ESEMPIO
‘ Dichiarazioni generali
Dim adoSupermercato As ADODB.Connection
Dim rsProdotti As ADODB.Recordset
Private Sub cmd_Nav_Click(Index As Integer)
Select Case Index
Case 0
rsProdotti.MoveFirst
Case 1
rsProdotti.MovePrevious
If rsProdotti.BOF Then
rsProdotti.MoveFirst
End If
Case 2
rsProdotti.MoveNext
If rsProdotti.EOF Then
rsProdotti.MoveLast
End If
Case 3
rsProdotti.MoveLast
End Select
Visualizza
End Sub
Private Sub Command1_Click(Index As Integer)
Ab_Disab1
Select Case Index
Case 0
rsProdotti.AddNew
txt_CodP = ""
txt_DesP = ""
txt_Prezzo = ""
txt_Giac = ""
txt_ScMin = ""
Case 1
Case 2
rsProdotti.Delete
End Select
End Sub
Private Sub Command2_Click(Index As Integer)
Select Case Index
Case 0
' Prepara il buffer per la registrazione
rsProdotti!DesP = txt_DesP
rsProdotti!Prezzo = txt_Prezzo
rsProdotti!Giacenza = txt_Giac
rsProdotti!ScortaMin = txt_ScMin
rsProdotti.Update
Case 1
rsProdotti.CancelUpdate
' Ripristina i valori precedenti
Visualizza
'txt_CodP = rsProdotti!CodProdotto
'txt_DesP = rsProdotti!DesP
'txt_Prezzo = rsProdotti!Prezzo
'txt_Giac = rsProdotti!Giacenza
'txt_ScMin = rsProdotti!ScortaMin
End Select
Ab_Disab2
End Sub
Private Sub Form_Load()
Set adoSupermercato = New ADODB.Connection
adoSupermercato.Open "DSN=Supermercato"
Set rsProdotti = New ADODB.Recordset
rsProdotti.Open "SELECT * FROM Prodotti", adoSupermercato, adOpenStatic,
adLockOptimistic, adCmdText
Visualizza
End Sub
Private Sub Visualizza()
txt_CodP = rsProdotti!CodProdotto
txt_DesP = rsProdotti!DesP
txt_Prezzo = rsProdotti!Prezzo
txt_Giac = rsProdotti!Giacenza
txt_ScMin = rsProdotti!ScortaMin
End Sub
Private Sub Ab_Disab1()
For i = 0 To Command1.Count - 1
Command1(i).Enabled = False
Next
For i = 0 To Command2.Count - 1
Command2(i).Enabled = True
Next
For i = 0 To cmd_Nav.Count - 1
cmd_Nav(i).Enabled = False
Next
txt_DesP.Enabled = True
txt_Prezzo.Enabled = True
txt_Giac.Enabled = True
txt_ScMin.Enabled = True
End Sub
Private Sub Ab_Disab2()
For i = 0 To Command1.Count - 1
Command1(i).Enabled = True
Next
For i = 0 To Command2.Count - 1
Command2(i).Enabled = False
Next
For i = 0 To cmd_Nav.Count - 1
cmd_Nav(i).Enabled = True
Next
txt_DesP.Enabled = False
txt_Prezzo.Enabled = False
txt_Giac.Enabled = False
txt_ScMin.Enabled = False
End Sub
Scarica