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;
}







1















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.










share|improve this question































    1















    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.










    share|improve this question



























      1












      1








      1








      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.










      share|improve this question
















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 29 at 19:24









      halfer

      14.8k759118




      14.8k759118










      asked Jan 4 at 17:08









      David FultonDavid Fulton

      292310




      292310
























          3 Answers
          3






          active

          oldest

          votes


















          2














          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





          share|improve this answer


























          • 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



















          1














          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 ?






          share|improve this answer
























          • 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



















          1














          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.






          share|improve this answer
























          • 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












          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          2














          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





          share|improve this answer


























          • 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
















          2














          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





          share|improve this answer


























          • 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














          2












          2








          2







          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





          share|improve this answer















          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






          share|improve this answer














          share|improve this answer



          share|improve this answer








          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



















          • 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













          1














          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 ?






          share|improve this answer
























          • 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
















          1














          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 ?






          share|improve this answer
























          • 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














          1












          1








          1







          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 ?






          share|improve this answer













          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 ?







          share|improve this answer












          share|improve this answer



          share|improve this answer










          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



















          • 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











          1














          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.






          share|improve this answer
























          • 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
















          1














          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.






          share|improve this answer
























          • 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














          1












          1








          1







          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.






          share|improve this answer













          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          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



















          • 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


















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          Mossoró

          Can't read property showImagePicker of undefined in react native iOS

          Pushsharp Apns notification error: 'InvalidToken'