Excel Sheet Name Error - vba

I'm using a VBA code to cycle through excel files in a directory and pull information from one worksheet and paste into a newly created worksheet. I'm also naming my new worksheets (in my destination file) by the name in one of the cells in the source file.
My code works for the first loop but fails/stops in the second loop (VBA points to an error in the Dest.Sheets.Add(After:=Dest.Sheets(Dest.Sheets.Count)).Name = Sheetname line. I need to loop through 75 of these files and I'm unsure of what's going on because it works correctly for the first file.
Thanks so much for the help!
Sub AddSummaryTables()
Dim Spath, Filename, Sheetname As String
Dim Source, Dest As Workbook
Dim WS As Worksheet
Set Dest = ThisWorkbook
Spath = InputBox("Enter File Source Path") & "\"
Filename = Dir(Spath & "*.xls*")
Do While Filename <> ""
Set Source = Workbooks.Open(Spath & Filename)
Sheetname = Source.Sheets("Summary").Range("B2").Text
MsgBox Sheetname
Dest.Sheets.Add(After:=Dest.Sheets(Dest.Sheets.Count)).Name = Sheetname
Source.Sheets("Summary").Range("A1:R150").Copy
Dest.Worksheets(Sheetname).Range("A1").PasteSpecial xlPasteValues
Dest.Worksheets(Sheetname).Range("A1").PasteSpecial xlPasteFormats
Dest.Worksheets(Sheetname).Range("A1:R150").WrapText = False
Dest.Worksheets(Sheetname).Rows.AutoFit
Dest.Worksheets(Sheetname).Columns.AutoFit
Source.Close SaveChanges:=False
Dest.Save
Filename = Dir()
Loop
End Sub

following Comintern's and Wyatt's suggestion you could try like follows
Option Explicit
Sub AddSummaryTables()
Dim sPath As String, fileName As String
Dim sourceWb As Workbook, destWb As Workbook
Dim sourceWs As Worksheet, destWs As Worksheet
Set destWb = ThisWorkbook
sPath = InputBox("Enter File Source Path") & "\"
fileName = Dir(sPath & "*.xls*")
Do While fileName <> ""
Set sourceWb = Workbooks.Open(sPath & fileName)
Set sourceWs = GetWorksheet(sourceWb, "Summary")
If Not sourceWs Is Nothing Then
Set destWs = SetWorksheet(destWb, sourceWs.Range("B2").Text)
sourceWs.Range("A1:R150").Copy
With destWs
.Range("A1").PasteSpecial xlPasteValues
.Range("A1").PasteSpecial xlPasteFormats
.UsedRange.WrapText = False
.Rows.AutoFit
.Columns.AutoFit
End With
sourceWb.Close SaveChanges:=False
destWb.Save
End If
fileName = Dir()
Loop
End Sub
Function GetWorksheet(wb As Workbook, sheetName As String) As Worksheet
On Error Resume Next
Set GetWorksheet = wb.Worksheets(sheetName)
On Error GoTo 0
End Function
Function SetWorksheet(wb As Workbook, sheetName As String) As Worksheet
Dim i As Integer
Do While Not GetWorksheet(wb, sheetName & IIf(i = 0, "", "-" & i)) Is Nothing
i = i + 1
Loop
With wb
.Worksheets.Add(After:=.Worksheets(.Worksheets.Count)).Name = sheetName & IIf(i = 0, "", "-" & Format(i, "000"))
Set SetWorksheet = .ActiveSheet
End With
End Function
where you make sure that
any opened workbook has a "Summary" worksheet
you name worksheets in your destination workbook such as not to have duplicates: if you happen to deal with say three worksheets named "Sheet5" then your destination workbook will have added worksheets "Sheet5", "Sheet5-001" and "Sheet5-002".

You're issue may be that when you are adding the sheet from the second workbook, it has the same name as the sheet from the first workbook. You could check if the sheet exists and add a number to it. The post below might help.
Test or check if sheet exists

Related

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

VBA: Run-Time Automation Error - "Code execution has been interrupted"

I'm attempting to write a program to loop through a directory of excel files and copy a range into a "Master Workbook". When I run the program I am prompted with "Code execution has been interrupted". If I select continue the code will successfully run but then a "run-time error '-2147221080' Automation error" appears.
The line that causes the error is:
Set ws = wb.Worksheets("Project Log")
My question is, why is this line causing the error and or is there a way to bypass the error prompt so that my code will successfully run?
Sub FileCompiler()
Dim folderPath As String
Dim Filename As String
Dim wb As Workbook
Dim Masterwb As Workbook
Dim ws as Worksheet
'set workbook in which data will be copied to
Set Masterwb = ActiveWorkbook
'declare path
'folderPath = "C:MyPath\"
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\"
'compile directory data to master spreadsheet
Filename = Dir(folderPath & "*.xls*")
Do While Filename <> ""
Application.ScreenUpdating = False
Set wb = Workbooks.Open(folderPath & Filename)
Set ws = wb.Worksheets("Project Log")
ws.Range(ws.Cells(2, "C"), ws.Cells(2, "C")).Copy
Masterwb.Worksheets("Staging").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
ws.Range(ws.Cells(7, "A"), ws.Cells(Rows.Count, "K").End(xlUp)).Copy
Masterwb.Worksheets("Staging").Range("B" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
wb.Close True
Filename = Dir
Loop
Application.ScreenUpdating = True
End Sub
Dim Finfo As String
Dim FilterIndex As Long
Dim Title As String
Dim CopyBook As Workbook
Dim CopySheet As Worksheet
Dim ForecastFileName As Variant
Dim MasterSheet AS Worksheet
Set MasterSheet = ThisWorkbook.Worksheets("Yoursheetname")
'now you can always use master sheet after you set copybook
'Set up file filter
Finfo = "Excel Files (*.xls*),*.xls*"
'Set filter index to Excel Files by default in case more are added
FilterIndex = 1
' set Caption for dialogue box
Title = "Hey there!, select a file"
'get the Forecast Filename
ForecastFileName = Application.GetOpenFilename(Finfo, FilterIndex, Title)
'Change this according to what you need for workbook and worksheet names
Workbooks.Open (ForecastFileName)
Set CopyBook = ActiveWorkbook
Set CopySheet = CopyBook.Worksheets(1)
'Do your code, remember to close
CopyBook.Close savechanges:=False 'Not needed now
You might want to check for the ForecastFileName being False, that is when the users x's out, you will also want to do a little validation the wb sheet is in the right format by checking column headers ect or you will wind up crashing.

Close file before moving onto the next file

This macro loops through all the files in a directory and formats the data as a table.
I need to sort Column J on the table from Largest to Smallest and then save the file before moving onto the next file. Currently it leaves all the files open.
Sub LoopThroughFiles()
FolderName = "C:\Folder1\"
If Right(FolderName, 1) <> Application.PathSeparator Then FolderName = FolderName & Application.PathSeparator
Fname = Dir(FolderName & "*.xls")
'loop through the files
Do While Len(Fname)
With Workbooks.Open(FolderName & Fname)
Dim tbl As ListObject
Dim rng As Range
Set rng = Range(Range("A1"), Range("A1").SpecialCells(xlLastCell))
Set tbl = ActiveSheet.ListObjects.Add(xlSrcRange, rng, , xlYes)
tbl.TableStyle = "TableStyleMedium2"
Columns("A:L").Select
Columns("A:L").EntireColumn.AutoFit
End With
'go to the next file in the folder
Fname = Dir
Loop
End Sub
You are missing the line where you Close the workbook : WB.Close True.
(if you don't want to save the changes made to the workbook use WB.Close False)
Note: you are not setting the Worksheet object on the workbook you open, so by default it will assume the ActiveSheet, which is the last ActiveSheet the last time you saved this workbook.
Try the code below:
Sub LoopThroughFiles()
Dim WB As Workbook
FolderName = "C:\Folder1\"
If Right(FolderName, 1) <> Application.PathSeparator Then FolderName = FolderName & Application.PathSeparator
fname = Dir(FolderName & "*.xls")
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'loop through the files
Do While Len(fname)
Set WB = Workbooks.Open(FolderName & fname) '<-- set the workbook object
With WB
Dim tbl As ListObject
Dim rng As Range
Set rng = Range(Range("A1"), Range("A1").SpecialCells(xlLastCell))
Set tbl = ActiveSheet.ListObjects.Add(xlSrcRange, rng, , xlYes)
tbl.TableStyle = "TableStyleMedium2"
Columns("A:L").Select
Columns("A:L").EntireColumn.AutoFit
End With
WB.Close True ' <-- close workbook and save changes
' go to the next file in the folder
fname = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Excel Macro: Replace formulas and save sheet as own file without changing original document

I have a workbook with a lot of worksheets. I only work on sheets marked with a !. I want to replace all formulas by values and store the sheets as own .xls files. My script is exactly doing that. My problem is that the original document is affected as well. Is there a way to replace the values only on the copied sheet which will be stored so the original document stays the same?
Dim wbk As Workbook
Dim ws As Worksheet
Dim rng As Range
Dim cl As Object
Dim xPath As String
Dim isReadable As Boolean
Dim sName As String
xPath = Application.ActiveWorkbook.Path
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
On Error Resume Next
Set wbk = ActiveWorkbook
For Each ws In wbk.Sheets
isReadable = (InStr(ws.Name, "!")) > 0
If isReadable Then
Debug.Print ws.Name
Set rng = ws.Range("A1").SpecialCells(xlCellTypeFormulas, 23)
If Not (rng Is Nothing) Then
For Each cl In rng
cl.Value = cl.Value
Next cl
End If
sName = Replace(ws.Name, "!", "")
sName = LCase(Replace(sName, "+", ""))
ws.Copy
Application.ActiveWorkbook.SaveAs Filename:=xPath & "\" & sName & ".xlsx", CreateBackup:=False
Application.ActiveWorkbook.Close False
Debug.Print sName
End If
Next ws
Application.Calculate
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
MsgBox "Done, do not save the changes!"
Make a copy of the sheet and work on that:
Sub DoStuff()
Dim wsOrig As Worksheet
Dim wsNew As Worksheet
Dim wbOrig As Workbook
Dim wbNew As Workbook
Set wsOrig = ActiveSheet ' or whatever
Set wbOrig = ActiveWorkbook ' or whatever
For s = 1 To wbOrig.Sheets.Count
If wbOrig.Sheets(s) ' meets my conditions then....
Application.SetWarnings False ' don't question if we want to delete thinsg
Set wbNew = Workbooks.Add
wsOrig.Copy After:=wbNew.Sheets(1)
wbNew.Sheets(1).Delete ' delete the default Sheet1 of the new workbook
Set wsNew = wbNew.Sheets(1)
With wsNew
' do all the stuff I want to do
End With
wbNew.SaveAs ' whatever
Application.SetWarnings True
End If
Next s
End Sub
Here is another way to make the changes only on the copied sheet:
Dim ws As Worksheet, ws2 As Worksheet
For Each ws In Worksheets
If ws.Name Like "*!*" Then
ws.Copy
Set ws2 = Workbooks(Workbooks.Count).Sheets(1) ' newest workbook
ws2.Name = LCase(Replace(Replace(ws.Name, "!", ""), "+", ""))
ws2.UsedRange.Value = ws2.UsedRange.Value
ws2.Parent.SaveAs ws.Parent.Path & "\" & sName & ".xlsx", CreateBackup:=False ' add checks if the file already exist and if path contains illegal characters that are not allowed
ws2.Parent.Close False
End If
Next

Copy value from active sheet to new excel file

I have a work sheet named Final_Sheet, I want to create a button on that sheet and execute the following operation
Select Cell Range A1:D30 and pickup the values from cell only and create a new Excel file and paste the copied cell values into Sheet1 of created excel file. I am able to o this much, further I can't understand what to do can anybody please help me out?
Private Sub Button1_Click()
Dim rownum As Integer
Dim selection As Range
On Error Resume Next
Application.ScreenUpdating = False
Application.DisplayAlerts = False
rownum = InputBox("Row No to Copy :", "OK")
selection = ActiveSheet.Range(Cells(1, 1), Cells(rownum, 10)).Select
selection.Copy
Flname = InputBox("Enter File Name :", "Creating New File...")
MsgBox ("Output File Created Successfully")
If Flname <> "" Then
Set NewWkbk = Workbooks.Add
ThisWorkbook.Sheets(1).Range("D1:D30").Copy Before:=NewWkbk.Sheets(1)
NewWkbk.Sheet(1).Select
Cells(1, 1).Activate
selection.PasteSpecial xlPasteValues
NewWkbk.SaveAs ThisWorkbook.Path & "\" & Flname
ActiveWorkbook.Close
End If
End Sub
The code below should do as you've asked.
EDIT: Pastes values only
Private Sub Button1_Click()
'Dim Variables
Dim ws As Worksheet
Dim rng As Range
Dim wbNew As Workbook, wbCurrent As Workbook
Dim strFileName As String
'Assign object variables
Set wbCurrent = ActiveWorkbook
Set ws = wbCurrent.ActiveSheet
Set rng = ws.Range("A1:D30") 'Amend range if needed
'Get desired file path from user
strFileName = InputBox("Enter File Name: ", "Creating New File...")
If strFileName <> "" Then
'Create new Workbook and paste rng into it
Set wbNew = Workbooks.Add
rng.Copy
wbNew.Sheets(1).Range("A1:D30").PasteSpecial xlValues
'Save new workbook using desired filepath
wbNew.SaveAs wbCurrent.Path & "\" & strFileName
End If
End Sub
It wasn't clear to me from the question which workbook you wished to close with ActiveWorkbook.Close but you could easily add wbNew.Close or wbCurrent.Close below wbNew.SaveAs ... as required.