I have more than 200 workbooks in an Folder, and i deletes the empty rows by giving an Range in the code that is Set rng = sht.Range("C3:C50000").
If Column C any cell is empty then delete entire Row. Day by day data is enhancing and below code took nearly half hour to complete the processing. That time limit is also increasing with the data.
I am looking for a way to to do this in couple of minutes or in less time. I hope to get some help.
Sub Doit()
Dim xFd As FileDialog
Dim xFdItem As String
Dim xFileName As String
Dim wbk As Workbook
Dim sht As Worksheet
Application.ScreenUpdating = FALSE
Application.DisplayAlerts = FALSE
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
Else
Beep
Exit Sub
End If
xFileName = Dir(xFdItem & "*.xlsx")
Do While xFileName <> ""
Set wbk = Workbooks.Open(xFdItem & xFileName)
For Each sht In wbk.Sheets
Dim rng As Range
Dim i As Long
Set rng = sht.Range("C3:C5000")
With rng
'Loop through all cells of the range
'Loop backwards, hence the "Step -1"
For i = .Rows.Count To 1 Step -1
If .Item(i) = "" Then
'Since cell Is empty, delete the whole row
.Item(i).EntireRow.Delete
End If
Next i
End With
Next sht
wbk.Close SaveChanges:=True
xFileName = Dir
Loop
Application.ScreenUpdating = TRUE
Application.DisplayAlerts = TRUE
End Sub
This is how I would implement my suggestions of
collecting the rows to delete into a single range and deleting after the loop.
opening the workbooks in a hidden window so the user is not disturbed by files opening and closing. (And also a minor speed boost when opening files)
Dynamically defining your search range to fit the data of each file, eliminating wasted time searching blank ranges.
Sub Doit()
Dim xFd As FileDialog
Dim xFdItem As String
Dim xFileName As String
Dim wbk As Workbook
Dim sht As Worksheet
Dim xlApp As Object
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
Else
Beep
Exit Sub
End If
xFileName = Dir(xFdItem & "*.xlsx")
Set xlApp = CreateObject("Excel.Application." & CLng(Application.Version))
Do While xFileName <> ""
Set wbk = xlApp.Workbooks.Open(xFdItem & xFileName)
For Each sht In wbk.Sheets
Dim rng As Range
Dim rngToDelete As Range
Dim i As Long
Dim LastRow as Long
LastRow = sht.Cells.Find("*", SearchDirection:=xlPrevious).Row
Set rng = sht.Range("C3:C" & LastRow)
With rng
'Loop through all cells of the range
'Loop backwards, hence the "Step -1"
For i = .Rows.Count To 1 Step -1
If .Item(i) = "" Then
'Since cell Is empty, delete the whole row
If rngToDelete Is Nothing Then
Set rngToDelete = .Item(i)
Else
Set rngToDelte = Union(rngToDelete, .Item(i))
End If
End If
Next i
End With
If Not rngToDelete Is Nothing Then rngToDelete.EntireRow.Delete
Next sht
wbk.Close SaveChanges:=True
xFileName = Dir
Loop
xlApp.Quit
Set xlApp = Nothing
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
I use CreateObject to create a new excel app, and I use Application.Version so the new excel app is the same as the current one. I have had bad experience using New Excel.Application to create the object because it sometimes gets redirected to an excel 365 demo, or some other version of excel that is installed on the computer but not intended for use.
Try this for quicker row deletion:
Sub Doit()
Dim xFd As FileDialog
Dim xFdItem As String
Dim xFileName As String
Dim wbk As Workbook
Dim sht As Worksheet
Application.ScreenUpdating = FALSE
Application.DisplayAlerts = FALSE
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
Else
Beep
Exit Sub
End If
xFileName = Dir(xFdItem & "*.xlsx")
Do While xFileName <> ""
Set wbk = Workbooks.Open(xFdItem & xFileName)
For Each sht In wbk.WorkSheets 'Sheets includes chart sheets...
On Error Resume Next 'in case of no blanks
sht.Range("C3:C5000").specialcells(xlcelltypeblanks).entirerow.delete
On Error Goto 0
Next sht
wbk.Close SaveChanges:=True
xFileName = Dir()
Loop
Application.ScreenUpdating = TRUE
Application.DisplayAlerts = TRUE
End Sub
Note though your biggest time sink may still be opening and saving/closing all the files.
Reference Filtered Column
The Function
Option Explicit
Function RefFilteredColumn( _
ByVal ColumnRange As Range, _
ByVal Criteria As String) _
As Range
Const ProcName As String = "RefFilteredColumn"
On Error GoTo ClearError
Dim ws As Worksheet: Set ws = ColumnRange.Worksheet
If ws.AutoFilterMode Then
ws.AutoFilterMode = False
End If
Dim crg As Range: Set crg = ColumnRange.Columns(1)
Dim cdrg As Range: Set cdrg = crg.Resize(crg.Rows.Count - 1).Offset(1)
crg.AutoFilter 1, Criteria, xlFilterValues
On Error Resume Next
Set RefFilteredColumn = cdrg.SpecialCells(xlCellTypeVisible)
On Error GoTo ClearError
ws.AutoFilterMode = False
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "': Unexpected Error!" & vbLf _
& " " & "Run-time error '" & Err.Number & "':" & vbLf _
& " " & Err.Description
Resume ProcExit
End Function
Use in Your Code
For Each sht In wbk.Worksheets
' The header row ('C2', not 'C3') is needed when using 'AutoFilter'.
Dim rng As Range: Set rng = sht.Range("C2:C5000")
Dim frg As Range: Set frg = RefFilteredColumn(rng, "")
If Not frg Is Nothing Then
frg.EntireRow.Delete
Set frg = Nothing
' Else ' no blanks
End If
Next sht
Related
With the help of others, I was able to build this working code. I do however need help in adding conditions to it.
Before the worksheets are moved to a new file it must first check if a file of the same name already exist. If one does exist, then it should just update it (paste new data at the bottom). If none exist, then it should create one (which is what this code is doing)
Sub ExportSheets()
' Export segregated sheets to individual workbooks
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim sPath As String, sAddress As String, wsCur As Worksheet
Dim arrNoMoveSh, mtchSh
Dim sht As String
Dim x As Range
Dim rng As Range
Dim last As Long
Dim ControllerTab As Worksheet
Dim ControllerTabBase As Range
Set ControllerTab = ThisWorkbook.Worksheets("Controller")
Set ControllerTabBase = ControllerTab.Range("B1")
' --Creates an array of the sheet names to not be moved
arrNoMoveSh = Split("Read Me,Validations,Controller,MTI Data,Other", ",")
' --Store path of this workbook
sPath = ThisWorkbook.path & Application.PathSeparator
' --Loop through worksheets
For Each wsCur In ThisWorkbook.Worksheets
mtchSh = Application.Match(wsCur.Name, arrNoMoveSh, 0)
If IsError(mtchSh) Then 'no sheet names found in the array
wsCur.Copy 'create a new workbook for the sheet to be copied!!!
' --Specifies the sheet name in which the data is stored
sht = wsCur.Name
last = Sheets(sht).Cells(Rows.Count, "A").End(xlUp).Row
Set rng = Sheets(sht).Range("A1:P" & last)
Sheets(sht).Range("N1:N" & last).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("BB1"), Unique:=True
For Each x In Range([BB2], Cells(Rows.Count, "BB").End(xlUp))
With rng
.AutoFilter Field:=14, Criteria1:=x.Value
.SpecialCells(xlCellTypeVisible).Copy
Sheets.Add(After:=Sheets(Sheets.Count)).Name = x.Value
ActiveSheet.Paste
End With
Next x
Sheets(sht).Activate
Sheets(sht).Delete
ActiveWorkbook.SaveAs sPath & wsCur.Name & ".xlsx"
ActiveWorkbook.Close SaveChanges:=True
End If
Next wsCur
Application.ScreenUpdating = True
Application.DisplayAlerts = True
ControllerTab.Activate
ControllerTabBase.Select
End Sub
Export Worksheets to Workbooks
Option Explicit
Sub ExportWorksheets()
Dim siws As Worksheet: Set siws = ThisWorkbook.Worksheets("Controller")
Dim siCell As Range: Set siCell = siws.Range("B1")
Dim Exceptions() As String
Exceptions = Split("Read Me,Validations,Controller,MTI Data,Other", ",")
Dim sPath As String: sPath = ThisWorkbook.Path & Application.PathSeparator
Application.ScreenUpdating = False
Dim sws As Worksheet
Dim sName As String
Dim dwb As Workbook
Dim dws As Workbook
Dim drg As Range
Dim dCell As Range
Dim dlRow As Long
Dim dFilePath As String
Dim dName As String
Dim dnws As Worksheet ' existing worksheet
Dim ddrg As Range ' excluding headers
For Each sws In ThisWorkbook.Worksheets
sName = sws.Name
If IsError(Application.Match(sName, Exceptions, 0)) Then ' not found
dFilePath = sPath & sName & ".xlsx"
If Len(Dir(dFilePath)) = 0 Then ' file doesn't exist
' Copy to workbook.
sws.Copy
Set dwb = Workbooks(Workbooks.Count)
Set dws = dwb.Worksheets(sName)
dlRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row
Set drg = dws.Range("A1:P" & dlRow)
' Advance Filter
dws.Range("N1:N" & dlRow).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=dws.Range("BB1"), Unique:=True
' Copy to worksheets.
For Each dCell In dws.Range("BB2", _
dws.Cells(dws.Rows.Count, "BB").End(xlUp)).Cells
dName = dCell.Value
With drg
.AutoFilter Field:=14, Criteria1:=dName
.SpecialCells(xlCellTypeVisible).Copy
dwb.Worksheets.Add(After:=dwb.Sheets( _
dwb.Sheets.Count)).Name = dName
ActiveSheet.Paste
End With
Next dCell
' Save.
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
dwb.SaveAs Filename:=dFilePath
dwb.Close SaveChanges:=False
Else ' file exists
' Copy to workbook.
Set dwb = Workbooks.Open(dFilePath)
sws.Copy Before:=dwb.Sheets(1)
Set dws = dwb.Worksheets(sName)
dlRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row
Set drg = dws.Range("A1:P" & dlRow)
Set ddrg = dws.Range("A2:P" & dlRow)
' Advanced Filter
dws.Range("N1:N" & dlRow).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=dws.Range("BB1"), Unique:=True
' Copy to worksheets.
For Each dCell In dws.Range("BB2", _
dws.Cells(dws.Rows.Count, "BB").End(xlUp)).Cells
dName = dCell.Value
On Error Resume Next
Set dnws = dwb.Worksheets(dName)
On Error GoTo 0
If dnws Is Nothing Then ' worksheet doesn't exist...
With drg ' ... the same as when file doesn't exist
.AutoFilter Field:=14, Criteria1:=dName
.SpecialCells(xlCellTypeVisible).Copy
dwb.Worksheets.Add(After:=dwb.Sheets( _
dwb.Sheets.Count)).Name = dName
ActiveSheet.Paste
End With
Else ' worksheet already exists
drg.AutoFilter Field:=14, Criteria1:=dName
ddrg.SpecialCells(xlCellTypeVisible).Copy _
dnws.Cells(dnws.Rows.Count, "A").End(xlUp).Offset(1)
Set dnws = Nothing
End If
Next dCell
' Save.
Application.DisplayAlerts = False
dws.Delete
Application.DisplayAlerts = True
dwb.Close SaveChanges:=True
End If
'Else ' is in the exceptions list; do nothing
End If
Next sws
' Finishing Touches
siws.Select
siCell.Select
Application.ScreenUpdating = True
MsgBox "Worksheets exported.", vbInformation
End Sub
Here's a function to determine whether a file currently exists:
Private Function FileExists(FileName As String) As Boolean
On Error Resume Next
FileExists = CBool(FileLen(FileName) + 1)
End Function
Function FileExists(FileName As String) As Boolean
FileExists = Len(Dir(FileName)) > 0
End Function
Usage
I would add the FileExists(FileName) clase to the existing If statement.
FileName = sPath & wsCur.Name & ".xlsx"
If IsError(mtchSh) And Not FileExists(FileName) Then 'no sheet names found in the array
When trying to copy range("A2:H2") + End(xlDown) from multiple files into master Workbook
Run time error '424' Object Required
Sub Create()
Dim folderPath As String
Dim fileName As String
Dim erow As Long
Dim wbMaster As Workbook, wbTemp As Workbook
Dim wsMaster As Worksheet, wsTemp As Worksheet
folderPath= "\\Groups\DAILY RECON\October 2021"
Set wbMaster = ActiveWorkbook
Set wsMaster = wbMaster.Sheets("NY")
if Right(folderPath, 1)<> "\" Then folderPath = folderPath & "\"
fileName = Dir(folderPath & "*.xlsm")
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
Do While fileName<>""
if fileName <> "master.xlsm" Then
Set wbTemp = Workbooks.Open(folderPath & fileName, ReadOnly= True)
Set wsTemp = wbTemp.Sheets("NY")
With wsMaster
erow = .Range("A" & .Rows.Count).End(xlUp).Row
ws.Temp.Range("A2:H2").Select ' ----> **Error**
Range(ActiveCell,ActiveCell.End(xlDown)).Select
Selection.Copy
.Range("A" & erow).Offset(1,0).PasteSpecial xlPasteValues
End With
wbTemp.Close False
Set wsTemp = Nothing
Set wbTemp = Nothing
End If
fileName = Dir
Loop
MsgBox "Finished"
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
Copy Range From Multiple Files
Option Explicit
Sub Create()
Dim wbMaster As Workbook, wbTemp As Workbook
Dim wsMaster As Worksheet, wsTemp As Worksheet
Dim mrg As Range, trg As Range
Dim mrrg As Range
Dim meRow As Long
Dim mFileName As String, tFileName As String
Dim tFolderPath As String
Dim rCount As Long
Dim cCount As Long
tFolderPath = "\\Groups\DAILY RECON\October 2021"
Set wbMaster = ActiveWorkbook ' ThisWorkbook ' workbook containing this code
Set wsMaster = wbMaster.Sheets("NY")
With wsMaster
meRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
cCount = wsMaster.Columns("A:H").Columns.Count
Set mrrg = .Range("A" & meRow).Resize(, cCount)
End With
mFileName = wbMaster.Name
If Right(tFolderPath, 1) <> "\" Then tFolderPath = tFolderPath & "\"
tFileName = Dir(tFolderPath & "*.xlsm")
Application.ScreenUpdating = False
Do While tFileName <> ""
If StrComp(tFileName, mFileName, vbTextCompare) <> 0 Then
Set wbTemp = Workbooks.Open(tFolderPath & tFileName, ReadOnly:=True)
On Error Resume Next ' check if exists
Set wsTemp = wbTemp.Sheets("NY")
On Error GoTo 0
If Not wsTemp Is Nothing Then ' it exists
With wsTemp.Range("A1").CurrentRegion.Columns("A:H")
Set trg = .Resize(.Rows.Count - 1).Offset(1)
End With
rCount = trg.Rows.Count
Set mrg = mrrg.Resize(rCount)
mrg.Value = trg.Value
Set mrrg = mrrg.Offset(rCount)
Set wsTemp = Nothing
End If
wbTemp.Close SaveChanges:=False
End If
tFileName = Dir
Loop
Application.ScreenUpdating = True
MsgBox "Finished"
End Sub
I'm trying to loop through files in a folder with following path "C:\Users\Ouen\Downloads\Test" and paste each output into a new specific sheet in a MASTER workbook.
For example, the below are all the same worksbooks that each have a specific worksheet called "Annual" with different outputs:
Asset1
Asset2
Asset3
Etc
I would like to copy the whole Annual worksheet from each of the workbooks above and paste into a MASTER workbook, while being able to rename them to the following:
Asset1 - Annual
Asset2 - Annual
Asset3 - Annual
Etc
I have had some luck in copying and pasting from each workbook into the master but I'm unable to to paste each output into a new worksheet within the master and rename. Any ideas?
Sub Assets2Master()
Dim xRg As Range
Dim xSelItem As Variant
Dim xFileDlg As FileDialog
Dim xFileName, xSheetName, xRgStr As String
Dim xBook, xWorkBook As Workbook
Dim xSheet As Worksheet
On Error Resume Next
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
xSheetName = "Annual"
xRgStr = "B1:GI100"
Set xFileDlg = Application.FileDialog(msoFileDialogFolderPicker)
With xFileDlg
If .Show = -1 Then
xSelItem = .SelectedItems.Item(1)
Set xWorkBook = ThisWorkbook
Set xSheet = xWorkBook.Sheets("MASTER")
If xSheet Is Nothing Then
xWorkBook.Sheets.Add(after:=xWorkBook.Worksheets(xWorkBook.Worksheets.Count)).Name = "MASTER"
Set xSheet = xWorkBook.Sheets("MASTER")
End If
xFileName = Dir(xSelItem & "\*.xlsx", vbNormal)
If xFileName = "" Then Exit Sub
Do Until xFileName = ""
Set xBook = Workbooks.Open(xSelItem & "\" & xFileName)
Set xRg = xBook.Worksheets(xSheetName).Range(xRgStr)
xRg.Copy xSheet.Range("A65536").End(xlUp).Offset(1, 0)
xFileName = Dir()
xBook.Close
Loop
End If
End With
et xRg = xSheet.UsedRange
xRg.ClearFormats
xRg.UseStandardHeight = True
xRg.UseStandardWidth = True
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Copy to the end
This code will copy, if it exists, the Annual worksheet from each workbook in the folder you select via the dialog.
They will be copied to the workbook the code is in and the copied sheets will be renamed with the name of the workbook they came from appended with - Annual.
The copied sheets will be copied after the last sheet in the MASTER workbook.
Sub Assets2Master()
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim wsSrc As Worksheet
Dim dlg As Object
Dim strFileName As String
Dim strFolder As String
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Set dlg = Application.FileDialog(msoFileDialogFolderPicker)
With dlg
If .Show = -1 Then
strFolder = .SelectedItems.Item(1)
End If
End With
Set wbDst = ThisWorkbook
strFileName = Dir(strFolder & "\*.xlsx", vbNormal)
If strFileName = "" Then Exit Sub
Do Until strFileName = ""
If strFileName <> wbDst.Name Then
Set wbSrc = Workbooks.Open(strFolder & "\" & strFileName)
' check if 'Annual' sheet exists, and if it does copy it to master workbook
If IfSheetExists("Annual", wbSrc) Then
Set wsSrc = wbSrc.Sheets("Annual")
With wbDst
wsSrc.Copy After:=.Sheets(.Sheets.Count)
.Sheets(.Sheets.Count).Name = Left(strFileName, Len(strFileName) - 5) & " - Annual"
End With
End If
wbSrc.Close SaveChanges:=False
End If
strFileName = Dir()
Loop
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Function IfSheetExists(strName As String, Optional wb As Workbook) As Boolean
' checks for the existence of a worksheet named strName in the, optional, workbook wb
' if wb not stated checks in the active workbook
Dim ws As Worksheet
If wb Is Nothing Then
Set wb = ActiveWorkbook
End If
For Each ws In wb.Sheets
If ws.Name = strName Then
IfSheetExists = True
Exit For
End If
Next ws
End Function
Copy after specific sheet
This code is basically identical to the previous code but the workheets will be copied after a specific worksheet in the MASTER workbook.
Option Explicit
Sub Assets2Master()
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim wsSrc As Worksheet
Dim dlg As Object
Dim strFileName As String
Dim strFolder As String
Dim lngDstIndex As Long
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Set dlg = Application.FileDialog(msoFileDialogFolderPicker)
With dlg
If .Show = -1 Then
strFolder = .SelectedItems.Item(1)
End If
End With
Set wbDst = ThisWorkbook
' change Specific Tab to the name ypu want the sheets to be copied after
lngDstIndex = wbDst.Sheets("Specific Tab").Index
strFileName = Dir(strFolder & "\*.xlsx", vbNormal)
If strFileName = "" Then Exit Sub
Do Until strFileName = ""
If strFileName <> wbDst.Name Then
Set wbSrc = Workbooks.Open(strFolder & "\" & strFileName)
' check if 'Annual' sheet exists, and if it does copy it to master workbook
If IfSheetExists("Annual", wbSrc) Then
Set wsSrc = wbSrc.Sheets("Annual")
With wbDst
' copy sheet to MASTER workbook
wsSrc.Copy After:=.Sheets(.Sheets.Count)
' rename sheet and move it after specified sheet
With .Sheets(.Sheets.Count)
.Name = Left(strFileName, Len(strFileName) - 5) & " - Annual"
.Move After:=wbDst.Sheets(lngDstIndex)
lngDstIndex = lngDstIndex + 1
End With
End With
End If
wbSrc.Close SaveChanges:=False
End If
strFileName = Dir()
Loop
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Function IfSheetExists(strName As String, Optional wb As Workbook) As Boolean
' checks for the existence of a worksheet named strName in the, optional, workbook wb
' if wb not stated checks in the active workbook
Dim ws As Worksheet
If wb Is Nothing Then
Set wb = ActiveWorkbook
End If
For Each ws In wb.Sheets
If ws.Name = strName Then
IfSheetExists = True
Exit For
End If
Next ws
End Function
Try this. The Master wb should be placed in a different folder than the one you store the Asset Files:
Sub Assets2Master()
Dim xRg As Range
Dim xSelItem As Variant
Dim xFileDlg As FileDialog
Dim xFileName, xSheetName, xRgStr As String
Dim xBook, xWorkBook As Workbook
Dim xSheet As Worksheet
On Error Resume Next
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
xSheetName = "Annual"
xRgStr = "B1:GI100"
Set xFileDlg = Application.FileDialog(msoFileDialogFolderPicker)
With xFileDlg
If .Show = -1 Then
xSelItem = .SelectedItems.item(1)
Set xWorkBook = ActiveWorkbook
Set xSheet = xWorkBook.Sheets("MASTER")
If xSheet Is Nothing Then
xWorkBook.Sheets.Add(After:=xWorkBook.Worksheets(xWorkBook.Worksheets.count)).Name = "MASTER"
Set xSheet = xWorkBook.Sheets("MASTER")
End If
xFileName = Dir(xSelItem & "\*.xlsx", vbNormal)
If xFileName = "" Then Exit Sub
Do Until xFileName = ""
Set xBook = Workbooks.Open(xSelItem & "\" & xFileName)
Set xRg = xBook.Worksheets(xSheetName).Range(xRgStr)
xRg.Copy xSheet.Range("A65536").End(xlUp).Offset(1, 0)
xFileName = Dir()
xBook.Close
xBook.Name = xBook.Name & " - Annual"
Loop
End If
End With
Set xRg = xSheet.UsedRange
xRg.ClearFormats
xRg.UseStandardHeight = True
xRg.UseStandardWidth = True
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Stack Ranges
This is about what I thought your code was supposed to do. What you asked for is kind of illustrated with the commented block of code in the Do...Loop. By modifying the code in the Do...Loop, there are many possibilities of what you could achieve.
Option Explicit
Sub StackRanges()
' Source
Const sName As String = "Sheet1" ' "Annual"
Const sAddress As String = "B1:GI100"
' Destination
Const dName As String = "MASTER"
Const dCol As String = "A"
Application.ScreenUpdating = False
' Open the dialog to pick a folder.
Dim xFileDlg As FileDialog
Set xFileDlg = Application.FileDialog(msoFileDialogFolderPicker)
Dim sFolderPath As Variant
With xFileDlg
.InitialFileName = ThisWorkbook.Path
If .Show = True Then
sFolderPath = .SelectedItems.Item(1)
Else
MsgBox "Canceled.", vbExclamation, "Assets2Master"
Exit Sub
End If
End With
' Write the name of the first file to the Source File Name variable.
Dim sfName As String: sfName = Dir(sFolderPath & "\*.xlsx")
' Validate first Source File Name.
If Len(sfName) = 0 Then Exit Sub ' no files found
' Create a reference to the Destination Workbook.
Dim dwb As Workbook: Set dwb = ThisWorkbook
' Write the name of the Destination Workbook
' to the Destination File Name variable.
Dim dfName As String: dfName = dwb.Name
' Attempt to create a reference to the Destination Worksheet.
Dim dws As Worksheet
On Error Resume Next
Set dws = dwb.Worksheets(dName)
On Error GoTo 0
' If the attempt was unsuccessful, add a new worksheet and do it now.
If dws Is Nothing Then
dwb.Worksheets.Add(After:=dwb.Sheets(dwb.Sheets.Count)).Name = dName
Set dws = dwb.Worksheets(dName)
' Maybe add some headers... to the Destination Worksheet.
End If
' Create a reference to the (first) Destination Range.
Dim drg As Range: Set drg = dws.Range(sAddress)
Dim rCount As Long: rCount = drg.Rows.Count
Dim cCount As Long: cCount = drg.Columns.Count
Set drg = dws.Cells(dws.Rows.Count, dCol).End(xlUp) _
.Offset(1, 0).Resize(rCount, cCount)
' Declare additional variables for the following 'Do Loop'.
Dim swb As Workbook
Dim sws As Worksheet
Dim srg As Range
' Loop through the files in the folder...
Do Until Len(sfName) = 0
' Check if the Source File Name is different
' than the Destination File Name.
If StrComp(sfName, dfName, vbTextCompare) <> 0 Then
' Open and create a reference to the Source Workbook.
Set swb = Workbooks.Open(sFolderPath & "\" & sfName)
' Attempt to create a reference to the Source Worksheet.
Set sws = Nothing
On Error Resume Next
Set sws = swb.Worksheets(sName)
On Error GoTo 0
' Stack Ranges
' If the attempt was successful...
If Not sws Is Nothing Then
' Create a reference to the Source Range.
Set srg = sws.Range(sAddress)
' Copy the values from the Source to the Destination Range
' by assignment.
drg.Value = srg.Value
' Create a reference to the (next) Destination Range.
Set drg = drg.Offset(rCount)
End If
' ' Copy Worksheets (instead)
'
' ' If the attempt was successful...
' If Not sws Is Nothing Then
' sws.Copy After:=dwb.Sheets(dwb.Sheets.Count)
' ' Caution: Has to be less than 32 characters!
' ActiveSheet.Name = Left(sfName, Len(sfName) - 5) & " - " & sName
' End If
' Close the Source Workbook.
swb.Close SaveChanges:=False
End If
' Write the name of the next file to the Source File Name variable.
sfName = Dir
Loop
Application.ScreenUpdating = True
' Inform the user.
MsgBox "Data copied.", vbInformation, "Assets2Master"
End Sub
I was using below code to get the multiple CSV files into single sheet.
code is working fine but the issue is that, it should not copy the headers of each file, because each file header is same.
Code should copy the first file header not all files.
One more thing that i do not want first column to copy all sheets name i have tried to remove that filed but code does not work.
Can i get any help.
thanks
Sub CSV()
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Set xSht = ThisWorkbook.ActiveSheet
Application.ScreenUpdating = False
xFile = Dir(xStrPath & "\" & "*.csv")
Do While xFile <> ""
Set xWb = Workbooks.Open(xStrPath & "\" & xFile)
Columns(1).Insert xlShiftToRight
Columns(1).SpecialCells(xlBlanks).Value = ActiveSheet.Name
ActiveSheet.UsedRange.Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
xWb.Close False
xFile = Dir
Loop
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox "no files csv", , "Kutools for Excel"
End Sub
EDIT: I did two attempts, first one untested, and did it on my phone:
Sub CSV()
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
On Error GoTo ErrHandler
Set xFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
xFileDialog.AllowMultiSelect = False
xFileDialog.Title = "Select a folder [Kutools for Excel]"
If xFileDialog.Show = -1 Then
xStrPath = xFileDialog.SelectedItems(1)
End If
If xStrPath = "" Then Exit Sub
Set xSht = ThisWorkbook.ActiveSheet
Application.ScreenUpdating = False
xFile = Dir(xStrPath & "\" & "*.csv")
Dim counter as Long
Do While xFile <> ""
Set xWb = Workbooks.Open(xStrPath & "\" & xFile)
Dim sourceRange as Range
Set sourceRange = xWb.Worksheets(1).UsedRange
If counter = 0 then
sourceRange.Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
else
sourceRange.Offset(1, 0).Resize(sourceRange.Rows.Count - 1, sourceRange.Columns.Count).Copy xSht.Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
xWb.Close False
xFile = Dir
counter = counter + 1
Loop
Application.ScreenUpdating = True
Exit Sub
ErrHandler:
MsgBox "no files csv", , "Kutools for Excel"
End Sub
Second attempt from my computer, I refactored the code handled first file case, skipped the clipboard and use proper procedure and variable names.
Public Sub ImportAndAppendCSVFromFolder()
' Set basic error handling
On Error GoTo CleanFail
' Turn off stuff
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim xSht As Worksheet
Dim xWb As Workbook
Dim xStrPath As String
Dim xFileDialog As FileDialog
Dim xFile As String
' Prepare and display file dialog to user
Dim customFileDialog As FileDialog
Set customFileDialog = Application.FileDialog(msoFileDialogFolderPicker)
customFileDialog.AllowMultiSelect = False
customFileDialog.Title = "Select a folder"
' Get folder path from file dialog
If customFileDialog.Show = -1 Then
Dim folderPath As String
folderPath = customFileDialog.SelectedItems(1)
End If
' Exit if nothing was selected
If folderPath = vbNullString Then Exit Sub
' Set reference to active sheet (could be replaced to a specific sheet name with this: ThisWorkbook.Worksheets("SheetName") )
Dim targetSheet As Worksheet
Set targetSheet = ThisWorkbook.ActiveSheet
' Get files in directory ending with specific extension
Dim sourceFile As String
sourceFile = Dir(folderPath & "\" & "*.csv")
' Loop through files
Do While sourceFile <> ""
' Open file
Dim sourceWorkbook As Workbook
Set sourceWorkbook = Workbooks.Open(folderPath & "\" & sourceFile)
' Set reference to sheet in file (as it's a csv file, it only has one worksheet)
Dim sourceSheet As Worksheet
Set sourceSheet = sourceWorkbook.Worksheets(1)
' Depending if it's the first file, include headers or not
Dim counter As Long
If counter = 0 Then
' Set reference to used range in source file
Dim sourceRange As Range
Set sourceRange = sourceSheet.UsedRange
' Calc offset if it's first file
Dim rowOffset As Long
rowOffset = 0
Else
' Don't include headers in range
Set sourceRange = sourceSheet.UsedRange.Offset(1, 0).Resize(sourceSheet.UsedRange.Rows.Count - 1, sourceSheet.UsedRange.Columns.Count)
' Calc offset if it's not first file
rowOffset = 1
End If
' Perform copy (as this comes from a csv file, we can skip the clipboard
targetSheet.Range("A" & targetSheet.Rows.Count).End(xlUp).Resize(sourceRange.Rows.Count, sourceRange.Columns.Count).Offset(rowOffset).Value2 = sourceRange.Value2
' Close csv file
sourceWorkbook.Close False
' Get reference to next file
sourceFile = Dir
counter = counter + 1
Loop
CleanExit:
' Turn on stuff again
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Exit Sub
CleanFail:
MsgBox "An error occurred:" & Err.Description
GoTo CleanExit
End Sub
The code below throws a Runtime Error: 13 Type mismatch. I have a list of thousands of URLs in the Sheet3, column A where I run my vba script. It finds each of the URLs in Sites, column B of 300 workbooks which is in a folder. If found, the column E of the same row is updated with Yes.
Sub ReplaceInFolder()
Dim strPath As String
Dim strFile As String
Dim wbk As Workbook
Dim wsh As Worksheet
Dim strReplace As String
Dim i As Long
Dim FoundCell As Variant
Dim FoundNo As String
strReplace = "Yes"
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show Then
strPath = .SelectedItems(1)
Else
MsgBox "No folder selected!", vbExclamation
Exit Sub
End If
End With
If Right(strPath, 1) <> "\" Then
strPath = strPath & "\"
End If
Application.ScreenUpdating = False
strFile = Dir(strPath & "*.xls*")
Do While strFile <> ""
Set wbk = Workbooks.Open(Filename:=strPath & strFile, AddToMRU:=False)
For Each wsh In wbk.Worksheets
If wsh.Name = "Sites" Then
For i = 1 To Range("A" & Rows.Count).End(xlUp).Row
Set FoundCell = wsh.Range("B:B").Find(What:=Cells(i, "A").Value, LookAt:=xlWhole, MatchCase:=False)
If Not FoundCell Is Nothing Then
FoundNo = FoundCell.Address
Debug.Print FoundCell.Address
Do Until FoundCell Is Nothing
wsh.Cells(FoundCell.Row, 5).Value = strReplace
Set FoundCell = wsh.Cells.FindNext(after:=FoundCell)
If FoundCell.Address = FoundNo Then Exit Do
Loop
End If
Next i
End If
Next wsh
wbk.Close SaveChanges:=True
strFile = Dir
Loop
Application.ScreenUpdating = True
End Sub