J
Jay Freedman
Excellent! Thanks.
Here's my latest version. I have some questions at the end.
You're really getting into this! Good stuff... I'll just throw in a
couple of suggestions about your code before I get to the questions.
'======================= sample code =================
Sub RandCharColors()
Dim oChar As Range
Dim myColor As Word.WdColorIndex
Dim vaColors As Variant
Dim iChar As Integer
Dim sOption As String
The sOption variable really should be declared as an Integer instead
of a String. If you look at the VBA help topic on the MsgBox function,
you'll see that it returns an Integer value to tell you which button
was pressed, and the vbYes/vbNo/vbCancel constants are all integers.
Your code functions because VBA does a silent conversion in the
assignment and logical comparison operators, but it shouldn't have to.
'Define the colors to be used
vaColors = Array(wdRed, wdGreen, wdBlack)
'Find out if the user wants random or repeating colors
Const sPrompt As String = "Click on:" & vbCrLf & _
"Yes = random colors" & vbCrLf & _
"No = repeating colors"
Const sTitle As String = "Random Character Colors Macro"
sOption = MsgBox(sPrompt, vbYesNoCancel, sTitle)
If sOption <> vbYes And sOption <> vbNo Then 'If neither yes or no,
exit
It would be simpler here to write
If sOption = vbCancel Then
Call MsgBox("No action taken", , sTitle)
Return
If you test this by clicking the Cancel button, you'll get an error
("Return without GoSub"). Instead of Return, what you want here is
Exit Sub.
End If
'Apply the colors
iChar = 0
Randomize
For Each oChar In Selection.Characters
If oChar.Text = " " Or oChar.Text = vbCr Or oChar.Text = vbLf Then
myColor = vbBlack
ElseIf sOption = vbYes Then
myColor = vaColors(Int((UBound(vaColors) + 1) * Rnd()))
Else
myColor = vaColors(iChar Mod (UBound(vaColors) + 1))
iChar = iChar + 1
End If
oChar.Font.ColorIndex = myColor
Next oChar
End Sub
'===========================================
1. Is there some way to modify the MsgBox function so that it will put
up buttins with different labels? I would like "Random", "Repeating",
and "Cancel". If not, is there another function to accomplish that?
There's no way in standard VBA to get a MsgBox to display any buttons
except the ones listed in the help topic. I suspect there might be a
way to use a Windows API call to modify the captions on the buttons,
but I'd have to spend some time studying it.
The alternative is to make a userform that looks like a message box,
and contains whatever text and buttons you want. This is a little more
complex, but if you think this kind of macro programming is fun,
userforms will be a real blast. Start at
http://www.word.mvps.org/FAQs/Userforms/CreateAUserForm.htm, and let
me know if you need help.
2. I am testing for certain characters, such as space, CR and LF, so I
can skip them. Otherwise, the repeating pattern gets off. I should
probably add others such as tab. Is there a good way to test the
current character against a list (without doing separate compares) or
is there a way to test if it is a printable character (a-z, 0-9, or
certain specials (!#$%...)?
You can test against a list by replacing
If oChar.Text = " " Or oChar.Text = vbCr Or oChar.Text = vbLf Then
with
If oChar.Text Like "[ ^13^10^9]" Then
where the numeric codes are ^13 = vbCr, ^10 = vbLf, and ^9 = vbTab.
The Like operator checks the oChar.Text to see if it's any of the
characters inside the brackets.
Alternatively, you can set up the loop this way:
For Each oChar In Selection.Characters
If oChar.Text Like "[A-Za-z0-9!#$%*]" Then
If sOption = vbYes Then
myColor = vaColors(Int((UBound(vaColors) + 1) * Rnd()))
Else
myColor = vaColors(iChar Mod (UBound(vaColors) + 1))
iChar = iChar + 1
End If
Else
myColor = vbBlack
End If
oChar.Font.ColorIndex = myColor
Next oChar
Now the coloring is done only for letters, digits, and the listed
special characters, and anything else falls into the vbBlack case.
3. What's the best way to call the macro other than assigning it to a
keyboard shortcut?
You have these choices:
- Keyboard shortcut
- Toolbar button
- Menu item
- Entry or Exit macro of a protected form field
- Intercept a built-in command such as Save or Print
- Respond to an event such as opening, closing, switching to another
window, etc.
Which one is the "best" way depends on what the macro does and what
your preference is. Often it's nice to have two or more ways for the
same macro, for instance a shortcut and a menu item.
Here are some references:
http://www.word.mvps.org/FAQs/Customization/AsgnCmdOrMacroToHotkey.htm
http://www.word.mvps.org/FAQs/Customization/AsgnCmdOrMacroToToolbar.htm
http://www.word.mvps.org/FAQs/MacrosVBA/InterceptSavePrint.htm
http://www.word.mvps.org/FAQs/MacrosVBA/DocumentEvents.htm
http://www.word.mvps.org/FAQs/MacrosVBA/ApplicationEvents.htm
Thanks. This has been kinda fun.
Yeah, I know. It's been fun for me since Word 2.0. That's why I'm
here.
--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the
newsgroup so all may benefit.