Split a payslip print run into one file each
Payroll has sent one PDF again. Four hundred and something pages, one payslip after another, and by Friday every person in it needs their own file and nobody else's.
You tried cutting it every two pages, because last month's run was two sheets each. The first thirty came out right. Then someone with two cost centres spilled onto a third sheet, and from that point on every file holds the back half of one person's pay and the front half of the next one's.
That is not a mistake you can afford to find at the sending stage. So do not cut on a number. Cut on what the pages say.
Why "every N pages" goes wrong quietly
A payroll run is not a document of fixed-length parts. It is a queue of documents that happen to have been printed into one file, and their lengths vary for ordinary reasons: an extra cost centre, a long list of deductions, a year-to-date table that tips over the bottom margin, a starter or a leaver with a P45 line the others do not have.
A splitter set to "every 2 pages" knows nothing about any of that. It counts. The first employee who takes three sheets does not produce one wrong file — they push every boundary after them out by one page, permanently. The run stays broken to the end, and each file looks plausible on its own: a page of somebody's pay, then a page of somebody's pay.
A wrong split does not fail loudly. It produces two hundred plausible files, most of them carrying part of a second person's salary to the wrong address.
Split PDF by pages is the right tool only when the run is genuinely uniform — every employee on exactly one sheet, which some exports do produce. The test is arithmetic: divide the page count by your headcount. If it is not a whole number, the run is not uniform and counting will not work. If it is exactly 1, one file per page is the whole job and you can stop reading.
What matching on words actually does
Split PDF by text reads the text layer of each page, one page at a time, and asks a single question: does this page contain the phrase you typed? Every page that does begins a new file. Everything between one match and the next belongs to the file the match opened, however many pages that is. Length stops mattering.
Four details of the matching decide whether it works on your run:
- It is a plain substring search, not a pattern. There are no wildcards and no "any number", so
you cannot match
Employee 004\d\d. Match the fixed label sitting next to the number instead. - Capitals are ignored unless you ask for them to count, so
PAYSLIPandPayslipare the same phrase. - Whitespace is flattened on both sides before comparing. A heading that wraps onto two lines in the PDF, or is spread out with extra spacing, still matches what you typed on one line.
- The page is read in position order, so a two-column payslip does not interleave its left and right columns in the middle of your phrase.
The cut is always at a page boundary. It cannot start a new file part-way down a sheet.
Choosing the phrase, and the trap in it
You need a line that appears on the first sheet of every payslip and on no other sheet.
The employee's name is the wrong choice, even though it is the obvious one — it identifies the
person, not the start of the document, and it usually appears on their continuation sheets as well.
The right choice is a fixed label from the template: Payslip, Payment advice, Period ending,
Tax period, Employee number.
Then check the one thing that ruins it. Payroll templates repeat their header on continuation sheets.
If the word Payslip sits in the header of sheet 1 and sheet 2, matching on it starts a new file at
every sheet and you are back where you began, with a slightly different flavour of wrong.
Two ways past that:
- Look for pagination text. Many payroll exports print
Page 1 of 2on the first sheet andPage 2 of 2on the second.Page 1 ofmatches the first sheet of every payslip regardless of how many sheets follow it, which is exactly the boundary you want. - Look for a line that only a first sheet carries. The address block,
Payment date,Net pay this period— something in the summary that a continuation sheet does not repeat.
To see what is actually on the pages rather than guessing, run the file through PDF to text first, tick the option that marks where each page ends, and search the output for your candidate phrase. Counting the hits in a text editor takes a minute and tells you before you split whether the phrase matches once per employee or once per sheet.
Doing the split
- Confirm the file has a text layer. Our PDF inspector reads it in your browser without uploading anything. A run exported by a payroll system is real text; a run that was printed and scanned back in is pictures of text, and nothing here can read it.
- Know your headcount before you start. It is the number you will check against.
- Open Split PDF by text and type the phrase. Leave the capitals option off unless the capitals are the distinguishing feature.
- Read the count in the result, before you open anything. It says how many pages the phrase was found on. That number should equal your headcount. Four hundred matches in a four-hundred-page file means the phrase is in a header and you have matched every sheet. Three matches means it is not the phrase.
- Note whether there is an extra file at the front. Anything before the first match — a cover sheet, a control total, a batch header — comes back as its own file, and the result says which page the first match was on. That file is part 1, which pushes everybody else's number up by one.
- Open the first part, the last part, and one from the middle. Each should start with one person's summary and contain nobody else's.
The parts are numbered, not named
This is the part of the job where the mistakes happen, so it is worth being blunt about what the tool
does not do. The parts come back named after your original with a number on the end —
payroll-march-1.pdf, payroll-march-2.pdf — because the phrase decides where the cuts go, not what
the files are called. Nothing reads the page and works out whose payslip it is.
Our Rename PDF tool gives one file a proper name and, if you want, sets the matching title inside the document. One file at a time, deliberately: there is no batch rename and no naming pattern here, because a pattern applied to the wrong folder is a mess nobody can unpick. For this job that is the right shape anyway — you rename each file at the moment you have it open and can see whose it is, which is also the moment you verify it.
The tempting shortcut is to map the numbers onto your payroll listing, since part order follows page order and page order usually follows the payroll's own sort. It works right up until it does not: one unexpected match, or one cover sheet you did not account for, shifts every number after it by one and the map pairs each file with the following person. Only map positionally once the match count has equalled the headcount, and even then open a few and check the names.
Chaining the steps into a workflow saves the download and re-upload between tools, but it does not solve this: a step's options are set once for the whole run, so a rename step after a split would give every part the same name.
If your run has bookmarks — some ERP exports write one outline entry per employee — Split PDF by bookmarks is the better tool entirely, because it cuts at the bookmarks and names each part after the entry it starts at. That is the same mechanism as splitting a manual into chapters, applied to people instead of chapters, and it is the only route here that produces named files in one pass.
Before you upload anybody's pay
A browser tool means the file goes to a server. Ours holds uploads for 2 hours and results for 24, then deletes them, and it is stated plainly on the retention page — but your own policy may simply not allow a full payroll run to leave the building, and that is a legitimate answer. If so, do the job locally with the commands below rather than asking forgiveness.
Whichever route you take, delete the merged run and the intermediate files when you are done. Two hundred separate payslips sitting in one downloads folder is the same exposure as the original file, in a less obvious shape.
If you are emailing them, Password protect PDF encrypts a PDF with a password — but one run sets one password, so it cannot give each employee their own. For per-employee passwords you need your payroll system's own distribution, or a script.
And if the run is a scan, none of this applies: there is no text to match, and the job stops with a message rather than handing you one big file. Our OCR PDF tool reports which pages have no text layer but cannot add one on this deployment, so a scanned run has to go through OCR elsewhere first — OCRmyPDF is free and does it properly.
It is a monthly job. Script it.
This comes round every month with the same template, which is the case where a browser is the wrong tool. Two free pieces do the whole thing:
pdfgrep -n "Page 1 of" run.pdfprints the page number of every match. That is your cut list, and it is also the fastest way to test a candidate phrase against last month's file.qpdf --empty --pages run.pdf 12-14 -- "A Smith.pdf"writes one part out, with the name you want, without re-rendering anything.
Put those in a loop and you have the split. The step our tools genuinely cannot do — naming each file
after the person on it — is about twenty lines of Python with pypdf: read each page's text, pull the
employee number or name out with a regular expression, write the pages to a file called that. Being
able to use a pattern rather than a fixed phrase is the whole difference, and it is why a script wins
the second time you do this.
For checking what a page contains without leaving the terminal, pdftotext -layout run.pdf - from
poppler prints it with the columns roughly where they sit on the page.
The check that matters
Match count equals headcount. File count equals headcount plus any front matter. First, last and one middle file opened and read. Then send them.
Everything else is recoverable. Sending someone else's salary is not.