用 Access 中的起始部分在物料清单中查找最终项目的方法是啥?数组?递归函数?
Posted
技术标签:
【中文标题】用 Access 中的起始部分在物料清单中查找最终项目的方法是啥?数组?递归函数?【英文标题】:What is an approach to find the end item in a Bill of Materials with starting part in Access? Arrays? Recursive Function?用 Access 中的起始部分在物料清单中查找最终项目的方法是什么?数组?递归函数? 【发布时间】:2018-02-12 17:31:37 【问题描述】:我正在寻找一种开始的方法,不一定是完整的解决方案。我的问题是如何构建一个程序,该程序采用零件编号并在材料清单中上升每个级别,检查下一个更高组件是否列在单独的表中,同时仍牢记用户输入的第一个零件编号?我已经包含了示例数据以及该程序如何在我的脑海中运行。
我相信我需要使用数组或某种递归函数。我真的不知道除了 SQL 之外找到 Next Higher Assembly 的最佳方法是什么。
我有一张表,其中包含零件编号及其 Next Higher Assembly,如下所示,其中提供了名为 tbl_PartandNHA 的各种零件编号的材料清单:
Part Number NHA
Part A Part L
Part A Part M
Part L Part S
Part M Part S
Part M Part R
Part S Part Y
Part S Part Z
Part R Part Y
Part B Part N
Part N Part Q
Part Q Part W
我还有另一个表格,其中列出了符合某些标准的零件编号。我将其命名为 tbl_PartMeetsCriteria。
零件符合标准
Part Z
Part Q
对于 W 部分,物料清单如下所示:
Part W
Part Q
Part N
Part B
程序被赋予了一个零件号,并在材料清单中向上爬,以寻找在 tbl_PartMeetsCriteria 中列出的零件号。该算法的工作原理如下:查找 Part B 的 NHA。NHA 是 Part N。检查 tbl_PartMeetCriteria 中的 Part N。它不在表中,因此请查找 NHA。它是 Part Q。检查 tbl_PartMeetsCriteria 中的 Part Q。它在桌子上。停止例程并显示一个消息框“Q 部分在表格中。 B 部分构建 Q 部分”实际上,我的程序会将匹配存储在其他地方。
现在我们要分析 A 部分。 A 部分的物料清单写在这里。
Part Y
Part S
Part L
Part A
Part M
Part A
Part R
Part M
Part A
Part Z
Part S
Part L
Part A
Part M
Part A
程序将看到 A 部分有两个 NHA(L 部分、M 部分)。程序将检查 tbl_PartMeetsCriteria 中的每一项。然后程序必须分支出来。它必须寻找 M 部分的 NHA,然后是 R 部分的 NHA。它将出现没有匹配项。然后它必须返回并检查 L 部分的 NHA,然后检查 S 部分以在 tbl_PartMeetsCriteria 中查找匹配项。 S 部分的 NHA 是 Y 部分和 Z 部分。程序将找到与 Z 部分匹配的内容并说“Z 部分在表格中。 A 部分构建 Z 部分”
我的问题是如何构建一个程序来查找材料清单的每个选项以找到匹配项?
我将其视为一系列嵌套数组,如下所示:
A部分(L部分(S部分(Y部分,Z部分)),M部分(R部分(Y部分),S部分(Y部分,Z部分)))
我了解如何使用 SQL 进行查询。我了解数组和 FOR 循环的基础知识,但我不知道这是否是正确的方法。问题是示例数据是物料清单的简化版本。有数千个连接和更多级别,具体取决于较低的部件号。该程序需要数组中的动态数组来存储选项并调查下一个更高程序集的每个可能线程,直到找到匹配项或达到***别。我怎么能这样做?有比数组更好的选择吗?
【问题讨论】:
Access (JET/Ace) SQL 不执行递归或循环。至于 VBA 解决方案,这个问题太宽泛了。有很多方法可以解决它,以及数组的替代方案,例如对象和集合。 你能指点一下对象和集合吗?喜欢一些资源或链接。那会很有帮助。 在Queries: BOM, with Joe Celko Nested Sets查看 Joe Celko 的示例 对象是面向对象编程语言中编程的核心概念。 This 是一个非常基础的 youtube 教程,涵盖了一些基础知识。但是,为了进一步理解,我可以推荐一整门面向对象编程的课程,以及 OOP 中的父母和孩子。收藏请见MSDN 查看此处了解带有记录集的 VBA 中的基本递归:***.com/a/2701099/3820271 【参考方案1】:真正关心的是您被允许编辑源数据的方式。循环引用会导致无限递归,这就是为什么任何递归设置都不允许直接输入。任何输入都必须经过验证。
这里有一些使用 VBA 的递归示例,后面是您问题的答案,您可以在其中阅读和扩展以满足您的需求。
以下代码将递归搜索下一个元素,直到找不到下一个元素。 F(x) = F(f(x))
Public Function RecursiveSingleNode(PartNumber As String, Optional NHA As String, Optional recursionDepth As Integer) As String
'Will return the last element of a first found node!
'
On Error Resume Next
If PartNumber = "" Then Exit Function
If (Nz(DLookup("nha", "tbl_PartandNHA", "partnumber='" & PartNumber & "'"), "") <> "") Then
RecursiveSingleNode = RecursiveSingleNode(Nz(DLookup("nha", "tbl_PartandNHA", "partnumber='" & PartNumber & "'"), ""))
Else
RecursiveSingleNode = PartNumber
End If
End Function
此代码与上面相同,但检查是否在您的 meetCriteria 表中找到该值。
Public Function RecursiveSingleNodeFindMeet(PartNumber As String, Optional NHA As String, Optional recursionDepth As Integer) As String
On Error Resume Next
If PartNumber = "" Then Exit Function
If (Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & PartNumber & "'"), "") <> "") Then
RecursiveSingleNodeFindMeet = Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & PartNumber & "'"), "")
Else
RecursiveSingleNodeFindMeet = RecursiveSingleNodeFindMeet(Nz(DLookup("nha", "tbl_PartandNHA", "partnumber='" & PartNumber & "'"), ""))
End If
End Function
在您的示例表中,您有多个以相同元素开头的节点。 像A,L..; A, M.. 每个节点都必须单独搜索。为此,您需要一个要搜索的所有节点的列表。使用标准sql,并结合递归方法。
理论上,你会列出所有节点
1> A-L、L-S、S-Y、 A-m,m-s,s-y,这对于 M 和 S 的每个子节点都是相同的。因此,您需要将此列表函数包含在递归函数中。 于是就变成了
-
获取下一个元素
检索下一个元素的所有节点
递归搜索每个元素并检查是否在匹配条件表中找到。
对节点中的每个下一个元素执行此操作,直到节点结束
查找以用户输入开头的所有节点:
Public Function FindNHA(PartNumber As String)
Dim SQL_GET As String
SQL_GET = "SELECT * FROM tbl_PartandNHA WHERE(partnumber like '" & PartNumber & "')"
Dim MyRs As Recordset
Set MyRs = CurrentDb.OpenRecordset(SQL_GET)
If Not (MyRs.BOF Or MyRs.EOF) Then
Dim Result As String
While Not MyRs.EOF
'Recursive method to find the part matching in partmeetcriteria table
Result = FindNHAR(Nz(MyRs("partnumber"), ""), Nz(MyRs("nha"), ""))
If (Result <> "") Then
FindNHA = Result
Exit Function
End If
MyRs.MoveNext
Wend
End If
End Function
Public Function FindNHAR(PartNumber As String, Optional NHA As String, Optional recursionDepth As Integer) As String
'Recursively search for next element and check if it's found in your PartMeetsCriteria. Return blank if not
On Error Resume Next
If PartNumber = "" Then Exit Function
If (Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & PartNumber & "'"), "") <> "") Then
' if partnumber is found in meetsCriteria table return it
FindNHAR = Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & PartNumber & "'"), "")
ElseIf (Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & NHA & "'"), "") <> "") Then
' if NHAis found in meetsCriteria table return it
FindNHAR = Nz(DLookup("partnumber", "PartMeetsCriteria", "partnumber='" & NHA & "'"), "")
Else
If Not NHA = "" Then
'For each element, check if it has multiple nodes and search each element in each node again, starting with NHA
FindNHAR = FindNHA(NHA)
Else
'Same as above since NHA is empty, use partnumber
FindNHAR = FindNHAR(Nz(DLookup("nha", "tbl_PartandNHA ", "partnumber='" & PartNumber & "'"), ""))
End If
End If
End Function
用法:在您的即时窗口中试试这个
?FindNHA("Part S") Part Z
?FindNHA("Part A") Part Z
?FindNHA("Part B") Part Q
?FindNHA("Part R") ""
?FindNHA("Part M") Part Z
?FindNHA("Part N") Part Q
您应该知道这只是一个概念证明。您可以使用它来了解 VBA 的递归功能,但在实施此功能之前您必须采取额外的安全措施。您可以使用子函数缩短几行代码。我留下更大的版本让你理解。 RecursionDepth 由你来实现。
【讨论】:
非常感谢!这将需要一些时间来研究和实施,但它非常有帮助。以上是关于用 Access 中的起始部分在物料清单中查找最终项目的方法是啥?数组?递归函数?的主要内容,如果未能解决你的问题,请参考以下文章