【问题标题】:merge several bits of data from different sheets合并来自不同工作表的几位数据
【发布时间】:2020-09-21 20:07:45
【问题描述】:

我正在尝试合并来自不同工作表的几位数据。经过几个问题和尝试(在数组中,感谢 Stackoverflow 之前的帮助),我认为字典可能是最好的。最终结果是一个填充表,其中包含每个条目的所有数据。 (取决于条目,原始数据中的列中的数据可能位于不同的位置)

数据可以包含一个人的多个条目。但是每个条目的数据根据​​条目的阶段而有所不同。例如,如果条件是第 1 阶段,则第 3 列中的数据将位于最终表格的第 5 列,但是如果条件是第 2 阶段,则第 3 列中的相同数据可能是最终表格的第 10 列。

https://www.youtube.com/watch?v=o8fSY_4p93s

按照这个视频教程 ondictionaires,我想我可以通过 dtaa 找到每个单独的条目,然后为案例添加相应的变量。例如。查找 Steve Smith 的数据,如果 steve smith 存在则如果 stage 1,则将数据添加到变量 stagedate1,如果 stage2 将数据添加到 stage2date,依此类推。如果找不到,请添加条目并找到舞台。

与视频类似,他在视频中找到每个客户的相应数据,并添加销售额和销量,如果之前使用 if 函数来确定哪个数据阶段,然后将值放入正确的变量中,我也可以这样做。

我知道会有一百万种方法可以做到这一点,但这似乎简单而有效。

Sub Dictionary()

Dim dict As Dictionary

Set dict = ReadData()

Call WriteDict(dict)

End Sub

Function ReadData()

Dim dict As New Dictionary

Dim DataWs As Worksheet: Set DataWs = ThisWorkbook.Sheets("DATA")
Dim PoolOfWeekWs As Worksheet: Set PoolOfWeekWs = ThisWorkbook.Sheets("Pool of the week")

Dim LastrowData As Long: LastrowData = DataWs.range("A" & Rows.Count).End(xlUp).Row
Dim LastColData As Long: LastColData = DataWs.Cells(1 & DataWs.Columns.Count).End(xlToLeft).Column


Dim LastColDataString As String: LastColDataString = Split(Cells(1, LastColData).Address, "$")(1)

Dim DataRange As range: Set DataRange = DataWs.range("A1:" & LastColDataString & LastrowData)
Dim DataArr As Variant: DataArr = DataWs.range("A1:AO" & LastrowData)

Dim range As range: Set range = DataWs.range("A1").CurrentRegion

Dim i As Long
Dim CandidateProcessID As String, CandidateName As String, FirstName As String, ProcessStatus As String, PQLDate As Date, oCandidate As ClsCandidate

For i = 2 To range.Rows.Count
    CandidateProcessID = range.Cells(i, 10).Value
    CandidateName = range.Cells(i, 16).Value
    FirstName = range.Cells(i, 17).Value
    ProcessStatus = range.Cells(i, 9).Value
    
    If dict.Exists(CandidateProcessID) = True Then
        Set oCandidate = dict(CandidateProcessID)   'CODE ERRORS HERE AFTER A FEW ROWS (Comes across a 
    Else                                             an entry that is already in the dictionary)
        Set oCandidate = New ClsCandidate
        dict.Add CandidateProcessID, oCustomer
    End If
    
    oCandidate.CandidateName = oCandidate.CandidateName
    oCandidate.FirstName = oCandidate.FirstName
    oCandidate.ProcessStatus = oCandidate.ProcessStatus
    oCandidate.PQLDate = oCandidate.PQLDate
Next i

Set ReadData = dict


End Function

Sub WriteDict(dict As Dictionary)

    Dim key As Variant, oCandidate As ClsCandidate
    
    For Each key In dict
        Set oCandidate = dict(key)
        Debug.Print key, oCandidate.CandidateName, oCandidate.FirstName, oCandidate.ProcessStatus, oCandidate.PQLDate
    Next key

End Sub

【问题讨论】:

  • Cells(1 & DataWs.Columns.Count) 将是 BMF8,这可能不是您想要的。试试Cells(1, DataWs.Columns.Count)
  • "这里的代码错误" - 究竟是如何出错了?
  • 我相信错误是对象错误。它停止并调试。感谢您发现这一点,但我认为这不会导致错误,因为我使用的是不同的范围。根据我的解释,带有类的字典是最好的方法吗?
  • oCandidate 声明在哪里,oCustomer 是什么?是不是打错字了?

标签: arrays excel vba dictionary


【解决方案1】:

我相信错误是对象错误。它停止并调试。

那将是“需要对象”,这完全符合一个非常常见的陷阱:在每个模块的顶部添加Option Explicit,现在VBA 将不允许您运行代码直到它知道oCustomer 是什么。

Option Explicit 的丢失允许代码以未声明的oCustomer 运行:简单地说,为该本地标识符(“oCustomer”)现场创建一个新的Variant/Empty 指针,这样每次迭代“有效”只是在为那些不成功的做好准备:

    If dict.Exists(CandidateProcessID) = True Then
        Set oCandidate = dict(CandidateProcessID) '<~ Variant/Empty is retrieved here: "object required"
    Else
        Set oCandidate = New ClsCandidate
        dict.Add CandidateProcessID, oCustomer '<~ Variant/Empty is added here
    End If

从字典中成功检索到Variant/Empty:问题是该Set oCandidate 运算符左侧的Set oCandidate 指令表示操作的右侧必须是对象引用。 Variant/Empty 无法满足此要求,并引发“需要对象”运行时错误。

错误不在于检索:它与存储有关!

您可以使用静态代码分析工具轻松找到此类错误,例如Rubberduck(披露:这是我的网站)。

【讨论】:

  • 嗨@MathieuGuidon 感谢这个愚蠢的错误,不知道我是怎么错过的!问题,你认为我使用字典的想法是个好主意吗?从多个工作表和列中收集有关候选人的数据并填充主工作表。
猜你喜欢
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
相关资源
最近更新 更多