How to change the text of the clicked button? - vba

I'm trying to make a macro where it will change the text of the button that is clicked by the user.
I already tried the oShape declaration mentioned in Microsoft's forum.
Here's what I have:
Sub changeLetter(oShape As Shape)
If ActivePresentation.Slides(oShape.Parent.SlideID).Shapes(oShape.Name).TextFrame.TextRange.Text = "a" Then
ActivePresentation.Slides(oShape.Parent.SlideID).Shapes(oShape.Name).TextFrame.TextRange.Text = "b"
ElseIf ActivePresentation.Slides(oShape.Parent.SlideID).Shapes(oShape.Name).TextFrame.TextRange.Text = "b" Then
ActivePresentation.Slides(oShape.Parent.SlideID).Shapes(oShape.Name).TextFrame.TextRange.Text = "a"
End If
End Sub
What I have here is a toggle between "a" and "b".
EDIT: I decided to use command buttons instead:
Private Sub letter1_Click()
If letter1.Caption = "a" Then
letter1.Caption = "b"
ElseIf letter1.Caption = "b" Then
letter1.Caption = "a"
End If
End Sub

Is there some reason you're starting with a known shape (handed to you in oShape) and backing up to the parent slide only to work your way down the object hierarchy to the shape again?
Assuming you're using Windows PPT, try this instead:
Sub changeLetter(oShape As Shape)
With oShape.TextFrame.TextRange
Select Case .Text
Case Is = "a"
.Text = "b"
Case Is = "b"
.Text = "a"
Case Else
' do nothing
End Select
End With
End Sub
If you're on Mac, it Thinks Different, of course, but there's a way around it. Either way, this requires that you assign a Run Macro action setting so your macro runs when the shape is clicked, and it only works in slide show view.

Related

Repeating legacy option buttons within a repeating section

I am currently attempting to turn a form I am working on into a more dynamic one using vba in word, but I am facing two issues with the option buttons within a repeating section:
The code is not dynamic; when I run the code it does what I need it to but doesn't dynamically recalculate as I change my choice.
The option buttons do not repeat when I add a new section, and the only way for me to include them is by readding them and creating a new module specific for the new option button group.
Below is a picture of the section I am repeating and the code I am using.
enter image description here
Private Sub Yes_Click()
Dim k(0 To 3) As String
k(0) = "Select one"
k(1) = "Pass"
k(2) = "Fail"
k(3) = "N/A"
Dim i As Long
If Yes = True Then
Me.Controls.Clear
Me.Controls1.Clear
For i = 0 To 3
Me.Controls.AddItem k(i)
Me.Controls1.AddItem k(i)
Next i
End If
On Error Resume Next
Me.Controls = "Select one"
Me.Controls1 = "Select one"
If Yes = False Then
Me.Controls = "N/A"
Me.Controls1 = "N/A"
End If
On Error Resume Next
End Sub
Is there a way to approach either issues?
Thanks in advance.

VBA Expand/Collapse rows

I have a report in which I am asking the users to click buttons to reveal where they need to add their commentary. I have it working but wanted to put in an If statement in case they have already expanded the row.
I have two macros, the first relates to the button they push and sends to the main macro the name of the button and a row number which is part of the section that is either expanded or collapsed
Sub ROccupancy()
'
Dim RecName As String
RecName = "ROccupancy"
Dim RowNum As Integer
RowNum = 27
Call ToogleRec(RecName, RowNum)
End Sub
The next macro is where I am having the trouble
Sub ToogleRec(RecName, RowNum)
'
Dim Toogle As String
Dim MyObj As Object
Set MyObj = ActiveSheet.Shapes.Range(Array(RecName))
Toogle = Left(MyObj.TextFrame2.TextRange.Characters.Text, 4)
TextName = Mid(MyObj.TextFrame2.TextRange.Characters.Text, 5, 100)
If Toogle = "Show" Then
MyObj.ShapeStyle = msoShapeStylePreset9
MyObj.TextFrame2.TextRange.Characters.Text = _
"Hide" & TextName
MsgBox Rows(RowNum).ShowDetail
If Rows(RowNum).ShowDetail = False Then
Rows(RowNum).ShowDetail = True
End If
Else
MyObj.ShapeStyle = msoShapeStylePreset11
MyObj.TextFrame2.TextRange.Characters.Text = _
"Show" & TextName
MsgBox Rows(RowNum).ShowDetail
If Rows(RowNum).ShowDetail = True Then
Rows(RowNum).ShowDetail = False
End If
End If
Range("C" & RowNum).Select
End Sub
The issue is the Rows(RowNum).ShowDetail is always TRUE, no matter if it's expanded or collapsed. I can remove the If section and set it to TRUE or FALSE using "Rows(RowNum).ShowDetail = False" or "Rows(RowNum).ShowDetail = TRUE". However, if the user has manually expanded or collapsed the row it causes an error (which freaks them out)
This question and answer seemed promising but Rows(RowNum).ShowDetail always seems to be TRUE
I put the MsgBox in there for error checking. I'll remove it in the final version.
Have you tried using Hidden property? Something like:
With Sheet1.Rows(5)
.ShowDetail = .Hidden
End With
Take note though that for you to use .ShowDetail method, you'll need to Group the rows first (needs to be in outline form).
True if the outline is expanded for the specified range (so that the detail of the column or row is visible). The specified range must be a single summary column or row in an outline.
Above code toggles hiding/unhiding a grouped row 5. You don't even need an If statement for the toggling. HTH.

Word 2010 VBA make a table and text disappear

I am working on a word document and made a command button that is suppose to hide a table. Now when I first set it, I thought I got it working I got it all styled and titled and when I clicked the button the table would disappear.
Then I saved it and closed the document but when I opened up the document I saw that the only thing that was hidden was the words inside the table, the table lines are not hidden and when I toggle the button the only thing hiding is the text.
Is there something I am doing wrong ? Here is the code in VBA
Private Sub CommandButton1_Click()
ThisDocument.Styles("HideText").Font.Hidden = Not ThisDocument.Styles("HideText").Font.Hidden
End Sub
I just want the button to toggle the text and the Table to hide every time it the button is pressed and when the document is open and closed.
Update may be on to something the table has its own style as well. should I be targeting that as well as the text within the style ? is that what is happening ?
Update #2
I was able to now hide and unhide the section of the table I wanted but it doesn't bring up the lines after I make the table visible. So is there a way to get the table grid to show up with the click of the button?
here is what I have so far.
Private Sub CommandButton1_Click()
ThisDocument.Styles("HideText").Font.Hidden = Not ThisDocument.Styles("HideText").Font.Hidden
'Table Grid
Dim s As Style
Dim An As Integer
An = 0
If An = 0 Then
For Each s In ActiveDocument.Styles
If s.Type = wdStyleTypeTable Then
If s.NameLocal = "Table Grid" Then
Debug.Print (s.NameLocal)
s.Visibility = False
s.UnhideWhenUsed = False
Call s.Delete
End If
End If
Next
An = 1
End If
If An = 1 Then
For Each s In ActiveDocument.Styles
If s.Type = wdStyleTypeTable Then
If s.NameLocal = "Table Grid" Then
Debug.Print (s.NameLocal)
s.Visibility = True
s.UnhideWhenUsed = True
Call s.Delete
End If
End If
Next
An = 0
End If
End Sub
I'd approach this by hiding the font of the table (as below) rather than attempting to hide a specific font style which you're using within the table.
You could try something along the lines of:
Public sub CommandButton1_Click()
With ActiveDocument.Tables(1).Range.Font
.Hidden = Not .Hidden
End With
End Sub

Advancing two slides in powerpoint VBA

I am trying to advance slides based on a response. I want to go forward 2 slides if the user selects easy and one if they select hard. This is my current code. The Nextpage script isn't working AND I would prefer for it to be usable for multiple questions--I can't seem to get it to work with something like slide +1 or slide +2 (or ++).
Sub Start()
ActivePresentation.Slides(2).Shapes("selection_hard").Visible = False
ActivePresentation.Slides(2).Shapes("selection_easy").Visible = False
ActivePresentation.SlideShowWindow.View.Next
End Sub
Sub Shoe_Easy()
ShoeAnswer = "Easy"
ActivePresentation.Slides(2).Shapes("selection_hard").Visible = False
ActivePresentation.Slides(2).Shapes("selection_easy").Visible = True
'ActivePresentation.SlideShowWindow.View.GotoSlide (11)
End Sub
Sub Shoe_Hard()
ShoeAnswer = "Hard"
ActivePresentation.Slides(2).Shapes("selection_hard").Visible = True
ActivePresentation.Slides(2).Shapes("selection_easy").Visible = False
'ActivePresentation.SlideShowWindow.View.GotoSlide (12)
End Sub
Sub Nextpage()
If ActivePresentation.Slides(2).Shapes("selection_hard").Visisble = True Then
ActivePresentation.SlideShowWindow.View.GotoSlide (3)
ElseIf ActivePresenation.Slides(2).Shapes("selection_easy").Visible = True Then
ActivePresenation.SlideShowWindow.View.GotoSlide (4)
End If
End Sub
Assuming that "response" means clicking on one of two shapes (Easy or Hard), this will do it. You just need to make sure that the text in the shape and the code below match up and that you assign the HandleClick macro as a RunMacro action setting to each of the shapes (assign them to two of them then copy/paste the shapes elsewhere as needed).
There are a few extra hoops to jump through to get this working on a Mac; shout if you need it to work there too.
Sub HandleClick(oSh As Shape)
' Did they click the Easy or Hard button?
' oSh contains a reference to the shape they clicked
' Look a the text in oSh to decide where to go next:
Select Case UCase(oSh.TextFrame.TextRange.Text)
Case Is = "EASY"
SlideShowWindows(1).View.GotoSlide (oSh.Parent.SlideIndex + 2)
Case Is = "HARD"
SlideShowWindows(1).View.GotoSlide (oSh.Parent.SlideIndex + 1)
Case Else
' Do nothing
End Select
End Sub
This immediately advances the slide as soon as it's clicked. If you want the user to be able to choose an answer and then advance, you'd need a different approach.
Instead of advancing immediately as above, you'd set the value of a global variable to, say, "EASY" or "HARD", depending on the user's selection.
Then in a separate macro assigned to your forward button, you'd advance one or two slides depending on the value of the global variable.
I think something like this might help:
Nextpage()
Dim currentSlide as Slide
Set currentSlide = ActivePresentation.SlideshowWindow.View.Slide
If ActivePresentation.Slides(2).Shapes("selection_hard").Visisble = True Then
ActivePresentation.SlideShowWindow.View.GotoSlide currentSlide.SlideIndex + 1
ElseIf ActivePresenation.Slides(2).Shapes("selection_easy").Visible = True Then
ActivePresenation.SlideShowWindow.View.GotoSlide currentSlide.SlideIndex + 2
End If
End Sub

VBA Grey Checkboxes

I would like to grey out my checkboxes in Excel VBA. When using Checkbox.Enabled = False, the checkbox is not editable, but it is also not grey. How do I get the greyed out effect?
Using form controls with Excel 2010. Inserted via developer tab directly into excel worksheet. Not used in a VBA userform.
Thanks!
Whenever anyone says "it is impossible", it hits my stubborn streak. So may I present to you: "The Impossible".
"Visible" and enabled checkbox:
"Disabled" checkbox (you can tweak the degree of visibility by changing values in the code for both color and transparency of the cover shape):
Basic idea: you place a semi transparent shape over the checkbox, and assign a dummy macro to it. Now you can't change the value of the checkbox. The "toggle" button is there to change the state - either place the shapes, or remove them. It uses a global variable to track the current state.
Finally - note that you can't use For Each when you delete (or add) shapes as you should not modify the collection you are iterating over. I circumvented that with a simple "count shapes, then iterate backwards by numerical index".
Is it a hack? You bet! Does it do what you asked? Yes!
Dim checkBoxesVisible As Boolean
Option Explicit
Sub toggleIt()
' macro assigned to "Toggle visibility" button
checkBoxesVisible = Not checkBoxesVisible
toggleCheckboxes checkBoxesVisible
End Sub
Sub grayOut(cb)
' put a "cover" shape over a checkbox
' change the color and transparency to adjust the appearance
Dim cover As Shape
Set cover = ActiveSheet.Shapes.AddShape(msoShapeRectangle, cb.Left, cb.Top, cb.Width, cb.Height)
With cover
.Line.Visible = msoFalse
With .Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 255, 255)
.Transparency = 0.4
.Solid
End With
End With
cover.Name = "cover"
cover.OnAction = "doNothing"
End Sub
Sub doNothing()
' dummy macro to assign to cover shapes
End Sub
Sub unGray(cb)
' find the cover shape for the checkbox passed as the argument
' and delete it
' "correct shape" has the name "cover" and is properly aligned with top left
Dim sh As Shape
For Each sh In ActiveSheet.Shapes
If sh.Name = "cover" And sh.Left = cb.Left And sh.Top = cb.Top Then
sh.Delete
Exit For
End If
Next sh
End Sub
Sub toggleCheckboxes(onOff)
Dim s As Shape
Dim n As Integer, ii As Integer
n = ActiveSheet.Shapes.Count
' loop backwards over shapes: if you do a "For Each" you get in trouble
' when you delete things!
For ii = n To 1 Step -1
Set s = ActiveSheet.Shapes(ii)
If s.Type = msoFormControl Then
If s.FormControlType = xlCheckBox Then
If onOff Then
unGray s
Else
grayOut s
End If
End If
End If
Next ii
End Sub
A slight hack - but the following does work. I created a simple userform with two controls - a regular checkbox (CheckBox1), and a button I called "DisableButton" with the following code:
Private Sub DisableButton_Click()
CheckBox1.Enabled = Not (CheckBox1.Enabled)
If CheckBox1.Enabled Then
CheckBox1.ForeColor = RGB(0, 0, 0)
Else
CheckBox1.ForeColor = RGB(128, 128, 128)
End If
End Sub
When I clicked the button, the checkbox was grayed out and unavailable. Clicking it again "brought it back to life". I think this is the effect you were looking for. If it's not - that's what comments are for.
Here is what it looks like:
I am afraid it is impossible what you are trying to do within a worksheet. You can refer to the Floris' answer if you are using an UserForm.
For more details on the properties of (Form/worksheet) check boxes see MSDN
Maybe this is what you want.
Private Sub CheckBox1_Click()
If CheckBox1.Value = True Then
CheckBox2.Value = False
CheckBox2.Enabled = False
CheckBox2.ForeColor = rgbBlue
Else
CheckBox2.Visible = True
CheckBox2.ForeColor = rgbAntiqueWhite
CheckBox2.Enabled = True
End If
Code tels that when checkbox1 is checked, checkbox2 is disabled; unchecked and the forecollor changes. the colors can be what you want.
Did this with the checkboxes directly in the excel worksheet.
Based on Floris' idea.
The code assumes all the controls are on ActiveSheet and they are called CheckBox1 and CheckBox2, if not, change it accordingly.
You can call this when you click on CheckBox1 or you can call it from another sub, with an optional ticked status (True/False) to check or uncheck CheckBox1.
Draw an object on top of CheckBox2 and name it "mask" (you can name it anything else but then you have to change the code accordingly)
Give mask the same fill color as your background color and opacity of around 50%.
Public Sub CheckBox1_Click(Optional ticked As Variant)
Application.ScreenUpdating = False
ActiveSheet.Unprotect
If Not IsMissing(ticked) Then
If ticked = True Then ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value = 1 Else ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value = -4146
End If
If ActiveSheet.Shapes("CheckBox1").OLEFormat.Object.Value > 0 Then
ActiveSheet.Shapes("mask").OLEFormat.Object.ShapeRange.ZOrder msoSendToBack
Else
ActiveSheet.Shapes("mask").OLEFormat.Object.ShapeRange.ZOrder msoBringToFront
End If
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
Application.ScreenUpdating = True
End Sub
Now each time you tick CheckBox1, mask comes to front to hide CheckBox2 and when you untick it, mask goes to back to unhide it. Since it is opaque, it gives you the greyed out effect and you don't even have to worry about enable/disable either.
Worksheet should be protected so that user can't accidentally move or edit mask, but should be unprotected for SendToBack/BringToFront to work, so the code does that. Please check the protection settings at the Application.Protect part.