0

I have lot of scanned pages of old reports stored in the following directory structure:

Report 1/
 contents.pdf
 execsummary.pdf
 chapter 1/
   page 1.pdf
   page 2.pdf
   page 3.pdf
 chapter 2/
   page 4.pdf
   page 5.pdf
   page 6.pdf

I want to generate Report 1.pdf from these with bookmarks matching the directory structure. How can I do this?

I am on Windows 10 and I don't have Adobe Acrobat but I have Foxit Phantompdf.

6
  • I have 20-30 such reports
    – claws
    Jul 11, 2016 at 12:27
  • Just a minor thought: if there are more than 9 chapters, the order might become weird ("chapter 2" being larger than "chapter 12" in most sorting implementations). You might want to define (or at least fine-tune) the index manually then.
    – Arjan
    Jul 17, 2016 at 8:59
  • @Arjan: Can you reopen the question for a while? I discovered a simplest solution to this problem. Let me answer it.
    – claws
    Aug 18, 2016 at 14:17
  • 1
    @claws: (1) It’s often useful to read the screen. (a) Arjan didn’t close the question. He (along with about 700 other people) can vote to reopen it, but he can’t do it all by himself. Pinging individual users with reopen requests isn’t really productive. (b) It would have been helpful if you had edited your question, as the closed box suggests (and as fixer1234 did), to make it a candidate for reopening. (2) Your question has gotten three Leave Closed votes. It still can be reopened, but it has been removed from the reopen queue. You might get some help if you ask on meta or in chat. Aug 18, 2016 at 22:26
  • @Scott is right. But I don't understand why this was closed...
    – Arjan
    Aug 18, 2016 at 23:04

3 Answers 3

1

This is probably not the solution you're looking for:

You can use, e.g., LaTeX to achieve this. You need to generate the TeX-file another way, e.g., your favorite programming language. This requires you to know how to programme, use LaTeX and, of course, install the required tools.

In case you're interested, I can elaborate on this and add sample scripts.

Edit:

I made a little FreeBASIC programme (bit dirty but does the job) to generate the .tex-file. This can then be used to generate the final pdf-file with, e.g., Miktex and TexnicCenter.

  • Download and extract the FreeBASIC compiler from http://www.freebasic.net/ (I used FreeBASIC-1.05.0-win64.zip).
  • Save the code below as, say code.bas, and compile it with fbc.exe code.bas.
  • Drag and drop the folders "Report 1", "Report 2" etc. onto the new executable code.exe. This will generate the files "Report 1.tex", "Report 2.tex" in their respective folder.
  • Download and install Miktex from http://www.miktex.org/ (enable on-the-fly installation of packages during setup) and TexnicCenter from http://www.texniccenter.org/download/ and open the report files in TexnicCenter. I'm not certain if you need to make any changes to the default settings but the internet is full of resources for this. When compiling LaTeX -> PDF it should install the missing packages.

Sourcecode: Processes explicitly the mentioned folder structure and filenames and nothing more.

    ' Drag and drop folders onto the executable in order to generate a .tex-file 
    ' which can be used to merge the pdfs in each passed folder using LaTeX.
    '

    #include "vbcompat.bi"

    sub expandEnviron__isFileOrFolder ( byref strPath as string )
        dim iLetter as integer
        if left(strPath,1)="%" then
            for iLetter=2 to len(strPath)
                if mid(strPath,iLetter,1)="%" then              
                    strPath=environ(mid(strPath,2,iLetter-2))+right(strPath,len(strPath)-iLetter)
                    exit for
                end if
            next iLetter
        end if
    end sub

    function isFileOrFolder ( byref strPath as string, byval expPath as string ptr = 0 ) as integer
        ' return value:
        '    0: path doesn't exist
        '    1: file
        '    2: folder
        '

        dim strDir as string = curdir

        dim as string strPathCopy
        dim as string ptr pPath
        if expPath then
            *expPath = strPath
            expandEnviron__isFileOrFolder(*expPath)
            pPath = expPath
        else
            strPathCopy = strPath
            expandEnviron__isFileOrFolder(strPathCopy)
            pPath = @strPathCopy
        end if

        if fileExists(*pPath) then
            return 1
        elseif ( chdir(*pPath) = 0 ) then
            chdir(strDir)
            return 2
        else
            return 0
        end if
    end function


    color(1,15)
    cls

    if command(1) = "" then
        print "Drag and drop folders onto the executable."
        sleep
        end
    end if

    dim as string basedir
    dim as string strPath = ""
    dim as integer i = 1
    ' Process all command line arguments i.e process all folders.
    while command(i) <> ""
        basedir = command(i)
        dim as string basedirName

        ' Make sure the argument is indeed a folder.
        if isFileOrFolder(basedir,@strPath) = 2 then
            if right(strPath,1) = "\" then basedir = left(strPath,len(strPath)-1)
            basedirName = right(basedir,len(basedir)-instrrev(basedir,"\"))
            print ""
            print baseDirName
            '
            ' Print some LaTeX commands.
            open basedir+"\"+baseDirName+".tex" for output as #1
            print #1, $"\documentclass{scrreprt}"
            print #1, $"\usepackage{grffile}"
            print #1, $"\usepackage{pdfpages}"
            print #1, $"\usepackage{bookmark}"
            print #1, $"\hypersetup{pageanchor=false}"
            print #1, $"\begin{document}"
            print #1, $"\pagestyle{empty}"
            print #1, $"\pagenumbering{gobble}"
            print #1, "%"
            '
            ' Process contents.pdf.
            dim as string tmp = basedir+"\contents.pdf"
            if isFileOrFolder(tmp) = 1 then
                print #1, $"\includepdf[pages=-]{contents.pdf}"
            else
                color(12,15):print chr(9);"missing contents.pdf":color(1,15)
            end if
            '
            ' Process execsummary.pdf.
            tmp = basedir+$"\execsummary.pdf"
            if isFileOrFolder(tmp) = 1 then
                print #1, $"\includepdf[pages=-]{execsummary.pdf}"
            else
                color(12,15):print chr(9);"missing execsummary.pdf":color(1,15)
            end if
            '
            ' Process all subfolders named "chapter 1", "chapter 2" etc.
            ' If "chapter 4" exists but "chapter 3" does not, then "chapter 4" and 
            ' all after that will be ignored.
            dim as integer chapter_link_cnt = 0
            dim as integer j = 1
            dim as string nextChapterDir = basedir+$"\chapter "+str(j)
            while isFileOrFolder(nextChapterDir) = 2
                print #1, "%"
                dim as integer k = 1
                '
                ' Process all files named "page 1", "page 2" etc.
                dim as string nextPage = nextChapterDir + $"\page "+str(k)+".pdf"
                while isFileOrFolder(nextPage) = 1
                    if k = 1 then
                        chapter_link_cnt += 1
                        print #1, $"\includepdf[link,linkname=l";str(chapter_link_cnt); _
                            ",pages=-]{chapter ";str(j);"/page ";str(k);".pdf}"
                        print #1, $"\bookmark[dest=l";str(chapter_link_cnt); _
                            ".1]{chapter ";str(j);"}"
                    else
                        print #1, $"\includepdf[pages=-]{chapter ";str(j);"/page ";str(k);".pdf}"
                    end if
                    k += 1
                    nextPage = nextChapterDir + $"\page "+str(k)+".pdf"
                wend
                j += 1
                nextChapterDir = basedir+$"\chapter "+str(j)
            wend
            '
            print #1, $"\end{document}"
            close #1
        else
            print ""
            color(12,15):print "Error (not a folder): ";command(i):color(1,15)
        end if
        i += 1
    wend

    print ""
    print ""
    print "Done."
    sleep

In case you want to use a different language (perhaps it can be done with a powershell script), here is a sample tex-file:

\documentclass{scrreprt}
\usepackage{grffile}
\usepackage{pdfpages}
\usepackage{bookmark}
\hypersetup{pageanchor=false}
\begin{document}
\pagestyle{empty}
\pagenumbering{gobble}
%
\includepdf[pages=-]{contents.pdf}
\includepdf[pages=-]{execsummary.pdf}
%
\includepdf[link,linkname=l1,pages=-]{chapter 1/page 1.pdf}
\bookmark[dest=l1.1]{chapter 1}
\includepdf[pages=-]{chapter 1/page 2.pdf}
%
\includepdf[link,linkname=l2,pages=-]{chapter 2/page 1.pdf}
\bookmark[dest=l2.1]{chapter 2}
\includepdf[pages=-]{chapter 2/page 2.pdf}
%
\includepdf[link,linkname=l3,pages=-]{chapter 3/page 1.pdf}
\bookmark[dest=l3.1]{chapter 3}
\includepdf[pages=-]{chapter 3/page 2.pdf}
\includepdf[pages=-]{chapter 3/page 3.pdf}
\includepdf[pages=-]{chapter 3/page 4.pdf}
\end{document}
2
  • Yes please. Could you kindly expand your answer?
    – claws
    Jul 17, 2016 at 14:15
  • 1) You may have to adjust the FreeBASIC code to your exact setup. 2) I also wasn't sure how you wanted to merge the PDF files (add chapter titles? etc.). So you may need to adjust this as well.
    – nx105
    Jul 17, 2016 at 17:36
0

PDFsam Basic does what you want for free

http://www.pdfsam.org/

https://sourceforge.net/projects/pdfsam/

3
  • 1
    Does PDF sam do the bookmark structure? That seems a pretty critical part of the question
    – Journeyman Geek
    Jul 17, 2016 at 7:50
  • they say the do but never tried myself; I think what they really do is combining every individual pdf bookmark into the compiled one. Just give it a try.
    – Pat
    Jul 17, 2016 at 14:10
  • I tried pdfsam but sadly it doesn't serve the needs mentioned in this question. You can may your answer.
    – claws
    Aug 18, 2016 at 17:50
0

I was having the same issue and landed up writing my own code using Excel VBA. I have uploaded the module to Github: https://github.com/markbrauning/BlueBeam-eX-Excel-Submittal-from-Folder-Structure

Note that this module requires that you are have Bluebeam eXtreme installed since this using the ScriptEngine command line to do the actual PDF merging.

Dim i As Long, k As Long
Dim scriptRevu As String
Dim SectionPDFpath As String
Dim PDFFilePath As String
Dim SectionFolder As String
Dim QuoteCheck As Boolean
For i = 0 To UBound(xFoldersList_temp, 2)
    SectionFolder = xFoldersList_temp(0, i)
    '---SectionPDFpath = ParentFolderPath + SubFolderName + .pdf
    SectionPDFpath = xFoldersList_temp(3, i) & "\" & xFoldersList_temp(1, i) & ".pdf"
    scriptRevu = "Open('" & SectionPDFpath & "', '')"
    QuoteCheck = Not GetFilesList(SectionFolder, False, "pdf", 0)
    If QuoteCheck Then GoTo Sub_Exit
    For k = 0 To UBound(xFilesList, 1)
        PDFFilePath = xFilesList(k)
        scriptRevu = scriptRevu & " " & "InsertPages(9999, '" & PDFFilePath & "', true, false, false, false, false)"
    Next k
    scriptRevu = scriptRevu & " Save('" & SectionPDFpath & "', 1)"
    scriptRevu = scriptRevu & " Close(true, 1)"
    RunRevuScript scriptRevu
    
    'if next script is for the next folder depth up, then wait for a few seconds
    If Not (i = UBound(xFoldersList_temp, 2)) Then
        If xFoldersList_temp(2, i) <> xFoldersList_temp(2, i + 1) Then
            waitdepth Int(xFoldersList_temp(2, i + 1)), 7
        End If
    End If
    
Next i

Where RunRevuScript is a function that send the written command through a shell

Sub RunRevuScript(RevuScript As String)
    Dim RevuPath As String
    Dim command As String    
    RevuPath = "C:\Program Files\Bluebeam Software\Bluebeam Revu\20\Revu\ScriptEngine.exe"
    command = RevuPath & " " & RevuScript
    Shell command, vbNormalFocus
    End sub

Hope this helps someone!

2
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    May 24, 2023 at 19:32
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – Destroy666
    May 24, 2023 at 19:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .