Impresión Del Resultado De Una Consulta SQL


Objetivo: Impresión Del Resultado De Una Consulta SQL
Se ofrece la definición de una clase que permite imprimir el resultado de una consulta.

El código está comentado y permite ver cómo realizar impresiones con Gambas3 (Que no es nada fácil ). Se puede adaptar fácilmente a otras necesidades de impresión.

También muestra un bug de la impresión con este sistema .No funciona cuando se selecciona impresión en landscape.
Si alguien entiende que no es un bug sino que yo estoy haciéndolo mal agradeceré una corrección .

Aquí está. Espero que sea útil a mucha gente.
' gambas class file

' *********************************************************************************************
' Esta clase dispone lo necesario para crear un listado a partir de un resultado
' ************************************************************************************************

Private iPages As Integer
Private iYPos As Integer
Private RMargin As Integer
Private LMargin As Integer
Private TMargin As Integer
Private BMargin As Integer

Private resDatos As Result

Private PrinterName As String
Private pPrinter As Printer
Private FontName As String
Private pFont As Font

Private bolPDF As Boolean
Private iOrientation As Integer
Private sTitulo As String

Private fLineHeight As Float
Private fTitleHeight As Float
Private fTitleFontSize As Float
Private fLineFontSize As Float


Public Struct FieldPrint
'Esta estructura determina las características de un campo en la impresión
Name As String
X As Integer
Width As Integer
Align As Integer
End Struct

Public Struct Page
'Esta estructura determina la estructura de una página
sFields As FieldPrint[]
lFirstRecord As Long
lLastRecord As Long
End Struct

Private Pages As Page[] 'Almacenará las estructuras de todas las páginas que intervienen en el listado


Public Sub _new(res As Result, titulo As String, Optional sPrinter As String = "", Optional sFont As String = "Serif", Optional fFontSize As Integer = 3.5, Optional orientation As Integer = 0, Optional generarPDF As Boolean = False)

resDatos = res
bolPDF = generarPDF
'*******************************************************
iOrientation = orientation 'Esto no funciona
'*******************************************************
sTitulo = titulo
fTitleFontSize = fFontSize * 1.5
fLineFontSize = fFontSize
PrinterName = sPrinter
FontName = sFont

End

Public Sub Imprimir()
pPrinter = New Printer As "FPrinter"

If bolPDF Then
pPrinter.Name = "Imprimir a un archivo"
Dialog.Title = "Archivo destino"
Dialog.Path = "/tmp/" & sTitulo
Dialog.Filter = ["*.pdf", "Formato de documento portable"]
Dialog.AutoExt = True
Dialog.SaveFile
pPrinter.OutputFile = Dialog.Path
Else

If Not PrinterName Then
If pPrinter.Configure() Then Return
Endif

Endif

'Para calcular las posiciones de impresión de cada elemento lo hacemos sobre el área completa de la página y no sobre la
'parte efectivamente imprimible
pPrinter.FullPage = True

Inc Application.Busy

'Esto no funciona cuando la orientación es 1 - Landscape
'Lo mismo sucederá si se abre el diálogo de configuración de impresoras y se selecciona landscape en este
''*********************************************
'pPrinter.Orientation = iOrientation
'**********************************************

pPrinter.print 'Dispara el evento Printer_Begin()
Dec Application.Busy

Catch
Message.Error("Error " & Error.Code & " " & Error.Text, "Aceptar")

End

Public Sub FPrinter_Begin()

'La impresión se hace mediante Paint así que establecemos las medidas de Paint a las de nuestra página
Paint.Scale((Paint.Width) / pPrinter.PaperWidth, (Paint.Height) / pPrinter.PaperHeight) 'Cooordenadas en milímetros

pfont = New Font(FontName)

LMargin = 12
RMargin = pPrinter.PaperWidth - LMargin
TMargin = 10
BMargin = pPrinter.PaperHeight - 15

'Aquí tenemos dos opciones que son:
'1 - Indicar el número de páginas a imprimir si podemos conocerlo por ser un listado simple

'pPrinter.Count = iPages

'2 - comentar la línea anterior y utilizar el evento Paginate para calcular el número de páginas a imprimir.
'El evento paginate se dispara si dentro del evento Begin en que estamos no se asigna ninguna cantidad a Count

End

Public Sub FPrinter_Paginate()
Dim fld As ResultField, curFieldPrint As FieldPrint, intRecordsPerPage As Integer, curPage As Page, iColPages As Integer
Dim cp As Integer, rp As Integer, iRowPages As Integer

Debug "Paginando"

'Determinando la altura de la línea de título
pFont.Size = fTitleFontSize
fTitleHeight = pFont.TextHeight("H")
'determinando la altura de la línea de texto
pFont.Size = fLineFontSize
fLineHeight = pFont.TextHeight("H")

'Creando las definiciones de páginas
Pages = New Page[]
curPage = New Page
iRowPages = 1 'iRowPages contendrá el número de páginas que ocupa cada fila de datos teniendo en cuenta el tamaño
'de la impresión
curPage.sFields = New FieldPrint[]
pFont.Size = fLineFontSize
'El número de registros que cabrán por página se calcula restando del margen inferior el margen superior, el alto del título,
'el alto de los títulos de columnnas 1 líneas y 1.5 líneas para el número de página
intRecordsPerPage = (BMargin - TMargin - fTitleHeight - fLineHeight - fLineHeight * 1.5) / fLineHeight

For Each fld In resDatos.Fields
curFieldPrint = New FieldPrint
Select Case fld.Type
Case gb.Boolean
curFieldPrint.Width = pFont.TextWidth("T")
curFieldPrint.Align = 3

Case gb.Integer
curFieldPrint.Width = pFont.TextWidth("12345")
curFieldPrint.Align = 2

Case GB.Long
curFieldPrint.Width = pFont.TextWidth("1234567")
curFieldPrint.Align = 2

Case gb.Float
curFieldPrint.Width = pFont.TextWidth("12345,12")
curFieldPrint.Align = 2

Case gb.Date
curFieldPrint.Width = pFont.TextWidth("01/01/0000")
curFieldPrint.Align = 3

Case gb.String
If (fld.Length / 3) > 20 Then 'Length devuelve tres veces la longitud de la cadena
curFieldPrint.Width = pFont.TextWidth("M") * 20
Else
curFieldPrint.Width = (fld.Length / 3) * pFont.TextWidth("a")
Endif

curFieldPrint.Align = 1
End Select
'Comprobamos si entra en la página y si no creamos otra
pFont.Bold = True
curFieldPrint.Width = Max(curFieldPrint.Width, pFont.TextWidth(fld.Name))

If curPage.sFields.Count = 0 Then
curFieldPrint.X = LMargin + 2
curFieldPrint.Name = fld.Name
Else
'CurrentX es igual al anterior X + su ancho + 4 mm de separación
curFieldPrint.X = curPage.sFields[curPage.sFields.Count - 1].X + curPage.sFields[curPage.sFields.Count - 1].Width + 4
curFieldPrint.Name = fld.Name
Endif
If (curFieldPrint.X + curFieldPrint.Width + 2) > (RMargin) Then
curPage.lFirstRecord = 0
curPage.lLastRecord = intRecordsPerPage - 1
Pages.Add(curPage)
curFieldPrint.X = LMargin + 2
curPage = New Page
curPage.sFields = New FieldPrint[]
Inc iRowPages
Endif
curPage.sFields.Add(curFieldPrint)
Next
curPage.lFirstRecord = 0
curPage.lLastRecord = intRecordsPerPage - 1
Pages.Add(curPage)

IRowPages = Pages.Count

iColPages = Int(resDatos.Count / intRecordsPerPage) 'Páginas necesarias para cada columna de datos
'El número total de páginas es iRowPages * iColPages
If resDatos.Count Mod intRecordsPerPage Then Inc iColPages

For cp = 1 To iColPages - 1 'cp es contador para iColPages Contamos desde 1 porque la primera fila de páginas
'ya ha sido definida

For rp = 0 To iRowPages - 1 'rp es contador de iRowPages
curPage = New Page
curPage.sFields = Pages[rp].sFields 'Cada fila de páginas clona la definición de campos de la anterior

'Definiendo filas del resultado a imprimir en la página
curPage.lFirstRecord = cp * intRecordsPerPage
curPage.lLastRecord = (cp + 1) * intRecordsPerPage - 1
'Cuidamos no pasar del último registro aunque en la página quepan más filas
If curPage.lLastRecord > resDatos.Count - 1 Then curPage.lLastRecord = resDatos.Count - 1
Pages.Add(curPage)
Next
Next
'Debug "Páginas a imprimir " & Str(Pages.Count)
pPrinter.Count = Pages.Count
End


Public Sub FPrinter_Draw()
'Este evento se dispara para cada página a imprimir
Dim fp As FieldPrint, r As Integer
Dim sTexto As String
'Debug "Llegamos a la impresión"


Paint.Font = Font[pFont.ToString()]
Paint.LineWidth = 0.1

Paint.Font.Size = fTitleFontSize
Debug Paint.Font.ToString
Paint.DrawText("Este es el título", LMargin, TMargin, pPrinter.PaperWidth - LMargin * 2, fTitleHeight, Align.Center)

Debug "TextExtends alto " & Paint.TextExtents("Este es el título").Height
iYPos = TMargin + fTitleHeight

' Paint.MoveTo(LMargin, iYPos)
' Paint.LineTo(RMargin, iYPos)

Paint.Font.Size = fLineFontSize
Debug Paint.Font.ToString
Paint.Font.Bold = True

Paint.MoveTo(LMargin, iYpos)
Paint.LineTo(LMargin, BMargin - fLineHeight * 1.5)

For Each fp In Pages[pPrinter.Page - 1].sFields
Paint.drawText(fp.Name, fp.X, iYPos, Paint.TextExtents(fp.Name).Width, fLineHeight, Align.Left)
'Paint.Fill
Paint.MoveTo(fp.X + fp.Width + 2, iYPos)
Paint.LineTo(fp.X + fp.Width + 2, BMargin - fLineHeight * 1.5)
Paint.Stroke
Next

Paint.MoveTo(LMargin, TMargin + fTitleHeight)
Paint.LineTo(fp.X + fp.Width + 2, TMargin + fTitleHeight)
Paint.MoveTo(LMargin, TMargin + fTitleHeight + fLineHeight)
Paint.LineTo(fp.X + fp.Width + 2, TMargin + fTitleHeight + fLineHeight)
Paint.MoveTo(LMargin, BMargin - fLineHeight * 1.5)
Paint.LineTo(fp.X + fp.Width + 2, BMargin - fLineHeight * 1.5)
Paint.Stroke
iypos += fLineHeight

' Paint.MoveTo(LMargin, iYPos)
' Paint.LineTo(RMargin, iYPos)

Paint.MoveTo(LMargin, iYPos - fLineHeight)
Paint.LineTo(LMargin, BMargin - fLineHeight * 1.5)
Paint.Stroke
Paint.Font.Bold = False
For r = Pages[pPrinter.Page - 1].lFirstRecord To Pages[pPrinter.Page - 1].lLastRecord
'Debug "Record " & Str(r)
resDatos.MoveTo(r)
With Pages[pPrinter.Page - 1]
For Each fp In .sFields
Paint.drawText(resDatos[fp.Name], fp.X, iYPos, fp.Width, fLineHeight, fp.Align)
'Paint.Fill

Next
End With
'Inc r
iYPos += fLineHeight
Next

Paint.Font.Bold = True
iypos = BMargin - fLineHeight
Paint.DrawText("Página " & Str(pPrinter.Page), LMargin, iypos, pPrinter.PaperWidth - LMargin * 2, fLineHeight, Align.center)
End

última edición por Sebas el Viernes, 11 Enero 2013, 17:44; editado 1 vez
Perfil MP  
Objetivo: Re: Impresión Del Resultado De Una Consulta SQL
Muchas gracias. Los novatos con el 3 agradecemos el aporte.
Lo miraré despacito y te comento, si hay algo que comentar, claro.

Un saludo.

Perfil MP  
Objetivo: Re: Impresión Del Resultado De Una Consulta SQL
Sebas:

Buen aporte. Es conveniente que tengamos siempre varias opciones a elegir para poder hacer informes.

Saludos

Objetivo: Re: Impresión Del Resultado De Una Consulta SQL
Anoto una errata y una observación de última hora.

Primero en la definición de la clase:

Public Sub _new(res As Result, titulo As String, Optional sPrinter As String = "", Optional sFont As String = "Serif", Optional fFontSize As Integer = 3.5, Optional orientation As Integer = 0, Optional generarPDF As Boolean = False)


fFontSize debe ser As Float

Por otro lado he comprobado en el siguiente código;
Public Sub Imprimir()
pPrinter = New Printer As "FPrinter"


If bolPDF Then
pPrinter.Name = "Imprimir a un archivo"
Dialog.Title = "Archivo destino"
Dialog.Path = "/tmp/" & sTitulo
Dialog.Filter = ["*.pdf", "Formato de documento portable"]
Dialog.AutoExt = True
Dialog.SaveFile
pPrinter.OutputFile = Dialog.Path
Else

If Not PrinterName Then
If pPrinter.Configure() Then Return
Endif

Endif
....pPrinter.FullPage = True


Que cuando entramos en el diálogo printer.configure() si cancelamos la impresión el resto del código no se ejecuta, tal como está previsto. Pero si se selecciona vista previa de la impresión tampoco ejecuta el resto del código en esta función sino que internamente llama a Printer.Print y, por lo tanto, el pPrinter.FullPage = True que viene a continuación o cualquier otro código debe colocarse con anterioridad al cuadro de diálogo o la vista previa no responderá al código escrito.

Perfil MP  
Objetivo: Re: Impresión Del Resultado De Una Consulta SQL
Buen trabajo, se agradece mucho.

En poco tiempo tendré que ponerme a actualizar una aplicación grande de gambas2 a gambas3, así que voy a estudiar tu ejemplo a ver si por fin asimilo el tema de impresión y paginado que por alguna razón siempre me ha parecido bastante complicado.

Saludos y gracias nuevamente.


P.D. Sebas, he visto que has creado un artículo a partir de este post, pero por alguna razón el código sale mal, porque convierte algunos caracteres en entidades html. Creo que es un fallo en el módulo de base de conocimientos del foro, tendré que revisarlo cuando tenga un rato.
Sin pretender abusar de tu bondad, te aconsejo, sólo para mayor claridad, que trates de elaborar el artículo paso a paso con fragmentos de código limpio (sin comentarios largos) y que los comentarios formen parte del artículo explicando esa parte concreta del código. Estoy seguro de que toda la comunidad te estará muy agradecida, yo el primero

Perfil MP  
Objetivo: Re: Impresión Del Resultado De Una Consulta SQL
jguardon escribió: [Ver mensaje]
Buen trabajo, se agradece mucho.

En poco tiempo tendré que ponerme a actualizar una aplicación grande de gambas2 a gambas3, así que voy a estudiar tu ejemplo a ver si por fin asimilo el tema de impresión y paginado que por alguna razón siempre me ha parecido bastante complicado.

Saludos y gracias nuevamente.


P.D. Sebas, he visto que has creado un artículo a partir de este post, pero por alguna razón el código sale mal, porque convierte algunos caracteres en entidades html. Creo que es un fallo en el módulo de base de conocimientos del foro, tendré que revisarlo cuando tenga un rato.
Sin pretender abusar de tu bondad, te aconsejo, sólo para mayor claridad, que trates de elaborar el artículo paso a paso con fragmentos de código limpio (sin comentarios largos) y que los comentarios formen parte del artículo explicando esa parte concreta del código. Estoy seguro de que toda la comunidad te estará muy agradecida, yo el primero


Bueno no es un abuso. Para mí es un placer poder ayudar a la comunidad dentro de mis posibilidades así que lo intentaré.

Impresión en gambas 3. Clase para imprimir el resultado de una consulta SQL

La impresión en gambas3 es la más extraña con la que me he topado desde que programo. Está conducida por eventos.
Intentaré explicarla a partir del código.

' gambas class file

' *********************************************************************************************
' Esta clase dispone lo necesario para crear un listado a partir de un resultado
' ************************************************************************************************

Private iPages As Integer 'Contador de páginas
Private iYPos As Integer 'Índice de la posición vertical durante la impresión
Private RMargin As Integer 'Márgenes derecho, izquierdo, superior e inferior
Private LMargin As Integer
Private TMargin As Integer
Private BMargin As Integer

Private resDatos As Result 'Resultado que vamos a imprimir

Private PrinterName As String
Private pPrinter As Printer
Private FontName As String
Private pFont As Font

Private bolPDF As Boolean 'Imprimir a un archivo pdf
Private iOrientation As Integer 'Orientación 'En apaisado no funciona pero lo incluyo para cuando se pueda solucionar
Private sTitulo As String 'Título del listado

Private fLineHeight As Float 'Alto de la línea de texto
Private fTitleHeight As Float 'Alto del título
Private fTitleFontSize As Float 'Tamaño de letra para el título
Private fLineFontSize As Float 'Tamaño de letra para las líneas


Public Struct FieldPrint
'Esta estructura determina las características de un campo en la impresión
Name As String
X As Integer
Width As Integer
Align As Integer
End Struct

Public Struct Page
'Esta estructura determina la estructura de una página
sFields As FieldPrint[]
lFirstRecord As Long
lLastRecord As Long
End Struct

Private Pages As Page[] 'Almacenará las estructuras de todas las páginas que intervienen en el listado



Inicialmente establecemos todas las variables que vamos a necesitar para realizar la impresión.
Estructura FieldPrint.
contendrá los datos necesarios para imprimir el contenido de un campo (Nombre, Posición X, Ancho de impresión y Alineación)
Estructura Page
Contiene los datos necesarios para imprimir una página (Un array con los FieldPrint que se van a utilizar en dicha página, el primer registro y el último que corresponden a dicha página).
Por último una array -Pages- guardará todas las definiciones de páginas.

Dada la forma de imprimir de gambas necesitamos conocer el número total de páginas antes de iniciar la impresión (lo veremos más adelante). Este conjunto de estructuras y variables nos ayudan a conocer el número de páginas a utilizar y ya de paso definir su contenido. Esto no será necesario en impresiones más simples.

Creación de la clase
Public Sub _new(res As Result, titulo As String, Optional sPrinter As String = "", Optional sFont As String = "Serif", Optional fFontSize As Float = 3.5, Optional orientation As Integer = 0, Optional generarPDF As Boolean = False)

resDatos = res
bolPDF = generarPDF
'*******************************************************
iOrientation = orientation 'Esto no funciona
'*******************************************************
sTitulo = titulo
fTitleFontSize = fFontSize * 1.5
fLineFontSize = fFontSize
PrinterName = sPrinter
FontName = sFont

End


Aquí se da valor a las variables más importantes. Las variables que no están en los parámetros tomarán valor más adelante aunque cada cual puede parametrizar aquellas variables que le parezcan más oportunas para sus listados.

Public Sub Imprimir()
pPrinter = New Printer As "FPrinter"
'Para calcular las posiciones de impresión de cada elemento lo hacemos sobre el área completa de la página y no sobre la
'parte efectivamente imprimible
pPrinter.FullPage = True

'Esto no funciona cuando la orientación es 1 - Landscape
'Lo mismo sucederá si se abre el diálogo de configuración de impresoras y se selecciona landscape
'*********************************************
'pPrinter.Orientation = iOrientation
'**********************************************

If bolPDF Then
pPrinter.Name = "Imprimir a un archivo"
Dialog.Title = "Archivo destino"
Dialog.Path = "/tmp/" & sTitulo
Dialog.Filter = ["*.pdf", "Formato de documento portable"]
Dialog.AutoExt = True
Dialog.SaveFile
pPrinter.OutputFile = Dialog.Path
Else

If Not PrinterName Then
''Cuando se selecciona vista previa no se ejecuta nada del código que venga a continuación
If pPrinter.Configure() Then Return
Endif

Endif

Inc Application.Busy

pPrinter.print 'Dispara el evento Printer_Begin()
Dec Application.Busy

Catch
Message.Error("Error " & Error.Code & " " & Error.Text, "Aceptar")

End


Esta es la única función pública de la clase. Básicamente crea el objeto printer y le manda imprimir. Pero hay que fijarse en varias cosas.

pPrinter.FullPage=TRUE indica que tomaremos las medidas completas de la página para imprimir. De otra forma no conoceremos los márgenes de impresión ya que el objeto printer no tiene propiedades para fijarlos.

pPrinter.Print inicia el proceso de impresión por eventos y no retorna hasta completar la impresión. Si se quiere capturar el resultado devuelve FALSE cuando la impresión se llevó a término sin errores o TRUE si falló o fue interrumpida.
El primer evento que se genera es Begin.

Public Sub FPrinter_Begin()

'La impresión se hace mediante Paint así que establecemos las medidas de Paint a las de nuestra página
Paint.Scale((Paint.Width) / pPrinter.PaperWidth, (Paint.Height) / pPrinter.PaperHeight) 'Cooordenadas en milímetros

pfont = New Font(FontName)

LMargin = 12
RMargin = pPrinter.PaperWidth - LMargin
TMargin = 10
BMargin = pPrinter.PaperHeight - 15

'Aquí tenemos dos opciones que son:
'1 - Indicar el número de páginas a imprimir si podemos conocerlo por ser un listado simple

'pPrinter.Count = iPages

'2 - comentar la línea anterior y utilizar el evento Paginate para calcular el número de páginas a imprimir.
'El evento paginate se dispara si dentro del evento Begin en que estamos no se asigna ninguna cantidad a Count

End


El código de este evento lo aprovechamos para fijar algunas características de la impresión como los márgenes y crear un objeto fuente que nos va a ayudar a calcular los tamaños de impresión. Fijamos también las escalas a que trabajará Paint para ajustarse las medidas de la página que gambas cuenta en mm.

Lo más importante a tener en cuenta es que el bucle local de eventos de impresión exige que se defina el número de páginas que se van a imprimir asignando valor a pPrinter.Count; este valor es fácilmente calculable para trabajos de impresión simples pero en muchos casos solo lo sabremos realizando la impresión o simulándola.
Si no se indica el número de páginas el bucle local dispara el evento Paginate.

Public Sub FPrinter_Paginate()
Dim fld As ResultField, curFieldPrint As FieldPrint, intRecordsPerPage As Integer, curPage As Page, iColPages As Integer
Dim cp As Integer, rp As Integer, iRowPages As Integer

Debug "Paginando"

'Determinando la altura de la línea de título
pFont.Size = fTitleFontSize
fTitleHeight = pFont.TextHeight("H")
'determinando la altura de la línea de texto
pFont.Size = fLineFontSize
fLineHeight = pFont.TextHeight("H")

'Creando las definiciones de páginas
Pages = New Page[]
curPage = New Page
iRowPages = 1 'iRowPages contendrá el número de páginas que ocupa cada fila de datos teniendo en cuenta el tamaño
'de la impresión
curPage.sFields = New FieldPrint[]
pFont.Size = fLineFontSize
'El número de registros que cabrán por página se calcula restando del margen inferior el margen superior, el alto del título,
'el alto de los títulos de columnnas 1 líneas y 1.5 líneas para el número de página
intRecordsPerPage = (BMargin - TMargin - fTitleHeight - fLineHeight - fLineHeight * 1.5) / fLineHeight

For Each fld In resDatos.Fields
curFieldPrint = New FieldPrint
Select Case fld.Type
Case gb.Boolean
curFieldPrint.Width = pFont.TextWidth("T")
curFieldPrint.Align = 3

Case gb.Integer
curFieldPrint.Width = pFont.TextWidth("12345")
curFieldPrint.Align = 2

Case GB.Long
curFieldPrint.Width = pFont.TextWidth("1234567")
curFieldPrint.Align = 2

Case gb.Float
curFieldPrint.Width = pFont.TextWidth("12345,12")
curFieldPrint.Align = 2

Case gb.Date
curFieldPrint.Width = pFont.TextWidth("01/01/0000")
curFieldPrint.Align = 3

Case gb.String
If (fld.Length / 3) > 20 Then 'Length devuelve tres veces la longitud de la cadena
curFieldPrint.Width = pFont.TextWidth("M") * 20
Else
curFieldPrint.Width = (fld.Length / 3) * pFont.TextWidth("a")
Endif

curFieldPrint.Align = 1
End Select
'Comprobamos si entra en la página y si no creamos otra
pFont.Bold = True
curFieldPrint.Width = Max(curFieldPrint.Width, pFont.TextWidth(fld.Name))

If curPage.sFields.Count = 0 Then
curFieldPrint.X = LMargin + 2
curFieldPrint.Name = fld.Name
Else
'CurrentX es igual al anterior X + su ancho + 4 mm de separación
curFieldPrint.X = curPage.sFields[curPage.sFields.Count - 1].X + curPage.sFields[curPage.sFields.Count - 1].Width + 4
curFieldPrint.Name = fld.Name
Endif
If (curFieldPrint.X + curFieldPrint.Width + 2) > (RMargin) Then
curPage.lFirstRecord = 0
curPage.lLastRecord = intRecordsPerPage - 1
Pages.Add(curPage)
curFieldPrint.X = LMargin + 2
curPage = New Page
curPage.sFields = New FieldPrint[]
Inc iRowPages
Endif
curPage.sFields.Add(curFieldPrint)
Next
curPage.lFirstRecord = 0
curPage.lLastRecord = intRecordsPerPage - 1
Pages.Add(curPage)

IRowPages = Pages.Count

iColPages = Int(resDatos.Count / intRecordsPerPage) 'Páginas necesarias para cada columna de datos
'El número total de páginas es iRowPages * iColPages
If resDatos.Count Mod intRecordsPerPage Then Inc iColPages

For cp = 1 To iColPages - 1 'cp es contador para iColPages Contamos desde 1 porque la primera fila de páginas
'ya ha sido definida

For rp = 0 To iRowPages - 1 'rp es contador de iRowPages
curPage = New Page
curPage.sFields = Pages[rp].sFields 'Cada fila de páginas clona la definición de campos de la anterior

'Definiendo filas del resultado a imprimir en la página
curPage.lFirstRecord = cp * intRecordsPerPage
curPage.lLastRecord = (cp + 1) * intRecordsPerPage - 1
'Cuidamos no pasar del último registro aunque en la página quepan más filas
If curPage.lLastRecord > resDatos.Count - 1 Then curPage.lLastRecord = resDatos.Count - 1
Pages.Add(curPage)
Next
Next
'Debug "Páginas a imprimir " & Str(Pages.Count)
pPrinter.Count = Pages.Count
End


El evento paginate debe finalmente dar valor a pPrinter.Count o seguirá generándose este evento en un bucle sin fin. Por lo tanto este valor debe asignarse aunque no es necesario que se haga en una sola ejecución del evento.

Respecto a nuestro código calcula con ayuda de las estructuras FieldPrint y Page los campos que se van a listar en cada página y el número de registros que caben dejando sitio para el título y el número de página.

En el evento Begin habíamos creado un objeto fuente que nos ayudará a calcular el espacio ocupado por los textos mediante los métodos Font.TextWidth y Font.TextHeight.
El objeto Paint no está disponible aún y no podemos utilizar Paint.Font.

Una vez definido el valor de pPrinter.Count se dispara el evento Draw ¡¡¡POR FIN VAMOS A IMPRIMIR!!!



Public Sub FPrinter_Draw()
'Este evento se dispara para cada página a imprimir
Dim fp As FieldPrint, r As Integer
Dim sTexto As String
'Debug "Llegamos a la impresión"


Paint.Font = Font[pFont.ToString()]
Paint.LineWidth = 0.1

Paint.Font.Size = fTitleFontSize
Debug Paint.Font.ToString
Paint.DrawText("Este es el título", LMargin, TMargin, pPrinter.PaperWidth - LMargin * 2, fTitleHeight, Align.Center)

Debug "TextExtends alto " & Paint.TextExtents("Este es el título").Height
iYPos = TMargin + fTitleHeight

Paint.Font.Size = fLineFontSize
Debug Paint.Font.ToString
Paint.Font.Bold = True

Paint.MoveTo(LMargin, iYpos)
Paint.LineTo(LMargin, BMargin - fLineHeight * 1.5)

For Each fp In Pages[pPrinter.Page - 1].sFields
Paint.drawText(fp.Name, fp.X, iYPos, Paint.TextExtents(fp.Name).Width, fLineHeight, Align.Left)
Paint.MoveTo(fp.X + fp.Width + 2, iYPos)
Paint.LineTo(fp.X + fp.Width + 2, BMargin - fLineHeight * 1.5)
Paint.Stroke
Next

Paint.MoveTo(LMargin, TMargin + fTitleHeight)
Paint.LineTo(fp.X + fp.Width + 2, TMargin + fTitleHeight)
Paint.MoveTo(LMargin, TMargin + fTitleHeight + fLineHeight)
Paint.LineTo(fp.X + fp.Width + 2, TMargin + fTitleHeight + fLineHeight)
Paint.MoveTo(LMargin, BMargin - fLineHeight * 1.5)
Paint.LineTo(fp.X + fp.Width + 2, BMargin - fLineHeight * 1.5)
Paint.Stroke
iypos += fLineHeight

' Paint.MoveTo(LMargin, iYPos)
' Paint.LineTo(RMargin, iYPos)

Paint.MoveTo(LMargin, iYPos - fLineHeight)
Paint.LineTo(LMargin, BMargin - fLineHeight * 1.5)
Paint.Stroke
Paint.Font.Bold = False
For r = Pages[pPrinter.Page - 1].lFirstRecord To Pages[pPrinter.Page - 1].lLastRecord
'Debug "Record " & Str(r)
resDatos.MoveTo(r)
With Pages[pPrinter.Page - 1]
For Each fp In .sFields
Paint.drawText(resDatos[fp.Name], fp.X, iYPos, fp.Width, fLineHeight, fp.Align)
'Paint.Fill

Next
End With
iYPos += fLineHeight
Next

Paint.Font.Bold = True
iypos = BMargin - fLineHeight
Paint.DrawText("Página " & Str(pPrinter.Page), LMargin, iypos, pPrinter.PaperWidth - LMargin * 2, fLineHeight, Align.center)
End



El evento Draw se dispara una vez por cada página que tenemos que imprimir. La variable pPrinter.Page nos indica qué página es está imprimiendo en cada entrada y por lo tanto utilizamos la definición de página correspondiente teniendo en cuenta que pPrinter.Page pagina desde la página 1 y el array Pages[] cuenta desde 0.

Aquí es donde se inicializa el objeto Paint para cada página y en este momento ya se pueden utilizar los métodos de Paint para dibujar en la página. En este caso utilizamos el método Paint.DrawText para escribir texto y los métodos Paint.MoveTo y Paint.LineTo para situar el pincel y dibujar líneas respectivamente. Las líneas y otras operaciones de dibujo no se dibujan hasta que se llama al método Paint.Stroke.

Finalmente se produce el evento End del objeto Printer pero en este caso yo no he necesitado utilizarle. este evento se produce cuando la impresión ya ha finalizado por lo tanto no se podrán realizar operaciones de dibujo ni texto en el mismo.


Espero haber dejado claro el funcionamiento de la impresión y no haber sido demasiado extenso o farragoso en las explicaciones. Aquí queda de todas formas una herramienta para imprimir listados por un lado y un tutorial para comprender el sistema de impresión de Gambas3 por otro.

Sebas

última edición por Sebas el Viernes, 11 Enero 2013, 17:48; editado 1 vez
Perfil MP  

Página 1 de 1


  
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas
No puede adjuntar archivos
Puede descargar archivos
No puede publicar eventos en el calendario

   

Está utilizando la versión (Lo-Fi). Para ver la versión completa del foro, haga clic aquí.

Powered by Icy Phoenix based on phpBB
Design by DiDiDaDo

Página generada en:: 1.3851s (PHP: 7% SQL: 93%)
Consultas SQL: 47 - Debug off - GZIP Activado