If data doesn't exist add to bottom of list - arrays

Basically I'm working on a excel document which copies values from this workbook into another if they match. So if they have the same ID and a "yes" then a field is updated. However in some instances it may be that the ID doesn't exist in the workbook im copying to, but if there is a "yes" I would like to add it to the next empty row.
Below is what I have so far
Dim fpath As String
Dim owb As Workbook
Dim thisone As String
Dim Siteref(1000) As String, siteref2(1000) As String, sitename(1000) As String, sitename2(1000) As String
fpath = "my file path"
Set owb = Application.Workbooks.Open(fpath) 'open location and file
Dim Master As Worksheet 'declare both
Dim Slave As Worksheet
Set Slave = owb.Worksheets("Schedule") 'sheet in workbook im copying too
Set Master = ThisWorkbook.Worksheets("Tbl_Primary") 'sheet from workbook im in
For i = 1 To 1000 '(the slave sheet) 'for first 1000 cells
For j = 1 To 1000 '(the master sheet)
If Master.Cells(j, 2).Value = "" Then
GoTo lastline
End If ' if ID cell is blank jump to last line
If Master.Cells(j, 2).Value = Slave.Cells(i, 1).Value And Master.Cells(j, 65).Value = "Yes" Then
Slave.Cells(i, 4).Value = Master.Cells(j, 18).Value 'If the ID equals that in the slave sheet and there is a yes ticked the copy address
End If
lastline:
Next
Next
MsgBox ("Data Transfer Successful")
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Tbl_Primary").Delete 'delete sheet
Application.DisplayAlerts = True
ThisWorkbook.Save
ThisWorkbook.Close 'save and close it

Give this one a try and let me know if it works. I wrote it "blind" without testing. So, I am not entirely sure it will work:
Dim bolFound As Boolean
Dim lngLastRow As Long
Dim fpath As String
Dim owb As Workbook
Dim Master As Worksheet 'declare both
Dim Slave As Worksheet
fpath = ActiveWorkbook.Path
Set owb = Application.Workbooks.Open(fpath) 'open location and file
Set Master = ThisWorkbook.Worksheets("Tbl_Primary") 'sheet from workbook im in
Set Slave = owb.Worksheets("Schedule") 'sheet in workbook im copying too
'
lngLastRow = Slave.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
For j = 1 To 1000 '(the master sheet)
bolFound = False
For i = 1 To 1000 '(the slave sheet) 'for first 1000 cells
If Trim(Master.Cells(j, 2).Value2) = vbNullString Then Exit For 'if ID cell is blank jump to last line
If Master.Cells(j, 2).Value = Slave.Cells(i, 1).Value And _
Master.Cells(j, 65).Value = "Yes" Then
Slave.Cells(i, 4).Value = Master.Cells(j, 18).Value 'If the ID equals that in the slave sheet and there is a yes ticked the copy address
bolFound = True
End If
Next
If bolFound = False And _
Master.Cells(j, 65).Value = "Yes" Then
Slave.Cells(lngLastRow, 4).Value = Master.Cells(j, 18).Value 'adding the new entry to the list
lngLastRow = lngLastRow + 1
End If
Next
MsgBox ("Data Transfer Successful")
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Tbl_Primary").Delete 'delete sheet
Application.DisplayAlerts = True
ThisWorkbook.Save
ThisWorkbook.Close 'save and close it

NOT tested.
Dim fpath As String
Dim owb As Workbook
Dim thisone As String
Dim Siteref(1000) As String, siteref2(1000) As String, sitename(1000) As String, sitename2(1000) As String
Dim lastRow As Long
fpath = "my file path"
Set owb = Application.Workbooks.Open(fpath) 'open location and file
Dim Master As Worksheet 'declare both
Dim Slave As Worksheet
Set Slave = owb.Worksheets("Schedule") 'sheet in workbook im copying to
Set Master = ThisWorkbook.Worksheets("Tbl_Primary") 'sheet from workbook im in
For i = 1 To 1000 '(the slave sheet) 'for first 1000 cells
For j = 1 To 1000 '(the master sheet)
If Master.Cells(j, 2).Value = "" Then
Exit For
End If ' if ID cell is blank jump to last line
If Master.Cells(j, 2).Value = Slave.Cells(i, 1).Value And Master.Cells(j, 65).Value = "Yes" Then
'If the ID equals that in the slave sheet and there is a yes ticked the copy address
Slave.Cells(i, 4).Value = Master.Cells(j, 18).Value
End If
If Master.Cells(j, 65).Value = "Yes" Then
lastRow = Slave.Cells(ActiveSheet.Rows.Count, "D").End(xlUp).Row
'if yes found, copy value
Slave.Cells(lastRow + 1, 4).Value = Master.Cells(j, 18).Value
End If
Next
Next
MsgBox ("Data Transfer Successful")
Application.DisplayAlerts = False
ThisWorkbook.Worksheets("Tbl_Primary").Delete 'delete sheet
Application.DisplayAlerts = True
ThisWorkbook.Save
ThisWorkbook.Close 'save and close it

Related

Pasting a new row using vba is not expanding table

I am hoping someone can help I have the below code which is pasting a new row into a new worksheet in SharePoint with a table. However when it is pasted into the next blank row the table is not changing dynamically with it. Can you please assist.
Sub Complete()
Dim tb1 As ListObject, tb2 As ListObject, tbl As ListObject
Dim Lrow As Long, dRow As Long
Dim ws As Worksheet, ws1 As Worksheet
Dim searchRange As Range, foundCell As Range
Dim mysearch As String
Dim wb As Workbook, Scwb As Workbook
Dim ScRow As Range
Application.DisplayAlerts = False
Set wb = ThisWorkbook
mysearch = Sheets("OI").Range("D4").Value
Set ws = wb.Sheets("OI")
Set tb1 = ws.ListObjects("OITs")
Set tb2 = wb.Sheets("TDets").ListObjects("OIFinal")
Lrow = tb2.ListRows.Count
With ws
.Range("A:A").EntireColumn.Hidden = False
End With
tb1.Range.AutoFilter Field:=11, Criteria1:="<>" & vbNullString
NumRows = tb1.DataBodyRange.Cells.SpecialCells(xlCellTypeVisible).Rows.Count
tb1.DataBodyRange.Cells.SpecialCells(xlCellTypeVisible).Copy
tb2.DataBodyRange(Lrow + 1, 1).PasteSpecial xlPasteValues
Application.CutCopyMode = False
tb1.DataBodyRange.Columns(4).Resize(, 7).ClearContents
tb1.Range.AutoFilter Field:=11, Criteria1:="=" & vbNullString
With ws
.Range("A:A").EntireColumn.Hidden = True
End With
With wb.Sheets("CReqs")
Set searchRange = .Range("G1", .Range("G" & .Rows.Count).End(xlUp))
End With
Set Scwb = Workbooks.Open("https://*****.sharepoint.com/sites/*****/Shared%20Documents/General/NAA/Apps.xlsx")
Set tbl = Scwb.Sheets("AppAccs").ListObjects("Pending")
dRow = tbl.Range.Rows.Count
Set foundCell = searchRange.Find(what:=mysearch, Lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not foundCell Is Nothing Then
foundCell.Offset(0, 6).Value = "Yes"
foundCell.Offset(0, -6).EntireRow.Copy Destination:=tbl.Range(dRow, "A").Offset(1) ' This is the line that pastes the code to a new wb but does not expand the table.
Scwb.Save
Scwb.Close
Else
MsgBox "We cannot find the ID " & mysearch & " to send for approval. Please check ID."
End If
Application.DisplayAlerts = True
End Sub
I have resolved the above by simply adding tbl.Resize tbl.Range.CurrentRegion to the next line after pasting across to the new SP workbook

Transpose Filtered Column As String to Cell

I have a table which looks like this:
I wrote code which gives output like this:
The goal is a results table which does the following:
Count number of times "old" status appears
Count numer of times "new" status appears
Get all the (unique) old groups in one cell
Get all the (unique) new groups in one cell
The following code worked on one computer but not on another (both Windows, 64bit):
Sub TableSummary()
Dim sht As Worksheet
Dim i As Integer
Dim tbl As ListObject
Dim new_tbl As ListObject, old_tbl As ListObject
Dim new_array As Variant, old_array As Variant
'2. Disable Screen Updating - stop screen flickering and Disable Events to avoid inturupted dialogs / popups
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Application.DisplayAlerts = False
On Error Resume Next
Application.DisplayAlerts = True
'4. Add a new summary table to summary worksheet
With ActiveWorkbook
sht.ListObjects.Add(xlSrcRange, sht.UsedRange, , xlYes).Name = "Summary"
sht.ListObjects("Summary").TableStyle = "TableStyleMedium5"
End With
i = 1
For Each sht In ActiveWorkbook.Worksheets
If sht.Name = "Summary" Then
'Define Column Headers of Summary
sht.Cells(1, 4).Resize(1, 4).Value = Array("Nbr of old", "Nbr of new", "Groups old", "Groups new")
i = i + 1
For Each tbl In sht.ListObjects
' Blue table
If tbl.TableStyle = "TableStyleMedium2" Then
sht.Range("D" & i).Value = WorksheetFunction.CountIf(tbl.Range, "old")
sht.Range("E" & i).Value = WorksheetFunction.CountIf(tbl.Range, "new")
Set new_tbl = sht.ListObjects("Summary")
Set new_tbl = sht.ListObjects("Summary").Range().AutoFilter(Field:=2, Criteria1:="old")
new_array = Application.Transpose(WorksheetFunction.Unique(sht.ListObjects("Summary").ListColumns("Group").DataBodyRange.SpecialCells(xlCellTypeVisible))) 'This doesn't work on my other machine
sht.Range("F" & i).Value = Join(new_array, ", ") 'works!
'Debug.Print Join(new_array, ", ")
sht.ListObjects("Summary").AutoFilter.ShowAllData
Set new_tbl = sht.ListObjects("Summary")
Set new_tbl = sht.ListObjects("Summary").Range().AutoFilter(Field:=2, Criteria1:="new")
new_array = Application.Transpose(WorksheetFunction.Unique(sht.ListObjects("Summary").ListColumns("Group").DataBodyRange.SpecialCells(xlCellTypeVisible))) 'This doesn't work on my other machine
sht.Range("G" & i).Value = Join(new_array, ", ") 'works!
Debug.Print Join(new_array, ", ")
sht.ListObjects("Summary").AutoFilter.ShowAllData
End If
Next
End If
Next
End Sub
Application.Transpose does not work on my second machine.
Here's a different approach using a function to create the list of unique values:
Sub TableSummary()
Const NEW_OLD_COL As Long = 2
Const GROUP_COL As String = "Group"
Const VAL_OLD As String = "old"
Const VAL_NEW As String = "new"
Dim sht As Worksheet, DstSht As Worksheet
Dim i As Integer
Dim tbl As ListObject
Dim new_tbl As ListObject, old_tbl As ListObject
Dim new_array As Variant, old_array As Variant
Set sht = ActiveSheet 'or whatever...
Set DstSht = sht
i = 2
For Each tbl In sht.ListObjects
' Blue table
If tbl.TableStyle = "TableStyleMedium2" Then
With tbl.ListColumns(NEW_OLD_COL)
DstSht.Range("G" & i).Value = WorksheetFunction.CountIf(.DataBodyRange, VAL_OLD)
DstSht.Range("H" & i).Value = WorksheetFunction.CountIf(.DataBodyRange, VAL_NEW)
End With
tbl.Range.AutoFilter Field:=NEW_OLD_COL, Criteria1:="new"
DstSht.Range("I" & i).Value = VisibleUniques(tbl, GROUP_COL)
tbl.Range.AutoFilter
tbl.Range.AutoFilter Field:=NEW_OLD_COL, Criteria1:="old"
DstSht.Range("J" & i).Value = VisibleUniques(tbl, GROUP_COL)
tbl.Range.AutoFilter
i = i + 1
End If
Next
End Sub
'Return a comma-separated list of all unique values in visible cells in
' column `ColName` of listobject `tbl`
Function VisibleUniques(tbl As ListObject, ColName As String) As String
Dim rngVis As Range, dict As Object, c As Range
On Error Resume Next 'ignore error if no visible cells
Set rngVis = tbl.ListColumns(ColName).DataBodyRange.SpecialCells(xlCellTypeVisible)
On Error GoTo 0 'stop ignoring errors
If rngVis Is Nothing Then Exit Function
Set dict = CreateObject("scripting.dictionary")
For Each c In rngVis.Cells
dict(CStr(c.Value)) = True
Next c
VisibleUniques = Join(dict.keys, ", ")
End Function

Object doesn't support property or method - array of sheets

I have a master file having different account details. I am trying to make a code that will send a copy of the workbook after deleting unnecessary account details and mail it. It is working fine for one sheet but when I am using array for multiple sheets it is giving me object doesn't support method in this line of code ".DisplayPageBreaks = False".
Here is my code:
Sub Mail_Sheets_Array()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim Sourcewb As Workbook
Dim Destwb As Workbook
Dim TempFilePath As String
Dim TempFileName As String
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim TheActiveWindow As Window
Dim TempWindow As Window
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set Sourcewb = ActiveWorkbook
'Copy the sheets to a new workbook
'We add a temporary Window to avoid the Copy problem
'if there is a List or Table in one of the sheets and
'if the sheets are grouped
With Sourcewb
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("REC_INT", "REC_EXT")).Copy
End With
'Close temporary Window
TempWindow.Close
Set Destwb = ActiveWorkbook
'Determine the Excel version and file extension/format
With Destwb
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007-2016
Select Case Sourcewb.FileFormat
Case 51: FileExtStr = ".xlsx": FileFormatNum = 51
Case 52:
If .HasVBProject Then
FileExtStr = ".xlsm": FileFormatNum = 52
Else
FileExtStr = ".xlsx": FileFormatNum = 51
End If
Case 56: FileExtStr = ".xls": FileFormatNum = 56
Case Else: FileExtStr = ".xlsb": FileFormatNum = 50
End Select
End If
End With
'Change all cells in the worksheets to values if you want
For Each sh In Destwb.Worksheets
sh.Select
With sh.UsedRange
.Cells.Copy
.Cells.PasteSpecial xlPasteValues
.Cells(1).Select
End With
Application.CutCopyMode = False
Destwb.Worksheets(1).Select
Next sh
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = "Part of " & Sourcewb.name & " " & Format(Now, "dd-mmm-yy h-mm-ss")
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim prow As Long
Dim r As Long
Dim x As Long
Dim y As Long
Dim CalcMode As Long
Dim ViewMode As Long
r = 0
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'We use the ActiveSheet but you can replace this with
With Destwb.Sheets(Array("REC_INT", "REC_EXT"))
' With ActiveSheet
'We select the sheet so we can change the window view
.Select
'If you are in Page Break Preview Or Page Layout view go
'back to normal view, we do this for speed
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
'Turn off Page Breaks, we do this for speed
.DisplayPageBreaks = False
'Set the first and last row to loop through
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
'We loop from Lastrow to Firstrow (bottom to top)
For Lrow = 9 To Lastrow Step 1
'We check the values in the A column in this example
With .Cells(Lrow, "C")
If Not IsError(.Value) Then
If Cells(Lrow, "D").Value = "Total" Then
GoTo y
End If
If .Value = Sheet1.Cells(2, 6) Then
r = r + 1
End If
If .Value <> Sheet1.Cells(2, 6) Then
If .Value = "" Then
r = 0
End If
prow = Lrow - r
If Cells(prow, "C").Value = Sheet1.Cells(2, 6) Then
r = r + 1
GoTo x
End If
.EntireRow.ClearContents
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
x:
End If
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
y:
Range(Cells(9, 3), Cells(Lrow, 3)). _
SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'xxxxxxxxxxxxxxxxxx
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = "hadi#siemens.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = "Hi there"
.Attachments.Add Destwb.FullName
'You can add other files also like this
'.Attachments.Add ("C:\test.txt")
'.Send 'or use
.Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
'Delete the file you have send
Kill TempFilePath & TempFileName & FileExtStr
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
You are trying to run a property only supported on a specified sheet, on multiple sheets at once. This is not supported, hence the error 438.
You can try to loop these sheets:
For Each ws In Destwb.Sheets
If ws.Name = "REC_INT" or ws.Name = "REC_EXT" then
Destwb.Worksheets(ws.Name).DisplayPageBreaks = False
End if
Next ws
I think you don't need to check for the sheets names, as you copy just the two of them into a new workbook.

Merging tables and arrays from multiple sheets into one consolidated table

I am very new to VBA and struggling!
I've tried searching the forums but can't find anything close enough to my situation...
I have 30+ sheets titled 001, 002 ...0nn
I want to create a new sheet title 'Actions summary'
I want this sheet to contain compiled information from each sheet with sheet name '0nn' (or i tried limiting the code to sheet names that are integers) - -
From each sheet i want to copy the information from columns A to G, And rows 9 to last row with information in.
I would also like the heading (A8:G8) at the top of the new 'actions summary' sheet.
SCREEN SHOT typical sheet 0nn format
Been going a bit mad and would really appreciate some simple help, ideally the code required with explanations for what each bit is doing so i can learn.
My Attempt below:
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function LastCol(sh As Worksheet)
On Error Resume Next
LastCol = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
End Function
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
' Delete the summary sheet if it exists.
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("Actions Summary").Delete
On Error GoTo 0
Application.DisplayAlerts = True
' Add a new summary worksheet.
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "Actions Summary"
' Loop through all worksheets and copy the data to the
' summary worksheet.
For Each sh In ActiveWorkbook.Worksheets
'If LCase(Left(sh.Name, 1)) = "0" Then
If IsNumeric(sh.Name) = True Then
Debug.Print (sh.Name)
' Find the last row with data on the summary worksheet.
Last = LastRow(DestSh)
'LastRow = Cells.SpecialCells(xlCellTypeLastCell).Row
Debug.Print (Last)
' Specify the range to place the data.
Set CopyRng = sh.Range("A9").CurrentRegion
Set CopyRng = Range(Cells(9, 1), Cells(Last, 7))
' Test to see whether there are enough rows in the summary
' worksheet to copy all the data.
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the " & _
"summary worksheet to place the data."
GoTo ExitTheSub
End If
' This statement copies values and formats from each
' worksheet.
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
' Optional: This statement will copy the sheet
' name in the H column.
' DestSh.Cells(Last + 1, "H").Resize(CopyRng.Rows.Count).Value = sh.Name
End If
Next
'ExitTheSub:
Application.Goto DestSh.Cells(1)
' AutoFit the column width in the summary sheet.
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Sub selectA1_and_insertRow()
'
' selectA1_and_insertRow Macro
Worksheets("Actions Summary").Rows("1:1").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Columns("B:B").ColumnWidth = 36.43
Rows("1:1").Select
'Range.Copy to other worksheets
Worksheets("001").Range("A8:G8").Copy Worksheets("Actions Summary").Range("A1:G1")
End Sub
Many thanks in advance.
Tom
CODE:
Here's the new code:
Sub UpDate_List_v2()
Dim wb As Workbook
Dim ws As Worksheet
Dim wsSum As Worksheet
Dim rLastCell As Range
Dim lCalc As XlCalculation
Dim bHasHeaders As Boolean
'Turn off calculation, events, and screenupdating
'This allows the code to run faster and prevents "screen flickering"
With Application
lCalc = .Calculation
.Calculation = xlCalculationManual
.EnableEvents = False
.ScreenUpdating = False
End With
Set wb = ActiveWorkbook
'Check if Actions Summary sheet exists already or not
On Error Resume Next
Set wsSum = wb.Sheets("Actions summary")
On Error GoTo 0
If wsSum Is Nothing Then
'Does not exist, create it
Set wsSum = wb.Sheets.Add(Before:=wb.Sheets(1))
wsSum.Name = "Actions summary"
bHasHeaders = False
Else
'Already exists, clear previous data
wsSum.UsedRange.Offset(1).Clear
bHasHeaders = True
End If
'Loop through all sheets in the workbook
For Each ws In wb.Sheets
'Only look for worksheets whose names are numbers (e.g. "001", "002", etc)
If IsNumeric(ws.Name) Then
'Check if the "Actions Summary" sheet already has headers
If bHasHeaders = False Then
'Does not have headers yet
With ws.Range("A8:M8")
'Check if this sheet has headers in A8:G8
If WorksheetFunction.CountBlank(.Cells) = 0 Then
'This sheet does have headers, copy them over
.Copy wsSum.Range("A1")
bHasHeaders = True
End If
End With
End If
'Find the last row of the sheet
Set rLastCell = ws.Cells.Find("*", ws.Range("A1"), SearchDirection:=xlPrevious)
If Not rLastCell Is Nothing Then
'Check if the last row is greater than the header row
If rLastCell.Row > 8 Then
'Last row is greater than the header row so there is data
'Check if the "Actions Summary" sheet has enough rows to hold the data
If wsSum.Cells(wsSum.Rows.Count, "A").End(xlUp).Row + rLastCell.Row - 8 > wsSum.Rows.Count Then
'Not enough rows, return error and exit the subroutine
MsgBox "There are not enough rows in the summary worksheet to place the data.", , "Data Overflow"
Exit Sub
Else
'Does have enough rows, copy the data - Values
ws.Range("A9:M" & rLastCell.Row).Copy
With wsSum.Cells(wsSum.Rows.Count, "A").End(xlUp).Offset(1)
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
End With
End If
End If
End If
End If
Next ws
'Sheets("Actions summary").Columns("H:L").EntireColumn.Delete 'Delete unwanted columns
'Sheets("Actions summary").Columns("H:L").Hidden = True 'Hide unwanted columns
Worksheets("Actions summary").Columns("H:j").Hidden = True
Worksheets("Actions summary").Columns("L").Hidden = True
Sheets("Actions summary").Columns("H").Style = "currency" 'Set to £
Application.CutCopyMode = False 'Remove the cut/copy border
'wsSum.Range("A1").CurrentRegion.EntireColumn.AutoFit 'Autofit columns on the "Actions Summary" sheet
'Turn calculation, events, and screenupdating back on
With Application
.Calculation = lCalc
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Something like this should work for you. I have commented the code for clarity.
Sub tgr()
Dim wb As Workbook
Dim ws As Worksheet
Dim wsSum As Worksheet
Dim rLastCell As Range
Dim lCalc As XlCalculation
Dim bHasHeaders As Boolean
'Turn off calculation, events, and screenupdating
'This allows the code to run faster and prevents "screen flickering"
With Application
lCalc = .Calculation
.Calculation = xlCalculationManual
.EnableEvents = False
.ScreenUpdating = False
End With
Set wb = ActiveWorkbook
'Check if Actions Summary sheet exists already or not
On Error Resume Next
Set wsSum = wb.Sheets("Actions summary")
On Error GoTo 0
If wsSum Is Nothing Then
'Does not exist, create it
Set wsSum = wb.Sheets.Add(Before:=wb.Sheets(1))
wsSum.Name = "Actions summary"
bHasHeaders = False
Else
'Already exists, clear previous data
wsSum.UsedRange.Offset(1).Clear
bHasHeaders = True
End If
'Loop through all sheets in the workbook
For Each ws In wb.Sheets
'Only look for worksheets whose names are numbers (e.g. "001", "002", etc)
If IsNumeric(ws.Name) Then
'Check if the "Actions Summary" sheet already has headers
If bHasHeaders = False Then
'Does not have headers yet
With ws.Range("A8:G8")
'Check if this sheet has headers in A8:G8
If WorksheetFunction.CountBlank(.Cells) = 0 Then
'This sheet does have headers, copy them over
.Copy wsSum.Range("A1")
bHasHeaders = True
End If
End With
End If
'Find the last row of the sheet
Set rLastCell = ws.Cells.Find("*", ws.Range("A1"), SearchDirection:=xlPrevious)
If Not rLastCell Is Nothing Then
'Check if the last row is greater than the header row
If rLastCell.Row > 8 Then
'Last row is greater than the header row so there is data
'Check if the "Actions Summary" sheet has enough rows to hold the data
If wsSum.Cells(wsSum.Rows.Count, "A").End(xlUp).Row + rLastCell.Row - 8 > wsSum.Rows.Count Then
'Not enough rows, return error and exit the subroutine
MsgBox "There are not enough rows in the summary worksheet to place the data.", , "Data Overflow"
Exit Sub
Else
'Does have enough rows, copy the data - Values
ws.Range("A9:G" & rLastCell.Row).Copy
With wsSum.Cells(wsSum.Rows.Count, "A").End(xlUp).Offset(1)
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
End With
End If
End If
End If
End If
Next ws
Application.CutCopyMode = False 'Remove the cut/copy border
wsSum.Range("A1").CurrentRegion.EntireColumn.AutoFit 'Autofit columns on the "Actions Summary" sheet
'Turn calculation, events, and screenupdating back on
With Application
.Calculation = lCalc
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub

Excel VBA How to open more workbook using array?

i have a job which i need to merge 4 files together. May i know what if i have more files in coming future to merge, instead keying the "open workbook"code. What kind of method should i use? and yet meet the lowest line merge criteria as well. Below is the code i have attempt so far
Sub GetFile()
Dim Book1Path As Variant, Book2Path As Variant, Book3Path As Variant, Book4Path As Variant
Dim SourceWB As Workbook, DestWB As Workbook
Dim lRow As Long
Dim ws1, ws2, ws3, ws4 As Worksheet
Dim c3ll1, c3ll2, c3113, c3114, range1, range2, range3, range4 As Range
'## Open both workbook first:
Book1Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 1")
If Book1Path = False Then Exit Sub
Set SourceWB = Workbooks.Open(Book1Path)
Book2Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 2")
If Book2Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book2Path)
Book3Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 3")
If Book3Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book3Path)
Book4Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 4")
If Book4Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book4Path)
'Copy.
With SourceWB.Sheets("Report")
lRow = .Cells(Rows.Count, 1).End(xlUp).Row
.Range("A2:F" & lRow).Copy
End With
'Active Merge Workbook
ThisWorkbook.Activate
'Paste.
Columns("A").Find("", Cells(Rows.Count, "A")).Select
Selection.PasteSpecial
'Active CWPI Topic 1 Assessment Workbook
SourceWB.Activate
'Copy.
With SourceWB.Sheets("Report")
lRow = .Cells(Rows.Count, 1).End(xlUp).Row
.Range("G2:G" & lRow).Copy
End With
'Active Merge Workbook
ThisWorkbook.Activate
'Paste.
Columns("G").Find("", Cells(Rows.Count, "G")).Select
Selection.PasteSpecial
Set ws1 = SourceWB.Sheets("Report")
Set ws2 = DestWB.Sheets("Report")
Set ws3 = DestWB.Sheets("Report")
Set ws4 = DestWB.Sheets("Report")
lastrow2 = ws2.Cells(Rows.Count, 1).End(xlUp).Row
Set range2 = ws2.Range("A2:A" & lastrow2)
lastrow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
Set range1 = ws1.Range("A2:A" & lastrow1)
For Each c3ll2 In range2
a = 0
activerow2 = c3ll2.Row
For Each c3ll1 In range1
If c3ll1.Value = c3ll2.Value Then
activerow1 = c3ll1.Row
Cells(activerow1, "H") = ws2.Cells(activerow2, 3)
Cells(activerow1, "I") = ws2.Cells(activerow2, 4)
Cells(activerow1, "J") = ws2.Cells(activerow2, 5)
Cells(activerow1, "K") = ws2.Cells(activerow2, 6)
Cells(activerow1, "L") = ws2.Cells(activerow2, 7)
a = 1 'Username is found
Exit For
End If
Next c3ll1
If a = 0 Then 'If Username is not found print at end
lastrow1 = lastrow1 + 1
Cells(lastrow1, "A") = ws2.Cells(activerow2, 1)
Cells(lastrow1, "B") = ws2.Cells(activerow2, 2)
Cells(lastrow1, "H") = ws2.Cells(activerow2, 3)
Cells(lastrow1, "I") = ws2.Cells(activerow2, 4)
Cells(lastrow1, "J") = ws2.Cells(activerow2, 5)
Cells(lastrow1, "K") = ws2.Cells(activerow2, 6)
Cells(lastrow1, "L") = ws2.Cells(activerow2, 7)
End If
Next c3ll2
'Columns Width Autofit
ActiveSheet.Columns.AutoFit
With Application
Cells(.CountA(Columns("A:A")) + 1, 1).Select
.ScreenUpdating = True
.DisplayAlerts = False
SourceWB.Close
DestWB.Close
End With
End Sub
So...you're looking for a loop to open up more workbooks in an easy way? Right now, you are not opening 3 versions of DestWB like you think you are. You are instead overwriting DestWB each time you call...
Set DestWB = Workbooks.Open(BookXPath)
I would replace your three blocks that open the path, check the path, and then open the path to the workbook DestWB with the following:
'Create an array of paths, and a corresponding array of workbooks
Dim paths() As String, wbs() as Workbook
ReDim paths(3)
'ReDim wbs to the same as path so its easier to adjust in the future
ReDim wbs(UBound(paths))
'Set your paths, then loop through them to assign your workbooks
Dim x as Integer
For x = 1 To UBound(paths)
paths(x) = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter " + CStr(x))
If paths(x) = "False" Then
Exit Sub
End If
Set wbs(x) = Workbooks.Open(paths(x))
Next x
You can use the same loop methodology to do the other tasks in this macro. You can also eliminate all your activating of the ThisWorkbook by setting it as a variable.
Dim thisWB as Workbook
Set thisWB = ThisWorkbook
This will in turn let you clean up this code...
Columns("A").Find("", Cells(Rows.Count, "A")).Select
Selection.PasteSpecial
Into this code...
thisWB.Sheets("SOMESHEET").Columns("A").Find("", Cells(Rows.Count, "A")).PasteSpecial
In general .Select and Selection should be avoided. Search around stackoverflow and Google, there are plenty of examples for both loops and eliminating .Select and Selection.

Resources