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

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

Related

Loop & Search for Matching Worksheets in Separate Wkbks; Add Wksht if No Match Found

I have a series of workbooks by District, Territory, and Period that have monthly sales data for each combination of District, Territory, and Period. There is a master workbook for each District containing separate worksheets for each Territory. The monthly data appears in columns B:M.
I need to open each of the monthly District, Territory, and Period files, open the corresponding District's master workbook, search for a corresponding Territory, and paste that month's data in the column associated with that month (e.g., Feb. data is pasted in column C). This should be followed by closing the monthly file and loop to the next monthly file.
However, I need to have code for the possibility that a NEW Territory is added to a District in midyear--sometime after that District's master workbook was initially created.
The loop as written wants to jump from the open monthly file to the next part of the loop code that would create a new worksheet, but that is not what is needed.
Any suggestions for fixing this? Here is what I have so far:
Sub DSMReportsP02()
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim DistrictDSM As Range, DistrictsDSMList As Range
Dim Period As String, Path As String, DistPeriodFile As String, Territory As String
Dim YYYY As Variant
Dim WBMaster As Workbook, DistMaster As Workbook, CurDstTerrFile As Workbook
Dim wsCount As Integer, x As Integer
Dim wsExists As Boolean
Set DistrictsDSMList = Range("E11:E" & Cells(Rows.Count, "E").End(xlUp).Row)
Set WBMaster = ActiveWorkbook
Period = Range("C6").Value
YYYY = Range("C8").Value
wsExists = False
For Each DistrictDSM In DistrictsDSMList.Cells
Workbooks.Open Filename:="H:\Accounting\Monthend " & YYYY & "\DSM Files\DSM Master Reports\" & DistrictDSM & ".xlsx"
Set DistMaster = ActiveWorkbook
wsCount = Application.Sheets.Count
Path = "H:\Accounting\Monthend " & YYYY & "\DSM Files\" & DistrictDSM & "\P02"
DistPeriodFile = Dir(Path & "\*.xlsx")
Do While DistPeriodFile <> ""
Workbooks.Open Filename:=Path & "\" & DistPeriodFile, UpdateLinks:=False
DistPeriodFile = Dir
Set CurDstTerrFile = ActiveWorkbook
Territory = CurDstTerrFile.Sheets("Index").Range("A3").Value
For x = 1 To wsCount
If DistMaster.Worksheets(x).name = Territory Then
CurDstTerrFile.Sheets("Index").Range("F20").Copy 'PM
DistMaster.Sheets(Territory).Activate
Range("C3").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("J20").Copy 'XRA
DistMaster.Sheets(Territory).Activate
Range("C5").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("N20").Copy 'CO-OP
DistMaster.Sheets(Territory).Activate
Range("C7").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("S20").Copy 'VR
DistMaster.Sheets(Territory).Activate
Range("C9").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("W20").Copy 'OVER & ABOVE
DistMaster.Sheets(Territory).Activate
Range("C11").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("AA20").Copy 'SS
DistMaster.Sheets(Territory).Activate
Range("C13").PasteSpecial Paste:=xlPasteValues
CurDstTerrFile.Sheets("Index").Range("A3:D19").Copy 'COPY BTs by DISTRICT
WBMaster.Sheets("BTs by District").Activate
Range("A1000000").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
Exit For
End If
Next x
If wsExists = False Then '***********FIX THIS SECTION!!!*************************
Worksheets.Add after:=DistMaster.Worksheets(Worksheets.Count)
CurDstTerrFile.Sheets("Index").Range("A3").Copy 'COPY TERRITORY
ActiveSheet.name = "New Territory"
DistMaster.Sheets(Territory).Activate
Range("A1").PasteSpecial Paste:=xlPasteValues
End If
Dim WS As Worksheet, SheetXXX As Worksheet
Set WS = WBMaster.Sheets("ReptTemplate")
WS.Copy after:=Sheets(WBMaster.Sheets.Count)
Set SheetXXX = ActiveWorkbook.ActiveSheet
SheetXXX.name = Worksheets("ReptTemplate").Range("A1").Value
CurDstTerrFile.Close
Loop
Dim DistWS As Worksheet
Dim DistName As String
Dim wbNew As Workbook
DistName = Left(DistrictDSM, 6) & "*"
Set wbNew = Application.Workbooks.Add
For Each DistWS In WBMaster.Sheets
If DistWS.name Like DistName Then DistWS.Move after:=Sheets(wbNew.Sheets.Count)
Next DistWS
With wbNew
.SaveAs "H:\Accounting\Monthend " & YYYY & "\DSM Files\DSM Master Reports\" & DistrictDSM & ".xlsx"
.Close
End With
Next DistrictDSM
Application.EnableEvents = True
End Sub
I am sorry but I cannot comment (not enough reputation to comment on questions) or otherwise I would have asked a few question before posting this.
From what I understood. What you need is a logic/algorithm that checks whether a new sheet (new territory) is required be added to the master file before starting the copying process to the master file. If a sheet needs to be added, it should be added at the end of the master file.
The code below is a general code, but you should be able to tweak it easily to fit your purpose. The code below compares the worksheets in wb2 with wb1. if a sheet name in wb2 does not exist in wb1 it will be added to a new sheet at the end of wb1 with a name similar to the one in wb2.
This code should be placed immediately after both files are opened.
Sub Comapre_Sheets()
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim wks1 As Worksheet
Dim wks2 As Worksheet
Dim bWorkSheet_Found As Boolean
Set wb1 = Workbooks("Book1") ''' Change this to the master file
Set wb2 = Workbooks("Book2") ''' Change this to the file that might have the new sheet/territory
For Each wks2 In wb2.Worksheets
bWorkSheet_Found = False
For Each wks1 In wb1.Worksheets
If wks1.name = wks2.name Then
bWorkSheet_Found = True
End If
Next wks1
If Not bWorkSheet_Found Then
wb1.Worksheets.Add(After:=Worksheets(wb1.Sheets.Count)).name = wks2.name
End If
Next wks2
End Sub
Hope this helps you

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

How to import excel data into new workbook?

I am trying to combine multiple excel files into one file. I am able to do that correctly, but the location I want to place the data is running into a small problem.
I want my data to start (paste) at cell A2 under the header row, but since my sheet is formatted as a table with a named range, my data is pasted just below the last line of that blank table. This is the code I'm using to paste the data.
Sub CombineFiles()
Dim path As String, ThisWB As String, lngFilecounter As Long
Dim wbDest As Workbook, shtDest As Worksheet, ws As Worksheet
Dim Filename As String, Wkb As Workbook
Dim CopyRng As Range, Dest As Range
Dim RowofCopySheet As Integer
ThisWB = ActiveWorkbook.Name
path = "C:\MyFolder"
RowofCopySheet = 2
Application.EnableEvents = False
Application.ScreenUpdating = False
Set shtDest = ActiveWorkbook.Sheets("Import")
Range("A2").Select
Filename = Dir(path & "\*.xl??", vbNormal)
If Len(Filename) = 0 Then Exit Sub
Do Until Filename = vbNullString
If Not Filename = ThisWB Then
Set Wkb = Workbooks.Open(Filename:=path & "\" & Filename)
Set CopyRng = Wkb.Sheets(1).Range(Cells(RowofCopySheet, 1), Cells(Cells(Rows.Count, 1).End(xlUp).Row, Cells(1, Columns.Count).End(xlToLeft).Column))
Set Dest = shtDest.Range("A" & shtDest.Cells(Rows.Count, 1).End(xlUp).Row + 1)
CopyRng.Copy
Dest.PasteSpecial xlPasteFormats
Dest.PasteSpecial xlPasteValuesAndNumberFormats
Application.CutCopyMode = False 'Clear Clipboard
Wkb.Close False
End If
Filename = Dir()
Loop
Sheets("Import").Select
Range("A1").Select
End Sub
Is there any change I can make to the code or the contents of the cells in the table to allow this to work correctly? Thanks for the help!
Please try this after changing range to your requirements. It will paste from A2. Using the clipboard takes time and resources so the best way would be to avoid a copy and paste and just set the values equal to what you want.Though you have mentioned that data transfer is required between separate workbooks but mentioned code for only basic problem, so this code fragment conveys the basic concept for transfer in a situation where there is a named table involved.
Sub Normalize()
Dim CopyFrom As Range
Set CopyFrom = Sheets("Sheet2").Range("A2", [H30])
Sheets("Sheet1").Range("A1").Resize(CopyFrom.Rows.Count).Value = CopyFrom.Value
End Sub

Import data from different Workbooks VBA

I have a code see below to import data from different workbooks inside one folder. I try it and it works perfectly however I was wondering if someone could help me to improve it.
I explain: "zmaster.xlms" workbook is the one where all data are past in sheet one. In this same workbook in sheet2 i have a table like this:
Where the column "Excel Column code" is where the data should be past (in the "zmaster.xlms") and "Form Cell Code" correspond to the cells which should be copy from every workbooks (which are in the same file in my desktop).
Question: How To say to the macro to look at the table and copy the cell K26 and past it in the columnA of the zmaster file and loop until the end of the table?
Dim MyFile As String
Dim erow
Dim Filepath As String
Filepath = "C:\Desktop\New folder\"
MyFile = Dir(Filepath)
Do While Len(MyFile) > 0
If MyFile = "zmaster.xlsm" Then
Exit Sub
End If
Workbooks.Open (Filepath & MyFile)
' Range("A1:D1").Copy
ActiveWorkbook.Close
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Paste Destination:=Worksheets("Sheet1").Range(Cells(erow, 1), Cells(erow, 4))
MyFile = Dir
Loop
End Sub
Thank you in advance for your help!
All you need to do is to loop through the cells in sheet 2 (zmaster.xlsm). Have a look at example code. Please, read comments.
[EDIT]
Code has been updated!
Option Explicit
'assuming that:
'- "Excel Column Code" is in column A
'- "Form Cell Code" is in column B
'in zmaster.xlsm!Sheet2
Sub UpdateData()
Dim sFile As String, sPath As String
Dim srcWbk As Workbook, dstWbk As Workbook
Dim srcWsh As Worksheet, dstWsh As Worksheet, infoWsh As Worksheet
Dim i As Long, j As Long, k As Long
On Error GoTo Err_UpdateData
Set dstWbk = ThisWorkbook
Set dstWsh = dstWbk.Worksheets("Sheet1")
Set infoWsh = dstWbk.Worksheets("Sheet2")
sPath = "C:\Desktop\New folder\"
sFile = Dir(sPath)
Do While Len(sFile) > 0
If sFile = "zmaster.xlsm" Then
GoTo SkipNext
End If
Set srcWbk = Workbooks.Open(sPath & sFile)
Set srcWsh = srcWbk.Worksheets(1)
i = 2
'loop through the information about copy-paste method
Do While infoWsh.Range("A" & i) <> ""
'get first empty row, use "Excel Column Code" to get column name
j = GetFirstEmpty(dstWsh, infoWsh.Range("A" & i))
'copy data from source sheet to the destination sheet
'use "Form Cell Code" to define destination cell
srcWsh.Range(infoWsh.Range("B" & i)).Copy dstWsh.Range(infoWsh.Range("A" & i) & j)
i = i + 1
Loop
srcwbk.Close SaveChanges:=False
SkipNext:
sFile = Dir
Loop
Exit_UpdateData:
On Error Resume Next
Set srcWsh = Nothing
Set dstWsh = Nothing
Set srcWbk = Nothing
Set dstWbk = Nothing
Exit Sub
Err_UpdateData:
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_UpdateData
End Sub
'returns first empty row in a destination sheet based on column name
Function GetFirstEmpty(ByVal wsh As Worksheet, Optional ByVal sCol As String = "A") As Long
GetFirstEmpty = wsh.Range(sCol & wsh.Rows.Count).End(xlUp).Row + 1
End Function
At the moment you code
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Paste Destination:=Worksheets("Sheet1").Range(Cells(erow, 1), Cells(erow, 4))
is simply copying columns A to D of the first row of data in the source worksheet to a new row in the destination worksheet.
I'm assuming that you still want to create a new single row, but that you want the table on sheet2 to define which cells are put into which column of the new row.
you need to write something like this (which is untested):
Sub YourCode()
Dim MyFile As String
Dim erow
Dim Filepath As String
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim wsDestination As Worksheet
Dim rngMapping As Range
Dim DestinationRow As Long
Dim cell As Range
Filepath = "C:\Desktop\New folder\"
MyFile = Dir(Filepath)
Set wsDestination = ActiveWorkbook.Sheet1
' Named range "MappingTableFirstColumn" is defined as having the first column in the sheet2 table and all the rows of the table.
Set rngMapping = ActiveWorkbook.Names("MappingTable").RefersToRange
Do While Len(MyFile) > 0
If MyFile = "zmaster.xlsm" Then
Exit Sub
End If
Set wbSource = Workbooks.Open(Filepath & MyFile)
Set wsSource = wbSource.Sheets("Sheet1")
DestinationRow = wsDestination.Cells(wsDestination.Rows.Count, 1).End(xlUp).Offset(1, 0).Row
For Each cell In rngMapping
wsDestination.Range(cell.Value & DestinationRow) = wsSource.Range(cell.Offset(0, 1)).Value
Next cell
MyFile = Dir
Loop
ActiveWorkbook.Close
End Sub

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.