Exportar en lote facturas access vba

Agradecer de antemano la ayuda como siempre.

Tengo un formulario con un listado de facturas. Tengo un botón que pretendo que exporte en pdf en lote las facturas filtradas, pero el problema es que solo la primera de la lista obtiene los datos de la factura, las demás aparecen con el contenido en blanco.

El código del botón es este:

Private Sub Comando124_Click()
On Error Resume Next
Dim i As Integer
DoCmd.GoToRecord , , acFirst
For i = 1 To Me.Recordset.RecordCount
DoCmd.OpenReport "FacturaListado", acViewReport, , "NumeroFactura='" & Me.NumeroFactura & "'", acHidden
DoCmd.OutputTo acOutputReport, "FacturaListado", "PDFFormat(*.pdf)", "D:\PRODUCCION\FACTURAS\TEMPORAL\" & [NumeroFactura] & ". " & [ClienteFiscal] & ". " & [TituloFactura] & ".pdf"
DoCmd.GoToRecord , , acNext
Next
If p = Me.Recordset.RecordCount Then
Exit Sub
End If
End Sub

He probado varias cosas, pero no funciona, siguen saliendo en blanco menos el primero. Alguna sugerencia?

1 Respuesta

Respuesta
1

Si Access hiciera caso, lo más probable es que la página final fuera negra y chorrearía la tinta.

Para que se genere el informe (y con el el PDF) hay que abrirlo, utilizarlo y CERRARLO para iniciar un nuevo ciclo.

Antes del Next cierra el informe para que se complete el ciclo y el segundo y siguientes se puedan crear adecuadamente.

P.D.

Creo que seria el momento idóneo para unir el PDF recién creado con su dirección de correo-e asociada así como otros detalles (facilitaría su envío) aunque se puede buscar después.

Gracias Enrique. Había probado también con una posible solución, pero sigue saliendo igual:

Private Sub Comando124_Click()
On Error Resume Next
Dim i As Integer
DoCmd.GoToRecord , , acFirst
For i = 1 To Me.Recordset.RecordCount
DoCmd.OpenReport "FacturaListado", acViewReport, , "NumeroFactura='" & Me.NumeroFactura & "'", acHidden
DoCmd.OutputTo acOutputReport, "FacturaListado", "PDFFormat(*.pdf)", "D:\PRODUCCION\FACTURAS\TEMPORAL\" & [NumeroFactura] & ". " & [ClienteFiscal] & ". " & [TituloFactura] & ".pdf"
DoCmd.Close acReport, "FacturasListado"
DoCmd.GoToRecord , , acNext
Next
If p = Me.Recordset.RecordCount Then
Exit Sub
End If
End Sub

La línea que cierra el informe de la factura está puesta justo después de la exportación a pdf y antes de que el código vuelva al primer registro, debería ser de otra manera?

Este caso me serviría para poder generar un correo (con formato html) para adjuntar al cliente todos las facturas generadas y archivadas, pero desconozco cómo podría hacerlo, sabrías el código?

También es cierto que son funciones distintas, es decir, no siempre que tengo que generar y guardar la factura en la carpeta correspondiente necesito enviar la factura por correo, ya que la mayoría se envían por whatsapp.

El destino de las facturas puede ser variable sea correo postal, correo electrónico, WhatsApp, adjunta al producto o cualquiera otro que se acuerde con el cliente.

Creo que para utilizar el correo electrónico o WhatsAppp hay que generarla en PDF (las otras en papel) y esa característica debería figurar en la ficha del cliente, ello permitiría clasificarlas separando en una carpeta las del correo-e, en otra WhatsApp y en otra las de papel (para imprimirlas mas tarde) o simplemente se desprecian (se generaran cuando les corresponda).

Desconozco como se gestiona en esa empresa la facturación y desconociendo el método, vamos a crear uno básico: generarlas todas en formato PDF

De la clasificación de los destinos que se encargue otro (que posiblemente 'te odie' pero ese es 'otro problema').

Vamos a partir del supuesto de que si no se le condiciona, el actual informe imprimirá todas las facturas de forma correcta y de que si se le condiciona: imprime la que se le indique.

En el evento Open del informe se añade una condición: si 'una variable' tiene contenido se aplica como filtro, si no tiene contenido se la ignora (y aquí no se puede aplicar el clásico OpenArgs), hay que ser creativos.

En cualquier modulo independiente, declaramos la variable de texto y publica:

Public FiltroInf As String

En el informe y su evento Open aplicamos la condición:

Private Sub Report_Open(Cancel As Integer)
If Len(FiltroInf) > 0 Then Me.Filter = FiltroInf: Me.FilterOn = True
End Sub

Con esto se evita el tener que abrir y cerrar el informe para poder exportarlo, se aplica el filtro al informe mediante la variable y directamente se ejecuta la exportación.

Un ejemplo en el que se utiliza una tabla con dos campos (uno numérico, otro de texto) y ... los demás, se utilizan los daos campos como ejemplo para números y texto.

Abrimos la tabla, verificamos que existen datos para continuar o abortar y la recorremos generando el filtro en tiempo de ejecución (a la tabla la puede sustituir una consulta, solo es un origen de datos).

He creado esta función en un modulo independiente (por eso la variable ha de ser publica) si se crea en un formulario puede ser privada.

Public Function Crea_PFDs()
Dim M_Tabla As DAO.Recordset
Set M_Tabla = CurrentDb.OpenRecordset("Tbl_Datos", , dbReadOnly)
If M_Tabla.RecordCount = 0 Then Exit Function
With M_Tabla
.MoveLast: .MoveFirst
Do Until .EOF
FiltroInf = "Dato_1 = '" & !Dato_1 & "' And Dato_2 = " & !Dato_2
DoCmd.OutputTo acOutputReport, "Inf_Datos", "*.pdf", "F:\Temporal\AAAA" & !Dato_1 & " - " & !Dato_2 & ".pdf", False, , , acExportQualityPrint
.MoveNext
Loop
.Close
End With
End Function

En el disco y carpeta tenemos todos los PDFs y se decide enviarlos como adjuntos a la bandeja de salida de correo-e, nos quedamos con las dos líneas:
.- La condición (se puede utilizar la misma que se aplica actualmente para abrir el informe)
FiltroInf ="NumeroFactura='" & Me.NumeroFactura & "'"

.- La generación del PDF
DoCmd.OutputTo acOutputReport, "Inf_Datos", "*.pdf", "F:\Temporal\AAAA" & !Dato_1 & " - " & !Dato_2 & ".pdf", False, , , acExportQualityPrint 

Tras finalizar la creación de ese correo se puede matar el archivo con Kill (tenemos su nombre y ubicación) y limpiaremos la variable utilizada, si se utiliza una variable de texto para la ruta es mas sencillo aún.

Kill "F:\Temporal\AAAA" & !Dato_1 & " - " & !Dato_2 & ".pdf
FiltroInf = ""

Espero que sea útil este método de generar el/los PDF y te ayude a conseguir el objetivo para el envío unitario o la generación en bloque.

Muchas gracias Enrique.

Debido a mi bajo nivel de conocimiento de vba me llevará un pelín de tiempo implementar lo que me dices, pero te agradezco mucho la explicación.

Sí que había advertido un error en mi código que era lo que, en la función de imprimir en lote me estaba provocando facturas en blanco. En la línea de cierre de informe había una "s" en el nombre del mismo que no lo estaba aplicando, así que el código

Private Sub Comando124_Click()
On Error Resume Next
Dim i As Integer
    DoCmd.GoToRecord , , acFirst
    For i = 1 To Me.Recordset.RecordCount
        DoCmd.OpenReport "FacturaListado", acViewReport, , "NumeroFactura='" & Me.NumeroFactura & "'", acHidden
        DoCmd.OutputTo acOutputReport, "FacturaListado", "PDFFormat(*.pdf)", "D:\PRODUCCION\FACTURAS\TEMPORAL\" & [NumeroFactura] & ". " & [ClienteFiscal] & ". " & [TituloFactura] & ".pdf"
        DoCmd.Close acReport, "FacturaListado"
    DoCmd.GoToRecord , , acNext
    Next
        If p = Me.Recordset.RecordCount Then
        Exit Sub
    End If
End Sub

es correcto, lo dejo aquí para que cualquier otro lo pueda utilizar.

Muchas gracias de nuevo!

Elimina el control de errores (los errores no se oculta: se corrigen)

Elimina la innecesaria verificación de que 'se recorrió el bucle tras finalizar el bucle', esto es: elimina todo lo que hay después del NEXT y desaparece el error que se intenta ocultar.

Desconozco el tiempo que se tarde en generar los PDF, pero seguramente el triple de lo que se tardaría con el método que propuse.

Recorrer el formulario registro a registro le lleva 'su tiempo' al que se suma el de crear el informe para luego destruirlo (con ese método el informe se ejecuta dos veces, la segunda se solapa con la primera).

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas