Impress - Go back to last shown slide

Hi!

I’m using Impress version 25.2.1.2.

I give English online classes and I’m using Impress to explain grammar. I often have to jump to ‘general rules’ to show why something is as it is and then jump back to the last slide I presented.

After some extensive search, I understand that this isn’t possible out of the can and I tried to create such a functionality using macros, which seems to be over my head.

I have cobbled this code together and annotated the different functions:

' === GLOBALS ===
Dim gLastSlideIndex As Integer
Dim gIsInitialized As Boolean
Const SHOW_DEBUG As Boolean = True ' Set to False when done testing


' === TRACK CURRENT SLIDE BEFORE JUMPING TO INDEX ===
Sub TrackCurrentSlide
    On Error Resume Next

    Dim oPres As Object, oController As Object, oShow As Object
    Dim nIdx As Integer

    oPres = ThisComponent
    oController = oPres.getCurrentController()

    If oPres.Presentation.IsRunning Then
        oShow = oController.getFrame().getController()
        nIdx = oShow.getCurrentSlideIndex()
    Else
        nIdx = oController.getCurrentPage().getPropertyValue("Number") - 1
    End If

    gLastSlideIndex = nIdx
    gIsInitialized = True

    If SHOW_DEBUG Then
        MsgBox "Tracking current slide: " & (gLastSlideIndex + 1), vbInformation, "DEBUG"
    End If
End Sub


' === BUTTON: GO TO INDEX SLIDE (e.g. SLIDE 1) ===
Sub GoToIndexWithTracking
    On Error Resume Next

    TrackCurrentSlide

    Dim oShow As Object
    oShow = ThisComponent.getCurrentController().getFrame().getController()

    If Not oShow Is Nothing Then
        oShow.gotoSlideIndex(0) ' Slide 1 = index 0
    Else
        MsgBox "Unable to access slideshow controller.", vbExclamation, "Navigation Error"
    End If
End Sub


' === BUTTON: GO BACK TO LAST RECORDED SLIDE ===
Sub GoToPreviousSlide
    On Error GoTo ErrorHandler

    If Not gIsInitialized Then
        MsgBox "First use – nothing to go back to.", vbExclamation, "NAVIGATION"
        Exit Sub
    End If

    Dim oPres As Object, oController As Object, oDrawPages As Object
    Dim oFrame As Object, oShow As Object
    Dim nTargetIdx As Integer, nCurrentIdx As Integer
    Dim sDebug As String, bIsSlideShow As Boolean

    oPres = ThisComponent
    If oPres Is Nothing Then ExitWithError("No active presentation found")

    oController = oPres.getCurrentController()
    oDrawPages = oPres.getDrawPages()
    If oDrawPages.getCount() = 0 Then ExitWithError("Presentation contains no slides")

    Set oFrame = oController.getFrame()
    Set oShow = oFrame.getController()
    bIsSlideShow = (Not oShow Is Nothing)

    If bIsSlideShow Then
        nCurrentIdx = oShow.getCurrentSlideIndex()
    Else
        nCurrentIdx = oController.getCurrentPage().getPropertyValue("Number") - 1
    End If

    nTargetIdx = gLastSlideIndex
    If nTargetIdx < 0 Or nTargetIdx >= oDrawPages.getCount() Then
        MsgBox "Invalid stored slide index.", vbCritical, "NAVIGATION ERROR"
        Exit Sub
    End If

    If SHOW_DEBUG Then
        sDebug = "DEBUG INFO:" & vbCrLf & _
                 "Current Slide: " & (nCurrentIdx + 1) & vbCrLf & _
                 "Last Stored Slide: " & (nTargetIdx + 1) & vbCrLf & _
                 "Presentation Mode: " & bIsSlideShow
        MsgBox sDebug, vbInformation, "DIAGNOSTICS"
    End If

    If nCurrentIdx = nTargetIdx Then
        MsgBox "You're already on the last tracked slide.", vbInformation, "NO ACTION"
        Exit Sub
    End If

    If bIsSlideShow Then
        oShow.gotoSlideIndex(nTargetIdx)

        If oShow.getCurrentSlideIndex() <> nTargetIdx Then
            Dim dispatcher As Object
            dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
            dispatcher.executeDispatch(oFrame, ".uno:GoToSlide", "", 0, Array())
        End If

        If oShow.getCurrentSlideIndex() <> nTargetIdx Then
            oShow.gotoSlideIndex(nTargetIdx)
        End If
    Else
        oController.setCurrentPage(oDrawPages.getByIndex(nTargetIdx))
    End If

    Dim nVerified As Integer
    If bIsSlideShow Then
        nVerified = oShow.getCurrentSlideIndex()
    Else
        nVerified = oController.getCurrentPage().getPropertyValue("Number") - 1
    End If

    If SHOW_DEBUG Then
        If nVerified = nTargetIdx Then
            MsgBox "✅ Navigation succeeded. Now on slide: " & (nVerified + 1), vbInformation, "SUCCESS"
        Else
            MsgBox "❌ Navigation failed!" & vbCrLf & _
                   "Expected: " & (nTargetIdx + 1) & vbCrLf & _
                   "Actual: " & (nVerified + 1), vbCritical, "ERROR"
        End If
    End If

    If Not oFrame Is Nothing Then oFrame.getContainerWindow().repaint()
    Exit Sub

ErrorHandler:
    MsgBox "Critical error during navigation!" & vbCrLf & _
           "Error " & Err.Number & ": " & Err.Description, vbCritical, "ERROR"
End Sub


' === ERROR MESSAGE HANDLER ===
Sub ExitWithError(sMessage As String)
    MsgBox "FATAL ERROR: " & sMessage, vbCritical, "TERMINATING"
    End
End Sub

As far as I understand it, I have to start with the sub TrackCurrentSlide to register my last slide used, then invoke using a ‘button’ the sub GoToIndexWithTracking. I always have the general rules at the position ‘slide 1’, which makes it easier to cut it out when converting to a pdf.

The sub GoToPreviousSlide should lead me back to the originating slide. I tried to track the progress using debug messages.

There are two problems I can’t overcome:

  1. When invoking GoToIndexWithTracking, the slide doesn’t change when in presentation mode.
  2. Jumping back to the originating slide is mostly wrong. It misses normally by one slide before or after.

Are there any wizards in this forum which could help me out with this? I wasn’t able to find a solution anywhere and maybe I’m just trying to invent the wheel again, in this case, please point me to an existing solution.

Thank you!

oController = ThisComponent.getPresentation().getController()

e.g. Using interactions or Macros to change text color on click - #2 by fpy
How to get information on what object was clicked on an Impress presentation? - #2 by fpy

Hi!
Thanks for reacting on my post.

I’m not sure if I follow. I have several oController lines and I’m not clear which one you are pointing at. Is this related to point 1 or 2 of my question?

but none with the correct one, actually controlling your slideshow,
and oPres.Presentation.IsRunning does not really make sense in your use case, you’re definitely in a slideshow, aren’t you ?

(ThisComponent.getCurrentController() is when you’re editing your slides)

So, using the correct controller should fix both your problems.


See also LibreOffice SDK Guide: Chapter 11. Draw/Impress APIs Overview - The Document Foundation Wiki #6._The_Slide_Show_APIs

Yes, I want to use it during the slide show, correct.

I think you are overestimating my programming skills :sweat_smile:

So I would have to switch all the ‘oController’ statements with
oController = ThisComponent.getPresentation().getController()?

I’m using the oPres.Presentation.IsRunning because I realized that when I run the macro to see if I have a syntax error, it would fail as I’m not in presentation mode.

Or are we talking just about the initialization:
oPres = ThisComponent
oController = oPres.getCurrentController()

oops. indeed …
let’s forget the cobbled code :confused:

it’s more like : Exit impress at end of slideshow - #3 by fpy

so, you basically rather need :

Global prevSlide, currSlide as Object
Global oController as Object

Sub startWithListener
  oPresentation = ThisComponent.Presentation
  Listener = createUnoListener("EV_","com.sun.star.presentation.XSlideShowListener")
  oPresentation.Start()
  wait(500)
  oController = oPresentation.Controller
  oController.addSlideShowListener(Listener)
End sub

Sub gotoPrevSlide
  oController.gotoSlide(prevSlide)
End sub 

Sub EV_slideTransitionStarted(oEv)
  prevSlide = currSlide
  currSlide = oController.getCurrentSlide()
End Sub

:warning: To work properly, the slideshow requires to be started by the macro startWithListener

image

show prev slide 120971.odp (16.4 KB)

fpy, thanks for taking your time!

I tried to run the presentation you sent me, but I get
image

as soon as I click on ‘click here to go to prev slide’.

Probably it won’t work correctly because the startWithListener isn’t active?

with startWithListener ? :thinking:

(tested on LO 24.8.5.2 / Ubuntu 24.10)

yep, I just edited my post :slight_smile:

How do I start it? I tried to include this with my ‘go to index’ button in my failed attempt.

Tools > Macros > Run Macro > …

Alright, that avoids any error message.

But, as I said in the opening post, my use case isn’t just jumping back one slide.

Imagine an English grammar lesson (riveting, I know :smiley: ) where I present a main grammar rule at the start of the presentation (slide 1). Then I explain some more stuff and go to the exercises.

During the exercise (let’s say slide 6), the students aren’t sure anymore and I want, from any slide I’m just on, to jump back to the first slide, showing the grammar rule again.

After the big “ahhhh!” moment, I would like to continue the exercises, jumping back from where I came from (in this case slide 6).

It should work like the ‘back’ button on the browser.
:slight_smile:
This should work the same from any slide I place a button, always going back to the originating one.

how ?

if you go directly, e.g. with Ctrl+Home
then the previous slide will actually be the 6.

I suspect you mean some kind of history …
like your go 6,5,4,…1 then expect back, back, back ?
(technically an easy extension with https://wiki.documentfoundation.org/Documentation/BASIC_Guide#Simple_Arrays)

how many slides you work with on average ?
maybe an actual index (at the bottom) could be easier to navigate …

Well, presenting slide after slide until the exercises start. Let’s take a simple example:
Slide 1 - General rule (with button to go back to originating slide)
Slide 2 - Exceptions
Slide 3 - Grammar structure
Slide 4 - Examples
Slide 5 - Examples
Slide 6 - Exercise (with button to slide 1)
Slide 7 - Exercise (with button to slide 1)
Slide 8 - Exercise (with button to slide 1)
.
Typically I go through the presentation slide by slide in presentation mode. That works until the exercises, where I often have to go back to the general rules on slide 1.
.
Concept:
After going slide by slide to slide 6, I would place a button linking to slide 1.
Store the slide 6 as a variable and jump to slide 1 when pressing the button.
When hitting the button to go back, it would take the stored slide 6 and jump to it.
This happens all in presentation mode!
.
No, I normally don’t need ‘back, back, back’. It’s just to get quickly and without revealing the rest of the presentation, when leaving presentation mode, back to slide 1 (rules) and then back to where I came from. I wouldn’t see any need to have an extensive index at the bottom of the page, as I’m just aiming to get quickly back and forth.
So yeah, it’s a history, but for only the invoking slide, there is no need to store more.
My presentations can be very small to about 30 slides in size.

to prevent overestimation and misunderstanding, add this button on slide 3 in my attached odp,
and see how it does work;
or attach the result here if it doesn’t work the way you expect.

Hm… Are you talking about the odp from before? show prev slide 120971.odp?
show prev slide 120971.odp (723.4 KB)

ok, this topic is geting a bit too long; it already adressed the original problem of going to any previous slide, which actually requires code, so I’ll leave it there.

you need to get yourself familiar with navigation and interaction :

show prev slide v2 120971.odp (47.6 KB)

please, open a new topic for further questions.