Add new shape at certain position in visio page

Started by ExcelMVP, January 02, 2013, 12:30:52 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

ExcelMVP

Hey , Thanks for looking into my query

just wondering what will be a VBA code to add new shape(say rectangle) on Visio page at certain position of the Visio page. I actually want to create a dynamic legend based on the color of the shapes, so would want to add the shape somewhere at the bottom of the sheet.

Many thanks.


Paul Herber

Electronic and Electrical engineering, business and software stencils for Visio -

https://www.paulherber.co.uk/

ExcelMVP


Michelle

I was wondering something very similar...
Just out of curiosity, can I control the location of a shape placed via VBA in relation to another shape just placed on the page?  I have a shape that uses a Macro to place another shape once it is placed.  I'd love to be able to have VBA place that "automatic" shape in close proximity to the original shape just placed.  (rather than the predetermined spot which is the same each time I place that original shape resulting in several of these "second" shapes right on top of each other in that location)

If there is a solution for this, please (for me) "dumb down" your answer, as I am easily confused, LOL  ;)

Michelle

Jumpy

As stated in the other thread: Use CALLTHIS instead of RUNMACRO.

A macro that you start with CALLTHIS has to be sligthly different than one started with RUNMACRO, because with CALLTHIS you automatically get a referece to the calling shape in the code:

Sub MyMacro(shp as Visio.Shape)
' Do sth.
End Sub

For your example/problem with the placing of a new shape relative to the old/calling shape:

Sub MyMacro(shp as Visio.Shape)
  Dim newshp as Shape
  Const xoffset=10
  Const yoffset=0
  'Do something that results in the newshape droped somewhere on the page
  'Now you can place the new shape relative to the old shape:

  newshp.Cells("PinX").Result("mm") = shp.Cells("PinX").Result("mm") + xoffset
  newshp.Cells("PinY").Result("mm") = shp.Cells("PinY").Result("mm") + yoffset
End Sub


contact_ankit86

Hi,

I had a very similar problem. I want to drop a shape on the chart and connect it with another shape. I am able to copy a shape, do some modifications and paste the shape on a chart. it also gets connected the way i want to. the only problem is that the new sahpe gets pasted on any other shape. In other words it gets overlapped with other shape. Chart is all dynamic so will not be knowing the PINX and PINY where the new shape needs to be placed. even if i add some constant value to existing shapes PINX and PINY, i will not be knowing if thers already a shape at that position.

Is there any way by which i can find the empty/ vacant place on the chart so that the new shape gets pasted there and connected to another shape.


Jumpy

When the shape is posted, you can see if it's overlapping another shape and reposition at again.
There are functions ot the shape object in Visio like DistanceFrom or SpatialNeighbours that you could use for that.

contact_ankit86

Thanks Jumpy.. It helped..!! SpatialNeighbours did not work but got an idea from this function..!!

Cheers  ;)

vojo

I did something like this a few years back....as I recall, the functions I found in visio did not seem work
(very poor precision...based on my experience, visio must use some other hidden functions support autoroute et al tasks and such).
I ended up creating my own distancefrom / spatial neighbor functions

Michelle

Hey Jumpy,

I wanted to refer back to your reply to me... I wasn't able to try it out then, but now the issue has come up again, so I need to try it now.

The first Code sample you show... is that what I need to add to the beginning of my macro to make it work with the CALLTHIS function?  Or can I just use CALLTHIS instead of RUNMACRO leaving everything else the same? 

The second Code example... Is this a macro I create and then call in the EventDrop cell of the shape that is brought in automatically vis the macro?  The code confuses me, how does it know which shape to place it near?  I don't need this to be precise, I just need the shapes to reliably place near each other no matter where on the drawing page I place the first one....

Any help is greatly appreciated!
Michelle

Jumpy

Quote from: Michelle on January 16, 2013, 09:54:50 PM
The first Code sample you show... is that what I need to add to the beginning of my macro to make it work with the CALLTHIS function?  Or can I just use CALLTHIS instead of RUNMACRO leaving everything else the same? 
Yes. A macro that is called with Callthis, has to have the (shp as Visio.Shape) part. A variable for a Shape object.
The name u use doesn't matter, so you could for example write (myShape as Visio.Shape), too.
Inside the macro that variable shp represents the shape that started this macro, so if for example you place Callthis in EventDrop cell, shp represents the Shape that you just droped on the page.

Quote
The second Code example... Is this a macro I create and then call in the EventDrop cell of the shape that is brought in automatically vis the macro?  The code confuses me, how does it know which shape to place it near?  I don't need this to be precise, I just need the shapes to reliably place near each other no matter where on the drawing page I place the first one....

shp is a shape you just placed on the shape (was it in your case photo device or sth.?).
With shp.cells("PinX").Result("mm") and shp.Cells("PinY").Result("mm") you know the position of your shape in mm.
Know the macro drops the new shape, that you wan't to place near the old shape. How to select a mastershape and drop a shape is explained somewhere in this forum, I'd bet.
The only thing that remains is to place the new shape near the old shape, in my example above via:

newshp.Cells("PinX").Result("mm") = shp.Cells("PinX").Result("mm") + xoffset
newshp.Cells("PinY").Result("mm") = shp.Cells("PinY").Result("mm") + yoffset

where xoffset and yoffset are constants that define where to position the newshape in relation to the oldshape.


In Essence: I react to the first shape droped (the foto devide) and that code drops and places the second shape (the lens device).

---------
I don't want to confuse you but the best way to do this (without using a smart shape) would be to use the code above, but additionally add an information of the newshape (for example the ID) somewhere in the shapesheet of the oldshape.
If you know change the property in the oldshape, that defined what a shape has to be near the old shape, you can call a macro again wiht Callthis and DEPENSON that first deletes the former newshape (find it with the ID stored somewhere in the old shape) and know drops another differnet newshape near your oldshape and stores it's ID in the oldshape again.



Michelle

OK, I am going to try what you are telling me, but I am very intrigued by your last paragraph...

QuoteI don't want to confuse you but the best way to do this (without using a smart shape) would be to use the code above, but additionally add an information of the newshape (for example the ID) somewhere in the shapesheet of the oldshape.
If you know change the property in the oldshape, that defined what a shape has to be near the old shape, you can call a macro again wiht Callthis and DEPENSON that first deletes the former newshape (find it with the ID stored somewhere in the old shape) and know drops another differnet newshape near your oldshape and stores it's ID in the oldshape again.

Too late now to worry about confusing me!   :P  j/k.  I am very comfortable with smart shapes.  I have been working within the shape sheet for a few years now.  It is the code stuff that throws me for a real loop.  I am interested in how you mention that I can add information in the old shape about the ID of the new shape?  I thought that was always my problem of doing this within the shape sheet, that when the shapes are placed on the drawing area they get assigned new ID.  I need this to run whether I place the shape first, or 51st.  And also if I use the shape one time or 17 times.  Can I refer to the shape to be brought in, even though it is actually a copy of a shape from another page?  The ID is different once it is a copy, correct?

Michelle

I thought I'd try to be smart and midify my module code to work in my situation.  So much for that Ha Ha!  Here's what I am trying.  (Mind you I have tried several versions of this...)

Sub MyMacro4(shp As Visio.Shape)

    'Enable diagram services
    Dim DiagramServices As Integer
    DiagramServices = ActiveDocument.DiagramServicesEnabled
    ActiveDocument.DiagramServicesEnabled = visServiceVersion140

    Application.ActiveWindow.Page = Application.ActiveDocument.Pages.ItemU("Page-3")

    ActiveWindow.DeselectAll
    ActiveWindow.Select Application.ActiveWindow.Page.Shapes.ItemFromID(14), visSelect
    Application.ActiveWindow.Selection.Copy

    Application.ActiveWindow.Page = Application.ActiveDocument.Pages.ItemU("Site Layout")
    Dim newshp As Shape
   

    Application.ActiveWindow.Page.PasteToLocation shp.Cells("PinX").Result("#") + 10#, shp.Cells("PinY").Result("#") + 0, 0
End Sub


But pretty much everyting I try places the copied shape in the same exact spot as where my original macro had it.  I changed the "mm" to # because I am working with inches, and my original macro had code that said:

Application.ActiveWindow.Page.PasteToLocation 664#, 248#, 0

I was thinking I could change out the reference to the original shape right in there, but Either I can't or I'm doing something wrong! 

Any help would be appreciated!

Michelle

vojo

last line is using shp....not newshp

If I understand this macro...it basically is placing the current shape where it already is


Michelle

I have tried what seems like every combination of shp & newshp, and nothing gets that second shape placed anywhere new.  I don't know if it is not doing anything, or like you said... just placing it where it already is.  I need it to place at a certain location offset from the shape that originally called it. 

Where should I place the "CALLTHIS" to make that happen?  In the EventDrop of the calling shape?  In the EVentDrop of the "new" called shape?  In a scratch section of one of those two like I did for the original module that calls the shape ion the first place? 

I feel like I'm close, but can't get it.... and I NEED this! 
Thanks for any help!
Michelle