如何编写Excel VBA宏回溯表格目标字段的多来源及溯源路径
Excel VBA 字段溯源实现方案
核心思路
- 预加载所有
target到source的映射关系,同一个目标对应的多个来源统一存储 - 采用递归方式遍历所有溯源链路,自动处理多分支场景,遇到无上游来源的节点自动终止
- 内置循环引用跳过、来源/路径去重逻辑,避免运行异常和结果冗余
完整可运行代码
Sub TraceSource() Dim srcDict As Object Set srcDict = CreateObject("Scripting.Dictionary") Dim lastRow As Long, i As Long Dim wsSrc As Worksheet, wsRes As Worksheet Set wsSrc = Sheet1 ' 数据源所在工作表,可按需修改 Set wsRes = Sheet2 ' 结果输出工作表,可按需修改 wsRes.Cells.Clear ' 第一步:加载所有映射关系 lastRow = wsSrc.Cells(wsSrc.Rows.Count, "D").End(xlUp).Row For i = 2 To lastRow ' 跳过表头行 target = Trim(wsSrc.Cells(i, "D").Value) source = Trim(wsSrc.Cells(i, "C").Value) If target <> source Then ' 跳过自引用循环数据,如示例中的y2→y2 If Not srcDict.Exists(target) Then srcDict.Add target, New Collection End If srcDict(target).Add source End If Next i ' 第二步:遍历目标节点生成溯源结果 Dim resRow As Long: resRow = 1 ' 写入表头 wsRes.Cells(resRow, 1) = "目标字段" wsRes.Cells(resRow, 2) = "所有上游来源" wsRes.Cells(resRow, 3) = "完整溯源链路" resRow = resRow + 1 ' 当前默认处理type为v1的字段,可修改条件适配需求 For i = 2 To lastRow If Trim(wsSrc.Cells(i, "A").Value) = "v1" Then currTarget = Trim(wsSrc.Cells(i, "D").Value) ' 避免重复处理同一个目标 If wsRes.Cells(wsRes.Rows.Count, 1).Find(currTarget, LookIn:=xlValues, lookat:=xlWhole) Is Nothing Then Dim sources As Collection, paths As Collection Set sources = New Collection Set paths = New Collection ' 递归遍历链路 Call RecursiveTrace(currTarget, srcDict, "", sources, paths) ' 拼接来源 Dim srcStr As String For Each s In sources srcStr = srcStr & s & "、" Next wsRes.Cells(resRow, 2) = Left(srcStr, Len(srcStr) - 1) ' 拼接路径 Dim pathStr As String For Each p In paths pathStr = pathStr & p & ";" Next wsRes.Cells(resRow, 3) = Left(pathStr, Len(pathStr) - 1) wsRes.Cells(resRow, 1) = currTarget resRow = resRow + 1 End If End If Next i wsRes.Columns("A:C").AutoFit MsgBox "溯源完成,结果已保存至Sheet2" End Sub ' 递归溯源子过程 Sub RecursiveTrace(currNode As String, srcDict As Object, currPath As String, sources As Collection, paths As Collection) ' 无上游来源,当前节点为根来源 If Not srcDict.Exists(currNode) Then ' 去重存储来源 On Error Resume Next sources.Add currNode, CStr(currNode) On Error GoTo 0 ' 存储完整路径,去掉开头多余的→ paths.Add Right(currPath & "→" & currNode, Len(currPath & "→" & currNode) - 1) Exit Sub End If ' 遍历所有上游分支 For Each src In srcDict(currNode) Call RecursiveTrace(src, srcDict, currPath & "→" & currNode, sources, paths) Next End Sub
使用说明
- 按
Alt+F11打开VBA编辑器,插入新模块粘贴上述代码直接运行即可 - 运行后输出的结果完全匹配需求,单目标对应多来源的所有分支都会被完整识别和记录
内容的提问来源于stack exchange,提问作者MageshJ
相关产品推荐
相关产品推荐

