Batched numerical PDF imprint

The answer to this may be a simple ‘No’, but thought I should ask.

Is there a way of imprinting a number onto each page of a pdf, but batched, so that the first three pages to have ‘01’, the next three ‘02’ etc?

The use case is this: I need to circulate conference paper proposals to evaluators. Google Forms produces a long pdf of all the proposals which, after editing, comprise 3 pages each; typically 50 proposals, 150 pages. I want to add the imprint – say top right corner, bright red, 96 pt – to help the evaluators navigate this.

Failing that, if the proposals were split into 50 separate documents each of three pages, is there a way of producing the same consecutive numbering? Could be simply applying the filename

If you had separate documents, you could set up an imprint in Settings > Imprinter and apply the filename to each page in each document.

Processing the entire document, especially if you wanted to reuse a counter, e.g., file A-01, file B-01, etc., would require some scripting.

I have family business and a long drive ahead but I will look at this later if no one has offered other suggestions.

That should be possible by using the imprint command in a script. Something like

function performsmartrule(records) {
  const app = Application("DEVONthink 3");
  records.forEach(r => {
  app.imprint(app, {font: "Helvetica", 
        position: "top right", 
        size: 48, 
        record: r, 
        foregroundColor: [65534, 30000, 30000], 
        text: r.name()
      });
  })
}

That JavaScript code can be used in a smart rule (which should, of course, select the right PDFs first). It imprints the name of the current record at the top right of each page in a light red color. The size 48 might be too large for longer file names, though.

To split a file, you can use the following code:

ObjC.import('PDFKit');
ObjC.import('CoreGraphics');
(() => {
  const app = Application("DEVONthink 3");
  
  // Change baseName to whatever you want as name for the new PDFs. You'll get
  // "/Users/ck/Desktop/newPDF-1.pdf", "Users/ck/Desktop/newPDF-2.pdf" etc. 
  const baseName = '/Users/ck/Desktop/newPDF-'; 
  
  // Change to the number of pages to be stored in each new PDF
  const pagesPerPDF = 3;
  const record = app.selectedRecords[0];

  const pathURL = $.NSURL.fileURLWithPath($(record.path()));
  const currentPDF = $.CGPDFDocumentCreateWithURL(pathURL);
  const currentPages = $.CGPDFDocumentGetNumberOfPages(currentPDF);
  const mediaBox = $.CGPDFPageGetBoxRect($.CGPDFDocumentGetPage(currentPDF, 1),$.kCGPDFMediaBox);

  let pagesWritten = 0;
  let fileNo = 1;
  
  // Write pagesPerPDF pages from the old PDF into each new PDF
  while (pagesWritten <= currentPages) {
    const fileName = `${baseName}${fileNo}.pdf`;
    const fileURL = $.NSURL.fileURLWithPath($(fileName));
    const PDFContext = $.CGPDFContextCreateWithURL (fileURL, mediaBox, null);
    for (let pageNo = pagesWritten; pageNo < pagesWritten + pagesPerPDF && pageNo < currentPages; pageNo++) {
      $.CGPDFContextBeginPage(PDFContext, null);
      const page = $.CGPDFDocumentGetPage(currentPDF, pageNo + 1);
      $.CGContextDrawPDFPage(PDFContext, page);
      $.CGPDFContextEndPage(PDFContext);
    }
    $.CGPDFContextClose(PDFContext);
    pagesWritten += pagesPerPDF;
    fileNo++;
  }
})()

It splits the currently selected DT record (which should be a PDF, of course) into pagesPerPDF pages (set to 3 here, but you can use whatever number you want). The new PDFs are stored in files named after baseName with numbers 1, 2, 3 etc. appended. You can modify basename to whatever convention you like.

All code is JavaScript, not AppleScript. I tested both scripts, but not extensively.

1 Like