PDF上のテキストと座標を取得

TOP > *      [...]

コスプレ

概要

PDFのページ上に存在するテキスト情報を取得する為の技術情報です。

  1. テキスト:
    ページ上に有るテキストを取得します。全テキストも、前から何番目のテキストとしての抽出も出来ます。半角と全角文字(日本語)の場合は扱いが変わります。
     
  2. テキストの座標:
    該当テキストをページ左下を基点として、右端(Left)、上部(Top)、下部(bottom)、左端(Right)の4つの値で取得できます。全角文字は一文字単位、半角英字は連続テキスト単位、数字は並びの単位、記号は出現時での座標が取得できます。
     
  3. ページ内の全テキスト領域の座標:
    ページ上に存在する全テキストの領域を、右端(Left)、上部(Top)、下部(bottom)、左端(Right)の4つの値で取得できます。よってページにより値は変化する場合が有ります。 

コレ以外に「選択中のテキストの情報」や「Acrobat JavaScriptからの操作」も有りますが、ココでは省略します。

 

抽出の区切り

PDF上のテキストは1文字単位では無く、一定の区切りを持っています。

例えば以下の場合

Acrobat OLEで抽出する時の区切りを青線で表示すると

※↑↓クリックで拡大表示

になります。上記の青線はAcrobat OLEが返すテキスト領域の座標を使ってAcrobat OLEで描いています。

区切りの基本は、半角の空白、記号、又は改行です。それ以外は以下となります。

  • 半角の英字:次の空白、改行、又は次の全角で区切り
  • 半角の数字:次の空白、改行、又は次の全角で区切り
  • 半角の記号:出現した後で区切り
  • 全角文字:1文字単位で区切り

この区切りの単位で座標「右端(Left)、上部(Top)、下部(bottom)、左端(Right)」が取得できます。2文字以上のテキストで特定の文字の座標が欲しいときは文字数で計算する必要が有ります。

区切りの条件を変更する設定等は存在しません。

 

 

抽出されたテキスト

Acrobat OLE(IAC)のテキスト抽出のパターンは2つ存在します。上記サンプルPDFから抽出したテキストの一部で見比べてみます。

以下は

  • [Space(1)]:半角スペース1個
  • [CRLF]:改行コード

を意味します。

Seq パターン① パターン②
1 Windows[Space(1)] Windows
2 10[Space(1)] 10
3 Home[Space(1)] Home
4 64 64
5
6
7 [CRLF]
8 CPU[Space(1)] CPU
9 Core[Space(1)] Core
10 i5- i5-
11 9400[CRLF] 9400
12
13
14
15
16 Core[Space(1)] Core
17 i5- i5-
18 9400[Space(1)] 9400
19 ( (
20 2.90GHz- 2.90GHz-
21 4.10GHz/ 4.10GHz/
22 6 6
23
24
25 / /
26 6 6
27
28
29
30
31 )[CRLF] )

パターン①はテキスト(単語)の区切りの判断として、半角1文字の空白、又は改行コードが使えるのが特徴です。

 

抽出パターンの特徴

  1. パターン①
    • 特徴:
      • ページ全体のテキスト抽出が高速で出来る
      • テキストの最後の半角空白や改行コードでテキスト(単語)の区切りが判断可能
    • 問題点:
      • テキスト単位の座標は取得できない
        ページ全体のテキスト領域の座標しか取得できない
  2. パターン②
    • 特徴:
      • テキストとその座標が取得できる
    • 問題点:
      • テキストの区切り、改行が判断できない
        座標を見たら判断可能かもしれないがかなり微妙!
      • テキスト別の座標の取得には処理時間が掛かる

処理速度を考えると部分的に組み合わせて使う必要も有ります。

 

テキストの座標

1文字単位では無いですが、テキスト領域の座標が取得できます。

ページ左下を基点として、上部(Top)、下部(bottom)、右端(Left)、左端(Right)の4つの値で取得できます。

ピタリの値では無いので、使う場合は1~2の微調整が必要になる場合が有ります。

 

VBAのサンプル

テキスト抽出はAcroPDTextSelectオブジェクトのGetTextメソッドで行います。ただし、途中のオブジェクト操作によってGetTextメソッドの結果が前述のパターン①、パターン②に変わります。

CreatePageHilite での文字列抽出は不可解な結果が出る場合が有るので使用は推奨しません。CreateWordHilite のみを使う前提で解説します。

ダウンロード:Sample-Get-Text-Rect.xls

パターン①:

001 Option Explicit 002 003 Sub Main_Patern_1() 004 005 Dim i1 As Long 006 Dim i2 As Long 007 Dim j As Long 008 Dim iCnt As Long 009 Dim iPageNo As Long 010 Dim iPageCnt As Long 011 Dim iRet As Long 012 Dim bRet As Boolean 013 Dim sGetText(1000) As String 014 015 Dim objAcroApp As New Acrobat.AcroApp 016 Dim objAcroAVDoc As New Acrobat.AcroAVDoc 017 Dim objAcroPDDoc As New Acrobat.AcroPDDoc 018 Dim objAcroPDPage As Acrobat.AcroPDPage 019 Dim objAcroHiliteList As New Acrobat.AcroHiliteList 020 Dim objAcroPDTextSelect As Acrobat.AcroPDTextSelect 021 022 Dim sFilePathIn As String 023 sFilePathIn = ThisWorkbook.Path & "\test-001.pdf" 024 objAcroApp.CloseAllDocs 025 objAcroApp.Hide '稀にデスクトップに表示されるので隠す 026 'PDFファイルを開く 027 bRet = objAcroAVDoc.Open(sFilePathIn, "") 028 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc 029 iPageCnt = objAcroPDDoc.GetNumPages 030 031 i2 = 0 032 For iPageNo = 0 To iPageCnt - 1 033 'ページ単位のPDPageオブジェクトを作成 034 Set objAcroPDPage = objAcroPDDoc.AcquirePage(iPageNo) 035 'ハイライトリストを作成 036 Set objAcroHiliteList = Nothing '先にクリア 037 iRet = objAcroHiliteList.Add(0, 32767) 038 If objAcroHiliteList Is Nothing Then 039 'ページにテキストが無い 040 Exit For 041 End If 042 'テキスト選択のPDTextSelectオブジェクトを作成 043 Set objAcroPDTextSelect = _ 044 objAcroPDPage.CreateWordHilite(objAcroHiliteList) 045 If objAcroPDTextSelect Is Nothing Then _ 046 GoTo Main_Patern_1_skip1: 047 '抽出した文字列の数(Index)を取得 048 iCnt = objAcroPDTextSelect.GetNumText() - 1 049 For j = 0 To iCnt 050 sGetText(i2) = objAcroPDTextSelect.GetText(j) 051 ' sGetText(i2) = Replace(sGetText(i2), " ", "[Space(1)]") 052 ' sGetText(i2) = Replace(sGetText(i2), vbCrLf, "[CRLF]") 053 i2 = i2 + 1 054 Next j 055 Main_Patern_1_skip1: 056 Next iPageNo 057 058 '★ 059 '★sGetText(i2):抽出した全テキスト 060 '★ 061 Debug.Print "Get件数=" & i2 062 063 '変更しないで閉じます。 064 bRet = objAcroAVDoc.Close(False) 065 'Acrobatアプリケーションの終了 066 objAcroApp.Hide 067 objAcroApp.Exit 068 'オブジェクトの開放 069 Set objAcroHiliteList = Nothing 070 Set objAcroPDTextSelect = Nothing 071 Set objAcroPDPage = Nothing 072 Set objAcroPDDoc = Nothing 073 Set objAcroAVDoc = Nothing 074 Set objAcroApp = Nothing 075 076 End Sub


 Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
 

パターン②:

001 Option Explicit 002 003 Sub Main_Patern_2() 004 005 Dim i1 As Long 006 Dim i2 As Long 007 Dim iCnt As Long 008 Dim iPageNo As Long 009 Dim iPageCnt As Long 010 Dim iRet As Long 011 Dim bRet As Boolean 012 Dim sGetText(1000) As String 013 Dim sGetTextXY(1000, 3) As Long 014 015 Dim objAcroApp As New Acrobat.AcroApp 016 Dim objAcroAVDoc As New Acrobat.AcroAVDoc 017 Dim objAcroPDDoc As New Acrobat.AcroPDDoc 018 Dim objAcroPDPage As Acrobat.AcroPDPage 019 Dim objAcroPoint As Acrobat.AcroPoint 020 Dim objAcroHiliteList As New Acrobat.AcroHiliteList 021 Dim objAcroAVPageView As Acrobat.AcroAVPageView 022 Dim objAcroPDTextSelect As Acrobat.AcroPDTextSelect 023 Dim objAcroRect As Acrobat.AcroRect 024 025 Dim sFilePathIn As String 026 sFilePathIn = ThisWorkbook.Path & "\test-001.pdf" 027 objAcroApp.CloseAllDocs 028 objAcroApp.Hide '稀にデスクトップに表示されるので隠す 029 'PDFファイルを開く 030 bRet = objAcroAVDoc.Open(sFilePathIn, "") 031 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc 032 iPageCnt = objAcroPDDoc.GetNumPages 033 034 i2 = 0 035 For iPageNo = 0 To iPageCnt - 1 036 'ページ単位のPDPageオブジェクトを作成 037 Set objAcroPDPage = objAcroPDDoc.AcquirePage(iPageNo) 038 For i1 = 0 To 9999 039 'ハイライトリストを作成 040 Set objAcroHiliteList = Nothing '先にクリア 041 iRet = objAcroHiliteList.Add(i1, 1) 042 If objAcroHiliteList Is Nothing Then 043 'ページにテキストが無い 044 Exit For 045 End If 046 'テキスト選択のPDTextSelectオブジェクトを作成 047 Set objAcroPDTextSelect = _ 048 objAcroPDPage.CreateWordHilite(objAcroHiliteList) 049 If objAcroPDTextSelect Is Nothing Then _ 050 GoTo Main_Patern_2_skip1: 051 '抽出した文字列の数(Index)を取得:0が返される 052 iCnt = objAcroPDTextSelect.GetNumText() - 1 053 sGetText(i2) = objAcroPDTextSelect.GetText(0) 054 ' sGetText(i2) = Replace(sGetText(i2), " ", "[Space(1)]") 055 ' sGetText(i2) = Replace(sGetText(i2), vbCrLf, "[CRLF]") 056 '四方範囲(AcroRect)を取得 057 Set objAcroRect = _ 058 objAcroPDTextSelect.GetBoundingRect 059 With objAcroRect 060 sGetTextXY(i2, 0) = .Top 061 sGetTextXY(i2, 1) = .bottom 062 sGetTextXY(i2, 2) = .Left 063 sGetTextXY(i2, 3) = .Right 064 End With 065 ' Debug.Print i2 + 1 & "=[" & sGetText(i2) & _ 066 ' "] Top=" & sGetTextXY(i2, 0) & _ 067 ' " Bottom=" & sGetTextXY(i2, 1) & _ 068 ' " Left=" & sGetTextXY(i2, 2) & _ 069 ' " Right=" & sGetTextXY(i2, 3) 070 i2 = i2 + 1 071 Next i1 072 Main_Patern_2_skip1: 073 Next iPageNo 074 075 '★ 076 '★sGetText(i2)   :抽出したテキスト 077 '★sGetTextXY(i2, 3):テキストに対応した座標 078 Debug.Print "Get件数=" & i2 079 080 '変更しないで閉じます。 081 bRet = objAcroAVDoc.Close(False) 082 'Acrobatアプリケーションの終了 083 objAcroApp.Hide 084 objAcroApp.Exit 085 'オブジェクトの開放 086 Set objAcroHiliteList = Nothing 087 Set objAcroAVPageView = Nothing 088 Set objAcroPDTextSelect = Nothing 089 Set objAcroRect = Nothing 090 Set objAcroPDPage = Nothing 091 Set objAcroPoint = Nothing 092 Set objAcroPDDoc = Nothing 093 Set objAcroAVDoc = Nothing 094 Set objAcroApp = Nothing 095 End Sub


 Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
 

 

ページ内の全テキスト領域の座標

概要の3番目に書いた部分です。使い道が有るかは疑問ですが紹介します。

以下を見てください。ページの上部にテキストが集中して表示されています。その青線で囲った領域の座標を言います。

それを取得するサンプルです。Debug.Print でページ単位に表示しています。

001 Option Explicit 002 003 Sub Main_Patern_3() 004 Dim i1 As Long 005 Dim iPageNo As Long 006 Dim iPageCnt As Long 007 Dim iRet As Long 008 Dim bRet As Boolean 009 010 Dim objAcroApp As New Acrobat.AcroApp 011 Dim objAcroAVDoc As New Acrobat.AcroAVDoc 012 Dim objAcroPDDoc As New Acrobat.AcroPDDoc 013 Dim objAcroPDPage As Acrobat.AcroPDPage 014 Dim objAcroHiliteList As New Acrobat.AcroHiliteList 015 Dim objAcroPDTextSelect As Acrobat.AcroPDTextSelect 016 Dim objAcroRect As Acrobat.AcroRect 017 018 Dim sFilePathIn As String 019 sFilePathIn = ThisWorkbook.Path & "\test-001.pdf" 020 objAcroApp.CloseAllDocs 021 objAcroApp.Hide '稀にデスクトップに表示されるので隠す 022 'PDFファイルを開く 023 bRet = objAcroAVDoc.Open(sFilePathIn, "") 024 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc 025 iPageCnt = objAcroPDDoc.GetNumPages 026 027 For iPageNo = 0 To iPageCnt - 1 028 'ページ単位のPDPageオブジェクトを作成 029 Set objAcroPDPage = objAcroPDDoc.AcquirePage(iPageNo) 030 'ハイライトリストを作成 031 Set objAcroHiliteList = Nothing '先にクリア 032 iRet = objAcroHiliteList.Add(0, 32767) 033 If objAcroHiliteList Is Nothing Then 034 'ページにテキストが無い 035 Exit For 036 End If 037 'テキスト選択のPDTextSelectオブジェクトを作成 038 Set objAcroPDTextSelect = _ 039 objAcroPDPage.CreateWordHilite(objAcroHiliteList) 040 If objAcroPDTextSelect Is Nothing Then _ 041 GoTo Main_Patern_3_skip1: 042 043 '四方範囲(AcroRect)を取得 044 Set objAcroRect = _ 045 objAcroPDTextSelect.GetBoundingRect 046 With objAcroRect 047 Debug.Print "PageNo=" & iPageNo + 1 & _ 048 " Top=" & .Top & _ 049 " Bottom=" & .bottom & _ 050 " Left=" & .Left & _ 051 " Right=" & .Right 052 End With 053 054 Main_Patern_3_skip1: 055 Next iPageNo 056 057 '変更しないで閉じます。 058 bRet = objAcroAVDoc.Close(False) 059 'Acrobatアプリケーションの終了 060 objAcroApp.Hide 061 objAcroApp.Exit 062 'オブジェクトの開放 063 Set objAcroRect = Nothing 064 Set objAcroHiliteList = Nothing 065 Set objAcroPDTextSelect = Nothing 066 Set objAcroPDPage = Nothing 067 Set objAcroPDDoc = Nothing 068 Set objAcroAVDoc = Nothing 069 Set objAcroApp = Nothing 070 End Sub


 Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
 

当然ですがヘッダーやフッターが存在すると領域はドンと広がります。

 

処理速度

使用に耐えられない程の処理時間がかかってしまう場合が有ります。それは、

iRet = objAcroHiliteList.Add( x , y )

のヒントリストを作成する処理です。この命令はパソコンスペックにかなり依存します。

処理時間がかかり過ぎる場合は、上記の使用を抑えたロジックに見直して下さい。

 

注意

PDF上のテキストをAcrobatアプリケーションや他のツールで修正を行うと、座標に関する情報に乱れが発生する場合が見受けられます。

この場合は座標に関する情報が正しく取得できません。これに対する対象方法は無く、PDFを最初から作り直すしか手がないです。

 

参照

 

Acrobat JavaScriptの応用

Acrobat OLEからAcrobat JavaScriptを起動(ExecuteThisJavascript)することができます。そうすればハイライト処理やテキストに注釈の追加も出来ます。

しかし、現段階では範囲が広すぎて手が付けられません。時間が出来た時に紹介したいと思います。

 


 

管理者メモ

これ以降は管理者の技術メモです。サイトを後でメンテする為の情報なので、見なくても結構です。


VBAからPDF上のテキスト領域の区切り座標を青線で表示。手作業で枠を引くのが結構面倒なので。しかし、かえって座標の値の確認が出来て、重宝!

AFormFields.ExecuteThisJavascriptを使って、Acrobat JavaScriptを実行。四角の注釈をテキスト上に表示。線幅は0.3ポイント。マニュアルにwidthは1からみたいな雰囲気で書かれていたが、小数点値も使える。

折角なので機能を追加。SW1をFlaseにすると、注釈に座標の情報も一緒に追加&表示。

以下のVBAで作成。コメントは未Update&未再確認。不要なロジック多少有り。公開専用では無いので放置。

001 Option Explicit 002 003 Sub Main_Add_Annot() 004 Const iMax As Long = 200 005 006 Dim i1 As Long 007 Dim i2 As Long 008 Dim j As Long 009 Dim iCnt As Long 010 Dim iPageNo As Long '処理したページ数 011 Dim iPageCnt As Long 012 Dim iRet As Long 013 Dim bRet As Boolean 014 Dim sGetText(1000) As String 015 Dim sGetTextXY(1000, 3) As Long 016 Dim iButtonCnt As Long '登録した数 017 018 Dim objAcroApp As New Acrobat.AcroApp 019 Dim objAcroAVDoc As New Acrobat.AcroAVDoc 020 Dim objAcroPDDoc As New Acrobat.AcroPDDoc 021 Dim objAcroPDPage As Acrobat.AcroPDPage 022 Dim objAcroPoint As Acrobat.AcroPoint 023 Dim objAcroHiliteList As New Acrobat.AcroHiliteList 024 Dim objAcroAVPageView As Acrobat.AcroAVPageView 025 Dim objAcroPDTextSelect As Acrobat.AcroPDTextSelect 026 Dim objAcroRect As Acrobat.AcroRect 027 028 Dim objAFormApp As AFORMAUTLib.AFormApp 029 Dim objAFormFields As AFORMAUTLib.Fields 030 Dim objAFormField As AFORMAUTLib.Field 031 032 Dim sFilePathIn As String 033 Dim sFilePathOut As String 034 035 Dim sAJS As String 036 Dim sReturn As String 037 038 Const SW1 = False 039 Const sAcrobatJavaScript = _ 040 "oRet = this.addAnnot({type: ""Square"", " & _ 041 "rect:[@1,@2,@3,@4], " & _ 042 "page:@p , " & _ 043 "strokeColor:color.blue , width:0.3 }); " 044 Const sAcrobatJavaScript2 = _ 045 "oRet = this.addAnnot({type: ""Square"", " & _ 046 "rect:[@1,@2,@3,@4], " & _ 047 "page:@p , " & _ 048 "strokeColor:color.blue , width:0.3 , contents:""@t""}); " 049 050 sFilePathIn = ThisWorkbook.Path & "\test-001.pdf" 051 sFilePathOut = ThisWorkbook.Path & "\test-001_New.pdf" 052 053 objAcroApp.CloseAllDocs 054 objAcroApp.Hide '稀にデスクトップに表示されるので隠す 055 056 'PDFファイルを開く 057 bRet = objAcroAVDoc.Open(sFilePathIn, "") 058 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc 059 iPageCnt = objAcroPDDoc.GetNumPages 060 061 Set objAFormApp = CreateObject("AFormAut.App") 062 Set objAFormFields = objAFormApp.Fields 063 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc 064 065 i2 = 0 066 For iPageNo = 0 To iPageCnt - 1 067 'ページ単位のPDPageオブジェクトを作成 068 Set objAcroPDPage = objAcroPDDoc.AcquirePage(iPageNo) 069 For i1 = 0 To 9999 070 'ハイライトリストを作成 071 Set objAcroHiliteList = Nothing '先にクリアが必要 072 iRet = objAcroHiliteList.Add(i1, 1) 073 If objAcroHiliteList Is Nothing Then 074 'ページにテキストが無い 075 Exit For 076 End If 077 'テキスト選択のPDTextSelectオブジェクトを作成 078 Set objAcroPDTextSelect = _ 079 objAcroPDPage.CreateWordHilite(objAcroHiliteList) 080 If objAcroPDTextSelect Is Nothing Then GoTo skip1: 081 '抽出した文字列の数(Index)を取得:0が返される 082 iCnt = objAcroPDTextSelect.GetNumText() - 1 083 084 '※半角英字は単語単位、日本語は1文字単位 085 sGetText(i2) = objAcroPDTextSelect.GetText(0) 086 '四方範囲(AcroRect)を取得 087 Set objAcroRect = objAcroPDTextSelect.GetBoundingRect 088 With objAcroRect 089 sGetTextXY(i2, 0) = .Top 090 sGetTextXY(i2, 1) = .bottom 091 sGetTextXY(i2, 2) = .Left 092 sGetTextXY(i2, 3) = .Right 093 End With 094 Debug.Print i2 + 1 & "=[" & sGetText(i2) & _ 095 "] Top=" & sGetTextXY(i2, 0) & _ 096 " Bottom=" & sGetTextXY(i2, 1) & _ 097 " Left=" & sGetTextXY(i2, 2) & _ 098 " Right=" & sGetTextXY(i2, 3) 099 iButtonCnt = iButtonCnt + 1 100 101 'Acrobat JavaScriptの作成 102 With objAcroRect 103 If SW1 Then 104 sAJS = sAcrobatJavaScript 105 Else 106 sAJS = sAcrobatJavaScript2 107 sAJS = Replace(sAJS, "@t", _ 108 "Top=" & .Top & _ 109 " Bottom=" & .bottom & _ 110 " Left=" & .Left & _ 111 " Right=" & .Right) 112 End If 113 sAJS = Replace(sAJS, "@1", .Left) 114 sAJS = Replace(sAJS, "@2", .bottom) 115 sAJS = Replace(sAJS, "@3", .Right) 116 sAJS = Replace(sAJS, "@4", .Top) 117 sAJS = Replace(sAJS, "@p", iPageNo) 118 End With 119 'Acrobat JavaScript の実行 120 sReturn = objAFormFields.ExecuteThisJavascript(sAJS) 121 122 i2 = i2 + 1 123 If i2 > iMax Then Exit For 124 Next i1 125 If i2 > iMax Then Exit For 126 skip1: 127 Next iPageNo 128 '更新したら別名で保存 129 If iButtonCnt > 0 Then 130 'PDFファイルを別名で保存 131 bRet = objAcroPDDoc.Save(1, sFilePathOut) 132 If bRet = False Then 133 MsgBox "PDFファイルへ保存出来ませんでした", _ 134 vbOKOnly + vbCritical, "実行エラー" 135 End If 136 End If 137 Debug.Print "Get=" & i2 138 '変更しないで閉じます。 139 bRet = objAcroAVDoc.Close(False) 140 'Acrobatアプリケーションの終了 141 objAcroApp.Hide 142 objAcroApp.Exit 143 'オブジェクトの開放 144 Set objAcroHiliteList = Nothing 145 Set objAcroAVPageView = Nothing 146 Set objAcroPDTextSelect = Nothing 147 Set objAFormFields = Nothing 148 Set objAFormField = Nothing 149 Set objAcroRect = Nothing 150 Set objAcroPDPage = Nothing 151 Set objAcroPoint = Nothing 152 Set objAcroPDDoc = Nothing 153 Set objAcroAVDoc = Nothing 154 Set objAcroApp = Nothing 155 End Sub


 Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


出来るだけ早く返答する様には心がけています。
が、遅くなる時もありますのでご了承ください。


SAMURAI Plugin

コメントをする時は出来れば以下もお願いします。

  • OS名 バージョン
  • Acrobat バージョン
  • ツール(Excel等) バージョン
コメントにサンプルコードを入れるとエラーになる場合が有ります。その時はコードの前後に <code> ・・・</code> タグを入れてください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください