Dictionary 如何检查字典中的字段值,然后有条件地赋值?
我正在努力实现以下目标: 使用VBA在表格中循环,并使用以下三个参数为人员分配礼物: 1) 个人的优先权得分 2) 个人对接受何种礼物的偏好 3) 库存中该类型礼品的数量 理想情况下,VBA将从优先级1组的第一个记录开始,分配他们最喜欢的礼物(如果有库存),然后继续根据他们的偏好分配优先级1的个人,同时检查库存 在表对象“tbl_gift_Assignments”(tbl_gift_Assignments))中为所有优先级1的个人分配了礼物(给定了“assigned_gift”(已分配的礼物)值后,VBA将移到优先级2的个人,依此类推 现在,我在处理个人的首选礼品未列在库存表中的情况时遇到困难 在我的数据库中,我有下表(表对象称为“tbl\U礼物\U分配”): 此外,我还有一个表,告诉我库存中每个项目的库存量(表对象称为“tbl_库存”): 为了完成这项任务,我使用dictionary对象将每个礼物的库存缓存到内存字典中。每次我给唱片分配礼物时,它都会减少库存 到目前为止,我得到的VBA如下:Dictionary 如何检查字典中的字段值,然后有条件地赋值?,dictionary,ms-access,data-structures,vba,Dictionary,Ms Access,Data Structures,Vba,我正在努力实现以下目标: 使用VBA在表格中循环,并使用以下三个参数为人员分配礼物: 1) 个人的优先权得分 2) 个人对接受何种礼物的偏好 3) 库存中该类型礼品的数量 理想情况下,VBA将从优先级1组的第一个记录开始,分配他们最喜欢的礼物(如果有库存),然后继续根据他们的偏好分配优先级1的个人,同时检查库存 在表对象“tbl_gift_Assignments”(tbl_gift_Assignments))中为所有优先级1的个人分配了礼物(给定了“assigned_gift”(已分配的礼物)值
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Dim GiftInvDict As New Scripting.dictionary
Set db = CurrentDb()
Set rsInv = db.OpenRecordset("SELECT DISTINCT ItemID, Number_in_stock FROM tbl_Inventory")
While Not rsInv.EOF
GiftsInvDict.Add Cstr(rsInv!ItemID), CInt(rsInv!Number_in_stock)
Loop
rsInv.Close
strSQL = "SELECT * FROM tbl_Gift_Assignments WHERE Priority =1"
Set rs = db.OpenRecordset(strSQL)
Do Until rs.EOF
With rs
'Process for each preferred item
'Path #1_step_a: If preferred item is not in dictionary
If Not GiftsInvDict.Exists(Cstr(rs!Preference_1)) Then
' Path #1_step_b: Add it to dictionary, with value of 0
GiftsInvDict.Add Cstr(rsInv!Preference_1), 0 Then
' Path #1_step_c: Don't know how to tell it to jump
' to next preference
End If
' Path #2_step_a: If preferred item is actually in dictionary
ElseIf GiftInvDict.Exists(Cstr(rs!Preference_1)) Then
' Path #2_step_b: Check that the inventory is greater than 0
If GiftsInvDict(Cstr(rs!Preference_1)) > 0 Then
' Path #2_step_c: If inventory greater than 0, change
''Gift_Assignment' value to preference
.Edit
!Gift_Assignment = rs!Preference_1
.Update
GiftsInvDict(!Preference_1) = GiftsInvDict(!Preference_1) - 1
End If
'End of process for each preferred item
'Do the process again for 'Preference_2....Preference_N' until all preferences
'are checked
'If, after each preference has been through the process, preferred gifts cannot be assigned
'assign 'No_Gift_Available' value to 'Gift_Assignment' field
Else
.Edit
!Gift_Assignment = "No_Gift_Available"
.Update
End If
.MoveNext
End With
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
挑战
我知道个人列出了没有库存的偏好(没有列在“tbl_清单”中,如“按摩浴缸”、“雪橇”、“赛车”)。我目前的方法是让VBA检查dictionary对象中是否存在首选项,因为我不知道如何让VBA跳过dictionary对象中不存在的礼物首选项。如果没有,请将值为0的键添加到字典中。现在,VBA只是跳转到“Else”条件,在该条件下,您不会向个人分配礼物,即使他们有其他库存中的首选礼物(可能存在于dictionary对象中) 我终于在您的代码方面取得了一些进展。我不确定您是否在匆忙处理上述问题,或者剪切/粘贴问题,但我必须纠正至少5或6个编译错误 我只是简化了您的代码,以便它可以按顺序检查首选项。根据你想做什么,你需要解决好几件事。以下是我的建议:
Option Compare Database
Option Explicit
Sub Assign_Gifts()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsINV As DAO.Recordset ' ** Not Defined
Dim strSQL As String
Dim GiftsInvDict As New Scripting.Dictionary ' ** Needed 's' / inconsistent
Dim i As Integer
Dim iQTY As Integer
Dim itemArray
Set GiftsInvDict = New Scripting.Dictionary
Set db = CurrentDb()
Set rsINV = db.OpenRecordset("SELECT DISTINCT ItemID, Number_in_stock FROM tbl_Inventory")
Do While Not rsINV.EOF ' Changed to DO
GiftsInvDict.add CStr(rsINV!ItemID), CInt(rsINV!Number_in_stock)
rsINV.MoveNext ' Missing MOVENEXT
Loop ' ** Loop without Do
rsINV.Close
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "----- NAMES -----"
strSQL = "SELECT * FROM tbl_Gift_Assignments WHERE Priority =1"
Set rs = db.OpenRecordset(strSQL)
Do Until rs.EOF
With rs
Debug.Print rs!Name & vbTab & rs!Preference_1 & vbTab & rs!Preference_2 & vbTab & rs!Preference_n
' Check 1st Pref
If Not GiftsInvDict.Exists(CStr(rs!Preference_1)) Then ' Fails to find 'Racecar'!!!!
Debug.Print "1st Pref not avail: " & rs!Preference_1 & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_1)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_1)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_1
.Update
GiftsInvDict.Item(CStr(rs!Preference_1)) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
' Check 2nd Pref
If Not GiftsInvDict.Exists(CStr(rs!Preference_2)) Then
Debug.Print "2nd Pref not avail: " & rs!Preference_2 & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_2)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_2)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_2
.Update
GiftsInvDict.Item((CStr(rs!Preference_2))) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
' Try 3rd choice --- being lazy, BUT I WOULD CHANGE ALL THIS CODE TO HANDLE ANY NUMBER OF PREDERENCES!!
If Not IsNull(rs!Preference_n) Then
If Not GiftsInvDict.Exists(CStr(rs!Preference_n)) Then
Debug.Print "nth Pref not avail: " & rs!Preference_n & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_n)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_n)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_n
.Update
GiftsInvDict.Item(!Preference_n) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
Else
Debug.Print "Pref_n is NULL"
End If
.Edit
!Gift_Assignment = "No_Gift_Available"
.Update
'End of process for each preferred item
'Do the process again for 'Preference_2....Preference_N' until all preferences
'are checked
'If, after each preference has been through the process, preferred gifts cannot be assigned
'assign 'No_Gift_Available' value to 'Gift_Assignment' field
Satisfied:
.MoveNext
End With
Loop
rs.Close
Debug.Print "-----------------------------------------------------------------------"
'Add code to insert new records into Inventory if desired....
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
strSQL = "UPDATE tbl_Inventory SET tbl_Inventory.Number_in_stock = " & CInt(GiftsInvDict.Items()(i)) & " " & _
"WHERE (((tbl_Inventory.ItemID)='" & CStr(GiftsInvDict.Keys()(i)) & "'));"
db.Execute strSQL, , iRecAff
Next i
Set rs = Nothing
Set db = Nothing
End Sub
一般来说,如果您有编号的字段/列(pref_1,pref_2),您需要重新考虑您的数据库设计。如果“pref_1不可用,但pref_2可用,您应该分配它吗?@WayneG.Dunn:是的,这是正确的。@Wayne_G_Dunn:对您的方法的逐步解释非常好。我还认为最好不要更新库存盘点。另外,正如您正确猜测的,我不想向表中添加项。
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String
Dim GiftInvDict As New Scripting.dictionary
Set db = CurrentDb()
Set rsInv = db.OpenRecordset("SELECT DISTINCT ItemID, Number_in_stock FROM tbl_Inventory")
While Not rsInv.EOF
GiftsInvDict.Add Cstr(rsInv!ItemID), CInt(rsInv!Number_in_stock)
Loop
rsInv.Close
strSQL = "SELECT * FROM tbl_Gift_Assignments WHERE Priority =1"
Set rs = db.OpenRecordset(strSQL)
Do Until rs.EOF
With rs
'Process for each preferred item
'Path #1_step_a: If preferred item is not in dictionary
If Not GiftsInvDict.Exists(Cstr(rs!Preference_1)) Then
' Path #1_step_b: Add it to dictionary, with value of 0
GiftsInvDict.Add Cstr(rsInv!Preference_1), 0 Then
' Path #1_step_c: Don't know how to tell it to jump
' to next preference
End If
' Path #2_step_a: If preferred item is actually in dictionary
ElseIf GiftInvDict.Exists(Cstr(rs!Preference_1)) Then
' Path #2_step_b: Check that the inventory is greater than 0
If GiftsInvDict(Cstr(rs!Preference_1)) > 0 Then
' Path #2_step_c: If inventory greater than 0, change
''Gift_Assignment' value to preference
.Edit
!Gift_Assignment = rs!Preference_1
.Update
GiftsInvDict(!Preference_1) = GiftsInvDict(!Preference_1) - 1
End If
'End of process for each preferred item
'Do the process again for 'Preference_2....Preference_N' until all preferences
'are checked
'If, after each preference has been through the process, preferred gifts cannot be assigned
'assign 'No_Gift_Available' value to 'Gift_Assignment' field
Else
.Edit
!Gift_Assignment = "No_Gift_Available"
.Update
End If
.MoveNext
End With
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
Option Compare Database
Option Explicit
Sub Assign_Gifts()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsINV As DAO.Recordset ' ** Not Defined
Dim strSQL As String
Dim GiftsInvDict As New Scripting.Dictionary ' ** Needed 's' / inconsistent
Dim i As Integer
Dim iQTY As Integer
Dim itemArray
Set GiftsInvDict = New Scripting.Dictionary
Set db = CurrentDb()
Set rsINV = db.OpenRecordset("SELECT DISTINCT ItemID, Number_in_stock FROM tbl_Inventory")
Do While Not rsINV.EOF ' Changed to DO
GiftsInvDict.add CStr(rsINV!ItemID), CInt(rsINV!Number_in_stock)
rsINV.MoveNext ' Missing MOVENEXT
Loop ' ** Loop without Do
rsINV.Close
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "----- NAMES -----"
strSQL = "SELECT * FROM tbl_Gift_Assignments WHERE Priority =1"
Set rs = db.OpenRecordset(strSQL)
Do Until rs.EOF
With rs
Debug.Print rs!Name & vbTab & rs!Preference_1 & vbTab & rs!Preference_2 & vbTab & rs!Preference_n
' Check 1st Pref
If Not GiftsInvDict.Exists(CStr(rs!Preference_1)) Then ' Fails to find 'Racecar'!!!!
Debug.Print "1st Pref not avail: " & rs!Preference_1 & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_1)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_1)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_1
.Update
GiftsInvDict.Item(CStr(rs!Preference_1)) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
' Check 2nd Pref
If Not GiftsInvDict.Exists(CStr(rs!Preference_2)) Then
Debug.Print "2nd Pref not avail: " & rs!Preference_2 & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_2)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_2)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_2
.Update
GiftsInvDict.Item((CStr(rs!Preference_2))) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
' Try 3rd choice --- being lazy, BUT I WOULD CHANGE ALL THIS CODE TO HANDLE ANY NUMBER OF PREDERENCES!!
If Not IsNull(rs!Preference_n) Then
If Not GiftsInvDict.Exists(CStr(rs!Preference_n)) Then
Debug.Print "nth Pref not avail: " & rs!Preference_n & vbTab & " add it "
GiftsInvDict.Item(CStr(rs!Preference_n)) = 0
Debug.Print "----- INVENTORY -----"
Debug.Print "Count: " & GiftsInvDict.Count & vbTab & "C2: " & UBound(GiftsInvDict.Keys) + 1 & vbTab & "C3: " & UBound(GiftsInvDict.Items) + 1
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
Next i
Debug.Print "---------------------"
Else
iQTY = CInt(GiftsInvDict.Item(CStr(rs!Preference_n)))
If iQTY > 0 Then
.Edit
!Gift_Assignment = rs!Preference_n
.Update
GiftsInvDict.Item(!Preference_n) = CInt(iQTY - 1)
GoTo Satisfied
End If
End If
Else
Debug.Print "Pref_n is NULL"
End If
.Edit
!Gift_Assignment = "No_Gift_Available"
.Update
'End of process for each preferred item
'Do the process again for 'Preference_2....Preference_N' until all preferences
'are checked
'If, after each preference has been through the process, preferred gifts cannot be assigned
'assign 'No_Gift_Available' value to 'Gift_Assignment' field
Satisfied:
.MoveNext
End With
Loop
rs.Close
Debug.Print "-----------------------------------------------------------------------"
'Add code to insert new records into Inventory if desired....
For i = 0 To GiftsInvDict.Count - 1
Debug.Print GiftsInvDict.Keys()(i), GiftsInvDict.Items()(i)
strSQL = "UPDATE tbl_Inventory SET tbl_Inventory.Number_in_stock = " & CInt(GiftsInvDict.Items()(i)) & " " & _
"WHERE (((tbl_Inventory.ItemID)='" & CStr(GiftsInvDict.Keys()(i)) & "'));"
db.Execute strSQL, , iRecAff
Next i
Set rs = Nothing
Set db = Nothing
End Sub