Bring Writer macro cursor into view?

The following simple macro does move the View and Text cursors, but the document does not scroll to their position.

Sub eofTEST
dim dispatcher, oText as Object
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
oViewCursor = ThisComponent.CurrentController.ViewCursor

Dim oTextCursor
oText = ThisComponent.Text
oTextCursor = oText.createTextCursorByRange(oViewCursor)

Rem 	go to doc end:
oViewCursor.gotoEnd(False)
oTextCursor.gotoRange(oViewCursor, False)

Rem  All this seems to work, but doc does not SCROLL to the cursors
end Sub

Also, a simple recorded macro, capturing Ctrl-End, does not work either:

sub EOF_TEST1
dim document   as object
dim dispatcher as object
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(document, ".uno:GoToEndOfDoc", "", 0, Array())
end sub

So how does one scroll a Writer document to the current position of one of the macro cursors?

Thanks much.

Use method oViewCursor.gotoRange(…) to scroll visible cursor :slight_smile:

In my first example above I have:

oViewCursor.gotoEnd(False)
oTextCursor.gotoRange(oViewCursor, False)

What am I missing?

In general, it is not necessary to move the visible cursor to manipulate the text, but…

    doc = ThisComponent
    oViewCursor = doc.CurrentController.ViewCursor
    oViewCursor.gotoRange(doc.Text.End, False)

Adding that to a basic macro:

Sub eofTEST
dim dispatcher, oText as Object
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
oViewCursor = ThisComponent.CurrentController.ViewCursor

Dim oTextCursor
oText = ThisComponent.Text
oTextCursor = oText.createTextCursorByRange(oViewCursor)

doc = ThisComponent
oViewCursor.gotoRange(doc.Text.End, False)
end Sub

As before, the cursors do go to the doc end, but the scrolling does not.

If you run macro from Writer menu Tools/ Macros/ Run macro then it is functional, but run in Basic editor doesn’t scroll the view cursor - it is interesting finding, I din’t know about it. :slight_smile:
But it is possible to “activate” the doc window.

Sub eofTEST
	dim doc as object, oViewCursor as object
	doc=ThisComponent
	doc.CurrentController.Frame.ContainerWindow.toFront() 'doc window to top
	oViewCursor=doc.CurrentController.ViewCursor
	oViewCursor.gotoRange(doc.Text.End, false)
End Sub

@KamilLanda This is true, I see. oViewCursor.gotoRange(doc.Text.End, false) doesn’t work from within the BASIC editor, and it doesn’t work when in an autorun macro attached to a file’s opening, which is what I’m trying to achieve. But it does work when called manually from within the document itself.

I also tested your macro, above. From the BASIC editor it does activate the document, but it does not scroll to the document end.

BTW, a simple oViewCursor.gotoEnd (If I have that correct) used to work fine in my autorun macro. But a few months ago or so it stopped working. At this point I think something broke.

The controller deals with selections. Your view cursor selects text invisibly for your Basic program.
I don’t know how to select anything in Writer, but you may get the idea in the last line:

Sub eofTEST
	doc=ThisComponent
	view = doc.CurrentController
	frame = view.Frame
	win = frame.ContainerWindow.toFront() 'doc window to top
	frame.activate()
	oViewCursor = view.ViewCursor
	oViewCursor.gotoRange(doc.Text.End, false)
view.select(oViewCursor) ' fails too
End Sub

In my laptop it is functional and macro scrolls to the end of document from document and also from Basic Editor, I don’t know where the problem is :-(. Libre 7.3.3.1 Win10x64
​
But adding the macro for view cursor to the Open Document Event is problematic. Loading the bigger document to memory isn’t immediate and the macro is run sooner than document is all in memory.
I add the macro to the Open Document Event and tested both, oViewCursor.goToRange(doc.Text.End, false) and oViewCursor.goToEnd(false).
With 6-pages document after Open it jumped only to 5th page :-(. But for 184-pages document it jumped to the end.
​
I know there was some change for loading the documents to the memory some months ago. The documents are rendering during loading ones to the memory, so some first pages are rendered sooner than all document is in memory.
​
test: Open some big document and press Ctrl+End immediately → and visible cursor will jump to the end of document, but probably you will see it isn’t real last page. And the scrollbar will move the scroll fixture upper, how the rest of document is loaded to the memory. Or maybe after Ctrl+End the rendered document-pages in your Libreoffice window will be changed several times than all document is loaded into memory.
​
Unfortunately I don’t know how to solve it :-(.

I’m on 7.3.0.3 / Linux here. I’ll do an update later.

In my actual macro, I do other things before visibly scrolling to the end. I test if the file has been saved already on the current date, I create a couple of blank paragraphs and change paragraph style, I call another macro which inserts the date, and then finally I move the visible focus to the end, which now doesn’t work. All those other things are still performing perfectly, and the oViewCursor is at the EOF, which tells me this is not a doc loading problem. The doc in question is 738kb in size, with basic formatting except for a ToC, and my processor is a capable Ryzen 5.

And other methods of visible cursor?

Sub eofTEST
	dim doc as object, oViewCursor as object
	doc=ThisComponent
	doc.CurrentController.Frame.ContainerWindow.toFront() 'bring doc window to top
	oViewCursor=doc.CurrentController.ViewCursor
	oViewCursor.jumpToLastPage()
	oViewCursor.jumpToEndOfPage()
End Sub

or “complicated”

Sub eofTEST2
	dim doc as object, oViewCursor as object
	doc=ThisComponent
	doc.CurrentController.Frame.ContainerWindow.toFront() 'bring doc window to top
	oViewCursor=doc.CurrentController.ViewCursor
	oViewCursor.goToEnd(false)
	oViewCursor.jumpToPreviousPage()
	oViewCursor.jumpToNextPage()
	oViewCursor.jumpToEndOfPage()
End Sub

Along with the previous suggestion, I tried the first example, above, now in LO 7.3.3.1, and it’s still not working. I think the code is correct; something is wrong under the hood.

So it seems as bug under some Linux :frowning:. If you think it is bug, you can report it to Bugzilla How to Report Bugs in LibreOffice - The Document Foundation Wiki

This works for me with the “View created” event:

Sub eofTEST
	doc=ThisComponent
	view = doc.CurrentController
	frame = view.Frame
	win = frame.ContainerWindow.toFront() 'doc window to top
	frame.activate()
	wait 200
	exec_Dispatch(frame, ".uno:GoToEndOfDoc")
End Sub


sub exec_Dispatch(frame, sCmd, optional sTarget, optional n, optional args)
if ismissing(sTarget) then sTarget = ""
if ismissing(n) then n = 0
if ismissing(args) then args = Array()
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(frame, sCmd, sTarget, n, args)
end sub
1 Like