Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Range is in Field

    How can I test to see if a range is within a field?

    I thought that the following code worked, but it appears not:
    <pre> For Each wrd In ActiveDocument.Words
    ' How do i know if I am IN a field?
    If wrd.Fields.Count > 0 Then
    Else
    </pre>


    I'd love to have something along the lines of Range.Information(wdWithinTable) but Range.Information(wdWithinField) instead.


    In my test case I have a document with a table of contents {TOC} field. I'm looping For Each wrd in ActiveDocument.Words, but I want to ignore any "wrd" within the {TOC}, or, for that matter, in ANY field, including {Hyperlink}, {XE} and so on.

    I suppose I could set up a table of ranges (.Start and .End) and test each wrd within that table, but ForEachWrd is already slow enough without adding overhead.

  2. #2
    JustCallMeAl
    Guest

    Re: Range is in Field

    Is there anything in this that may be helpful:

    <pre>Public Function SelectionWithinField() As Field
    Dim bFieldsToggled As Boolean
    Dim rgOriginal As Range

    On Error GoTo SelectionWithinField_Error

    If Not Selection Is Nothing Then
    With Selection
    Set rgOriginal = .Range
    If ActiveWindow.View.ShowFieldCodes = False Then
    Selection.Fields.ToggleShowCodes
    bFieldsToggled = True
    End If
    If .Words(1).Fields.Count Then
    Set SelectionWithinField = .Words(1).Fields(1)
    End If
    If bFieldsToggled Then
    .Fields.ToggleShowCodes
    End If
    End With
    End If
    SelectionWithinField_Error:
    If Not rgOriginal Is Nothing Then
    rgOriginal.Select
    End If
    End Function
    </pre>


  3. #3
    2 Star Lounger
    Join Date
    Feb 2001
    Location
    Eugene, Oregon, USA
    Posts
    110
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    I can't seem to access a "Word" object directory--but this sub seems to work for me.


    Sub WordInField()
    Dim i As Integer
    For i = 1 To ActiveDocument.Words.Count
    If Not ActiveDocument.Words(i).Fields.Count > 0 Then
    MsgBox (ActiveDocument.Words(i))
    End If
    Next
    End Sub

  4. #4
    2 Star Lounger
    Join Date
    Feb 2001
    Location
    Eugene, Oregon, USA
    Posts
    110
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    oops. i had answered too soon. my first posted code also falls apart. looking further...

    It appears that the only "words" that Word reliably identifies as having a field are the field markers themselves.

    Thus, if you cycle through a document/range word-by-word, the first time you hit a word that has a "Field.Count", that word will be the beginning of a field code. If you continue to cycle word-by-word, the next word you hit that has a "field.count" will be the end of the field code. Assuming that there are no nested codes (is that possible?), the following seems to exclude all words in a field...

    ActiveWindow.View.ShowFieldCodes = True
    FOR i = 1 To myDoc.Words.Count
    IF myDoc.Words(i).Fields.Count > 0 Then
    boolInField = True
    DO WHILE boolInField
    i = i + 1
    If myDoc.Words(i).Fields.Count > 0 Then boolInField = False
    LOOP

    ELSE
    END IF
    NEXT
    ActiveWindow.View.ShowFieldCodes = False

  5. #5
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    I can't seem to access a "Word" object directory--but this sub seems to work for me.
    Sub WordInField()

    Not for me and my (t)rusty ole Word97SR2.


    I set up a document with three paragraphs:
    <pre> Contents
    {TOC}
    Test
    [pre]
    That's a plain-jane {TOC} field there; no switches, no nothin.

    I run your macro and get the follwing outputs
    [pre]
    Contents
    (null)
    TOC <<< It seems to pick up the string TOC WITHIN the field braces.
    (null)
    Test
    (null)
    </pre>



    Here's the strange thing:

    If I turn field codes OFF, I see on my document the familiar "Error! No table of contents entries found." and when I re-run the loop I see:
    <pre>Contents
    (null)
    !
    No table
    of
    contents
    </pre>



    and that's it! What happened to the rest of the text, which I didn't want to see anyway. I wanted to see only half of it even less!

  6. #6
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    Yup. Our posts crossed.

    let's BOTH go back to the drawing board.

    re my original post: I take it that your replies endorse my suspicions that there is no wdWithinField type of flag/status? We are going to have to hack our way around this?

  7. #7
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    > Assuming that there are no nested codes (is that possible?),

    It's possible to *assume that*, but deadly (grin!)

    Nested fields are supported in the Word97 hell files: Here's a snip from "Field codes: = (Formula) field"

    Page { PAGE } of { = (47 - 1) + { NUMPAGES } }




    Interesting point, though. My immediate requirement is to skip anything if it is within a pair of field braces. It would be neat to have a function that returned not a Boolean (as I need now) but an Integer indicating the depth of nesting of braces. A result of 0 would indicate "not inside a field".

  8. #8
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    >Is there anything in this that may be helpful:

    Yes, there may, although I'm still a tad puzzled by the behaviour of .Fields.Count

    I'm running Word97SR2 here.


    Without changing your code, try this REAL SMALL experiment:

    In a new document, insert a TOC field. With Field Codes displayed you'll see just:
    <pre> { TOC }
    </pre>

    No text, no headings, nothing. Just a single Field, and within it a single field code and no switches.


    Now run the following User macro:
    <pre>Sub TESTSelectionWithinField()
    Dim wrd As Range
    For Each wrd In ActiveDocument.Words
    wrd.Select
    On Error Resume Next
    MsgBox SelectionWithinField.Code.Text
    Next wrd
    End Sub
    </pre>


    I *hate* On Error, but I'll make an exception here because I dodn't want to modify your original code - yet! You should see "TOC" be MsgBoxed twice. Once for the entire field, and once for the 3-character string within the field. We'll discuss "each word in ActiveDocument.Words" some other time.


    I reason that if I make your function return a STRING rather than a field, and generate EITHER the Fields(1).Code.Text or the Selection.Text, my user macro doesn't need the On Error, and I can be working my way towards a utility function that tests and returns a BOOLEAN, so here's my next stage:


    <pre>Public Function SelectionWithinField() As String ' Changed
    Dim bFieldsToggled As Boolean
    Dim rgOriginal As Range

    On Error GoTo SelectionWithinField_Error

    If Not Selection Is Nothing Then
    With Selection
    Set rgOriginal = .Range
    If ActiveWindow.View.ShowFieldCodes = False Then
    Selection.Fields.ToggleShowCodes
    bFieldsToggled = True
    End If
    If .Words(1).Fields.Count Then
    SelectionWithinField = "field " & _
    .Words(1).Fields(1).Code.Text ' Changed
    Else ' Changed
    SelectionWithinField = "Word " & Selection.Text ' Changed
    End If
    If bFieldsToggled Then
    .Fields.ToggleShowCodes
    End If
    End With
    End If
    SelectionWithinField_Error:
    If Not rgOriginal Is Nothing Then
    rgOriginal.Select
    End If
    End Function
    Sub TESTSelectionWithinField()
    Dim wrd As Range
    For Each wrd In ActiveDocument.Words
    wrd.Select
    ' On Error Resume Next ' Changed
    MsgBox SelectionWithinField ' Changed
    Next wrd
    End Sub
    </pre>


    I augmented the document to include a paragraph with one word "Contents" at before the {TOC} and a paragraph with "Text" after the {Toc}.

    Now I run my test macro and get as output:
    Word contents
    Word (the paragraph mark)
    Field TOC (OK)
    Word TOC (eh? )
    Field TOC Hmmm. The {TOC} gets counted on the way out as wella s the way in.


    So far the test for a word (in our case selected, but usually I'm using ranges) fails to determine that the word is WITHIN Field Code braces.


    My problem last night was in looping through all words in a document, and getting caught up in both a Contents table and an Index table. It's no fun AutoMarking words from the index table, honest!


    I can't always be sure that I'm looping through all words in a document, either; the user might have directed me to locate certain strings. I need to determine if I'm in a field without having noted that I've crossed a Field boundary ({) going in or (}) coming out.

  9. #9
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    I'm either getting closer to a solution, or wandering down the wrong path. Story of my life.



    I can now detect what I want for non-nested fields.

    In the code below I have eliminated all the fancy stuff, like preserving the ShowCodes settings etc. I want to get the bare-bones device working. A production version would return Integer flags indicating the result rather than strings. etc.



    My main thought still is "I must have missed something. How come I can't issue a simple test for where I am? How come none of the properties of Field that I have tested will acieve my aims?

    I hate On Error, but even trying things like:
    <pre>On error go to NotInAField
    selection.fields(1)."some property"
    </pre>

    isn't getting me anywhere.




    <pre>Function a2() As String
    ActiveWindow.View.ShowFieldCodes = True
    Dim rngInitial As Range
    Set rngInitial = Selection.Range
    With Selection.Find
    .Text = "^d"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindContinue
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    End With
    Selection.Find.Execute
    Dim rngAfterFind As Range
    Set rngAfterFind = Selection.Range

    If rngInitial.Start > rngAfterFind.Start Then
    If rngInitial.End < rngAfterFind.End Then
    a2 = "was wholly in a field"
    Else
    a2 = "was after a field"
    End If
    Else
    If rngInitial.End < rngAfterFind.End Then
    a2 = "was before a field"
    Else
    a2 = "was partly in a field"
    End If
    End If
    rngInitial.Select
    End Function

    Sub TESTa2()
    ' Succeeds on "Contents {TOC}Text"
    ' Fails on "Contents {TOC{SEQ}}Text"
    Dim wrd As Range
    For Each wrd In ActiveDocument.Words
    wrd.Select
    MsgBox a2
    Next wrd
    End Sub
    </pre>


  10. #10
    JustCallMeAl
    Guest

    Re: Range is in Field

    Okay, back to the drawing board.

    What is the purpose of you wanting to find out if a word is in a field? At one point, you mention:

    <hr>getting caught up in both a Contents table and an Index table. It's no fun AutoMarking words from the index table, honest!<hr>

    Is it for an AutoMarking purpose?

    I realize that this may not answer all your questions, but if it solves the problem, then at a later time the whys can be dealt with.

    The real problem here, as I see it, is to be able to ignore the field codes. The problem is that field codes have two sets of "words" within them. One represented by the property Result and the other by Code. If you are looking at the "TOC" in the field code, that is the Code. If you are looking at the generated table of contents, that's the Result.

    Anyway, how about this. Forget about the fields for now. At the beginning of your turn on ShowFieldCodes. This should then make it that your automarking ignores your field codes.

    Are you looking for words that are part of the field code definition? i.e., "TOC"?

    If so, consider:

    <pre> Dim wrd As Object

    For Each wrd In activedocument.Words

    On Error Resume Next
    MsgBox wrd.Fields(1).Code
    If Err.Number = 5941 Then
    End If

    Next wrd</pre>


  11. #11
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    Al, thanks for your time on this. I value your your insights, even 'though you look like Auntie Jack from the late sixties ABC comedy show .... (I doubt than any other Aussies here will remember Aunty Jack ....)


    <pre>Sub test()
    ' Display each word & page number in {TOC} field
    ActiveWindow.View.ShowFieldCodes = False
    ' Display only the code & switches of the {TOC} field.
    ActiveWindow.View.ShowFieldCodes = True
    Dim wrd
    For Each wrd In ActiveDocument.Words
    Debug.Print wrd.Text
    Next wrd
    End Sub
    </pre>



    >What is the purpose of you wanting to find out if a word is in a field

    The practical purpose is : I am collecting words to load into a Concordance table prior to using AutoMark. That's a good enough reason NOT to use the words of the TOC or XE of HYPERLINK or INDEX fields. On top of that I analyse each word to determine if it is "Interesting". If it is, I'll use it, and use it further: I'll load it into a Leader phrase and also into a KWIC phrase, that is, I'll employ it embedded in its surrounding words. In short, I do a whack of analysis after I've found a word, and I don't want to spend time analysing words that aren't going to be of much use in the end. You can d/l the technical stuff from <A target="_blank" HREF=http://www.vif.com/users/cgreaves/INDXRnew.htm>http://www.vif.com/users/cgreaves/INDXRnew.htm</A> if you're interested in the analysis.


    The technical side is - it ought to be possible! It seems like not such an unreasonable thing to ask: Am I inside a set of field braces?

    >At the beginning .. turn on ShowFieldCodes ... automarking ignores your field codes.

    I agree with get-it-working and then clean it up. This seems to be a reasonable solution. If I vacumn up the odd TOC code it's no big deal. My analysis for "Interesting" words will probably chuck it out immediately.

    However, this seems to present a further problem: If ShowCodes is set OFF, then I get all the text entries from the {TOC} but none of the {XE}. If ShowCodes is set ON, then I get none of the text entries from the {TOC} but all of the {XE}. Am I going crazy or what?



    <pre> On Error Resume Next
    MsgBox wrd.Fields(1).Code
    If Err.Number = 5941 Then
    End If
    </pre>



    I'll give this a try too.

    I've just run a test with a slightly better verion (boolean result) of my earlier function. A user-function to test for presence of a field really slows down the already-slow processing (index through the collection), especially when the user is me!


    <pre>Function boolInField(rngInitial As Range) As Boolean
    With Selection.Find
    .Text = "^d"
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindContinue
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    End With
    Selection.Find.Execute
    Dim rngAfterFind As Range
    Set rngAfterFind = Selection.Range
    If rngInitial.Start >= rngAfterFind.Start Then
    If rngInitial.End <= rngAfterFind.End Then
    boolInField = True
    Else
    boolInField = False
    End If
    Else
    If rngInitial.End < rngAfterFind.End Then
    boolInField = False
    Else
    boolInField = True
    End If
    End If
    rngInitial.Select
    'Sub TESTboolInField()
    'ActiveWindow.View.ShowFieldCodes = True
    'Dim wrd As Range
    'For Each wrd In ActiveDocument.Words
    ' wrd.Select
    ' MsgBox wrd.Text & " " & boolInField(wrd)
    'Next wrd
    'End Sub
    End Function
    </pre>


  12. #12
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    (sigh!) There's nothing for it then but to rewrite my old parser routine.

    <pre>
    ' Inputs: strSource As String - Holds the gigantic buffer of text to be analysed
    ' Unchanged by this procedure.
    ' lngStart As Long - Holds the pointer to the starting point for our search.
    ' Initialised by the caller prior to the first call.
    ' Updated by this procedure.
    ' When lngStart >= len(strSource) we are done.
    ' strValid As String - A series of valid characters,
    ' each of which will constitute a word-string,
    ' strNesters As String - A series of pairs of characters which define
    ' chunks of text to be ignored.
    ' For example ASC(019) and ASC(021) are the Field Code braces.
    ' while ASC(040) and ASC(041) are parentheses.
    ' Returns: STRING of characters NOT containing any one of strDelimiters and strNesters.
    ' Assumes: Nothing
    ' Side Effects: lngStart will change between calls and should NOT be managed by the caller.
    ' Tested: By the calls shown below.

    ' Method:
    ' While the stack is non-empty
    ' Loop along the string until we match top-of-stack
    ' at which time we pop the stack.
    '
    ' When the stack is empty
    ' Loop along the string examining one character at a time.
    ' When a character is found NOT belonging to strValid,
    ' we return our accumulation as the next string
    '
    </pre>



    The accompanying code is a bit buggy. I'll reexamine it tomorrow. I don't handle boundary conditions very well - If I have valid characters immediately after a field brace with no intervening space, I drop the leading character. From "{{seq}}Chris" I get "hris".
    Attached Files Attached Files

  13. #13
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    Haven't improved the code yet, but HAVE compared timings using the sweep-second hand of my office clock.

    The old code (For Each wrd in ActiveDocument.Words) takes 30 seconds to analyse the user guide.

    The new code (Function strGetNextWord) takes 20 seconds.



    Go figure! Analysing a string of text by using a Collection is 50% SLOWER than analysing it by "hand" using a string of characters.

  14. #14
    JustCallMeAl
    Guest

    Re: Range is in Field

    Chris;

    I was going through my pile of This-is-neat-I-really-must-read-this-some-day, and I found this little gem: <A target="_blank" HREF=http://www.scottm.dircon.co.uk/vbatips/word/selrange/infield.htm>How to tell if the insertion point is on a field</A>.

    I have no idea whether you have already discounted the programming tips/tricks the page talks about or not. However, having stumbled on it, I thought it may be of some use.

  15. #15
    Platinum Lounger
    Join Date
    Feb 2001
    Location
    Yilgarn region of Toronto, Ontario
    Posts
    5,453
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Range is in Field

    This is the code you showed yesterday.

    Try creating a document with just a bare-bones TOC field, looks like this underneath the field codes: { TOC }

    Then run this text macro:
    <pre>Sub TESTSelectionWithinField()
    MsgBox SelectionWithinField.Code.Text
    End Sub
    </pre>


    If you have carefully clicked in between the "O" and "C" of TOC, it will generate an error.


    The Fields.Count trick only works when the entire field is selected, as we found yesterday, and either way I'm going to get stuff back that i don't want.


    It's really strange, but the strGetNextWord I posted yesterday not only WORKS better than Fields.Count by RUNS FASTER. And is more flexible to boot.



    I do like the web site, though. I wonder if he'd mind if I stole his layout ......

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •