Abrir varias instancias de un mismo Informe en Access

Necesitaría saber si me pueden orientar sobre que material leer o si bien alguien dispone de un ejemplo similar para lograr varias instancias de un informe en VBA Access. El informe en cuestión filtra datos anuales de una tabla. Quisiera lograr abrir el mismo informe y comparar la información en varios años. Es decir, por ejemplo, abrir tres veces el mismo informe con los años 2018, 2020 y 2022 por decir unas fechas.

No necesito el código exacto, pero al menos algo orientativo. No encontré mucha información. Leí algo sobre "collection" pero nada que me puede ayudar. También encontré una forma de como abrir hasta dos formularios, pero no lo pude replicar en informes y la verdad es que tampoco es lo que necesito

3 respuestas

Respuesta
2

Carlos, con todo respeto las respuestas que le dan no son la solución. Claro que se pueden instanciar los reportes como si fueran formularios. Le preparé este ejemplo

TABLA

FORMULARIO PARA ELEGIR LOS REPORTES

Selecciono tres registros y hago clic en Imprimir y obtengo:

RESULTADO DE LOS REPORTES

CONSULTA ORIGEN DE DATOS PARA EL REPORTE

Observe que para el Criterio he asignado en resultado de una función, se llama micliente()

CÓDIGO DE BOTÓN IMPRIMIR 

Private Sub cmdActualza_Click()
  Dim varPos As Variant
  Dim strFiltro As String
  Dim frmChild  As Report_rptClientes
  Dim x, y, w, z As Integer
  Dim maxForm As Integer
  Dim strArchivo As String
  x = 1400 ' Izquierda
  y = 1400 ' Superior
  maxForm = 5 ' Máximo número de reportes que se pueden abrir
  ' Reviso que haya seleccionado uno o mas clientes
   If Me.lstclientes.ItemsSelected.Count = 0 Then
        MsgBox "Debe seleccionar uno o más clientes.", vbInformation, "Error"
        Exit Sub
    End If
    'Verifico si seleccionó todos los clientes - tendría problema de Memoria Insuficiente
    'Igualmente se podría condicionar para que se abra un número limitado de formularios
 'mediante, por ejemplo, Me. Lstclientes. ItemsSelected. Count >10
    If Me.lstclientes.ItemsSelected.Count > maxForm Then
       MsgBox "Máximo puede abrir 5 reportes", vbInformation, "Cuidado"
       Exit Sub
    End If
    If flag Then
       If MsgBox("¿Está seguro de seleccioanar todos los clientes, podría tener problema de memoria?", vbYesNo + vbDefaultButton2 + vbQuestion, "CUIDADO") = vbNo Then
         Exit Sub
       End If
    End If
 ' Aca está la parte interesante, observe como uso Set frmChild = New Report_rptClientes
 ' para instanciar el formulario frmClientes
  For Each varPos In Me.lstclientes.ItemsSelected
    strFiltro = Me.lstclientes.ItemData(varPos)
    idcliente = strFiltro  ' Guardo el ID del cliente para pasarselo a la función
     Set frmChild = New Report_rptClientes
      With frmChild
         .Caption = Me.lstclientes.Column(1, varPos) & " " & Me.lstclientes.Column(2, varPos)
         .Move Left:=x, Top:=y
         .Filter = strFiltro
         .FilterOn = True
         .Visible = True
         idcliente = strFiltro
         colFormList.Add frmChild
         x = x + 200
         y = y + 250
      End With
  Next varPos
End Sub

CÓDIGO QUE SE DEBE INCLUIR EN UN MODULO

Option Compare Database
Option Explicit
 Public colFormList As New Collection
 Public idcliente As Long
Public Function micliente() As Long
  micliente = idcliente
End Function

Eduardo, la verdad que tu respuesta es justamente lo que estaba buscando, es la repuesta a lo que plantee inicialmente en mi cabeza cuando pensaba en como implementarlo. La otras opciones que me pasaron fueron también otra forma de lograr un resultado muy similar, sobre todo la de imprimir y abrir archivos pdf que fue lo que logré implementar anoche a última hora. Muchas gracias por tomarte el tiempo y preparar el ejemplo que cuando finalice aquí te escribí para pedírtelo. Gracias a personas como Uds esto crece día a día! Un gusto contactar genete con tanto conocimiento e ideas!

Respecto a enviar los reportes a PDF no veo la necesidad, pero lo importante es que haya solucionado su problema.

La idea no es enviarlo, lo que buscaba era comparar la información. Al selectar los años, dado que no podía lograr lo que tu hiciste, la forma que me ayudaba a lograr el mismo efecto era abrir cada año en un pdf y efectuar la comparación.

Carlos, creo que su intención es realizar reportes dinámicos con consultas de referencias cruzadas. Se puede obtener de la misma forma como le explique, solo que se deben adicionar otra variable pública para el año y con base en esta crear una función, la cual se le pasa a la consulta, no se ponga a crear tablas auxiliares ni crear archivos PDF, estos los puede generar al imprimir, en mis aplicaciones creo un menú en la cinta de opciones para los reportes, en donde puede enviarlos a PDF. Observe la siguiente imagen en donde selecciono de un cuadro de lista los años.

FORMULARIO

Al hacer clic en Imprimir, obtengo:

Así de practico sin tantas vueltas, me extraña que un "experto" en Access no sepa manejar las clases e instancias.

Respuesta
1

Ante la falta de alternativas, queda la opción de crear una copia del informe por cada instancia, al momento de abrir los informes, aplicarles el filtro por año.

Finalizado el trabajo se verifica que estén cerrados (se conoce sus nombres, ya que se les ha 'bautizado') y si no lo están se les cierra, tras ello se les destruye.

No es la opción más elegante y si se utiliza con frecuencia no sería una mala idea el compactar la base para eliminar el espacio utilizado y no liberado.

Hay alternativas a los informes sin complicarse mas de lo indispensable y manteniendo a raya la ecología.

Se basaría en imprimirlos de forma virtual: en PDF
(Desde la versión A'2010 esta 'disponible' como impresora virtual licenciada por Adobe).

Dado que se conocen sus nombres y ubicaciones, teniendo esos datos se pueden abrir desde Access de forma automatizada y/o enviar a otros destinatarios incluso destruirlos, para ello se puede utilizar la función Kill cerciorándose de que el archivo este cerrado.

Respuesta
1

En principio, sin saber como quieres comparar los años, no necesitas abrir varios informes. Por ejemplo, supongamos que tengo una tabla Pedidos con la fecha del pedido, y quiero comparar los pedidos por meses y años( sólo hay pedidos de 1996,1997 y 1998, bendita Neptuno).

tengo creada una tabla Aux que sólo me sirve para que el informe me salga "bonito"

En un formulario te pongo dos ejemplos de como lo puedes hacer, o bien con un cuadro de lista multiselección o un cuadro combinado.

1º Cuadro de lista. Selecciono los años que quiero comparar

Cuando pulso Ver Informe

En el caso de usar el combinado, selecciono un año, y ya no me aparece más( para evitar que por error se vuelva a seleccionar el mismo

Selecciono 1996 y luego selecciono 1998( puedes ver que en el combinado ya no me aparece el año 1996)

y al pulsar Ver informe

En este caso, en el evento Al hacer clic del botón del cuadro de lista le tengo puesto

Private Sub Comando40_Click()
Dim var As Variant
For Each var In Me.Lista38.ItemsSelected
DoCmd.RunSQL "INSERT INTO Aux ( TotalMes, Año, MesN, MesL ) SELECT Count([FechaPedido]), Year([fechapedido]), Month([fechapedido]), Format([fechapedido],""mmmm"")" _
& " FROM Pedidos GROUP BY Year([fechapedido]), Month([fechapedido]), Format([fechapedido],""mmmm"")HAVING Year([fechapedido]) = " & Me.Lista38.ItemData(var) & "" _
& " ORDER BY Year([fechapedido]), Month([fechapedido])"
Next
DoCmd.OpenReport "aux", acPreview
End Sub

En el caso del combinado, en el evento Después de actualizar del cuadro combinado

Private Sub ElegirAño_AfterUpdate()
DoCmd.SetWarnings False
DoCmd.RunSQL "INSERT INTO Aux ( TotalMes, Año, MesN, MesL ) SELECT Count([FechaPedido]), Year([fechapedido]), Month([fechapedido]), Format([fechapedido],""mmmm"")" _
& " FROM Pedidos GROUP BY Year([fechapedido]), Month([fechapedido]), Format([fechapedido],""mmmm"")HAVING (((Year([fechapedido])) = [Forms]![formulario4]![ElegirAño]))" _
& " ORDER BY Year([fechapedido]), Month([fechapedido])"
ElegirAño.Requery
End Sub

En el origen de la fila de ese combinado le tengo puesto

SELECT Year([fechapedido]) AS Año FROM pedidos WHERE (((Year([fechapedido])) Not In (SELECT año FROM aux))) GROUP BY Year([fechapedido]);

Y en el evento Al hacer clic del botón Ver Informe del combinado le tengo puesto

Private Sub Comando41_Click()
DoCmd.OpenReport "aux", acPreview
End Sub

Se podría hacer por columnas, pero eso lleva mucho trabajo.

Julián, muchas gracias por la dedicación a la respuesta. Sin querer me solucionaste un problema que tenia a futuro, así que muchas gracias de antemano! El problema que tengo al implementar esta solución es que son informes muy complejos. Son informes resultantes de una tabla de referencias cruzadas y de cada mes. Similar a tu ejemplo pero más complejas ya que los meses están en el eje horizontal y los items a listar y a comparar están en el vertical. Pero como te dije anteriormente es ideal para otro problema que estaba teniendo y había dejado para después. Muchas gracias nuevamente por tu respuesta y el ejemplo! .

El problema de las consultas de referencias cruzadas es que sólo sirven para el momento en que se hacen.

Si totalmente de acuerdo. El problema que es una base de datos que fue creciendo a medida que se iba usando y a medida que iba conociendo funciones y capacidades. Lo mío es completamente autodidacta y me apoyo mucho en internet sitios como este, que nos ayudan a los que intentamos mejorar nuestras creaciones. Ahora después de hacer ese informe que es muy útil en la inofrmación que muestra, a alguien se le ocurrió que era un necesidad de compararlo en los diferentes años ja ja, mas que nada por eso seguí en esa línea. Esto me dejo como enseñanza una mejor planificación para la próxima. Muchas gracias por tu aporte.

Carlos, que sepas que también se puede presentar como si fuera una consulta de referencias cruzadas sin necesidad de usarlas, ya que son muy engorrosas. Por ejemplo, acuérdate de mi tabla Pedidos. Pues en un formulario elijo los años que quiero

Y cuando pulso Ver el informe

Y no creas que es tan complicado

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas