0
votes

I have a workbook that's broken up exactly how I'd like with regards to page breaks (from using Subtotals), but obviously that all goes into one PDF -- which means to send it out, I'd have to manually split it up and re-save each person's lists amongst 100+ employees.

Is there any way that I can group them to export as an individual PDF per employee, if there's a unique value in each cell for the employee in the spreadsheet?

So basically my page breaks are currently exactly how I'd like them -- but if there's 60 cells (all already ordered/grouped together) from B2:B61 that say "John Smith" for employee, make those 60 rows one PDF (page broken within that PDF how it's currently laid out), then if the next 25 cells from B62:B87 say "Jane Smith" for employee, make that one PDF with its current page breaks, etc.

Is something like this possible? Maybe using VBA?

Thanks!

EDIT: Here's a sample of data -- I'm using Excel with subtotals in Column C, which is how to get the page breaks where I'd like them at the change in each group. I just use Print >> Save to PDF to make my PDF. Everything works well, except while the page breaks are at every change in Group -- I'd like to somehow have Excel spit out separate PDFs based on what's in Column D. Here's the spreadsheet. (Even though Dropbox seemingly removes the current page breaks, which is just every time there's a change in Column C.)

1
Run the code in my answer changing dCol to 4.barryleajo

1 Answers

2
votes

Within VBA you have access to a number of properties to manage page breaks.

Range.PageBreak returns or sets a page break, so you could manage your page breaks programatically with respect to your employee counts.

Worksheet.HPageBreaks and Worksheet.VPageBreaks give you access to the horizontal and vertical page breaks collection.

So Worksheet.HPageBreaks.Count for example, will give yuo the number of horizontal page breaks in your worksheet.

Worksheet.HPageBreaks(1).Location.Row will give you the position of the first horizontal page break and similarly Worksheet.VPageBreaks(1).Location.Column will give you the location of the first vertical page break.

These tools coupled with a .Find or two should allow you to describe the range(s) to be produced as .pdf and allow you to accomplish what you require.

EDIT with starter code sample following OP comment

Having re-read your post this starter code produces two .pdf files based on your original Q. I have set page length to be 50 lines - this is sensitive to font size, paper size, margins etc. You need to provide your own 'outputPath' to save your files. Example runs on a single column of data.

It's a starter so no warranties with this, and be aware that when the code runs, all manual page breaks will be removed (.ResetAllPageBreaks).

Option Base 1
Sub pdf()
Dim ws As Worksheet
Dim dArr() As String, outputPath As String, fileStem As String
Dim dCol As Long, stRow As Long, endRow As Long, pStRow As Long
Dim docCnt As Long, lnCnt As Long
Dim rwsPerPage As Integer, topM As Integer, botM As Integer
Dim empNme As String

Set ws = Sheets("Data")
dCol = 2    'col B
stRow = 2   'row 2

pStRow = stRow
rwsPerPage = 50
topM = 36   'default in points
botM = 36   'default in points
outputPath = "<yourpath>\"
fileStem = "Employee "

docCnt = 1
lnCnt = 0

    With ws
        'set essential page parameters
        With .PageSetup
            .Orientation = xlPortrait
            .TopMargin = topM
            .BottomMargin = botM
        End With
        .ResetAllPageBreaks

        'last data row
        endRow = .Cells(Rows.Count, dCol).End(xlUp).Row
        'first employee name
        empNme = .Cells(stRow, dCol)

            'for each data row
            For c = stRow To endRow
                lnCnt = lnCnt + 1

                    'at change of employee name
                    If Not .Cells(c, dCol).Value = empNme Then
                        'put doc range into array
                        ReDim Preserve dArr(docCnt)
                        dArr(docCnt) = .Range(.Cells(pStRow, dCol), .Cells(c - 1, dCol)).Address
                        docCnt = docCnt + 1
                        'reset startrow of new employee
                        pStRow = c
                        empNme = .Cells(c, dCol).Value
                        'add hpage break
                        .HPageBreaks.Add before:=.Cells(c, dCol)
                        lnCnt = 0
                    End If

                    'at page length
                    If lnCnt = rwsPerPage Then
                        'add hpage break
                        .HPageBreaks.Add before:=.Cells(lnCnt, dCol)
                        lnCnt = 0
                    End If
            Next c

            'last employee if appropriate to array
            If c - 1 > pStRow Then
                ReDim Preserve dArr(docCnt)
                dArr(docCnt) = .Range(.Cells(pStRow, dCol), .Cells(c, dCol)).Address
            End If

            'produce pdf files
            For d = 1 To UBound(dArr, 1)
                .Range(dArr(d)).ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                    outputpat & fileStem & d & ".pdf", Quality:=xlQualityStandard, _
                    IncludeDocProperties:=True, IgnorePrintAreas:=False, _
                    OpenAfterPublish:=True
            Next d

    End With

End Sub 

EDIT #2 with starter code sample using OP data and correcting a typo in the outputPath

Option Base 1
Sub pdf()
Dim ws As Worksheet
Dim dArr() As String, outputPath As String, fileStem As String
Dim dCol As Long, stRow As Long, endRow As Long, pStRow As Long
Dim docCnt As Long, lnCnt As Long
Dim rwsPerPage As Integer, topM As Integer, botM As Integer
Dim empNme As String

Set ws = Sheets("Data")
dCol = 4    'col D
stRow = 2   'row 2

pStRow = stRow
rwsPerPage = 50
topM = 36   'default in points
botM = 36   'default in points
outputPath = "<yourpath>\"
fileStem = "Employee "

docCnt = 1
lnCnt = 0

    With ws
        'set essential page parameters
        With .PageSetup
            .Orientation = xlPortrait
            .TopMargin = topM
            .BottomMargin = botM
        End With
        .ResetAllPageBreaks

        'last data row
        endRow = .Cells(Rows.Count, dCol).End(xlUp).Row
        'first employee name
        empNme = .Cells(stRow, dCol)

            'for each data row
            For c = stRow To endRow
                lnCnt = lnCnt + 1

                    'at change of employee name
                    If Not .Cells(c, dCol).Value = empNme Then
                        'put doc range into array
                        ReDim Preserve dArr(docCnt)
                        dArr(docCnt) = .Range(.Cells(pStRow, dCol - 3), .Cells(c - 1, dCol - 1)).Address
                        docCnt = docCnt + 1
                        'reset startrow of new employee
                        pStRow = c
                        empNme = .Cells(c, dCol).Value
                        'add hpage break
                        .HPageBreaks.Add before:=.Cells(c, dCol)
                        lnCnt = 0
                    End If

                    'at page length
                    If lnCnt = rwsPerPage Then
                        'add hpage break
                        .HPageBreaks.Add before:=.Cells(lnCnt, dCol)
                        lnCnt = 0
                    End If
            Next c

            'last employee if appropriate to array
            If c - 1 > pStRow Then
                ReDim Preserve dArr(docCnt)
                dArr(docCnt) = .Range(.Cells(pStRow, dCol - 3), .Cells(c - 1, dCol - 1)).Address
            End If

            'produce pdf files
            For d = 1 To UBound(dArr, 1)
                .Range(dArr(d)).ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                    outputPath & fileStem & d & ".pdf", Quality:=xlQualityStandard, _
                    IncludeDocProperties:=True, IgnorePrintAreas:=False, _
                    OpenAfterPublish:=True
            Next d

    End With

End Sub