Please maintain the crosspost for the benefit of the thread on
docmanagement.
--
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Graham Mayor - Word MVP
Web site www.gmayor.com
Word MVP web site www.mvps.org/word
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Charles Kenyon wrote:
> Hi Graham,
>
> I tried to adapt your procedures to a generic field checker and
> failed. The code:
>
> Sub ExitField()
> Dim strName As String
> Dim Balloon As Balloon
> If Selection.FormFields.Count = 1 Then
> 'No textbox but a check- or listbox
> strName = Selection.FormFields(1).Name
> ElseIf Selection.FormFields.Count = 0 And
> Selection.Bookmarks.Count > 0 Then
> strName = Selection.Bookmarks(Selection.Bookmarks.Count).Name
> End If
> With ActiveDocument.FormFields(strName)
> If Len(.Result) = 0 Then
> Beep
> Application.OnTime When:=Now + TimeValue("00:00:11"), _
> Name:="GoBacktoField(" & strName & ")"
> Set Balloon = Assistant.NewBalloon
> With Balloon
> .Text = "No Data!" & vbCr & "You must fill in this
> FormField "
> .Button = msoButtonSetOK
> .Animation = msoAnimationBeginSpeaking
> .Show
> End With
> End If
> End With
> End Sub
> Sub GoBacktoField(strName As String)
> ActiveDocument.Bookmarks(strName).Range.Fields(1).Result.Select
> End Sub
>
> I also tried it with a direct command to select the field rather than
> calling a subroutine.
>
> In both cases it failed when used as an on-exit macro but worked fine
> when run from the VBE or stepped-through. The failure was that even
> though the message displayed, the selection was the next field rather
> than the one that had been checked.
>
> I've looked at
> http://word.mvps.org/FAQs/TblsFldsFms/ValidateFFields.htm and
> http://word.mvps.org/FAQs/TblsFldsFms/GetCurFmFldName.htm.
>
> This is the first time I've looked at the OnTime function and I'm not
> sure that it allows the passing of parameters.
>
>
> "Graham Mayor" <gma...@DELETECAPSmvps.org> wrote in message
> news:Oy9Vae0...@tk2msftngp13.phx.gbl...
>> You can test for content using a pair of macros run on exit from the
>> field. You'll need a similar pair of macros macro for each field you
>> wish to test. The following tests for content in the first field,
>> which by default is called Text1. Change Text1 for the name of the
>> form field bookmark you wish to test and the text prompt for
>> whatever you want to say. Save the macros in the document template -
>> not normal.dot. The main macro uses the help assistant to pop up the
>> message. You could adapt to use a message box if you prefer.
>>
>> Sub ExitText1()
>> With ActiveDocument.FormFields("Text1")
>> If Len(.Result) = 0 Then
>> Beep
>> Application.OnTime When:=Now + TimeValue("00:00:01"),
>> Name:="GoBacktoText1"
>> Set Balloon = Assistant.NewBalloon
>> With Balloon
>> .Text = "No Data!" & vbCr & "You must fill in this
>> formfield"
>> .Button = msoButtonSetOK
>> .Animation = msoAnimationBeginSpeaking
>> .Show
>> End With
>> End If
>> End With
>> End Sub
>> Sub GoBacktoText1()
>> ActiveDocument.Bookmarks("Text1").Range.Fields(1).Result.Select
>> End Sub
>>
>> See http://www.gmayor.com/installing_macro.htm
>>
>> --
>> <>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
>> Graham Mayor - Word MVP
>>
>> Web site www.gmayor.com
>> Word MVP web site www.mvps.org/word
>> <>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
>>
>>
>> Bob wrote:
>>> I have created a MS Word Form that I want people to use
>>> when placing an order. Is there a way that I can make
>>> several of the form fields mandatory to fill out?
>>>
>>> Thanks
In short you can't prevent a "tab-out" of a FormField from moving to the
next FormField. You can't stop Word moving you to the next FF by doing
anything on the OnExit macro! However, you can work around it. Here's the
code and I'll explain the methodology:
Public Sub AOnExit()
ActiveDocument.Variables("ForceFF").Value = "Text1"
End Sub
Public Sub AOnEntry()
Dim strCurrentFF As String
' MsgBox GetCurrentFF.Name
strCurrentFF = ActiveDocument.Variables("ForceFF").Value
If LenB(Trim$(strCurrentFF)) > 0 Then
ActiveDocument.Variables("ForceFF").Value = " "
GotoFF strCurrentFF
End If
End Sub
Private Sub GotoFF(ByVal strFFName As String)
Dim fldTemp As Word.Field
Dim rngBM As Word.Range
Dim rngField As Word.Range
Dim strOnEntry As String
With ActiveDocument
' This is really the Form Field we want
Set rngBM = .Bookmarks(strFFName).Range
For Each fldTemp In .Fields
' Some fields are collapsed so adjust start to ensure
' the field falls within the bookmarks range
Set rngField = fldTemp.Result
If rngField.Start = rngField.End Then
rngField.Start = rngField.Start - 1
End If
' Selection appropriate to Form Field type
If rngField.InRange(rngBM) Then
If fldTemp.Type = wdFieldFormTextInput Then
fldTemp.Result.Select
Else
fldTemp.Select
End If
' Run the on entry macro if present
strOnEntry = .FormFields(strFFName).EntryMacro
If LenB(strOnEntry) > 0 Then
Application.Run strOnEntry
End If
Exit Sub
End If
Next
End With
End Sub
Ok for a simple test create a document with 3 text FormFields, Text1,
Text2, Text3. Set all FFs to use the "AOnEntry" OnEntry macro. Set Text1 to
use the "AOnExit" OnExit macro.
Once you've protected the document for Forms, it looks like you can't tab
out of the Text1 FF. Of course you can display the appropriate message, so
that the user knows why they're "stuck" in a field, but I've left that bit
out.
The mechanism is simple the OnExit macro loads a Document Variable with
it's own name. The OnEntry macro checks to see if the DV is not blank, if
it's not blank it then GoTos that FF! So that Word does not delete the DV
by assigning a nullstring to it, assign a space to it. This keeps the code
simple by not having to handle a non existent DV.
If you want to display messages set another DV to the message in the OnExit
macro and display it in the OnEntry macro.
HTH + Cheers - Peter
"Graham Mayor" <gma...@DELETECAPSmvps.org> wrote in
news:eWl3rPPB...@tk2msftngp13.phx.gbl:
That looks a tad complicated for an immediate reply :) I'll have a play
around and see where I get to. Thanks very much for supplying the code.
The puzzle arose because the original code, naming the field, does exactly
what I wanted, but doesn't when you thrown in the variable to allow the same
code to be used on all fields. It was this part I (and Charles) couldn't
figure out.
I REALLY don't like the timer method as it just does not work reliably. If
you tab through another field that uses the OnTime in its exit macro it
cancels the first one, or if code is still running at the elapsed time the
macro does not fire!
Anyway, you can't pass a parameter to a macro you're running using
"OnTime". You can resolve your problem by using a Private scope variable in
the module containing all this code. Here's a trivial example:
Private mstrValue As String
Public Sub AOnExit()
mstrValue = GetCurrentFF.Name
Application.OnTime Now + TimeValue("00:00:01"), "TimerTest"
End Sub
Public Sub TimerTest()
MsgBox "The ForField you left was" & vbCr & mstrValue
End Sub
Private Function GetCurrentFF() As Word.FormField
Dim rngFF As Word.Range
Set rngFF = Selection.Range
rngFF.Expand wdParagraph
Set GetCurrentFF = rngFF.FormFields(1)
End Function
If you attach the "AOnExit" procedure to any field as its OnExit macro, the
TimerText will display the name of the FF you last exited!
Here's a simplified version of my previous post, just attach the on entry
macro to ALL FormFields an the OnExit macro to any FormField you don't want
to be "blank". It's all the code you need plus it's more reliable than
OnTime!!!
Private mstrFF As String
Public Sub AOnExit()
With GetCurrentFF
If Len(.Result) = 0 Then
MsgBox "You can't leave field: " & .Name & " blank"
mstrFF = GetCurrentFF.Name
End If
End With
End Sub
Public Sub AOnEntry()
Dim strCurrentFF As String
' Goto another FormField if we weren't supposed to leave it!
If LenB(mstrFF) > 0 Then
ActiveDocument.FormFields(mstrFF).Select
mstrFF = vbNullString
End If
End Sub
Private Function GetCurrentFF() As Word.FormField
Dim rngFF As Word.Range
Dim fldFF As Word.FormField
Set rngFF = Selection.Range
rngFF.Expand wdParagraph
' You can't reliably use "rngFF.FormFields(1)" if you
' hit enter and tab out of the FF the code fails
For Each fldFF In rngFF.FormFields
Set GetCurrentFF = fldFF
Exit For
Next
End Function
HTH + Cheers - Peter
"Graham Mayor" <gma...@DELETECAPSmvps.org> wrote in
news:#LgqU4SB...@TK2MSFTNGP09.phx.gbl:
Charles Kenyon
See the MVP FAQ: <URL: http://www.mvps.org/word/> which is awesome!
--------- --------- --------- --------- --------- ---------
This message is posted to a newsgroup. Please post replies
and questions to the newsgroup so that others can learn
from my ignorance and your wisdom.
"Peter Hewett" <Nos...@xtra.co.nz> wrote in message
news:Xns94A78BB2...@207.46.248.16...
Charles Kenyon
See the MVP FAQ: <URL: http://www.mvps.org/word/> which is awesome!
--------- --------- --------- --------- --------- ---------
This message is posted to a newsgroup. Please post replies
and questions to the newsgroup so that others can learn
from my ignorance and your wisdom.
"Peter Hewett" <Nos...@xtra.co.nz> wrote in message
news:Xns94A78BB2...@207.46.248.16...
Anyway, it still doesn't cure the problem of the person who simply saves /
exits from a form without filling in a field, but it is a step in the right
direction. If I really need this, I will write some intercepts for Save and
SaveAs to catch those. I don't really care about the user who exits without
saving.
--
Charles Kenyon
See the MVP FAQ: <URL: http://www.mvps.org/word/> which is awesome!
--------- --------- --------- --------- --------- ---------
This message is posted to a newsgroup. Please post replies
and questions to the newsgroup so that others can learn
from my ignorance and your wisdom.
"Peter Hewett" <Nos...@xtra.co.nz> wrote in message
news:Xns94A78BB2...@207.46.248.16...
I don't see why it should skip a FF on you? ALL FF's need the OnEntry macro
but only those you want validated need the OnExit macro. As soon as you
leave a FF it set the Private variable mstrFF based on the contents of the
current FF. So when you move to the next FF and fire its OnEntry macro the
variables already set.
No, you're right the OnExit macro does not fire when you close or save your
document. To do what you want you have to use apllication events. The
Document_Save event is no good to you as you can't cancel it if the current
FF is invalid. As you know you can hook the DocumentBeforeSave event. You
can then run a validation procedure. You can't use the OnExit macros
because there is no way of stoping the document from being saved! What you
need is separate validation function. Here's how you would might set up the
code in the ThisDocument module:
Public WithEvents mappWord As Word.Application
Private mstrFF As String
Private Sub Document_New()
' Hook the event handler
Set mappWord = Word.Application
End Sub
Private Sub Document_Open()
' Hook the event handler
Set mappWord = Word.Application
End Sub
Private Sub mappWord_DocumentBeforeClose(ByVal Doc As Document, Cancel As
Boolean)
Cancel = Not ValidateAllFFs
End Sub
Private Function GetCurrentFF() As Word.FormField
Dim rngFF As Word.Range
Dim fldFF As Word.FormField
Set rngFF = Selection.Range
rngFF.Expand wdParagraph
' You can't reliably use "rngFF.FormFields(1)" if you
' hit enter and tab out of the FF the code fails!!
For Each fldFF In rngFF.FormFields
Set GetCurrentFF = fldFF
Exit For
Next
End Function
Private Function ValidateAllFFs() As Boolean
If LenB(GetFF("Text1").Result) = 0 Then
MsgBox "Cant leave field: Text1 blank"
ElseIf LenB(GetFF("Text2").Result) = 0 Then
MsgBox "Cant leave field: Text2 blank"
ElseIf LenB(GetFF("Text3").Result) = 0 Then
MsgBox "Cant leave field: Text3 blank"
Else
ValidateAllFFs = True
End If
End Function
Private Function GetFF(ByVal strFFName As String) As Word.FormField
ActiveDocument.FormFields(strFFName).Select
Set GetFF = GetCurrentFF
End Function
Public Sub AOnExit()
With GetCurrentFF
If Len(.Result) = 0 Then
MsgBox "You cant leave field: " & .Name & " blank"
mstrFF = .Name
End If
End With
End Sub
Public Sub AOnEntry()
Dim strCurrentFF As String
If LenB(mstrFF) > 0 Then
ActiveDocument.FormFields(mstrFF).Select
mstrFF = vbNullString
End If
End Sub
HTH + Cheers - Peter
"Charles Kenyon" <msnew...@remove.no.spam.addbalance.com> wrote in news:
#x$cmQXBE...@TK2MSFTNGP12.phx.gbl:
Hooked the wrong event, I should have choosen:
Private Sub mappWord_DocumentBeforeSave(ByVal Doc As Document, _
SaveAsUI As Boolean, Cancel As Boolean)
Cancel = Not ValidateAllFFs
End Sub
and not:
mappWord_DocumentBeforeClose
Cheers - Peter
Peter Hewett <Nos...@xtra.co.nz> wrote in
news:Xns94A7A2F5...@207.46.248.16:
Of the three batches of code, only the original one, which calls the
bookmarked fields by name responds correctly, thus the following works for
the same three fields Text1-3. Unfortunately this means you have to
duplicate the code for each field, which produces a lot of code for a form
with lots of fields, and plenty of opportunities to screw up the field names
when anything more complicated than Text1-3 is desired, hence the desire to
simplify it. Your own code also requires separate (albeit shorter) onexit
macros for each field.
I have changed the messages to use MsgBox rather than the help assistant for
the sake of clarity. Any further insights you have would be appreciated.
Sub ExitText1()
With ActiveDocument.FormFields("Text1")
If Len(.Result) = 0 Then
Beep
Application.OnTime When:=Now + TimeValue("00:00:01"),
Name:="GotoText1"
MsgBox ("Field must be completed")
End If
End With
End Sub
Sub ExitText2()
With ActiveDocument.FormFields("Text2")
If Len(.Result) = 0 Then
Beep
Application.OnTime When:=Now + TimeValue("00:00:01"),
Name:="GotoText2"
MsgBox ("Field must be completed")
End If
End With
End Sub
Sub ExitText3()
With ActiveDocument.FormFields("Text3")
If Len(.Result) = 0 Then
Beep
Application.OnTime When:=Now + TimeValue("00:00:01"),
Name:="GotoText3"
MsgBox ("Field must be completed")
End If
End With
End Sub
Sub GotoText1()
ActiveDocument.Bookmarks("Text1").Range.Fields(1).Result.Select
End Sub
Sub GotoText2()
ActiveDocument.Bookmarks("Text2").Range.Fields(1).Result.Select
End Sub
Sub GotoText3()
ActiveDocument.Bookmarks("Text3").Range.Fields(1).Result.Select
End Sub
I'm not sure what's happening (or not for you) but rather than persevere
with that code I've posted more concise and document variableless versions.
Check the follow up posts for a more viable and complete code samples. Lack
of conciseness is a problem when you post code at 2.00am!!
If you have further problems, post again and I'll email you something that
works.
Sorry for any confusion + Cheers - Peter
"Graham Mayor" <gma...@DELETECAPSmvps.org> wrote in
news:OzjqFrZB...@TK2MSFTNGP11.phx.gbl:
--
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Graham Mayor - Word MVP
Web site www.gmayor.com
Word MVP web site www.mvps.org/word
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
--
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Graham Mayor - Word MVP
Web site www.gmayor.com
Word MVP web site www.mvps.org/word
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
I suspect that the OnEntry macro did not fire upon the protection of the
document. The focus was, nevertheless, in the field. All I need to do with
templates is cycle through the fields manually once and then reset them
before saving.
Thank you for the coding.
--
Charles Kenyon
See the MVP FAQ: <URL: http://www.mvps.org/word/> which is awesome!
--------- --------- --------- --------- --------- ---------
This message is posted to a newsgroup. Please post replies
and questions to the newsgroup so that others can learn
from my ignorance and your wisdom.
"Peter Hewett" <Nos...@xtra.co.nz> wrote in message
news:Xns94A7A2F5...@207.46.248.16...
The new page should be active by the time you see this. If not try again in
a couple of minutes.
--
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Graham Mayor - Word MVP
Web site www.gmayor.com
Word MVP web site www.mvps.org/word
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Thanks for the attribution. You're more than welcome to use whatever I post.
I hope the house building project goes well for you.
Cheers + Good luck - Peter
"Graham Mayor" <gma...@DELETECAPSmvps.org>, said:
>Peter
>I have added some of this to my web site with appropriate credit to you. I
>do not have your e-mail address to contact you off group. If you have any
>comments or objections, let me know and I will change or remove the page.
>http://www.gmayor.com/Whats_New.htm
>
>The new page should be active by the time you see this. If not try again in
>a couple of minutes.
HTH + Cheers - Peter
--
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>
Graham Mayor - Word MVP
Web site www.gmayor.com
Word MVP web site www.mvps.org/word
<>>< ><<> ><<> <>>< ><<> <>>< <>>< ><<>