VBA-extrair dados do PDF e Adicionar à folha de trabalho
Tenho um projecto onde estou a tentar extrair os dados de um documento PDF para uma folha de trabalho. O PDF já é mostrado e texto e pode ser copiado e colado manualmente no documento Excel.
Estou neste momento a fazer este projecto através do SendKeys e ele não está a funcionar muito bem, pois recebo um erro quando tento colar os dados do documento PDF seja qual for o método que use! Alguém conhece uma maneira mais bonita de fazer as coisas? Seria uma grande ajuda! E também, porque é que a minha pasta não a trabalhar?! Se eu colar depois que a macro parou de correr passa como normal? Código Abaixo:
Dim myPath As String, myExt As String
Dim ws As Worksheet
Dim openPDF As Object
'Dim pasteData As MSForms.DataObject
Dim fCell As Range
'Set pasteData = New MSForms.DataObject
Set ws = Sheets("DATA")
If ws.Cells(ws.Rows.Count, "A").End(xlUp).Row > 1 Then Range("A3:A" & ws.Cells(ws.Rows.Count, "A").End(xlUp).Row).ClearContents
myExt = "\*.pdf"
'When Scan Receipts Button Pressed Scan the selected folder/s for receipts
For Each fCell In Range(ws.Cells(1, 1), ws.Cells(1, ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column))
myPath = Dir(fCell.Value & myExt)
Do While myPath <> ""
myPath = fCell.Value & "\" & myPath
Set openPDF = CreateObject("Shell.Application")
openPDF.Open (myPath)
Application.Wait Now + TimeValue("00:00:2")
SendKeys "^a"
Application.Wait Now + TimeValue("00:00:2")
SendKeys "^c"
'Application.Wait Now + TimeValue("00:00:2")
ws.Select
ActiveSheet.Paste
'pasteData.GetFromClipboard
'ws.Cells(3, 1) = pasteData.GetText
Exit Sub
myPath = Dir
Loop
Next fCell
4 answers
Você pode abrir o arquivo PDF e extrair seu conteúdo usando a Biblioteca Adobe (que eu acredito que você pode baixar do Adobe como parte do SDK, mas ele vem com certas versões do Acrobat também)
Certifique-se de adicionar a Biblioteca às suas referências também (na minha máquina é a Biblioteca do tipo Adobe Acrobat 10.0, mas não tenho a certeza se essa é a versão mais recente)
Mesmo com a biblioteca Adobe não é trivial (você vai precisar adicionar sua própria armadilha de erros etc):
Function getTextFromPDF(ByVal strFilename As String) As String
Dim objAVDoc As New AcroAVDoc
Dim objPDDoc As New AcroPDDoc
Dim objPage As AcroPDPage
Dim objSelection As AcroPDTextSelect
Dim objHighlight As AcroHiliteList
Dim pageNum As Long
Dim strText As String
strText = ""
If (objAvDoc.Open(strFilename, "") Then
Set objPDDoc = objAVDoc.GetPDDoc
For pageNum = 0 To objPDDoc.GetNumPages() - 1
Set objPage = objPDDoc.AcquirePage(pageNum)
Set objHighlight = New AcroHiliteList
objHighlight.Add 0, 10000 ' Adjust this up if it's not getting all the text on the page
Set objSelection = objPage.CreatePageHilite(objHighlight)
If Not objSelection Is Nothing Then
For tCount = 0 To objSelection.GetNumText - 1
strText = strText & objSelection.GetText(tCount)
Next tCount
End If
Next pageNum
objAVDoc.Close 1
End If
getTextFromPDF = strText
End Function
O que isso faz é essencialmente a mesma coisa que você está tentando fazer - apenas usando a própria biblioteca do Adobe. Ele está indo através do PDF uma página de cada vez, destacando todo o texto na página, em seguida, largando-o (um elemento de texto de cada vez) em uma string.
Tenha em mente o que você obtém a partir disto pode estar cheio de todos os tipos de caracteres não-Impressão (feeds de linha, newlines, etc) que podem até acabar no meio do que se parecem com blocos contíguos de texto, para que você possa é preciso um código adicional para limpar antes de poder usá-lo.
Espero que isso ajude!Copiar e colar por interações do utilizador a emulação não pode ser fiável (por exemplo, aparece o popup e muda o foco). Você pode estar interessado em tentar o comercial ByteScout PDF Extractor SDK que é projetado especificamente para extrair dados de PDF e funciona a partir de VBA. É igualmente capaz de extrair dados de facturas e quadros como CSV utilizando o código VB.
Aqui está o código VBA para o Excel extrair texto de determinados locais e guardá - los em células na Sheet1
:
Private Sub CommandButton1_Click()
' Create TextExtractor object
' Set extractor = CreateObject("Bytescout.PDFExtractor.TextExtractor")
Dim extractor As New Bytescout_PDFExtractor.TextExtractor
extractor.RegistrationName = "demo"
extractor.RegistrationKey = "demo"
' Load sample PDF document
extractor.LoadDocumentFromFile ("c:\sample1.pdf")
' Get page count
pageCount = extractor.GetPageCount()
Dim wb As Workbook
Dim ws As Worksheet
Dim TxtRng As Range
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1")
For i = 0 To pageCount - 1
RectLeft = 10
RectTop = 10
RectWidth = 100
RectHeight = 100
' check the same text is extracted from returned coordinates
extractor.SetExtractionArea RectLeft, RectTop, RectWidth, RectHeight
' extract text from given area
extractedText = extractor.GetTextFromPage(i)
' insert rows
' Rows(1).Insert shift:=xlShiftDown
' write cell value
Set TxtRng = ws.Range("A" & CStr(i + 2))
TxtRng.Value = extractedText
Next
Set extractor = Nothing
End Sub
divulgação: sou parente da ByteScout
Com o tempo, descobri que extrair texto de PDFs num formato estruturado é uma tarefa difícil. No entanto, se está à procura de uma solução fácil, pode querer considerar xpdf a ferramenta pdftotext
.
Pseudocódigo para extrair o texto incluiria:
- usando
SHELL
a declaração VBA para extrair o texto do PDF para um ficheiro temporário usando XPDF - usando declarações sequenciais de leitura de ficheiros para ler o conteúdo temporário do ficheiro num string Colando a string no Excel
Exemplo simplificado abaixo:
Sub ReadIntoExcel(PDFName As String)
'Convert PDF to text
Shell "C:\Utils\pdftotext.exe -layout " & PDFName & " tempfile.txt"
'Read in the text file and write to Excel
Dim TextLine as String
Dim RowNumber as Integer
Dim F1 as Integer
RowNumber = 1
F1 = Freefile()
Open "tempfile.txt" for Input as #F1
While Not EOF(#F1)
Line Input #F1, TextLine
ThisWorkbook.WorkSheets(1).Cells(RowNumber, 1).Value = TextLine
RowNumber = RowNumber + 1
Wend
Close #F1
End Sub
Usar Bytescout PDF Extractor SDK é uma boa opção. É barato e dá muita funcionalidade relacionada com PDF. Uma das respostas acima aponta para a página morta Bytescout em GitHub. Estou fornecendo uma amostra de trabalho relevante para extrair mesa de PDF. Você pode usá-lo para exportar em qualquer formato.
Set extractor = CreateObject("Bytescout.PDFExtractor.StructuredExtractor")
extractor.RegistrationName = "demo"
extractor.RegistrationKey = "demo"
' Load sample PDF document
extractor.LoadDocumentFromFile "../../sample3.pdf"
For ipage = 0 To extractor.GetPageCount() - 1
' starting extraction from page #"
extractor.PrepareStructure ipage
rowCount = extractor.GetRowCount(ipage)
For row = 0 To rowCount - 1
columnCount = extractor.GetColumnCount(ipage, row)
For col = 0 To columnCount-1
WScript.Echo "Cell at page #" +CStr(ipage) + ", row=" & CStr(row) & ", column=" & _
CStr(col) & vbCRLF & extractor.GetCellValue(ipage, row, col)
Next
Next
Next
Muitas mais amostras disponíveis aqui: https://github.com/bytescout/pdf-extractor-sdk-samples