我会采用一种方法,使用用户定义的对象(类)和字典来收集和重组数据。使用易于理解的名称,以便日后维护和调试。
此外,通过使用 VBA 数组,宏的执行速度应该比对工作表的多次读取和写入要快得多
然后将数据重新编译成所需的格式。
我定义的两个类
我会检查以确保最后三列中的条目数量相同。
如您所见,如果需要,向任一类添加额外信息将相当简单。
输入两个类模块和一个常规模块
重命名 Class Modules 如 cmets 所示
请务必设置对 Microsoft Scripting Runtime 的引用,以便能够使用 Dictionary 对象。
此外,您可能需要为源/结果工作表/范围重新定义 wsSrc、wsRes 和 rRes。为方便起见,我将它们放在同一个工作表上,但没有必要。
类模块 1
Option Explicit
'Rename this to: cSite
'Assuming only a single Site Key Contact per site
Private pSite As String
Private pSiteKeyContact As String
Private pCompanyContactInfo As Dictionary
Private pCC As cCompanyContact
Public Property Get Site() As String
Site = pSite
End Property
Public Property Let Site(Value As String)
pSite = Value
End Property
Public Property Get SiteKeyContact() As String
SiteKeyContact = pSiteKeyContact
End Property
Public Property Let SiteKeyContact(Value As String)
pSiteKeyContact = Value
End Property
Public Property Get CompanyContactInfo() As Dictionary
Set CompanyContactInfo = pCompanyContactInfo
End Property
Public Function AddCompanyContactInfo(ByVal CompanyContact As String, _
ByVal RelationshipLength As String, ByVal RelationshipStrength As String)
Set pCC = New cCompanyContact
With pCC
.CompanyContact = CompanyContact
.LengthOfRelationship = RelationshipLength
.StrengthOfRelationship = RelationshipStrength
pCompanyContactInfo.Add Key:=.CompanyContact, Item:=pCC
End With
End Function
Private Sub Class_Initialize()
Set pCompanyContactInfo = New Dictionary
End Sub
类模块 2
Option Explicit
'Rename to: cCompanyContact
Private pCompanyContact As String
Private pLengthOfRelationship As String
Private pStrengthOfRelationship As String
Public Property Get CompanyContact() As String
CompanyContact = pCompanyContact
End Property
Public Property Let CompanyContact(Value As String)
pCompanyContact = Value
End Property
Public Property Get LengthOfRelationship() As String
LengthOfRelationship = pLengthOfRelationship
End Property
Public Property Let LengthOfRelationship(Value As String)
pLengthOfRelationship = Value
End Property
Public Property Get StrengthOfRelationship() As String
StrengthOfRelationship = pStrengthOfRelationship
End Property
Public Property Let StrengthOfRelationship(Value As String)
pStrengthOfRelationship = Value
End Property
常规模块
Option Explicit
'Set Reference to Microsoft Scripting Runtime
Sub SiteInfo()
Dim wsSrc As Worksheet, wsRes As Worksheet, rRes As Range
Dim vSrc As Variant, vRes As Variant
Dim cS As cSite, dS As Dictionary
Dim I As Long, J As Long
Dim V As Variant, W As Variant, X As Variant
'Set source and results worksheets and results range
Set wsSrc = Worksheets("Sheet4")
Set wsRes = Worksheets("Sheet4")
Set rRes = wsRes.Cells(1, 10)
'Get source data
With wsSrc
vSrc = .Range(.Cells(1, 1), .Cells(.Rows.Count, 5).End(xlUp))
End With
'Split and collect the data into objects
Set dS = New Dictionary
For I = 2 To UBound(vSrc, 1) 'skip first row
Set cS = New cSite
V = Split(vSrc(I, 3), ",")
W = Split(vSrc(I, 4), ",")
X = Split(vSrc(I, 5), ",")
If Not UBound(V) = UBound(W) And UBound(V) = UBound(X) Then
MsgBox "Mismatch in Company Contact / Length / Strength"
Exit Sub
End If
With cS
.Site = vSrc(I, 1)
.SiteKeyContact = vSrc(I, 2)
For J = 0 To UBound(V)
If Not dS.Exists(.Site) Then
.AddCompanyContactInfo Trim(V(J)), Trim(W(J)), Trim(X(J))
dS.Add .Site, cS
Else
dS(.Site).AddCompanyContactInfo Trim(V(J)), Trim(W(J)), Trim(X(J))
End If
Next J
End With
Next I
'Set up Results array
I = 0
For Each V In dS
I = I + dS(V).CompanyContactInfo.Count
Next V
ReDim vRes(0 To I, 1 To 5)
'Headers
For J = 1 To UBound(vRes, 2)
vRes(0, J) = vSrc(1, J)
Next J
'Populate the data
I = 0
For Each V In dS
For Each W In dS(V).CompanyContactInfo
I = I + 1
vRes(I, 1) = dS(V).Site
vRes(I, 2) = dS(V).SiteKeyContact
vRes(I, 3) = dS(V).CompanyContactInfo(W).CompanyContact
vRes(I, 4) = dS(V).CompanyContactInfo(W).LengthOfRelationship
vRes(I, 5) = dS(V).CompanyContactInfo(W).StrengthOfRelationship
Next W
Next V
'Write the results
Set rRes = rRes.Resize(UBound(vRes, 1) + 1, UBound(vRes, 2))
With rRes
.EntireColumn.Clear
.Value = vRes
With .Rows(1)
.Font.Bold = True
.HorizontalAlignment = xlCenter
End With
.EntireColumn.AutoFit
End With
End Sub