Copy all sheets from a targeted workbook - vba

I am getting run-time error '2147 and for the life of me I can't see what I am missing.
All I am trying to do is from my current workook open a selected workbook and copy in all sheets.
Thank you.
Sub GetFile()
Dim fNameAndPath As Variant
Dim wb As Workbook, wb2 As Workbook
Dim Ws As Worksheet
fNameAndPath = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Select File To Be Opened")
If fNameAndPath = False Then Exit Sub
Workbooks.Open Filename:=fNameAndPath
Application.ScreenUpdating = False
Set wb = ActiveWorkbook
Set wb2 = Workbooks.Add(fNameAndPath)
For Each Ws In wb2.Worksheets
Ws.Copy After:=wb.Sheets(wb.Sheets(1))
Next Ws
Application.ScreenUpdating = True
End Sub

Public Sub this()
Dim path As String, fileName As String
Dim sheet As Worksheet, thisWB As Workbook, thatWB As Workbook
Dim arr() As Variant
Dim rowC As Long, colC As Long
path = "C:\Users\dcoats\Desktop" & "\"
fileName = Dir(path & "*.xl??")
Set thisWB = ThisWorkbook
Do While Len(fileName) > 0
Set thatWB = Workbooks.Open(path & fileName, True, True)
For Each sheet In thatWB.Sheets
arr = sheet.UsedRange
rowC = sheet.UsedRange.Rows.Count
colC = sheet.UsedRange.Columns.Count
thisWB.Sheets.Add After:=Worksheets(Worksheets.Count)
thisWB.ActiveSheet.Range(thisWB.ActiveSheet.Cells(1, 1), thisWB.ActiveSheet.Cells(rowC, colC)).Value2 = arr
Next sheet
thatWB.Close False
fileName = Dir()
Loop
End Sub
This should work for you. Careful though it loops through all files in a directory (sorry I basically copied/pasted this from a script library i keep).

Related

Open, copy, paste close and loop files in a folder

I have a folder with 50 excel files I need to open, copy, paste, close and open the next one.
The macro is working until the loop, but it is not opening the next file. It stops
Any suggestion?
Sub open_and_close()
Dim MyFolder As String
Dim MyFile As Variant
Dim LC3 As Long
Dim WB1 As Workbook
Dim WB2 As Workbook
Set WB1 = ThisWorkbook
MyFolder = "C:\Users\x\y\z\Test script\"
MyFile = Dir(MyFolder & "*.xlsx")
Do While MyFile <> ""
Workbooks.Open (MyFolder & MyFile)
Set WB2 = ActiveWorkbook
ActiveWorkbook.Sheets("Test Script Scenario 1").Range("J3:J99").Copy
WB1.Sheets("Test Script Scenario 1").Activate
LC3 = Cells(3, Columns.Count).End(xlToLeft).Column
Cells(3, LC3 + 1).PasteSpecial Paste:=xlPasteValues
Cells(1, LC3 + 1) = Dir(WB2.Name)
WB2.Close savechanges:=False
MyFile = Dir()
Loop
End Sub
I always avoid DIR as it behaves strange if called several times.
I assume that's your problem - as you call Dir(wb2.name).
Try using FilesystemObject.
You have to add a reference to your project:
Furthermore it's not necessary to copy/paste >> see sub copyRangeValues
Plus: consider using a table (Insert > table) than it is much easier to add new columns.
Option Explicit
Private Const pathToFiles As String = "C:\Users\x\y\z\Test script\"
Private Const SourceSheetname As String = "Test Script Scenario 1"
Private Const SourceAddressToCopy As String = "J3:J99"
Private Const TargetSheetname As String = "Test Script Scenario 1"
Private Const TargetStartRow As Long = 3
Sub readDataFromFiles()
Dim fso As FileSystemObject
Set fso = New FileSystemObject
Dim SourceFolder As Folder
Set SourceFolder = fso.GetFolder(pathToFiles)
Dim SourceFile As File, wbSource As Workbook
For Each SourceFile In SourceFolder.Files
If SourceFile.Name Like "*.xlsx" Then
Set wbSource = getWorkbook(pathToFiles & "\" & SourceFile.Name)
copyDataFromSource wbSource
wbSource.Close False
End If
Next
End Sub
Private Sub copyDataFromSource(wbSource As Workbook)
Dim rgSource As Range
Set rgSource = wbSource.Worksheets(SourceSheetname).Range(SourceAddressToCopy)
Dim rgTargetCell As Range
Set rgTargetCell = getTargetCell
copyRangeValues rgSource, rgTargetCell
'add filename to row 1
rgTargetCell.Offset(TargetStartRow - 2).Value = wbSource.Name
End Sub
Private Function getTargetCell() As Range
Dim wsTarget As Worksheet: Set wsTarget = ThisWorkbook.Worksheets(TargetSheetname)
'I copied your code - but it looks weird to me
'think of using a table and then your can work with the listobject to add a new column
Dim LC3 As Long
With wsTarget
LC3 = .Cells(3, .Columns.Count).End(xlToLeft).Column
End With
Set getTargetCell = wsTarget.Cells(TargetStartRow, LC3)
End Function
Public Sub copyRangeValues(rgSource As Range, rgTargetCell As Range)
'generic routine to copy one range to another
'rgTargetCell = top left corner of target range
Dim rgTarget As Range
'resize rgTarget according to dimensions of rgSource
With rgSource
Set rgTarget = rgTargetCell.Resize(.Rows.Count, .Columns.Count)
End With
'write values from rgSource to rgTarget - no copy/paste necessary!!!
'formats are not copied - only values
rgTarget.Value = rgSource.Value
End Sub
Private Function getWorkbook(FullFilename As String) As Workbook
Dim wb As Workbook
Set wb = Application.Workbooks.Open(FullFilename)
Set getWorkbook = wb
End Function
First collect the files in an array, then process the files.
Sub open_and_close()
Dim MyFolder As String
Dim MyFile As Variant, Files As Variant
Dim LC3 As Long, NumFiles As Long, Idx As Long
Dim WB1 As Workbook, WB2 As Workbook
Set WB1 = ThisWorkbook
MyFolder = "C:\Users\x\y\z\Test script\"
' First collect the files in an array
MyFile = Dir(MyFolder & "*.xlsx")
NumFiles = 0
Do While MyFile <> ""
NumFiles = NumFiles + 1
If NumFiles = 1 Then
ReDim Files(1 To 1)
Else
ReDim Preserve Files(1 To NumFiles)
End If
Files(NumFiles) = MyFile
MyFile = Dir()
Loop
' Then process the files
For Idx = 1 To NumFiles
MyFile = Files(Idx)
Set WB2 = Workbooks.Open(MyFolder & MyFile)
ActiveWorkbook.Sheets("Test Script Scenario 1").Range("J3:J99").Copy
WB1.Sheets("Test Script Scenario 1").Activate
LC3 = Cells(3, Columns.Count).End(xlToLeft).Column
Cells(3, LC3 + 1).PasteSpecial Paste:=xlPasteValues
Cells(1, LC3 + 1) = Dir(WB2.Name)
WB2.Close savechanges:=False
Next Idx
End Sub

Copy data from multiple workbook to one workbook after using Autofilter

I am trying to copy data from multiple WB to one WB after using filter. I am able to select the copy range but I don't know how to paste them to the destination WB without making the data overwritten.
I am sorry for the format of my code. I do not know how to fix it when I post it here.
Here is my code:
Option Explicit
Const FOLDER_PATH = "D:\Programming\VBA\Linh\CARD DELIVERY\New folder\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
Dim rowCount As Long
rowTarget = 2
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error GoTo errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Sheet1")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbSource.Worksheets(1) 'EDIT IF NECESSARY
wsSource.Range("A2", Range("P" & Rows.Count).End(xlUp)).AutoFilter Field:=12, Criteria1:="Phát thành công"
wsSource.Range("I2", Range("I" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible).Copy
rowCount = wsSource.Range("I2", Range("I" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible).Cells.Count
'import the data
With wsTarget
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
just add:
'import the data
wsTarget
.cells(.Rows.Count, "A").End(xlUp).Offset(1).PasteSpecial
End With
to keep pasting filtered data in wsTarget column A from row 2 downwards

Looping through files in a folder, copy contents to specific sheet and loop through sheets in master file

Before starting to explain my problem, sorry for the messy code, I'm still a beginner in VBA and thank you for your help in advance.
So what I'm trying to do is getting a way of copying the contents of some workbooks in a folder to my master file, which is kinda like a data base. The trick here is that I need the 2 sheets from the file to be copied into the 1st sheet of my master file.
In the mean time and looking through a lot of posts, like this one,
VBA Loop through files in folder and copy/paste to master file, I came up with this code:
Option Explicit
Sub AllFiles()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.EnableCancelKey = xlDisabled
Application.ScreenUpdating = False
Dim folderPath As String
Dim Filename As String
Dim wb As Workbook
Dim Masterwb As Workbook
Dim sh As Worksheet
Dim NewSht As Worksheet
Dim FindRng As Range
Dim PasteRow As Long
Dim i As Integer
' set master workbook
Set Masterwb = ThisWorkbook
folderPath = Sheets("teste").Range("A1").Value 'contains folder path
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\"
For i = 1 To Sheets("leit_func").Range("S2")
Filename = Dir(folderPath & Sheets("teste").Range("A3"))
Do While Filename <> ""
Set wb = Workbooks.Open(folderPath & Filename)
If Len(wb.Name) > 35 Then
MsgBox "Sheet's name can be up to 31 characters long, shorten the Excel file name"
wb.Close False
GoTo Exit_Loop
Else
' add a new sheet with the file's name (remove the extension)
'-------------------------------------------------------------------------------------------
'Set NewSht = Masterwb.Worksheets.Add(After:=Masterwb.Worksheets(1))
'NewSht.Name = Replace(wb.Name, ".xlsx", "")
'-------------------------------------------------------------------------------------------
Set NewSht = ThisWorkbook.Sheets(i)
End If
' loop through all sheets in opened wb
For Each sh In wb.Worksheets
' get the first empty row in the new sheet
Set FindRng = NewSht.Cells.Find(What:="*", Lookat:=xlPart, LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not FindRng Is Nothing Then ' If find is successful
PasteRow = FindRng.Row + 1
Else ' find was unsuccessfull > new empty sheet, should paste at the first row
PasteRow = 1
End If
sh.UsedRange.Copy
NewSht.Range("A" & PasteRow).PasteSpecial xlPasteValues
'NewSht.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=False
Next sh
wb.Close False
Exit_Loop:
Set wb = Nothing
Filename = Dir()
Loop
Next i
Application.ScreenUpdating = True
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.EnableEvents = False
End Sub
With this code I can paste the info in different sheets, but the problem is that it's getting the contents from all the files in the folder, and I want file 1 in sheet 1, file 2 in sheet 2, and so on.
I think my problem has something to do with the placement of my For cycle for the sheets, but I'm not exactly sure.
Thank you!
Here is a copy/paste from a script library i keep. It is a rough example of how to loop through files in a directory and copy and paste each sheet to a new sheet in the master workbook. I have included a section that shows how to append to the end of a range as well. Both can be useful. Note that i use arrays to move data as its easier and faster.
Public Sub this()
Dim path As String, fileName As String, shtName As String
Dim sheet As Worksheet, thisWB As Workbook, thatWB As Workbook
Dim arr() As Variant
Dim rowC As Long, colC As Long, mrowC As Long, mColC As Long
path = "your path to directory" & "\"
fileName = Dir(path & "*.xl??")
Set thisWB = ThisWorkbook
Do While Len(fileName) > 0
Set thatWB = Workbooks.Open(path & fileName, True, True)
For Each sheet In thatWB.Sheets
shtName = Left(Mid(fileName, 1, InStrRev(fileName, ".") - 1), 30)
thisWB.ActiveSheet.Name = shtName
mrowC = thisWB.Sheets(shtName).UsedRange.Rows.Count
mColC = thisWB.Sheets(shtName).UsedRange.Columns.Count
arr = sheet.UsedRange
rowC = sheet.UsedRange.Rows.Count
colC = sheet.UsedRange.Columns.Count
thisWB.Sheets(shtName).Range(thisWB.Sheets(shtName).Cells(mrowC + 1, 1), thisWB.Sheets(shtName).Cells(mrowC + 1 + rowC, colC)).Value2 = arr
Next sheet
thatWB.Close False
fileName = Dir()
thisWB.Sheets.Add After:=Worksheets(Worksheets.Count)
Loop
End Sub

Copy Active sheet of all workbooks in a folder to a new workbook

Hi I have the following code to copy all worksheets of all workbooks in a given folder to a single workbook. I need to modify this code to copy only the active sheet on all workbooks (now it copies all the sheets). Can you help me with this?
Option Explicit
Sub CombineFiles()
Dim Path As String
Dim FileName As String
Dim Wkb As Workbook
Dim WS As Worksheet
Application.EnableEvents = False
Application.ScreenUpdating = False
Path = "C:\" 'Change as needed
FileName = Dir(Path & "\*.xlsx", vbNormal)
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
For Each WS In Wkb.Worksheets
WS.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
Next WS
Wkb.Close False
FileName = Dir()
Loop
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This way you can do what you want:
Option Explicit
Sub CombineFiles()
Dim Path As String
Dim FileName As String
Dim Wkb As Workbook
Dim WS As Worksheet
Application.EnableEvents = False
Application.ScreenUpdating = False
Path = "C:\" 'Change as needed
FileName = Dir(Path & "\*.xlsx", vbNormal)
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
ActiveSheet.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
'For Each WS In Wkb.Worksheets
' WS.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
'Next WS
Wkb.Close False
FileName = Dir()
Loop
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Note:
When you open the workbook, you go over all the sheets with the FOR LOOP, but you only need to copy the ActiveSheet then (as you said) you only need to copy to the new Wrokbook

copying workbooks from current folder and also subfolders

This is part of the sub I found to copy all tabs in all workbooks in a directory to my current workbook, but how can I adjust it to scan all subfolders as well? Currently, it only copies from the folder I select and then stops.
Here's the full code with functions: http://www.vbaexpress.com/kb/getarticle.php?kb_id=829
Sub CombineFiles()
Dim path As String
Dim FileName As String
Dim LastCell As Range
Dim Wkb As Workbook
Dim WS As Worksheet
Dim ThisWB As String
ThisWB = ThisWorkbook.Name
Application.EnableEvents = False
Application.ScreenUpdating = False
path = GetDirectory
FileName = Dir(path & "\*.xls*", vbNormal)
Do Until FileName = ""
If FileName <> ThisWB Then
Set Wkb = Workbooks.Open(FileName:=path & "\" & FileName)
For Each WS In Wkb.Worksheets
Set LastCell = WS.Cells.SpecialCells(xlCellTypeLastCell)
If LastCell.Value = "" And LastCell.Address = Range("$A$1").Address Then
Else
WS.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
End If
Next WS
Wkb.Close False
End If
FileName = Dir()
Loop
Application.EnableEvents = True
Application.ScreenUpdating = True
Set Wkb = Nothing
Set LastCell = Nothing
End Sub
Using the code I posted in the linked question (untested)
Sub CombineFiles()
Dim path As String
Dim FileName As String
Dim LastCell As Range
Dim Wkb As Workbook
Dim WS As Worksheet
Dim ThisWB As String
Dim colFiles As New Collection, fPath
ThisWB = ThisWorkbook.path & "\" & ThisWorkbook.Name
Application.EnableEvents = False
Application.ScreenUpdating = False
path = GetDirectory
GetFiles path, "*.xls*", True, colFiles
For Each fPath In colFiles
If fPath <> ThisWB Then
Set Wkb = Workbooks.Open(FileName:=fPath)
For Each WS In Wkb.Worksheets
Set LastCell = WS.Cells.SpecialCells(xlCellTypeLastCell)
If LastCell.Value = "" And LastCell.Address = Range("$A$1").Address Then
Else
WS.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
End If
Next WS
Wkb.Close False
End If
Next fPath
Application.EnableEvents = True
Application.ScreenUpdating = True
Set Wkb = Nothing
Set LastCell = Nothing
End Sub
VBA macro that search for file in multiple subfolders