** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Access y VBA > Access y VBA
  Mensajes nuevos Mensajes nuevos RSS - Reemplazar datos para plantilla
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Tema cerradoReemplazar datos para plantilla

 Responder Responder
Autor
Mensaje
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Tema: Reemplazar datos para plantilla
    Enviado: 01/Junio/2023 a las 00:22
Muy buenas noches.

Tengo una duda desde hace bastante tiempo que no sé cómo resolver. Espero explicarme más o menos bien. Veamos...

En una base de datos de mi trabajo (curro para la Administración) que yo suelo hacerme para facilitar la tarea, tengo un código dentro de un formulario que realiza la acción de abrir un documento World (plantilla) y coger campos de ese formulario y rellenarlo en la plantilla. Tira de una tabla donde se identifican las campos del formulario y hace las sustituciones. Esta tabla tiene dos campos:


CodeToReplace ({Cambia1}, es lo que ponemos en la plantilla)

ReplaceWithFieldName (Forms!Formulario!campo_txt, es el valor en el formulario


El código es un poco largo pero lo transcribo:


Private Sub Comando306_Click()
Dim dbLocal As Database
   Dim snpReplaceCodes As Recordset
   Dim strCurrAppDir As String
   Dim strFinalDoc As String
   Dim varReplaceWith As Variant
   Dim docWord As Word.Document
   
   On Error GoTo Error_cmdCreateLetter_Click
   Set dbLocal = CurrentDb()
   strCurrAppDir = Left$(dbLocal.Name, InStrRev(dbLocal.Name, "\"))
         
   strFinalDoc = strCurrAppDir & "documento1.dot"
     
   On Error GoTo Error_cmdCreateLetter_Click
   Set appWord = New Word.Application
   Set docWord = appWord.Documents.Add(strFinalDoc)
   appWord.Visible = True
   'abro ahora la tabla de las sustituciones
   Set snpReplaceCodes = dbLocal.OpenRecordset("ReemplazaCodigos", _
         dbOpenSnapshot)
   
   Do While Not snpReplaceCodes.EOF
      
      
      varReplaceWith = Eval(snpReplaceCodes!ReplaceWithFieldName)
      varReplaceWith = IIf(IsNull(varReplaceWith), " ", CStr(varReplaceWith))
            
      With docWord.Content.Find
         
         If snpReplaceCodes!CodeToReplace = "{MOVIETITLE}" Then
            With .Replacement
               .ClearFormatting
               .Font.Bold = True
               .Font.Italic = True
            End With
         End If
         
         .Execute FindText:=snpReplaceCodes!CodeToReplace, _
               ReplaceWith:=varReplaceWith, Format:=True, _
               Replace:=wdReplaceAll
       
       End With
              
       snpReplaceCodes.MoveNext
   
   Loop
   
   snpReplaceCodes.Close
   Exit Sub
   
Error_cmdCreateLetter_Click:

   Beep
   ' MsgBox "Ha ocurrido el error:" & vbCrLf & _
   ' Err.Description, vbCritical, "OLE Error!"
   Exit Sub
      
End Sub


La plantilla, (documento1.dot) debe estar en la ruta de la base de datos (o se puede cambiar indicándoselo). Hace una llamada a la tabla (ReemplazaCodigos) para hacer las sustituciones y, poco más.

Pues bien, ocurre lo siguiente. Abre la plantilla y hace sustituciones hasta que se encuentra un campo en el formulario sin datos y, a partir de ahí, no hace más sustituciones y deja los campos en la plantilla sin cambiar. No tengo ni idea de dónde dice eso en el código o porqué lo hace.

La solución más "estúpida" por mi parte, es rellenar los campos del formulario con un guión, espacio, punto o "algo", pero no es lo suyo.

Aparte de todo esto (me estoy extendiendo demasiado), el código lo adapté con ayuda de un foro de OpenOfficce, para abrir un documento de LibreOfficce Writer en vez de World (cosas de la Administración) y funcionaba igual de bien abriendo la plantilla de Writer pero haciendo lo mismo: Se paraban las sustituciones al encontrar un campo vacío en el formulario. Pongo también el código:


Public Sub Comando413_Click()
Dim dbLocal As Database
   Dim snpReplaceCodes As Recordset
   Dim strCurrAppDir As String
   Dim strFinalDoc As String
   Dim varReplaceWith As Variant
  '++++++++++++++
  Dim mibusqueda As Object
  Dim oservicio As Object
  Dim Escritorio As Object
  Dim document As Object
 
  '++++++++++++++++
   On Error GoTo Error_Comando413_Click
   Set dbLocal = CurrentDb()
   strCurrAppDir = Left$(dbLocal.Name, InStrRev(dbLocal.Name, "\"))
              
   strFinalDoc = strCurrAppDir & "Plantillas/documento1.ott"
   On Error GoTo Error_Comando413_Click
   strFinalDoc = Replace(strFinalDoc, "\", "/")
   strFinalDoc = "file:///" + strFinalDoc
      
   Dim args(1) As Object
    Set oservicio = CreateObject("com.sun.star.ServiceManager")
    Set Escritorio = oservicio.createInstance("com.sun.star.frame.Desktop")
    Set args(0) = oservicio.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
    args(0).Name = "Hidden"
    args(0).Value = True
    Set document = Escritorio.loadComponentFromURL(strFinalDoc, "_blank", 0, args())
    Call document.getCurrentController.getFrame.getContainerWindow.setVisible(True)
    Call document.getCurrentController.getFrame.getComponentWindow.setVisible(True)
    Set mibusqueda = document.createReplaceDescriptor



'abro ahora la tabla de las sustituciones
   Set snpReplaceCodes = dbLocal.OpenRecordset("ReemplazaPropuesta", _
         dbOpenSnapshot)

   Do While Not snpReplaceCodes.EOF


      varReplaceWith = Eval(snpReplaceCodes!ReplaceWithFieldName)
      varReplaceWith = IIf(IsNull(varReplaceWith), " ", CStr(varReplaceWith))

    mibusqueda.setsearchstring (snpReplaceCodes!CodeToReplace)
    mibusqueda.setreplacestring (varReplaceWith)
    Call document.replaceall(mibusqueda)


       snpReplaceCodes.MoveNext

   Loop
'
  snpReplaceCodes.Close
   Exit Sub
   
Error_Comando413_Click:

   Beep
   ' MsgBox "Ha ocurrido el error:" & vbCrLf & _
   ' Err.Description, vbCritical, "OLE Error!"
   Exit Sub
End Sub



Bueno, ustedes sois los "máquinas", por si veis algo… y lo queréis comentar

Muchas gracias de antemano.



Arriba
happy Ver desplegable
Moderador
Moderador


Unido: 29/Enero/2005
Localización: España
Estado: Sin conexión
Puntos: 3192
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 09:27
Lo que yo te sugiero es que compruebes el valor que va tomando la variable varReplaceWith, pues parece que esta es la variable que utilizas para colocar los valores de sustitución. Por lo que comentas a partir de que la rutina encuentra algún valor vacío o nulo es cuando empieza a hacer el tonto. Por eso te sugiero que pongas un punto de interrupción en alguna línea y a partir de ahí vayas ejecutando el código paso a paso pulsando F8. Comprueba qué valor va tomando cada vez la variable y mira qué efecto tiene en el documento final (mientras haces pruebas hazlo visible si no lo está, y así podrás ver qué ocurre con cada instrucción)

Espero que te sirva
Saludos,

Juan M. Afan de Ribera
Arriba
prga Ver desplegable
Moderador
Moderador


Unido: 16/Noviembre/2004
Localización: España
Estado: Sin conexión
Puntos: 3523
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 13:10
Hola
Salvo mejor opinión, no hay que confundir un "nulo" con una cadena vacía -space(0)-
La función isnull en
varReplaceWith = IIf(IsNull(varReplaceWith), " ", CStr(varReplaceWith))
detecta nulos, pero no cadenas vacías y cabe la posibilidad de que el writer no admita ese tipo de cadena vacía.
Espero que ayude a resolver la duda.
Ya comentas.
Un saludo a todos

Arriba
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 15:52
Buenas.
Me pongo a mirar y hacer pruebas con lo comentado pero ya adelanto (Sr. prga), que el "efecto" es el mismo tanto si abres la plantilla en Writer como en World
Arriba
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 19:30
Buenas. No entiendo mucho ésto... Y además no creo que sea "tan simple".
La primera prueba que he realizado es comentar la línea:

'varReplaceWith = IIf(IsNull(varReplaceWith), "", CStr(varReplaceWith))

pensando que era la que gestionaba los campos sin datos. Pues bien. Ahora no se para y sigue calculando los campos.
Se supone que se ha solucionado?
A tal extremo no me atrevo yo a decir... pero Vds. dirán.

He hecho un miniejemplo para que se observe lo ocurrido. Con el libro calc no lo he probado. Si el foro me puede indicar algún link dónde ponerlo lo subo.
Salu2


Editado por maserrano - 01/Junio/2023 a las 19:31
Arriba
happy Ver desplegable
Moderador
Moderador


Unido: 29/Enero/2005
Localización: España
Estado: Sin conexión
Puntos: 3192
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 20:22
Yo sigo pensando que lo mejor es poner un punto de interrupción y luego ejecutar paso a paso con F8 para ver qué valor toma la variable varReplaceWith.

Al menos yo, cuando me pasan cosas que no comprendo no dejo las cosas al azar, aunque parezca que se arreglan. Lo mejor es averiguar qué pasa y por qué. De esa manera controlas el tema y aprendes cosas que para futuro siempre viene bien saber.

De paso, si averiguas algo interesante y lo quieres compartir, pues aprendemos el resto de los mortales Smile. Pero en fin, dependerá del tiempo que quieras o puedas dedicarle ...

Sí te puedo decir que la línea que has comentado, aunque como dice Prga, no tiene en cuenta los valores Empty (por defecto las variables Variant toman ese valor, no un Null), sí que sería la que se encargaría de los nulos. En mi opinión puedes hacerlo de esta otra manera y así abarcas tanto Null como Empty:

varReplaceWith = Iif(Len(Nz(varReplaceWith,"")) = 0, "", Cstr(varReplaceWith))
Saludos,

Juan M. Afan de Ribera
Arriba
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Enviado: 01/Junio/2023 a las 21:18
No, no sí que lo haré Sr. happy. Lo que ocurre es que me ha sorprendido tanto el efecto de "quitar" esa línea que lo he comentado con vds.
Arriba
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Enviado: 02/Junio/2023 a las 00:19
Buenaas. Aprovecho ahora que tengo un ratito (niños acostados).
He puesto un punto de interrupción y hago los pasos uno a uno (F8).
En el caso de que todos los campos (3) están rellenos y con el código completo (sin nada comentado):
Abre el documento Writer en:
Call document.getCurrentController.getFrame.getComponentWindow.setVisible(True)
Luego procesa un bucle entre:
Do While Not snpReplaceCodes.EOF
y
Loop
Hace una sustitución en cada bucle en la línea:
snpReplaceCodes.MoveNext
Cuando hace la última, se va a
Exit Sub
Veamos ahora cuando falta el 2º campo de 3:
Todo igual hasta hacer la primera sustitución; llega a Loop y vuelve a:
Do While Not snpReplaceCodes.EOF
y cuando llega a la línea:
varReplaceWith = IIf(IsNull(varReplaceWith), "", CStr(varReplaceWith))
automáticamente se va a Beep y acaba

..., está claro que es esa línea (la que dejé comentada) la que casca.
Si realizo el ejemplo con la línea comentada el Loop sigue y no se detiene en el Beep de error. y sigue rellenando campos.
Bueno, hasta aquí llego. La parte "dura" de todo ésto ya se me escapa ...
Por cierto, el ejemplito está en este enlace:


(La línea no está comentada. Para hacer pruebas hay que comentarla)
Buenas noches y salu2




Editado por maserrano - 02/Junio/2023 a las 00:21
Arriba
happy Ver desplegable
Moderador
Moderador


Unido: 29/Enero/2005
Localización: España
Estado: Sin conexión
Puntos: 3192
Enlace directo a este mensaje Enviado: 02/Junio/2023 a las 08:57
Y qué mensaje de error se produce? (porque dices que se va a Beep y termina, pero en medio tienes un msgbox que indica el error que se ha producido). También deberíais averiguar qué valor (si es que lleva alguno) contiene la variable varReplaceWith en ese momento del error. Quién sabe, ¿podría contener hasta algún error del tipo #Err, o cosas así? varReplaceWith es una variable Variant, o sea que puede contener casi cualquier cosa y además viene del resultado del Eval() de la línea anterior. 

Es posible que todo venga por ahí: de la fórmula que tienes definida en la tabla o consulta ReemplazaPropuesta, que en caso de un elemento vacío, casca y vete a saber qué cosa devuelve Eval() en un caso como ese ... Si es eso, entonces, lo que debes hacer es rehacer la fórmula para que tenga en cuenta un valor vacío o Nulo

Son sugerencias ...


Editado por happy - 02/Junio/2023 a las 08:58
Saludos,

Juan M. Afan de Ribera
Arriba
prga Ver desplegable
Moderador
Moderador


Unido: 16/Noviembre/2004
Localización: España
Estado: Sin conexión
Puntos: 3523
Enlace directo a este mensaje Enviado: 02/Junio/2023 a las 13:32
Hola.
Haciendo alguna prueba, parece ser que el problema venía por lo apuntado por happy en la función eval, vamos cambiando  por:
      varReplaceWith = CStr(Nz(Eval(snpReplaceCodes!ReplaceWithFieldName), " "))
      varReplaceWith = IIf(IsEmpty(varReplaceWith), " ", varReplaceWith)

 al menos a mí me funciona.
Por otra parte, es buena práctica anular el "gestor" de errores en la función o procedimiento mientras de problemas, así el código se bloquea en la línea correspondiente al error ( que haga beep no nos sirve para nada) y nos sirve para buscar una solución
Ya comentas.
Un saludo a todos
Arriba
maserrano Ver desplegable
Colaborador
Colaborador


Unido: 02/Abril/2014
Localización: España
Estado: Sin conexión
Puntos: 690
Enlace directo a este mensaje Enviado: 02/Junio/2023 a las 19:17
Pues va genial. He realizado un puñado de pruebas y lo dicho, está genial. Muchas gracias por la aportación y si queréis se puede cerrar el hilo.
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable