Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MS Word function to append a Range to a document

Suppose I want to add some text at the end of a document and immediately access it as a Range object so I can set some properties of it without affecting the preceding text. Ideally, the Range.InsertAfter method would return a Range object which would be perfect for this, but it doesn't.

It irks me that Word must know perfectly well what range defines the result of calling InsertAfter, but on the face of it, I need to calculate it "after the fact" from the length of the inserted text, or in some other way.

So I've devised a simple-minded work-around. In pseudo-code (actually it's Delphi code but I hope that won't discourage VBA answers) what I do is this

ARange := Document.Range
ARange.Text := 'AAA'

AEnd := ARange.End - 1        // AEnd is an integer
ARange.SetRange(AEnd, AEnd)
ARange.Text := 'XXX'
ARange.Bold := True

and it seems that I can carry on indefinitely adding blocks of text to the end of a document by repeating the second block of code.

The line

ARange.SetRange(AEnd, AEnd)

as I understand it, seems to construct a new Range at the end of the existing one (unlike calling Collapse on an existing range), and works fine for the simple test cases I've tried. But it leaves me wondering whether I'm missing a trick somewhere. Is there a more direct way to append a range to a document and get a reference to it?

PS: I should have been a bit clearer that I'm trying to do this without using the Selection object (for a variety of reasons, including the fact that you can only have one of them at at time).

like image 899
MartynA Avatar asked Jan 22 '16 17:01

MartynA


2 Answers

There are various ways to get the Range at the end of the document. You've discovered one, but as you say, it's somewhat circuitous. My preference:

Word.Range rngEndOfDoc = Document.Content; 
//Content returns a Range object and is a property, not a method like Range()
rngEndOfDoc.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
rngEndOfDoc.Text = "Text at the end of the document";

Collapsing the Range is conceptually like pressing the Right (or Left) arrow key when you have a selection. So rngEndOfDoc becomes a "point" rather than containing the entire content of the main body of the document.

FWIW I can never think of a situation when I'd use EndKey for this (emulate user actions) and I'd only change the Selection when I want to leave the user at the end of the document so that he can start typing at that location.

like image 186
Cindy Meister Avatar answered Oct 24 '22 06:10

Cindy Meister


With thanks for the three admirable answers from others, I thought I would add my own. The following are two versions of the function that I started out wishing Word provided natively, returning an appended range.

The first version uses the MS Word objects in the MS Word Type Library import unit that traditionally comes with Delphi (e.g. the Word2000.Pas one), and uses "early binding" automation, while the second version does the same thing using late binding.

function AppendRange(InputRange : Range) : Range;
var
  Direction : OleVariant;
begin
  Result := InputRange;
  Direction := wdCollapseEnd;
  Result.Collapse(Direction);
end;

function AppendRangeLB(InputRange : OleVariant) : OleVariant;
begin
  Result := InputRange;
  Result.Collapse(wdCollapseEnd);
end;

Usage is e.g.

AppendedRange := AppendRange(ExistingRange);
AppendedRange.Text := 'YYY';
like image 28
MartynA Avatar answered Oct 24 '22 06:10

MartynA