Macro VBA para Word

He hecho una macro en word para sustituir un texto por otro en un documento en el que puede variar su tamaño y veces en las que hay que hacer la sustitución.
No he tenido problemas en meterlo en un bucle (Do-loop) para que lo haga solo pero sí cuando intento decirle que se detenga al finalizar el documento ya que, si no, empieza de nuevo indefinidamente.
Mi pregunta es: ¿Existe alguna propiedad de documento o forma de decirle que ha llegado al final del documento y que se salga del bucle?

2 Respuestas

Respuesta
1
La propiedad EOF (End Of File) puede solucionarte este problema. Por ejemplo:
Do Until EOF(1)
Además quiero aclararte que esta propiedad está disponible en casi todos los lenguajes conocidos, por lo que te será muy útil en el futuro.
Muchas gracias por responder.
Estoy intentando utilizar el EOF de varias formas pero me da un error de depuración (52), seguramente porque no se exactamente. He probado con:
    Do While EOF(1)
        (condiciones)
    Loop
 o
    While Not EOF(1)
       (Condiciones)
    Wend
Haciéndolo de las 2 formas me da el mismo error. No sé si es que hay que hacer algo previamente o es que simplemente no lo estoy haciendo bien.
Utilizo el VBA de Word 2003 (6.3).
Muchas gracias.
La verdad es que desconozco los comando de VBA, y no puedo probar ninguno porque no tengo instalado el Office, pero me encontré un código por ahí que podría servirte de ayuda:
Open "Datafile.txt" For Input As #1
Do While Not EOF(1)
   Input #1, sFirst, sLast, sAddress, sCity, sState, sZip
   Debug. Print sFirst, sLast, sAddress, sCity, sState, sZip
Loop
Close #1
Espero que te sirva. Si no te funciona buscaré algo más de ese error que te da.
No me sirve. La parte del bucle y eso es como ya he probado y me da el error de depuración. No sé por donde seguir probando.
Pásame tu código y mientras voy instalando el Office, a ver si veo algo. Si no quieres que la gente lo vea puedes enviármelo por email a [email protected]
También dime si debo tener algo en consideración cuando ejecute tu código (por si es algo casero, ya sabes).
Este es el código que estoy usando. Ya ves que es sencillísmo, la única pega es lo del bucle, que se salga al terminar el documento:
Do
    Selection.HomeKey Unit:=wdLine
    Selection.Find.ClearFormatting
    With Selection.Find
        .Text = "texto1"
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindAsk
        .Format = False
        .MatchCase = False
         .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute
    Selection.TypeText Text:="texto2"
    Selection.MoveRight Unit:=wdCharacter, Count:=1
Loop While Not EOF(1)
End Sub
Gracias por tu interés
OK. Tu problema es que no abres el archivo. Debes poner un línea como la siguiente al principio:
Open "archivo" for input as #1
Es algo así como decir: abre el archivo tal para introducirle texto y que sea el archivo nº 1
Es que, en tu código, si no abres el archivo no puedes saber si es el final del fichero.
También te recomiendo que uses la estructura TRY / CATCH. Para trabajar con ficheros siempre es recomendable, para que así no falle la aplicación en caso de encontrar un error de lectura.
Si me explicas un poco más lo que quieres hacer quizás pueda ayudarte en algo más, ya que hasta ahora no me has explicado nada. ¿Qué es realmente lo que quieres hacer? Quizás así aprendamos el uno del otro, porque hasta ahora nunca había usado estas funciones del Office.
Es más, no hace falta que me lo expliques, tan solo comenta el código.
Verás, lo que quiero es tan sencillo que me da vergüenza preguntar pero tengo interés en hacerlo de esta manera para poder usarlo en un futuro cercano.
En este caso concreto, simplemente necesito cambiar un texto que aparezca en un documento por otro. Es decir, cambiar "texto1" por "texto2". Esto no tiene ningún problema, el tema es que me lo haga en todo el documento y solo una vez, si no lo ejecuto otra vez, claro.
Siguiendo tus indicaciones he utilizado este código:
Sub Prueba()
Open "c:\prueba.doc" For Input As #1
    Do
    Selection.HomeKey Unit:=wdLine
    Selection.Find.ClearFormatting
    With Selection.Find
        .Text = "prueba"
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindAsk
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute
    Selection.TypeText Text:="texto2"
    Selection.MoveRight Unit:=wdCharacter, Count:=1
Loop While Not EOF(1)
Close #1
End Sub
Gracias al "open" que me dijiste ya no da un error al utilizarlo pero no lo hace bien (porque no sé hacerlo supongo) ya que hace la sustitución correctamente en todo el documento pero, al llegar al final no se detiene, sale un mensaje diciendo que ha llegado al final del documento y que si quiero continuar la búsqueda desde el principio.
Le diga lo que le diga entra en un bucle infinito en el que siempre está ese mensaje en pantalla y del que solo se puede se salir cerrando el proceso del Word.
Si embargo, si le quito el Not a la fila "Loop While Not EOF(1)", me hace el proceso del Loop (o sea, la sustitución) una sola vez.
La verdad es que estoy bastante perdido. Muchas gracias por tu interés.
Déjame investigar un poco más, porque supongo (ya te dije que nunca había tocado este tema) que habrá una forma de hacer que se marque la casilla de "Reemplazar Todo" y ejecutar ese módulo del programa.
Además, estoy indagando sobre el tema y puede que el EOF no te sirva, ya que eso es para recorrer un archivo, pero no para seleccionar un texto. De hecho, la propiedad Wrap hace que te pregunte, por lo que también se podría averiguar dónde se guarda esa respuesta y así saber si se ha llegado al final y si el usuario ha respondido que sí o no.
Por otra parte, que no te dé vergüenza decir para qué sirve tu código, porque todos hemos empezado haciendo programas que no sirven de mucho, pero a nosotros nos hace pensar y averiguar cómo se hacen las cosas.
Vale, parece ser que he dado con la tecla antes de tiempo. Prueba este código:
Dim ejectuado As Boolean
Selection.Find.ClearFormatting  'Formatea la entrada de los datos
With Selection.Find   'Declara todas las posibilidades de la ventana BUSCAR
.Text = "Texto1"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindAsk
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Replacement.ClearFormatting   'Limpia el cuadro de "Reemplazar por:"
Selection.Find.Replacement.Text = "Texto2"   'Escribe en el cuadro anterior
'La siguiente línea ejecuta el cuadro Reemplazar con la opción REEMPLAZAR TODO marcada
ejecutado = Selection.Find.Execute(Selection.Find.Text, Selection.Find.MatchCase, Selection.Find.MatchWholeWord, Selection.Find.MatchWildcards, Selection.Find.MatchSoundsLike, Selection.Find.MatchAllWordForms, Selection.Find.Forward, Selection.Find.Wrap, Selection.Find.Format, Selection.Find.Replacement.Text, Word.wdReplaceAll)
La variable ENCONTRADO no sirve para nada, sólo que me decía que el Execute debía de devolver algo, y se lo asigné a una variable de ese tipo. Cosas del Basic.
Prúebalo y dime si te lo hace bien o no, porque por lo que yo he probado sí.
Respuesta
1
Buf!, en el tema de macros me pillas un poco, pero te digo lo que se me ocurren que te pueden ayudar, es que no se como tienes hecho el while:
    - "ThisDocument.Content.Words.Count", te devuelve el numero de palabras.
    - "ThisDocument.Content.Paragraphs.Count", te devuelve el numero de parrafos.
    - "ThisDocument.Content.Paragraphs(index).Range", te devuelve parrafo seleccionado.
    - "ThisDocument.Content.Characters.Count", te devuelve el numero de caracteres.
    - "Len(cadena)", te devuelve el numero de caracteres de esa cadena.
    - "Replace(ThisDocument.Content.Text, "palabra_que_busca", "palabra_nueva"[, Caracter_inicio, numero_de_caracteres])", cambia la palabra buscada. Opcionalmente puedes poner el rango al final, donde metes la posición del carácter inicial y el numero de caracteres que que deseas seleccionar.
Me cuentas si te vale o no. Aun así voy a ver si veo en concreto lo que me dices.
Me temo que no me sirve.
A grandes rasgos se trata de poder salirse de un bucle cuando haya revisado el documento entero pero no sé como hacer para que vea que ha llegado al final.
Me han hablado de la propiedad EOF (End Of File) pero no he sabido usarla. ¿Te suena si podría hacerlo con ésto?
¿Cómo recorres el documento? , como usas el while para ir recorriendo el documento?.
He probado utilizando el Do- Loop mó menos así:
Do
Selection.HomeKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
    .Text = "texto1"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindAsk
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
End With
Selection.Find.Execute
Selection.TypeText Text:="texto2"
Selection.MoveRight Unit:=wdCharacter, Count:=1
Loop While Not EOF(1)
End Sub
En esta macro a sustitución funciona bien pero la condición del bucle (lo que está en negrita) probablemente no se haga así pero no veo como hacerlo o si es que simplemente no le he sabido decir como hacerlo.
¿Puedes ayudarme? Gracias
Sin modificarte mucho tu proceso, mi solución es:
Dim vDonde As Long
Dim Salida As Byte
Salida = 1

Do
Selection.HomeKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
    .Text = "texto1"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindAsk
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
End With
vDonde = InStr(ThisDocument.Content.Text, "texto1")
If vDonde 0 Then
    Selection.Find.Execute
    Selection.TypeText Text:="texto2"
    Selection.MoveRight Unit:=wdCharacter, Count:=1
Else
    Salida = 0
End If

Loop While Salida = 1
Prueba
¿Al final que tal te fue?
Perdona la tardanza.
He probado con tu código pero me pasa lo mismo que me pasa con el mio al utilizar el EOF.
Te adjunto el último código que estoy usando:
Sub Prueba()
Open "c:\prueba.doc" For Input As #1
    Do
    Selection.HomeKey Unit:=wdLine
    Selection.Find.ClearFormatting
    With Selection.Find
        .Text = "prueba"
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindAsk
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute
    Selection.TypeText Text:="texto2"
    Selection.MoveRight Unit:=wdCharacter, Count:=1
Loop While Not EOF(1)
Close #1
End Sub
El problema que me da es exacto al que me me da con tu código. Hace la sustitución correctamente en todo el documento pero, al llegar al final no se detiene, sale un mensaje diciendo que ha llegado al final del documento y que si quiero continuar la búsqueda desde el principio.
Le diga lo que le diga entra en un bucle infinito en el que siempre está ese mensaje en pantalla y del que solo se puede se salir cerrando el proceso del Word.
Si embargo, si le quito el Not a la fila "Loop While Not EOF(1)", me hace el proceso del Loop (o sea, la sustitución) una sola vez.
La verdad es que estoy bastante perdido. Muchas gracias por tu interés.
¿En qué momento lanzas la macro?, ¿En algún evento(al abrir, al guardar, ...)?
La tengo puesta para usar un botón en una barra de herramientas.
La tienes el objetivo del botón, ¿es qué te lo modifique en todo el documento cada vez que de al botón?
Eso es, que cambie todo el documento al darle al botón.
Según mi forma, no miré en la tuya, pon justo antes del bucle do "ThisDocument.Content.Select". Mira a ver y me dices.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas