Excel VBA Macro to output multiple PDFs based on column value - excel

I am attempting to setup a VBA macro in Excel that outputs a PDF for every set of rows with the same account number. I am tailoring this from a macro found for a similar purpose. I have two sheets, Data and Account. The Data sheet has the unfiltered data [A0, MTIME, MDATE, MINIT, MTEXT] as the row headers and the Account sheet just has the unique account numbers I want to pull.
The filtering appears to work correctly but the macro is dying at the first output component and I am a bit stumped as to why. Have verified permissions are good. Any thoughts would be apprecaited. Code Below.
Sub PracticeToPDF()
'Prepared by Dr Moxie
Dim ws As Worksheet
Dim ws_unique As Worksheet
Dim DataRange As Range
Dim iLastRow As Long
Dim iLastRow_unique As Long
Dim UniqueRng As Range
Dim Cell As Range
Dim LastRow As Long
Dim LastColumn As Long
Application.ScreenUpdating = False
'Note that the macro will save the pdf files in this active directory so you should save in an appropriate folder
DirectoryLocation = ActiveWorkbook.Path
Set ws = Worksheets("Data") 'Amend to reflect the sheet you wish to work with
Set ws_unique = Worksheets("Account") 'Amend to reflect the sheet you wish to work with
'Find the last row in each worksheet
iLastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
iLastRow_unique = ws_unique.Cells(Rows.Count, "A").End(xlUp).Row
With ws
'I've set my range to reflect my headers which are fixed for this report
Set DataRange = ws.Range("$A$1:$E$" & iLastRow)
'autofilter field is 4 as I want to print based on the practice value in column D
DataRange.AutoFilter Field:=1
Set UniqueRng = ws_unique.Range("A1:A20" & iLastRow_unique)
For Each Cell In UniqueRng
DataRange.AutoFilter Field:=1, Criteria1:=Cell
Name = DirectoryLocation & "\" & Cell.Value & " Account Notes" & ".pdf"
ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:=Name _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=False
Next Cell
End With
With ws
.Protect Userinterfaceonly:=True, _
DrawingObjects:=False, Contents:=True, Scenarios:= _
True, AllowFormattingColumns:=True, AllowFormattingRows:=True
.EnableOutlining = True
.EnableAutoFilter = True
If .FilterMode Then
.ShowAllData
End If
End With
Application.ScreenUpdating = True
End Sub

z32a7ul put me on the right track with some items I had to correct. The ultimate issue was I had the macro built out on the sheet level and not as a module. Moved the code to the module and combined with the edits got it up and going. Thanks z32a7ul!

Related

VBA to add data and export as excel for a list

I Have a list of data that needs to be pasted in a form in next tab and export it into PDF
Sub Mpolicy()
Dim varItemsToReplace As Variant
Dim varItem As Variant
Dim wksSource As Worksheet
Dim wksDest As Worksheet
Dim rngSource As Range
Dim rngSource2 As Range
Dim rngCell As Range
Set wksSource = Worksheets("Instruction")
Set wksDest = Worksheets("Mobile Policy")
With wksSource
Set rngSource = .Range("A5:A" & .Cells(.Rows.Count, "A").End(xlUp).Row)
End With
For Each rngCell In rngSource
With wksDest
Range("A75").Formula = "=Instruction!A5"
Range("C75").Formula = "=Instruction!C5"
Range("E75").Formula = "=Instruction!B5"
Range("G75").Formula = "=Instruction!D5"
Range("A1").Select
wksDest.Activate
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"C:\Users\jkurlawala\Desktop\Master Data Template\Joby Declaration\" & ActiveSheet.Range("A75").Value & " - " & ActiveSheet.Range("C75").Value & ".pdf" _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=False
End With
Next rngCell
End Sub
Unfortunately only 1 line of data is being copied from the list to policy form , rest of the list is not working
enter image description here
It seems as though you are trying to make a PDF for each record of the contiguous data on the sheet named "Instruction." To do that you need to put the data from one row at a time onto the sheet called "Mobile Policy," which has the policy information common to each customer. Then make a pdf of the policy with the customer data, naming according to the user's name and mobile model. If so, here is a block of code that has been simplified to accomplish just that. I've added comments to help you understand what each part is doing.
Sub Mpolicy()
Dim wksSource As Worksheet
Dim wksDest As Worksheet
Dim exportPath As String
Dim exportRange As Range
Dim x As Integer
Set wksSource = Worksheets("Instruction")
Set wksDest = Worksheets("Mobile Policy")
'set the range of data to export to the block of contiguous data
'starts in cell A5 of the source worksheet
Set exportRange = wksSource.Range("A5").CurrentRegion
'iterate over the sourece data, skipping the header row
For x = 2 To exportRange.Rows.Count
'copy data from the current user to the policy sheet
exportRange.Rows(x).Copy
wksDest.Range("A75").PasteSpecial xlPasteAll
'compose the full path for the current file to export, starting
'with the path entered in cell B1 of the source worksheet
exportPath = wksSource.Range("b1").Value & _
wksDest.Range("A75").Value & " - " & _
wksDest.Range("C75").Value & ".pdf"
'make the PDF for the current row
wksDest.ExportAsFixedFormat Type:=xlTypePDF, _
filename:=exportPath, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
Next
End Sub

Convert Excel Sheet to PDFs, Infinite Loop Error

I have used bits and pieces of code on forums to create a macro that exports PDF's from a single sheet in excel. Each PDF contains the header and all relevant rows to the employee (all rows with employee ID). When I run it all goes well and the pdfs are correct, however the macro never stops running.
I believe I have created an infinite loop and am not sure how to correct it.
It also creates a PDF just containing the header that is not necessary.
Sub PracticeToPDF()
Dim ws As Worksheet
Dim ws_unique As Worksheet
Dim DataRange As Range
Dim iLastRow As Long
Dim iLastRow_unique As Long
Dim UniqueRng As Range
Dim Cell As Range
Dim LastRow As Long
Dim LastColumn As Long
Application.ScreenUpdating = False
'Note that the macro will save the pdf files in this active directory so you should save in an appropriate folder
DirectoryLocation = ActiveWorkbook.Path
Set ws = Worksheets("BootVSPayroll") 'Amend to reflect the sheet you wish to work with
Set ws_unique = Worksheets("BootVSPayroll") 'Amend to reflect the sheet you wish to work with
'Find the last row in each worksheet
iLastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
iLastRow_unique = ws_unique.Cells(Rows.Count, "A").End(xlUp).Row
With ws
'I've set my range to reflect my headers which are fixed for this report
Set DataRange = ws.Range("$A$1:$K$1" & iLastRow)
'autofilter field is 4 as I want to print based on the practice value in column D
DataRange.AutoFilter Field:=1
Set UniqueRng = ws_unique.Range("A1:A20" & iLastRow_unique)
For Each Cell In UniqueRng
DataRange.AutoFilter Field:=1, Criteria1:=Cell
Name = DirectoryLocation & "\" & Cell.Value & " BOOT Report" & ".pdf"
ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:=Name _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=False
Next Cell
End With
With ws
.Protect Userinterfaceonly:=True, _
DrawingObjects:=False, Contents:=True, Scenarios:= _
True, AllowFormattingColumns:=True, AllowFormattingRows:=True
.EnableOutlining = True
.EnableAutoFilter = True
If .FilterMode Then
.ShowAllData
End If
End With
Application.ScreenUpdating = True
End Sub
Did you perhaps mean for:
Set DataRange = ws.Range("$A$1:$K$1" & iLastRow)
...
Set UniqueRng = ws_unique.Range("A1:A20" & iLastRow_unique)
to instead be:
Set DataRange = ws.Range("$A$1:$K$" & iLastRow)
...
Set UniqueRng = ws_unique.Range("A1:A" & iLastRow_unique)
?
If, for example, (taken from ws_unique) your last used row, iLastRow_unique equals 200, then "A1:A20" & iLastRow_unique is equivalent to "A1:A20200" -- which may be a lot more rows that you intended to loop through, I think.

Split data across multiple workbooks depending on column value

I have a workbook that has some 100,000+ number of lead records. Each record has an agent code which determines to whom the record is allotted to(50 plus agents). What I would like to do is to distribute all lead records per agent(workbook) depending on the agent code while also maintaining the existing data formatting, data validation and also automatically creating a worksheet password. Is this possible with excel VBA?
The table runs by this sequence:
enter image description here
EDIT:
Here are some of the sample scripts we ran:
Sub ExtractToNewWorkbook()
Dim ws As Worksheet
Dim wsNew As Workbook
Dim rData As Range
Dim rfl As Range
Dim state As String
Dim sfilename As String
Set ws = ThisWorkbook.Sheets("emp")
'Apply advance filter in your sheet
With ws
Set rData = .Range(.Cells(1, 1), .Cells(.Rows.Count, 11).End(xlUp))
.Columns(.Columns.Count).Clear
.Range(.Cells(2, 6), .Cells(.Rows.Count, 6).End(xlUp)).AdvancedFilter _
Action:=xlFilterCopy, _
CopyToRange:=.Cells(1, .Columns.Count), _
Unique:=True
For Each rfl In .Range(.Cells(1, .Columns.Count), .Cells(.Rows.Count, .Columns.Count).End(xlUp))
state = rfl.Text
Set wsNew = Workbooks.Add
sfilename = state & ".xlsx"
'Set the Location
ActiveWorkbook.SaveAs ThisWorkbook.Path & "\" & sfilename
Application.DisplayAlerts = False
ws.Activate
rData.AutoFilter Field:=6, Criteria1:=state
rData.Copy
Windows(state).Activate
ActiveSheet.Paste
ActiveWorkbook.Close SaveChanges:=True
Next rfl
Application.DisplayAlerts = True
End With
ws.Columns(Columns.Count).ClearContents
rData.AutoFilter
End Sub

Generate new workbook and add a template header with multiple rows

I have compiled a Macro to generate new workbooks based on unique values i the original workbook. Then it copies the rows related to thees values into the new workbook. This works great.
However I also want a template to be copied after this process and inserted as new rows in the new workbook. I am having trouble activating this new workbook to run these actions.
I am guessing that the new workbook needs to be set to something so I can use this as a reference. To later be used in this part: Windows("newBook").Activate. Or should this part be written completely different?
And when should the new workbook be saved to set it´s name?
Using this part ActiveWorkbook.SaveAs SavePath & ArrayOfUniqueValues(ArrayItem) & ".xlsx", 51
This is what I have so far:
Option Explicit
Sub DataExport()
'Declare variables
Dim ArrayItem As Long
Dim ws As Worksheet
Dim NewBook As Workbook
Dim ArrayOfUniqueValues As Variant
Dim SavePath As String
Dim ColumnHeadingInt As Long
Dim ColumnHeadingStr As String
Dim rng As Range
Set ws = Sheets("Data")
Set NewBook = 'what?
'The save path for the files created
SavePath = Range("FolderPath")
'Variables for the column to separate data based on
ColumnHeadingInt = WorksheetFunction.Match(Range("ExportCriteria").Value, Range("Data[#Headers]"), 0)
ColumnHeadingStr = "Data[[#All],[" & Range("ExportCriteria").Value & "]]"
'Turn off screen updating to save runtime
Application.ScreenUpdating = False
'Creates a temporary list of unique values
Range(ColumnHeadingStr & "").AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=Range("UniqueValues"), Unique:=True
'Sort the temporary list of unique values
ws.Range("UniqueValues").EntireColumn.Sort Key1:=ws.Range("UniqueValues").Offset(1, 0), _
Order1:=xlAscending, Header:=xlYes, OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
'Add unique field values into an array
ArrayOfUniqueValues = Application.WorksheetFunction.Transpose(ws.Range("UniqueValues").EntireColumn.SpecialCells(xlCellTypeConstants))
'Delete the temporary values
ws.Range("UniqueValues").EntireColumn.Clear
'Loop through the array of unique field values. Then copy paste into new workbooks and save.
For ArrayItem = 1 To UBound(ArrayOfUniqueValues)
ws.ListObjects("Data").Range.AutoFilter Field:=ColumnHeadingInt, Criteria1:=ArrayOfUniqueValues(ArrayItem)
ws.Range("Data[#All]").SpecialCells(xlCellTypeVisible).Copy
Workbooks.Add
Range("A1").PasteSpecial xlPasteAll ' pastes all values
Columns(1).EntireColumn.Delete
'saving the new workbook. Should it be places somewhere else?
ActiveWorkbook.SaveAs SavePath & ArrayOfUniqueValues(ArrayItem) & ".xlsx", 51
'here is where the trouble starts
Windows("REFERENCE with export VB.xlsm").Activate
Sheets("Template").Select
Rows("1:5").Select
Selection.Copy
'Now the tricky part on how to go back to the new workbook
Windows("newBook").Activate
Rows("1:1").Select
Selection.Insert Shift:=xlDown
'Saving and closing
ActiveWorkbook.Save
ActiveWorkbook.Close False
ws.ListObjects("Data").Range.AutoFilter Field:=ColumnHeadingInt
Next ArrayItem
ws.AutoFilterMode = False
MsgBox "Finished exporting!"
Application.ScreenUpdating = True
End Sub
I've tried to explain the code so it makes sense. I don't know what do you actually want to do with the copied rows from the sheet templates, I've assumed you wanted to paste the format to the first 5 rows of your new workbok...
Option Explicit
Sub DataExport()
'Turn off screen updating to save runtime
Application.ScreenUpdating = False 'do it at the beginning of your code
'Declare variables
'try to declare your variables just before using them so it's easier to know what do they do.
'Dim rng As Range you are not using this
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Data") 'always reference workbook and worksheet
'The save path for the files created
Dim SavePath As String
SavePath = Range("FolderPath")
With ws 'you can use this to reference this worksheet using only a dot
'Variables for the column to separate data based on
Dim ColumnHeadingInt As Long
ColumnHeadingInt = WorksheetFunction.Match(.Range("ExportCriteria").Value, .Range("Data[#Headers]"), 0)
Dim ColumnHeadingStr As String
ColumnHeadingStr = "Data[[#All],[" & .Range("ExportCriteria") & "]]"
'Creates a temporary list of unique values
.Range(ColumnHeadingStr & "").AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=.Range("UniqueValues"), Unique:=True
'Sort the temporary list of unique values
.Range("UniqueValues").EntireColumn.Sort Key1:=ws.Range("UniqueValues").Offset(1, 0), _
Order1:=xlAscending, Header:=xlYes, OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom, DataOption1:=xlSortNormal
'Add unique field values into an array
Dim ArrayOfUniqueValues As Variant
ArrayOfUniqueValues = Application.WorksheetFunction.Transpose(.Range("UniqueValues").EntireColumn.SpecialCells(xlCellTypeConstants))
'Delete the temporary values
.Range("UniqueValues").EntireColumn.Clear
End With 'here ends the reference to your ws sheet
'You shouldn't declare anything inside a loop, so you do it just before.
Dim NewBook As Workbook
'Loop through the array of unique field values. Then copy paste into new workbooks and save.
Dim ArrayItem As Long
For ArrayItem = LBound(ArrayOfUniqueValues) To UBound(ArrayOfUniqueValues)
.ListObjects("Data").Range.AutoFilter Field:=ColumnHeadingInt, Criteria1:=ArrayOfUniqueValues(ArrayItem)
.Range("Data[#All]").SpecialCells(xlCellTypeVisible).Copy
'Here you use the NewBook variable.
Set NewBook = Workbooks.Add 'you can use the workbook variable like this
With NewBook.Sheets(1)
.Range("A1").PasteSpecial xlPasteAll ' pastes all values
.Columns(1).EntireColumn.Delete
.Rows("1:1").Insert Shift:=xlDown
End With
'here is where the trouble starts this block can be resumed in one line of code
' Windows("REFERENCE with export VB.xlsm").Activate
' Sheets("Template").Select
' Rows("1:5").Select
' Selection.Copy
'ThisWorkbook always refers to the workbook running the code
ThisWorkbook.Sheets("Template").Rows("1:5").Copy
With NewBook 'again reference the new workbook
'This I think is what you want to do, paste formats from rows 1 to 5 on your Template sheet
.Sheets(1).Range("A1").PasteSpecial xlPasteFormats
'saving the new workbook. Should it be places somewhere else?
'Should be placed just before the last operation so you don't need to save multiple times
.SaveAs SavePath & ArrayOfUniqueValues(ArrayItem) & ".xlsx", 51
.Close
End With
ws.ListObjects("Data").Range.AutoFilter Field:=ColumnHeadingInt
Next ArrayItem
ws.AutoFilterMode = False
MsgBox "Finished exporting!"
Application.ScreenUpdating = True
End Sub

How to add exceptions in the creation of pdf files according to an excel list using macros

Hi I downloaded an excel file with macros that generates pdf files according to a list. There are 2 sheets and the pdf are generated from the sheet called "WEST" to generate them it uses an Autofilter function in column D so it generates a pdf for each unique value specified in the list from the sheet called "PRACTICE".
Here is the link to the file http://nhsexcel.com/filtered-list-to-pdf/
The thing is that I want to add exceptions to the code, for example I don´t want to generate pdf´s of the rows in the sheet "WEST", that contain in column i values less than 10.
I tried to add an autofilter with that criteria but the code keeps saying that it´s not a valid metod.
Sub PracticeToPDF()
'Prepared by Dr Moxie
Dim ws As Worksheet
Dim ws_unique As Worksheet
Dim DataRange As Range
Dim iLastRow As Long
Dim iLastRow_unique As Long
Dim UniqueRng As Range
Dim Cell As Range
Dim LastRow As Long
Dim LastColumn As Long
Application.ScreenUpdating = False
'Note that the macro will save the pdf files in this active directory so you should save in an appropriate folder
DirectoryLocation = ActiveWorkbook.Path
Set ws = Worksheets("WEST") 'Amend to reflect the sheet you wish to work with
Set ws_unique = Worksheets("PRACTICE") 'Amend to reflect the sheet you wish to work with
'Find the last row in each worksheet
iLastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
iLastRow_unique = ws_unique.Cells(Rows.Count, "A").End(xlUp).Row
With ws
'I've set my range to reflect my headers which are fixed for this report
Set DataRange = ws.Range("$A$8:$L$" & iLastRow)
'autofilter field is 4 as I want to print based on the practice value in column D
DataRange.AutoFilter Field:=4
Set UniqueRng = ws_unique.Range("A4:A" & iLastRow_unique)
For Each Cell In UniqueRng
DataRange.AutoFilter Field:=4, Criteria1:=Cell
Name = DirectoryLocation & "\" & Cell.Value & " Practice Report" & ".pdf"
ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:=Name _
, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=False
Next Cell
End With
With ws
.Protect Userinterfaceonly:=True, _
DrawingObjects:=False, Contents:=True, Scenarios:= _
True, AllowFormattingColumns:=True, AllowFormattingRows:=True
.EnableOutlining = True
.EnableAutoFilter = True
If .FilterMode Then
.ShowAllData
End If
End With
Application.ScreenUpdating = True
End Sub
I would like to just generate the pdf files of all the rows which value in column I is greater than ten, but no matter what I have tried it keeps either generating all the pdfs or not generating any at all.
I think you want an IF statement to check if there are any rows visible (excluding headers) before proceeding with the export.
That's what I do in the code below.
Option Explicit
Sub PracticeToPDF()
Dim dataSheet As Worksheet
Set dataSheet = Worksheets("WEST") 'Amend to reflect the sheet you wish to work with
Dim uniqueSheet As Worksheet
Set uniqueSheet = Worksheets("PRACTICE") 'Amend to reflect the sheet you wish to work with
'Note that the macro will save the pdf files in this active directory so you should save in an appropriate folder
Dim directoryLocation As String
directoryLocation = ActiveWorkbook.Path ' Maybe you should be using Thisworkbook.Path?
If Len(Dir$(directoryLocation, vbDirectory)) = 0 Then ' Just in case the ActiveWorkbook hasn't been saved.
MsgBox "'" & directoryLocation & "' is not a valid path. Code will stop running now."
Exit Sub
End If
'Find the last row in each worksheet
Dim lastRowOnDataSheet As Long
lastRowOnDataSheet = dataSheet.Cells(dataSheet.Rows.Count, "A").End(xlUp).Row
Dim lastRowOnUniqueSheet As Long
lastRowOnUniqueSheet = uniqueSheet.Cells(uniqueSheet.Rows.Count, "A").End(xlUp).Row
'I've set my range to reflect my headers which are fixed for this report
Dim dataRange As Range
Set dataRange = dataSheet.Range("$A$8:$L$" & lastRowOnDataSheet)
Dim uniqueRange As Range
Set uniqueRange = uniqueSheet.Range("A4:A" & lastRowOnUniqueSheet)
'Application.ScreenUpdating = False ' Uncomment this when the code is working.
If dataSheet.AutoFilterMode Then
On Error Resume Next
dataSheet.ShowAllData ' Will throw if filters have already been cleared
On Error GoTo 0
End If
Dim cell As Range
For Each cell In uniqueRange
With dataRange
.AutoFilter Field:=4, Criteria1:=cell ' Filter for whatever unique value we're currently at in the loop
.AutoFilter Field:=9, Criteria1:=">10" ' Filter column I for values greater than 10
' Only export the PDF if the filter leaves at least one row (not including the header row)
If .Columns(1).SpecialCells(xlCellTypeVisible).CountLarge > 1 Then
Dim fullPathToExportPDFTo As String
fullPathToExportPDFTo = directoryLocation & "\" & cell.Value & " Practice Report" & ".pdf"
dataSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=fullPathToExportPDFTo, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=False
End If
.Parent.ShowAllData ' Reset the filter for the loop iteration.
End With
Next cell
With dataSheet
.Protect Userinterfaceonly:=True, DrawingObjects:=False, Contents:=True, Scenarios:=True, _
AllowFormattingColumns:=True, AllowFormattingRows:=True
.EnableOutlining = True
.EnableAutoFilter = True
End With
' Application.ScreenUpdating = True ' Uncomment this when the code is working.
End Sub

Resources