Finding id of shape dragged onto screen in Visio using VBA macro - vba

I currently have a program in Visio that when a specific shape in my custom stencil is dragged onto the screen, a user form comes up and asks the user a question with a combo box used for the user to select an answer.
Based on the answer selected, the shape data should change for that object.
The problem that I am facing is that I am not sure how to target the ID of the shape automatically to then change its shape data. Since multiple of these shapes may be placed, I can not manually write a new piece of code for every ID.
Image: Shapesheet of the shape running the macro on drop. "Form" is the user form.
Image: Userform macro
I would be very grateful if someone could help me with this problem.
Thank you

I wonder if the CALLTHIS ShapeSheet function might be more useful here as it passes a reference to the calling shape. So, for example, in the EventDrop cell add this formula:
CALLTHIS("ThisDocument.OnMyShapeDrop","Drawing001")
and then add this backing code:
Public Sub OnMyShapeDrop(shp As Visio.Shape)
MsgBox "Shape dropped - ID = " & shp.ID, vbOKOnly, "Shape Dropped"
End Sub
Note, that I've put the code in the ThisDocument class, but it can live in any accessable module. Also note the project name (Drawing001) which will likely be the file name without the extension.

Related

PowerPoint VBA add shape event/ add shape with tag value

i'am currently trying to add a small function to PowerPoint using VBA, my goal is to create a gadget that works kind of like Photoshop graphics layer.
My plan is to add a layer name Tag on each shape that is drawn by user, so later I can parse through every item by loop and preform lock/unlock, show/hide shapes based on it's tag value, such as:
Sub add_shape_with_layer_tag()
Set islide = ActivePresentation.Slides(1)
Set ishape = islide.Shapes.AddShape(msoShapeRectangle, 5, 5, 80, 60)
ishape.Tags.Add "Layer", "1"
End Sub
Sub show_hide_layer_one_shapes()
Dim active_slide As Slide
Set active_slide = ActiveWindow.View.Slide
For Each ishape In active_slide.Shapes
If ishape.Tags("Layer") = "1" Then
ishape.Visible = Not (ishape.Visible)
End If
Next ishape
End Sub
However, I couldn't found a way to achieve this, so I would like to ask whether there's a method that provides following functions?
override add shape function so I can sneak tag value in to shape every time user drawn a shape
catch add shape event (if this thing did exist) so i can add tag to the last added item
a way to set a default tag value to shape, just like setting default shape color/line width
or is there any better options that is also viable?
thanks.
20200728
To John, thanks for the advice, I did found some interesting event that might be helpful for some of my other projects, however I couldn't found events that able to trigger after custom function while shape is added.
To Steve, my plan is to add a modeless userform with list UI that manage layers, the shape tag and shape fill texture/color will be determined based on what list item that currently selected.
As to saving settings, I'll use VBComponents.CodeModule to dump existing settings in userforms to a VBA module and store as text, so in theory I should able to make this function self contained in one file.
Not totally an answer, sorry SO, but comments don't allow enough scope for this. So ...
To Steve, my plan is to add a modeless userform with list UI that manage layers, the shape tag and shape fill texture/color will be determined based on what list item that currently selected.
Ah, so you're creating your own "pseudo-layers". That wasn't clear. Thanks for the add'l info. As it happens, I have a selection manager add-in that works very similarly to what you're proposing.
To John, thanks for the advice, I did found some interesting event that might be helpful for some of my other projects, however I couldn't found events that able to trigger after custom function while shape is added.
The SelectionChange event should get you there. When it fires, you'll need to check first to see if the current selection is a shape or something else. If a shape, check to see if its .Index = current slide's .Shapes.Count and also to see if you've already tagged it. If no tag AND if it's the correct index, it'll be a newly added shape. If you're tagging ALL shapes, you may only need to check to see if the .Tag(name) is blank.
As to saving settings, I'll use VBComponents.CodeModule to dump existing settings in userforms to a VBA module and store as text, so in theory I should able to make this function self contained in one file.
Why not save any needed slide or presentation level info as further slide- or presentation-level tags? PPT can absorb quite a lot of info as tags w/o getting cranky.

How to copy and paste a clicked shape from one slide to another

I am new to VBA in PowerPoint and I am trying to develop an interactive program for my class where a text box grouped with a bubble shape floats across the screen and they have to click it if they notice it contains a certain grapheme. I want the clicked text boxes to copy to another slide so that I can assess if the children have been successful or just clicked anything they saw.
I've pieced together this code from other sites:
Sub copyobject()
With ActivePresentation
Set myshape1 = ActivePresentation.Slides(2).Shapes(group5)
myshape1.ActionSettings(ppMouseClick).Action = myshape1.Copy
.Slides(3).myshape1.Paste
End With
End Sub
It doesn't appear to be working though. Can anybody help me out?
The error message I receive is 'compile error: method or data member not found' with .myshape1 highlighted.
If anybody could give me a completed code for this or correct what I have created I would greatly appreciate it.
Many thanks
Since the name of the object is "group5", I assume it's a group. But you can't apply an Action Setting to a group, only to a single object. This works for a single shape:
Sub copyobject()
With ActivePresentation
Set myshape1 = .Slides(2).Shapes("Rectangle 1")
myshape1.ActionSettings(ppMouseClick).Action = myshape1.Copy
.Slides(3).Shapes.Paste
End With
End Sub
BTW, an excellent VBA book for what you're doing is David Markovitz's Powerful PowerPoint for Educators. His support site for the book also has lots of free code and samples.

Get shape control name from access form to pass value in vba

I have a form in Access with over 500 shapes that each represent a specific record. Each shape has the control name of Box1, Box2 etc. In VBA I am trying to capture the shape name so if the user clicks the shape called Box502 for example it will go to record 502. Since it is a shape, the other methods I have used are not capturing this control name. If I can capture the name, I can remove “Box” from it and get the number to use to go to that record.
If I use a command button instead of a shape I can use the code below and get it to do what I want, but there is also code that changes the color of the shape so that does not work on the command button.
Private Sub Box2_Click()
Dim strActiveCtl As String
strActiveCtl = Replace(Me.ActiveControl.Name, "Box", "")
DoCmd.GoToRecord acDataForm, "Form1", acGoTo, [strActiveCtl]
End Sub
If I use this line of code on the shape, it is grabbing another control and not what I had clicked on.
On click I was using the code builder and this line of code, but it is capturing another control and not what I am clicking on.
Dim strActiveCtl As String
strActiveCtl = Screen.ActiveControl.Name
The reason there are these little boxes are because they basically relate to a service that is monitored. There are about 550 services monitored. When the service has been noted as reviewed the shape goes from red to green. The team wanted to be able to just click on the shape as well and have it take to them to the service it was associated with.
I can't for the life of me envision a Form with over 500 shape boxes that each represent a different record. Egads.
But maybe you have a unique reason for doing this. So I won't question this design philosophy other than to say most people use "sub-forms" and "list boxes" when trying to identify individual records like you are doing. You may be able to save yourself lots of headaches by reading up on how to design forms using those methods. (As well as many other methods that avoid putting over 500 shape boxes on your form.)
However, if this is a design that you have to adhere to... there are a few things you need to know about Access and the way it resolves the active control as well as what happens when a control is clicked on.
Whenever you click on a control or shape, if you have the control properties set so it can accept "Focus", Access instantly makes that the "active control".
So if you then go to click on something else... your shape will lose it's status of being the "active control" and the new thing will now be the new "active control".
So there is no way to click on a shape and then click on something else to launch your code that you want to have performed on the previous "active control". Access doesn't keep a memory of past "active controls".
So this brings up the question of: "What can you do to figure out if a control or shape was clicked on?"
Luckily (or unluckily) for you, when a shape is clicked on, it checks if code has been written for it's "On Click" property.
Each and every shape you put on the Form will have it's very own "On Click" property. Which means you can write a function that you can place in every single shape you create. You can pass to that function the number of which "Box" it was that called it.
This is obviously very cumbersome. (Which is why I'd suggest using "sub-forms" or "list boxes".) But it's the only way you are going to capture the Box number that is different for each of the 500 boxes since there is no way to launch other code without losing the "Focus" on which box you were on.
So if you want to continue with your "500 shapes on one Form each addressing a different record"... you could write a VBA function that calls your record with an input parameter that tells what "Box" called it. Like this:
Private Sub subGoToNewRecord(intActiveCtl As Integer)
DoCmd.GoToRecord acDataForm, "Form1", acGoTo, intActiveCtl
End Sub
Then for each Shape Box you can write:
Private Sub Box1_Click()
subGoToNewRecord 1
End Sub
Private Sub Box2_Click()
subGoToNewRecord 2
End Sub
.
.
.
Private Sub Box502_Click()
subGoToNewRecord 502
End Sub
This will get you what you want. (Although, some shapes require you to click on the outline of the shape in order make it the "active control". So you may need to make your shape boundary thick and tell users to click on the boundary line.)
Once again, I have no idea why you'd want to do this. I'd suggest again to look into what "sub-forms" are and to look into what "List Boxes" are. They are much better suited to helping you select a desired record and then make that the "Active Record".
Hope that helps. :)

How to identify the clicked shape name in VBA

I am trying to create an excel template where I have already assigned different macros to different shape that act as buttons. Now I am having problem of locating which one I have clicked since I need to modify the attributes of the clicked shape after clicking on that shape. While searching on this problem, I have noticed that there is a way to identify which shape has been selected whereas I still doesn't know How to get the name of the shape I have clicked or is there a way to refer to that clicked shape in VBA? Thank you!
You should be able to get the name of the clicked shape by using Application.Caller
usage as shown
'Application.Caller contains a reference to the clicked Shape
msgbox Application.Caller.Name
ActiveSheet.Shapes(Application.Caller).TextFrame.Characters.Text

Is it possible to identify the shape ID that triggers a mouseover on a powerpoint presentation?

Is it possible to identify the shape ID that triggers a mouseover on a powerpoint presentation.
What I want to do is have a series of shapes on a slide with titles, and when the user mouseovers a shape, I want to use VBA to show more details about the shape in another part of the page, possibly in a separate help text box. I could then use the selected shapes ALt Text to display in the help box. What i can't see is how to identify what shape has triggered the mouseover macro. Is this possible? If I can identify the shape that triggered the action, I could then get info about that shape.
The Shape object in PowerPoint does not allow you to interact with its events as you normally would with other objects in VBA code. The only two 'events' that are exposed are not actually VBA events. They are a special class called Actions, and they are 'ppMouseOver' and 'ppMouseClick'. If you know all the information about your shapes and their corresponding information beforehand, you could write some code to do what you want, but it would all be hard-coded, which is probably not what you want.
You could run a routine something like this when the presentation starts:
Sub SetActionsRoutine()
Shape1.ActionSettings(ppMouseOver).Action = ppActionRunMacro
Shape1.ActionSettings(ppMouseOver).Run = "showInformation1"
Shape2.ActionSettings(ppMouseOver).Action = ppActionRunMacro
Shape2.ActionSettings(ppMouseOver).Run = "showInformation2"
...
...
End Sub
And then whenever you did a MouseOver of those shapes, one of the following routines would run.
Sub showInformation1()
myTextBox.Text = Shape1.AlternativeText
End Sub
Sub showInformation2()
myTextBox.Text = Shape2.AlternativeText
End Sub
This is very limited and requires that you write a subroutine for every shape on your slide. Probably not the approach you want, but again, with PowerPoint, your options are very limited.
New to StackOverflow, late to answer, but you can do this:
Sub RespondToShape(oSh as Shape)
MsgBox "You clicked " & oSh.Name
End Sub
Assign every shape you want to interact with an Action setting of Run Macro and choose RepondToShape as the macro.