So I have designed this code to insert new entries into my master Database Log but when I run the code it is much too slow.
Private Sub CommandButton2_Click()
Dim ws As Worksheet
Dim LR As Long, i As Long, iRow As Long
Set ws = ThisWorkbook.Worksheets("Data Entry")
With ws
LR = .Cells(Rows.Count, 1).End(xlUp).Row
If 2 > LR Then Exit Sub
iRow = 3
For i = 1 To LR
If .Cells(i, 1).DisplayFormat.Interior.Color = RGB(217, 230, 251) Then
Worksheets("Call Log").Rows("3:3").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
.Cells(i, 1).Resize(1, 7).Copy ThisWorkbook.Worksheets("Call Log").Cells(iRow, "A")
End If
Next i
End With
Set ws = Nothing
End Sub
As you can see, my code goes through the range, determines if it matches my criteria (in this case the color of the cell) and then Inserts a row in the destination Worksheet and copies the data into that newly created row over and over until it finishes. I've thought of maybe having it select all of the necessary cells, copy and then insert them all at once into the destination worksheet, but I'm not sure how to go about that.
Any help is greatly appreciated!
One of the things you are doing obsoletely, is copying something to the clipboard, while this is not necessary: instead of
Range("<somewhere>").Copy
Range("<elsewhere>").Paste
You might simply do:
Range("<elsewhere>".Value = Range("<somewhere>").Value
It's always a good idea to turn off screen updating and set calculations to manual (unless you need it)
Application.SceenUpdating = false
Application.calculations = xlmanual
Then set them back to true and xlautomatic at the end of the code.
Not sure if the syntaxes is correct, I'm typing from my phone
If you absolutely need to copy the source formatting of the cells also, then you could use a filter and then copy only the visible cells, all in one go. Something like this:
Private Sub CommandButton2_Click()
Const shtDataName As String = "Data Entry"
Const shtLogName As String = "Call Log"
Dim shtData As Worksheet
Dim shtLog As Worksheet
'
'Make sure required resources are available
Set shtData = GetWorksheet(shtDataName, ThisWorkbook)
If shtData Is Nothing Then
MsgBox "Missing sheet <" & shtDataName & ">!", vbInformation, "Cancelled"
Exit Sub
End If
Set shtLog = GetWorksheet(shtLogName, ThisWorkbook)
If shtLog Is Nothing Then
MsgBox "Missing sheet <" & shtLogName & ">!", vbInformation, "Cancelled"
Exit Sub
End If
'
'Check last row
Dim lastRow As Long
'
lastRow = shtData.Cells(Rows.Count, 1).End(xlUp).Row
If lastRow = 1 Then Exit Sub
'
Dim filterColor As Long
'
'Filter Range
filterColor = RGB(217, 230, 251)
With Range(shtData.Cells(1, 1), shtData.Cells(lastRow, 1))
.AutoFilter Field:=1, Criteria1:=filterColor, Operator:=xlFilterCellColor
End With
'
Dim rng As Range
Const lastCol As Long = 7
Dim firstRow As Long
'
'Get filtered range
'First row remains visible regardless of filter. Check it
If shtData.Cells(1, 1).Cells(1, 1).DisplayFormat.Interior.Color <> filterColor Then
firstRow = 2
Else
firstRow = 1
End If
On Error Resume Next
Set rng = Range(shtData.Cells(firstRow, 1), shtData.Cells(lastRow, lastCol)).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rng Is Nothing Then Exit Sub 'Nothing meets criteria
'
Dim tempArea As Range
Dim rCount As Long
'
'Get required rows count
For Each tempArea In rng.Areas
rCount = rCount + tempArea.Rows.Count
Next tempArea
'
'Insert rows
Const iRow As Long = 3
'
shtLog.Rows(iRow & ":" & iRow + rCount - 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
rng.Copy shtLog.Cells(iRow, 1)
'
'Remove filter
rng.AutoFilter
End Sub
But, if you don't care about source formatting then you could use something like this:
Private Sub CommandButton2_Click()
Const shtDataName As String = "Data Entry"
Const shtLogName As String = "Call Log"
Dim shtData As Worksheet
Dim shtLog As Worksheet
'
'Make sure required resources are available
Set shtData = GetWorksheet(shtDataName, ThisWorkbook)
If shtData Is Nothing Then
MsgBox "Missing sheet <" & shtDataName & ">!", vbInformation, "Cancelled"
Exit Sub
End If
Set shtLog = GetWorksheet(shtLogName, ThisWorkbook)
If shtLog Is Nothing Then
MsgBox "Missing sheet <" & shtLogName & ">!", vbInformation, "Cancelled"
Exit Sub
End If
'
'Check last row
Dim lastRow As Long
'
lastRow = shtData.Cells(Rows.Count, 1).End(xlUp).Row
If lastRow = 1 Then Exit Sub
'
'Read data in array (super fast)
Dim rng As Range
Dim arrData() As Variant
Const lastCol As Long = 7
'
Set rng = Range(shtData.Cells(1, 1), shtData.Cells(lastRow, lastCol))
arrData = rng.Value2
'
'Store relevant row numbers
Dim collRows As New Collection
Dim i As Long
Dim filterColor As Long: filterColor = RGB(217, 230, 251)
'
For i = LBound(arrData) To UBound(arrData)
If rng.Cells(i, 1).DisplayFormat.Interior.Color = filterColor Then
collRows.Add i
End If
'
'I am not a fan of using colors for filtering. It's much faster to have a separate
' column (indicator column) that can be used for that. This way we could do
' something like: If arrData(i, indCol) = expectedValue Then ...
' which is much faster than accesing cells
Next i
'
'Prepare data for writing
Dim arrFiltered() As Variant
ReDim arrFiltered(1 To collRows.Count, 1 To lastCol)
Dim r As Variant
Dim c As Long
'
i = 0
For Each r In collRows
i = i + 1
For c = 1 To lastCol
arrFiltered(i, c) = arrData(r, c)
Next c
Next r
'
'Insert rows
Const iRow As Long = 3
'
shtLog.Rows(iRow & ":" & iRow + collRows.Count - 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
'
'Write
With Range(shtLog.Cells(iRow, 1), shtLog.Cells(iRow + collRows.Count - 1, lastCol))
.Value2 = arrFiltered
End With
End Sub
Private Function GetWorksheet(ByVal sheetName As String, ByVal book As Workbook) As Worksheet
On Error Resume Next
Set GetWorksheet = book.Worksheets(sheetName)
On Error GoTo 0
End Function
The above is rushed code but proves some ways of doing the task. Other things that need to be considered are:
Are the worksheets protected? if yes, filtering and inserting rows can be an issue
Inserting rows will fail if the rows are intersecting multiple dynamic tables (listobjects)
Code needs to be changed if data doesn't start on row 1 in the source
and probably others that don't come to mind right now
Related
I have the below code which looks at the current open sheet, looks for column Team Manager and filters text. The headers are on the 3rd row and the column Team Manager might change to TM hence me using wild card.
For some reason, it is not working. Am i missing something?
Here is my code
Option Explicit
Sub FindMatt()
Dim ws As Worksheet
Dim LastRow As Long, col As Long
Const login = "matroux"
Const header = "T*M*"
Set ws = ActiveSheet
col = Application.WorksheetFunction.Match(header, ws.Range("3:3"), 0)
LastRow = ws.Cells(Rows.Count, col).End(xlUp).Row
With ws.Range(ws.Cells(3, col), ws.Cells(LastRow, col))
.AutoFilter 1, login
End With
End Sub
AutoFilter Data
I'm not sure why your code didn't work (but works now; my guess would be you had another filter active) but the following illustrates what could go wrong. Also, you need to make sure the correct worksheet is active when using ActiveSheet.
Sub FindMatt()
Const Login As String = "matroux"
Const Header As String = "T*M*"
Const HeaderRow As Long = 3
Dim ws As Worksheet: Set ws = ActiveSheet
If ws.FilterMode Then ws.ShowAllData
Dim Col As Variant ' it could be an error value hence 'As Variant'
Col = Application.Match(Header, ws.Rows(HeaderRow), 0)
If IsError(Col) Then ' this doesn't work with 'WorksheetFunction.Match'
MsgBox "Header not found.", vbCritical
Exit Sub
End If
Dim LastRow As Long: LastRow = ws.Cells(ws.Rows.Count, Col).End(xlUp).Row
If LastRow <= HeaderRow Then
MsgBox "No data in column range.", vbCritical
Exit Sub
End If
With ws.Range(ws.Cells(HeaderRow, Col), ws.Cells(LastRow, Col))
.AutoFilter 1, Login
End With
End Sub
I need to find certain names on a worksheet, copy the entire row once it finds said name and paste it on another worksheet.
I wrote code that finds one of the names, then copies the row and pastes it to another sheet.
Sub Macro2()
Dim StatusCol As Range
Dim Status As Range
Dim PasteCell As Range
Set StatusCol = Sheet10.Range("A1:AV1569")
For Each Status In StatusCol
If Sheet11.Range("A2") = "" Then
Set PasteCell = Sheet11.Range("A2")
Else
Set PasteCell = Sheet11.Range("A1").End(xlDown).Offset(1, 0)
End If
If Status = "Jane Thompson" Then Status.Offset(0, -4).Resize(1, 5).Copy PasteCell
Next Status
End Sub
Instead of finding only one string, the "Jane Thompson" name, I want to loop through a list of names, find each, copy the entire row where they are located and paste the row into another sheet. I have all the names on another worksheet (about 80 different names)
I managed to find code that gives me the desired output:
Sub FruitBasket()
Dim rngCell As Range
Dim lngLstRow As Long
Dim strFruit() As String
Dim intFruitMax As Integer
intFruitMax = 3
ReDim strFruit(1 To intFruitMax)
strFruit(1) = "Fruit 2"
strFruit(2) = "Fruit 5"
strFruit(3) = "Fruit 18"
lngLstRow = ActiveSheet.UsedRange.Rows.Count
For Each rngCell In Range("A2:A" & lngLstRow)
For i = 1 To intFruitMax
If strFruit(i) = rngCell.Value Then
rngCell.EntireRow.Copy
Sheets("Inventory").Select
Range("A65536").End(xlUp).Offset(1, 0).Select
Selection.PasteSpecial xlPasteValues
Sheets("Fruit").Select
End If
Next i
Next
End Sub
But instead of 3 items in the array, I had to hard code 81 names. Is there any way to pull the items of an array from another sheet?
With the names in an array you can use Match rather than looping through them.
Option Explicit
Sub FruitBasket()
Dim ws As Worksheet, wsInv As Worksheet
Dim rngCell As Range, v As Variant, arNames
Dim lngLastRow As Long, lngInvRow As Long
With Sheets("Names")
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
arNames = .Range("A2:A" & lngLastRow)
End With
Set wsInv = Sheets("Inventory")
With wsInv
lngInvRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Application.ScreenUpdating = False
Set ws = ActiveSheet
With ws
lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For Each rngCell In .Range("A2:A" & lngLastRow)
' check if value is in array
v = Application.Match(rngCell, arNames, 0)
If IsError(v) Then
' no match
Else
' match
rngCell.EntireRow.Copy
lngInvRow = lngInvRow + 1
wsInv.Cells(lngInvRow, "A").PasteSpecial xlPasteValues
End If
Next
End With
Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Done"
End Sub
I have a spreadsheet with 20+ worksheets listing servers. I am trying to format each sheet to pull only the first four columns of data, while preserving the original data. I am inserting 6 columns on the left, creating column headings, copying the first four rows of data (with starting name of "SERV-"), then putting the name of the worksheet in the 5th column. I got the code to work fine if ran in one sheet. I am trying to put it in a loop, but it isn't working. It is inserting the columns and headers in the first worksheet only.
Once I have this loop working, I want to create a summary tab where it pulls the data from these first five rows of each sheet into the summary tab. This should be easy, but I haven't gotten to that point in the code yet.
This is the code I have so far:
'PhaseOne of test code
Sub PhaseOne()
Dim ws As Worksheet
Dim lngRow As Long
Dim lngCount As Long
lngRow = 8
For Each ws In Worksheets
'(2) Remove blank rows (WORKS)
Dim x As Long
With ws
For x = .Cells.SpecialCells(xlCellTypeLastCell).Row To 1 Step -1
If WorksheetFunction.CountA(.Rows(x)) = 0 Then
ws.Rows(x).Delete
End If
Next
End With
'(3) Insert 5 columns (WORKS)
Columns("A:F").Insert Shift:=xlToRight
'(4) Label columns (WORKS)
Range("$A$1").Value = "ServLabel"
Range("$B$1").Value = "Primary IP"
Range("$C$1").Value = "DC"
Range("$D$1").Value = "Service ID"
Range("$E$1").Value = "Sheet"
'(5) Find and Copy Range (WORKS)
Dim lastRow As Long
With ws
lastRow = .Cells(.Rows.Count, "J").End(xlUp).Row
End With
Dim rFound As Range
On Error Resume Next
Set rFound = Cells.Find(What:="SERV-", _
After:=Cells(Rows.Count, Columns.Count), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
On Error GoTo 0
If rFound Is Nothing Then
Else
rFound.Select
Selection.Resize(lastRow, numcolumns + 4).Select
Selection.Copy
Range("A2").Select
ws.Paste
End If
'(8) Enter active sheet name in Column E (WORKS)
If ws.Range("A2") = "" Then
Else
Dim lastRow2 As Long
With ws
lastRow2 = .Cells(.Rows.Count, "d").End(xlUp).Row
End With
Range("E2").Select
Selection.Resize(lastRow2 - 1).Select
Selection = ws.Name
End If
Next ws
End Sub
Unless you have some other reason it's probably easier to just scan the sheets and copy the data to the summary.
Option Explicit
Sub summary()
Const SUM_SHEET = "Summary" ' name of smmary sheet
Const PREFIX = "SERV-*"
Dim wb As Workbook, ws As Worksheet, wsSum As Worksheet
Dim iRow As Long, iSumRow As Long
Dim iStartrow As Long, iLastRow As Long, rng As Range, cell As Range
Set wb = ActiveWorkbook
Set wsSum = wb.Sheets(SUM_SHEET)
wsSum.Range("A1:E1") = Array("ServLabel", "Primary IP", "DC", "Service ID", "Sheet")
iSumRow = 1
For Each ws In wb.Sheets
If ws.Name <> SUM_SHEET Then
' find column SERV-
On Error Resume Next
Set rng = ws.Cells.Find(PREFIX)
On Error GoTo 0
' set scan start/end row
If rng Is Nothing Then
MsgBox "Can't find " & PREFIX & " on " & ws.Name, vbCritical
GoTo SkipSheet
Else
iLastRow = ws.Cells(Rows.Count, rng.Column).End(xlUp).Row
iStartrow = rng.Row + 1
End If
Debug.Print ws.Name, "Col=", rng.Column, "iStartRow=", iStartrow, "iLastRow=", iLastRow
' scan the sheet and write to summary
For iRow = iStartrow To iLastRow
Set cell = ws.Cells(iRow, rng.Column)
' skip blank line
If Len(cell) > 0 Then
iSumRow = iSumRow + 1
cell.Resize(1, 4).Copy wsSum.Cells(iSumRow, 1)
wsSum.Cells(iSumRow, 5) = ws.Name
End If
Next
End If
SkipSheet:
Next
MsgBox iSumRow - 1 & " rows copied to " & wsSum.Name, vbInformation
End Sub
I'm trying to compare sheet1 "A" column values to sheet2 "E:E" column values and copy/paste the whole line of every match to sheet3. Please help me to complete this task. I'm very new to VBA.
Thank you very much in advance!
Sub DelDups_TwoLists()
Dim iListCount As Integer
Dim iCtr As Integer
' Turn off screen updating to speed up macro.
Application.ScreenUpdating = False
' Get count of records to search through (list that will be deleted).
iListCount = Sheets("sheet1").Cells(Rows.Count, "A").End(xlUp).Row
' Loop through the "master" list.
For Each x In Sheets("Sheet2").Range("E:E" & Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row)
' Loop through all records in the second list.
For iCtr = iListCount To 1 Step -1
' Do comparison of next record.
' To specify a different column, change 1 to the column number.
If x.Value = Sheets("Sheet1").Cells(iCtr, 1).Value Then
' If match is true then delete row.
Sheets("Sheet1").Cells(iCtr, 1).EntireRow.Copy
Sheets("Sheet3").Select.Paste
End If
Next iCtr
Next
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
Sub DelDupsTwoLists()
Dim lastRowWs1 As Long, lastRowWs2 As Long
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
Set ws1 = Worksheets(1)
Set ws2 = Worksheets(2)
Set ws3 = Worksheets(3)
lastRowWs1 = LastRow(ws1.Name, 1)
lastRowWs2 = LastRow(ws2.Name, 5) 'E = 5
Dim myCell1 As Range, myCell2 As Range
Dim ws1Range As Range, ws2Range As Range
Set ws1Range = ws1.Range(ws1.Cells(1, "A"), ws1.Cells(lastRowWs1, 1))
Set ws2Range = ws2.Range(ws2.Cells(1, "E"), ws2.Cells(lastRowWs2, 1))
Dim rangeToDelete As Range
For Each myCell1 In ws1Range
For Each myCell2 In ws2Range
If myCell1.Value = myCell2.Value Then
Dim lastRowWs3: lastRowWs3 = LastRow(ws3.Name, 1) + 1
myCell2.EntireRow.Copy Destination:=ws3.Cells(lastRowWs3, 1)
If Not rangeToDelete Is Nothing Then
Set rangeToDelete = Union(rangeToDelete, myCell2.EntireRow)
Else
Set rangeToDelete = myCell2.EntireRow
End If
End If
Next
Next
If Not rangeToDelete Is Nothing Then
Debug.Print "Deleting rangeToDelete - "; rangeToDelete.Address
rangeToDelete.Delete
End If
Debug.Print "Done!"
End Sub
Public Function LastRow(wsName As String, Optional columnToCheck As Long = 1) As Long
Dim ws As Worksheet
Set ws = Worksheets(wsName)
LastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row
End Function
Pretty much I rewrote the whole code from scratch. It pretty much uses the initial n2 complexity, but is rather faster than that, because the deletion of the rows in WorkSheet(2) is done in a single last step rangeToDelete.Delete, which saves a lot of time.
Pretty much, the code defines 2 ranges with which is works - ws1Range and ws2Range, using the LastRow function. Once it defines them, it starts looping through them and comparing them. Hence the n2 complexity. In case of equal values, the row is copied and the cell is added to the rangeToDelete.
Note - it will probably not work as "out of the box solution", but try to debug further with F8 and see what happens.
Additionally:
Using Integer is not a great idea in VBA.
"_" in the Sub name is used for Events in VBA, thus it is not a great idea to use it. (although it works)
How to avoid using Select in Excel VBA
Give this a try (see comments in code for more details):
Sub DelDups_TwoLists()
' Turn off screen updating to speed up macro.
Application.ScreenUpdating = False
With ActiveWorkbook
Dim wsSrc As Worksheet: Set wsSrc = .Sheets("Sheet1") 'declare and set the source worksheet
Dim wsDst As Worksheet: Set wsDst = .Sheets("Sheet3") 'declare and set the destination worksheet
Dim R1 As Long, R2 As Long, C As Long, lRow As Long, lCol As Long 'declare variables to use
With wsSrc
lCol = .Cells(1, Columns.Count).End(xlToLeft).Column 'get the last column value in the source sheet, at row 1, will reuse this laster
Dim arrData_1 As Variant: arrData_1 = .Range(.Cells(1, 1), .Cells(.Cells(Rows.Count, 1).End(xlUp).Row, 1)) 'declare and allocate the source data to an array
End With
With .Sheets("Sheet2")
Dim arrData_2 As Variant: arrData_2 = .Range("E1:E" & .Cells(Rows.Count, 1).End(xlUp).Row) 'declare and allocate the compare data to an array
End With
End With
With wsDst
For R1 = LBound(arrData_1) To UBound(arrData_1) 'for each row in the source data
For R2 = LBound(arrData_2) To UBound(arrData_2) 'for each row in the compare data
If arrData_1(R1, 2) = arrData_2(R2, 1) Then 'if there is a match
lRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1 'get the last row in the destination sheet
.Range(.Cells(lRow, 1), .Cells(lRow, lCol)).Value = _
wsSrc.Range(wsSrc.Cells(R1, 1), wsSrc.Cells(R1, lCol)).Value 'allocate the matching values
Exit For 'exit early here if there is a match, go to next row to check
End If
Next R2
Next R1
End With
Application.ScreenUpdating = True
MsgBox "Done!"
End Sub
I need summ column values from multiple workbooks and worksheets in single worksheet. If i'm trying do it like this:
While targetCell.Row <> LastRow
targetCell.Value = targetCell.Value + sourseCell.Value
Set sourseCell = sourseSheet.Cells(sourseCell.Row + 1, sourseCell.Column)
Set targetCell = targetSheet.Cells(targetCell.Row + 1, targetCell.Column)
Wend
It takes too much time(Hours!!!).
Like this:
targetSheet.Range("D14:BJ" & LastRow).Value = targetSheet.Range("D14:BJ" & LastRow).Value + sourseSheet.Range("D14:BJ" & LastRow).Value
I'm sometimes have error type mismatch
Full code:
For Each foldername In subFolders
If foldername <> ThisWorkbook.path Then
filePath = foldername & fileName
Dim app As New Excel.Application
app.Visible = False
Dim book As Excel.Workbook
Set book = app.Workbooks.Add(filePath)
For Each targetSheet In ActiveWorkbook.Worksheets
Dim sourseSheet As Worksheet
Set sourseSheet = book.Worksheets(targetSheet.Name)
Call CopyColumn(targetSheet, sourseSheet, LastRow)
Next
book.Close SaveChanges:=False
app.Quit
Set app = Nothing
End If
Next
Sub CopyColumn(targetSheet, sourseSheet As Worksheet, LastRow As Integer)
Dim sourseCell, targetCell As Range
Set targetCell = targetSheet.Cells(14,"D")
Set sourseCell = sourseCell.Cells(14,"CH")
While targetCell.Row <> LastRow
targetCell.Value = targetCell.Value + sourseCell.Value
Set sourseCell = sourseSheet.Cells(sourseCell.Row + 1, sourseCell.Column)
Set targetCell = targetSheet.Cells(targetCell.Row + 1, targetCell.Column)
Wend
End Sub
Copying the ranges to Variant arrays is quite fast. Your subroutine amended and commented below:
Sub CopyColumn(targetSheet As Worksheet, sourseSheet As Worksheet, LastRow As Long)
' LastRow as Integer will give an error for rows > 32,767, use Long instead
' Check the syntax: sourseCell, targetCell as Range means:
' sourceCell as Variant, targetCell as Range. We should include
' "as Range" after each variable declaration if we want it to be a Range
Dim sourseCell As Range, targetCell As Range
Dim lCount As Long
Dim vTarget, vSource
' I kept the names targetCell, sourseSheet, but turned them to ranges
' You might want to change sourseSheet to sourceSheet
With targetSheet
Set targetCell = .Range(.Cells(14, "D"), .Cells(LastRow, "D"))
End With
' I assume you mean sourceSheet instead of sourceCell,
' in your original code?
With sourseSheet
Set sourseCell = .Range(.Cells(14, "CH"), .Cells(LastRow, "CH"))
End With
vTarget = targetCell.Value2
vSource = sourseCell.Value2
' If there is a change you do not have numeric values
' this needs error trapping
For lCount = LBound(vTarget, 1) To UBound(vTarget, 1)
vTarget(lCount, 1) = vTarget(lCount, 1) + vSource(lCount, 1)
Next lCount
targetCell.Value = vTarget
End Sub
Testing:
Option Explicit
Private Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub test_copy_column()
Dim targetSheet As Worksheet, sourseSheet As Worksheet, LastRow As Long, _
tick As Long
' Maybe change sourseSheet to sourceSheet :)
tick = GetTickCount ' Clock count
Set targetSheet = Sheet1
Set sourseSheet = Sheet1
LastRow = 50000 ' I inputted random numbers for testing
CopyColumn targetSheet, sourseSheet, LastRow
MsgBox "Time to copy: " & GetTickCount - tick & " milliseconds"
End Sub
Result:
Relevant SO question here
I hope that helps!
for fast non-VBA solution, open all workbooks and insert following formula into a helper sheet:
=first_cell_from_source_workbook + first_cell_from_target_workbook + ...
copy the formula to cover whole range you need to cover.
copy & paste-special-as-values to target range if you wish to replace the original values in target range..
each time you wish to recalculate, make sure all source workbooks are open.