VB Tips Database
Bug di VB5 con DataControl in ReadOnly

Un bug di VB5 scomparso però in VB6 un po bizzarro è:

Se il primo DataControl aperto dall'applicazione è in ReadOnly con molta probabilità da quel punto in avanti il database a cui quel datacontrolè legato saràReadOnly per tutti gli altri oggetti DAO.Per evitare questo inconveniente basta fare in modo che il primo datacontrol sia ReadOnly = False.

Query parametrica

Una query parametrica è una query che attendeun valore dall'esterno quando deve essere eseguita. Sotto Access è Access stesso che richiede il valore quando neccessario, mentre sotto VB occorre passarlo da codice per es. usando l'oggetto QueryDef

Creare delle Query utilizzando delle variabili in VB

SQL = "select * from table where _
datefield = #" & DateValue(text1.text) & "#" 'Per passare variabili di tipo data

SQL = "select * from table where _
stringfield = '" & text1.text & "'" 'Per passare variabili di tipo stringa

SQL = "select * from table where _
numericfield = " & val(text1.text) 'Per passare variabili Integer

 

Connettersi ad una fonte dati ODBC tramite DAO 3.5

Per eseguire il codice seguente e' necessario avere configurato una fonte dati ODBC

Public Sub ApriFonteODBC()
Dim wrkODBC As Workspace
Dim conODBC As Connection
Dim rs As Recordset

On Error GoTo GestError
'Crea l’oggetto Workspace di ODBCDirect.
Set wrkODBC = CreateWorkspace("NewODBCWorkspace", _
"admin", "", dbUseODBC)
'Il nome della fonte dati utilizzata in questo caso e' MyDSN
Set conODBC = wrkODBC.OpenConnection("Connection1", _
dbDriverNoPrompt, , "ODBC;UID=;PWD=;DSN=MyDSN")
'il database utilizzato in questo esempio contiene
'una tabella Regioni; modificarla con i propri dati
Set rs = conODBC.OpenRecordset("select * from Regioni")
Do While Not rs.EOF
'Visualizza nella finestra di debug tutti i valori del
'Fields(1) (la tabella in questo caso ha due campi)
Debug.Print rs.Fields(1)
rs.MoveNext
Loop
conODBC.Close
wrkODBC.Close
Exit Sub

GestError:
MsgBox "Attenzione " & Err.Description
End Sub

 

Enumerare e stampare i report di un Db di Access

Con le seguenti funzioni e' possibile ottenere i nomi dei report all'interno di un DB Access ed in seguito visualizzarli o stamparli. Per funzionare, deve essere presente un copia del programma Access sul PC dove dovra' girare il software che utilizza queste funzioni. Potete scaricare il file report.zip con un'esempio in VB5 sull'uso delle due funzioni:

Questa funzione ottiene la lista dei reports presenti nel DB e carica i loro nomi in una ListBox passatagli come argomento. Esempio di utilizzo:
Flag = EnumReports("C:\MioDb.mdb",form1.list1)

Public Function EnumReports(DbName As String, TheControl As Control) As Boolean
On Error GoTo ErrHandle
Dim IntRep As Integer
GetReports = False
If Not Exists(DbName) Then
MsgBox "Errore: " + vbCrLf + _
"Il file" + DbName + vbCrLf + _
"non esiste.", vbCritical
Exit Function
End If
If Not TypeOf TheControl Is ListBox Then
MsgBox "Errore: " + vbCrLf + _
"Il controllo non e' una ListBox", vbCritical
Exit Function
Else
TheControl.Clear
End If
Screen.MousePointer = vbHourglass
Set objAccess = CreateObject("Access.Application")
With objAccess
.OpenCurrentDatabase (DbName)
Set dbs = .CurrentDb
With dbs.Containers("Reports")
For IntRep = 0 To .Documents.Count - 1
If Left(.Documents(IntRep).Name, 4) <> "~TMP" Then
TheControl.AddItem .Documents(IntRep).Name
End If
Next IntRep
End With
End With
GetReports = True
Screen.MousePointer = vbDefault
Exit Function
ErrHandle:
MsgBox "Errore #" + Str(Err.Number) + ": " + Err.Description + ".", _
vbCritical
Screen.MousePointer = vbDefault
End Function

Questa funzione crea la stampa un report presente nel DB.

Public Function PrintReport(WhichReport) As Boolean
On Error GoTo ErrHandle
'Const acPreview = 2 'Costanti definite di Access
'Const acReport = 3
Screen.MousePointer = vbHourglass
PrintReport = False
If WhichReport = "" Then
MsgBox "Internal Error: " + vbCrLf + _
"Report String not passed.", vbCritical, ProgTitle
Exit Function
End If
objAccess.DoCmd.OpenReport WhichReport ', acPreview per l'anteprima
'objAccess.DoCmd.Maximize
'objAccess.DoCmd.SelectObject acReport, WhichReport
PrintReport = True
Screen.MousePointer = vbDefault
Exit Function
ErrHandle:
MsgBox "Error #" + Str(Err.Number) + ": " + Err.Description + ".", _
vbCritical, ProgTitle
Screen.MousePointer = vbDefault
End Function

 

Proteggere un Db con una password

A volte puo' essere utile proteggere dei dati medainte l'utilizzo di password. Il Jet Engine 3.5 della Microsoft dispone di metodi appositi per proteggere i propri database con password. Per creare una nuova password o modificare la password corrente di un database, e' necessario che lo stessso venga aperto in modalita' esclusiva. Gli esempi che seguono, sono validi solo per il Jet Engine della Microsoft. ATTENZIONE: Se la password di accesso ad un database viene dimenticata o smarrita, sara' impossibile riaccedere ai dati presenti in esso.

Dichiarazioni

Dim db As Database
Dim rs As Recordset
Dim ws As Workspace
Dim CurrentPassword As String
Dim NewPasswordForDB As String
'modificare questa stringa con il proprio percorso
Const sData = "c:\documenti\database.mdb"

Creare una nuova password (database senza password)

Public Sub dbNewPSW()
'eventuali errori saranno gestiti in GestError
On Error GoTo GestError
'Apertura del DB in modalita' esclusiva non protetto da PWD
Set db = ws.OpenDatabase(sData, True, False)
'aggiornamento del DB con la password contenuta in NewPasswordForDB
db.NewPassword "", NewPasswordForDB
db.Close
Exit Sub
GestError:
MsgBox "Attenzione " & Err.Description
End Sub

Aprire un database protetto da password

Public Sub OpenDbPWD()
'eventuali errori saranno gestiti in GestError
On Error GoTo GestError
'Apertura del DB in modalita' utilizzando la PWD contenuta in CurrentPassword
Set db = ws.OpenDatabase(sData, True, False, ";pwd=" & CurrentPassword)
MsgBox "Accesso al DB consentito!"
db.Close
Exit Sub
GestError:
MsgBox "Attenzione " & Err.Description
End Sub

Modificare la password del database

Public Sub dbChangePSW()
'eventuali errori saranno gestiti in GestError
On Error GoTo GestError
'Apertura del DB in modalita' utilizzando la PWD contenuta in CurrentPassword
Set db = ws.OpenDatabase(sData, True, False, ";pwd=" & CurrentPassword)
'aggiornamento del DB con la nuova password contenuta in NewPasswordForDB
db.NewPassword CurrentPassword, NewPasswordForDB
db.Close
Exit Sub
GestError:
MsgBox "Attenzione " & Err.Description
End Sub

 

Richiamare una SQL StoredProcedure da VB

Il metodo per chiamare una procedura SQL memorizzata in un DB dipende se la procedura restituisce dei record o no. Per esempio:

Procedure che non restituiscono record possono essere eseguite con il methodo ExecuteSQL() nel seguente modo

i% = MyDb.ExecuteSQL("StoredProc")

Il codice qui sopra esegue la procedura StoreProc (per esempio una query SQL che restituisce il numero dei record nel DB), la quale restituisce il valore nella variabile i%. Il metodo ExecuteSQL e' utile nell'esecuzione delle cosiddette 'action query' ovvero query SQL che manipolano i dati presenti nelle tabelle, ad esempio:

Delete Authors where name like "fred%"

Il metodo ExecuteSQL() e' valido solo per query SQL che non restituiscono record. Uno statement SQL che utilizza "SELECT..." restituisce dei records, mentre uno statement SQL che utilizza "DELETE..." non restituisce records.

Query che restituiscono records, richiedo un Dynaset o uno SnapShot per ottenere i dati. Ecco due esempi:

Esempio utilizzando un DataControl:

Data1.Options = dbSQLPassThrough
Data1.Recordsource = "StoreProc" ' il nome della procedura memorizzata da richiamare.
Data1.Refresh

Quando si usa la costante SqlPassThrough, il motore di Microsoft Access ignora la sintassi utilizzata e passa il comando al server SQL.

Esempio utilizzando gli oggetti di accesso ai dati:

Dim Ds as Recordset
' Aprire il database voluto...
Set MyDB = DBEngine.Workspaces(0).OpenDatabase(TheDataBase)
Set Ds = MyDB.OpenRecordset("StoreProc", dbOpenDynaset, _
dbSQLPassThrough)

Se la query memorizzata richiede dei parametri, basta includere gli stessi dopo il nome della procedura da richiamare, ad esempio:

' Specifica la stringa SQL.
command.SQLx = "StoreProc parm1, parm2, parm3"

' nel caso in cui la procedura non restituisce record...
i = MyDB.ExecuteSQL(SQLx)
'...nel caso in cui la procedura restituisce record

set Ds = MyDB.OpenRecordset(SQLx, dbOpenDynaset, dbSQLPassThrough)

La variabile oggetto (Ds) contiene il primo set di risultati ottenuti dalla stored procedure (StoreProc).

Le seguenti righe mostrano alcuni usi di entrambi i metodi

Dim db as Database
Dim x as Long
Dim Ss as Recordset
Set Db = DBEngine.Workspaces(0).OpenDatabase _
("", False, False, "ODBC;dsn=yourdsn;uid=youruid;pwd=yourpwd:")
' Per le stored procedure che non restituiscono record.
x=Db.ExecuteSQL("StoredProc_Name")
' Per le stored procedure che restituiscono record.
Set Ss = Db.OpenRecordset("StoredProc_Name", dbOpenSnapshot, _
dbSQLPassThrough)