Cut and paste Visio shape in macro
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I'm trying to write a VBA macro that builds a basic diagram from data and certain template shapes (held on a separate page). While I can cut and paste successfully, I seem to be unable to reference the new shape after I do this. I can relocate the shape before I cut and paste it, but if I try to do anything after the fact, I hit a run-time error. There are various reasons why I might need to move / update the objects later, so I need to be able to subsequently reference them.
My code is as follows:
Dim Shape as Visio.Shape
Dim ShapeID as Integer
‘copy shape from template page 2, ID 12
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-2").Shapes.ItemFromID(12).Duplicate
ShapeID = Shape.ID
MsgBox ("Created shape ID: " & ShapeID)
'Now relocate the shape appropriately
currentX = startX + (Count * xSpacing)
currentY = startY
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
Shape.Cut
'Now go to page 1 and paste the object
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
‘*** THE FOLLOWING LINE THAT DOESN’T WORK ***
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-1").Shapes.ItemFromID(ShapeID)
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
If I run the above, I get the error "Invalid sheet identifier" at the highlighted line (the shape is pasted successfully). If I cut this line out, I get "an exception occurred" on the following line, so it looks like I've lost my reference to the object.
vba visio visio-vba
add a comment |
I'm trying to write a VBA macro that builds a basic diagram from data and certain template shapes (held on a separate page). While I can cut and paste successfully, I seem to be unable to reference the new shape after I do this. I can relocate the shape before I cut and paste it, but if I try to do anything after the fact, I hit a run-time error. There are various reasons why I might need to move / update the objects later, so I need to be able to subsequently reference them.
My code is as follows:
Dim Shape as Visio.Shape
Dim ShapeID as Integer
‘copy shape from template page 2, ID 12
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-2").Shapes.ItemFromID(12).Duplicate
ShapeID = Shape.ID
MsgBox ("Created shape ID: " & ShapeID)
'Now relocate the shape appropriately
currentX = startX + (Count * xSpacing)
currentY = startY
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
Shape.Cut
'Now go to page 1 and paste the object
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
‘*** THE FOLLOWING LINE THAT DOESN’T WORK ***
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-1").Shapes.ItemFromID(ShapeID)
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
If I run the above, I get the error "Invalid sheet identifier" at the highlighted line (the shape is pasted successfully). If I cut this line out, I get "an exception occurred" on the following line, so it looks like I've lost my reference to the object.
vba visio visio-vba
add a comment |
I'm trying to write a VBA macro that builds a basic diagram from data and certain template shapes (held on a separate page). While I can cut and paste successfully, I seem to be unable to reference the new shape after I do this. I can relocate the shape before I cut and paste it, but if I try to do anything after the fact, I hit a run-time error. There are various reasons why I might need to move / update the objects later, so I need to be able to subsequently reference them.
My code is as follows:
Dim Shape as Visio.Shape
Dim ShapeID as Integer
‘copy shape from template page 2, ID 12
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-2").Shapes.ItemFromID(12).Duplicate
ShapeID = Shape.ID
MsgBox ("Created shape ID: " & ShapeID)
'Now relocate the shape appropriately
currentX = startX + (Count * xSpacing)
currentY = startY
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
Shape.Cut
'Now go to page 1 and paste the object
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
‘*** THE FOLLOWING LINE THAT DOESN’T WORK ***
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-1").Shapes.ItemFromID(ShapeID)
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
If I run the above, I get the error "Invalid sheet identifier" at the highlighted line (the shape is pasted successfully). If I cut this line out, I get "an exception occurred" on the following line, so it looks like I've lost my reference to the object.
vba visio visio-vba
I'm trying to write a VBA macro that builds a basic diagram from data and certain template shapes (held on a separate page). While I can cut and paste successfully, I seem to be unable to reference the new shape after I do this. I can relocate the shape before I cut and paste it, but if I try to do anything after the fact, I hit a run-time error. There are various reasons why I might need to move / update the objects later, so I need to be able to subsequently reference them.
My code is as follows:
Dim Shape as Visio.Shape
Dim ShapeID as Integer
‘copy shape from template page 2, ID 12
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-2").Shapes.ItemFromID(12).Duplicate
ShapeID = Shape.ID
MsgBox ("Created shape ID: " & ShapeID)
'Now relocate the shape appropriately
currentX = startX + (Count * xSpacing)
currentY = startY
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
Shape.Cut
'Now go to page 1 and paste the object
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
‘*** THE FOLLOWING LINE THAT DOESN’T WORK ***
Set Shape = Application.ActiveDocument.Pages.ItemU("Page-1").Shapes.ItemFromID(ShapeID)
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinX).FormulaForceU = "" & currentX & " mm"
Shape.CellsSRC(visSectionObject, visRowXFormOut, visXFormPinY).FormulaForceU = "" & currentY & " mm"
If I run the above, I get the error "Invalid sheet identifier" at the highlighted line (the shape is pasted successfully). If I cut this line out, I get "an exception occurred" on the following line, so it looks like I've lost my reference to the object.
vba visio visio-vba
vba visio visio-vba
edited Jan 29 at 19:24
halfer
14.8k759118
14.8k759118
asked Jan 4 at 17:08
David FultonDavid Fulton
292310
292310
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
A shape's ID is only unique to its page, so the new shape that you paste into Page-1 will receive a new ID and hence the error that you're receiving. Although the Duplicate method returns a shape reference to the new shape, Paste does not so you need to get a reference to it by other means - either assuming something about the window selection (as per Surrogate's answer) or by index:
Dim shp As Visio.Shape
Dim pag As Visio.Page
Set pag = ActivePage 'or some alternative reference to Page-1
Set shp = pag.Shapes.ItemU(pag.Shapes.Count)
Debug.Print shp.Index
A more usual workflow would be to generate masters (in a stencil document) and then drop those masters rather than copying and pasting between pages, but your scenario may require a different approach.
I'll add this link as useful reference for dealing with Index and ID properties:
- Working with Shape Objects
[Update]
@Jon Fournier's comment below is quite right that the above does make assumptions. For example, if the DisplayLevel cell in the source shape is less than the top most shape then it will be pasted into the page's shapes collection at the corresponding index and so count won't return the correct shape ID.
An alternative approach might be to listen to the ShapeAdded event on Pages (or Page). The following is a slight adaption from the IsInScope example in the docs, with code placed ThisDocument. This allows you to top and tail your code in an event scope ID pair that you can inspect when handling the ShapeAdded event:
Private WithEvents vPags As Visio.Pages
Private pastedScopeID As Long
Public Sub TestCopyAndPaste()
Dim vDoc As Visio.Document
Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required
Dim srcPag As Visio.Page
Set srcPag = vDoc.Pages.ItemU("Page-2")
Dim targetPag As Visio.Page
Set targetPag = vDoc.Pages.ItemU("Page-1")
Dim srcShp As Visio.Shape
Set srcShp = srcPag.Shapes.ItemFromID(12)
Set vPags = vDoc.Pages
pastedScopeID = Application.BeginUndoScope("Paste to page")
srcShp.Copy
targetPag.Paste
Application.EndUndoScope pastedScopeID, True
End Sub
Private Sub vPags_ShapeAdded(ByVal shp As IVShape)
If shp.Application.IsInScope(pastedScopeID) Then
Debug.Print "Application.CurrentScope " & Application.CurrentScope
Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name
DoSomethingToPastedShape shp
Else
Debug.Print "Application.CurrentScope " & Application.CurrentScope
End If
End Sub
Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape)
If Not shp Is Nothing Then
shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)"
End If
End Sub
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
add a comment |
Of course you get error "Invalid sheet identifier" ! Because at "Page-1" you can have shape with ShapeID, which you defined for shape placed at "Page-2".
You can paste shape and after this step define selected shape.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
' You can define this variable as shape which is selected
Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Why you use variable two times ?
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
add a comment |
I haven’t found a great way to handle this. I have a method that will paste the clipboard to a page and return any new shapes, by listing all shape ids before and after pasting, and then returning new shapes.
If speed is a big issue for me I’ll usually paste to an empty hidden page, do whatever I have to on that page, then cut and paste in place on the destination page. If you need to glue with other shapes this wouldn’t really work, but when it makes sense I use this logic.
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54043283%2fcut-and-paste-visio-shape-in-macro%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
A shape's ID is only unique to its page, so the new shape that you paste into Page-1 will receive a new ID and hence the error that you're receiving. Although the Duplicate method returns a shape reference to the new shape, Paste does not so you need to get a reference to it by other means - either assuming something about the window selection (as per Surrogate's answer) or by index:
Dim shp As Visio.Shape
Dim pag As Visio.Page
Set pag = ActivePage 'or some alternative reference to Page-1
Set shp = pag.Shapes.ItemU(pag.Shapes.Count)
Debug.Print shp.Index
A more usual workflow would be to generate masters (in a stencil document) and then drop those masters rather than copying and pasting between pages, but your scenario may require a different approach.
I'll add this link as useful reference for dealing with Index and ID properties:
- Working with Shape Objects
[Update]
@Jon Fournier's comment below is quite right that the above does make assumptions. For example, if the DisplayLevel cell in the source shape is less than the top most shape then it will be pasted into the page's shapes collection at the corresponding index and so count won't return the correct shape ID.
An alternative approach might be to listen to the ShapeAdded event on Pages (or Page). The following is a slight adaption from the IsInScope example in the docs, with code placed ThisDocument. This allows you to top and tail your code in an event scope ID pair that you can inspect when handling the ShapeAdded event:
Private WithEvents vPags As Visio.Pages
Private pastedScopeID As Long
Public Sub TestCopyAndPaste()
Dim vDoc As Visio.Document
Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required
Dim srcPag As Visio.Page
Set srcPag = vDoc.Pages.ItemU("Page-2")
Dim targetPag As Visio.Page
Set targetPag = vDoc.Pages.ItemU("Page-1")
Dim srcShp As Visio.Shape
Set srcShp = srcPag.Shapes.ItemFromID(12)
Set vPags = vDoc.Pages
pastedScopeID = Application.BeginUndoScope("Paste to page")
srcShp.Copy
targetPag.Paste
Application.EndUndoScope pastedScopeID, True
End Sub
Private Sub vPags_ShapeAdded(ByVal shp As IVShape)
If shp.Application.IsInScope(pastedScopeID) Then
Debug.Print "Application.CurrentScope " & Application.CurrentScope
Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name
DoSomethingToPastedShape shp
Else
Debug.Print "Application.CurrentScope " & Application.CurrentScope
End If
End Sub
Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape)
If Not shp Is Nothing Then
shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)"
End If
End Sub
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
add a comment |
A shape's ID is only unique to its page, so the new shape that you paste into Page-1 will receive a new ID and hence the error that you're receiving. Although the Duplicate method returns a shape reference to the new shape, Paste does not so you need to get a reference to it by other means - either assuming something about the window selection (as per Surrogate's answer) or by index:
Dim shp As Visio.Shape
Dim pag As Visio.Page
Set pag = ActivePage 'or some alternative reference to Page-1
Set shp = pag.Shapes.ItemU(pag.Shapes.Count)
Debug.Print shp.Index
A more usual workflow would be to generate masters (in a stencil document) and then drop those masters rather than copying and pasting between pages, but your scenario may require a different approach.
I'll add this link as useful reference for dealing with Index and ID properties:
- Working with Shape Objects
[Update]
@Jon Fournier's comment below is quite right that the above does make assumptions. For example, if the DisplayLevel cell in the source shape is less than the top most shape then it will be pasted into the page's shapes collection at the corresponding index and so count won't return the correct shape ID.
An alternative approach might be to listen to the ShapeAdded event on Pages (or Page). The following is a slight adaption from the IsInScope example in the docs, with code placed ThisDocument. This allows you to top and tail your code in an event scope ID pair that you can inspect when handling the ShapeAdded event:
Private WithEvents vPags As Visio.Pages
Private pastedScopeID As Long
Public Sub TestCopyAndPaste()
Dim vDoc As Visio.Document
Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required
Dim srcPag As Visio.Page
Set srcPag = vDoc.Pages.ItemU("Page-2")
Dim targetPag As Visio.Page
Set targetPag = vDoc.Pages.ItemU("Page-1")
Dim srcShp As Visio.Shape
Set srcShp = srcPag.Shapes.ItemFromID(12)
Set vPags = vDoc.Pages
pastedScopeID = Application.BeginUndoScope("Paste to page")
srcShp.Copy
targetPag.Paste
Application.EndUndoScope pastedScopeID, True
End Sub
Private Sub vPags_ShapeAdded(ByVal shp As IVShape)
If shp.Application.IsInScope(pastedScopeID) Then
Debug.Print "Application.CurrentScope " & Application.CurrentScope
Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name
DoSomethingToPastedShape shp
Else
Debug.Print "Application.CurrentScope " & Application.CurrentScope
End If
End Sub
Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape)
If Not shp Is Nothing Then
shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)"
End If
End Sub
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
add a comment |
A shape's ID is only unique to its page, so the new shape that you paste into Page-1 will receive a new ID and hence the error that you're receiving. Although the Duplicate method returns a shape reference to the new shape, Paste does not so you need to get a reference to it by other means - either assuming something about the window selection (as per Surrogate's answer) or by index:
Dim shp As Visio.Shape
Dim pag As Visio.Page
Set pag = ActivePage 'or some alternative reference to Page-1
Set shp = pag.Shapes.ItemU(pag.Shapes.Count)
Debug.Print shp.Index
A more usual workflow would be to generate masters (in a stencil document) and then drop those masters rather than copying and pasting between pages, but your scenario may require a different approach.
I'll add this link as useful reference for dealing with Index and ID properties:
- Working with Shape Objects
[Update]
@Jon Fournier's comment below is quite right that the above does make assumptions. For example, if the DisplayLevel cell in the source shape is less than the top most shape then it will be pasted into the page's shapes collection at the corresponding index and so count won't return the correct shape ID.
An alternative approach might be to listen to the ShapeAdded event on Pages (or Page). The following is a slight adaption from the IsInScope example in the docs, with code placed ThisDocument. This allows you to top and tail your code in an event scope ID pair that you can inspect when handling the ShapeAdded event:
Private WithEvents vPags As Visio.Pages
Private pastedScopeID As Long
Public Sub TestCopyAndPaste()
Dim vDoc As Visio.Document
Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required
Dim srcPag As Visio.Page
Set srcPag = vDoc.Pages.ItemU("Page-2")
Dim targetPag As Visio.Page
Set targetPag = vDoc.Pages.ItemU("Page-1")
Dim srcShp As Visio.Shape
Set srcShp = srcPag.Shapes.ItemFromID(12)
Set vPags = vDoc.Pages
pastedScopeID = Application.BeginUndoScope("Paste to page")
srcShp.Copy
targetPag.Paste
Application.EndUndoScope pastedScopeID, True
End Sub
Private Sub vPags_ShapeAdded(ByVal shp As IVShape)
If shp.Application.IsInScope(pastedScopeID) Then
Debug.Print "Application.CurrentScope " & Application.CurrentScope
Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name
DoSomethingToPastedShape shp
Else
Debug.Print "Application.CurrentScope " & Application.CurrentScope
End If
End Sub
Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape)
If Not shp Is Nothing Then
shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)"
End If
End Sub
A shape's ID is only unique to its page, so the new shape that you paste into Page-1 will receive a new ID and hence the error that you're receiving. Although the Duplicate method returns a shape reference to the new shape, Paste does not so you need to get a reference to it by other means - either assuming something about the window selection (as per Surrogate's answer) or by index:
Dim shp As Visio.Shape
Dim pag As Visio.Page
Set pag = ActivePage 'or some alternative reference to Page-1
Set shp = pag.Shapes.ItemU(pag.Shapes.Count)
Debug.Print shp.Index
A more usual workflow would be to generate masters (in a stencil document) and then drop those masters rather than copying and pasting between pages, but your scenario may require a different approach.
I'll add this link as useful reference for dealing with Index and ID properties:
- Working with Shape Objects
[Update]
@Jon Fournier's comment below is quite right that the above does make assumptions. For example, if the DisplayLevel cell in the source shape is less than the top most shape then it will be pasted into the page's shapes collection at the corresponding index and so count won't return the correct shape ID.
An alternative approach might be to listen to the ShapeAdded event on Pages (or Page). The following is a slight adaption from the IsInScope example in the docs, with code placed ThisDocument. This allows you to top and tail your code in an event scope ID pair that you can inspect when handling the ShapeAdded event:
Private WithEvents vPags As Visio.Pages
Private pastedScopeID As Long
Public Sub TestCopyAndPaste()
Dim vDoc As Visio.Document
Set vDoc = Me 'assumes code is in ThisDocument class module, but change as required
Dim srcPag As Visio.Page
Set srcPag = vDoc.Pages.ItemU("Page-2")
Dim targetPag As Visio.Page
Set targetPag = vDoc.Pages.ItemU("Page-1")
Dim srcShp As Visio.Shape
Set srcShp = srcPag.Shapes.ItemFromID(12)
Set vPags = vDoc.Pages
pastedScopeID = Application.BeginUndoScope("Paste to page")
srcShp.Copy
targetPag.Paste
Application.EndUndoScope pastedScopeID, True
End Sub
Private Sub vPags_ShapeAdded(ByVal shp As IVShape)
If shp.Application.IsInScope(pastedScopeID) Then
Debug.Print "Application.CurrentScope " & Application.CurrentScope
Debug.Print "ShapeAdded - " & shp.NameID & " on page " & shp.ContainingPage.Name
DoSomethingToPastedShape shp
Else
Debug.Print "Application.CurrentScope " & Application.CurrentScope
End If
End Sub
Private Sub DoSomethingToPastedShape(ByVal shp As Visio.Shape)
If Not shp Is Nothing Then
shp.CellsU("FillForegnd").FormulaU = "=RGB(200, 30, 30)"
End If
End Sub
edited Jan 6 at 12:46
answered Jan 4 at 23:24
JohnGoldsmithJohnGoldsmith
2,1751023
2,1751023
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
add a comment |
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
I don’t remember when, but I got burned assuming the pasted shape was last in the shapes collection
– Jon Fournier
Jan 5 at 18:40
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Thanks. The big thing for me was discovering it's not the same reference on different pages. This really clarifies what's going on.
– David Fulton
Jan 5 at 21:19
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
Yes, good point @Jon. Have updated answer with alternative approach.
– JohnGoldsmith
Jan 6 at 12:50
add a comment |
Of course you get error "Invalid sheet identifier" ! Because at "Page-1" you can have shape with ShapeID, which you defined for shape placed at "Page-2".
You can paste shape and after this step define selected shape.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
' You can define this variable as shape which is selected
Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Why you use variable two times ?
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
add a comment |
Of course you get error "Invalid sheet identifier" ! Because at "Page-1" you can have shape with ShapeID, which you defined for shape placed at "Page-2".
You can paste shape and after this step define selected shape.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
' You can define this variable as shape which is selected
Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Why you use variable two times ?
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
add a comment |
Of course you get error "Invalid sheet identifier" ! Because at "Page-1" you can have shape with ShapeID, which you defined for shape placed at "Page-2".
You can paste shape and after this step define selected shape.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
' You can define this variable as shape which is selected
Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Why you use variable two times ?
Of course you get error "Invalid sheet identifier" ! Because at "Page-1" you can have shape with ShapeID, which you defined for shape placed at "Page-2".
You can paste shape and after this step define selected shape.
Application.ActiveDocument.Pages.ItemU("Page-1").Paste
' You can define this variable as shape which is selected
Set Shape = Application.ActiveWindow.Selection.PrimaryItem
Why you use variable two times ?
answered Jan 4 at 22:32
SurrogateSurrogate
589511
589511
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
add a comment |
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Maybe I'm just not understanding how these methods work, but what I thought was happening here (and seems to work) is 1. Select item (on page 2). 2. Duplicate item (on page 2) and store the ID in ShapeID. 3. Cut the item. 4 Paste the item on page 1. That all works in the above code, but then what I want to do is move the shape that I've pasted on page 1. If I remove the problem line, Shape doesn't hold a reference at all (it seems to lose it at the paste). If I put it in, I want it to find the one I pasted.
– David Fulton
Jan 4 at 22:37
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Sorry - didn't see you'd changed the code as well. So the pasted item will be the selected one? If so, that makes sense, but I don't quite understand why my code wouldn't also have worked. Does a shape ID change if I move it between pages?
– David Fulton
Jan 4 at 22:43
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Yes, shape's ID changed when you paste it in another page. ID in general, is the number corresponding to the order of adding shapes to the page! Please read more about Shape.ID Property, look at Remarks
– Surrogate
Jan 4 at 23:55
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
Right. That's the big thing I was missing. Upvoted as explanation now makes sense to me and you've supplied code to solve the problem. Many thanks!
– David Fulton
Jan 5 at 21:20
add a comment |
I haven’t found a great way to handle this. I have a method that will paste the clipboard to a page and return any new shapes, by listing all shape ids before and after pasting, and then returning new shapes.
If speed is a big issue for me I’ll usually paste to an empty hidden page, do whatever I have to on that page, then cut and paste in place on the destination page. If you need to glue with other shapes this wouldn’t really work, but when it makes sense I use this logic.
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
add a comment |
I haven’t found a great way to handle this. I have a method that will paste the clipboard to a page and return any new shapes, by listing all shape ids before and after pasting, and then returning new shapes.
If speed is a big issue for me I’ll usually paste to an empty hidden page, do whatever I have to on that page, then cut and paste in place on the destination page. If you need to glue with other shapes this wouldn’t really work, but when it makes sense I use this logic.
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
add a comment |
I haven’t found a great way to handle this. I have a method that will paste the clipboard to a page and return any new shapes, by listing all shape ids before and after pasting, and then returning new shapes.
If speed is a big issue for me I’ll usually paste to an empty hidden page, do whatever I have to on that page, then cut and paste in place on the destination page. If you need to glue with other shapes this wouldn’t really work, but when it makes sense I use this logic.
I haven’t found a great way to handle this. I have a method that will paste the clipboard to a page and return any new shapes, by listing all shape ids before and after pasting, and then returning new shapes.
If speed is a big issue for me I’ll usually paste to an empty hidden page, do whatever I have to on that page, then cut and paste in place on the destination page. If you need to glue with other shapes this wouldn’t really work, but when it makes sense I use this logic.
answered Jan 5 at 18:43
Jon FournierJon Fournier
3,46512440
3,46512440
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
add a comment |
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
Glad it's not just me having the problem. Speed is not an issue as the idea was to write a script that took a description of the flow I wanted and then build it once (I have a lot of these to draw and the requirements change daily, so it was a labour-saving idea). The solution below gives a way of identifying the pasted item, so it looks like I have a solution, but your workaround is also valid for my requirements.
– David Fulton
Jan 5 at 21:23
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54043283%2fcut-and-paste-visio-shape-in-macro%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown