I'm very new to macros and I'm trying to teach myself VBA in excel 2013 and could use a lot of help. I would like to know how to change a shape fill color (not a cell) when I click an ActiveX button. Here is what I'm thinking:
onClick() <-- Do I need a button name?
if shape.color = RGB(231,230,230) <-- this is the starting color
shape.color = RGB(0,0,0) <-- this is what I want to change it to
else
shape.color = RGB(231,230,230) <-- if color is black change to this
end if
By the way, this is for fun and not for anything special or official.
Here is the code you are looking for:
Option Explicit
Sub ButtonClick()
Dim shp As Shape
Set shp = ThisWorkbook.Worksheets(1).Shapes("Rectangle 1")
If shp.Fill.ForeColor.RGB = RGB(231, 230, 230) Then
shp.Fill.ForeColor.RGB = RGB(0, 0, 0)
Else
shp.Fill.ForeColor.RGB = RGB(231, 230, 230)
End If
End Sub
Just make sure that you adjust the above code to the correct shape name (which is "Rectablge 1" in this example, which is located on Sheet(1)).
Afterwards, create a button on that sheet and assign this macro to the button to make it work and toggle the shape color between black and grey.
Next time, I recommend that you (in a first step) record the things you want Excel to do for you with the VBA macro recorder: https://www.youtube.com/watch?v=Q_HQGHPBYoo Afterwards, have a look at the code and try to understand it by highlighting VBA key-words and pressing F1. Also, I'd recommend reading this: http://www.homeandlearn.org/ Afterwards you should be set to write some rather fancy macros.
Put this in the module of the worksheet which contains the button:
EDITED: Sorry, I originally thought you wanted the actual button colour to change. I borrowed from Ralph's answer to account for the shape being the object of the colour change, but below this is for an ActiveX control (as you asked) instead of a form button:
Private Sub CommandButton1_Click() ' Yes, you do need to specify the button
Dim shp As Shape
Set shp = ThisWorkbook.Worksheets(1).Shapes("Rectangle 1")
If shp.Fill.ForeColor.RGB = RGB(231, 230, 230) Then
shp.Fill.ForeColor.RGB = RGB(0, 0, 0)
Else
shp.Fill.ForeColor.RGB = RGB(231, 230, 230)
End If
End Sub
Yes, you need a button name. Drop an ActiveX control on the sheet, then go to the sheet's module in the VBE. In the left dropdown at the top of the code pane, find your control name (you probably want to rename it first - I didn't for this example)
When you pick the control name in the left dropdown and the event name in the right, the VBE stubs the Sub and End Sub for you.
Next you need to reference your shape in your code. Start by using the Me keyword. When you're in a sheet's code module, Me refers to that sheet. Then the dot operator will expose all the properties and methods of that sheet. When you drop an ActiveX control on a sheet, a new property of the sheet is automatically created that provides access to the object. You can use
Me.CommandButton1.BackColor = RGB(231, 230, 230)
You If logic looks fine.
Related
I have a Powerpoint-Slide with pasted, formatted source code in the form of text shapes. Sadly the contrast of some part of that text is bad on a projector, so I would like to change every colour occurence for a specific font with a different colour. In this specific example I want to replace the orange colour:
Iterating over all shapes and accessing the whole text of a shape is not a problem, but I can't find any property that allows me to enumerate over the styled text segments:
Sub ChangeSourceColours()
For Each pptSlide In Application.ActivePresentation.Slides
For Each pptShape In pptSlide.Shapes
If (pptShape.Type = 1) And (pptShape.TextFrame.TextRange.Font.Name = "Consolas") Then
' Iterate over styled segments and change them if the previous colour is orangey
MsgBox pptShape.TextFrame.TextRange
End If
Next
Next
End Sub
The TextRange2 property looked helpful at a first glance, but looking at the variables in the debugger I see nothing that looks like a series of formatted segments. I would expect to find something like <span> in HTML to check and possibly change the colour.
The textFrame2.textRange.Font is valid for the whole text. If you want to access the single characters and their individual formatting, you need to access textRange.Characters.
The following routine changes the text color for all characters that have a specific color to a new color:
Sub ChangeTextColor(sh As Shape, fromColor As Long, toColor As Long)
Dim i As Long
With sh.TextFrame2.TextRange
For i = 1 To .Characters.Length
If .Characters(i).Font.Fill.ForeColor.RGB = fromColor Then
.Characters(i).Font.Fill.ForeColor.RGB = toColor
End If
Next i
End With
End Sub
You call it from your code with
Dim pptSlide as Slide
For Each pptSlide In Application.ActivePresentation.Slides
Dim pptShape As Shape
For Each pptShape In pptSlide.Shapes
If (pptShape.Type = 1) And (pptShape.TextFrame.TextRange.Font.Name = "Consolas") Then
ChangeTextColor pptShape, RGB(255, 192, 0), vbRed
End If
Next
Next
You will have to adapt the RGB-Code to the orange you are using, or instead of using RGB, you can use ObjectThemeColor. To avoid a type mismatch, you need to declare the pptShape variable as Shape - you should declare all your variables and use Option Explicit anyhow.
Note that you can use the ChangeTextColor-routine also in Excel (and probably also in Word). Shapes are defined similar in Excel and Powerpoint. Advantage in Excel: You can use the macro recorder to get some insights how a Shape can be used in Office VBA.
I'm trying to make a button that when clicked, will add two text boxes to the selected slide in a specified place with specified formatting (font, size, color, justified). I've been trying to reverse engineer anything applicable, but just end up breaking things. This set of code will allow me to make a rectangle (not a textbox which is preferred) size it and place it (just 1 not 2) with sample text.. For the life of me I cant figure out how to make it create a textbox on the selected slide or active window.. what am I doing wrong? Heres the code I found..
Sub AddTextBox()
Set myDocument = ActivePresentation.Slides(1)
With myDocument.Shapes _
.AddTextBox(msoShapeRectangle, 180, 175, 350, 140).TextFrame
.TextRange.Text = "Ctrl+A(Select all), Ctrl+V(Paste)"
.MarginTop = 10
End With
End Sub
To refer to the slide that's currently being displayed, you can use the Slide Property of the View object...
Dim mySlide As Slide
Set mySlide = ActiveWindow.View.Slide
For creating a textbox, here's the proper syntax as per the documentation here...
Syntax
expression. AddTextbox( Orientation, Left, Top, Width,
Height )
expression A variable that represents a Shapes object.
So, in your case, it would be something like this...
Dim myTextbox As Shape
Set myTextbox = mySlide.Shapes.AddTextbox(msoTextOrientationHorizontal, 180, 175, 350, 140)
Change the text orientation as desired.
I changed the size of text with the following line of code
shp.CellsSRC(visSectionCharacter, 0, visCharacterSize).FormulaU = " 3pt"
I'd like to change the style (to Bold) and color of the shape text with the same pattern of code ?
I didn't find the exact "formula", would you know how I could do that ?
Thank you very much in advance
Edit : I found this line for the color :
shp.CellsSRC(visSectionCharacter, 0, visCharacterColor).FormulaU = "THEMEGUARD(RGB(255,0,0))"
I'm not sure why there is no enumeration for setting the Style. In any case, it's Column 2 in the shape properties. So use
shp.CellsSRC(visSectionCharacter, 0, 2).FormulaU = 17
to set your text to Bold.
How do I know this you ask? Based on the Microsoft reference on Understanding the Shape Sheet, there is a helpful snippet of code to use.
First, select the shape in your drawing that you want to see information about the properties. Then open up the Shape Properties window in the Visio editor (not in the VBE) -- you can get there by viewing the Developer ribbon, then click on the Show ShapeSheet icon
In the shape properties window, scroll down until you see the Characters section. You MUST select one of the cells in the properties window. The example here has selected the Style column.
Once you have done this, then run the following code snippet below and you'll get the information you need in the Immediate Window of the VBE.
Public Sub DebugPrintCellProperties()
' Abort if ShapeSheet not selected in the Visio UI
If Not Visio.ActiveWindow.Type = Visio.VisWinTypes.visSheet Then
Exit Sub
End If
Dim cel As Visio.Cell
Set cel = Visio.ActiveWindow.SelectedCell
'Print out some of the cell properties
Debug.Print "Section", cel.Section
Debug.Print "Row", cel.Row
Debug.Print "Column", cel.Column
Debug.Print "Name", cel.Name
Debug.Print "FormulaU", cel.FormulaU
Debug.Print "ResultIU", cel.ResultIU
Debug.Print "ResultStr("""")", cel.ResultStr("")
Debug.Print "Dependents", UBound(cel.Dependents)
' cel.Precedents may cause an error
On Error Resume Next
Debug.Print "Precedents", UBound(cel.Precedents)
Debug.Print "--------------------------------------"
End Sub
This will tell you the Section, Row, and Column to use when you call CellsSRC. What I did was to figure out the property, then I manually set the text to BOLD and viewed the results of DebugPrintCellProperties again to see that the FormulaU = 17 for bold.
I would like to make a macro in Powerpoint that enables me to create shapes in a similar fashion as when you select the autoshapes in the autoshape overview (i.e. once you call the macro you have a possibility to click to set the coordinates and subsequently you drag and click to set the width&height). Also, I would like to give it pre-set cosmetic characteristics (e.g. certain inner margins, fill color, border style and transparancy), which will be defined in the vba code.
I am aware of .addshapes(), however, this requires coordinates and height/width as input. Moreover, I have not find any posts / documents on vba to create shapes without defined coordinates and height/width.
Anyone some ideas on how to tackle this challenge?
Many thanks in advance!
Sofar
Building on what John Korchok suggested, here's code that retrieves the just-drawn shape so that your code can resume and manipulate it...
Sub testAppComBars()
Dim SHP As Shape
Application.CommandBars.ExecuteMso ("ShapeFreeform")
Stop
Set SHP = Selection.ShapeRange(1)
With SHP.Fill
.ForeColor.RGB = RGB(192, 0, 0)
.Transparency = 0.75
End With
End Sub
I would hope there's a more elegant solution than using Stop to pause code execution while the user picks the shape's location (or in this case, draws a freeform polyline/polygon), but that's all I could come up with off the top of my head.
I was fascinated by this problem and think this might help you.
Consider that when you draw a new autoshape, you have changed the window selection, and created a new selection ShapeRange with exactly 1 item (the new shape).
So by setting a WindowSelectionChange event, you're able to apply any formatting you wish at the time of creation.
First create a class module called cPptEvents with the following:
Public WithEvents PPTEvent As Application
Private Sub PPTEvent_WindowSelectionChange(ByVal sel As Selection)
On Error GoTo Errhandler
Debug.Print "IN_PPTEvent_WindowSelectionChange"
Dim oShp As Shape
If (ActiveWindow.ViewType = ppViewNormal) Then
With sel
If .Type = ppSelectionShapes Then
If .ShapeRange.Count = 1 Then
Set oShp = .ShapeRange(1)
If oShp.Type = msoAutoShape Then
If oShp.AutoShapeType = msoShapeOval Then
If oShp.Tags("new_oval") = "" Then
oShp.Fill.ForeColor.RGB = RGB(255, 0, 0)
oShp.Tags.Add "new_oval", "true"
End If
End If
End If
End If
End If
End With
End If
Exit Sub
Errhandler:
Debug.Print "Error: " & Err.Description
End Sub
This checks the selection every time it changes. If there's an oval selected, it looks for the "new_oval" tag, which will not exist for a newly created shape. In that case, it applies a red fill, although of course once you get to this point you can call an entirely different sub, pass along the shape, and do whatever you want formatting-wise to it.
By adding that "new_oval" tag, you ensure that the formatting will not be applied to an oval that hasn't been newly created. This allows the user to make manual changes to the formatting as needed -- otherwise you're just resetting the formatting every time the user selects an oval.
Note that for the _WindowSelectionChange event to be running in the background, you have to call this at some point:
Public MyEventClassModule As New cPptEvents
'
Public Sub StartMeUp()
Set MyEventClassModule.PPTEvent = Application
End Sub
You can include that one line from StartMeUp above in whatever Ribbon_Onload sub is triggered by your addin, if you're making a new addin ribbon.
With this solution, you don't even have to give the end user a special button or set of tools to create the shapes that are being formatted. It happens invisibly whenever the user draws a new shape from the native PPT tools.
This will put your cursor in drawing mode to draw an oval. After running, you may have to click on the slide once, then the cursor will change shape and you can draw an oval:
Sub DrawOval()
Application.CommandBars.ExecuteMso ("ShapeOval")
End Sub
Other commands to substitute for ShapeOval:
ShapeRectangle
ShapeElbowConnectorArrow
ShapeStraightConnectorArrow
Get the full list in Excel spreadsheets from Microsoft Office 2016 Help Files: Office Fluent User Interface Control Identifiers
Look for the powerpointcontrols.xlsx file and search the first column with "shape"
There are 173 shapes in the menu, so you have a lot of macros to write.
I am new to VBA (since this morning so please treat me like an idiot and you will be about right!) and am stuck on something that seems as though it should be very simple.
I am working in PowerPoint and have a set of circles and below them a red and a green coloured square.
I would like to be able to select a relevant circle and then click on the appropriate square to change that circle only to red or green, as below
Select your option: O O O O O
Change colour: [Red] [Green]
At the moment I am using animations and triggers but I have LOTS of circles and I only want to change them one at a time.
+1 to Siddharth for that answer. There's another bit that won't be apparent if you're just getting started out. You can have PPT pass a reference to the clicked shape when the shape triggers a macro (caution: Mac PPT is buggy/incomplete. This won't work there).
Using Siddharth's suggestion as a jumping off point, you can do something like this:
Option Explicit
Sub SelectMe(oSh As Shape)
' assign this macro to each of the shapes you want to color
' saves time to assign it to one shape, then copy the shape as many
' times as needed.
ActivePresentation.Tags.Add "LastSelected", oSh.Name
End Sub
Sub ColorMeRed(oSh As Shape)
' assign this macro to the "color it red" shape
' when this runs because you clicked a shape assigned to run the macro,
' oSh will contain a reference to the shape you clicked
' oSh.Parent returns a reference to the slide that contains the shape
' oSh.Parent.Shapes(ActivePresentation.Tags("LastSelected")) returns a reference
' to the shape whose name is contained in the "LastSelected" tag,
' which was applied in the SelectMe macro above.
' Whew!
If Len(ActivePresentation.Tags("LastSelected")) > 0 Then
With oSh.Parent.Shapes(ActivePresentation.Tags("LastSelected"))
.Fill.ForeColor.RGB = RGB(255, 0, 0)
End With
End If
End Sub
Sub ColorMeBlue(oSh As Shape)
' assign this macro to the "color it blue" shape
If Len(ActivePresentation.Tags("LastSelected")) > 0 Then
With oSh.Parent.Shapes(ActivePresentation.Tags("LastSelected"))
.Fill.ForeColor.RGB = RGB(0, 0, 255)
End With
End If
End Sub