我的数据分布在 90 个客户的 90 个 Excel 文件中。每个文件大约有 50 张。每张表都包含来自特定团队的客户数据。每个工作表可以有多行具有相同的客户 ID。第 1 行有标题,后面的行有客户数据。
注意
我写了一段代码 -
我的代码可以工作,但需要花费大量时间来编译每个客户文件。如果有人能帮助我快速完成,将会有很大的帮助。
PS。该代码还有一个进度条。
Sub CustomerCompile()
Dim wbcompile As Workbook
Dim wbCust As Workbook
Dim strfile As Variant
Dim w As Integer
Dim wb_count As Integer
'delete current tabs
Set wbcompile = ActiveWorkbook
Dim ws As Worksheet
Application.DisplayAlerts = False
For Each ws In ThisWorkbook.Worksheets
If (ws.Name <> "Dashboard" And ws.Name <> "Customer Dataset") Then ws.Delete
Next
Application.DisplayAlerts = True
'delete dashboard table for tabs
With wbcompile.Sheets("Dashboard").ListObjects("CustomerDetails")
If Not .DataBodyRange Is Nothing Then
.DataBodyRange.Delete
End If
End With
'wbcompile.Sheets("Dashboard").Range("CustomerDetails").Select
'ActiveCell.Offset(1, 0).Select
'Range(Selection, Selection.End(xlToRight)).Select
'Range(Selection, Selection.End(xlDown)).Select
' Selection.ClearContents
'Open dialog box to select customer files
strfile = Application.GetOpenFilename(FileFilter:="Excel files (*.xlsx*),*.xlsx*", Title:="Choose customer profiles to pull", MultiSelect:=True)
'Compile customer profile data in single tab
UserForm1.Show
Dim t As Integer
t = 0
For w = LBound(strfile) To UBound(strfile)
Workbooks.Open strfile(w)
Set wbCust = ActiveWorkbook
Dim ws_Count As Integer
Dim I As Integer
Dim ShtNm As String
Dim ReqID As String
Sheets.Add
ActiveSheet.Move Before:=ActiveWorkbook.Sheets(1)
ActiveSheet.Name = "Compile"
'Set WS_Count equal to the number of worksheets in the active workbook.
ws_Count = ActiveWorkbook.Worksheets.Count
'Begin the loop.
For I = 2 To ws_Count
Worksheets(I).Select
ShtNm = ActiveSheet.Name
'Debug.Print ShtNm
Rows("1:1").Select
Selection.Insert Shift:=xlDown
Range("A2").Select
Selection.End(xlToRight).Select
Selection.End(xlUp).Select
ActiveCell.Value = ShtNm
ActiveCell.Copy
Range(Selection, Selection.End(xlToLeft)).Select
ActiveSheet.Paste
Selection.End(xlToLeft).Select
Selection.End(xlUp).Select
'Range(Selection, Selection.End(xlToRight)).Select
'Range(Selection, Selection.End(xlDown)).Select
ActiveSheet.UsedRange.Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Compile").Select
Range("XFD1").Select
Selection.End(xlToLeft).Select
ActiveCell.Offset(0, 1).Select
ActiveSheet.Paste
Worksheets(I).Select
Rows("1:1").Select
Selection.Delete Shift:=xlUp
'MsgBox ActiveWorkbook.Worksheets(I).Name
t = t + 1
Debug.Print "Customer: " & w & "/" & UBound(strfile) & "; Overall Completed: " & Format(t / (UBound(strfile) * ws_Count) * 100, "#.0")
UserForm1.Label2.Width = UserForm1.Label1.Width * t / (UBound(strfile) * ws_Count)
UserForm1.Label3.Caption = Format(t / (UBound(strfile) * ws_Count) * 100, "#.0") & "% completed."
Next I
ReqID = ActiveWorkbook.Sheets("BASIC DATA").Range("a2").Value
Sheets("Compile").Select
Columns("A:A").Select
Selection.Delete Shift:=xlLeft
Dim wscust As Worksheet
Set wscust = ActiveWorkbook.Sheets("Compile")
wscust.Copy After:=wbcompile.Sheets(wbcompile.Sheets.Count)
ActiveSheet.Name = ReqID
wbCust.Close SaveChanges:=False
'MsgBox ActiveWorkbook.Worksheets(ReqID).Name & " Imported"
'Adding header key
Rows("1:1").Select
Selection.Insert Shift:=xlDown
Range("A2").Select
Selection.End(xlToRight).Select
Selection.End(xlUp).Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=R[1]C&""_""&R[2]C"
Selection.End(xlUp).Select
Selection.Copy
Range(Selection, Selection.End(xlToLeft)).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.End(xlToLeft).Select
Dim Row_Count As Integer
Row_Count = Cells.CurrentRegion.Rows.Count
ActiveSheet.Range("A4").Copy
ActiveSheet.Range("A5:A" & Row_Count).Select
ActiveSheet.Paste
'MsgBox Row_Count
'Adding #Profile_Section and #Header
Dim Section_count As Integer
Dim Header_count As Integer
Dim Profile_Section As Range
Set Profile_Section = Worksheets(ReqID).Range("2:2")
Header_count = Worksheets(ReqID).Range("3:3").Cells.SpecialCells(xlCellTypeConstants).Count
wbcompile.Activate
ActiveWorkbook.Sheets("Dashboard").Range("Cust_num").Offset(w, 0).Value = w
ActiveWorkbook.Sheets("Dashboard").Range("Tab_name").Offset(w, 0).Value = ReqID
ActiveWorkbook.Sheets("Dashboard").Range("Profile_Sections").Offset(w, 0).Value = Unique(Profile_Section) - 1
ActiveWorkbook.Sheets("Dashboard").Range("Headers").Offset(w, 0).Value = Header_count
Next w
UserForm1.Label2.Width = UserForm1.Label1.Width
UserForm1.Label3.Caption = "100.0% completed."
'Unload UserForm1
Beep
Worksheets("Dashboard").Activate
ActiveWorkbook.Save
End Sub
Function Unique(Profile_Section As Range) As Integer
Dim rng As Range
Dim List As Object
Set List = CreateObject("Scripting.dictionary")
For Each rng In Profile_Section
If Not List.exists(rng.Value) Then List.Add rng.Value, Nothing
Next
Unique = List.Count
End Function
一些改进建议(已编译但未测试):
Option Explicit
Sub CustomerCompile()
Dim wbCompile As Workbook, ws As Worksheet, wsCompile As Worksheet
Dim wbCust As Workbook, cDest As Range
Dim strfile As Variant, rngCopy As Range, loDash As ListObject
Dim w As Long, lastCol As Long
Dim frm As UserForm1
Dim ws_Count As Long, I As Long
Dim ShtNm As String, ReqID As String
'speed up...
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'delete current tabs
Set wbCompile = ActiveWorkbook
Application.DisplayAlerts = False
For Each ws In wbCompile.Worksheets
If (ws.Name <> "Dashboard" And ws.Name <> "Customer Dataset") Then ws.Delete
Next
Application.DisplayAlerts = True
'delete dashboard table for tabs
Set loDash = wbCompile.sheets("Dashboard").ListObjects("CustomerDetails")
If Not loDash.DataBodyRange Is Nothing Then loDash.DataBodyRange.Delete
'Open dialog box to select customer files
strfile = Application.GetOpenFilename(FileFilter:="Excel files (*.xlsx*),*.xlsx*", _
Title:="Choose customer profiles to pull", MultiSelect:=True)
'Compile customer profile data in single tab
Set frm = New UserForm1 'don't use the default form instance....
frm.Show
Dim t As Integer
t = 0
For w = LBound(strfile) To UBound(strfile)
Set wbCust = Workbooks.Open(strfile(w), ReadOnly:=True)
'insert a new sheet in this workbook and name it
Set wsCompile = wbCompile.Worksheets.Add( _
after:=wbCompile.Worksheets(wbCompile.Worksheets.Count))
ReqID = wbCust.sheets("BASIC DATA").Range("a2").Value
wsCompile.Name = ReqID
Set cDest = wsCompile.Range("A1") 'start adding here on the new sheet...
'Begin the loop.
For I = 2 To wbCust.Worksheets.Count
Set ws = wbCust.Worksheets(I) 'reference the source sheet
ShtNm = ws.Name
Set rngCopy = ws.UsedRange 'data on `ws` to copy
cDest.Resize(1, rngCopy.Columns.Count).Value = ShtNm 'add the sheet name
cDest.Offset(1).Resize(rngCopy.Rows.Count, _
rngCopy.Columns.Count).Value = rngCopy.Value 'directly copy the data
Set cDest = cDest.Offset(0, rngCopy.Columns.Count) 'next paste position
t = t + 1
Debug.Print "Customer: " & w & "/" & UBound(strfile) & _
"; Overall Completed: " & Format(t / (UBound(strfile) * ws_Count) * 100, "#.0")
frm.Label2.Width = frm.Label1.Width * t / (UBound(strfile) * ws_Count)
frm.Label3.Caption = Format(t / (UBound(strfile) * ws_Count) * 100, "#.0") & "% completed."
Next I
wbCust.Close SaveChanges:=False
'Adding header key by combining rows 2 and 3
wsCompile.Rows(1).Insert Shift:=xlDown
lastCol = wsCompile.Cells(2, wsCompile.Columns.Count).End(xlToLeft).Column
With wsCompile.Range("A1", wsCompile.Cells(1, lastCol))
.Formula = "=A2 & ""_"" & A3"
.Value = .Value 'convert formulas to values
End With
'fill down the value from A4
wsCompile.Range("A5:A" & wsCompile.UsedRange.Rows.Count).Value = wsCompile.Range("A4").Value
'Add info to a new row in the listobject on Dashboard
With loDash.ListRows.Add.Range
.Cells(1).Value = w
.Cells(2).Value = ReqID
.Cells(3).Value = Unique(wsCompile.Rows(2)) - 1
.Cells(4).Value = wsCompile.Rows(3).Cells.SpecialCells(xlCellTypeConstants).Count
End With
Next w
frm.Label2.Width = frm.Label1.Width
frm.Label3.Caption = "100.0% completed."
'Unload UserForm1
Beep
wbCompile.Activate
wbCompile.Worksheets("Dashboard").Select
wbCompile.Save
Application.Calculation = xlCalculationAutomatic 'reset calcs
End Sub
'count unique values inrange `rng`
Function Unique(rng As Range) As Long 'prefer Long over Integer
Dim arr, r As Long, c As Long, List As Object, v
Set List = CreateObject("Scripting.dictionary")
arr = rng.Value 'read to array (faster)
For r = 1 To UBound(arr, 1) 'loop over rows and colummns
For c = 1 To UBound(arr, 2)
v = arr(r, c)
If Len(v) > 0 Then
If Not List.Exists(v) Then List.Add v, Nothing
End If
Next c
Next r
Unique = List.Count
End Function