Insert shape at x, y on page n

W

Workgroups

I want to insert the shape on the last page of a document (whatever page #
that may be, it's variable). It's a textbox with some text in it, and it's
background is filled with a bitmap of someone's signature - it goes on the
last page in the bottom-right corner to "sign" a document. Our users "apply
a signature to the document" by clicking a little macro button that does
[essentially] this:

Dim objYouWereHere as Range

Set objYouWereHere = Selection.Range
Application.ScreenUpdating = False

'Physically move to the "last page"
Selection.EndKey Unit:=wdStory

'Position the signature textbox
With ActiveDocument.Shapes("SignatureBox")
.Top = 536
.Left = 231
End With

'Return my user to wherever they were prior to running the macro
objYouWereHere.Select
Application.ScreenUpdating = True

I'm not well versed enough in word/vba to know the answer to this; but is it
possible to programatically define the last page (maybe as a range?) in such
a way that I could insert a shape onto it at an x, y coordinate relative to
that page **without** having to move the selection? With the above
methodology, the user does end up at wherever they were prior to running the
macro, but the objYouWereHere.Select call can sometimes leave them at a new
vertical scroll position and it's a little disorienting for them.

So, before I go hunting down how to store & retreive the vertical scroll
position (similar to how I store and retrieve the selection pre & post
textbox adjustment)... is there a more "elegant" way to do this that doesn't
require I move the selection at all? Insert shape at x, y on page n,
without involving the Selection?
 
J

Jean-Guy Marcil

Workgroups was telling us:
Workgroups nous racontait que :
I want to insert the shape on the last page of a document (whatever
page # that may be, it's variable). It's a textbox with some text in
it, and it's background is filled with a bitmap of someone's
signature - it goes on the last page in the bottom-right corner to
"sign" a document. Our users "apply a signature to the document" by
clicking a little macro button that does [essentially] this:

Dim objYouWereHere as Range

Set objYouWereHere = Selection.Range
Application.ScreenUpdating = False

'Physically move to the "last page"
Selection.EndKey Unit:=wdStory

'Position the signature textbox
With ActiveDocument.Shapes("SignatureBox")
.Top = 536
.Left = 231
End With

'Return my user to wherever they were prior to running the macro
objYouWereHere.Select
Application.ScreenUpdating = True

How are you getting the shape?

Normally, when you insert the shape, you use the Anchor attribute to
position it where you want:

Dim Myshape As Shape

With ActiveDocument
Set Myshape = .Shapes.AddShape(Type:=msoShapeRectangle, _
Left:=231, Top:=536, Width:=100, Height:=50, _
Anchor:=.Paragraphs(.Paragraphs.Count).Range)
End With


--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
W

Workgroups

How are you getting the shape?

With the AddTextBox method of the ActiveDocument's Shapes collection;
similar to your example, but I was not specifying an Anchor value. Here is
the actual statement I'm using:

With ActiveDocument.Shapes.AddTextbox(msoTextOrientationHorizontal, 0, 0, _
sWIDTH_IN_INCHES * sSCREEN_PPI, sHEIGHT_IN_INCHES * sSCREEN_PPI)
.TextFrame.TextRange.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Name = "SignatureBox"
.Line.Visible = msoFalse
.ZOrder msoSendBehindText
End With

As an aside, there's something I don't understand about the Anchor
parameter. I was assuming that if you didn't supply an Anchor, it defaults
to something like... ActiveDocument.Bookmarks("\Page").Range (guessing). An
IsEqual between the "\Page" bookmark and my shape's Anchor is False, and the
Anchor isn't Nothing, so I'm not really sure what range object the textbox
is anchoring to when I don't supply an Anchor parameter to the AddTextbox
method.

In what is probably a related issue, when I assign the left and top values
to 231 and 536, respectively, anywhere within the above With block statement
(omitting an anchor value), it's placing the textbox off the visible screen
somewhere. Just after the AddTextbox method is called, it reports it's Top
as 536 and it's Left as 231 in the immediate window, but I can't see the
textbox anywhere on the document as I'm stepping through the code. So it's
at 231, 536, but relative to what I have no idea.

The weird part is that if I assign the initial Left and Top to 0, 0 in the
AddTextbox method, it inserts the textbox at the upper left corner of the
page - so why 231,536 is not a displayable location I have no idea. So once
it's at 0,0 I re-assigning the Top and Left values immediately thereafter in
a new statement; and when I do that, the textbox ends up where I want it:

With ActiveDocument.Shapes("SignatureBox")
.Top = 536
.Left = 231
End With

So I can work within that phenomenon, but I don't yet understand why it
happens.
Normally, when you insert the shape, you use the Anchor attribute to
position it where you want:

Dim Myshape As Shape

With ActiveDocument
Set Myshape = .Shapes.AddShape(Type:=msoShapeRectangle, _
Left:=231, Top:=536, Width:=100, Height:=50, _
Anchor:=.Paragraphs(.Paragraphs.Count).Range)
End With

I need the textbox to "float" independantly of the document's text contents,
and position it at a constant x,y pixel value relative to the upper-left
corner of the last page. I tried anchoring it to the last paragraph, and
while this does have the my saught-after virtue of automatically appearing
on the last page without moving the selection, it also has 2 problems: If
the number of paragraphs in my document changes, the textbox changes
vertical position. And secondly, even if the number of paragraphs were
forever constant, the last paragraph is going to be at an unpredictable,
variable veritcal position on the last page; so establishing position 231,
536 relative to the upper-left corner of the page based from a dynamically
positioned paragraph range is starting to sound like opening pandora's box
when it comes time to position the thing where I want it.

I have found that this solution isn't quite so bad:

Application.ScreenUpdating = False

Set objYouWereHere = Selection.Range
lngYourVerticalScrollPercentage =
ActiveDocument.ActiveWindow.VerticalPercentScrolled

Selection.EndKey unit:=Word.wdStory

With ActiveDocument.Shapes.AddTextbox(msoTextOrientationHorizontal, 0, 0, _
sWIDTH_IN_INCHES * sSCREEN_PPI, sHEIGHT_IN_INCHES * sSCREEN_PPI)
.TextFrame.TextRange.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Name = "SignatureBox"
.Line.Visible = msoFalse
.ZOrder msoSendBehindText
End With

With ActiveDocument.Shapes("SignatureBox")
.Top = 536
.Left = 231
End With

objYouWereHere.Select
ActiveDocument.ActiveWindow.VerticalPercentScrolled =
lngYourVerticalScrollPercentage

Application.ScreenUpdating = True
 
J

Jean-Guy Marcil

Workgroups was telling us:
Workgroups nous racontait que :
With the AddTextBox method of the ActiveDocument's Shapes collection;
similar to your example, but I was not specifying an Anchor value. Here is
the actual statement I'm using:

With ActiveDocument.Shapes.AddTextbox(msoTextOrientationHorizontal,
0, 0, _ sWIDTH_IN_INCHES * sSCREEN_PPI, sHEIGHT_IN_INCHES *
sSCREEN_PPI) .TextFrame.TextRange.ParagraphFormat.Alignment =
wdAlignParagraphCenter .Name = "SignatureBox"
.Line.Visible = msoFalse
.ZOrder msoSendBehindText
End With

As an aside, there's something I don't understand about the Anchor
parameter. I was assuming that if you didn't supply an Anchor, it
defaults to something like... ActiveDocument.Bookmarks("\Page").Range
(guessing). An IsEqual between the "\Page" bookmark and my shape's
Anchor is False, and the Anchor isn't Nothing, so I'm not really sure
what range object the textbox is anchoring to when I don't supply an
Anchor parameter to the AddTextbox method.

From the online help:
Anchor Optional Variant. A Range object that represents the text to which
the text box is bound. If Anchor is specified, the anchor is positioned at
the beginning of the first paragraph in the anchoring range. If this
argument is omitted, the anchoring range is selected automatically and the
text box is positioned relative to the top and left edges of the page.

In what is probably a related issue, when I assign the left and top
values to 231 and 536, respectively, anywhere within the above With
block statement (omitting an anchor value), it's placing the textbox
off the visible screen somewhere. Just after the AddTextbox method
is called, it reports it's Top as 536 and it's Left as 231 in the
immediate window, but I can't see the textbox anywhere on the
document as I'm stepping through the code. So it's at 231, 536, but
relative to what I have no idea.

Look at the InchesToPoints method.
The weird part is that if I assign the initial Left and Top to 0, 0
in the AddTextbox method, it inserts the textbox at the upper left
corner of the page - so why 231,536 is not a displayable location I
have no idea. So once it's at 0,0 I re-assigning the Top and Left
values immediately thereafter in a new statement; and when I do that,
the textbox ends up where I want it:
With ActiveDocument.Shapes("SignatureBox")
.Top = 536
.Left = 231
End With

So I can work within that phenomenon, but I don't yet understand why
it happens.


I need the textbox to "float" independantly of the document's text
contents, and position it at a constant x,y pixel value relative to
the upper-left corner of the last page. I tried anchoring it to the
last paragraph, and while this does have the my saught-after virtue
of automatically appearing on the last page without moving the
selection, it also has 2 problems: If the number of paragraphs in my
document changes, the textbox changes vertical position. And
secondly, even if the number of paragraphs were forever constant, the
last paragraph is going to be at an unpredictable, variable veritcal
position on the last page; so establishing position 231, 536 relative
to the upper-left corner of the page based from a dynamically
positioned paragraph range is starting to sound like opening
pandora's box when it comes time to position the thing where I want
it.

After you anchor it to the last paragraph, lock the anchor and use the
.RelativeHorizontalPosition
.RelativeVerticalPosition
properties to make sure that the position is relative to page edges.
Then set the actual position as you want it. It shouls stay put after that.

I have done this before many times and never had any problems.

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
W

Workgroups

Jean-Guy Marcil said:
After you anchor it to the last paragraph, lock the anchor and use the
.RelativeHorizontalPosition
.RelativeVerticalPosition
properties to make sure that the position is relative to page edges.
Then set the actual position as you want it. It shouls stay put after
that.

I have done this before many times and never had any problems.

Ah ok, I understand it now - this is a VERY good solution! I anchored the
textbox to the last paragraph of the paragraphs collection, set .LockAnchor
= True & set .RelativeHorizToPage & .RelativeVertToPage = True & assigned
x,y coordinates (relative to page this time, instead of margins). I also
did not understand the meaning of LockAnchor - I incorrectly believed it
behaved in a reverse fashion, so I had attempted setting it to False (I
should have been using *True*).

So now the textbox is always on my last page (because it is anchored to the
last paragraph), and always in the right spot thanks to the RelativeToPage
pixel positioning. Even if the user makes a new page or removes the last
page, the textbox is always in the correct place automatically. And I don't
have to alter the selection to accomplish this - I'm very pleased! :) Thank
you for your help.
 
J

Jean-Guy Marcil

Workgroups was telling us:
Workgroups nous racontait que :
Ah ok, I understand it now - this is a VERY good solution! I
anchored the textbox to the last paragraph of the paragraphs
collection, set .LockAnchor = True & set .RelativeHorizToPage &
.RelativeVertToPage = True & assigned x,y coordinates (relative to
page this time, instead of margins). I also did not understand the
meaning of LockAnchor - I incorrectly believed it behaved in a
reverse fashion, so I had attempted setting it to False (I should
have been using *True*).
So now the textbox is always on my last page (because it is anchored
to the last paragraph), and always in the right spot thanks to the
RelativeToPage pixel positioning. Even if the user makes a new page
or removes the last page, the textbox is always in the correct place
automatically. And I don't have to alter the selection to accomplish
this - I'm very pleased! :) Thank you for your help.

You're welcome!

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 

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