I have macro, which copies data from selected workbooks' Sheet1 to this main workbook's Sheet1 in last row. For small number of files, it is fast, but when I select more files (say 20), it breaks and excel even crashes. How to make this more efficient as I am already using Application.EnableEvents and ScreenUpdating?
Sub Copy_From_Workbooks()
Dim numberOfFilesChosen, i As Integer
Dim tempFileDialog As FileDialog
Dim sourceWorkbook As Workbook
Dim loLastRow As Long
Application.EnableEvents = False
Application.ScreenUpdating = False
Set tempFileDialog = Application.FileDialog(msoFileDialogFilePicker)
tempFileDialog.Filters.Add "Excel Files", "*.xlsx?", 1
tempFileDialog.AllowMultiSelect = True
numberOfFilesChosen = tempFileDialog.Show
For i = 1 To tempFileDialog.SelectedItems.Count
Workbooks.Open tempFileDialog.SelectedItems(i)
Set sourceWorkbook = ActiveWorkbook
If ActiveWorkbook.Worksheets(1).Range("A1") <> "" Then
With ActiveWorkbook.Worksheets(1)
With .Cells(1).CurrentRegion
.Offset(1).Resize(.Rows.Count - 1, .Columns.Count - 1).Copy
End With
End With
End If
With ThisWorkbook.Worksheets("Sheet1")
loLastRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
.Range("A" & loLastRow).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
'ThisWorkbook.Save
End With
sourceWorkbook.Close
Next i
Application.EnableEvents = False
Application.ScreenUpdating = True
End Sub
You set a variable for the source workbook, but do not use it.
Use With blocks so you don't call the referencing object over and over and over.
Write the values directly as opposed to using the slower copy/paste.
For i = 1 To tempFileDialog.SelectedItems.Count
Set sourceWorkbook = Workbooks.Open(tempFileDialog.SelectedItems(i))
With sourceWorkbook.Worksheets(1)
If .Range("A1") <> "" Then
Dim valRange as Range
With .Cells(1).CurrentRegion
Set valRange = .Offset(1).Resize(.Rows.Count - 1, .Columns.Count - 1)
End With
End With
End If
With ThisWorkbook.Worksheets("Sheet1")
loLastRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
.Range("A" & loLastRow).Resize(valRange.Rows.Count,valRange.Columns.Count).Value = valRange.Value
'ThisWorkbook.Save
End With
sourceWorkbook.Close
Next i
Related
Extracting a range of non-contiguous cells within number of excel files in a particular folder (data has to be pulled from either of 2 UNIQUE SHEETS)
I have the below code for pulling data (range of cells) that are non-contiguous and pasting them in a new sheet. However, the code needs to look for the data in either of the 2 sheets , namely - "summary1" or "extract1".
[Note- Only one of the two sheets would be available in each file]
I can successfully pull for one of them but if i add both of them using "On Error Resume Next" i get an error. Kindly guide me on how to resolve this!
Any suggestions or tips are much appreciate!!
Code:
Sub PIdataextraction()
Dim myFile As String, path As String
Dim erow As Long, col As Long
path = "C:\Users\New\"
myFile = Dir(path & "*.xl??")
Application.ScreenUpdating = False
Do While myFile <> ""
Workbooks.Open (path & myFile)
Windows(myFile).Activate
Set copyrange = Sheets("summary1").Range("B4,E7,E9,E11,E13,E15,I12,J22,C24,C25,C26,I11,R16")
On Error Resume Next
Set copyrange = Sheets("extract1").Range("B4,E7,E9,E11,E13,E15,I12,J22,C24,C25,C26,I11,R16")
Windows("MasterFile.xlsm").Activate
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
col = 1
For Each cel In copyrange
cel.Copy
Cells(erow, col).PasteSpecial xlPasteValues
col = col + 1
Next
Windows(myFile).Close savechanges:=False
myFile = Dir()
Loop
Range("A:E").EntireColumn.AutoFit
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Data has been Compiled,Please Check!"
End Sub
Here's one approach which factors out the "find one of these sheets in a workbook" logic into a separate function.
Sub PIdataextraction()
Const PTH As String = "C:\Users\New\" 'use const for fixed values
Const RNG As String = "B4,E7,E9,E11,E13,E15,I12,J22,C24,C25,C26,I11,R16"
Dim myFile As String, path As String, c As Range
Dim erow As Long, col As Long, wb As Workbook, ws As Worksheet
Application.ScreenUpdating = False
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).row
myFile = Dir(PTH & "*.xl??")
Do While myFile <> ""
Set wb = Workbooks.Open(path & myFile)
Set ws = FindFirstSheet(wb, Array("summary1", "extract1"))
If Not ws Is Nothing Then 'check we got a sheet
col = 1
For Each c In ws.Range(RNG).Cells
Sheet1.Cells(erow, col).Value = c.Value
col = col + 1
Next c
Sheet1.Cells(erow, col).Value = wb.Name '<<<<<<<<<<<<<<<<
erow = erow + 1
Else
Debug.Print "No sheet found in " & ws.Name
End If
wb.Close savechanges:=False
myFile = Dir()
Loop
Range("A:E").EntireColumn.AutoFit
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Data has been Compiled,Please Check!"
End Sub
'Given a workbook `wb`, return the first sheet found from
' an array of sheet names `SheetNames`
Function FindFirstSheet(wb As Workbook, SheetNames) As Worksheet
Dim ws As Worksheet, s
For Each s In SheetNames
On Error Resume Next
Set ws = wb.Worksheets(s)
On Error GoTo 0
If Not ws Is Nothing Then Exit For
Next s
Set FindFirstSheet = ws
End Function
The following code worked for me. As usual thank you for your valuable inputs!! much appriciated
Sub PIdataextraction()
Dim myFile As String, path As String
Dim erow As Long, col As Long
Dim shtSrc As Worksheet
Dim copyrange As Range, cel As Range
path = "C:\Users\New\"
myFile = Dir(path & "*.xl??")
Application.ScreenUpdating = False
Do While myFile <> ""
Workbooks.Open (path & myFile)
Windows(myFile).Activate
On Error Resume Next
Set shtSrc = Worksheets("summary1")
If Err = 9 Then
On Error Resume Next
Set shtSrc = Worksheets("extract1")
If Err = 9 Then Exit Sub
On Error GoTo 0
End If
Set copyrange = shtSrc.Range("B4,E7,E9,E11,E13,E15,I12,J22,C24,C25,C26,I11,R16")
Windows("MasterFile.xlsm").Activate
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
col = 1
For Each cel In copyrange
Cells(erow, col).Value = cel.Value ' Equivalent of xlPasteValues
col = col + 1
Next
Windows(myFile).Close savechanges:=False
myFile = Dir()
Loop
Range("A:E").EntireColumn.AutoFit
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Data has been Compiled,Please Check!"
End Sub
So, I have one excel workbook containing around 80 sheets, the sheets are named as Input, Input(1), input, INPUT, INPUT(2) and Output, Output(1), Output(2), output, OUTPUT and so on, you get the idea... I want to create a macro which creates two mastersheets in the Workbook named "MASTERSHEET INPUT" and "MASTERSHEET Output". The macro should copy all the data from any sheet having any variation of input in its sheet name and paste it one into the MASTERSHEET INPUT and the same goes for the sheets named output which will be pasted into MASTERSHEET OUTPUT. I'm relatively new to VBA and I'd really appreciate it if someone could help me out.
Thanks in advance!
This is the code I was using previously
Sub CombineData()
Dim I As Long
Dim xRg As Range
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet"
For I = 2 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
Next
End Sub
But this merges all the sheets in the workbook into one without checking the sheet name.
I tried using this one next but this just pastes the first Output sheet into both mastersheets and then ends:
Sub CombineData()
Dim I As Long
Dim xRg As Range
Dim xWs As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet Output"
For I = 2 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name = "OUTPUT*" Or xWs.Name = "output*" Or xWs.Name = "Output*" Then
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
End If
Next
Next
On Error Resume Next
Worksheets.Add Sheets(1)
ActiveSheet.Name = "MasterSheet Input"
For I = 3 To Sheets.Count
Set xRg = Sheets(1).UsedRange
If I > 2 Then
Set xRg = Sheets(1).Cells(xRg.Rows.Count + 1, 1)
End If
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name = "INPUT*" Or xWs.Name = "input*" Or xWs.Name = "Input*" Then
Sheets(I).Activate
ActiveSheet.UsedRange.Copy xRg
End If
Next
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Call DeleteAllSheetsExceptMaster
End Sub
I also tried using this but this does absolutely nothing:
Sub CombineData()
Dim I As Long
Dim xrg As Range
Dim counter As Long
Dim xWs1 As Worksheet
Dim xWs2 As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
For counter = 1 To 2
Worksheets.Add Sheets(1)
If counter = 1 Then
ActiveSheet.Name = "MasterSheet Input"
Set xWs1 = ActiveSheet
End If
If counter = 2 Then
ActiveSheet.Name = "MasterSheet Output"
Set xWs2 = ActiveSheet
End If
Next counter
For I = 2 To Sheets.count
Set xrg = Sheets(1).UsedRange
If I > 2 Then
Set xrg = Sheets(1).Cells(xrg.Rows.count + 1, 1)
End If
Sheets(I).Activate
If Sheets(I).Name = "OUTPUT*" Or Sheets(I).Name = "output*" Or Sheets(I).Name = "Output*" Then
ActiveSheet.UsedRange.Copy xWs2
End If
If Sheets(I).Name = "INPUT*" Or Sheets(I).Name = "input*" Or Sheets(I).Name = "Input*" Then
ActiveSheet.UsedRange.Copy xWs1
End If
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Create Master Sheets
The following will delete each of the master worksheets if they exist and then create new ones. Then it will copy the data from the current region starting in A1 of the defined source worksheets to the appropriate master worksheets (read OP's requirements).
The Code
Option Explicit
Sub createMasterSheets()
' Define constants incl. the Names Arrays and the workbook.
Const srcFirst As String = "A1"
Const tgtFirst As String = "A1"
Dim srcNames As Variant
srcNames = Array("iNpUt", "oUtPuT") ' Case does not matter.
Dim tgtNames As Variant
tgtNames = Array("MasterIn", "MasterOut")
Dim wb As Workbook
Set wb = ThisWorkbook
' Define lower and upper subscripts of the 1D arrays:
' srcNames, tgtNames, Dicts
Dim sFirst As Long
sFirst = LBound(srcNames)
Dim sLast As Long
sLast = UBound(srcNames)
' Turn off screen updating.
Application.ScreenUpdating = False
' Add Target Worksheets.
Dim ws As Worksheet
Dim n As Long
For n = sLast To sFirst Step -1
On Error Resume Next
Set ws = wb.Sheets(tgtNames(n))
On Error GoTo 0
If Not ws Is Nothing Then
Application.DisplayAlerts = False
wb.Sheets(tgtNames(n)).Delete
Application.DisplayAlerts = True
End If
wb.Worksheets.Add Before:=wb.Sheets(1)
ActiveSheet.Name = tgtNames(n)
Next n
' Define Dictionaries Array and populate it with Dictionaries.
' The Dictionaries will hold the Data Arrays.
Dim Dicts As Variant
ReDim Dicts(sFirst To sLast)
Dim dict As Object
For n = sFirst To sLast
Set dict = CreateObject("Scripting.Dictionary")
Set Dicts(n) = dict
Next n
' Declare variables.
Dim wsName As String ' Current Worksheet Name
Dim rng As Range ' Current Source Range, Current Target Cell Range
Dim m As Long ' Subscript of Current Data Array in Current Dictionary
' of Dictionaries Array
' Write values from Source Ranges to Data Arrays.
For Each ws In wb.Worksheets
wsName = ws.Name
For n = sFirst To sLast
If InStr(1, wsName, srcNames(n), vbTextCompare) = 1 Then
' Define Source Range. You might need to do this in another way.
Set rng = ws.Range(srcFirst).CurrentRegion
m = m + 1
Dicts(n)(m) = rng.Value ' This will fail later if one cell only.
Exit For
End If
Next n
Next ws
' Declare variables
Dim Key As Variant ' Current Key in Current Dictionary
' of Dictionaries Array.
' Write values from Data Arrays to Target Ranges.
For n = sFirst To sLast
Set rng = wb.Worksheets(tgtNames(n)).Range(tgtFirst)
Set ws = wb.Worksheets(tgtNames(n))
For Each Key In Dicts(n).Keys
rng.Resize(UBound(Dicts(n)(Key), 1), _
UBound(Dicts(n)(Key), 2)).Value = Dicts(n)(Key)
Set rng = rng.Offset(UBound(Dicts(n)(Key), 1))
Next Key
Next n
' Turn on screen updating.
Application.ScreenUpdating = True
' Inform user.
MsgBox "Sheets created, data transferred.", vbInformation, "Success"
End Sub
See if this works for you.
Edit: fixed case sensitivity.
Sub CopyFromWorksheets()
Dim wrk As Workbook 'Workbook object - Always good to work with object variables
Dim sht As Worksheet 'Object for handling worksheets in loop
Dim trg As Worksheet 'Input Master
Dim trg2 As Worksheet 'Output Master
Dim rng As Range 'Range object
Set wrk = ActiveWorkbook 'Working in active workbook
'Add new worksheet as the last worksheet
Set trg = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
'Rename the new worksheet
trg.Name = "Input Master"
'Add new worksheet as the last worksheet
Set trg2 = wrk.Worksheets.Add(After:=wrk.Worksheets(wrk.Worksheets.Count))
'Rename the new worksheet
trg2.Name = "Output Master"
'We can start loop
For Each sht In wrk.Worksheets
'If worksheet in loop is the last one, stop execution (it is Master worksheet)
If sht.Index = wrk.Worksheets.Count - 1 Then
Exit For
ElseIf LCase(sht.Name) Like "*" & "input" & "*" Then
Set rng = sht.Range(sht.Cells(1, 1), sht.Cells(65536, 1).End(xlUp))
'Put data into the Master worksheet
trg.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
ElseIf LCase(sht.Name) Like "*" & "output" & "*" Then
Set rng = sht.Range(sht.Cells(1, 1), sht.Cells(65536, 1).End(xlUp))
'Put data into the Master worksheet
trg2.Cells(65536, 1).End(xlUp).Offset(1).Resize(rng.Rows.Count, rng.Columns.Count).Value = rng.Value
End If
Next sht
'Fit the columns in Master worksheet
trg.Columns.AutoFit
trg.Rows(1).Delete
trg.Columns.AutoFit
trg2.Rows(1).Delete
End Sub
I have a workbook that stores quite a bit of data. I am trying to import a weekly report, paste it in a table, loop through the imported information and if a row does not match the issue key in a second table, the row needs to be copied and pasted into the second table.
Everything works until it gets to the Paste part of the code. It seems that the selection does not stay copied? I have tried several troubleshooting methods but none have worked.
Sub Get_Data_From_File()
Dim FileToOpen As Variant
Dim DAHelpPulse As Workbook
Application.ScreenUpdating = False
FileToOpen = Application.GetOpenFilename(Title:="Browse & Import Jira Pulse Check", FileFilter:="Excel Files(*.xls*),*xls*")
If FileToOpen <> False Then
Set DAHelpPulse = Application.Workbooks.Open(FileToOpen)
DAHelpPulse.Sheets(1).Range("A2", Range("M2").End(xlDown)).Copy
ThisWorkbook.Worksheets("Import").Visible = True
ThisWorkbook.Worksheets("Import").Range("A2").PasteSpecial xlPasteValues
DAHelpPulse.Close False
SearchandExtract
End If
Application.ScreenUpdating = False
End Sub
Sub SearchandExtract()
Dim datasheet As Worksheet
Dim ticketsheet As Worksheet
Dim homesheet As Worksheet
Dim issuekey As String
Dim finalrow As Integer
Dim i As Integer
Dim LastRow As Range
Dim TicketReviewTable As ListObject
Set datasheet = Sheet9
Set ticketsheet = Sheet2
Set homesheet = Sheet6
issuekey = ticketsheet.Range("B2").Value
datasheet.Select
finalrow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To finalrow
If Cells(i, 2) <> issuekey Then
Range(Cells(i, 1), Cells(1, 13)).Select
Selection.Copy
Sheet2.ListObjects("TicketReview").ListRows.Add
Set TicketReviewTable = Sheet2.ListObjects("TicketReview")
Set LastRow = TicketReviewTable.ListRows(TicketReviewTable.ListRows.Count).Range
With LastRow
LastRow.PasteSpecial xlPasteValues
End With
datasheet.Select
End If
Next i
homesheet.Select
End Sub
I don't think you really need to split this up into two subs - that just means you end up re-defining items already assigned in the first step.
Untested:
Sub Get_Data_From_File()
Dim FileToOpen As Variant, rngCopy As Range, rngPaste As Range
Dim DAHelpPulse As Workbook, tbl As ListObject, issuekey, rw As Range
FileToOpen = Application.GetOpenFilename(Title:="Browse & Import Jira Pulse Check", _
FileFilter:="Excel Files(*.xls*),*xls*")
If FileToOpen <> False Then
Application.ScreenUpdating = False
Set DAHelpPulse = Application.Workbooks.Open(FileToOpen)
With DAHelpPulse.Sheets(1)
Set rngCopy = .Range(.Range("A2"), .Range("M2").End(xlDown))
End With
With ThisWorkbook.Worksheets("Import")
.Visible = True
Set rngPaste = .Range("A2").Resize(rngCopy.Rows.Count, rngCopy.Columns.Count)
End With
rngPaste.Value = rngCopy.Value
DAHelpPulse.Close False 'no save
Set tbl = Sheet2.ListObjects("TicketReview")
issuekey = Sheet2.Range("B2").Value
For Each rw In rngPaste.Rows
If rw.Cells(2) <> issuekey Then
tbl.ListRows.Add.Range.Value = rw.Value
End If
Next rw
End If
End Sub
I'm new in Excel-VBA and I need to improve my macro performance. I have a macro that searches an excel, opens it, then goes through every sheet and copy-pastevalues for all cell with a specific color (yellow). Finally saves and closes the excel. In addition, excels sheets are locked and only those yellow cells are editable. This should be done for a list of excel that I indicate in a main template from where I call the macro. The problem is that it takes a lot of time and even gets blocked when the number of excels is more than 3.
I paste my code below and hope anyone can help. Thanks!
Sub Button1_Click()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim filePath As String
Dim rng As Range
Dim cel As Range
Dim cartera As String
Dim plantilla As String
Dim wb As Workbook
Dim ws As Worksheet
Dim obj_Cell As Range
filePath = Application.ThisWorkbook.Path
Range("B9").Select
Set rng = Application.Range(Selection, Selection.End(xlDown))
For Each cel In rng.Cells
cartera = cel.Value
plantilla = cel.Offset(0, 1).Value
If cartera = vbNullString Or plantilla = vbNullString Then
GoTo Saltar
End If
Application.StatusBar = "Ejecutando Cartera: " & cartera & ", Plantilla: " & plantilla
Set wb = Workbooks.Open(filePath & "\" & cartera & "\" & plantilla, UpdateLinks:=3)
For Each ws In wb.Worksheets
If ws.Name <> "Index" And ws.Name <> "Instructions" And ws.Name <> "Glossary" Then
Worksheets(ws.Name).Activate
For Each obj_Cell In Range("A1:DW105")
With obj_Cell
If obj_Cell.Interior.Color = RGB(255, 255, 153) Then
obj_Cell.Select
If obj_Cell.MergeCells = True Then
obj_Cell.MergeArea.Select
End If
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=True, Transpose:=False
If obj_Cell.MergeCells = True Then
If obj_Cell.MergeArea(1).Value = vbNullString Then
obj_Cell.MergeArea.Cells(1, 1).Select
Selection.ClearContents
End If
Else
If obj_Cell.Value = vbNullString Then
obj_Cell.ClearContents
End If
End If
End If
End With
Next obj_Cell
Range("A1").Select
End If
Next ws
Sheets(1).Select
wb.Close SaveChanges:=True
Saltar:
Next cel
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.StatusBar = False
End Sub
Untested- just some "start" ideas for you to use (e.g. no selections, using arrays, fix With statement, no GoTo). I don't understand the logic behind clearing vbNullstring. If it is necessary adapt the code in your way.
I would also suggest opening files with displayalerts on because of few potential problems (e.g. "serious error occur last time file was opened" would hangs your macro)
Sub Button1_Click()
With Application
.ScreenUpdating = False
.StatusBar = True
End With
' If possible change this reference
' from active sheet to sheet's name/codename/index
Dim activeWs As Worksheet
Set activeWs = ActiveSheet
Dim filePath As String
filePath = Application.ThisWorkbook.Path
Dim wb As Workbook
Dim ws As Worksheet
Dim obj_Cell As Range
' range definition
' if lastRow not working change to yours xlDown
' if possible End(xlUp) method is more reliable
Dim rng As Range
Dim lastRw As Long
With activeWs
lastRw = .Cells(.Cells.Rows.Count, "B").End(xlUp).Row
Set rng = .Range("B9:B" & lastRw)
End With
' read whole ranges at once
' instead of offset it is possible also to read
' cartera and plantilla at the same time to 2Darray
Dim cartera As Variant
cartera = Application.Transpose(rng.Value2)
Dim plantilla As Variant
plantilla = Application.Transpose(rng.Offset(, 1).Value2)
' main loop
Dim i As Long
For i = 1 To UBound(cartera)
If cartera(i) <> vbNullString Or plantilla(i) <> vbNullString Then
Application.StatusBar = "Ejecutando Cartera: " & cartera(i) & ", Plantilla: " & plantilla(i)
Set wb = Workbooks.Open(filePath & "\" & cartera(i) & "\" & plantilla(i), UpdateLinks:=3)
For Each ws In wb.Worksheets
If ws.Name <> "Index" And ws.Name <> "Instructions" And ws.Name <> "Glossary" Then
For Each obj_Cell In ws.Range("A1:DW105")
With obj_Cell
If .Interior.Color = RGB(255, 255, 153) Then
.Value2 = .Value2
' I commented this part beacuse it does not make sense for me...
' If .MergeCells Then
' If .MergeArea(1).Value = vbNullString Then _
.MergeArea.Cells(1, 1).ClearContents
' Else
' If .Value = vbNullString Then .ClearContents
' End If
End If
End With
Next obj_Cell
End If
Next ws
' I would place diplayalerts off here because of potential problems
' with opening files
' if problem occurs it can macro hangs
Application.DisplayAlerts = False
wb.Close SaveChanges:=True
Application.DisplayAlerts = True
End If
Next i
With Application
.ScreenUpdating = True
.DisplayAlerts = True
.StatusBar = False
End With
End Sub
I am copying a range from all open workbooks with the goal of pasting the copied cells into a consolidated sheet in the master (active) workbook. I need to paste the values only but get an "end of line" error message with this code
Spent pretty much all day googling my problem to no avail
Sub Consolidate()
Dim oBook As Workbook, ws As Worksheet, wb As Workbook, bk As Workbook
Dim copyFrom As Range
'Disable Screen Updating - stop screen flickering
' And Disable Events to avoid inturupted dialogs / popups
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the Consolidate_Data WorkSheet if it exists
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Sheets("Consolidate_Data").Delete
Application.DisplayAlerts = True
'Add a new WorkSheet and name as 'Consolidate_Data'
With ActiveWorkbook
Set DstSht = .Sheets.Add(After:=.Sheets(.Sheets.Count))
DstSht.Name = "Consolidate_Data"
End With
'Loop through each WorkBook in the folder and copy the data to the 'Consolidate_Data' WorkSheet in the ActiveWorkBook
Set wb = ActiveWorkbook
For Each oBook In Application.Workbooks
If Not oBook.Name = wb.Name Then
'Find the last row on the 'Consolidate_Data' sheet
DstRow = fn_LastRow(DstSht) + 1
'Determine Input data range
Set copyFrom = oBook.Worksheets(1).Range("A6:C8")
'Copy data to the 'consolidated_data' WorkSheet
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
End If
Next
IfError:
'Enable Screen Updating and Events
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
'Find the last Row of specified Sheet
Function fn_LastRow(ByVal Sht As Worksheet)
Dim lastRow As Long
lastRow = Sht.Cells.SpecialCells(xlLastCell).Row
lRow = Sht.Cells.SpecialCells(xlLastCell).Row
Do While Application.CountA(Sht.Rows(lRow)) = 0 And lRow <> 1
lRow = lRow - 1
Loop
fn_LastRow = lRow
End Function
Consolidate()
Dim oBook As Workbook, ws As Worksheet, wb As Workbook, bk As Workbook
Dim copyFrom As Range
'Disable Screen Updating - stop screen flickering
' And Disable Events to avoid inturupted dialogs / popups
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the Consolidate_Data WorkSheet if it exists
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Sheets("Consolidate_Data").Delete
Application.DisplayAlerts = True
'Add a new WorkSheet and name as 'Consolidate_Data'
With ActiveWorkbook
Set DstSht = .Sheets.Add(After:=.Sheets(.Sheets.Count))
DstSht.Name = "Consolidate_Data"
End With
'Loop through each WorkBook in the folder and copy the data to the 'Consolidate_Data' WorkSheet in the ActiveWorkBook
Set wb = ActiveWorkbook
For Each oBook In Application.Workbooks
If Not oBook.Name = wb.Name Then
'Find the last row on the 'Consolidate_Data' sheet
DstRow = fn_LastRow(DstSht) + 1
'Determine Input data range
Set copyFrom = oBook.Worksheets(1).Range("A6:C8")
'Copy data to the 'consolidated_data' WorkSheet
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
End If
Next
IfError:
'Enable Screen Updating and Events
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
'Find the last Row of specified Sheet
Function fn_LastRow(ByVal Sht As Worksheet)
Dim lastRow As Long
lastRow = Sht.Cells.SpecialCells(xlLastCell).Row
lRow = Sht.Cells.SpecialCells(xlLastCell).Row
Do While Application.CountA(Sht.Rows(lRow)) = 0 And lRow <> 1
lRow = lRow - 1
Loop
fn_LastRow = lRow
End Function
Get an error message at the PasteSpecial line. Everything works fine without the paste special but, as the copied range includes formulas, I do not get the values which is what I need.
.Copy and .PasteSpecial have to be done in 2 different lines but you concatenated the lines with _
copyFrom.Copy _
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
Change it to:
copyFrom.Copy 'no line concatenation here !
DstSht.Range("A" & DstRow).PasteSpecial xlPasteValues
For more information see the documentation:
Range.Copy method
Range.PasteSpecial method / Worksheet.PasteSpecial method