WebListBox a PDF NilObjectException

Hola, estoy trabajando en Xojo2017r1.1 con complementos MBS instalados (estoy trabajando en esta versión debido a que me dijeron que revisara un proyecto anterior).
Me asignaron hacer un botón que guarda el contenido de un WebListBox en un .pdf. Utilicé el complemento DynaPDF para hacerlo posible, y hasta ahora descargué el archivo pero está dañado/vacío, y en xojo obtengo el error “NilObjectException”.

Dim f as FolderItem = SpecialFolder.Desktop.child("test2.pdf")
Dim pdfOut As TextOutputStream = TextOutputStream.Create(f)
Dim pdf as MyDynaPDFMBS
dim intX, intY as integer
dim TableWidth as integer = 2000
'call pdf.SetFont("Helvetica", 12)

// creates table

dim ColumnCount as integer = lb.ColumnCount
const AllColumns = -1
const AllRows = -1
dim ColumnWidths() as Double
redim ColumnWidths(ColumnCount-1)


'Counts columns

dim i as integer
dim strColWidths() As string
dim s as string
s = lb.ColumnWidths
strColWidths =  s.Split(",")
dim bolCol() As Boolean
redim bolCol(strColWidths.Ubound)
dim colsVisible as integer

for i=0 to lb.ColumnCount - 1
  if trim(strColWidths(i))="*" or strColWidths(i).val <> 0 then
    colsVisible =colsVisible +1
    if trim(strColWidths(i))="*" then
      ColumnWidths(colsVisible-1) = -1
    else
      ColumnWidths(colsVisible-1) = strColWidths(i).val
    end if
    bolCol(i) = True
  else
    bolCol(i) = False
  end if
next i

dim SumColumnWidth as Double

for Column as integer = 0 to  colsVisible-1
  if ColumnWidths(Column) > 0 then
    SumColumnWidth = SumColumnWidth + ColumnWidths(Column)
  end if
next

for i=0 to lb.ColumnCount - 1
  if ColumnWidths(i) = -1 then
    ColumnWidths(i) = lb.Width - SumColumnWidth
    SumColumnWidth = SumColumnWidth + ColumnWidths(i)
    exit for
  end if
next i

dim tbl as DynaPDFTableMBS = pdf.CreateTable(lb.ColumnCount, colsvisible, TableWidth, 100.0)
call tbl.SetBorderWidth(AllRows, AllColumns, 1.0, 1.0, 1.0, 1.0)
'call tbl.SetFont(AllRows, AllColumns, "Helvetica", pdf.kfsNone, false, pdf.kcpUnicode)
call tbl.SetGridWidth( 1.0, 1.0)
call tbl.SetGridHorizontalColor(100, 100, 100)
call tbl.SetGridVerticalColor(100, 100, 100)
call tbl.SetBorderColor(AllRows, AllColumns, 100, 100, 100)


// add header row

dim rowNum as integer = tbl.AddRow
call tbl.SetFlags rowNum, -1, tbl.ktfHeaderRow
dim tblColumn as integer
for Column as integer = 0 to ColumnCount-1
  if bolcol(Column) then
    dim t as string = lb.Heading(Column)
    call tbl.SetCellText rowNum, tblColumn, pdf.ktaLeft,   tbl.kcoCenter, t
    tblColumn = tblColumn +1
  end if
next

// now fill all the cells

dim c as integer = lb.ColumnCount-1
for Row as integer = 0 to c
  tblColumn = 0
  rowNum = tbl.AddRow
  for Column as integer = 0 to ColumnCount-1
    if bolcol(Column) then
      dim AlignMent as integer = pdf.ktaLeft
      
      'Select case lb.ColumnAlignment(column)
      '
      'case lb.AlignCenter
      '
      'AlignMent = pdf.ktaCenter
      '
      'case lb.AlignRight
      '
      'AlignMent = pdf.ktaRight
      '
      'end Select
      
      dim t as string = lb.Cell(row, Column)
      call tbl.SetCellText rowNum, tblColumn, AlignMent,  tbl.kcoCenter, t
      tblColumn = tblColumn +1
    end if
  next
next


dim dblf as Double
dblf = TableWidth / SumColumnWidth
for Column as integer = 0 to colsVisible-1
  ColumnWidths(Column) = ColumnWidths(Column) * dblf
  call tbl.SetColWidth(Column, ColumnWidths(Column), false)
next
dim intNewY as integer
intNewY = intY + tbl.GetNumRows * 15

// Draw the table now

call tbl.DrawTable(30.0, intY, 0)
while tbl.HaveMore
  call pdf.EndPage
  call pdf.Append
  call tbl.DrawTable(30.0, 50.0, 0)
wend

'Return intNewY

Si hay alguien que pueda echarme una mano, se lo agradeceré enormemente.

Sería bueno que pudieras compartir un ejemplo (código) o des más información sobre el error “NilObjectException”

Me imagino que con las primeras 2 lineas de tu código, creas el archivo test2.pdf de 0 bytes.
Al final no veo que cierres el PDF, no se si esto sea necesario.

¿Qué línea provoca la NilObjectException?

¿dónde está la línea con “new MyDynaPDFMBS”?

¿y “pdf.CreateNewPDF()”?

Véase también:
https://www.monkeybreadsoftware.net/example-dynapdf-letter-webletter.shtml

dim pdf as new MyDynapdfMBS
			
call pdf.CreateNewPDF(nil)	
call pdf.append
...
call pdf.EndPage
call pdf.closefile

webfile = new WebFile
webfile.Data = pdf.GetBuffer
webfile.Filename = "letter.pdf"
webfile.ForceDownload = true

showurl webfile.URL
1 Like


Esta es la linea que cuando ejecuto el botón de exportar como pdf da error.

No creo que sea el hecho de que no lo cierre. Porque el problema sale por el hecho de que no esta grabando ningun dato y por eso me dice que esta corrupto cuando lo intento abrir.(@AlbertoD )

Ahora revisare el ejemplo que me adjuntaste para ver si con eso me puedo guiar.(@Christian_Schmitz)

Gracias a ambos por su colaboración!

te falta la parte en la que se inicializa la variable pdf.

Me imagino que te faltó la palabra ‘new’

Si, me faltaba eso.

Pero ahora me salta un error de OutOfBounds. Alguna idea sobre esto?


Dice que intenta acceder la celda (0,0) pero que el limite es (-1,8)

Me imagino que este código está haciendo que mandes Row = 0 aún cuando tu Weblistbox (lb) no tiene contenido (no existe row = 0).

osea, en si el weblistbox no tiene contenido pq el mismo lo trae de una base de datos SQL.

Si el weblistbox no tiene contenido, entonces no uses lb.cell(row, Column)
O tal vez no entendí tu comentario

Rehice el codigo para usar un iterador que recorra filas y columnas.

Dim f as FolderItem = SpecialFolder.Desktop.child("test2.pdf")
Dim pdfOut As TextOutputStream = TextOutputStream.Create(f)
Dim pdf as new MyDynaPDFMBS
dim intX, intY as integer
dim TableWidth as integer = 2000

//funcion
call pdf.CreateNewPDF(nil)

dim arsRows() as String
dim iColMax as Integer = lb.ColumnCount - 1
dim iRowMax as Integer = lb.RowCount - 1

for iRow as Integer = 0 to iRowMax
  dim arsThisRow() as String
  
  for iCol as Integer = 0 to iColMax
    arsThisRow.Append(chr(34) + lb.Cell(iRow, iCol) + chr(34))
    
  next iCol
  arsRows.Append(Join(arsThisRow, ","))
  
next iRow
dim sRowsOut as String = Join(arsRows, EndOfLine.UNIX)

pdfOut.Write(sRowsOut)

call pdf.EndPage
call pdf.closefile

Mi error es que no logro que los datos que estan en el web listbox se graben en el pdf, que funcion de DynaPDF deberia usar?

¿Viste el ejemplo en la liga que puso Christian?
Ahí usa pdf.Font para asignar el Font a usar pdf.SetTextRect para definir el área en el PDF que mandará texto y pdf.WriteFText para escribir el texto en el PDF.

Al parecer estás confundido también con tu definición de pdfOut como TextOutputStream. Ese normalmente se usa para crear un archivo de texto y no un PDF.

1 Like

Por favor, mire los ejemplos que vienen con el plugin.
(Please look on the examples coming with the plugin.)

e.g.
https://www.monkeybreadsoftware.net/example-dynapdf-tables-dynapdftablefromlistbox.shtml

1 Like

Si, intente adaptar el ejemplo a webapp pero no escribe ningun valor de la weblistbox

//Draw WLB
dim table as DynaPDFTableMBS
dim columnwidths(-1) as integer
dim rowNum as integer
dim PageWidth as integer = pdf.GetPageWidth-72-72 // width - left and right

// scale down to page width if listbox on GUI is wider
dim Factor as Double = PageWidth / list.Width

table = pdf.CreateTable(list.RowCount, list.ColumnCount, PageWidth, 8.0)

call table.SetFont(AllRows, AllColumns, "Arial", pdf.kfsRegular, true, pdf.kcpUnicode)

redim columnwidths(list.ColumnCount)

dim cw(-1) as string = split(List.ColumnWidths,",")
dim remainingspace as integer = PageWidth
dim starcount as integer

for each s as string in cw
  s = s.trim
  if s = "*" then
    starcount = starcount + 1
  elseif instr(s,"*")>0 then
    starcount=starcount+val(s)
  end if
next

for i as integer=0 to UBound(Cw)
  dim s as string = cw(i).trim
  dim columnwidth as integer
  
  if instr(s,"%")>0 then
    columnwidth=val(s)*(PageWidth)/100.0
  elseif s = "*" then
    columnwidth = remainingspace/starcount
  elseif instr(s,"*")>0 then
    columnwidth=val(s)*remainingspace/starcount
  else
    columnwidth=val(s)*Factor
  end if
  columnwidths(i)=columnwidth
  remainingspace=remainingspace-columnwidth
next


'dim font as string = list.TextFont
'if font="System" then font="Times"

'dim size as integer = list.TextSize
'if size <= 0 then size = 12

'call table.SetFont(AllRows, AllColumns, pdf.kfsRegular, true, pdf.kcpUnicode)

rowNum = table.AddRow
for cx as integer=0 to list.ColumnCount-1
  call table.SetColWidth(cx, columnwidths(cx), false)
  
  if columnwidths(cx) = 0 then
    // ignore
    'elseif list.ColumnAlignment(cx)=list.AlignCenter then
    'call table.SetCellText(rowNum, cx, pdf.ktaCenter, table.kcoCenter, list.Heading(cx))
    'elseif list.ColumnAlignment(cx)=list.AlignRight then
    'call table.SetCellText(rowNum, cx, pdf.ktaRight, table.kcoCenter, list.Heading(cx))
    'else
    call table.SetCellText(rowNum, cx, pdf.ktaLeft, table.kcoCenter, list.Heading(cx))
  end if
next

'call table.SetFont(rowNum, AllColumns, font, pdf.kfsBold, true, pdf.kcpUnicode)
call table.SetFlags(rowNum, AllColumns, table.ktfHeaderRow)
call table.SetBorderWidth(rowNum, AllColumns, 0.5, 0.5, 0.5, 0.5)


for cy as integer=0 to list.rowcount-1
  rowNum = table.AddRow
  
  for cx as integer=0 to list.ColumnCount-1
    if columnwidths(cx) = 0 then
      // ignore
      'elseif list.ColumnAlignment(cx)=list.AlignCenter then
      'call table.SetCellText(rowNum, cx, pdf.ktaCenter, table.kcoCenter, list.Cell(cy,cx) )
      'elseif list.ColumnAlignment(cx)=list.AlignRight then
      'call table.SetCellText(rowNum, cx, pdf.ktaRight, table.kcoCenter, list.Cell(cy,cx) )
      'else
      call table.SetCellText(rowNum, cx, pdf.ktaLeft, table.kcoCenter, list.Cell(cy,cx) )
    end if
  next
next

call table.SetCellPadding(AllRows, AllColumns, 0.0, 0.0, 2.0, 2.0)
call table.SetCellSpacing(AllRows, AllColumns, 0.0, 0.0, 0.0, 2.0)


dim PageHeight as Double = pdf.GetPageHeight - 72 - 72

do
  call table.DrawTable( 55.0, 72.0, PageHeight) 
  
  // draw footer
  if table.HaveMore then
    call pdf.EndPage
    call pdf.Append
    
  else 
    // done
    exit
  end if
loop
//run
dim pdf as new MyDynapdfMBS

pdf.SetLicenseKey "Starter" // For this example you can use a Starter, Lite, Pro or Enterprise License

dim outfile as FolderItem = SpecialFolder.Desktop.Child("Table.pdf")

call pdf.CreateNewPDF(nil) // the output file is created later

call pdf.SetDocInfo pdf.kdiCreator, "Realbasic test application"
call pdf.SetDocInfo pdf.kdiTitle, "My first table output"

call pdf.SetPageCoords pdf.kpcTopDown
call pdf.Append

DrawWLB pdf, Listbox1, 50, 50, pdf.GetPageWidth-100

call pdf.EndPage

// no error?
if pdf.HaveOpenDoc then
  if not pdf.OpenOutputFile(outfile) then
    MsgBox "Can't write file to "+outfile.NativePath
    quit
  end if
end if

call pdf.CloseFile

'outfile.Launch

En ambos casos hay partes del codigo original que tuve que comentar, porque sino no funcionaba

See this block:

 if columnwidths(cx) = 0 then
    // ignore
    'elseif list.ColumnAlignment(cx)=list.AlignCenter then
    'call table.SetCellText(rowNum, cx, pdf.ktaCenter, table.kcoCenter, list.Heading(cx))
    'elseif list.ColumnAlignment(cx)=list.AlignRight then
    'call table.SetCellText(rowNum, cx, pdf.ktaRight, table.kcoCenter, list.Heading(cx))
    'else
    call table.SetCellText(rowNum, cx, pdf.ktaLeft, table.kcoCenter, list.Heading(cx))
  end if

Since you commented out the else there, the SetCellText method is never called, unless columns width is zero.

1 Like
dim table as DynaPDFTableMBS
dim columnwidths(-1) as integer
dim rowNum as integer
dim PageWidth as integer = pdf.GetPageWidth-72-72 // width - left and right

// scale down to page width if listbox on GUI is wider
dim Factor as Double = PageWidth / list.Width

table = pdf.CreateTable(list.RowCount, list.ColumnCount, PageWidth, 8.0)

call table.SetFont(AllRows, AllColumns, "Arial", pdf.kfsRegular, true, pdf.kcpUnicode)

redim columnwidths(list.ColumnCount)

dim cw(-1) as string = split(List.ColumnWidths,",")
dim remainingspace as integer = PageWidth
dim starcount as integer

for each s as string in cw
  s = s.trim
  if s = "*" then
    starcount = starcount + 1
  elseif instr(s,"*")>0 then
    starcount=starcount+val(s)
  end if
next

for i as integer=0 to UBound(Cw)
  dim s as string = cw(i).trim
  dim columnwidth as integer
  
  if instr(s,"%")>0 then
    columnwidth=val(s)*(PageWidth)/100.0
  elseif s = "*" then
    columnwidth = remainingspace/starcount
  elseif instr(s,"*")>0 then
    columnwidth=val(s)*remainingspace/starcount
  else
    columnwidth=val(s)*Factor
  end if
  columnwidths(i)=columnwidth
  remainingspace=remainingspace-columnwidth
next

rowNum = table.AddRow
for cx as integer=0 to list.ColumnCount-1
  call table.SetColWidth(cx, columnwidths(cx), false)
  
  if columnwidths(cx) = 0 then
    // ignore
    call table.SetCellText(rowNum, cx, pdf.ktaCenter, table.kcoCenter, list.Heading(cx))
  end if
next

'call table.SetFont(rowNum, AllColumns, font, pdf.kfsBold, true, pdf.kcpUnicode)
call table.SetFlags(rowNum, AllColumns, table.ktfHeaderRow)
call table.SetBorderWidth(rowNum, AllColumns, 0.5, 0.5, 0.5, 0.5)


for cy as integer=0 to list.rowcount-1
  rowNum = table.AddRow
  
  for cx as integer=0 to list.ColumnCount-1
    if columnwidths(cx) = 0 then
      // ignore
      call table.SetCellText(rowNum, cx, pdf.ktaCenter, table.kcoCenter, list.Cell(cy,cx) )
    end if
  next
next

call table.SetCellPadding(AllRows, AllColumns, 0.0, 0.0, 2.0, 2.0)
call table.SetCellSpacing(AllRows, AllColumns, 0.0, 0.0, 0.0, 2.0)


dim PageHeight as Double = pdf.GetPageHeight - 72 - 72

do
  call table.DrawTable( 55.0, 72.0, PageHeight) 
  
  // draw footer
  if table.HaveMore then
    call pdf.EndPage
    call pdf.Append
    
  else 
    // done
    exit
  end if
loop

still, the pdf comes out empty

Como dijo Christian, este código sólo se ejecuta para las columnas que tienen ancho = 0, por lo que en realidad, nunca se ejecuta.

Esto no significa que sea lo único que se tenga que arreglar.

1 Like