前提・実現したいこと
######PDFファイルから文字や数字を抽出してExcelのシートにデータとして表を作成したいのですが、どのように処理したらよろしいでしょうか。
当方、Excelマクロについても初心者であるため、以下の環境を提示させていただいていますが、情報不足でしたら追加で情報を載せたいと思います。
・処理するpdfは1ページを縦に2分割して記載されているデータ。しかし、.txtだと2分割されず順番に記載された形で出てくる。
・読み込みたいpdfは約1500枚あるため、個々のpdfから特定の事項を抽出してExcelシートに書き込めるようにしたい。
例) PDF:
【ゲーム1】
0000
〇〇グループ
【参加者数】
合計 | 午前 | 午後1 | 午後2 | 夜間 | 他 | |
---|---|---|---|---|---|---|
男 | 20 | 5 | 10 | 0 | 4 | 1 |
女 | 20 | 5 | 10 | 0 | 4 | 1 |
男女計 | 40 | 10 | 20 | 0 | 8 | 2 |
参加の補助・諸制度
【プレイ時間】20時間/月
【追加料金】70,000円/月
【時間効率化の取り組み】行っている
【その他の諸制度】お弁当制度(ただしコアタイムにいる人(11:00~14:00)、昼休憩
(12:00~12:50))/短時間補助制度((補助が必要な方、もしくはそれに準ずる方)/半
日単位の追加ボーナス制度(午前(8:00~12:00)、午後(12:50~16:30))
⇒ Excel:
|コード|種別|名前|参加者数(男)|参加者数(女)|参加者数(合計)|プレイ時間|追加料金|時間効率化の取り組み|半日単位の追加ボーナス制度|
|:--|:--:|:--:|:--:|:--:|--:|
|0000|ゲーム1|〇〇グループ|20|20|40|20.0|70000|1|1|
・行っているの場合は「1」,無しの場合は「0」
念のため「.txt」だと以下のように表示されました。
【ゲーム1】
0000
〇〇グループ
(中略)
【参加者数】 合計 午前 午後1 午後2 夜間 他
男 20 5 10 0 4 1
女 20 5 10 0 4 1
男女計 40 10 20 0 8 2
参加の補助・諸制度
【プレイ時間】20.0時間/月
【追加料金】70,000円/月
【時間効率化の取り組み】行っている
【その他の諸制度】お弁当制度(ただしコアタイムにいる人(11:00~14:00)、昼休憩
(12:00~12:50))/短時間補助制度((補助が必要な方、もしくはそれに準ずる方)/半
日単位の追加ボーナス制度(午前(8:00~12:00)、午後(12:50~16:30))
・pdfはコピーした時に文字化けしない。
・Acrobat DCは購入済み。
・pdfファイルによって項目の回答の有無がある。
発生している問題・エラーメッセージ
実行時エラー13 型が一致しません 下から7行目のkingaku = kingaku + str(k + 2)に矢印が出ます。
該当のソースコード
VBA
1'---コード1|フォルダ内のPDFファイルを1つずつ処理する 2Option Explicit 3Sub filecheck() 4 Dim s1, s2, s3, filename, path, xmlpath 5 Dim i, cmax 6 Dim t1, t2 7 Dim ws1, ws2 As Worksheet 8 Set ws1 = Worksheets("Sheet1") 9 10 Dim fs As FileSystemObject 11 Dim basefolder As Scripting.Folder 12 Dim destifolder, filepath As String 13 14 Dim mysubfiles As Scripting.files 15 Dim mysubfile As Scripting.file 16 17 cmax = ws1.Range("A65536").End(xlUp).Row 18 Set fs = New Scripting.FileSystemObject 19 20 filepath = "C:/Users/名前/Documents/2019/" 21 22 Set basefolder = fs.GetFolder(filepath) 23 Set mysubfiles = basefolder.files 24 25 26 For Each mysubfile In mysubfiles 27 Debug.Print mysubfile.Name 28 Debug.Print fs.GetExtensionName(mysubfile) 29 Debug.Print fs.GetParentFolderName(mysubfile) 30 31 If fs.GetExtensionName(path:=mysubfile) = "pdf" Then 32 33 path = fs.GetParentFolderName(path:=mysubfile) 34 xmlpath = xmlurl(mysubfile.Name, path) 35 Call xml_parse(xmlpath) 36 End If 37 Next 38 39End Sub 40'---コード2|PDF毎にxml化する 41Function xmlurl(filename, path) 42 43 Dim objAcroApp As New Acrobat.AcroApp 44 Dim objAcroAVDoc As New Acrobat.AcroAVDoc 45 Dim objAcroPDDoc As Acrobat.AcroPDDoc 46 Dim id 47 Dim js 48 Dim fullpath, savename As String 49 50 fullpath = path & "\" & filename 51 Debug.Print fullpath 52 id = objAcroApp.Show 'Acrobatアプリケーションを起動する。 53 id = objAcroAVDoc.Open(fullpath, "") 54 Set objAcroPDDoc = objAcroAVDoc.GetPDDoc() 55 'JavaScriptオブジェクトを作成する。 56 Set js = objAcroPDDoc.GetJSObject 57 savename = Replace(fullpath, ".pdf", "") 58 js.SaveAs savename & ".xml", "com.adobe.acrobat.xml-1-00" 59 60 'PDFファイルを変更無しで閉じます。 61 id = objAcroAVDoc.Close(1) 62 'Acrobatアプリケーションを終了する。 63 id = objAcroApp.Hide 64 id = objAcroApp.Exit 65 'OLEを行うとAcrobatが不安定になるので、 66 '一応オブジェクトを強制開放する。 67 Set js = Nothing 68 Set objAcroAVDoc = Nothing 69 Set objAcroApp = Nothing 70 71 xmlurl = savename & ".xml" 72 73End Function 74 75'---コード2|フォルダ内のPDFファイルだけを抽出 76Sub xml_parse(ByVal xmlpath As String) 77'Microsoft XML v6.0 を参照設定 78 Dim XMLDocument As MSXML2.DOMDocument60 79 Dim pElem As MSHTML.HTMLParaElement 80 'Dim Doc As New XMLDocument 81 Dim e As MSHTML.HTMLHtmlElement 82 Dim ws1 As Worksheet 83 84 Set ws1 = Worksheets("Sheet1") 85 86 'MSXMLオブジェクトを生成し、xmlファイルをロード 87 Set XMLDocument = New MSXML2.DOMDocument60 88 89 'async = False → 読み込み終了後、次の処理をします(同期処理) 90 'async = true →だと、読み込みが終わらなくても、次のステップへ(非同期処理) 91 'VBAは非同期処理に対応していないので、async = Falseとします 92 XMLDocument.async = False 93 94 Dim strMsg As String 95 Dim i, j, k, cmax, n As Long 96 97 i = 0 98 cmax = ws1.Range("A1048576").End(xlUp).Row 99 'Doc.Load (xmlpath) 100 XMLDocument.Load (xmlpath) 101 102 If (XMLDocument.parseError.ErrorCode <> 0) Then 'ロード失敗 103 104 strMsg = XMLDocument.parseError.reason 'エラー内容を出力 105 106 MsgBox "ロードに失敗しました・・・" & vbCrLf & vbCrLf & strMsg, vbCritical 107 108 Exit Sub 109 110 End If 111 112 ws1.Range("A" & cmax + 1).Value = cmax 113 114 Dim objxml As Object 115 Dim tmp As Variant 116 117 For Each objxml In XMLDocument.getElementsByTagName("P") 118 If InStr(objxml.XML, "請求番号") > 0 Then 119 120 tmp = Split(objxml.Text, ":") 121 122 For k = 0 To UBound(tmp) 123 Debug.Print tmp(k) 124 If InStr(tmp(k), "請求日") > 0 And InStr(tmp(k), "請求日の") = 0 Then 125 ws1.Range("B" & cmax + 1).Value = Left(tmp(k), Len(tmp(k)) - 3) 126 127 ElseIf InStr(tmp(k), "支払期日") > 0 Then 128 ws1.Range("C" & cmax + 1).Value = Left(tmp(k), Len(tmp(k)) - 4) 129 130 ElseIf InStr(tmp(k), "貴社コード") > 0 Then 131 ws1.Range("D" & cmax + 1).Value = Mid(tmp(k), 2, Len(tmp(k)) - 6) 132 133 ElseIf InStr(tmp(k), "契約番号") > 0 Then 134 ws1.Range("E" & cmax + 1).Value = Mid(tmp(k), 2, Len(tmp(k)) - 5) 135 136 ElseIf InStr(tmp(k), "支払方法") > 0 Then 137 ws1.Range("F" & cmax + 1).Value = Left(tmp(k), Len(tmp(k)) - 4) 138 139 ElseIf k = UBound(tmp) Then 140 ws1.Range("G" & cmax + 1).Value = Mid(tmp(k), 2) 141 142 End If 143 Next 144 145 tmp = Null 146 147 End If 148 Next 149 150 j = 0 151 152 Dim cnode, dnode As IXMLDOMNode 153 Dim str() As Variant 154 Dim tdvar As Variant 155 156 Set cnode = XMLDocument.SelectSingleNode("//Table") 157 158 j = 0 159 For Each dnode In cnode.getElementsByTagName("TD") 160 ReDim Preserve str(j) 161 str(j) = dnode.Text 162 Debug.Print j, str(j) 163 j = j + 1 164 Next 165 166 Dim kingaku, zeigaku As Double 167 Dim tekiyou As String 168 kingaku = 0 169 zeigaku = 0 170 tekiyou = "" 171 172 For j = 0 To UBound(str) 173 k = 4 * j + 1 174 If InStr(str(k), "ご請求") > 0 Then 175 ws1.Range("H" & cmax + 1).Value = kingaku 176 ws1.Range("I" & cmax + 1).Value = zeigaku 177 ws1.Range("J" & cmax + 1).Value = kingaku + zeigaku 178 ws1.Range("K" & cmax + 1).Value = tekiyou 179 Exit For 180 181 ElseIf InStr(str(k), "消費税") > 0 Then 182 zeigaku = zeigaku + str(k + 2) 183 184 ElseIf str(k) <> "" Then 185 kingaku = kingaku + str(k + 2) 186 If tekiyou = "" Then 187 tekiyou = str(k) 188 End If 189 End If 190 191 Next 192End Sub 193
試したこと
・以下のサイトを参考にして、コードをコピぺしましたが、当然エラーは出てくるものの、さっぱり分からない状態です。ですので、後半はコピーしたまま、まだ手つかずの状態です。
https://www.fastclassinfo.com/entry/vba_pdf_text_extraction
・参照設定で、HTMLとAcrobatとMicrosoft Scripting Runtimeにはチェックを入れています。
・もし、pdfを他のツールで一気に(HTMLではなく)txt化して、「〇〇の文字の右横(あるいは下の行)の数字を取る」とか、「この文字があったら1を打つ」といったような設定ができるのではないかと考えましたが、これもわかりません。
・当方、初心者であるため、他の参考になるサイト等があればご教示いただけますと幸いです。
よろしくお願いいたします。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー