这是一个早期阶段,因此我没有要共享的代码-但我想确保从一开始就使用正确的工具。我的项目是预算优化脚本。现在,我计划使用字典来存储预算名称并遍历每个预算名称,然后将费用ID与符合这些预算条件的费用列表进行比较。我不确定我是否打算使用正确的工具。
举个例子,如果我有医疗费用,我想从我的健康储蓄帐户HSA支付该费用。但是,如果我的HSA不够用,我将使用一般资金来支付。HSA将被定义为比一般项目具有更高优先级的资金。
仍然会针对HSA检查另一笔费用,例如一瓶波旁威士忌,因为它将从最高优先级到最低优先级循环遍历每个预算,但ID不在HSA的合格列表中,因此只能为使用普通资金(或两者之间的其他专门资金)。
复杂的是,预算的数量和名称不限于特定数量。我希望能够根据需求变化定义2或200个预算。符合条件的条件将在针对费用预算针对每个预算设置的查询中定义。(所以,类似
select expenseid from tblexpenses where category in ("MEDICAL","DENTAL")
适用于HSA,但另一个可能与另一个预算重叠,例如由于保险资金过剩而设置的预算。资格查询可能是:
select expenseid from tblexpenses where category = "DENTAL" and expensedate < to_date("2018-01-01","yyyy-mm-dd");
有一个表存储所有预算及其资格查询名称。我将使用它来填充预算列表,并在循环中用于测试支出。
我目前的总体计划是:
我的问题是,对于存储构建多个列表,最优雅的方法是什么?我一直在考虑使用记录集,数组或字典直接查询表,到目前为止,看起来字典是赢家,但我不知道如何复制测试所需的查询,在SQL中,类似tblEligibility的SELECT count(1),其中WHERE预算= [BudgetID],而费用ID = [ExpenseID]。词典似乎能够对费用ID进行最后检查,但不能同时检查两者。
有什么建议吗?我在正确的轨道上吗?
编辑-tl:dr; 版:
我需要处理三个列表。一个是静态的,它是驱动循环的简单列表。第二个是具有两个数据元素的资格列表-预算ID和费用ID-我需要检查列表中是否存在组合对。最后是我需要随时修改的值。所有列表均由将存在于Access数据库中的表或查询填充。
嵌套字典可能没问题,但我会考虑构建一个更易于维护的自定义对象
。
编辑
一个更具体的场景来说明数据流和对象使用情况
(不具有所有细节和要求,这就是我处理项目的方式)
。
预算工作表-从数据库/查询填充
。
费用表-从数据库/查询填充
。
Module1 -Main Sub- pseudo-code
(不起作用,只是高层结构)
Option Explicit
Public Sub SetBudgets()
Dim wsB As Worksheet, wsE As Worksheet, budgets As clsBudget, itm As Range
Set wsB = ThisWorkbook.Worksheets("Budgets")
Set wsE = ThisWorkbook.Worksheets("Expense")
Set budgets = New clsBudget
Dim ok As Boolean, funded As Boolean, budget As clsBudget
ok = True
For Each itm In wsB.UsedRange.Rows 'Initialize Budgets
With itm
If ok Then ok = budgets.Init(.Cells(1), .Cells(2), .Cells(3), .Cells(4))
End With
Next
funded = True
Set budget = New clsBudget
If ok Then
For Each itm In wsE.UsedRange.Rows 'Commit Expenses
For Each budget In budgets
funded = budget.Commit(itm.Cells(4), itm.Cells(5))
If funded Then
itm.Cells(7) = "Funded by budget " & budget.BudgetFullName
Exit For
End If
Next
If Not funded Then itm.Cells(7) = "Unfunded"
Next
End If
End Sub
为了优化性能,将所有数据(两个工作表)都移到数组中
。
类实现- clsBudget - pseudo-code
(不工作,只是高层结构)
Option Explicit
Private Const ELIGIBILITY_LIST_DELIMITER = "||"
Private thisPriority As Long 'Managed by the class
Private totalBudgets As Long 'Managed by the class
Private priority As Long 'Validated by the class
Private funds As Double '>= 0
Private fullName As String 'Validated by the class (no special chars)
Private shortName As String 'Validated by the class - extract initials
Private categories As Dictionary 'No special chars, include other requirements...
Private Sub Class_Initialize()
SetGlobals True
End Sub
Private Sub Class_Terminate()
SetGlobals False
End Sub
Private Sub SetGlobals(Optional ByVal Init = False) 'reset all private variables
thisPriority = 0
totalBudgets = 0
fullName = vbNullString
'...
End Sub
Public Property Get BudgetFullName() 'define all accessor methods, and read-only props
BudgetFullName = fullName
End Property
Public Function Init(ByVal budgetLonglName As Byte, ByVal budgetPriority As Long, _
ByVal availableFunds As Double, ByVal eligibilityList As String) As Boolean
If Len(budgetLonglName) = 0 Then Exit Function 'Return Error Details
If budgetPriority <= currentPriority Then Exit Function 'Return Error Details
If availableFunds <= 0 Then Exit Function 'Return Error Details
If Len(eligibilityList) = 0 Then Exit Function 'Return Error Details
fullName = budgetLonglName 'Remove special chars ("!@#$%^&*()_+{}|:<>?[]\;',./""")
shortName = Split(fullName) 'For each itm extract first letter
priority = budgetPriority
funds = availableFunds
Dim eList As Variant, cat As Variant
eList = Split(eligibilityList, ELIGIBILITY_LIST_DELIMITER)
For Each cat In eList
'Remove special chars ("!@#$%^&*()_+{}|:<>?[]\;',./""")
If Len(cat) > 0 Then categories(cat) = 0
Next
If categories.Count > 0 Then 'Budget is OK
thisPriority = priority
totalBudgets = totalBudgets + 1
Init = True
Else
'Return Error Details
End If
End Function
Private Function IsAvailable(ByVal category As String, _
ByVal expense As Currency) As Boolean
If categories.Exists(category) Then IsAvailable = expense <= funds
End Function
Public Function Commit(ByVal category As String, _
ByVal expense As Currency) As Boolean
If IsAvailable(category, expense) Then
funds = funds - expense
Commit = True
End If
End Function
需要更多的逻辑来定义子类别(其他等)的资格映射,但是预算和费用之间的主要关系由类别字段驱动
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句