Can't read Range.Text in a protected document

R

Ray C

I need to find all emails inside a Word document. The problem is that when
the document is protected, I can't read the Text property of the range. I get
an error saying that the document is protected (Error #4605). All I'm doing
is reading, I'm not modifying anything. I use the Split function to get the
sentence of words where the @ sign was found, then I loop through the
elements of my array until I get to the one that has the @ sign. It's this
line that causes the error.

Here part of my code:

For Each rngStory In objDocument.StoryRanges
With rngStory.Find
.ClearFormatting
.Text = "@"
.Wrap = wdFindStop
.Forward = True
End With
Do Until rngStory.Find.Execute = False
With rngStory.Duplicate
.Expand Unit:=wdSentence
myArray = Split(.Text, " ", -1, vbTextCompare) '///
Error here !!!
If UBound(myArray) <> -1 Then
For i = 0 To UBound(myArray)
If InStr(1, myArray(i), "@", vbTextCompare) <> 0
Then
'/// ... Process Email here
numEmailsFound = numEmailsFound + 1
End If
Next i
End If
End With
Loop
Next rngStory
 
M

macropod

Hi Ray,

You need to unprotect documents protected for forms before you can process them in this way. Try something like this:
Sub Get_EmailAddrs()
Dim oRng As Range
Dim TstStr As String
Dim strPwd As String
Dim pState As Boolean
Dim i As Integer
With ActiveDocument
If .ProtectionType = wdAllowOnlyFormFields Then
pState = True
strPwd = InputBox("Please input the Password", "Document Protected for Forms")
.Unprotect (strPwd)
End If
For Each oRng In .StoryRanges
With oRng.Find
.ClearFormatting
.Text = "@"
.Wrap = wdFindStop
.Forward = True
End With
Do Until oRng.Find.Execute = False
With oRng.Duplicate
.Expand Unit:=wdSentence
TstStr = .Text
For i = 1 To 31
TstStr = Replace(Replace(TstStr, Chr(i), " "), " ", " ")
Next
TstStr = Replace(Replace(TstStr, Chr(160), " "), " ", " ")
For i = 0 To UBound(Split(TstStr, " "))
If InStr(1, Split(TstStr, " ")(i), "@") <> 0 Then
MsgBox Split(TstStr, " ")(i)
End If
Next i
End With
Loop
Next oRng
If pState = True Then .Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=strPwd
pState = False
End With
End Sub

You'll notice that I've also added some code to strip out any non-printing characters that might be next to the strings you're
testing. If you don't do this, you may get extra characters that invalidate the email strings (which you still should test for
validity anyway).

Cheers
 
R

Ray C

Thanks macropod, I got it to work flawlessly. But I have a question.

Why do I have to programmatically unprotect the document when all I'm doing
is extracting email addresses from the document? I'm not modifying the
document, I'm reading from the document.

This is why I found it strange that when my code tries to read the
Range.Text property I get an error saying that the document is protected.
Isn't the Range.Text property a readonly property?

Unfortunately, my client gets a lot of protected Word documents to which he
does not know the passwords. All he wants to do is extract the emails from
inside each document. He places them in a folder and my code loops through
all the documents in that folder.

Thanks in advance
Ray

macropod said:
Hi Ray,

You need to unprotect documents protected for forms before you can process them in this way. Try something like this:
Sub Get_EmailAddrs()
Dim oRng As Range
Dim TstStr As String
Dim strPwd As String
Dim pState As Boolean
Dim i As Integer
With ActiveDocument
If .ProtectionType = wdAllowOnlyFormFields Then
pState = True
strPwd = InputBox("Please input the Password", "Document Protected for Forms")
.Unprotect (strPwd)
End If
For Each oRng In .StoryRanges
With oRng.Find
.ClearFormatting
.Text = "@"
.Wrap = wdFindStop
.Forward = True
End With
Do Until oRng.Find.Execute = False
With oRng.Duplicate
.Expand Unit:=wdSentence
TstStr = .Text
For i = 1 To 31
TstStr = Replace(Replace(TstStr, Chr(i), " "), " ", " ")
Next
TstStr = Replace(Replace(TstStr, Chr(160), " "), " ", " ")
For i = 0 To UBound(Split(TstStr, " "))
If InStr(1, Split(TstStr, " ")(i), "@") <> 0 Then
MsgBox Split(TstStr, " ")(i)
End If
Next i
End With
Loop
Next oRng
If pState = True Then .Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=strPwd
pState = False
End With
End Sub

You'll notice that I've also added some code to strip out any non-printing characters that might be next to the strings you're
testing. If you don't do this, you may get extra characters that invalidate the email strings (which you still should test for
validity anyway).

Cheers
--
macropod
[MVP - Microsoft Word]
-------------------------

Ray C said:
I need to find all emails inside a Word document. The problem is that when
the document is protected, I can't read the Text property of the range. I get
an error saying that the document is protected (Error #4605). All I'm doing
is reading, I'm not modifying anything. I use the Split function to get the
sentence of words where the @ sign was found, then I loop through the
elements of my array until I get to the one that has the @ sign. It's this
line that causes the error.

Here part of my code:

For Each rngStory In objDocument.StoryRanges
With rngStory.Find
.ClearFormatting
.Text = "@"
.Wrap = wdFindStop
.Forward = True
End With
Do Until rngStory.Find.Execute = False
With rngStory.Duplicate
.Expand Unit:=wdSentence
myArray = Split(.Text, " ", -1, vbTextCompare) '///
Error here !!!
If UBound(myArray) <> -1 Then
For i = 0 To UBound(myArray)
If InStr(1, myArray(i), "@", vbTextCompare) <> 0
Then
'/// ... Process Email here
numEmailsFound = numEmailsFound + 1
End If
Next i
End If
End With
Loop
Next rngStory
 
M

macropod

Hi Ray,
Why do I have to programmatically unprotect the document when all I'm doing
is extracting email addresses from the document? I'm not modifying the
document, I'm reading from the document.

Because you're trying to access the protected area. If the email addresses existed only in the formfields, you could test just the
formfield results without unprotecting the document.
Isn't the Range.Text property a readonly property?

No. Try this in an unprotected document - it'll replace whatever's in the first paragraph:
Sub Test()
ActiveDocument.Paragraphs(1).Range.Text = "Hello World"
End Sub

Cheers
 

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