Find PARTLY italic words and replace non-italics by italics and theother way around

N

Nomey

Dear all,

How can I find words in which the first characters (sometimes one, sometimes 2, 3, or more) are in italics but the remainder of the word is not?

And secondly, how can I reverse all ocurrences of these mixed-format words in ons document, so the italics become non-italics and the non-italics become italics in those words?

Any help is much appreciated,

Regards,
Shirley Nomey
 
N

Nomey

Just to clarify what I woule like to achieve:

I want to replace all instances of e.g. /sunny/boy (sunny being italicized, and boy not) by sunny/boy/ (boy being italicized), without changing the formatting of words that are entirely italicized of entirely not-italicized.

Nomey
 
J

JP

Hey Nomey,

Check out the Characters collection.

Returns a Characters collection that represents the characters in a
document, range, or selection.

Example:
This example displays the first character in the selection. If nothing
is selected, the character immediately after the insertion point is
displayed.

char = Selection.Characters(1).Text
MsgBox "The first character is... " & char

This example returns the number of characters in the first sentence in
the active document (spaces are included in the count).

numchars = ActiveDocument.Sentences(1).Characters.Count


For an example (in Excel) check out this page.

http://www.bettersolutions.com/excel/EVD243/VU822216331.htm


HTH,
JP
 
D

Doug Robbins - Word MVP

Here is the code created by using the Macro recorder while making that
substitution:

Selection.Find.ClearFormatting
Selection.Find.Font.Italic = True
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Bold = True
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
With Selection.Find.Font
.Bold = False
.Italic = False
End With
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Italic = True
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
With Selection.Find.Font
.Bold = True
.Italic = True
End With
Selection.Find.Replacement.ClearFormatting
With Selection.Find.Replacement.Font
.Bold = False
.Italic = False
End With
With Selection.Find
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll

If the words that are partly italic are scattered throughout the document
and you do not what anything to be done with the other words, then it is
going to be quite a bit more difficult to come up with code that only acts
upon the partly italic words.

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP
 
H

Helmut Weber

Hi Nomey,

you may start with this approach:

Sub Macro3()
Dim rWrd As Range
Dim rDcm As Range
Set rDcm = ActiveDocument.Range
For Each rWrd In rDcm.Words
If rWrd.Font.Italic = "9999999" Then
rWrd.Select ' for testing
Stop ' for testing
End If
Next
End Sub

range.font.italic returns "9999999" if
neither font.italic is true nor font.italic is false,
means there is at least one italic character in the range.

I'm not quite sure, in the case of "sunnyboy"
with "sunny" italizeded, what should happen next.
Remove italic formatting from sunny and apply it to "boy"?

Note that "word" is a concept of fuzzy
natural language and as such to a certain extend
not computable at all.

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
H

Helmut Weber

Hi everybody,

there was no other amusement,
so I looked into that a bit deeper

Sub Macro3a()
' wdUndefined = 999999999
Dim rDcm As Range
Dim rChr As Range
Set rDcm = ActiveDocument.Range
With rDcm.Find
.Font.Italic = True
While .Execute
With rDcm.Words(1)
If .Font.Italic = wdUndefined Then
For Each rChr In .Characters
rChr.Font.Italic = Not rChr.Font.Italic
Next
End If
End With
rDcm.start = rDcm.Words(1).End
rDcm.End = ActiveDocument.Range.End
Wend
End With
End Sub

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
N

Nomey

Hi Doug,
If the words that are partly italic are scattered throughout the document
and you do not what anything to be done with the other words, then it is
going to be quite a bit more difficult to come up with code that only acts
upon the partly italic words.

That is exactly what I need to figure out. Unfortunately. But thanks for your code example anyway. I'll keep it somewhere for future reference.

Thanks for your help,
Shirley
 
N

Nomey

Hi Helmut,

That's indeed what needs to be done next. I'm really amazed by the result of your code. It's so complex I can't understand how it works.

There's another variant I need - in case you're still looking for some challenging entertainment: how would the macro look if the word was always the same (sunnyboy, partly italicized)?

Best regards,
Shirley
 
N

Nomey

What I mean is that adding an Inputbox statement, doesn't work:

Sub StaDi_cursiefmacro1()
' wdUndefined = 999999999
Dim rDcm As Range
Dim rChr As Range
Set rDcm = ActiveDocument.Range
With rDcm.Find
.Font.Italic = TrueWhile .Execute
With rDcm.Words(1)
If .Font.Italic = wdUndefined Then
For Each rChr In .Characters
rChr.Font.Italic = Not rChr.Font.Italic
Next
End If
End With
rDcm.Start = rDcm.Words(1).End
rDcm.End = ActiveDocument.Range.End
Wend
End With
End Sub
 
H

Helmut Weber

Hi Shirley,

just process "sunnyboy"?

Then:

Sub Macro3ab()
Dim rDcm As Range
Dim rChr As Range
Set rDcm = ActiveDocument.Range
With rDcm.Find
.Text = "sunnyboy"
While .Execute
With rDcm
If .Font.Italic = wdUndefined Then
For Each rChr In .Characters
rChr.Font.Italic = Not rChr.Font.Italic
Next
End If
End With
rDcm.start = rDcm.End
rDcm.End = ActiveDocument.Range.End
Wend
End With
End Sub

There will be faster ways,
but that would include quite a lot of
still much more complex coding.

My code is kind of a brute force approach,
checking whether there is an italic character in
the found range, and, if so, changing each
character's italic-property
in the found range to the opposite.

If you know beforehand, that "sunnyboy"
is half italic and half not italic,
you could do it all without checking.

HTH

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
H

Helmut Weber

Hi Shirley,

like that:

Sub StaDi_cursiefmacro1()
' wdUndefined = 999999999
Dim rDcm As Range
Dim rChr As Range
Dim sWrd As String
start:
Set rDcm = ActiveDocument.Range
sWrd = InputBox("Enter the word you want to reverse.")
If sWrd = "stop" Then Exit Sub ' quick and dirty
' but if it helps its alright
With rDcm.Find
.Text = sWrd
While .Execute
With rDcm
If .Font.Italic = wdUndefined Then
For Each rChr In .Characters
rChr.Font.Italic = Not rChr.Font.Italic
Next
End If
End With
rDcm.start = rDcm.End
rDcm.End = ActiveDocument.Range.End
Wend
End With
GoTo start
End Sub

Note again: if this were to process
large documents and many occurences of the searched for word,
then the whole thing would need another approach.

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
N

Nomey

Hi Helmut,

I've already figured it out (changing italics in SPECIFIC words):

Sub Change_Italics_In_Specific_Words()
' wdUndefined = 999999999
Dim rChr As Range
Dim rDcm As Range
Set rDcm = ActiveDocument.Range

With rDcm.Find
.Text = InputBox("Enter your search string:")
.MatchWildcards = False
.MatchWholeWord = True
.MatchCase = False
While .Execute
With rDcm.Words(1)
If .Font.Italic = wdUndefined Then
For Each rChr In .Characters
rChr.Font.Italic = Not rChr.Font.Italic
Next
End If
End With
rDcm.Start = rDcm.Words(1).End
rDcm.End = ActiveDocument.Range.End
Wend
End With
End Sub

And you're right: it's great fun to cut and paste (im my case - not yours, of course) one's way through VBA.

Thanks again,
Shirley
 
N

Nomey

Hi Helmut,

And just to mark any instance of a search string that is partly in italics? This doesn't work. Can you explain why (I always want to know why things work or don't work - if possible):

Sub StaDi_halfcursief_markeren()
' wdUndefined = 999999999
Dim rDcm As Range
Dim rChr As Range
Set rDcm = ActiveDocument.Range
With rDcm.Find
.Text = InputBox("Enter your search string:")
.Font.Italic = True
While .Execute
With rDcm.Words(1)
If .Font.Italic = wdUndefined Then
For Each rChr In .CharactersNext
End If
End With
rDcm.Start = rDcm.Words(1).End
rDcm.End = ActiveDocument.Range.End
Wend
End With
End Sub
 
H

Helmut Weber

Hi Shirley,

the problem is here:
.Text = InputBox("Enter your search string:")
.Font.Italic = True

This searches for an instance of your word,
which is entirely italic!

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
N

Nomey

I see. Well, thanks again. It's really kind of you to help, but then, writing macros is great fun, especially on a rainiy day in november, isn't it?

Kind regards,
Shirley
 
F

fumei via OfficeKB.com

Just want to point out that:

rDcm.start = rDcm.End
rDcm.End = ActiveDocument.Range.End


could be done as:

rDcm.Collapse Direction:=wdCollapseEnd

There is no need to make the range End explicitly the Document.Range.End, and
in fact, no point whatsoever. As long as Forward:=True of course.

The next iteration of the Execute will resize rDCm to the Found range anyway.

It is, IMO, better to Collapse, as it achieves what is wanted (to continue
onwards and not get looped), but it makes it very easy to start a NEW
interation (say a new input for the search string), by resizing back to the
whole document. Like this:

Sub ReplaceStuff()
Dim r As Range
Dim myArray()
Dim var
Set r = ActiveDocument.Range
myArray = Array("quick", "fox", "dog")
For var = 0 To UBound(myArray)
With r.Find
Do While .Execute(FindText:=myArray(var), _
Forward:=True) = True
' action each found and collapse
r.Font.Bold = True
r.Collapse Direction:=wdCollapseEnd
Loop
End With
' reset the range
Set r = ActiveDocument.Range
Next var
End Sub

This would go through the array, and make every instance of "quick" Bold,
every instance of "fox" Bold, and every instance of "dog" Bold.

If there is only one string being searched, then of course there is no need
to resize the range to the whole document again. You can just collapse.
 
H

Helmut Weber

Hi,

if you are striving for perfection,
you don't need more than that,
maybe even less code.

Sub ReplaceStuffa1()
Dim rDcm As Range
Dim lVar As Long
Dim myArray() As String
myArray = Split("quick, fox, dog", ", ")
For lVar = 0 To UBound(myArray)
Set rDcm = ActiveDocument.Range
With rDcm.Find
.Text = myArray(lVar)
Do While .Execute
rDcm.Font.Bold = Not rDcm.Font.Bold
Loop
End With
Next
End Sub

Your code
.Execute(FindText:=myArray(var), Forward:=True) = True
would evaluate to (true = true) or (false = true),
the usefulness of which is questionable.

And stay away from variants,
it may be useful one time.

"collapse" vs "range.start = " etc...

Yes, you are right, in principle, no doubt.

On the other hand, each code has it's history,
and there are other aspects to code than to fulfil
just one task, like extensability and reusability.

It might have been, that during testing
exact control over the range was once required.
I just left the code it as it was.
I saw no need, to replace two lines of code,
that did what I wanted, with one line of code.

Furthermore, for less experienced persons as the OP,
if I may say so, controlling the range
the way I did, enables the OP to understand better
what is going on, when adding "select" here
and there and check in single step mode
what is happening to the range.

Your welcome, have a nice day.

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
N

Nomey

Thanks, Fumei and Helmut, for your new ideas and variants. I am indeed not particularly experienced with VBA, but I do like to explore it further.

Best regards,
Shirley
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top