I have VBA code which creates a new workbook based on a template and saves it with a name based on a list.
I only want the code to create the workbooks IF a statement is true.
See following example:
Sheet "MC_TestSheetGenerator"
The macro ONE_CreateTestsheetWB_TEST_NEW_INST_01 creates new workbooks based on a template called "TEST-NEW-INST-01" and saves the file with the name in col "I" of "MC_TestSheetGenerator".
How can I only do that if the adjacent cell H equals "TEST-NEW-INST-01"?
In this example it should only create two new workbooks as the value is only present in row 3 and 8.
Sub ONE_CreateTestsheetWB_TEST_NEW_INST_01()
Application.DisplayAlerts = False
Dim wb As Workbook, sh1 As Worksheet, lr As Long, rng As Range
Set sh1 = Sheets("MC_TestSheetGenerator") 'Edit sheet name
lr = sh1.Cells(Rows.Count, "I").End(xlUp).Row
Set rng = sh1.Range("I3:I" & lr)
For Each c In rng
Sheets("TEST-NEW-INST-01").Copy 'Edit sheet name
Set wb = ActiveWorkbook
wb.Sheets(1).Range("A3") = c.Value
wb.SaveAs ThisWorkbook.Path & "\" & c.Value & ".xlsx", 51
wb.Close False
Application.DisplayAlerts = True
Next
End Sub
Inside your For loop just add an If statement using property OFFSET :
For Each c In Rng
If c.Offset(0, -1).Value = "TEST-NEW-INST-01" Then
Sheets("TEST-NEW-INST-01").Copy 'Edit sheet name
Set wb = ActiveWorkbook
wb.Sheets(1).Range("A3") = c.Value
wb.SaveAs ThisWorkbook.Path & "\" & c.Value & ".xlsx", 51
wb.Close False
Application.DisplayAlerts = True
End If
Next
Range.Offset property
(Excel)
Also, as advice, I'm pretty sure your Application.DisplayAlerts = True could be outside of the loop.
OFFSET property will be the easiest way to introduce it in your code OR you can change the loop type and loop directly in that column and check the condition after.
Also, I agree with #Foxfire And Burns And Burns, the Application.DisplayAlerts = True should be set outside the loop, preferably at the end of the code/sub.
I have revamped your code, please have a look:
Sub ONE_CreateTestsheetWB_TEST_NEW_INST_01()
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim wb As Workbook, wbnew As Workbook
Dim sh1 As Worksheet, lr As Long, rng As Range
Set wb = ThisWorkbook
Set sh1 = wb.Sheets("MC_TestSheetGenerator")
lr = sh1.Cells(Rows.Count, "I").End(xlUp).Row
For i = 3 To lr
If sh1.Range("H" & i).Value2 = "TEST-NEW-INST-01" Then
Set wbnew = Workbooks.Add
wb.Sheets("TEST-NEW-INST-01").Copy Before:=wbnew.Sheets(1)
wbnew.SaveAs wb.Path & "\" & sh1.Range("I" & i).Value2, FileFormat:=51
wbnew.Close
End If
Next i
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Related
I am trying to make a macro where I separate my tabs (one from each client) into new excel files and then also filter, copy and paste (from a sheet called database) in each of those excel files just created the informations regarding each client.
When I try to run the code, it separate the tabs just as expected, but it does not copy and paste the information from my database sheet. I got the following error: "Application-defined or object-definied error" for the line "For Each x In Workbk.Sheets(sht).Range([AA2], Cells(Rows.Count, "AA").End(xlUp))"
How can I fix it?
Sub Separar_guias()
Dim xPath As String
xPath = Application.ActiveWorkbook.Path
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In ThisWorkbook.Sheets
xWs.Copy
Application.ActiveWorkbook.SaveAs Filename:=xPath & "\" & xWs.Name & ".xlsx"
Application.ActiveWorkbook.Close False
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Sub filter()
Application.ScreenUpdating = False
Dim x As Range
Dim rng As Range
Dim rng1 As Range
Dim last As Long
Dim sht As String
Dim newBook As Excel.Workbook
Dim Workbk As Excel.Workbook
'Specify sheet name in which the data is stored
sht = "database"
'Workbook where VBA code resides
Set Workbk = ThisWorkbook
'change filter column in the following code
last = Workbk.Sheets(sht).Cells(Rows.Count, "AA").End(xlUp).Row
With Workbk.Sheets(sht)
Set rng = .Range("A1:T" & last)
End With
Workbk.Sheets(sht).Range("AA1:AA" & last).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("AA1"), Unique:=True
' Loop through unique values in column
For Each x In Workbk.Sheets(sht).Range([AA2], Cells(Rows.Count, "AA").End(xlUp))
With rng
.AutoFilter
.AutoFilter Field:=27, Criteria1:=x.Value
.SpecialCells(xlCellTypeVisible).Copy
'Add New Workbook in loop
Set newBook = Workbooks.Add(xlWBATWorksheet)
newBook.Sheets.Add(After:=Sheets(Sheets.Count)).Name = x.Value
newBook.Activate
ActiveSheet.Paste
End With
'Save new workbook
newBook.SaveAs x.Value & ".xlsx"
'Close workbook
newBook.Close SaveChanges:=False
Next x
' Turn off filter
Workbk.Sheets(sht).AutoFilterMode = False
With Application
.CutCopyMode = False
.ScreenUpdating = True
End With
End Sub
I'm looping through a Scripting Dictionary and call a function that loads specific filtered and sorted datasets to a sheet named "DonneesFiltrees".
I want to create a single workbook and through this loop add Sheets to the new workbook and copy paste "DonneesFiltrees" dataset into each sheets.
There is my code at this moment, my loop and function are working great but I have no clue about how to insert multiple sheet to a new workbook
Set wsData = Worksheets("DonneesFiltrees")
Application.ScreenUpdating = False
Dim varkey As Variant
'ActiveWorkbook.SaveAs (ThisWorkbook.Path & "\data_output\export_du_" & Format(Now(), "DD-MMM-YYYY hh mm AMPM") & ".xlsx")
For Each varkey In DicTheme.Keys
Call ChargerLesDonnees(CStr(DicTheme(varkey)), Me.listEntreprise.Value)
If wsData.Range("A2").Value <> "" Then
'Create sheet into new Workbook,
'Set DicTheme(varkey) as sheet name,
'copy paste wsData sheet dataset into this new sheet.
End If
Next varkey
Application.ScreenUpdating = True
Thank you in advance for your help.
Please have a look at the modified code of yours
Set wsData = Worksheets("DonneesFiltrees")
Application.ScreenUpdating = False
Dim varkey As Variant
'ActiveWorkbook.SaveAs (ThisWorkbook.Path & "\data_output\export_du_" & Format(Now(), "DD-MMM-YYYY hh mm AMPM") & ".xlsx")
' Create a new workbook
Dim wkb As Workbook
Set wkb = Workbooks.Add
For Each varkey In DicTheme.Keys
Call ChargerLesDonnees(CStr(DicTheme(varkey)), Me.listEntreprise.Value)
If wsData.Range("A2").Value <> "" Then
'Create sheet into new Workbook,
Dim wks As Worksheet ' no harm if one puts the declartion in the loop
Set wks = wkb.Worksheets.Add
'Set DicTheme(varkey) as sheet name,
wks.Name = DicTheme(varkey) ' DicTheme(varkey) should be a valid sheet name
'copy paste wsData sheet dataset into this new sheet.
End If
Next varkey
Application.ScreenUpdating = True
Further reading
Workbooks Add
Worsheets Add
Thanks a lot for bringing help, here is the final code in case it can interest people. As the workbook is created with a default worksheet I'm deleting it at the end before to set a name and save the file.
Set wsData = Worksheets("DonneesFiltrees")
Application.ScreenUpdating = False
Dim varkey As Variant
' Create a new workbook
Dim wkb As Workbook
Set wkb = Workbooks.Add
ThisWorkbook.Activate
For Each varkey In DicTheme.Keys
Call ChargerLesDonnees(CStr(DicTheme(varkey)), Me.listEntreprise.Value)
If wsData.Range("A2").Value <> "" Then
'Create sheet into new Workbook,
Dim wks As Worksheet ' no harm if one puts the declartion in the loop
Set wks = wkb.Worksheets.Add
'Set DicTheme(varkey) as sheet name,
wks.Name = DicTheme(varkey) ' DicTheme(varkey) should be a valid sheet name
'copy paste wsData sheet dataset into this new sheet.
wsData.Visible = xlSheetVisible
wsData.ListObjects(1).HeaderRowRange.Copy Destination:=wks.Range("A1")
wsData.ListObjects(1).DataBodyRange.Copy Destination:=wks.Range("A2")
wsData.Visible = xlSheetHidden
End If
Next varkey
Application.DisplayAlerts = False
wkb.Sheets("Feuil1").Delete
Application.DisplayAlerts = True
wkb.SaveAs (ThisWorkbook.Path & "\data_output\export_GLOBAL_de_" & Me.listEntreprise.Value & "_du_" & Format(Now(), "DD-MMM-YYYY hh mm AMPM") & ".xlsx")
wkb.Close
ThisWorkbook.Activate
wsData.Cells.Clear
Application.ScreenUpdating = True
This script loops through each value within a filtered column with the aim of filtering one by one, copy the data, create a new workbook, paste it and save it.
It it now creating a signle new workbook with all the worksheets, instead of one workbook per worksheet.
Can someone point out how can I mend the code to create one workbook per value filtered?
On the other hand, the workbook is also keeping the original sheet1. I am also looking on how to remove it, but thought it would be importat to let you know.
Sub test()
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
' -------------------
Dim x As Range
Dim rng As Range
Dim rng1 As Range
Dim last As Long
Dim sht As String
Dim newBook As Excel.Workbook
Dim Workbk As Excel.Workbook
Dim ws As Worksheet
'Specify sheet name in which the data is stored
sht = "Report"
'Workbook where VBA code resides
Set Workbk = ThisWorkbook
'New Workbook
Set newBook = Workbooks.Add(xlWBATWorksheet)
Workbk.Activate
Set ws = Workbk.Worksheets(sht)
'change filter column in the following code
last = ws.Cells(Rows.Count, "BR").End(xlUp).Row
With ws
Set rng = .Range("A1:BR" & last)
End With
ws.Range("G1:G" & last).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("BT1"), Unique:=True
For Each x In ws.Range([BT2], Cells(Rows.Count, "BT").End(xlUp))
With rng
.AutoFilter
.AutoFilter Field:=7, Criteria1:=x.Value
.SpecialCells(xlCellTypeVisible).Copy
newBook.Sheets.Add(After:=newBook.Sheets(newBook.Sheets.Count)).Name = x.Value
newBook.Activate
ActiveSheet.Paste
End With
Next x
' Turn off filter
ws.AutoFilterMode = False
With Application
.CutCopyMode = False
.ScreenUpdating = True
End With
' -------------------
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox "Check."
End Sub ```
Put the Workbooks.Add line inside the loop.
Option Explicit
Sub test()
Dim wb As Workbook, wbNew As Workbook
Dim ws As Worksheet, wsNew As Worksheet
Dim rng As Range, cel As Range
Dim iLastRow As Long, iLastRowBT As Long
Dim folder As String
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
'Workbook where VBA code resides
Set wb = ThisWorkbook
Set ws = wb.Sheets("Report")
folder = wb.Path & "\"
With ws
'change filter column in the following code
iLastRow = .Cells(Rows.Count, "BR").End(xlUp).Row
.Range("BT:BT").Clear
.Range("G1:G" & iLastRow).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=Range("BT1"), Unique:=True
Set rng = .Range("A1:BR" & iLastRow)
iLastRowBT = .Cells(Rows.Count, "BT").End(xlUp).Row
End With
' create workbooks
For Each cel In ws.Range("BT2:BT" & iLastRowBT)
' Open New Workbook
Set wbNew = Workbooks.Add(xlWBATWorksheet)
Set wsNew = wbNew.Sheets(1)
wsNew.Name = cel.Value
' filter and copy data
With rng
.AutoFilter
.AutoFilter Field:=7, Criteria1:=cel.Value
.SpecialCells(xlCellTypeVisible).Copy
End With
' paste and save
wsNew.Paste
wbNew.SaveAs folder & cel.Value & ".xlsx"
wbNew.Close SaveChanges:=False
Next
' Turn off filter
ws.AutoFilterMode = False
With Application
.CutCopyMode = False
.ScreenUpdating = True
.DisplayAlerts = True
.EnableEvents = True
End With
MsgBox iLastRowBT - 1 & " Workbooks created in " & folder, vbInformation
End Sub
I'm using the following code to copy from an excel file starting with "Backorder Details":
Sub INSERT()
Dim Wb1 As Workbook, wb2 As Workbook, wB As Workbook
Dim rngToCopy As Range
Dim countEND As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Sheets("RAW_DATA").Select
Worksheets("RAW_DATA").Range("A3:CA45000").ClearContents
If ActiveSheet.AutoFilterMode Then ActiveSheet.AutoFilter.ShowAllData
For Each wB In Application.Workbooks
If Left(wB.Name, 17) = "Backorders Detail" Then
Set Wb1 = wB
Exit For
End If
Next
If Not Wb1 Is Nothing Then
Set wb2 = ThisWorkbook
With Wb1.Sheets(2)
Set rngToCopy = .Range("A3:BX3", .Cells(.Rows.Count, "A").End(xlUp))
End With
wb2.Sheets("RAW_DATA").Range("A3:BX3").Resize(rngToCopy.Rows.Count).Value = rngToCopy.Value
End If
With wb2.Sheets("RAW_DATA")
countEND = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("BY3:BY" & countEND).Formula = "=IFERROR(IF(AND(VLOOKUP(VALUE(AS3);BG_DATA!A:A;1;FALSE)=(VLOOKUP(VALUE(AS3);BG_DATA!A:A;1;FALSE));(AF3>0));"""";""x"");""x"")" 'Check
.Range("BZ3:BZ" & countEND).Formula = "=VLOOKUP(VALUE(AS3);BG_DATA!A:I;9;FALSE)" 'Vendor'
.Range("CA3:CA" & countEND).Formula = "=VLOOKUP(VALUE(AS3);BG_DATA!A:J;10;FALSE)" 'Planner
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "DONE!"
End Sub
I copied this function from another excel file I've made. It worked pretty good. But for some reason the following part is giving me an error now:
With wb2.Sheets("RAW_DATA")
countEND = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("BY3:BY" & countEND).Formula = "=IFERROR(IF(AND(VLOOKUP(VALUE(AS3);BG_DATA!A:A;1;FALSE)=(VLOOKUP(VALUE(AS3);BG_DATA!A:A;1;FALSE));(AF3>0));"""";""x"");""x"")" 'Check
.Range("BZ3:BZ" & countEND).Formula = "=VLOOKUP(VALUE(AS3);BG_DATA!A:I;9;FALSE)" 'Vendor'
.Range("CA3:CA" & countEND).Formula = "=VLOOKUP(VALUE(AS3);BG_DATA!A:J;10;FALSE)" 'Planner
End With
Run-time error 1004 - Application-defined or object defined error.
I googled this but didn't find a solution. Excel file was an XLSX and is an XLSM now. Can someone please tell what the problem is?
You are using semicolon ; as a delimiter in your formula, but the delimiter depends on the localization of your workbook. Use comma , instead:
With wb2.Sheets("RAW_DATA")
countEND = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("BY3:BY" & countEND).Formula = "=IFERROR(IF(AND(VLOOKUP(VALUE(AS3),BG_DATA!A:A,1,FALSE)=(VLOOKUP(VALUE(AS3),BG_DATA!A:A,1,FALSE)),(AF3>0)),"""",""x""),""x"")" 'Check
.Range("BZ3:BZ" & countEND).Formula = "=VLOOKUP(VALUE(AS3),BG_DATA!A:I,9,FALSE)" 'Vendor'
.Range("CA3:CA" & countEND).Formula = "=VLOOKUP(VALUE(AS3),BG_DATA!A:J,10,FALSE)" 'Planner
End With
Alternatively you could use .FormulaLocal instead of .Formula, but it will work only in the workbooks where localization defines semicolon as the delimiter.
I've made a macro that suites my needs perfectly except for one thing. Currently it creates new workbooks for me with no format. I would like to change this so that it references a template and uses that formatting.
I've been messing with the "Set wbDest = Workbooks.Add(xlWBATWorksheet)" line, but can't seem to get anything to work!
Private Sub CommandButton1_Click()
Const sColumn As String = "M"
Dim wbDest As Workbook
Dim rngFilter As Range, rngUniques As Range
Dim cell As Range
Set rngFilter = Range(sColumn & "1", Range(sColumn & Rows.Count).End(xlUp))
Application.ScreenUpdating = False
With rngFilter
.AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUniques = Range(sColumn & "2", Range(sColumn & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0
End With
For Each cell In rngUniques
Set wbDest = Workbooks.Add(xlWBATWorksheet)
rngFilter.AutoFilter Field:=1, Criteria1:=cell.Value
rngFilter.EntireRow.Copy
With wbDest.Sheets(1).Range("A1")
.PasteSpecial xlPasteColumnWidths
.PasteSpecial xlPasteValuesAndNumberFormats
End With
Application.CutCopyMode = True
wbDest.Sheets(1).Name = cell.Value
Application.DisplayAlerts = False
wbDest.SaveAs ThisWorkbook.Path & Application.PathSeparator & cell.Value & " " & Format(DateSerial(Year(Date), Month(Date) - 1, 1), "mm-yy")
wbDest.Close False
Application.DisplayAlerts = True
Next cell
rngFilter.Parent.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
`
Workbooks.Add() accepts a single argument - Template. So create a template, save it as an .xltx file, then use that filepath to add your new workbook:
Dim wb As Workbook
Dim filepath As String
filepath = "C:\template.xltx" 'Or what-ever...
Set wb = Application.Workbooks.Add(filepath)
With wb
'...
End With
how about..
Dim wbTemplate As Workbook
Set wbTemplate = Workbooks.Open("C:\mytemplate.xlsx")
Where mytemplate.xlsx is your preformatted template. The reason I assigned it to a variable object is because it looks like you'll need to reference it in order to enter data onto the template. If you simply trying to open a workbook, the one-liner below is acceptable..
Workbooks.Open("C:\mytemplate.xlsx")