spell check in protected forms

B

beverlydawn

I have inserted the macro that has been referred to in many of the replies to
this issue, however it does not reprotect after the spellcheck. Below is the
code I am inserting, where did I make my mistake? Any help would be
appreciated. Also, something I am noticing that could be the problem is that
the 3rd line has a line beneath it, effectively putting it into another
macro. When I cut and paste it into the spell check macro, the line goes
right back underneath it.

Option Explicit

Dim Cancelled As Boolean, MyRange As Range, _
CorrectedError As String, oDoc As Document



Sub RunSpellcheck()

Dim oSection As Section, OriginalRange As Range

'If no documents open, quit macro
If Documents.Count = 0 Then
Exit Sub
End If

Set oDoc = ActiveDocument
oDoc.Unprotect Password:="adatc"

'Check what type of protection - if any - has been applied
Select Case oDoc.ProtectionType

'If not protected, or if protected for tracked changes,
'run spellchecker and quit

Case wdNoProtection, wdAllowOnlyRevisions
If Options.CheckGrammarWithSpelling Then
oDoc.CheckGrammar
Else
oDoc.CheckSpelling
End If
Application.ScreenUpdating = True
Application.ScreenRefresh
If oDoc.SpellingErrors.Count = 0 Then
If Options.CheckGrammarWithSpelling Then
MsgBox "The spelling and grammar check is complete", _
vbInformation
Else
MsgBox "The spelling check is complete", vbInformation
End If
End If
System.Cursor = wdCursorNormal
Exit Sub

Case wdAllowOnlyComments
'Don't want to run spellchecker if protected for comments
Exit Sub
End Select

Set OriginalRange = Selection.Range
System.Cursor = wdCursorWait


'If we've got this far, it's protected for forms
'Now unprotect the document
oDoc.Unprotect
oDoc.SpellingChecked = False

'Check each section for its protection property -
'which you can get even after unprotecting the document.
'If the section was protected, call a subroutine to spellcheck the formfields.
'if it wasn't, spellcheck the section
StatusBar = "Spellchecking document ..."
For Each oSection In oDoc.Sections
If oSection.ProtectedForForms Then
Call CheckProtectedSection(oSection)
If Cancelled Then
'Boolean variable returned by CheckProtectedSection
'procedure if user pressed Cancel button
Exit For
End If
Else
If oSection.Range.SpellingErrors.Count > 0 Then
Application.ScreenUpdating = True
oSection.Range.CheckSpelling
If oSection.Range.SpellingErrors.Count > 0 Then
'User pressed Cancel button
'(Pressing Ignore reduces the count, pressing Cancel doesn't)
Exit For
End If
End If
End If
Next oSection

'Re-protect the document

oDoc.Protect Type:=wdAllowOnlyFormFields, NoReset:=True_
Password = "adatc"
OriginalRange.Select
Application.ScreenUpdating = True
Application.ScreenRefresh
If oDoc.Range.SpellingErrors.Count = 0 Then
If Options.CheckGrammarWithSpelling Then
MsgBox "The spelling and grammar check is complete", _
vbInformation
Else
MsgBox "The spelling check is complete", vbInformation
End If
End If

'Release variables from memory
System.Cursor = wdCursorNormal
Cancelled = False
CorrectedError = vbNullString
Set MyRange = Nothing

End Sub




Private Sub CheckProtectedSection(oSection As Section)

Dim FmFld As FormField, FmFldCount As Long, Pos As Long

'check only the text formfields,
'don't check listboxes and checkboxes - this speeds up the code
Application.ScreenUpdating = False
For Each FmFld In oSection.Range.FormFields
'Check to see if the field is a text formfield
If FmFld.Type = wdFieldFormTextInput Then
'Check if the field is a 'real' text field (no date, formula etc);
'and that it is enabled for text input
If FmFld.TextInput.Type = wdRegularText And FmFld.Enabled Then
'The following subroutine won't be called if Word 97 is in use
If Not Left$(Application.Version, 1) = "8" Then
Call TurnNoProofingOff(FmFld)
End If
FmFld.Range.SpellingChecked = False

'Change the language constant in the following line if necessary;
'when you type the = sign, a list of all supported language
'constants will appear, and you can choose one from the list.
FmFld.Range.LanguageID = wdEnglishUS
'Or whichever language is appropriate for you

'If the current form field contains errors, spellcheck the text
in it
If FmFld.Range.SpellingErrors.Count > 0 Then
'The following condition is to allow for a Word 97 bug, which
'was fixed in 2000; (and in the latest Word 97 patches). If
'the formfield is in a table and contains more than one
'paragraph, then spellchecking it will crash Word 97
If Left$(Application.Version, 1) = "8" _
And FmFld.Range.Paragraphs.Count > 1 _
And FmFld.Range.Tables.Count > 0 Then
Call Word97TableBugWorkaround(FmFld)
If Cancelled Then Exit Sub
Else
'Set a range to the formfield's range in case the user
'accidentally destroys the formfield by overtyping its
entire
'contents
Set MyRange = FmFld.Range
FmFldCount = oSection.Range.FormFields.Count
Application.ScreenUpdating = True

FmFld.Range.CheckSpelling

If IsObjectValid(FmFld) Then
If FmFld.Range.SpellingErrors.Count > 0 Then
'User pressed Cancel button. (Pressing Ignore
'reduces the count, pressing Cancel doesn't)
Cancelled = True
Exit Sub
End If
Else
'If formfield was destroyed because user overtyped its
'entire contents
CorrectedError = MyRange.Text
If Len(CorrectedError) = 0 Then
CorrectedError = MyRange.Words(1).Text
End If

'Formfields should really NEVER be preceded by a tab;
'design your forms so that each formfield is in its
own
'table cell (removing borders as necessary).
However, to
'cater for any legacy forms you may have, the
following
'loop works around the possibility that it might be
'preceded by a tab
Pos = InStr(CorrectedError, vbTab)
Do While Pos > 0
CorrectedError = Mid$(CorrectedError, Pos + 1)
Pos = InStr(CorrectedError, vbTab)
Loop

'If formfield was destroyed when the user corrected
the
'spelling, reinstate it, and put the user's
correction into its
'result. Note that although Undo reinstates the
Formfield
'itself, if the Formfield is preceded by a tab, It
doesn't
'reinstate the FmFld object, hence the need to do a
count
'(although, as previously stated, in a well-designed
form,
'formfields should never be preceded by a tab, as it's
'better use table cells (removing borders as
necessary).
Do While Not FmFldCount = _
oSection.Range.FormFields.Count
oDoc.Undo
Loop

'Also due to a Word bug, if the formfield is
preceded by a
'tab, the text within the formfield may now be
selected
'without the formfield itself being selected!
'Hence the following convoluted workaround
If Selection.FormFields.Count = 0 Then
Selection.MoveRight unit:=wdCharacter
Selection.MoveLeft unit:=wdCharacter, Extend:=True
End If
If Not IsObjectValid(FmFld) Then
Set FmFld = Selection.FormFields(1)
End If
FmFld.Result = CorrectedError
End If
End If
Application.ScreenUpdating = False
End If
End If
End If
Next FmFld

End Sub




Private Sub TurnNoProofingOff(FmFld As FormField)
'This subroutine is called only in Word 2000 and above
FmFld.Range.NoProofing = False

End Sub
 
B

Bear

BeverlyDawn:

I'm sorry I've not been of more help to you, but I can comment on this post.

As far as I can tell, the variables Cancelled, MyRange, CorrectedError and
oDoc should be defined at the module level. That is, you should paste them in
at the very beginning of the module. That defines them as being accessible to
all subroutines in that module.

The RunSpellcheck, CheckProtectedSection, and TurnNoProofingOff subroutines
should all have solid lines before them in the VBE, indicating them as
separate subroutines.

Bear

--
 
B

beverlydawn

Thanks! I was able to get the macro to work; it just takes several minutes
to run. Thanks for all your help.
 
D

Dorothy

I too pasted in the following macro, assigned a key and when I try to use the
key to check spelling in the protected document, I get "run-time error 5485 -
the password is incorrect". When I ask Visual Basic to debug it goes to the
macro and highlights "Doc.unprotect" in yellow. I am not a programmer and
this is very confusing and frustrating for me. Please walk me through how to
make spell check work. Thank you!

Option Explicit

Dim Cancelled As Boolean, MyRange As Range, _
CorrectedError As String, oDoc As Document

Sub RunSpellcheck()

Dim oSection As Section, OriginalRange As Range

'If no documents open, quit macro
If Documents.Count = 0 Then
Exit Sub
End If

Set oDoc = ActiveDocument

'Check what type of protection - if any - has been applied
Select Case oDoc.ProtectionType

'If not protected, or if protected for tracked changes,
'run spellchecker and quit
'-------------
Case wdNoProtection, wdAllowOnlyRevisions
If Options.CheckGrammarWithSpelling Then
oDoc.CheckGrammar
Else
oDoc.CheckSpelling
End If
Application.ScreenUpdating = True
Application.ScreenRefresh
If oDoc.SpellingErrors.Count = 0 Then
If Options.CheckGrammarWithSpelling Then
MsgBox "The spelling and grammar check is complete", _
vbInformation
Else
MsgBox "The spelling check is complete", vbInformation
End If
End If
System.Cursor = wdCursorNormal
Exit Sub
'-------------
Case wdAllowOnlyComments
'Don't want to run spellchecker if protected for comments
Exit Sub
End Select

Set OriginalRange = Selection.Range
System.Cursor = wdCursorWait

'-------------
'-------------
'If we've got this far, it's protected for forms
'Now unprotect the document
oDoc.Unprotect
oDoc.SpellingChecked = False

'Check each section for its protection property -
'which you can get even after unprotecting the document.
'If the section was protected, call a subroutine to spellcheck the formfields.
'if it wasn't, spellcheck the section
StatusBar = "Spellchecking document ..."
For Each oSection In oDoc.Sections
If oSection.ProtectedForForms Then
Call CheckProtectedSection(oSection)
If Cancelled Then
'Boolean variable returned by CheckProtectedSection
'procedure if user pressed Cancel button
Exit For
End If
Else
If oSection.Range.SpellingErrors.Count > 0 Then
Application.ScreenUpdating = True
oSection.Range.CheckSpelling
If oSection.Range.SpellingErrors.Count > 0 Then
'User pressed Cancel button
'(Pressing Ignore reduces the count, pressing Cancel doesn't)
Exit For
End If
End If
End If
Next oSection

'Re-protect the document
oDoc.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
OriginalRange.Select
Application.ScreenUpdating = True
Application.ScreenRefresh
If oDoc.Range.SpellingErrors.Count = 0 Then
If Options.CheckGrammarWithSpelling Then
MsgBox "The spelling and grammar check is complete", _
vbInformation
Else
MsgBox "The spelling check is complete", vbInformation
End If
End If

'Release variables from memory
System.Cursor = wdCursorNormal
Cancelled = False
CorrectedError = vbNullString
Set MyRange = Nothing

End Sub




Private Sub CheckProtectedSection(oSection As Section)

Dim FmFld As FormField, FmFldCount As Long, Pos As Long

'check only the text formfields,
'don't check listboxes and checkboxes - this speeds up the code
Application.ScreenUpdating = False
For Each FmFld In oSection.Range.FormFields
'Check to see if the field is a text formfield
If FmFld.Type = wdFieldFormTextInput Then
'Check if the field is a 'real' text field (no date, formula etc);
'and that it is enabled for text input
If FmFld.TextInput.Type = wdRegularText And FmFld.Enabled Then
'The following subroutine won't be called if Word 97 is in use
If Not Left$(Application.Version, 1) = "8" Then
Call TurnNoProofingOff(FmFld)
End If
FmFld.Range.SpellingChecked = False

'Change the language constant in the following line if necessary;
'when you type the = sign, a list of all supported language
'constants will appear, and you can choose one from the list.
FmFld.Range.LanguageID = wdEnglishUS
'Or whichever language is appropriate for you

'If the current form field contains errors, spellcheck the text
in it
If FmFld.Range.SpellingErrors.Count > 0 Then
'The following condition is to allow for a Word 97 bug, which
'was fixed in 2000; (and in the latest Word 97 patches). If
'the formfield is in a table and contains more than one
'paragraph, then spellchecking it will crash Word 97
If Left$(Application.Version, 1) = "8" _
And FmFld.Range.Paragraphs.Count > 1 _
And FmFld.Range.Tables.Count > 0 Then
Call Word97TableBugWorkaround(FmFld)
If Cancelled Then Exit Sub
Else
'Set a range to the formfield's range in case the user
'accidentally destroys the formfield by overtyping its
entire
'contents
Set MyRange = FmFld.Range
FmFldCount = oSection.Range.FormFields.Count
Application.ScreenUpdating = True

FmFld.Range.CheckSpelling

If IsObjectValid(FmFld) Then
If FmFld.Range.SpellingErrors.Count > 0 Then
'User pressed Cancel button. (Pressing Ignore
'reduces the count, pressing Cancel doesn't)
Cancelled = True
Exit Sub
End If
Else
'If formfield was destroyed because user overtyped its
'entire contents
CorrectedError = MyRange.Text
If Len(CorrectedError) = 0 Then
CorrectedError = MyRange.Words(1).Text
End If

'Formfields should really NEVER be preceded by a tab;
'design your forms so that each formfield is in its
own
'table cell (removing borders as necessary).
However, to
'cater for any legacy forms you may have, the
following
'loop works around the possibility that it might be
'preceded by a tab
Pos = InStr(CorrectedError, vbTab)
Do While Pos > 0
CorrectedError = Mid$(CorrectedError, Pos + 1)
Pos = InStr(CorrectedError, vbTab)
Loop

'If formfield was destroyed when the user corrected
the
'spelling, reinstate it, and put the user's
correction into its
'result. Note that although Undo reinstates the
Formfield
'itself, if the Formfield is preceded by a tab, It
doesn't
'reinstate the FmFld object, hence the need to do a
count
'(although, as previously stated, in a well-designed
form,
'formfields should never be preceded by a tab, as it's
'better use table cells (removing borders as
necessary).
Do While Not FmFldCount = _
oSection.Range.FormFields.Count
oDoc.Undo
Loop

'Also due to a Word bug, if the formfield is
preceded by a
'tab, the text within the formfield may now be
selected
'without the formfield itself being selected!
'Hence the following convoluted workaround
If Selection.FormFields.Count = 0 Then
Selection.MoveRight unit:=wdCharacter
Selection.MoveLeft unit:=wdCharacter, Extend:=True
End If
If Not IsObjectValid(FmFld) Then
Set FmFld = Selection.FormFields(1)
End If
FmFld.Result = CorrectedError
End If
End If
Application.ScreenUpdating = False
End If
End If
End If
Next FmFld

End Sub


--------------------------------------------------------------------------------

Private Sub TurnNoProofingOff(FmFld As FormField)
'This subroutine is called only in Word 2000 and above
FmFld.Range.NoProofing = False
End Sub


--------------------------------------------------------------------------------

Private Sub Word97TableBugWorkaround(FmFld As FormField)

'Unlink formfield (convert to text)
Set MyRange = FmFld.Range
FmFld.Range.Fields(1).Unlink
Application.ScreenUpdating = True
MyRange.CheckSpelling
If MyRange.SpellingErrors.Count > 0 Then
'User pressed Cancel button
'(Pressing Ignore reduces the count, pressing Cancel doesn't)
Cancelled = True
End If
CorrectedError = MyRange.Text
'Undo to reinstate the formfield
Do While Not IsObjectValid(FmFld)
oDoc.Undo
Loop
FmFld.Range.Fields(1).Result.Text = CorrectedError
Application.ScreenUpdating = False

End Sub



Sub Macro1()
'
' Macro1 Macro
' Macro recorded 9/17/2007 by Dorothy
'
End Sub
 
B

Bear

Dorothy:

I think the VBA might be telling you that your document is protected with a
password that you have to supply. Can you manually unprotect the document? If
so, try unprotecting it, then reprotecting it for Forms, but without using a
password. Then try the macro.

Bear
 
D

Dorothy

Thanks for the quick response. I tried to do spell check as the user would
and got the error message. They would not have the password to make changes.
I don't understand what you are asking me to do.
 
R

Robert M. Franz (RMF)

Hello Dorothy
Thanks for the quick response. I tried to do spell check as the user would
and got the error message. They would not have the password to make changes.
I don't understand what you are asking me to do.

the document seems to be protected with a password. The macro you posted
is not taking this into account, it assumes the document is merely
"protected for forms."

HTH
Robert
 
B

Bear

Dorothy:

Robert is correct. I'm asking you to do some things to troubleshoot the
problem.

Make a test copy of the document. Unprotect it -- I'm thinking this will
require a password. Now protect it again, but without using a password. Now
try the macro.

If it works, or at least gets past the last problem area, then that's what's
happening. The macro won't work on password protected forms. You'll either
need to remove the password protection, or add some code and provide your
users with the password to enter.

AFAIK there's no way to unprotect a password protected form either manually
or using VBA without the password.

Bear
 
D

Dorothy

The document is protected so that the users cannot make unauthorized changes.
How else can I protect the form other than a password. And more
importantly, how do I fix all of this? The last time I tried to use spell
check as a user I got the error message "cannot execute in break mode". Now
whe I go back to it, the document is frozen and I cannot do anything.
HELP?!?!?!
 
B

Bear

Dorothy:

Word is complaining because it thinks you have a macro open and in break
mode. If you can just end your Word session and start again, I'm hoping it
will close the macro and set things back the way you want.

You can protect a document for forms use without assigning a password.
You're the one that has to decide whether or not to use one. Protecting a
document for Forms use just enables the "formlike behavior" of the form. I.E.
everything gets protected from mistakes, and the Tab key gets you from field
to field, etc.

If you don't use a password, then your users *can* manually unprotect the
document and make unauthorized changes, as you've described. But this may not
be so big a problem or danger as to require password protection.

If you want to use password protection, and if you're the only one who knows
the password, then you could hard-code your password into the macro code and
password-protect your code as well so only you would be able to see the
password. Then the code would still be able to unprotect the form for
spell-check.

You'd change the unprotect statement to something like this:

ActiveDocument.Unprotect Password:="Blue"

where Blue is your password, and in the statement, you put double quotes
around it.

Then before you distribute your template, you'd open the VBE (Alt + F11) and
click Tools > [project name] - Properties > Protection. Then you check the
Lock Project for Viewing check box and enter and confirm a password. This is
the password to lock the template so the users can't examine your code to
find the form password.

It might be simpler just to ask your users not to make any changes.

Bear
 
D

Dorothy

Sorry to be so slow. I've removed the password. However, now the spell
check does not work at all in the user form. I feel like we're getting
there, . Now what?
 
B

Bear

Dorothy:

It might help if you watched what was happening as you ran the macro.

To do that, open the macro window (press Alt + F11). Now find the macro, and
put the cursor in the first line, the Sub RunSpellCheck(), and press F9. This
should insert a break point at the beginning of the macro, as shown by the
brown dot beside that line.

Whenever the macro is called to run, it will get to that point then enter
debug mode so you can control execution line by line.

If you have two monitors, put the macro window (this is called the VBE -- I
think for visual basic environment) in one monitor and the document in the
other. If you only have one monitor, tile the VBE and the document either
vertically or horizontally so you can see both at once.

Now attempt to run the macro as the user would from the document. When the
macro stops with the first line highlighted, switch to the VBE window (by
clicking the title bar) then step though the macro one line at a time by
pressing F8 to execute each line.

As you go along, see what's happening in the document, or where the macro
encounters trouble.

Bear
 
D

Dorothy

You are amazingly patient. Thank you.
I got this message:
Private Sub CheckProtectedSection(oSection As Section)
debug the run again -- run time error 5825 "object has been deleted
For Each FmFld In oSection.Range.FormFields debug and run again and get
"compile error - syntax error.

then it goes back to the last hightlighted line
For Each FmFld In oSection.Range.FormFields

From the user perspective, the spell check still does not work.
 
B

Bear

Dorothy:

I think we're both going to get old before we sort things out like this.

If you look at one of my replies, then click on Bear at the top (By: Bear)
you'll see my profile. A spam-encoded (sort of) version of my e-mail address
is there. Would you be able to e-mail me a copy of the problem form and your
template so I can see it directly? You'll need to change the extensions to
get them past my virus checker.

E.G. rename Problem Form.doc to Problem Form - doc.txt
and
rename MyFormTemplate.dot to MyFormTemplate - dot.txt

Or something like that.

Bear
 
D

Dorothy

Hi Bear,

I sent the documents to you, however, I had to take off the parenthetical
suffix to your address......neither of my email company's would allow me to
send to you. Hope the message arrived intact. Thanks again.
 
D

Dorothy

Hi Bear,

I sent the documents to you, however, I had to take off the parenthetical
suffix to your address......neither of my email providers would allow me to
send to you. Hope the message arrived intact. Thanks again.

:
 

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