PDA

View Full Version : [SOLVED:] How to Randomize Only VISIBLE Slides, Not Hidden Slides??



Kellaroo
02-22-2022, 11:46 PM
Hello all, I'm trying to make my code only randomize non-hidden slides. I'm a noobie to VBA. I've just tried to figure it out logically, but I'm afraid I lack fundamental coding knowledge to solve this problem.
There are 6 slides and the code will randomize them successfully if I leave out the If statement about "SlideShowTransition.Hidden = False" - So therein lies the problem...

Sub RandomVisibleSlides ()
FirstSlide = 1
LastSlide = 6
RSN = SlideIndex
Randomize
'generate random number for Index
GRN:
RSN = Int((LastSlide - FirstSlide + 1) * Rnd + FirstSlide)
If RSN = ActivePresentation.SlideShowWindow.View.Slide.SlideIndex Then
If ActivePresentation.Slides(RSN).SlideShowTransition.Hidden = False Then GoTo GRN
ActivePresentation.SlideShowWindow.View.GotoSlide (RSN)
End Sub

My experiment PowerPoint is attached.
What am I doing wrong?

Paul_Hossler
02-23-2022, 07:00 AM
Try this

It uses SlideID and a simple bubble sort

Hidden slides are pushed to the end



Option Explicit




Sub RandomVisibleSlides()
Dim arySlides() As Long, cntSlides As Long
Dim oSlide As Slide, oPres As Presentation
Dim aryRandom() As Double
Dim i As Long, j As Long
Dim HoldRnd As Double, HoldSlide As Long

Randomize

Set oPres = ActivePresentation
cntSlides = 0
For Each oSlide In oPres.Slides
If Not oSlide.SlideShowTransition.Hidden Then
cntSlides = cntSlides + 1
ReDim Preserve arySlides(1 To cntSlides)
arySlides(cntSlides) = oSlide.SlideID
ReDim Preserve aryRandom(1 To cntSlides)
aryRandom(cntSlides) = Rnd
End If
Next


For i = LBound(arySlides) To UBound(arySlides) - 1
For j = i + 1 To UBound(arySlides)
If aryRandom(i) > aryRandom(j) Then
HoldRnd = aryRandom(i)
aryRandom(i) = aryRandom(j)
aryRandom(j) = HoldRnd

HoldSlide = arySlides(i)
arySlides(i) = arySlides(j)
arySlides(j) = HoldSlide
End If
Next j
Next i

For i = LBound(arySlides) To UBound(arySlides)
oPres.Slides.FindBySlideID(arySlides(i)).MoveTo i
Next i
End Sub

Kellaroo
02-23-2022, 08:56 PM
Hi Paul, this code is brilliant and way over my head. I read through your points at the bottom. I was unaware of #4 and now, after having read it, I can understand the reasoning behind it. Thanks for sharing.
So, this code actually helps me solve another project I had lol, but I don't think it will work for my current problem because of two reasons:
1. Each slide represents a student's name (I'm a teacher) and they have to stay in a certain classroom order. An order that reflects project grouping.
2. The randomization needs to happen between certain slides (ie 12-18) - Sorry, my mistake to not include these conditions in the original post.

I found this other post about setting a footer only on visible slides. Could this method be applied to my problem??
https://stackoverflow.com/a/35277025/9526136

Thank you for your time-

Paul_Hossler
02-23-2022, 09:33 PM
Might be easier to attach a more realistic presentation file and clearly spell out what you're looking to end up with

So the slide order is

1 - Class 1
2 Student 1
3 Student 2
4 Student 3
5 Student 4
6 Student 5
7 - Class 2
8 Student 6
9 Student 7
10 Student 8
11 Student 9
12 Student 10

And you want to randomly arrange students 1 - 5 and 6 - 10, making something like this?

1 - Class 1
2 Student 5
3 Student 3
4 Student 1
5 Student 2
6 Student 4
7 - Class 2
8 Student 9
9 Student 7
10 Student 6
11 Student 10
12 Student 8

It's easy enough to input a From - To (e.g. 6 - 10) and sort just those if there is no way to identify the Class

If there's a Class lead in slide that is identifiable, we can use that also


Do you really need hidden slides if you can sort within a classroom?

Kellaroo
02-23-2022, 10:09 PM
Good suggestion. I tried to revise the PPT I originally posted to give a more accurate representation of my goal.
The code should just GoTo /hyperlink to a student's slide, but not change the order of the slides.
They need to stay in the same order index day after day.
Some students will be absent quite often, and on those days I will hide their slides.
My problem is that my current Randomizer still jumps to 'hidden' slides.

Thank you for your time-

Kellaroo
02-23-2022, 10:14 PM
I forgot to reply to your last question.
I guess I don't need to hide the slides of students who are absent, but I can't think of another way to omit their slides from the randomizer on days they are absent.
We will use the randomizer quite often, and if it's jumping to students who aren't present half the time then it will be really lagging on our tempo/efficiency.

Is it possible to randomly select from a range of objects (ie. objects that are hyperlinks) but not randomize those objects that are hidden? Perhaps this angle of approach would be easier.

Paul_Hossler
02-23-2022, 10:23 PM
Hello all, I'm trying to make my code only randomize non-hidden slides.


So you didn't really mean that you wanted to rearrange the non-hidden slides in a random order, but just pick a non-hidden slide from a classroom subset


Class 1
Student 1
Student 2
Student 3 (Hidden - don't pick)
Student 4
Student 5

Class 2
Student 6
Student 7 (Hidden - don't pick)
Student 8
Student 9 (Hidden - don't pick)
Student 10

So pick 1, 2, 4, or 5 at random and pick 6, 8, or 10 at random, but leave the slides in the original order?

Kellaroo
02-23-2022, 10:25 PM
Exactly right. That's what I mean to say.

Kellaroo
02-23-2022, 10:33 PM
Also, just to be clear - The 'hidden' slides will change from class to class, day to day. Much like an attendance sheet.

Paul_Hossler
02-23-2022, 11:14 PM
Try the attachment - barebones and needs some prettying-up




Option Explicit


Dim arySlides() As Long, cntSlides As Long
Dim aryRandom() As Double
Dim oPres As Presentation


Sub PickSlide(oShapeIn As Shape)


Call SetupRandomVisibleSlides

Select Case oShapeIn.Name
Case "Class 1"
Call GotoSlide(1)
Case "Class 2"
Call GotoSlide(2)
End Select
End Sub


Private Sub GotoSlide(ClassNum As Double)
Dim i As Long

For i = LBound(aryRandom) To UBound(aryRandom)
If aryRandom(i) = ClassNum Then
SlideShowWindows(1).View.GotoSlide arySlides(i + 1)
Exit Sub
End If
Next i


End Sub




Private Sub SetupRandomVisibleSlides()
Dim oSlide As Slide, oShape As Shape
Dim i As Long, j As Long
Dim HoldRnd As Double, HoldSlide As Long
Dim cntGroup As Double

Randomize

Set oPres = ActivePresentation

cntSlides = 0
cntGroup = 0#

For Each oSlide In oPres.Slides
For Each oShape In oSlide.Shapes
If oShape.Type = msoPlaceholder Then
If oShape.PlaceholderFormat.Type = ppPlaceholderTitle Then
If oShape.TextFrame.HasText Then
If LCase(oShape.TextFrame.TextRange.Text) Like "class*" Then
cntGroup = cntGroup + 1
cntSlides = cntSlides + 1
ReDim Preserve arySlides(1 To cntSlides)
arySlides(cntSlides) = oSlide.SlideNumber
ReDim Preserve aryRandom(1 To cntSlides)
aryRandom(cntSlides) = cntGroup
GoTo NextSlide
End If
End If
End If
End If
Next oShape

If cntGroup = 0 Then GoTo NextSlide

If Not oSlide.SlideShowTransition.Hidden Then
cntSlides = cntSlides + 1
ReDim Preserve arySlides(1 To cntSlides)
arySlides(cntSlides) = oSlide.SlideNumber
ReDim Preserve aryRandom(1 To cntSlides)
aryRandom(cntSlides) = cntGroup + Rnd
End If

NextSlide:
Next oSlide




For i = LBound(arySlides) To UBound(arySlides) - 1
For j = i + 1 To UBound(arySlides)
If aryRandom(i) > aryRandom(j) Then
HoldRnd = aryRandom(i)
aryRandom(i) = aryRandom(j)
aryRandom(j) = HoldRnd

HoldSlide = arySlides(i)
arySlides(i) = arySlides(j)
arySlides(j) = HoldSlide
End If
Next j
Next i
End Sub

Kellaroo
02-23-2022, 11:31 PM
Wow. It's brilliant and it works.
I will need to pore over this for hours to understand better, but am looking forward to that.
Could this code be modified to for no repeats? As in, not the same student back-to-back.

Sorry to bring this up now, but I'm suddenly starting to believe that all things are possible lol.

Paul_Hossler
02-23-2022, 11:42 PM
Wow. It's brilliant and it works.
I will need to pore over this for hours to understand better, but am looking forward to that.
Could this code be modified to for no repeats? As in, not the same student back-to-back.

Sorry to bring this up now, but I'm suddenly starting to believe that all things are possible lol.




it works.

Don't sound so surprised :devil2:

So now you want to go through each class' students in a random order

Class 1
Student 6
Student 3
Student2

and then back to the intro slide?

Right now they're re-randomize each time you click a class button o the first slide

Kellaroo
02-23-2022, 11:56 PM
I'm a teacher. I'm not really used to things working out lol

Good insight^. Now that I've thought about it more- Ideally I'd want it to be like:
Main Slide
Student 6
Return to Main
Student 2 (not Student 6)
Return to Main
Next Student (not Student 2)
Return to Main
Possibly Student 6 again

The same student could be up for discussion more than once, or more than other students, but not back-to-back consecutive.

Paul_Hossler
02-24-2022, 12:18 AM
That's harder since it requires housekeeping while you're in a class, and clearing if you go to another class

Look at this version

The [Next] action button takes you to the next random student in that class, with the last one returning you to slide 1. Clicking a Class button re-randomizes

Kellaroo
02-24-2022, 09:04 PM
Paul,
I pored over your coding for some hours. I still don't understand it really but I've successfully implemented it with previous classroom PPTs. It works wonderfully! This is going to add a level of sophistication to group discussion previously not thought possible! You're a wizard : )
Thank You!

Paul_Hossler
02-24-2022, 10:52 PM
Good

I added some comments to the code and a few explanations via screen clips to the slides

Feel free to come back


On the subject on comments ....

this is just my personal style / opinion / way of doing things

1. IMVHO a comment should provide information about why something is being done, and not just a free form English repeat of the code

2. I like to avoid 'magic numbers', e.g. 0.06 ("where did THAT come from) and use meaningful Const's and variables, Const SaleTaxRate = 0.06


This is an Excel example



Option Explicit

Sub NotGoodComments()
'define variables
Dim i As Long

'go from 4 to a long way down
For i = 4 To 10000
'Multiply inputs to get outputs
Cells(i, 3) = Cells(i, 4) * Cells(i, 5)

'if col B is empty
If Cells(i + 1, 2) = "" Then
'get out
GoTo Done
End If
'get another row
Next i

Done:
' blah blah blah


End Sub


Sub BetterComments()
Const rowStartOfRealData As Long = 4
Const colSalePerson As Long = 2
Const colSales As Long = 3
Const colQty As Long = 4
Const colUnitCost As Long = 5

Dim rowData As Long


'go down all sales persons until there are no more
For rowData = rowStartOfRealData To Cells(rowStartOfRealData, colSalePerson).End(xlDown).Row

'if there is no sales person in this row, we finished
If Cells(rowData + 1, colSalePerson) = "" Then Exit For

'Sales = Qty x Cost
Cells(rowData, colSales) = Cells(rowData, colQty) * Cells(rowData, colUnitCost)

Next rowData

' blah blah blah


End Sub

Kellaroo
02-26-2022, 09:18 PM
Annotated coding! The answer to all my riddles : )
On behalf of myself and every other VBA-newbie teacher who may find their way here - Thank You!

Tyas
11-14-2023, 03:07 PM
Try this

It uses SlideID and a simple bubble sort

Hidden slides are pushed to the end



Option Explicit




Sub RandomVisibleSlides()
Dim arySlides() As Long, cntSlides As Long
Dim oSlide As Slide, oPres As Presentation
Dim aryRandom() As Double
Dim i As Long, j As Long
Dim HoldRnd As Double, HoldSlide As Long

Randomize

Set oPres = ActivePresentation
cntSlides = 0
For Each oSlide In oPres.Slides
If Not oSlide.SlideShowTransition.Hidden Then
cntSlides = cntSlides + 1
ReDim Preserve arySlides(1 To cntSlides)
arySlides(cntSlides) = oSlide.SlideID
ReDim Preserve aryRandom(1 To cntSlides)
aryRandom(cntSlides) = Rnd
End If
Next


For i = LBound(arySlides) To UBound(arySlides) - 1
For j = i + 1 To UBound(arySlides)
If aryRandom(i) > aryRandom(j) Then
HoldRnd = aryRandom(i)
aryRandom(i) = aryRandom(j)
aryRandom(j) = HoldRnd

HoldSlide = arySlides(i)
arySlides(i) = arySlides(j)
arySlides(j) = HoldSlide
End If
Next j
Next i

For i = LBound(arySlides) To UBound(arySlides)
oPres.Slides.FindBySlideID(arySlides(i)).MoveTo i
Next i
End Sub



This code works perfect, but is works for all sheets in my slideshow.
Is it also posible to this with a small selections of sheets, so sheet 19 till 23?

Greetz Tyas