COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES

Hola a todos!

El post de hoy va a ser distinto a los que acostumbro a subir a la web, sobre todo porque está programado en WORD.

Hace ya tiempo que escribí un post relacionado con Combinar Correspondencia, en concreto para intentar dar solución a un problema muy común cuando se realiza esta funcionalidad con WORD, es decir, el obtener de manera individual todos los documentos generados.

Si no estáis familiarizados con Combinar Correspondencia, en este enlace podéis leer en profundidad de qué se trata. Si bien, en resumen, combinamos los campos de un archivo de Excel con una plantilla en WORD y generamos tantos documentos como datos tengamos en Excel. Podemos enviar por correo electrónico cada documento a su destinatario o generar los documentos todos a la vez, de uno en uno o por tramos.

Pero entonces, ¿cuál es el problema?, pues que si tenemos que generar 500 cartas (individuales), sería bastante tedioso el tener que generar y guardar cada documento de uno en uno manualmente.

Ante esta necesidad, en un primer avance lo he realizado con Excel directamente, y el proceso funciona correctamente, pero tiene sus limitaciones (fundamentalmente los formatos). Para solucionarlo me he decidido a hacerlo en Word. Me documenté con algunos procesos que se proponen en Internet, pero no me acababan de convencer, eran demasiado manuales y poco intuitivos. Así que he creado un proceso bastante más automatizado para facilitar la experiencia del usuario.

El primer paso que debemos realizar es obtener el archivo de WORD con los documentos ya generados, todos en el mismo archivo. Importante, el proceso está programado para documentos que ocupen un folio (una hoja de Word).

Pues bien, vamos a hacerlo paso a paso:

  • Generamos los documentos con Combinar correspondencia. Vamos a partir del siguiente listado en Excel (100 líneas)

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES

  • Combinamos correspondencia con el siguiente texto:

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES1

Una vez que hemos combinado y generado todos los documentos obtendremos un archivo de 100 hojas (una por empleado de la base de Excel).

A continuación, ese documento lo vamos a guardar, pero lo haremos o bien como .Doc o como .Docm (para macros), pero no .Docx. El motivo es que vamos a incluir una macro en el documento y con extensión .Docx no permite guardar con macros. Para este ejemplo lo denominaré como “DOCUMENTOS GENERADOS”

Hasta este punto ya tenemos el archivo de Word que queremos trocear en 100 archivos. Ahora debemos crear una carpeta o saber en cuál vamos a importar todos estos archivos, en mi ejemplo la crearé y la denominaré: “DESTINO”.

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES3

Y ya tenemos todo lo necesario para abrir DOCUMENTOS GENERADOS, crear un módulo estándar y pegar nuestra macro:

Option Explicit
Sub COMBINAR()
'DECLARAMOS VARIABLES
Dim mArchivo As Variant, fdocument As Document
Dim miExcel As String, target As Variant, obSQL As String
Dim cnn As Object, dataread As Object, filas As Long
Dim i As Long, iname As Variant, midoc As Document
Dim mi_archivo As String, campo As String, miCarpeta As Variant
Dim texto As Variant, target_a As Variant
'Capturamos documento actual
Set fdocument = ThisDocument
'Abrimos ventana de diálogo para seleccionar el archivo Excel
'que hemos combinado
Set mArchivo = Application.FileDialog(msoFileDialogOpen)
If mArchivo.Show = 0 Then Exit Sub
miExcel = mArchivo.SelectedItems(1)
'Abrimos ventana de diálogo para seleccionar la carpeta en la que
'guardaremos todos los archivos independientes
Set miCarpeta = Application.FileDialog(msoFileDialogFolderPicker)
If miCarpeta.Show = 0 Then Exit Sub
miCarpeta = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1) & "\"
'Generamos documento nuevo
Set target = Documents.Add
'Con instrucción SQL seleccionamos el nombre de la hoja
'y el campo con el que queremos identificar cada documento de word
obSQL = "SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]"
'Iniciamos conexión ADO para pasar una tabla con los items
'del campo seleccionado
Set cnn = New ADODB.Connection
With cnn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Connectionstring = "DATA SOURCE=" & miExcel
.Properties("Extended Properties") = "Excel 8.0"
.Open
End With
Set dataread = New ADODB.Recordset
With dataread
.Source = obSQL
.ActiveConnection = cnn
.CursorLocation = adUseClient
.CursorType = adOpenForwardOnly
.LockType = adLockReadOnly
.Open
End With
'Grabamos los datos en el documento Word generado (target)
dataread.MoveFirst
filas = dataread.RecordCount
Selection.InsertAfter dataread.Fields(0)
Do Until dataread.EOF
dataread.MoveNext
If dataread.EOF = "Verdadero" Then Exit Do
campo = Replace(dataread.Fields(0), "-", " ")
Selection.InsertAfter Chr(11) & campo
Loop
'Formateamos los datos grabados como una tabla
Selection.ConvertToTable Separator:=wdSeparateByDefaultListSeparator, _
numcolumns:=1, Numrows:=filas, AutoFitBehavior:=wdAutoFitFixed
Set midoc = ActiveDocument
'Recorremos la tabla
For i = 1 To midoc.Tables(1).Rows.Count
Set iname = midoc.Tables(1).Cell(i, 1).Range
'Eliminamos de cada dato el retorno de carro, Chr(13).
'Eliminamos el último caracter de la cadena de texto
mi_archivo = Mid(Replace(miCarpeta & iname.Text, Chr(13), ""), 1, Len(Replace(miCarpeta & iname.Text, Chr(13), "")) - 1)
'Recorremos todas las hojas del documento word actual
'Creamos un nuevo documento y pasamos el contenido de cada combinación.
Set texto = fdocument.Sections(i).Range
texto.End = texto.End - 1
Set target_a = Documents.Add
target_a.Range.FormattedText = texto
'Nombramos cada documento con el nombre
'de la hoja que contiene los datos extraidos de Excel
target_a.SaveAs FileName:=mi_archivo
'Cerramos cada documento
target_a.Close
Next i
'cerramos el documento con los datos de Excel
ActiveDocument.Close SaveChanges:=False
End Sub

Después de pegar la macro, debemos activar las referencias para trabajar con ADO: Microsoft ActiveX Data Object 2.8 Library (en caso de no tener esta librería podéis probar con otra de la lista).

Este paso debéis hacerlo, de lo contrario se mostrará un error y no podréis continuar.

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES4

Otro paso que debemos realizar manualmente es determinar el campo del archivo Excel a incluir en el documento de Word.

Debemos especificarlo en la siguiente línea de código:

obSQL = "SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]"

Donde la hoja de nuestro archivo Excel se denomina BBDD, debemos especificarlo en la sentencia SQL y siempre con el dólar al final. El campo que vamos a incluir será NOMBRE COMPLETO y también lo especificamos en el SQL. Este paso es importante, si el nombre de la hoja o del campo no es correcto, se mostrará un error y no podremos continuar. Si se muestra el error, debéis reiniciar la macro para volver a ejecutarla y eliminar el documento en blanco que se creó antes de llegar al error.

Pero sigamos, suponiendo que ya tenemos la macro totalmente preparada, cuando la ejecutemos se mostrará un cuadro de diálogo para seleccionar el archivo Excel:

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES6

A continuación se volverá a abrir otro cuadro de diálogo para seleccionar la carpeta en la que dejaremos todos los 100 documentos creados:

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES7

Después dejaremos que se vayan generando los documentos hasta que finalice la macro, el resultado será este:

COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES5

Como podéis observar hemos generado 100 documentos y los hemos identificado con su nombre (podría ser con otro campo cualquiera que sea un identificados único).

Y eso es todo!. Espero que el post sea lo bastante claro y no os queden dudas, pero en cualquier caso, os dejaré los dos archivos para que realicéis pruebas.

Descarga el archivo de ejemplo pulsando en: DOCUMENTOS GENERADOS

Descarga el archivo de ejemplo pulsando en: BASE EXCEL PARA COMBINAR

¿Te ha resultado de interés?, puedes apoyar a Excel Signum con una pequeña donación.

Donate Button with Credit Cards

¡¡Muchas gracias!!

Mediante la suscripción al blog, la realización comentarios o el uso del formulario de contacto estás dando tu consentimiento expreso al tratamiento de los datos personales proporcionados según lo dispuesto en la ley vigente (LOPD). Tienes más información al respecto en esta página del blog: Política de Privacidad y Cookies

Anuncios

29 pensamientos en “COMBINAR CORRESPONDENCIA Y GUARDAR DOCUMENTOS INDEPENDIENTES

  1. COMBINAR CORRESPONDENCIA me genera un ERROR Estoy seguro que se debe al paso manual: obSQL = “SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]” este paso hay que hacerlo en el Nombre del archivo en Word ? Remito archivo completo COMPRIMIDO Favor colaborarme Gracias

    Me gusta

    • Hola Emiro:

      No me ha llegado ningún archivo. El paso manual hace referencia al archivo EXCEL, en el post indico cómo deben incluirse los parámetros:

      BBDD es el nombre de la hoja, Nombre completo es el nombre del campo. Revisa el ejemplo del post, verás como en el segundo archivo (el Excel estos son los campos usados.

      Intenta reproducir mi ejemplo, paso por paso comprendiendo cómo funciona el código. En resumen, el SQL hace referencia al Excel no al Word.

      Saludos.

      Me gusta

  2. Excelente solución! esto debería estar incorporado en Word! sólo para reforzar el tutorial… en la línea

    “SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]”

    BBDD es el nombre de la Hoja de Excel, no el archivo Excel! cuando uno crea un archivo excel, por defecto se crea “Hoja1”
    NOMBRE COMPLETO: Es el nombre del campo! es decir, en los títulos de la tabla hay que elegir el que necesitas para generar en base a ese los nombres de los archivos.

    Recordar también que la primera ventana que aparece es para elegir el archivo y la segunda es para elegir la carpeta.

    Yo copié y pegue y modifique. Simple.

    Felicitaciones!

    Me gusta

  3. La función está excelente, sin embargo, es posible realizar también el copiado del encabezado? y que pasaría si esto tiene una imagen.

    Me gusta

    • Hola Francisco,

      Lo de la imagen no tiene ningún tipo de problema porque hacer antes el combinar correspondencia bajo el modelo que estimes oportuno, incluida la imagen.

      Lo de copiar los encabezados, francamente no veo la necesidad, en el combinar correspondencia no se admite, y aunque con ADO se puede copiar el encabezado, a la hora de trozear el archivo solo utilizas el campo que te interesa para distinguir los archivos, normalmente un nombre o un ID.

      Saludos.

      Me gusta

  4. Me ha sido de mucha ayuda. Te agradecería que me ayudaras por que no obstante me genera un error: campo = Replace (dataread.Fields (0), “-“, ” “)
    y cuando la ejecuto se abre una única hoja de word con una fila con todos los nombres de USUARIO, que es el nombre del que he elegido para el SQL.
    Por qué no genera todos los documentos?, por qué me da ese error si he copiado tu macro tal y como la tienes?.
    Muchas gracias por tu respuesta… urgente si puede ser. Te lo agradezco muchísimo. Amaia

    Me gusta

  5. Hola de nuevo!. Ahora me da un nuevo error:
    Iniciamos conexión ADO para pasar una tabla con los items
    del campo seleccionado
    LockType = adLockReadOnly
    Open
    Me pone error en el nombre, y me subraya fosforito este último Open
    Te agradezco mucho tu ayuda.
    Un saludo

    Me gusta

  6. ‘Iniciamos conexión ADO para pasar una tabla con los items
    ‘del campo seleccionado
    Set cnn = New ADODB.Connection
    With cnn
    .Provider = “Microsoft.ACE.OLEDB.12.0”
    .Connectionstring = “DATA SOURCE=” & miExcel
    .Properties(“Extended Properties”) = “Excel 8.0”
    .Open
    End With
    Set dataread = New ADODB.Recordset
    With dataread
    .Source = obSQL
    .ActiveConnection = cnn
    .CursorLocation = adUseClient
    .CursorType = adOpenForwardOnly
    .LockType = adLockReadOnly
    .Open

    Estos son los datos que me da error. Los he copiado exactamente para facilitar la ayuda.
    Gracias de nuevo.

    Me gusta

    • Hola Amaia:

      Ese error aparece cuando el nombre del archivo Excel o de la pestaña de Excel no es correcto:

      obSQL = “SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]”

      En el ejemplo que he subido, la pestaña o hoja Excel con los datos se llama BBDD$ siempre tienes que poner un dolar al final para indicar que se trata de una hoja. Y el campo o nombre de columna con el dato a asociar es NOMBRE COMPLETO.

      Esto debe ser exactamente como lo tengas en tu archivo excel.

      En cuanto al otro error:

      campo = Replace(dataread.Fields(0), “-“, ” “) omite el replace directamente:

      campo = dataread.Fields(0)

      Saludos.

      Me gusta

  7. Hola,
    Me gustaría pedir ayuda para saber como puedo combinar un documento de word con origen de datos en excel, donde en una misma línea del asunto tengo que combinar varios registros diferentes (filas) que corresponden a un mismo usuario, sin que me salgan tantos documentos como filas de registro son.
    Es decir, si tengo 3 filas con números de expedientes diferentes (B1, B2 y B3), donde A1, A2 y A3 es el mismo usuario , y quiero mandar una única carta cuyo asunto sea:
    Asunto: Expedientes {B1}, {B2}, {B3}
    Se puede hacer esto?, cómo puedo hacerlo?

    Luego también aplicaré la macro para que se guarden como documentos independientes….

    Muchísimas gracias por la ayuda!!!
    Amaia

    Me gusta

    • Hola Amaia:

      Lo que indicas no se puede hacer con combinar correspondencia, para ello sería necesario previamente pasar esos 3 registros a una única linea de datos para que la pueda leer word y combinar un documento por cliente.

      Sería necesarios analizar el archivo y verificar si es posible hacer un programa que agrupe los datos.

      Saludos

      Me gusta

  8. Hola Segu, una pregunta, lo tengo todo montado pero al ejecutar me da error. “Se ha producido error 54941 en tiempo de ejecucion: El elemento del conjunto solicitado no existe” Le doy a depurar y me lleva a la linea Set texto = fdocument.Sections(i).Range ¿A qué se debe?

    Gracias

    Me gusta

    • Hola Raul:

      Es complicado poder contestarte sin ver el archivo. Pero ese error surge cuando un objeto no existe, en tu caso parece que fdocument no lo encuentra.

      No sé que versión de Excel usas, en este caso estoy con 2019, pero debería funcionar igualmente desde por lo menos 2010. Si descargas mi ejemplo te funciona??, te dá el mismo error??, si funciona es que en algún momento al crear tu proceso con tus datos, hay algún elemento que has modificado o variado.

      Si mi ejemplo no funciona, prueba en otro office para verificar que no es un problema de la versión.

      Espero haberte ayudado,.

      Saludos.

      Me gusta

  9. Hola!

    Muchas gracias, el ejemplo me ha servido enormemente en un trabajo que vengo realizado.

    Tengo una pregunta, ¿es posible obtener el scrip para que los archivos los genere en formato pdf?

    Gracias nuevamente!

    Me gusta

    • Hola Jhon:

      Es posible, si añades lo siguiente en el código, obtendrás tanto los word como los PDF, uno de cada.

      'Nombramos cada documento con el nombre
      'de la hoja que contiene los datos extraidos de Excel
      target_a.ExportAsFixedFormat ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
      wdExportOptimizeForPrint, Range:=wdExportAllDocument, OutputFileName:=mi_archivo
      target_a.SaveAs FileName:=mi_archivo
      'Cerramos cada documento
      target_a.Close

      Le gusta a 1 persona

      • Hola.
        Lo primero: mil gracias por la macro y el código para PDF. En este último caso, cuando ejecuto la madro, me dice que el archivo está siendo usado y cuando voy a Depurar, me indica que el error está justo en el código de PDF.
        Lo que he hecho es sustituir (no añadir) ambas partes, la de nombrar documento y cerrar cada documento, por el código que has indicado.

        ¿Cual puede ser el error?
        Gracias

        Me gusta

        • Hola Manyez:

          Este mismo código con el ejemplo que he publicado funciona perfectamente. Intenta descargar el ejemplo del post y ejecutarlo en tu equipo, si funciona es posible que el problema con tu información sean los datos.

          Para poder ayudarte necesito ver un ejemplo de la información del Excel que estás usando.

          Saludos.

          Me gusta

          • Holla!
            Lo primero: gracias por todo. Estoy usando Excel 2013. El código original funciona sin problema, pero cuando cambio para usar la opción PDF es cuando surge el problema.
            Gracias de nuevo

            Me gusta

              • Hola Manyez:

                He probado el código en 2013 y funciona perfectamente:

                La opción de PDF se tiene que ejecutar con la de word, es decir generas dos archivos uno en word y otro en PDF

                Te dejo la macro completa:

                Option Explicit
                Sub COMBINAR()
                'DECLARAMOS VARIABLES
                Dim mArchivo As Variant, fdocument As Document
                Dim miExcel As String, target As Variant, obSQL As String
                Dim cnn As Object, dataread As Object, filas As Long
                Dim i As Long, iname As Variant, midoc As Document
                Dim mi_archivo As String, campo As String, miCarpeta As Variant
                Dim texto As Variant, target_a As Variant
                'Capturamos documento actual
                Set fdocument = ThisDocument
                'Abrimos ventana de diálogo para seleccionar el archivo Excel
                'que hemos combinado
                Set mArchivo = Application.FileDialog(msoFileDialogOpen)
                If mArchivo.Show = 0 Then Exit Sub
                miExcel = mArchivo.SelectedItems(1)
                'Abrimos ventana de diálogo para seleccionar la carpeta en la que
                'guardaremos todos los archivos independientes
                Set miCarpeta = Application.FileDialog(msoFileDialogFolderPicker)
                If miCarpeta.Show = 0 Then Exit Sub
                miCarpeta = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1) & "\"
                'Generamos documento nuevo
                Set target = Documents.Add
                'Con instrucción SQL seleccionamos el nombre de la hoja
                'y el campo con el que queremos identificar cada documento de word
                obSQL = "SELECT [BBDD$].[NOMBRE COMPLETO] FROM [BBDD$]"
                'Iniciamos conexión ADO para pasar una tabla con los items
                'del campo seleccionado
                Set cnn = New ADODB.Connection
                With cnn
                .Provider = "Microsoft.ACE.OLEDB.12.0"
                .Connectionstring = "DATA SOURCE=" & miExcel
                .Properties("Extended Properties") = "Excel 8.0"
                .Open
                End With
                Set dataread = New ADODB.Recordset
                With dataread
                .Source = obSQL
                .ActiveConnection = cnn
                .CursorLocation = adUseClient
                .CursorType = adOpenForwardOnly
                .LockType = adLockReadOnly
                .Open
                End With
                'Grabamos los datos en el documento Word generado (target)
                dataread.MoveFirst
                filas = dataread.RecordCount
                Selection.InsertAfter dataread.Fields(0)
                Do Until dataread.EOF
                dataread.MoveNext
                If dataread.EOF = "Verdadero" Then Exit Do
                campo = Replace(dataread.Fields(0), "-", " ")
                Selection.InsertAfter Chr(11) & campo
                Loop
                'Formateamos los datos grabados como una tabla
                Selection.ConvertToTable Separator:=wdSeparateByDefaultListSeparator, _
                numcolumns:=1, Numrows:=filas, AutoFitBehavior:=wdAutoFitFixed
                Set midoc = ActiveDocument
                'Recorremos la tabla
                For i = 1 To midoc.Tables(1).Rows.Count
                Set iname = midoc.Tables(1).Cell(i, 1).Range
                'Eliminamos de cada dato el retorno de carro, Chr(13).
                'Eliminamos el último caracter de la cadena de texto
                mi_archivo = Mid(Replace(miCarpeta & iname.Text, Chr(13), ""), 1, Len(Replace(miCarpeta & iname.Text, Chr(13), "")) - 1)
                'Recorremos todas las hojas del documento word actual
                'Creamos un nuevo documento y pasamos el contenido de cada combinación.
                Set texto = fdocument.Sections(i).Range
                texto.End = texto.End - 1
                Set target_a = Documents.Add
                target_a.Range.FormattedText = texto
                'Nombramos cada documento con el nombre
                target_a.ExportAsFixedFormat ExportFormat:=wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
                wdExportOptimizeForPrint, Range:=wdExportAllDocument, OutputFileName:=mi_archivo
                target_a.SaveAs FileName:=mi_archivo
                'Cerramos cada documento
                target_a.Close
                Next i
                'cerramos el documento con los datos de Excel
                ActiveDocument.Close SaveChanges:=False
                End Sub

                Me gusta

  10. hola
    muchissimas gracias para esa macro. He seguido tus instruciones solo que a mi me genera el error 94 uso no válido de null. Me podrias ayudar?

    Me gusta

    • Hola Carmen:

      Te contesto lo mismo que al lector anterior, necesitaría ver un ejemplo de los datos del Excel con que quieres combinar correspondencia para verificar si el problema está en los datos.

      SAludos.

      Me gusta

      • He podido solucionarlo
        ahora tengo un problema de formato. La macro funciona perfectamente pero al guardar los archivos me cambia el formato del documento word y la letra queda muy mal. Hay posibilidad de cambiar algo en la macro para ampliar el formato? O en que linea has programado el formato?
        Saludos

        Me gusta

        • Hola Carmen:

          El formato lo tienes que aplicar al hacer por primera vez el combinar correspondencia. La La macro lo que hace es trocear el archivo generado y guardarlo como word o pdf.

          SAludos.

          Me gusta

          • Pero que formato le aplico? porque tengo mi generica de la carta utilizo para combinar. Hasta ahi todo bien pero al aplicar la macro todo el formato cambia.

            Me gusta

            • Hola Carmen:

              Tal como te comentaba, el problema es el formato de la carta de inicio, margenes, saltos de sección, etc.

              Para poder configurar la macro para esa forma es necesario reprogramar toda la macro, no obstante lo estudiaré para futuras publicaciones.

              Me gusta

  11. Muy buenas y gracias por la ayuda que nos prestas,

    Tengo el mismo problema que AMAIA JAKIN, cuando ejecuto la macro se genera un único Word con una columna con el listado de nombres que he asignado y el error que me sale es “error “94” en tiempo de ejecución” Uso no válido Null. Al depurar me indica la línea:

    campo = Replace(dataread.Fields(0), “-“, ” “)

    esta línea la he sustituido por:

    campo = dataread.Fields(0)

    ejecuto y me sigue generando el mismo error.

    Agradecería me ayudases con el problema, un saludo.

    Me gusta

Responder a Segu Cancelar respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.