PDA

View Full Version : Working with range.find to parse a document



marsy00
09-27-2012, 01:54 PM
Hello Again,

So, I'm still trying to figure out exactly how the range object behaves. I've run into another question that I hope someone can help me with.

Below I paste an example requirement from my requirements document. I've added the styles of each portion in {} since I cant paste the actual word content into here.

SYS:0089 {Style = Requirement}

HW, FW {Style = Affects}

Example Requirement. This requirement is based on: {Style = Normal}
• IEC 60601-1, Subclause 6.3.1 {Style = Standards Char}
• IEC 45502-1, Subclause 15.6 {Style = Standards Char}


[Trace Tag] {Style = Trace}

§


Now, what I want to do is generate a report in Excel that lists each requirement in the document and parses the content into columns based on style. I have it working using the Find object, but it only finds the first item in the requirement with the given style. For example, the above requirement would only return the first bullet for the Standards style.

In my code below, the commented out block (near the bottom) is the functional code that only returns the one bullet. The code just below that is what I used to try to return both bullets. But, the problem is that when I use the do loop, the .find is executing on the entire document (i.e. its parsing the entire document full of requirements, not just the one requirement that I'm trying to work with). I thought that my r.MoveEndUntil cset:="§" limited the range to just the one requirement.

Any help is greatly appreciated! Thanks!


Private Function getReqData(req As String, toGet As String) As String

Dim r As Range
Dim i

Set r = ActiveDocument.Range
i = 0
' Find the requirement "req" in the document.
With r.find
.ClearFormatting
.Style = ActiveDocument.Styles("Requirement")
.Text = req
.Replacement.Text = ""
.Forward = True
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop

If .Execute = True Then
'Once found, exit the with block and find the "toGet" style.
Else
'If the requirement wasnt found, then exit the function (error condition).
getReqData = "ERROR:NOT FOUND"
Exit Function
End If
End With

' Expand the range to include the entire requirement.
r.MoveEndUntil cset:="§"

' Find the item in the requirement with the style = toGet.
With r.find
.ClearFormatting
.Style = ActiveDocument.Styles(toGet)
.Text = ""
.Replacement.Text = ""
.Forward = True
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop

' If .Execute = True Then
' getReqData = r.Text
' End If

Do While .Execute = True
If i = 0 Then
getReqData = r.Text
Else
getReqData = getReqData & vbCr & r.Text
End If
i = i + 1
Loop
End With

End Function

fumei
09-27-2012, 08:42 PM
[quote]I thought that my r.MoveEndUntil cset:="§" limited the range to just the one requirement.
[/quote[]Not quite.

It does exactly what it says it does. It moves the End point to just before "§".

BUT...the original quality (so to speak) of r = ActiveDocument.Range still applies.

Let me see if I can make that clearer. The Find method dynamically changes - temporarily - the Start and End of the range. You can think of it these as sort of sub-ranges.

So lets walk through.

1. r = whole document
2. r.Find looks for the first instance of text with the Requirement style
3. if it finds it, the range is dynamically reset for THAT instance of the style. No more, no less.
4. the range end is moved until to just before "§".


And where is the toGet style?????

marsy00
09-28-2012, 07:17 AM
[quote]I thought that my r.MoveEndUntil cset:="§" limited the range to just the one requirement.
[/quote[]Not quite.

It does exactly what it says it does. It moves the End point to just before "§".

BUT...the original quality (so to speak) of r = ActiveDocument.Range still applies.

Let me see if I can make that clearer. The Find method dynamically changes - temporarily - the Start and End of the range. You can think of it these as sort of sub-ranges.

So lets walk through.

1. r = whole document
2. r.Find looks for the first instance of text with the Requirement style
3. if it finds it, the range is dynamically reset for THAT instance of the style. No more, no less.
4. the range end is moved until to just before "§".


And where is the toGet style?????

Thanks for the explanation. And the "toGet" style is a parameter that is passed into the function.

Anyone have a suggestion for implementing this such that it returns both bullets when "standards char" is passed in?

Thanks!

fumei
09-28-2012, 10:48 AM
Ummm, so the string variable = "Standards Char". it would have been helpful to say that.

Hang on.

marsy00
09-28-2012, 10:51 AM
Ummm, so the string variable = "Standards Char". it would have been helpful to say that.

Hang on.

my bad... thats what happens when you stare at this stuff for hours -- you start making assumptions :)

fumei
09-28-2012, 11:03 AM
OK, here we go. If you have:
SYS:0089 {Style = Requirement}

HW, FW {Style = Affects}

Example Requirement. This requirement is based on: {Style = Normal}
• IEC 60601-1, Subclause 6.3.1 {Style = Standards Char}
• IEC 45502-1, Subclause 15.6 {Style = Standards Char}
[Trace Tag] {Style = Trace}
§


And you execute:
Option Explicit

Sub BlahBlah()
MsgBox getReqData("SYS:0089", "Standards Char")
End Sub
Private Function getReqData(req As String, toGet As String) As String

Dim r As Range
Dim i As Long

Set r = ActiveDocument.Range
i = 0
' Find the requirement "req" in the document.
With r.Find
.ClearFormatting
.Style = ActiveDocument.Styles("Requirement")
.Text = req
.Replacement.Text = ""
.Forward = True
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop
.Execute
If .Found = True Then
'Once found, exit the with block and find the "toGet" style.
Else
'If the requirement wasnt found, then exit the function (error condition).
getReqData = "ERROR:NOT FOUND"
Exit Function
End If
End With

' Expand the range to include the entire requirement.
r.MoveEndUntil cset:="§"

' Find the item in the requirement with the style = toGet.
With r.Find
.ClearFormatting
.Style = ActiveDocument.Styles(toGet)
.Text = ""
.Replacement.Text = ""
.Forward = True
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Wrap = wdFindStop

' If .Execute = True Then
' getReqData = r.Text
' End If

Do While .Execute = True
If i = 0 Then
getReqData = r.Text
Else
getReqData = getReqData & vbCr & r.Text
End If
i = i + 1
Loop
End With

End Function
You get a messagebox displaying.....wait for it

• IEC 60601-1, Subclause 6.3.1 {Style = Standards Char}
• IEC 45502-1, Subclause 15.6 {Style = Standards Char}

Can you see the difference? Hint, look at the first Execute.

Walk it through line by line. By the way, do you step through your code?

fumei
09-28-2012, 11:17 AM
BTW: why do you need both text and style as parameters of the function? I would have thought you would be searching for only the style. Otherwise you need to input the actual text string for the paragraph with the Requirements style.

And, if you are always basing this on a initial search for the Requirements style, you may as well make that a Constant. The following ALSO displays


• IEC 60601-1, Subclause 6.3.1 {Style = Standards Char}
• IEC 45502-1, Subclause 15.6 {Style = Standards Char}

Option Explicit
Const Req As String = "Requirement"
Sub BlahBlah()
MsgBox getReqData("Standards Char")
End Sub
Private Function getReqData(toGet As String) As String

Dim r As Range
Dim i As Long

Set r = ActiveDocument.Range
i = 0
' Find the requirement "req" in the document.
With r.Find
.ClearFormatting
.Style = ActiveDocument.Styles(Req)
.Replacement.Text = ""
.Execute
If .Found = False Then
'If the requirement wasnt found, then exit the function (error condition).
getReqData = "ERROR:NOT FOUND"
Exit Function
End If
End With

' Expand the range to include the entire requirement.
r.MoveEndUntil cset:="§"

' Find the item in the requirement with the style = toGet.
With r.Find
.ClearFormatting
.Style = ActiveDocument.Styles(toGet)
.Text = ""
Do While .Execute = True
If i = 0 Then
getReqData = r.Text
Else
getReqData = getReqData & vbCr & r.Text
End If
i = i + 1
Loop
End With
End Function

marsy00
09-28-2012, 11:32 AM
Thanks Fumei!

I wont be able to look this over til Monday, but I'll let you know how it works then.

Have a good weekend.

fumei
09-28-2012, 01:53 PM
"my bad... thats what happens when you stare at this stuff for hours -- you start making assumptions"

Oh it does not need hours to make assumptions. Assumptions are human nature. They happen very easily. By everyone.

marsy00
10-08-2012, 02:53 PM
BTW: why do you need both text and style as parameters of the function? I would have thought you would be searching for only the style. Otherwise you need to input the actual text string for the paragraph with the Requirements style.

And, if you are always basing this on a initial search for the Requirements style, you may as well make that a Constant. The following ALSO displays


• IEC 60601-1, Subclause 6.3.1 {Style = Standards Char}
• IEC 45502-1, Subclause 15.6 {Style = Standards Char}


I need the text to identify which requirement in which to search for the selected style.

I've attached a word doc with four requirements in it. Each requirement has two traceability tags at the end of it.

I modified my code per your suggestion above. I would expect that when I call
getReqData("PHN:0001", "Trace")
the function would return "[SYS:0001] [SYS:0002]".

However, the do while loop keeps executing, and it returns all of the trace tags for all four requirements...

Can you help me figure out how to limit the range to just the requirement in question?

Thanks again for your help!
Marshall

fumei
10-08-2012, 08:56 PM
I can not read docx files.

marsy00
10-08-2012, 09:04 PM
I can not read docx files.

.doc attached.

marsy00
10-16-2012, 11:32 AM
bump

marsy00
10-23-2012, 07:32 AM
anyone?