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

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

Related

Loop inserting worksheet name in column - mismatch error

Trying to do the following
1- Open directory with multiple workbooks (Origins), copy/paste
each worksheet into Master workbook (Destin)
2- insert in Columns 'A' in Master worksheet (Destin) with the name of each worksheet from dir (Origin) - the worksheets name contain the date
3- Finally, consolidate all worksheets in Master workbook (Destin) into 'Summary' sheet by copy/paste each
worksheet below the other (i.e. database format)
got step-1 to work....stuck now (step-2 mismatch error)
Option Explicit
Sub AllFiles()
'Application.EnableCancelKey = xlDisabled
Application.DisplayAlerts = True
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 lastrow As Long
' set master workbook
Set Masterwb = Workbooks("masterbook_AAFC.xlsm")
folderPath = "C:\Users\axchilmeran.G3NETWORK\Downloads\Master_AAFC\" 'contains folder path
If Right(folderPath, 1) <> "\" Then folderPath = folderPath & "\"
Filename = Dir(folderPath & "*.csv*")
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, ".pdf.csv", "")
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("B" & PasteRow).PasteSpecial xlPasteValues
these 2 lines below giving me mismatch error!
**lastrow = NewSht.UsedRange.Rows(NewSht.UsedRange.Rows.Count).Row
Worksheets(NewSht).Range("A2:A" & lastrow).Value = NewSht.Name**
Next sh
wb.Application.CutCopyMode = False
wb.Close False
Exit_Loop:
Set wb = Nothing
Filename = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
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

Splitting an identified range of spreadsheets to a new workbook with a new name

I've been trying to come up with a way to split a workbook into separate workbooks based on identified worksheets in the workbook.
For example:
Say I had a worksheet for every letter in the alphabet.
I would want to split worksheets A through C into a new workbook named "A through C."
D through I will go into a new workbook named "D through I."
etc...
My idea would be to first insert a worksheet that in column A names the new workbook it will become and Columns b through as many columns as there are will the names of the worksheets to be copied into the new workbook.
Does anyone have an idea of how to make a macro for this? I've tried myself but have been unsuccessful.
Thank you!
I found this Macro out there. Does anyone think it can be modified to work?
Sub Test()
Dim Sh As Worksheet
Dim Rng As Range
Dim c As Range
Dim List As New Collection
Dim Item As Variant
Dim WB As Workbook
Application.ScreenUpdating = False
Set Sh = Worksheets("Sheet1")
Set Rng = Sh.Range("A2:A" & Sh.Range("A65536").End(xlUp).Row)
On Error Resume Next
For Each c In Rng
List.Add c.Value, CStr(c.Value)
Next c
On Error GoTo 0
Set Rng = Sh.Range("A1:H" & Sh.Range("A65536").End(xlUp).Row)
For Each Item In List
Set WB = Workbooks.Add
Rng.AutoFilter Field:=1, Criteria1:=Item
Rng.SpecialCells(xlCellTypeVisible).Copy WB.Worksheets(1).Range("A1")
Rng.AutoFilter
With WB
.SaveAs ThisWorkbook.Path & "\" & Item & ".xls"
.Close
End With
Next Item
Sh.Activate
Application.ScreenUpdating = True
End Sub
The following code assumes you have your control sheet (named "Split Parameters") in the workbook containing the macro, and it is set out with the desired filenames in column A, and the sheets that you wish to copy into that file (from the ActiveWorkbook, which might, or might not, be the one containing the macro) listed in columns B, C, etc. Row 1 is assumed to be headings, and is therefore ignored.
Sub SplitBook()
Dim lastRow As Long
Dim LastColumn As Long
Dim srcWB As Workbook
Dim newWB As Workbook
Dim i As Long
Dim c As Long
Dim XPath As String
Dim newName As String
Dim sheetName As String
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set srcWB = ActiveWorkbook
XPath = srcWB.Path
With ThisWorkbook.Worksheets("Split Parameters")
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
'Take the first worksheet and create a new workbook
sheetName = .Cells(i, "B").Value
srcWB.Sheets(sheetName).Copy
Set newWB = ActiveWorkbook
'Now process all the other sheets that need to go into this workbook
LastColumn = .Cells(i, .Columns.Count).End(xlToLeft).Column
For c = 3 To LastColumn
sheetName = .Cells(i, c).Value
srcWB.Sheets(sheetname).Copy After:=newWB.Sheets(newWb.Sheets.Count)
Next
'Save the new workbook
newName = .Cells(i, "A").Value
newWB.SaveAs Filename:=xPath & "\" & newName & ".xls", FileFormat:=xlExcel8
newWB.Close False
Next
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub

How to get my macro working on other excel sheets

I pulled this code online, I am a noob, but I have made some changes to the looping. Please help me out! I want to get this macro working on other sheets, saved to the macro ribbon. I've added it as an Add-In, checked security settings, checked tools>references. The problem is if I save it as a module under the excel file I want to split, it works, but if I save it in a blank sheet and pull it as a macro, which is my goal for my team to use, the macro pulls the blank original sheet and breaks the master in half; leaving the active sheet untouched.
Sub Macrosplittest()
Dim Sht As Worksheet
Dim fName As String
Dim ShtCountBk1 As Integer
Dim ws As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
ShtCountBk1 = IIf(ActiveWorkbook.Sheets.Count Mod 2 = 1, Sheets.Count
/ 2 + 0.5, Sheets.Count / 2)
Set neww = Workbooks.Add
For Each Sht In ActiveWorkbook.Worksheets
i = i + 1
If i > ShtCountBk1 Then
fName = Replace(ThisWorkbook.Name, ".xls", "")
neww.SaveAs ThisWorkbook.Path & "\" & fName & " (1).xls"
Set neww = Workbooks.Add
i = 1
End If
Sht.Copy after:=Worksheets(neww.Sheets.Count)
If i = 1 Then
For Each ws In Worksheets
If ws.Name <> Sht.Name Then
ws.Delete
End If
Next ws
End If
Next Sht
fName = Replace(ThisWorkbook.Name, ".xls", "")
neww.SaveAs ThisWorkbook.Path & "\" & fName & " (2).xls"
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Try this, I think I see what you are trying to do:
Sub Macrosplittest()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim Sht As Worksheet
Dim fName As String
Dim ShtCountBk1 As Integer
Dim ws As Worksheet
Dim wbActive as Workbook
Dim newBook as Workbook
Dim lHolder as Long
Dim sHolder as String
Dim i as Long
Set wbActive = ActiveWorkbook
lHolder = wbActive.Sheets.Count
If lHolder Mod 2 = 1 Then
' This should evaluate just fine without parentheses, but I
' prefer to have the parentheses to make the code clear
ShtCountBk1 = (lHolder / 2) + .05
Else
ShtCountBk1 = lHolder / 2
End IF
Set newBook = Workbooks.Add
For Each Sht In wbActive.Worksheets
i = i + 1
Sht.Name = "SHT-" & Sht.Name
sHolder = Sht.Name
If i > ShtCountBk1 Then
fName = Replace(wbActive.Name, ".xls", "")
newBook.SaveAs wbActive.Path & "\" & fName & " (1).xls"
Set newBook= Workbooks.Add
i = 1
End If
Sht.Copy after:=Worksheets(newBook.Sheets.Count)
If i = 1 Then
For Each ws In Worksheets
If ws.Name <> sHolder Then
ws.Delete
End If
Next ws
End If
Next Sht
fName = Replace(wbActive.Name, ".xls", "")
newBook.SaveAs wbActive.Path & "\" & fName & " (2).xls"
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
I have made some modifications to make your code easier to read, and to make it properly refer to the workbooks you are targeting. It is best to avoid ActiveWorkbook since this can result in errors. Also, ThisWorkbook will refer to the workbook running the code. I am not sure if this will properly refer to the activeworkbook when ThisWorkbook is called by a add-in, but it is best to err on the side of caution.

Excel Sheet Name Error

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