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
Related
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.
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.
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.
I'm populating PowerPoint slides with data from an Excel spread sheet. At the moment, I'm accessing the slide using the page number:
Set mySlide = PowerPointApp.ActivePresentation.Slides(1)
Using the Master View option in the UI, you can rename the slide. How can I find the slide using that name?
Thanks,
Carlo.
ActivePresentation.Slides(i).Master.Design.Name
It is the name you see for the theme, in the master view for the slide.
layoutIndex = ActivePresentation.Slides(i).CustomLayout.Index
It is the current layout of the slide in the above theme.
ActivePresentation.Slides(i).Master.Design.Parent.CustomLayouts.Item(layoutIndex).Name
It is the layout name of the currently selected layout of the slide.
it is the VBA, what you can say :-).
Using the Slide.Name property will define the name of the slide and allow it to be called using:
ActivePresentation.Slides("Name")
per the MSDN
So, what I wanted was a way to uniquely identify a PPT slide through VBA. The problem is that I still need to be able to identify that slide if it is copied to another PPT document.
So, what I found I had to do was:
create a text box on each page and hard-code the text to be something like "Slide:Cover" or "Slide:QuarterlyResults", etc.
loop through each slide
find "Slide:" and strip it out to get the page title. That way, if the slide is copied to another PPT document, the name goes with it.
create a Dictionary that uses the Slide.SlideID as the key and the page title as the value.
Then what I do is loop through the slides, get the SlideID, use the Dictionary to get the page title and use a Select statement to map to the proper method to process the slide.
Yeah, I know... it's an icky hack, but it's the only way I could think of doing it.
Thanks for you help,
Carlo.
Well I was wondering whether we can somehow create custom looking text boxes that act as an input box and is linked to VBA.
As far as I am aware the standard procedure would entail adding an ActiveX Textbox Control and then using the TextBox1_Change event to add the code as to what needs to happen when the user enters something in to.
Sadly the look of the default textbox isn't matching the way I want by spreadsheet to look. So is there any way to change how it looks or have something replace it while serving the same purpose?
One thing I could think of and have tried is inserting a shape (blue):
Shape http://im52.gulfup.com/qD2F0B.png
I can get the text that is in the shape using VBA by:
InputText = Shapes("Rounded Rectangle 1").TextFrame.Characters.Text
But I don't suppose there is a way to detect a change of shape text event?
Suggestions / Workarounds are welcome!
Thanks
There are limitations on what you can change on an ActiveX TextBox, such as Font/Color/Border/SpecialEffects, but the basic rectangle shape cannot be changed.
However you can make the TextBox transparent by BackStyle property and group it to a shape (bring the TB forward) and still use the TextBox1_Change method for changes.
If you need to access the value in the TextBox somewhere else, a quick way is to use TextBox1.LinkedCell and below to set the value to a cell, or a Named Range.
Private Sub TextBox1_Change()
' Same Sheet as TextBox1
ActiveSheet.Range(TextBox1.LinkedCell).Value = TextBox1.Value
' Or Below for Named Range
ThisWorkbook.Names(TextBox1.LinkedCell).RefersToRange.Value = TextBox1.Value
End Sub