Copy a template worksheet multiple times in a new workbook with different worksheet names - vba

Trying to complete a VBA routine for the first time.
The goal is :
Use a vertical range of cell that have different names in each cell to create multiples worksheets in one new workbook.
Here's what i got until now :
Sub AddWorksheet()
Dim plage As Range
Dim i As Integer
Dim titre As String
Dim wb As Workbook
Set plage = Range("E6:E24")
Set wb = Workbooks.Add("New Workbook")
For i = 1 To plage.Height
If plage.Cells(i).Value <> "" Then
titre = plage.Cells(i).Value
ActiveWorkbook.Sheets("FeuilleTemplate").Copy After:=wb.Sheets(wb.Sheets.Count)
wb.Sheets(wb.Sheets.Count).Activate
ActiveSheet.Name = titre
End If
Next i
End Sub
Until now the following line is giving me a hard time :
Set wb = Workbooks.add("New Worbook")
The error message is : Error execution '1004' :
The method 'dd' of the object 'Workbooks' has failed.
I'm having a hard time reading and finding the info too for how the methods and class works
I'm use to java.
Thanx for those who gona take time to help me thru this

I think we cannot add a workbook with a specified name as it is not yet saved. So just add workbook do all the operations and in the end save it with the desired name.
Sub AddWorksheet()
Application.DefaultSaveFormat = xlOpenXMLWorkbook
Dim plage As Range
Dim i As Integer
Dim OldBook As Workbook, NewBook As Workbook 'declare both workbooks
Set OldBook = ActiveWorkbook
spath = ThisWorkbook.Path
Set plage = OldBook.Sheets("Sheet Names").Range("E6:E24") 'Assuming that sheet names are in range E6:E24 in "Sheet Names" sheet in old workbook
Set NewBook = Workbooks.Add 'adding new workbook so as to copy the template sheet but this workbook is not saved yet
For i = 1 To plage.Height
If plage.Cells(i).Value <> "" Then 'for each non blank cell in range
OldBook.Sheets("FeuilleTemplate").Copy After:=NewBook.Sheets(NewBook.Sheets.Count) 'Copy "FeuilleTemplate" sheet in workbook after last sheet
NewBook.Sheets("FeuilleTemplate").Name = plage.Cells(i).Value 'Rename the sheet to the desired names from range E6:E24 in "Sheet Names" sheet in old workbook
End If
Next i
With NewBook
.SaveAs Filename:=spath & "\" & "New Workbook with Templates"
.Close SaveChanges:=True
End With
End Sub

Related

Run on the master workbook, check if there are any new or deleted worksheets in the daily input workbook

I am trying to figure out how to do this, any guidance would be great.
Setup: I work between 2 workbooks called Master and Daily Input
The Daily Input file contains 10 worksheets, each worksheet = 1 person's name. + 1 worksheet named "Input Template"
The Master workbook contains a bunch of different worksheets for different calculations. + 9 worksheet with the team member's names.
Assume currently there are 9 people in the team.
When new people join or leave the team, they will open / delete worksheets from the Daily Input workbook.
Therefore I want to:
New Team Member added a new worksheet scenario:
If Daily Input have a worksheet that Master does not (except Input Template), then create a new worksheet in Master with the same name. The new worksheet is copied from Output Template that is already in the Master file.
If Master have a worksheet that Daily Input does not (except a few worksheets for calculation), then just prompt a messagebox.
Currently I have written something that extracts all the sheet names from the Daily Input file, and then put it in the Master File but I am not sure how to make use of that...
Maybe load both sheet name lists into an array and compare?
Sub ObtainNameList()
Application.ScreenUpdating = False
Dim WkBk_Input As Workbook
Dim WkBk_Active As Workbook
Dim GetListFName As String
Dim GetListFPath As String
Dim FName As String
Dim FPath As String
Dim i As Integer
Set WkBk_Active = Application.ActiveWorkbook
FPath = WkBk_Active.Worksheets("Menu").Range("B1")
FName = WkBk_Active.Worksheets("Menu").Range("B2")
Set WkBk_Input = Application.Workbooks.Open(FPath & "\" & FName)
WkBk_Active.Worksheets("NameList").Range("A:A").ClearContents
For i = 1 To WkBk_Input.Sheets.Count
WkBk_Active.Worksheets("NameList").Range("A" & i).Value = WkBk_Input.Sheets(i).Name
Next i
WkBk_Input.Close
Application.ScreenUpdating = True
End Sub
This ought to work, but I'm on my phone so can't actually check it:
Sub CheckandCreate()
Dim Fpath As String
Dim Fname As String
Dim master As Workbook
Set master = ThisWorkbook 'assume running in master
Dim daily As Workbook
'set daily path and name here
Set daily = Workbooks.Open(Fpath & "\" & Fname)
Dim ws As Worksheet
For Each ws In daily.Worksheets
Select Case ws.Name
Case "Input Template" 'add ay other sheet names you want to ignore here
Case Else
If SheetNotExist(ws.Name, master) Then
AddSheet (ws.Name)
End If
End Select
Next ws
daily.Close False 'close daily without saving
End Sub
Function SheetNotExist(sheetname As String, where As Workbook) As Boolean
On Error GoTo nope
Dim ws As Worksheet
Set ws = where.Worksheets(sheetname) 'if sheet exists this will work
SheetNotExist = False
Exit Function
nope:
SheetNotExist = True 'will only get here if sheet doesn't exist
End Function
Sub AddSheet(sheetname As String)
Dim ws As Worksheet
ThisWorkbook.Worksheets("Output Template").Copy _ after:=ThisWorkbook.Worksheets(ThisWorkbook.Sheets.Count) 'copy to end of workbook
Set ws = ThisWorkbook.Worksheets(ThisWorkbook.Sheets.Count) 'new worksheet
ws.Name = sheetname
End Sub

VBA import data: exclude sheet if doesn't exist

I have built this code which import data from a workbook and paste it to another one. The original workbook is composed by hundred of sheets (one sheet for each country, identified by the ISO 2 digit code: AE, AL, AM, AR etc...). The macro is opening each one of these sheets, copying the same cell, and printing all these cells in a new workbook.
The problem is that if, for example, the sheet F(AM) doesn't exists, the macro stops. I would like to make sure that if a sheet doesn't exist, the macro continues with all the other sheets (namely F(AR), F(AT), F(AU)) till the end.
Someone has any suggestion?
Many thanks in advance!
Sub ImportData()
Dim Wb1 As Workbook
Dim MainBook As Workbook
Dim Path As String
Dim SheetName As String
'Specify input data
Path = Worksheets("Input").Range("C6").Value
'Decide in which target sheet print the results
SheetName = "Data"
'From which sheets you need to take the data?
OriginSheet145 = "F(AE)"
OriginSheet146 = "F(AL)"
OriginSheet147 = "F(AM)"
OriginSheet148 = "F(AR)"
OriginSheet149 = "F(AT)"
OriginSheet150 = "F(AU)"
'Set the origin workbook
Set Wb1 = Workbooks.Open(Path & "_20171231.xlsx")
'Set the target workbook
Set MainBook = ThisWorkbook
'Vlookup to identify the correct data point
Wb1.Sheets(OriginSheet145).Range("N25").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet146).Range("N26").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet147).Range("N27").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet148).Range("N28").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet149).Range("N29").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
Wb1.Sheets(OriginSheet150).Range("N30").FormulaR1C1 = "=VLOOKUP(""010"",C[-10]:C[-7],2,FALSE)"
'Copy the data point and paste in the target sheet
Wb1.Sheets(OriginSheet145).Range("N25").Copy
MainBook.Sheets(SheetName).Range("AW5").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet146).Range("N26").Copy
MainBook.Sheets(SheetName).Range("AW6").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet147).Range("N27").Copy
MainBook.Sheets(SheetName).Range("AW7").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet148).Range("N28").Copy
MainBook.Sheets(SheetName).Range("AW8").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet149).Range("N29").Copy
MainBook.Sheets(SheetName).Range("AW9").PasteSpecial xlPasteValues
Wb1.Sheets(OriginSheet150).Range("N30").Copy
MainBook.Save
Wb1.Close savechanges:=False
MsgBox "Data: imported!"
End Sub
This function returns TRUE or FALSE, indicating whether a worksheet named in string wsName exists in workbook object
Function wsExists(wb As Workbook, wsName As String) As Boolean
Dim ws: For Each ws In wb.Sheets
wsExists = (wsName = ws.Name): If wsExists Then Exit For
Next ws
End Function
Us an IF statement to skip the applicable code if the worksheet does not exist.
Edit:
I can tell that you put a lot of work into your code, which is awesome, so don't take it the wrong way when I say it gave me anxiety so I had to simplify it. ...there are a lot of unneeded steps.
I do believe the "right way" is "whatever way works", so kudo's on getting this far. There's a steep learning curve in programming, so I figured I'd offer an alternate code block to replace yours. (The Option Explicit goes at the very top of the module, and will "force" you to properly declare/handle variables, objects, etc.)
Without seeing your data I can't guarantee this will work - in fact it very likely a cell reference wrong somewhere that you'll have to try to figure out - if you choose to use this at all.
Option Explicit
Sub ImportData()
Const SheetName = "Data" 'destination sheet name
Const sourceFile = "_20171231.xlsx" 'source filename for some reason
Dim wbSrc As Workbook, wbDest As Workbook, sht As Variant
Dim stPath As String, arrSourceSht() As Variant, inRow As Long
Set wbDest = ThisWorkbook 'dest wb object
stPath = Worksheets("Input").Range("C6").Value 'source wb stPath
'create array of source sheet names "146-150":
arrSourceSht = Array("F(AE)", "F(AL)", "F(AM)", "F(AR)", "F(AT)", "F(AU)")
Set wbSrc = Workbooks.Open(stPath & sourceFile) 'open source wb
With wbSrc
'VLookup to identify the correct data point
inRow = 5 'current input row
For Each sht In arrSourceSht
If wsExists(wbSrc, CStr(sht)) Then
wbDest.Sheets(sht).Range("AW" & inRow) = Application._
WorksheetFunction.VLookup("010", Range(.Sheets(sht).Range("N" & _
20 + inRow).Offset(-10), .Sheets(sht).Range("N" & 20 + inRow).Offset(-7)), 2, False)
End If
inRow = inRow + 1 'new input row
Next sht
wbDest.Save 'save dest
.Close savechanges:=False 'don't save source
End With
MsgBox "Data: imported!"
End Sub
Function wsExists(wb As Workbook, wsName As String) As Boolean
Dim ws: For Each ws In wb.Sheets
wsExists = (wsName = ws.Name): If wsExists Then Exit For
Next ws
End Function
Let me know if you have any questions, I can walk you through how it works if you like. (I'm on here at least once a day.)

Copy workbook & paste into new workbook

I'm trying to open a workbook FName from a folder and copy a range from it and paste into a new workbook WBNew, but i keep getting error
Subscript out of range or 1004 - Application defined
error.
Any idea why ?
Sub NewNumbers()
Dim FName As Workbook, WBNew As Workbook
Set FName = Workbooks.Open(Range("C3") & "\" & Range("C2"))
Set WBNew = Workbooks.Add
FName.Worksheets("Numbers").Range("U2", Range("U2").End(xlToRight)).Copy
WBNew.Sheets("Sheet1").Paste
End Sub
Copy >> Paste is a 1-line Command, also define a Range in "Sheet1" to paste.
Dim NumbersSht As Worksheet
' set the copied sheet object
Set NumbersSht = FName.Worksheets("Numbers")
With NumbersSht
.Range("U2", .Range("U2").End(xlToRight)).Copy Destination:=WBNew.Sheets("Sheet1").Range("A1") '<--- Modify "A1" to your desired range
End With

Splitting Sheets into Separate Workbooks

I have a workbook with a master sheet for school report cards. I have a macro applied to a button for exporting information from the master sheet to separate, newly-generated sheets in the same workbook. A1:C71 is the template and goes to every new sheet, and the following columns of info, from D1:71 to Q1:71, each appear in separate sheets (always in D1:71).
Here's the screenshot (http://imgur.com/a/ZDOVb), and here's the code:
`Option Explicit
Sub parse_data()
Dim studsSht As Worksheet
Dim cell As Range
Dim stud As Variant
Set studsSht = Worksheets("Input")
With CreateObject("Scripting.Dictionary")
For Each cell In studsSht.Range("D7:Q7").SpecialCells(xlCellTypeConstants, xlTextValues)
.Item(cell.Value) = .Item(cell.Value) & cell.EntireColumn.Address(False, False) & ","
Next
For Each stud In .keys
Intersect(studsSht.UsedRange, studsSht.Range(Left(.Item(stud), Len(.Item(stud)) - 1))).Copy Destination:=GetSheet(CStr(stud)).Range("D1")
Next
End With
studsSht.Activate
End Sub
Function GetSheet(shtName As String) As Worksheet
On Error Resume Next
Set GetSheet = Worksheets(shtName)
If GetSheet Is Nothing Then
Set GetSheet = Sheets.Add(after:=Worksheets(Worksheets.Count))
GetSheet.Name = shtName
Sheets("Input").Range("A1:C71").Copy
GetSheet.Range("A1:D71").PasteSpecial xlAll
GetSheet.Range("A1:B71").EntireColumn.ColumnWidth = 17.57
GetSheet.Range("C1:C71").EntireColumn.ColumnWidth = 54.14
GetSheet.Range("D1:D71").EntireColumn.ColumnWidth = 22
End If
End Function`
I would now like to create a separate button to split the sheets into separate workbooks so that the master sheet can be kept for record keeping and the individual workbooks can be shared with parents online (without divulging the info of any kid to parents other than their own). I would like the workbooks to be saved with the existing name of the sheet, and wonder if there's a way to have the new workbooks automatically saved in the same folder as the original workbook without having to input a path name? (It does not share the same filename as any of the sheets).
I tried finding other code and modifying it, but I just get single blank workbooks and I need as many as have been generated (preferably full of data!), which varies depending on the class size. Here's the pathetic attempt:
`Sub split_Reports()
Dim splitPath As String
Dim w As Workbook
Dim ws As Worksheet
Dim i As Long, j As Long
Dim lastr As Long
Dim wbkName As String
Dim wksName As String
Set wsh = ThisWorkbook.Worksheets(1)
splitPath = "G:\splitWb\"
Set w = Workbooks.Add
For i = 1 To lastr
wbkName = ws
w.Worksheets.Add(After:=w.Worksheets(Worksheets.Count)).Name = ws
w.SaveAs splitPath
w.Close
Set w = Workbooks.Add
Next i
End Sub`
I have learned so much, and yet I know so little.
Maybe this will start you off, just some simple code to save each sheet as a new workbook. You would probably need some check that the sheet name is a valid file name.
Sub x()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets
ws.Copy
ActiveWorkbook.Close SaveChanges:=True, Filename:=ws.Name & ".xlsx"
Next ws
End Sub

merging variable amount of files under matching columns

I have 3 open Excel files which i have opened using this code;
Dim myWorkbooks As New Collection
Sub GetFile()
Dim fNameAndPath As Variant, i As Long, x As Variant
fNameAndPath = Application.GetOpenFilename("All Files (*.*), *.*", , "Select Files To Be Opened", , True)
If Not IsArray(fNameAndPath) Then
If fNameAndPath = False Then Exit Sub Else fNameAndPath = Array (fNameAndPath)
End If
For i = LBound(fNameAndPath) To UBound(fNameAndPath)
Set x = Workbooks.Open(fNameAndPath(i))
myWorkbooks.Add x
Next
End Sub
i merged all the Sheets i Need in one Workbook. There is a mastersheet called "KomKo" in this Workbook. And i have other Sheets which are "data (2)" , "data (3)" and "data(4)". These Sheets can be more then 4 so i might have Sheets called "data(11) " and so on. I would like to be able to copy Column C of all "data" Sheets and paste it to Column A of "KomKo" Sheet. i should be able to paste These values to the next empty value of that Column A.
How can i do this ?
So, after you have corrected your question, this code should do the desired work:
Dim masterSheet As Worksheet
Set masterSheet = Sheets("Komko")
'Variable to save the used Range of the master sheet
Dim usedRangeMaster As Integer
Dim ws As Worksheet
'loop through each worksheet in current workbook
For Each ws In Worksheets
'If sheetname contains "data" (UCase casts the Name to upper case letters)
If InStr(1, UCase(ws.Name), "DATA", vbTextCompare) > 0 Then
'calculate the used range of the master sheet
usedRangeMaster = masterSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row + 1
'Variable to save the used Range of the sub sheet
Dim usedRangeSub As Integer
'calculate the used range of the sub sheet
usedRangeSub = ws.UsedRange.SpecialCells(xlCellTypeLastCell).Row
'copy relevant range from the subsheet
ws.Range("C1:C" & usedRangeSub).Copy
'paste the copied range after the used range in column a
masterSheet.Range("A" & usedRangeMaster).PasteSpecial
End If
Next ws
Since you already have a collection containing the relevant workbooks, you can just loop through these and copy the relevant stuff into your main wb.
So define a variable for the master sheet(to be able to refer to it)
And one Variable inside the loop which holds the "subsheet":
Dim mastersheet As Workbook
Set mastersheet = ThisWorkbook 'Assuming the code is inside the master sheet
Dim wb As Workbook
For Each wb In myWorkbooks
'Copy stuff
'Example to get a value from the "subsheet"
mastersheet.Sheets("sheet1").Cells(1, 1).Value = wb.Sheets("sheet1").Cells(1, 1)
Next wb
Then inside the loop, copy column c for example and paste it into column a of the master sheet:
wb.Sheets("sheet1").Range("C1").EntireColumn.Copy
mastersheet.Sheets("sheet1").Range("A1").PasteSpecial