ahha

Word UDF _Word_DocRangeSet affecting a different range

40 posts in this topic

#1 ·  Posted

Okay this is likely due to my not properly understanding objects.

I'm using _Word_DocRangeSet to extend a range (in this case to the end of a line).

The issue I've encountered is that extending one range seems to affect another range.

It may be that an object can't be assigned or equated.

In any event the program and test file (place in the same directory) illustrate the issue.

Test 1 - shows the documentation for _Word_DocRangeSet correctly shows how the range is extended and the assigned result is extended.  No problem here just part of my learning.

Test 2 - like Test 1 but no assignment of the result from  _Word_DocRangeSet is needed.  Again correct and my learning.

Test 3 - here is where the issue is.  After an assignment to a new object the old one seems to be affected by _Word_DocRangeSet.  This I don't understand (perhaps the assignment is really a namespace pool and points to the same structure like aliases <-- wild guess).

Test 4 - shows that using .Select can extend the range and leave the original range alone.

Any hints/pointers on what's going on appreciated.

Thanks

WordRangeTesting v1c.au3

Test for WordRangeTesting v1c.docx

Share this post


Link to post
Share on other sites



#2 ·  Posted

200 lines of code - that's kind of a huge reproducer script :)
Can you please strip it down to let's say 10 lines so we can concentrate on the lines causing the "problem"?

I just checked and the Word UDF does not use ByRef for the function parameters. So you only get variables set/changed when assigning the return value of a function.

BTW: Can you please add some information about the Office and AutoIt version you run?


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#3 ·  Posted

AutoIt version 3.3.14.2

Office version 2007   (12.0.6770.50) SP3 MSO (12.0.6772.5000)

Most of the lines are just toggles to turn bold on/off for a range.

Cut down to show problem only.  Use same test file from above.

Thanks

 

WordRangeTesting v1d.au3

Share this post


Link to post
Share on other sites

#4 ·  Posted

Will check as soon as I return to my office.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#5 ·  Posted

After some playing with your script I can only say: WAD - works as designed.

We create a Range object in Word by _Word_DocFind and assign it to Variable A. Then we copy variable A to variable B. So now both variables point to the same Range object. When we extend this Word Range Object only the starting and ending point properties get changed - the object is still the same. So variables A and B still point to the same Range Object with the new starting and ending Point.

You need to CREATE a new Range object as shown in my example code:

#include <MsgBoxConstants.au3>
#include <Word.au3>

Global $oWord = _Word_Create()
Global $sTestfile = "\Test for WordRangeTesting v1d.docx"
Global $oDoc = _Word_DocOpen($oWord, @ScriptDir & $sTestfile)
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "ERROR", "Error opening file = '" & @ScriptDir & $sTestfile & "'" & @CRLF & "@error = " & @error & ", @extended = " & @extended)

Global $oRange1 = _Word_DocFind($oDoc, "003")
MsgBox($MB_SYSTEMMODAL, "", "Range1 after _Word_DocFind: " & $oRange1.Characters.Count & " characters!")
$oRange1.Underline = True
MsgBox($MB_SYSTEMMODAL, "", "Range1 underlined!")

Global $oRangeTemp = $oDoc.Range($oRange1.Start, $oRange1.End); <== Create a new range object with start/end of $oRange1
MsgBox($MB_SYSTEMMODAL, "", "Range1 = RangeTemp? " & $oRange1.Isequal($oRangeTemp))
_Word_DocRangeSet($oDoc, $oRange1, Default, Default, $wdParagraph, 2) ; extend range to and including paragraph character - TRYING to leave $oRingeFind alone
MsgBox($MB_SYSTEMMODAL, "", "Range1 = RangeTemp? " & $oRange1.Isequal($oRangeTemp))
MsgBox($MB_SYSTEMMODAL, "", "Range1 " & $oRange1.Characters.Count & " characters!")
MsgBox($MB_SYSTEMMODAL, "", "RangeTemp " & $oRangeTemp.Characters.Count & " characters!")
$oRange1.Bold = True
MsgBox($MB_SYSTEMMODAL, "", "Range1 bold!")
$oRangeTemp.Italic = True
MsgBox($MB_SYSTEMMODAL, "", "RangeTemp italic!")

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#6 ·  Posted

water,

Thanks.  Still playing with it.  Part of my confusion I believe was based on my using arrays where you can copy array $A by assignment like $B = $A.  (As explained here:  https://www.autoitscript.com/forum/topic/115345-copy-array/ )

So if I understand correctly an assignment of a variable to an object is just another pointer to the same object and as you stated earlier "So you only get variables set/changed when assigning the return value of a function. "

I was not aware of this construct:

Global $oRangeTemp = $oDoc.Range($oRange1.Start, $oRange1.End); <== Create a new range object with start/end of $oRange1

So I'm still unclear how this is a return value of a function as it appears to be an assignment.

I'll play more with it when I get back from work. 

Thanks.

Share this post


Link to post
Share on other sites

#7 ·  Posted

1 hour ago, ahha said:

So if I understand correctly an assignment of a variable to an object is just another pointer to the same object

Correct.

1 hour ago, ahha said:

as you stated earlier "So you only get variables set/changed when assigning the return value of a function. "

So I'm still unclear how this is a return value of a function as it appears to be an assignment.

Forget this. I was on the wrong track when analyzing the "problem".

To sum it up:
_Word_DocFind returns a range which is then assigned to a variable. When you assign this avariable to another variable you end up with two variables pointing to the same range. Modifying the range takes effect for both variables.
The only way to save the Range before you modify it is to create a new range the way i described above.

Hope I could shed some light onto the subject.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#8 ·  Posted

water,

Thanks.  I'm still struggling on some questions regarding syntactical equivalents between VBA and doing it in Autoit and will get back when I have narrowed them down.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

water,

Okay I'm trying to copy with formatting and I've got something wrong.  This is not a range question so if I should start another topic let me know.

#AutoIt3Wrapper_run_debug_mode=Y    ;use this to debug in console window <--- LOOK

#include <MsgBoxConstants.au3>
#include <Word.au3>

$oWord = _Word_Create()     ;Create application object
$testfile = @ScriptDir & "\Test for WordRangeTesting v1f.docx"
$oDoc = _Word_DocOpen($oWord, $testfile, Default, Default, True)    ;put test file in same directory as script
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "ERROR", "Error opening file = '" & $testfile & "'" & @CRLF & "@error = " & @error & ", @extended = " & @extended)

$oRangeFind1 = _Word_DocFind($oDoc, "little", Default, Default, True)
$oRangeFind2 = _Word_DocFind($oDoc, "fleece", Default, Default, True)
$oRangeFind3 = _Word_DocFind($oDoc, "everywhere", Default, Default, True)

_Word_DocFindReplace($oDoc, "001", $oRangeFind1.Text)
_Word_DocFindReplace($oDoc, "002", $oRangeFind2.Text)
_Word_DocFindReplace($oDoc, "003", $oRangeFind3.Text)
Pause("Only text found and replaced.")

;now try with formatting
_Word_DocFindReplace($oDoc, "005", $oRangeFind1.FormattedText)
_Word_DocFindReplace($oDoc, "006", $oRangeFind2.FormattedText)
_Word_DocFindReplace($oDoc, "007", $oRangeFind3.FormattedText)
Pause("Text with formatting found and replaced.  Formatting NOT being picked up.  Why not?")


;----------------- functions --------------------

Func    Pause($string)
        MsgBox($MB_SYSTEMMODAL, "DEBUG", $string)
EndFunc

Thanks

Test for WordRangeTesting v1f.docx

Edited by ahha

Share this post


Link to post
Share on other sites

#10 ·  Posted

That's because the function only replaces text and clears the formatting before the replace is being done.
See this two lines in the UDF:

$oFind.ClearFormatting()
$oFind.Replacement.ClearFormatting()

 


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#11 ·  Posted

Thanks - now trying to figure it out.  I've tried copying the range to the new location using .InsertAfter and it appears to clear the formatting, so I guess I'm stuck.  Do you happen to know what operation/function can copy the formatting so that I can paste it into to a different location with the formatting maintained?

Thanks

Share this post


Link to post
Share on other sites

#12 ·  Posted

I would try:

$oSourceRange.Copy()
$oTargetRange.Paste()

as described here: https://msdn.microsoft.com/VBA/Word-VBA/articles/range-copy-method-word


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#13 ·  Posted

water,

From another post where I was using .Copy which was shown as not reliable you suggested using .Text to get the contents (which is far superior and faster) - so I was trying to avoid .Copy.  So I found the .FormattedText and thought it would work.  Thus my question about what functions/operations might maintain formatting.   Is it possible to replace one range with another?  I can't seem to get .Replacement to work.

https://msdn.microsoft.com/en-us/vba/word-vba/articles/selection-formattedtext-property-word

https://msdn.microsoft.com/en-us/library/office/aa211953(v=office.11).aspx

 

 

Share this post


Link to post
Share on other sites

#14 ·  Posted

$oRangeFind1 = _Word_DocFind($oDoc, "little", Default, Default, True)
$oRangeFind2 = _Word_DocFind($oDoc, "005", Default, Default, True)
$oRangeFind2.FormattedText = $oRangeFind1.FormattedText

Untested: Should replace text and formatting of "005" with text and formatting of "little".


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

water,

I can't seem to get your .FormattedText to work although one would think it should.  The code below shows one approach of saving font properties but the problem is I don't know all the .Font properties and can't seem to find a reference that lists them all.   I next tried Duplicating the font ($oldFont = $oRangeFind3.Font.Duplicate) but assigning it does not work although it would seem that if you can save the font properties you should be able to apply them.  Any help appreciated.

#AutoIt3Wrapper_run_debug_mode=Y    ;use this to debug in console window <--- LOOK

#include <MsgBoxConstants.au3>
#include <Word.au3>

$oWord = _Word_Create()     ;Create application object
$testfile = @ScriptDir & "\Test for WordRangeTesting v1f.docx"
$oDoc = _Word_DocOpen($oWord, $testfile, Default, Default, True)    ;put test file in same directory as script
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "ERROR", "Error opening file = '" & $testfile & "'" & @CRLF & "@error = " & @error & ", @extended = " & @extended)

$oRangeFind1 = _Word_DocFind($oDoc, "everywhere", Default, Default, True)   ;everywhere is bold
$oRangeFind2 = _Word_DocFind($oDoc, "005", Default, Default, True)

;see https://msdn.microsoft.com/en-us/vba/word-vba/articles/font-object-word
;https://msdn.microsoft.com/VBA/Word-VBA/articles/object-model-word-vba-reference

;save
$oldFontName = $oRangeFind1.Font.Name
$oldFontSize = $oRangeFind1.Font.Size
$oldFontBold = $oRangeFind1.Font.Bold

;operation
$oRangeFind2.Text = $oRangeFind1.Text

;restore
$oRangeFind2.Font.Name = $oldFontName
$oRangeFind2.Font.Size = $oldFontSize
$oRangeFind2.Font.Bold = $oldFontBold

Pause("save/restore")

;try another approach

$oRangeFind3= _Word_DocFind($oDoc, "little", Default, Default, True)    ;little is underlined
$oRangeFind4 = _Word_DocFind($oDoc, "007", Default, Default, True)

;from https://stackoverflow.com/questions/1739729/word-2007-vba-to-insert-text
$oldFont = $oRangeFind3.Font.Duplicate      ;save the format/font of the source

$oRangeFind4.Text = $oRangeFind3.Text

$oRangeFind4.Font = $oldFont    ;does not work! is there a way to apply the saved font??
Pause("$oRangeFind2.Font = $oldFont")

;----------------- functions --------------------

Func    Pause($string)
        MsgBox($MB_SYSTEMMODAL, "DEBUG", $string)
EndFunc

 

Test for WordRangeTesting v1f.docx

Edited by ahha
Typo

Share this post


Link to post
Share on other sites

#16 ·  Posted

Can't test at the moment.
But maybe the PasteAndFormat method (https://msdn.microsoft.com/de-de/vba/word-vba/articles/range-pasteandformat-method-word does what you are looking for.
As type I suggest to use wdFormatOriginalFormatting (https://msdn.microsoft.com/de-de/vba/word-vba/articles/wdrecoverytype-enumeration-word)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#17 ·  Posted

Water,

Tried   $oRangeFind4.PasteAndFormat.wdFormatOriginalFormatting

and get ==> The requested action with this object has failed.:

So my assumption is my expression is wrong.  Tried several others and nothing works so far.  Will keep trying.

 

Share this post


Link to post
Share on other sites

#18 ·  Posted

Should be:

Global $wdFormatOriginalFormatting = 16 ; Preserves original formatting of the pasted material.
$oRangeFind4.PasteAndFormat($wdFormatOriginalFormatting)

wdFormatOriginalFormatting is a parameter to the PasteAndFormat method.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#19 ·  Posted

water,

The .PasteAndFormat uses the .Copy contents correct?  And .Copy doesn't it use the clipboard?  I ask because I was trying to do it without using the clipboard (which is not consistent). 

Is there any way of applying a stored font/format to a range?

$oldFont = $oRangeFind3.Font.Duplicate      ;save the format/font of the source

$oRangeFind4.Text = $oRangeFind3.Text

$oRangeFind4.Font = $oldFont    ;does not work! is there a way to apply the saved font??

Share this post


Link to post
Share on other sites

#20 ·  Posted

water,

Does .Copy return any error codes?

From here: https://msdn.microsoft.com/VBA/Word-VBA/articles/range-copy-method-word

It does not show any.  I ask because the ClipPut and ClipGet do return error codes so one can check that they worked properly.  On the other hand I'm trying to make sure .Copy worked or is .Copy guaranteed to work?

Thanks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • ahha
      By ahha
      Okay I've hacked down a large program to illustrate the problem I'm having.
      I'm using the built-in Word UDF (which is great) and am finding a range and then copying it to the clipboard and sticking it in an array for viewing.
      Then extending the range and again copying it to a clipboard and sticking it into the array.
      It seems to drop the ranges randomly.  I can't figure out what I'm doing wrong (or if there's a better way to get a range into a variable).
      Run the program with the test file and you'll see entries being dropped (put test file in same directory as the program).
      Any pointers or help much appreciated.
      Hacked down program for testing Range extend and copy v3c.au3
      Test for Range Copy v1a.docx
    • Servant
      By Servant
      I tried a lot of techniques but still have no luck..
      How can I delete the second sentence until the last sentence of a set paragraph range on a Microsoft Word document?
      #include <Word.au3> Global $oWord, $oDoc $oWord = _Word_Create() $oDoc = _Word_DocGet($oWord, 1) Global Const $Count = $oDoc.Paragraphs.Count For $i = 0 To $Count - 1    $oRange = _Word_DocRangeSet($oDoc, -1, $wdParagraph, $i, $wdParagraph, 1)    ; Here will be placed the missing code Next Sample of the beginning of a Word document:
      This is a sentence 1. This is a sentence 2. This is a sentence 3. This is a sentence 4. This is a sentence 5. This is a sentence 6. This is a sentence 7. This is a sentence 8. This is a sentence 9. Sample of the final result:
      This is a sentence 1. This is a sentence 4. This is a sentence 7.
    • Servant
      By Servant
      Is there a way to get the style of a set range on a Microsoft Word document?
      If there is, then how?