Advancing two slides in powerpoint VBA - 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

Related

How to make shape visible based on calculation in PowerPoint

I have a PowerPoint quiz which calculates a score. If the score is above 80% I would like a button(shape with name "PrintCert") to become visible so the user may print a certificate. Currently the button is always visible. Here is the code that I've tried with no success. (The first and last part of the code updates labels.)
Sub showresult()
Percentage.Caption = Int((CA.Caption) * 100 / (TQ.Caption)) & "%"
With ActivePresentation.Slides(37)
If ((CA.Caption) * 100 / (TQ.Caption)) > 79.9 Then
.Shapes("PrintCert").Visible = True
Else
.Shapes("PrintCert").Visible = False
End If
End With
SlideLayout41.PercentageCertificate.Caption = Percentage.Caption
ActivePresentation.SlideShowWindow.View.Next
End Sub
Simplest thing might be to add a new first slide with a "Start the show" action button that users click to begin the presentation. You'd apply a Run Macro action setting to the button and have it run a macro something like this:
Sub StartShow()
' set your button shapes to be invisible
With SlideShowWindows(1).Presentation.Slides(37)
.Shapes("PrintCert").Visible = False
End With
' etc, for any other shapes you want to have
' hidden to start with
' go to the actual first slide
SlideShowWindows(1).View.GotoSlide (2)
End Sub

VBA Excel Toggle Button: With 10 rows, how do I unhide each row separately and not in a group?

I'm working in VBA and Excel 2007 with active control toggle button, which I'm trying to figure out how to get to function the way I need it to. Will someone please help me out?
This works for only unhiding a single row at a time for two hidden rows:
Private Sub ToggleButton1_Click()
If ToggleButton1 Then
Rows(76).EntireRow.Hidden = False
Else
Rows(77).EntireRow.Hidden = False
End If
End Sub
This does not work for only unhiding a single row at a time for more than two hidden rows:
Private Sub ToggleButton1_Click()
If ToggleButton1 Then
Rows(76).EntireRow.Hidden = False
Else
Rows(77).EntireRow.Hidden = False
Else
Rows(78).EntireRow.Hidden = False
End If
End Sub
What do I need to do to get this to work? This is all I need the toggle button to do. Each row has identical information (text fields, field names, etc.), but I need each row to only become visible upon clicking just one toggle button. I know multiple toggle buttons will works like a breeze, but I really am wanting to just use one toggle button to unhide each row, one at a time. By default, the rows will be hidden first, too.
You can use a counter and then count down and you should be able to do what you are looking for. In this example if the counter is 0 we hide the rows 1-3 and then show each row untill we are back to 0 and then hide them again when we click the button.
Dim counter As Integer
Private Sub ToggleButton1_Click()
If counter = 0 Then
Rows(1).EntireRow.Hidden = True
Rows(2).EntireRow.Hidden = True
Rows(3).EntireRow.Hidden = True
counter = 3
Else
Rows(counter).EntireRow.Hidden = False
counter = counter - 1
End If
End Sub
Hope it helps
//KH
Try this:
Private Sub ToggleButton1_Click()
Dim rng As Range
Dim myrow As Range
Set rng = Me.Rows("75:85")
If Me.ToggleButton1 Then
For Each myrow In rng
If Not myrow.Hidden Then
myrow.Hidden = True
If myrow.row = 85 Then
myrow.Offset(-10, 0).Hidden = False
Else
myrow.Offset(1, 0).Hidden = False
End If
Exit For
End If
Next
End If
End Sub
This hides and unhides Rows76-85 simultaneously.
You start with all 10 Rows hidden.
After 1st click, Row 76 will appear and so on.
All will be hidden again after Row 85 was shown.
I used 10 rows based on your question title, adjust it to suit your needs.
Edit1:
Private Sub ToggleButton1_Click()
Dim rng As Range
Dim myrow As Range
Set rng = Me.Rows("76:85")
If Me.ToggleButton1 Then
For Each myrow In rng
If myrow.Hidden Then
myrow.Hidden = False
Exit Sub
End If
Next
rng.Hidden = True
End If
End Sub
Above will work as you want it.
Although you already accepted an answer, I still would want to correct my code.
At least for you and others reference.

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.

(Excel VBA) If Cell Value equals "" Then Show/Hide Images

I am working on a Excel Spreadsheet that when a dropdown box value is selected an image will pop up, and if another value is selected it will hide the current image and pop up the image related to the selection. I have found a few methods that are just too time consuming using just the sheet and positioning of the image using coordinates; that's not exactly the route I would like to go.I have done a quite a bit of research before using StackOverflow, and nothing seemed to work thus far. Below is what I am trying to achieve. I am trying to keep all the images within the spreadsheet which adds another level of challenge, but I believe there is a way to do this because excel assigns the image a number when inserted EX. Picture 9.
Sub Main()
If Range(G11).Value = "anything" Then
Picture1 show
Picture2 hide
End If
End Sub
Any Help is greatly appreciated. Thanks
Rather than hiding/moving/reducing the size of the unwanted pic, why not simply delete it?
Logic:
Save all your images in a temp sheet. When ever a relevant picture is supposed to be shown, get it from the temp sheet and delete the previous.
Here is an example.
Sub Sample()
Select Case Range("G11").Value
Case "Picture 1": ShowPicture ("Picture 1")
Case "Picture 2": ShowPicture ("Picture 2")
Case "Picture 3": ShowPicture ("Picture 3")
Case "Picture 4": ShowPicture ("Picture 4")
End Select
End Sub
Sub ShowPicture(picname As String)
'~~> The reason why I am using OERN is because it is much simpler
'~~> than looping all shapes and then deleting them. There could be
'~~> charts, command buttons and other shapes. I will have to write
'~~> extra validation code so that those shapes are not deleted.
On Error Resume Next
Sheets("Sheet1").Shapes("Picture 1").Delete
Sheets("Sheet1").Shapes("Picture 2").Delete
Sheets("Sheet1").Shapes("Picture 3").Delete
Sheets("Sheet1").Shapes("Picture 4").Delete
On Error GoTo 0
Sheets("Temp").Shapes(picname).Copy
'<~~ Alternative to the below line. You may re-position the image
'<~~ after you paste as per your requirement
Sheets("Sheet1").Range("G15").Select
Sheets("Sheet1").Paste
End Sub
Snapshot of temp sheet
Here is a solution using the Visible property of the object.
I used this to show a picture based on a value in a field.
The field had a formula that resulted in either "good" or "bad".
If its value was "good", I wanted to show one picture; for "bad", another picture should show; and they should never show at the same time.
The field needed to update its value whenever a user refreshed a pivot table, so I put the code in that method of the worksheet where the pivot table and picture were to appear.
Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
'hide both pictures by loopng through all the shapes on the sheet
Dim s As Shape
For Each s In ActiveSheet.Shapes
'hide the shape if it is a picture, leave other shapes on the page visible.
If s.Type = msoPicture Then s.Visible = msoFalse
Next
Dim judgement As String
'The field whose value tells what picture to use is a one-cell named range called "judgement"
judgement = Range("judgement")
'you need to know which picture is which.
If judgement = "Good" Then ActiveSheet.Shapes("Picture 8").Visible = True
If judgement = "Bad" Then ActiveSheet.Shapes("Picture 1").Visible = True
End Sub
Sub hidePicture(myImage)
ActiveSheet.Shapes.Range(Array(myImage)).Select
Selection.ShapeRange.Height = 0
Selection.ShapeRange.Width = 0
End Sub
Sub showPicture(myImage)
ActiveSheet.Shapes.Range(Array(myImage)).Select
Selection.ShapeRange.Height = 200
Selection.ShapeRange.Width = 300
End Sub
Handy tip: record macro and look at the code it generates!
Might be better just to move your pictures "off screen", particularly if they're of different sizes.
Sub Tester()
ShowPicture "Picture 3"
End Sub
Sub ShowPicture(PicName As String)
Dim s As Shape
For Each s In ActiveSheet.Shapes
With s
.Top = IIf(.Name = PicName, 100, 100)
.Left = IIf(.Name = PicName, 100, 1000)
End With
Next s
End Sub

Word crashes on removing a Shape with VBA from a header

(disclaimer: i'm not a VBA programmer by occupation)
Attached to buttons in the Ribbon I have code to toggle the company logo in a Word Document.
One button for the logo type A, a second button for logo type B and a third for no logo (logo is preprintend on paper)
First I remove the logo with removeLogo and then i add it the requested logo with setLogoAt.
The first button click is fine (e.g. for Logo Type A), a logo is added to the header of the document. When i click an other button (e.g for Logo Type B) Word crashes (probably on removing the current logo)
What is wrong with my code (or less probably: with Word?)
Sub setLogoAt(left As Integer, path As String)
Dim logoShape As Shape
Dim anchorLocation As Range
Dim headerShapes As Shapes
Set logoShape = ActiveDocument. 'linebreks for readability
.Sections(1)
.Headers(wdHeaderFooterPrimary)
.Shapes
.AddPicture(FileName:=path, LinkToFile:=False,
SaveWithDocument:=True, left:=0,
Top:=0, Width:=100, Height:=80)
logoShape.name = "CompanyLogo"
logoShape.RelativeHorizontalPosition = wdRelativeHorizontalPositionPage
logoShape.RelativeVerticalPosition = wdRelativeVerticalPositionPage
logoShape.Top = CentimetersToPoints(0.1)
logoShape.left = CentimetersToPoints(left)
End Sub
Sub removeLogo()
Dim headerShapes As Shapes
Set headerShapes = ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes
Dim shapeToDelete As Shape
If (headerShapes.Count > 0) Then
If Not IsNull(headerShapes("CompanyLogo")) Then
Set shapeToDelete = headerShapes("CompanyLogo")
End If
End If
If Not (shapeToDelete Is Nothing) Then
shapeToDelete.Delete
End If
End Sub
edit
I steped trough my code. All is fine until I reach the line shapteToDelete.Delete in removeLogo. Here Word crashes hard, even while debugging. I'm using Word 2007 (and that is a requirement)
edit2
I cleared all macros, all normals.dot, all autoloading templates, then created a new document with the two routines above and this test method:
Sub test()
setLogoAt 5, "C:\path\to\logo.jpg"
removeLogo
setLogoAt 6, "C:\path\to\logo.jpg"
End Sub
When I run test it crashes in removeLogo at shapeToDelete.Delete.
Edit 3
I 'solved' the problem by first making the headers/footers view the active view in Word, then deleting the Shape and then returning to normal view. Very strange. It works but as a programmer I'm not happy.
Another potential solution is to try and select the shape first and then delete the selection:
shapeToDelete.Select
Selection.Delete
You would probably want to switch off screen updating if this works, else you'll get flickering as Word moves around the document.
I've experienced this problem before and normally with an automation error: "The object invoked has disconnected from its clients". I haven't yet found a solution.
However a good workaround is to hide the shape rather than delete it.
So:
shapeToDelete.Visible = False
This works:
I only have 2 boxes to hide so this isn't generic
Private Sub btnPrint_Click()
Dim hdrShapes As Shapes
Dim S As Shape
Dim aTohide(2) As String
Dim iNdx, i As Integer
iNdx = 0
' Hide buttons and print
Set hdrShapes = ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes
' GET BUTTON NAMES (ACTUALLY TEXT BOXES
For Each S In hdrShapes
If S.Type = msoTextBox Then
aTohide(iNdx) = S.Name
iNdx = iNdx + 1
End If
Next
' now hide , use the arrays as the for each statement crashes
For i = 0 To 1
hdrShapes(aTohide(i)).Visible = msoFalse
Next
' print it
With ActiveDocument
.PrintOut
End With
' and unhide the buttons
For i = 0 To 1
hdrShapes(aTohide(i)).Visible = msoTrue
Next
Set hdrShapes = Nothing
End Sub