Spanish Necesito ayuda para exportar un PDF a CSV

Gabino A. de la Gala

Active Member
Licensed User
Longtime User
Hola. Tengo unos cuantos ficheros en PDF que necesito convertir a CSV o similar para posteriormente hacer una importación hacia una base de datos.

La conversión de PDF a texto ya la tengo funcionando, el "problema" lo tengo con que los ficheros pdf vienen con los datos tabulados en columnas, con lo cual, cuando ha la conversión texto, dichas tabulaciones las pierdo y lo que me vienen son lineas de texto en "bruto" y únicamente separadas por espacios. O al menos eso es lo que me parece a mí.

Intenté hacer un replace buscando los TAB y sustituyendo por ";", pero no me pareció funcionar.

Posteriormente he ido complicándolo un poco y estoy preparando un proceso para que vaya cogiendo datos de cada línea en función de los espacios en blanco que se van encontrando. El problema que tengo con esto es que no todos los nombres tienen nombre y dos apellidos, etc.

¿Se os ocurre a alguno como poder hacer esto de la manera más "flexible"?

Lo que tengo hecho hasta ahora me funcioan, pero solo en parte ya que no todos los nombres están compuestos por el mismo número de palabras.

B4X:
  Project Attributes 
    #MainFormWidth: 600
    #MainFormHeight: 400 
#End Region
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private Button1 As Button
    Private TextArea1 As TextArea
    Private TextArea2 As TextArea
    Private TableView1 As TableView
    Private TableView2 As TableView
    Private TextArea3 As TextArea
    Private Button2 As Button
    Dim Lineas As List 
End Sub
Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.RootPane.LoadLayout("test") 'Load the layout file.
    MainForm.Show
End Sub
Sub SplitGetWords(txt As String, SplitCharacter As String, Index As Int, Count As Int) As String
    Private words() As String
   
    words = Regex.Split(SplitCharacter, txt)
    Dim Aux As String
    Dim i As Int
    For i = 0 To Count-1
        If i > 0 Then Aux = Aux & " "
        Aux = Aux & words(Index+i)
    Next
    Return Aux
End Sub
Sub Button1_MouseClicked (EventData As MouseEvent)
    Dim fc As FileChooser
    fc.Initialize
    Dim PDF As jPDFBoxDocument
    Dim Texto As String
    Dim FileName As String = fc.ShowOpen(MainForm)
    PDF.Initialize(FileName)
   
    Log(PDF.NumberOfPages)
   
    'Extracts all pages
    Texto = PDF.ExtractText
    TextArea1.Text = Texto
   
    ' Convierto la string en una lista para poder trabajar con ella mejor.
    File.WriteString(File.DirApp, "Pdf2Txt.txt", Texto)
    Lineas.Initialize
    Lineas = File.ReadList(File.DirApp, "Pdf2Txt.txt")
   
    'Optional Extract only a range of pages
    'TextArea1.Text = PDF.ExtractText2(1, 2)
   
    PDF.Close
   
End Sub
Sub Button2_Click
    Dim NLinea As Int 
    Dim NLineaIni As Int = 1
    Dim Linea As String
    Dim Resul, Aux As String
    Dim ResulLineas As List
    ResulLineas.Initialize
    For NLinea = NLineaIni To Lineas.Size -1
        Linea = Lineas.Get(NLinea)
        Resul = ""
        Log(NLinea & " - " & Linea)
        Aux = SplitGetWords(Linea, " ", 0, 1)
        Resul = Resul & Aux & ";"
        Linea = Linea.SubString(Aux.Length)
       
        Aux = SplitGetWords(Linea, " ", 1, 2)
        Resul = Resul & Aux & ";" 
        Linea = Linea.SubString(Aux.Length)
        ResulLineas.Add(Resul)
        Log(Resul)
    Next
   
    File.WriteList(File.DirApp, "Resul.csv", ResulLineas)
   
End Sub

Y el resultado:

B4X:
UserID;UserName UserType;
1;Bill Administrator;1;
9;Mike Whetmore;1;
10;John Barns;1;
11;Default Demo;1;
12;Donna Booth;1;
13;Alan Hoza;1;
14;Frank Tatlow;1;
15;Frank Tatlow;1;
16;Master Admin;1;
17;El Nin;1;
18;El Cero;1;
19;0 1;Error;

Si os fijáis, para la segunda columna le tengo definidos que tenga en cuenta dos espacios, con lo cual, en la primera fila, la de los títulos ya no pone el ";" después de UserName y luego en la última fila, la que empieza por 19, como el nombre es solo un 0, el uno de la siguiente columan lo une al nombre y coge el contenido de la siguiente columna.
 
Top