Range and Tables

  • Thread starter Lachezar Parvov
  • Start date
L

Lachezar Parvov

Hi. I use this:

Public AllTags As New Collection
Public AllPoss As New Collection

Set RegularExpressionObject = New RegExp

With RegularExpressionObject
..Pattern = "\[\[|\]\]|\["
..IgnoreCase = True
..Global = True
End With

Set Matches = RegularExpressionObject.Execute(doc.Range.Text)

For Each Match In Matches

AllTags.Add (Match.Value)

AllPoss.Add (Match.FirstIndex)

Next

In other function when I want to delete some range:
Dim rang As Range

Set rang = doc.Range

rang.SetRange AllPoss(k - 1), AllPoss(k)

rang.Delete

It is ok but if I have tables in word document the range is other.

Example: If original postion is 30, This code Match.FirstIndex return 32
when position 30 is in Table. If we have not table Match.FirstIndex return
30. If wi have table original postion is 30 but Match.FirstIndex return 32.
Pleace help me. How I can get original postion in table?
 
K

Klaus Linke

Hi Lachezar,

Both end-of-cell-markers and end-of-row-markers appear as Chr(13) &
Chr(7) -- that is, as two characters -- in your string.
In the Word doc, though, they only are one "Character" each (that is, they
occupy a range of length=1).

The solution is pretty simple: Replace the combination Chr(13) & Chr(7) with
a single character before you feed it to RegExp.
Say, Chr(7).
sText = doc.Range.Text
sText = Replace(sText, Chr(13) & Chr(7), Chr(7))
Set Matches = RegularExpressionObject.Execute(sText)



Two other things in a Word document can mess up the correspondence between
"string characters" and "Word Object Model characters" too though, and they
aren't as easily dealt with:

One is anchors for inline shapes, another fields.

If you have either in your document(s), it's going to be difficult to
handle.

Regards,
Klaus


Lachezar Parvov said:
Hi. I use this:

Public AllTags As New Collection
Public AllPoss As New Collection

Set RegularExpressionObject = New RegExp

With RegularExpressionObject
.Pattern = "\[\[|\]\]|\["
.IgnoreCase = True
.Global = True
End With

Set Matches = RegularExpressionObject.Execute(doc.Range.Text)

For Each Match In Matches

AllTags.Add (Match.Value)

AllPoss.Add (Match.FirstIndex)

Next

In other function when I want to delete some range:
Dim rang As Range

Set rang = doc.Range

rang.SetRange AllPoss(k - 1), AllPoss(k)

rang.Delete

It is ok but if I have tables in word document the range is other.

Example: If original postion is 30, This code Match.FirstIndex return 32
when position 30 is in Table. If we have not table Match.FirstIndex return
30. If wi have table original postion is 30 but Match.FirstIndex return
32.
Pleace help me. How I can get original postion in table?
 
L

Lachezar Parvov

thnak you.
I forogt to say that i can have any object (TextBox and other). What must I
Add to this function Replace(sText, Chr(13) & Chr(7), Chr(7)) except Chr(13)
and Chr(7)?

Sorry for my bad English....:(

Thnak you again.

Klaus Linke said:
Hi Lachezar,

Both end-of-cell-markers and end-of-row-markers appear as Chr(13) &
Chr(7) -- that is, as two characters -- in your string.
In the Word doc, though, they only are one "Character" each (that is, they
occupy a range of length=1).

The solution is pretty simple: Replace the combination Chr(13) & Chr(7) with
a single character before you feed it to RegExp.
Say, Chr(7).
sText = doc.Range.Text
sText = Replace(sText, Chr(13) & Chr(7), Chr(7))
Set Matches = RegularExpressionObject.Execute(sText)



Two other things in a Word document can mess up the correspondence between
"string characters" and "Word Object Model characters" too though, and they
aren't as easily dealt with:

One is anchors for inline shapes, another fields.

If you have either in your document(s), it's going to be difficult to
handle.

Regards,
Klaus


Lachezar Parvov said:
Hi. I use this:

Public AllTags As New Collection
Public AllPoss As New Collection

Set RegularExpressionObject = New RegExp

With RegularExpressionObject
.Pattern = "\[\[|\]\]|\["
.IgnoreCase = True
.Global = True
End With

Set Matches = RegularExpressionObject.Execute(doc.Range.Text)

For Each Match In Matches

AllTags.Add (Match.Value)

AllPoss.Add (Match.FirstIndex)

Next

In other function when I want to delete some range:
Dim rang As Range

Set rang = doc.Range

rang.SetRange AllPoss(k - 1), AllPoss(k)

rang.Delete

It is ok but if I have tables in word document the range is other.

Example: If original postion is 30, This code Match.FirstIndex return 32
when position 30 is in Table. If we have not table Match.FirstIndex return
30. If wi have table original postion is 30 but Match.FirstIndex return
32.
Pleace help me. How I can get original postion in table?
 
K

Klaus Linke

I forogt to say that i can have any object (TextBox and other).
What must I Add to this function Replace(sText, Chr(13) & Chr(7),
Chr(7)) except Chr(13) and Chr(7)?

As I already said, in both cases the work-around won't be as simple (or
quick).

IIRC (which may not be the case), the anchors for inline shapes occupy one
"Character" in the Word Object model, but that range of length=1 does not
contain any text, so it won't appear in the string at all.
The work-around would be to loop through all inline shapes, and add a
character in the string at the appropriate position.

With fields, it's even messier.
In the Word Object Model, you slways have the field code as well as the
field result in the Range, and both are separated by another range of
length=1 (...again, IIRC).
In the string, you have either one or the other, depending on your settings
for rng.TextRetrievalMode.IncludeFieldCodes.

And if that isn't bad enough, there are lots of different possible fields,
and some types of fields may only have the Code part, and no Result.
But that's documented nowhere, so you're on your own programming a
work-around.

I once tried, but gave up after the code was more than several hundred lines
(... pretty darn slow too, and buggy to boot).

Maybe better look for another way to solve whatever it is you want to do.
Word's own "Find/Replace" with wildcards might be such another way.

Regards,
Klaus
 
K

Klaus Linke

Just to show you the kind of string you would need to built to use RegEx and
then find the matching Ranges:
Use the code below on a small sample text with a small table, an inline
shape, and a field.
It inserts the string at the end of your current document.

With that string, the i-th character would match the document content's
range from i to i+1.

I used a special character for the anchors, and the currency sign ¤ for
end-of-cell-markers.
When I tried Chr(7) for the latter, I found Word deletes them if you output
the string into the Word document.

The simple approach taken by this macro would be too slow though on
documents of more than a few lines, and defeat all speed benefits you want
to gain by using RegEx in the first place.

Klaus


Dim rngChar As Range
Dim sOut As String
Dim i As Long
Set rngChar = ActiveDocument.Characters.First
rngChar.TextRetrievalMode.IncludeFieldCodes = True
For i = 1 To ActiveDocument.Content.End
rngChar.SetRange Start:=i, End:=i + 1
Select Case Len(rngChar.Text)
Case 0
sOut = sOut & ChrW(&HFFFD) ' embedded object?
Case 1
sOut = sOut & rngChar.Text ' unproblematic characters
Case 2
sOut = sOut & ChrW(&HA4) ' end-of-cell/row markers?
Case Else
MsgBox "Unexpected!"
End Select
Next i
ActiveDocument.Content.InsertAfter sOut
 
K

Klaus Linke

BTW, I just noticed that doc.Range.Text does contain an ASCII 1 in place for
each inline shape anchor.
The ASCII 7's of the end-of-cell markers, again, get lost if you put the
string into a Word document... but they are there in doc.Range.Text.

I don't remember why I had to handle the anchors... Or maybe it's an issue
that has been fixed.
In Word2007 and the docx format there's a new problem though:
The anchors now show as an ordinary slash... There was a discussion in this
group recently, March 13, "Counting occurence of specific character in
selection".

Klaus
 

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