Collegarsi ad una attività correlata con il VBA
Impariamo come collegarsi via codice ad una attività correlata con il VBA Visual Basic for Application
Passiamo al database Entertainment e diamo un’occhiata alla maschera frmContracts, che è la “centrale operativa” di questa applicazione.
L’attività della RM Production è incentrata sugli ingaggi dei gruppi nei club, la formulazione dei contratti e il controllo del pagamento delle commissioni.
Questo tutorial esplora alcune delle attività che sono automatizzate nella maschera frmContracts.
Una delle attività fondamentali nella maschera principale frmContracts, illustrata nella figura seguente è seguire i pagamenti delle commissioni sui contratti attivi.
Quando ci si sposta da contratto a contratto in questa maschera, il pulsante Payments sarà attivato o disattivato a seconda dello stato di quel particolare contratto.
La routine evento Su Corrente dellamaschera (Form_Current) esamina il campo di stato del contratto e imposta di conseguenza la proprietà Abilitato del pulsante (figura 1).
Spostiamoci su un contratto attivo e facciamo clic sul pulsante Payments per vedere che cosa succede.
Si dovrebbe vedere la maschera frmPayments che si apre, come nella figura (figura 2).
Questa maschera, nella quale si immettono i pagamenti per il contratto in questione, si apre come maschera modale, cioè a scelta obbligatoria, cosicché l’utente deve introdurre tutti i pagamenti prima di spostarsi su un altro contratto.
Se si apre la maschera frmPayments in visualizzazione Struttura, come si vede nella figura, si scoprirà che non ha un’origine dei record figura 3).
E allora, come funziona questa maschera? Dal momento che sappiamo che questa maschera verrà sempre utilizzata per modificare i dati relativi a un preciso contratto, non c’è motivo di sostenere il carico addizionale di aprire un altro recordset nella tabella tblContracts, particolarmente considerando che non è necessario modificare i dati del contratto nella maschera Payments.
La sottomaschera è associata alla tabella tblCommissions e la sua proprietà Collega Campi Master del controllo della sottomaschera fa riferimento al controllo non associato ContractNo nella maschera principale.
Gli altri controlli nella maschera sono lì semplicemente per confermare i dati del contratto e sono bloccati (non aggiornabili).
Questa maschera viene aperta e riempita dalla routine evento Su clic per il pulsante Payment nella maschera principale frmContracts.
Il codice è il seguente:
Private Sub cmdPayment_Click()
Dim frm As Form
' Controlla se vi sono dati non salvati in questa maschera
If Me.Dirty Then
' Se è così, devono avere valori validi
' per GrouplD e ClubID
If IsNothing(Me!GroupID) Or IsNothing(Me!ClubID) Then
MsgBox "You can't save a contract without a " & _
"Group Name and Club Name.", vbCritical, "Payments"
Me!GroupName.SetFocus
Exit Sub
End If
' Salva i dati “dirty”
DoCmd.RunCommand acCmdSaveRecord
End If
' Apre la maschera correlata per i pagamenti, nascosta
DoCmd.OpenForm FormName:="frmPayments", WindowMode:=acHidden
' Imposta una variabile maschera per ragioni di efficienza
Set frm = Forms!frmPayments
' Inserisce i dati non associati sui pagamenti
' ....è il ContractNo quello che fa funzionare
' la sottomaschera
frm!ContractNo = Me!ContractNo
frm!GroupName = Me!GroupID.Column(0)
frm!ClubName = Me!ClubID.Column(0)
frm!BeginningDate = Me!BeginningDate
frm!EndingDate = Me!EndingDate
' Porta il focus sulla sottomaschera
frm!fsubPayments.SetFocus
' e rende visibile la maschera
frm.Visible = True
End Sub
Dopo aver accertato che tutti gli eventuali cambiamenti sono stati salvati, il codice apre frmPayments come maschera nascosta (cosicché non lo vedremo mentre incolla i dati del contratto), copia i dati dello schermo nella maschera e poi la rende visibile.
Si osservi che non ci sono maschere per introdurre nel database nuove righe per le commissioni.
Queste righe vengono create automaticamente da un’altra routine VBA, che viene eseguita ogni volta che si conclude un aggiornamento nella maschera frmContracts (nell’evento Dopo Aggiornamento).
Il codice è il seguente:
Private Sub Form_AfterUpdate()
Dim db As Database, rst As Recordset, qd As QueryDef
Dim varMonday As Variant, curOwed As Currency, intWeeks As Integer, intI As Integer
On Error GoTo LoadComBail
DoCmd.Hourglass True
Set db = CurrentDb()
' Se non è un contratto RMP attivo o in attesa, provvede ‘a cancellare il file Cornmissions
If IsNothing(Me!Status) Or Me!Status = "D" Or Me!Status = "SB" Or Me!CommissionAgent1 <> "RMP" Or IsNull(Me!CommissionAgent1) Then
Set qd = db.CreateQueryDef("", "Delete * From qryCommissions;")
qd![Forms!frmContracts!ContractNo] = Me!ContractNo
qd.Execute
qd.Close
DoCmd.Hourglass False
Exit Sub
End If
' Contratto RMP Active, Pending o Paid - controlla che le Commissions siano corrette
Set qd = db.QueryDefs("qryCommissions")
qd![Forms!frmContracts!ContractNo] = Me!ContractNo
Set rst = qd.OpenRecordset(dbOpenDynaset)
curOwed = CCur(CLng(Me!ContractPrice * Me![Commission1%] * 100) / 100)
varMonday = Me![BeginningDate] - WeekDay(Me![BeginningDate], 2) + 1
' Se le condizioni del contratto vanno oltre un lunedì, ricalcola il primo giorno
' della settimana da fatturare
If Me![ContractLastDay] > 7 Then varMonday = varMonday + 7
intWeeks = CInt(Me!EndingDate - varMonday + 7) \ 7
' Imposta un array che contiene tutte le settimane valide per questo contratto
ReDim varWeekBeginning(1 To intWeeks + 1) As Variant
ReDim intHit(1 To intWeeks + 1) As Integer
For intI = 1 To intWeeks
varWeekBeginning(intI) = varMonday
varMonday = varMonday + 7
Next intI
varWeekBeginning(intWeeks + 1) = #1/1/2099#
intI = 1
' Trova i record delle commissioni che corrispondono e li aggiorna
Do Until rst.EOF
Do Until varWeekBeginning(intI) >= rst!WeekBeginning
intI = intI + 1
Loop
If varWeekBeginning(intI) = rst!WeekBeginning Then
rst.Edit
rst!AmountOwed = curOwed
If Me!Status = "Pd" Then rst!AmountPaid = curOwed
intHit(intI) = True
rst.Update
Else
rst.Delete
End If
rst.MoveNext
Loop
' Ora aggiunge gli eventuali mancanti
For intI = 1 To intWeeks
If Not intHit(intI) Then
rst.AddNew
rst!ContractNo = Me!ContractNo
rst!WeekBeginning = varWeekBeginning(intI)
rst!AmountOwed = curOwed
If Me!Status = "Pd" Then rst!AmountPaid = curOwed
rst.Update
End If
Next intI
rst.Close
DoCmd.Hourglass False
Exit Sub
LoadComBail:
MsgBox "Unexpected Error. " & Err & " " & Error, 16
Exit Sub
End Sub
In breve, questa routine fa quanto segue:
1 Verifica che questo sia un contratto attivo per il quale RM Production è l’agente commissionario principale. Se il contratto non è attivo, la routine verifica che non esistano righe per questo contratto nella tabella tblCommissions e si arresta.
2 In base ai valori BeginningDate ed EndingDate del contratto, la routine costruisce un array interno che contiene la data di Lunedì in una settimana contrattuale e un altro array che contiene un flag per indicare se quella settimana esiste già nella tabella tblCommissions. La routine calcola anche l’ammontare della commissione per settimana.
3 La routine percorre tutte le righe esistenti per questo contratto, cercando le settimane corrispondenti. Se trova una settimana che non corrisponde, cancella la riga. Se trova una settimana che corrisponde, imposta il flag “found” e verifica che l’ammontare della commissione sia esatto.
4 Per ogni settimana nell’array calcolato che non trova nella tabella tblCommissions, la procedura costruisce unanuova riga.
Esempi di accesso ai dati con VBA Microsoft Access
Tutorials su Microsoft Access
Dr.Maurizio Cucchiara
autore del corso:
"Corso Base di Microsoft Access"
disponibile on line su questo sito
MC2 E-Learning S.a r.l.
Formazione per il Web
http://www.mc2.it/html/access.html
Cerca sul web con Google:
