Múltiples cartas Word desde Access

Si bien este es un tema sobre el que se ha hablado en varios foros, al no encontrar una respuesta, es que hoy me atrevo a postear esta consulta pues necesito imprimir multiples cartas (mil) en Word para distintos destinatarios a partir de mi BD.

Les explico un poco, actualmente utilizo éste código VBA para reemplazar marcadores en una plantilla Word, puesto en un botón, evento "Al hacer click":

Private Sub BtnImpAcuse_Click()
'Generamos carta de acuse automática
On Error GoTo Err_cmdCombinar
Dim AppWord As Word.Application
Dim DocWord As Word.Document
Dim Texto As String

' Variable con el nombre completo de la carta a guardar.
Dim fileName As String
'Variable en la que se tiene u obtiene el nombre de la plantilla.
Dim Plantilla As String
' Variable en la que se tiene u obtiene el nombre del directorio de las cartas.
Dim DirNotas As String
Plantilla = "C:\midirectorio\cartas\CARTA_ACUSE_RC_2.dotx"
DirNotas = "C:\midirectorio\cartas\"

' Abrir el Word utilizando la plantilla.
AppWord.Documents.Add Template:=Plantilla, NewTemplate:=False
Set DocWord = AppWord.ActiveDocument
' Comprobar existencia de los marcadores , si Existe
' y el contenido del cuadro de texto del formulario no es nulo se introduce
' en el documento.
If DocWord.Bookmarks.Exists("Marcador1") Then
If Not IsNull(Campo1) Then
DocWord.Bookmarks("Marcador1").Select
Texto = Campo1
DocWord.Application.Selection.TypeText Text:=Texto
End If
End If
..... SON 7 MARCADORES CON DIFERENTES TIPOS DE DATOS

AppWord.Visible = True
AppWord.ActiveDocument.SaveAs2 fileName
AppWord.WindowState = wdWindowStateMaximize
Exit_cmdCombinar:
DoCmd.Hourglass False
Exit Sub

Err_cmdCombinar:

If Err = 91 Or Err = -2147023174 Then
Set AppWord = New Word.Application
Resume
End If

'bloqueo boton
Me.BtnImpAcuse.Enabled = False
End Sub

Este botón hace su trabajo y hasta ahora funciona bien, la cuestión es que necesito volver a generar las notas desde una fecha determinada al día de hoy y será muy tedioso hacer una por una las mas de mil que hay por hacer, entonces mi consulta concreta es la siguiente:

Como en la misma BD existe una formulario de búsqueda donde a través de una consulta y un Requery puedo tener datos de varios registros en un ListBox independiente de un determinado periodo, los cuales utilizo para generar varios Informes ya sea del resultado total o haciendo selección múltiple; lo que quería saber es si ¿es posible a partir de los resultados del ListBox generar las cartas en Word utilizando el código descrito más arriba?.

1 Respuesta

Respuesta
1

Sí es posible hacer lo que pides, con un bucle que recorra los elementos seleccionados en tu cuadro de lista, pero ya te adelanto que el proceso puede ser lento, sobre todo si tiene que generar muchas cartas.

La cosa iría así, suponiendo que tu cuadro de lista tenga las 7 columnas con los datos que usas en tus marcadores:

Private Sub BtnImpCartas_Click()
On Error GoTo Err_cmdCombinar
Dim AppWord As Word.Application
Dim DocWord As Word.Document
Dim Texto As String
Dim Opcion as Variant
Dim i As Integer
Dim fileName As String
Dim Plantilla As String
Dim DirNotas As String
Plantilla = "C:\midirectorio\cartas\CARTA_ACUSE_RC_2.dotx"
DirNotas = "C:\midirectorio\cartas\"
For Each Opcion In Me.CuadroLista.ItemsSelected
   AppWord.Documents.Add Template:=Plantilla, NewTemplate:=False
   Set DocWord = AppWord.ActiveDocument
   For i = 0 To Me.CuadroLista.ColumnCount - 1
      If DocWord.Bookmarks.Exists("Marcador1") Then
         If Not IsNull(Campo1) Then
            DocWord.Bookmarks("Marcador1").Select
            Texto = Me.CuadroLista.Column(i, Opcion)   
            DocWord.Application.Selection.TypeText Text:=Texto
         End If
      End If
..... SON 7 MARCADORES CON DIFERENTES TIPOS DE DATOS
   Next i
   'AppWord.Visible = True
   AppWord.ActiveDocument.SaveAs2 fileName
   'AppWord.WindowState = wdWindowStateMaximize
   AppWord.Quit
   Set AppWord=Nothing
Next Opcion
Exit_cmdCombinar:
DoCmd.Hourglass False
Exit Sub
Err_cmdCombinar:
If Err = 91 Or Err = -2147023174 Then
Set AppWord = New Word.Application
Resume
End If
Me.BtnImpAcuse.Enabled = False
End Sub

En teoría solo has de cambiar Me.CuadroLista por el nombre que le hayas dado a tu cuadro.

Gracias!. Lo probaré y te cuento como me ha ido. Saludos!

Lo probé (con los nombres de mi BD) y me da un error de compilación de variable no definida en la linea:

 If Not IsNull (MisionRemite) Then

Obviamente suponiendo que el dato lo tomará no de un Campo a través del formulario sino de una columna del cuadro de lista lo puse de la siguiente manera:

If DocWord.Bookmarks.Exists("MisionRemite1") Then
   If Not IsNull(Me.Lista_RESULTADO.Column(i, Opcion)) Then
   DocWord.Bookmarks("MisionRemite1").Select
   Texto = Me.Lista_RESULTADO.Column(i, Opcion)
   DocWord.Application.Selection.TypeText Text:=Texto
  End If
End If

Ya no saltó el error de compilación pero no ocurre nada. Aclaro que las 7 columnas de mi Cuadro Lista se corresponden con los marcadores de mi Plantilla. Evidentemente algo estoy haciendo mal.

Nuevamente gracias!

Has corregido bien el error que te daba, pues no me fijé en que también tenía que haber cambiado la referencia del campo por la de la columna del cuadro de lista.

Como habías dicho que el código funcionaba, no me paré a mirarlo, solo le hice los añadidos para responder a tu pregunta. Pero ahora que lo he replicado en una BD, veo que hay algún que otro error que probablemente sea la causa de que no te funcione mi propuesta (además de que tal como la puse tampoco acaba de ir del todo bien).

A ver así:

Private Sub BtnImpCartas_Click()
On Error GoTo Err_cmdCombinar
Dim AppWord As Word.Application
Dim DocWord As Word.Document
Dim Texto As String
Dim Opcion as Variant
Dim i As Integer
Dim fileName As String
Dim Plantilla As String
Dim DirNotas As String
Plantilla = "C:\midirectorio\cartas\CARTA_ACUSE_RC_2.dotx"
DirNotas = "C:\midirectorio\cartas\"
For Each Opcion In Me.Lista_RESULTADO.ItemsSelected
   Set AppWord = New Word.Application
   AppWord.Documents.Add Template:=Plantilla, NewTemplate:=False
   Set DocWord = AppWord.ActiveDocument
   'Para el primer marcador coges el valor de la primera columna
      If DocWord.Bookmarks.Exists("Marcador1") Then
         If Not IsNull(Me.Lista_RESULTADO.Column(0, Opcion)) Then
            DocWord.Bookmarks("Marcador1").Select
            Texto = Me.Lista_RESULTADO.Column(0, Opcion)   
            DocWord.Application.Selection.TypeText Text:=Texto
         End If
      End If
   'Para el segundo marcador coges el valor de la segundacolumna
      If DocWord.Bookmarks.Exists("Marcador1") Then
         If Not IsNull(Me.Lista_RESULTADO.Column(1, Opcion)) Then
            DocWord.Bookmarks("Marcador1").Select
            Texto = Me.Lista_RESULTADO.Column(1, Opcion)   
            DocWord.Application.Selection.TypeText Text:=Texto
         End If
      End If
    'Y así con los otros 5 marcadores (obviamente modificando el tipo de dato si lo necesitas)
   Next i
   'AppWord.Visible = True
   AppWord.ActiveDocument.SaveAs fileName:=DirNotas & "Carta a " & Me.Lista_RESULTADOS.Column(1, opcion) & ".docx"
   'AppWord.WindowState = wdWindowStateMaximize
   AppWord.Quit
   Set AppWord=Nothing
Next Opcion
Exit_cmdCombinar:
DoCmd.Hourglass False
Exit Sub
Err_cmdCombinar:
If Err = 91 Or Err = -2147023174 Then
Set AppWord = New Word.Application
Resume
End If
Me.BtnImpAcuse.Enabled = False
End Sub

Fíjate en la línea que guarda el documento, en el ejemplo te lo guarda en la ruta de la variable DirNotas con el nombre "Carta a " y el valor de la segunda columna de la fila seleccionada en cada pasada, y con extensión docx. Lógicamente esa linea la tendrás que modificar para que te guarde donde quieras y con el nombre que quieras.

Te adjunto también el archivo sobre el que hice la prueba (el código es prácticamente el mismo, solo le quité las validaciones de que las columnas no sean nulas, porque sé que en el ejemplo nunca lo serán) y que funciona perfectamente: http://www.filebig.net/files/BqTpSGUMgH

¡Gracias de nuevo!... Lo pruebo y ahí te digo como me ha ido.

Finalmente después de varios retoques el código ha funcionado de maravillas!. Ahora solo me queda programar una opción que genere un mensaje de error en caso de no seleccionar algún resultado de la lista (puede pasar) y voila!. Debo agradecerte Sveinbjorn El Rojo por tu invaluable ayuda. Llegue para ti un fuerte abrazo.

Lo del mensaje al no seleccionar ningún valor lo puedes resolver de varias formas, por ejemplo:

Private Sub BtnImpCartas_Click()
On Error GoTo Err_cmdCombinar
Dim AppWord As Word.Application
Dim DocWord As Word.Document
Dim Texto As String
Dim Opcion as Variant
Dim i As Integer
Dim fileName As String
Dim Plantilla As String
Dim DirNotas As String
'Creas una variable de control
Dim haySeleccion as Boolean  
'Le asignas inicialmente el valor False 
haySeleccion=False 
Plantilla = "C:\midirectorio\cartas\CARTA_ACUSE_RC_2.dotx"
DirNotas = "C:\midirectorio\cartas\"
For Each Opcion In Me.Lista_RESULTADO.ItemsSelected
   'Si hay algo seleccionado, entras al bucle y le das valor True
   haySeleccion=True 
   Set AppWord = New Word.Application
   'aquí el resto del código para pasar los marcadores
   ....
Next Opcion
'Compruebas la variable, si es False es porque no se seleccionó nada en el cuadro de lista
'y lanzas el mensaje que quieras
If Not haySeleccion Then
    MsgBox "No has seleccionado ningún valor", vbCritical,"Error"
End If
Exit_cmdCombinar:
DoCmd.Hourglass False
Exit Sub
Err_cmdCombinar:
If Err = 91 Or Err = -2147023174 Then
Set AppWord = New Word.Application
Resume
End If
Me.BtnImpAcuse.Enabled = False
End Sub

Te van las lineas nuevas precedidas de comentarios explicativos

¡Gracias de nuevo!. Lo aplicaré e informo sobre el resultado para que les sirva a otros usuarios. Aprovechando que estamos en éste tema de Word y marcadores, hoy me han pedido incluir al mismo docx, unas tablas (cómo las de un detalle de venta) con marcadores pero a partir de un subform. Talvez sea tema para otra pregunta pero si puedes darme luz sería genial. Cordial saludo!

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas