Turns a scanned PDF into text you can search, copy and edit, written into a Google Doc page by page.

UsesExtendGoogle DocsiLovePDF

Turn a multi-page scan into readable text

ValuesSet scanFile to blank.Set scanFile to blank.
ValuesSet scanLanguage to eng.Set scanLanguage to eng.
ValuesSet transcriptDocument to blank.Set transcriptDocument to blank.
ValuesSet maxPages to 40.Set maxPages to 40.
ValuesSet firstPage to 1.Set firstPage to 1.
TextTrim transcriptDocument and save it as documentLink.Trim transcriptDocument and save it as documentLink.
ValuesSet transcriptId to documentLink.Set transcriptId to documentLink.
Decisions & LoopsIf documentLink contains /d/If documentLink contains /d/
Yes
ListsGet the first item of the last item of documentLink split by /d/ split by / and save it as transcriptId.Get the first item of the last item of documentLink split by /d/ split by / and save it as transcriptId.
Else if @documentLink contains "/"
Decisions & LoopsStop and report a problem: The 'transcriptDocument' step does not look like a Google Docs link. Paste the link from the address bar while the document is open, or paste just its document id.Stop and report a problem: The 'transcriptDocument' step does not look like a Google Docs link. Paste the link from the address bar while the document is open, or paste just its document id.
Otherwise
No steps
Decisions & LoopsIf transcriptId is emptyIf transcriptId is empty
Yes
Decisions & LoopsStop and report a problem: No document id could be read out of the 'transcriptDocument' step. Paste the link from the address bar while the document is open.Stop and report a problem: No document id could be read out of the 'transcriptDocument' step. Paste the link from the address bar while the document is open.
No
No steps
MathRound maxPages to the nearest integer and save it as pageLimit.Round maxPages to the nearest integer and save it as pageLimit.
MathRound firstPage to the nearest integer and save it as startPage.Round firstPage to the nearest integer and save it as startPage.
FilesRead scanFile Save it as scanInfo.Read scanFile Save it as scanInfo.
TextUse scanInfo.pages, or 0 if it is empty and save it as pageCount.Use scanInfo.pages, or 0 if it is empty and save it as pageCount.
Decisions & LoopsIf pageCount is less than 1If pageCount is less than 1
Yes
Decisions & LoopsStop and report a problem: That file has no pages that can be read. Check 'scanFile' is the scanned PDF itself, not a link to a page that shows it.Stop and report a problem: That file has no pages that can be read. Check 'scanFile' is the scanned PDF itself, not a link to a page that shows it.
No
No steps
Decisions & LoopsIf startPage is greater than pageCountIf startPage is greater than pageCount
Yes
Decisions & LoopsStop and report a problem: The scan has pageCount pages, so there is nothing from page startPage on. Set 'firstPage' to 1, or to the page after the last one written, then run it again.Stop and report a problem: The scan has pageCount pages, so there is nothing from page startPage on. Set 'firstPage' to 1, or to the page after the last one written, then run it again.
No
No steps
MathSet pagesAfterFirst to pageLimit minus 1.Set pagesAfterFirst to pageLimit minus 1.
MathSet lastPage to startPage plus pagesAfterFirst.Set lastPage to startPage plus pagesAfterFirst.
Decisions & LoopsIf lastPage is greater than pageCountIf lastPage is greater than pageCount
Yes
ValuesChange lastPage to pageCount.Change lastPage to pageCount.
No
No steps
iLovePDFiLovePDFRun OCR on scanFile. Save it as searchableScan.Run OCR on scanFile. Save it as searchableScan.
TextTrim searchableScan.document_ref and save it as searchableRef.Trim searchableScan.document_ref and save it as searchableRef.
Decisions & LoopsIf searchableRef is null or searchableRef is emptyIf searchableRef is null or searchableRef is empty
Yes
Decisions & LoopsStop and report a problem: The scan could not be made searchable, so no text was read. Check the file is a PDF and that it is not password protected.Stop and report a problem: The scan could not be made searchable, so no text was read. Check the file is a PDF and that it is not password protected.
No
No steps
ExtendExtendParse a document. Save it as readPages.Parse a document. Save it as readPages.
TextTrim readPages.file_name and save it as scanTitle.Trim readPages.file_name and save it as scanTitle.
Decisions & LoopsIf scanTitle is null or scanTitle is emptyIf scanTitle is null or scanTitle is empty
Yes
ValuesChange scanTitle to Scanned document.Change scanTitle to Scanned document.
No
No steps
ValuesSet pagesFound to 0.Set pagesFound to 0.
ValuesSet pagesWritten to 0.Set pagesWritten to 0.
ValuesSet pagesBlank to 0.Set pagesBlank to 0.
ValuesSet pagesFailed to 0.Set pagesFailed to 0.
ValuesSet lastWriteProblem to blank.Set lastWriteProblem to blank.
Dates & TimesGet today's date and save it as today.Get today's date and save it as today.
Dates & TimesMake today readable as โ€œMonday, November 2, 2026โ€ and save it as readDate.Make today readable as โ€œMonday, November 2, 2026โ€ and save it as readDate.
Decisions & LoopsIf a step below fails, save the error as headingErrorIf a step below fails, save the error as headingError
Try
Google DocsGoogle DocsAdd text to transcriptId. Save it as spacer.Add text to transcriptId. Save it as spacer.
Google DocsGoogle DocsAdd the heading '@scanTitle, read on readDate' to transcriptId. Save it as scanHeading.Add the heading '@scanTitle, read on readDate' to transcriptId. Save it as scanHeading.
On error
ValuesShow in the output: The heading for this scan could not be written: headingError.message.Show in the output: The heading for this scan could not be written: headingError.message.
Decisions & LoopsFor each page in readPages.chunks:For each page in readPages.chunks:
ValuesAdd 1 to pagesFound.Add 1 to pagesFound.
Decisions & LoopsIf pagesWritten is greater than or equal to pageLimitIf pagesWritten is greater than or equal to pageLimit
Yes
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
TextTrim page.content and save it as pageText.Trim page.content and save it as pageText.
Decisions & LoopsIf pageText is null or pageText is emptyIf pageText is null or pageText is empty
Yes
ValuesAdd 1 to pagesBlank.Add 1 to pagesBlank.
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
TextReplace the pattern (?m)^[ \t]*#{1,6}[ \t]+|^[ \t]*\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)*\|?[ \t]*(?:\n|$)|^[ \t]*\|[ \t]*|[ \t]*\|[ \t]*$|\*\* with in pageText and save it as plainText.Replace the pattern (?m)^[ \t]*#{1,6}[ \t]+|^[ \t]*\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)*\|?[ \t]*(?:\n|$)|^[ \t]*\|[ \t]*|[ \t]*\|[ \t]*$|\*\* with in pageText and save it as plainText.
Decisions & LoopsIf a step below fails, save the error as pageErrorIf a step below fails, save the error as pageError
Try
Google DocsGoogle DocsAdd the heading 'Page page.page_start' to transcriptId. Save it as pageHeading.Add the heading 'Page page.page_start' to transcriptId. Save it as pageHeading.
Google DocsGoogle DocsAdd text to transcriptId. Save it as pageWritten.Add text to transcriptId. Save it as pageWritten.plainText
ValuesAdd 1 to pagesWritten.Add 1 to pagesWritten.
On error
ValuesAdd 1 to pagesFailed.Add 1 to pagesFailed.
ValuesChange lastWriteProblem to pageError.message.Change lastWriteProblem to pageError.message.
ValuesShow in the output: Page page.page_start could not be written: pageError.message.Show in the output: Page page.page_start could not be written: pageError.message.
Decisions & LoopsIf pagesFound is 0If pagesFound is 0
Yes
Decisions & LoopsStop and report a problem: No pages came back from that scan, so nothing was written. Check the file is the scan itself and that it has at least one page.Stop and report a problem: No pages came back from that scan, so nothing was written. Check the file is the scan itself and that it has at least one page.
No
No steps
Decisions & LoopsIf pagesWritten is 0 and pagesFailed is greater than 0If pagesWritten is 0 and pagesFailed is greater than 0
Yes
Decisions & LoopsStop and report a problem: No page could be written to your Google Doc (lastWriteProblem). Check the link in 'transcriptDocument' and that your Google Docs connection can edit that Doc, then run it again.Stop and report a problem: No page could be written to your Google Doc (lastWriteProblem). Check the link in 'transcriptDocument' and that your Google Docs connection can edit that Doc, then run it again.
No
No steps
Decisions & LoopsIf pagesWritten is 0If pagesWritten is 0
Yes
Decisions & LoopsStop and report a problem: No readable text was found on any page, so nothing was written. A photograph of a page at an angle, or a scan set to the wrong language, both look like this - check 'scanLanguage' and try a straighter scan.Stop and report a problem: No readable text was found on any page, so nothing was written. A photograph of a page at an angle, or a scan set to the wrong language, both look like this - check 'scanLanguage' and try a straighter scan.
No
No steps
MathSet pagesMissing to pagesFound minus pagesWritten.Set pagesMissing to pagesFound minus pagesWritten.
ValuesSet runSummary to pagesFound pages were read and pagesWritten were written. pagesBlank had no readable text and pagesFailed failed to write.Set runSummary to pagesFound pages were read and pagesWritten were written. pagesBlank had no readable text and pagesFailed failed to write.
MathSet nextPage to lastPage plus 1.Set nextPage to lastPage plus 1.
ValuesSet pagesLeftNote to blank.Set pagesLeftNote to blank.
Decisions & LoopsIf pageCount is greater than lastPageIf pageCount is greater than lastPage
Yes
TextBuild the text Pages @nextPage to @pageCount of the scan were not read this time: set 'firstPage' to @nextPage and run it again to add them below, without repeating the pages... and save it as pagesLeftNote.Build the text Pages @nextPage to @pageCount of the scan were not read this time: set 'firstPage' to @nextPage and run it again to add them below, without repeating the pages... and save it as pagesLeftNote.
No
No steps
Decisions & LoopsIf pagesMissing is greater than 0 or pagesLeftNote isn't emptyIf pagesMissing is greater than 0 or pagesLeftNote isn't empty
Yes
Decisions & LoopsIf a step below fails, save the error as noteErrorIf a step below fails, save the error as noteError
Try
Google DocsGoogle DocsAdd text to transcriptId. Save it as noteWritten.Add text to transcriptId. Save it as noteWritten.[INCOMPLETE] runSummary@pagesLeftNote The pages above are not the whole scan.
On error
ValuesShow in the output: The incomplete-scan note could not be written: noteError.message.Show in the output: The incomplete-scan note could not be written: noteError.message.
Decisions & LoopsIf pagesFailed is greater than 0If pagesFailed is greater than 0
Yes
Decisions & LoopsStop and report a problem: runSummary plus pagesLeftNote.Stop and report a problem: runSummary plus pagesLeftNote.
No
Decisions & LoopsFinish the run: runSummary plus pagesLeftNote.Finish the run: runSummary plus pagesLeftNote.
No
ValuesShow in the output: runSummary.Show in the output: runSummary.