Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

Hallo,

mit z.B. (http://www.dannenhoefer.de/faqstarbasic ... tteln.html):

Code: Alles auswählen

myDoc=thisComponent
myViewCursor=myDoc.GetCurrentController.ViewCursor
page=myViewCursor.getPage()
Msgbox page
kann man die Seitennummer der Seite ermitteln auf der der View-Cursor sich gerade befindet. Dabei liefert .getPage() jedoch die physische Seitennummer, welche bei Dokumenten mit manuellen Seitenumbrüchen und Neubeginn von Seitenzählung (bzw. festgelegtem Offset der Zeilenzählung bei einem Seitenumbruch) nicht der tatsächlichen Seitennummer entspricht.

Zur Verdeutlichung ein Screenshot, bei dem obiges Makro die Nummer x liefert, jedoch die Nummer y liefern soll:
Makroergebnis.gif
Makroergebnis.gif (22.5 KiB) 6888 mal betrachtet

Hat jemand eine Lösung?


Gruß
Stephan
Toxitom
********
Beiträge: 3768
Registriert: Di, 12.08.2003 18:07
Wohnort: Wiesbaden
Kontaktdaten:

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Toxitom »

Hey Stepfan,

die Lösung ist :

Code: Alles auswählen

page=myViewCursor.getPage()   'liefert die aktuelle Seitenzahl des Cursors
pageoffset = myViewCursor.PageNumberOffset 'liefert den Startwert der Seitenzählung 
Soweit sogut - wenn also die Zählung bei physikaisch Seite 1 beginnt - die erste Seite aber das Offset 200 hat, wäre die angezeigte Seitennummer eben 200 + 1 -1

Schwierig wird es erst, wenn das Offset mitten im Dokument gesetzt weird - dann musst Du das erst herausbekommen....

Viele Grüße
Tom
Unterstützer LibreOffice, zertifizierter Trainer und Berater
Bücher: LibreOffice 6- Einstieg und Umstieg
Makros Grundlagen - LibreOffice / OpenOffice Basic
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

die Lösung ist : [...]
Danke, .PageNumberOffset war mir tatsächlich noch nicht auf- bzw. ein-gefallen.
Schwierig wird es erst, wenn das Offset mitten im Dokument gesetzt weird - dann musst Du das erst herausbekommen....
Und das ist wohl leider genau das Problem (naja, es kostet wieder Rechenzeit und das Makro rechnet jetzt schon 'ewig').
Die Seitenzahlen im Screenshot sind real und das dort der OO/LO-typische Blindtext steht dient nur dazu den Realtext (eines Kunden) hier nicht ins Forum zu stellen. In Realität ist das ein ziemlich langes Dokument, das in steter Bearbeitung begriffen ist und ich kann nicht sicher sein das sich einmal vorhandene manuelle Umbrüche nicht ändern.


Gruß
Stephan
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo

Ich bin soweit gekommen:

Code: Alles auswählen

def pagenum():
    doc =XSCRIPTCONTEXT.getDocument()

    viewcursor = doc.CurrentController.ViewCursor
    current = viewcursor.Start
    viewcursor.jumpToStartOfPage()
    corr = 0
    while True:
        offset =  viewcursor.PageNumberOffset
        if offset:
            break
        corr += 1
        viewcursor.jumpToPreviousPage()
        viewcursor.jumpToStartOfPage()

    page = corr + offset
    viewcursor.gotoRange(current, False) 
mit dem Schönheitsfehler:
- Es wird nur der letzte vorhergehende Offset berücksichtigt.
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

ich hatte zwar nicht vor dafür Python zu benutzen, aber viewcursor.jump...Page() ist eine prima Anregung (ich hatte zunächst vor durch Absätze zu interieren, was ja garnicht nötig ist)


Damit ich noch gleich etwas lerne, sag mir doch bitte:

Warum .jumpToPreviousPage()? (trotz viewcursor.Start)

Verständnisfehler meinerseits oder Flüchtigkeitsfehler Deinerseits?


Gruß
Stephan
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo

Du musst das eigentlich nicht mit python machen, der wesentliche Teil davon sind sowieso API-methoden die in Basic ganz genauso aussehen.


.PageNumberOffset liefert nur an exakt den Stellen ein Ergebnis wo die Manuellen Umbrüche mit Seitennummerkorrektur gesetzt wurden, die sind nicht zwingend am Anfang der aktuellen Seite, deshalb die `while True` Schleife die solange "rückwärts blättert" und 'corr' hochzählt bis dieser Punkt am Seitenanfang gefunden ist.

Mir ist nochwas aufgefallen, theoretisch kann man solch eine Seitenkorrektur auf den Wert 0 setzen, daher müsste die if Abfrage genaugenommen lauten:

Code: Alles auswählen

if not offset is None:
    break 
in Basic wahrscheinlich dann sowas wie:

Code: Alles auswählen

if not isempty( offset ) then
oder besser:

Code: Alles auswählen

do
…
loop while isempty( offset )
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

Du musst das eigentlich nicht mit python machen, der wesentliche Teil davon sind sowieso API-methoden die in Basic ganz genauso aussehen.
ja, deswegen hatte ich Dir ja für die Anregung gedankt.
(mir war vor Deinem Post schlicht nicht selbst der Gedanke gekommen das es ja reicht mit dem Cursor über die Seiten zu interieren, ich meinte ich müsse durch alle Absätze)
deshalb die `while True` Schleife die solange "rückwärts blättert"
die Schleife verstehe ich, aber vor der Schleife steht doch:

Code: Alles auswählen

viewcursor = doc.CurrentController.ViewCursor
current = viewcursor.Start
viewcursor.jumpToStartOfPage()
und das hatte ich für den Dokumentanfang gehalten und deshalb verstehe ich die Rückwärtsschleife nicht (und dachte .jumpToPreviousPage() könne ein Flüchtigkeitsfehler Deinerseits sein).

Oder frage ich jetzt dummes Zeug?





Gruß
Stephan
Toxitom
********
Beiträge: 3768
Registriert: Di, 12.08.2003 18:07
Wohnort: Wiesbaden
Kontaktdaten:

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Toxitom »

Hey zusammen,

möchte noch mal einen Aspekt zur Diskussion mit einbringen.

Meine Idee wäre eigentlich auch die Enummerieung der Absätze und schauen, welcher Absatz den Offset auslöst.

Ich finde die hier gepostete Lösung elegant - hab sie aber nicht getestet. Der Viewcurser bewirkt ja an sich auch ein Neurendern der aktuellen Ansicht - wenn der also Seite für Seite zurückblättert ... ist das nicht etwas "nervig" im Frontend? ok, man könnte den Controller sperren - dann sind aber keine
Aktivitäten vom User möglich.

Wäre schön, mal ein Ergebnis zu hören :)

Viele Grüße
Tom
Unterstützer LibreOffice, zertifizierter Trainer und Berater
Bücher: LibreOffice 6- Einstieg und Umstieg
Makros Grundlagen - LibreOffice / OpenOffice Basic
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

Der Viewcurser bewirkt ja an sich auch ein Neurendern der aktuellen Ansicht - wenn der also Seite für Seite zurückblättert ... ist das nicht etwas "nervig" im Frontend?
Ja, ich finde es störend, aber es ist nicht vermeidbar, wenn ich die Seitenzahl so bestimmen will, wie hier im Thread besprochen.
ok, man könnte den Controller sperren
ja, schon probiert

Wäre schön, mal ein Ergebnis zu hören
derzeitig habe ich:

Code: Alles auswählen

Function seiten_nr(seite As Long)
	nOK = 1
	tc = ThisComponent
	v_cur = tc.CurrentController.ViewCursor
	v_cur.jumpToFirstPage() 'erste Seite nicht berücksichtigen
	
	Do
		v_cur.jumpToNextPage
		v_cur.jumpToStartofPage
		If v_cur.PageNumberOffset() > 0 Then
			tmp_korr = v_cur.getPage() - v_cur.PageNumberOffset()
		End If
		If v_cur.getPage() = seite Then
			nOK = 0
			seiten_nr = v_cur.getPage() - tmp_korr
			Exit Do
		End If
	Loop
	If nOK = 1 Then seiten_nr = "nOK"
End Function

Gruß
Stephan
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo

Ich sehe da keinen Laufzeit-Vorteil (gegenüber meinem Ansatz), letzlich iterierst du vom Dokumentenanfang über alle Seiten bis zur aktuellen Seite!
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

Ich sehe da keinen Laufzeit-Vorteil (gegenüber meinem Ansatz),
ICH EBENFALLS NICHT!

Und ich schreihe hier mit Großbuchstaben weil ich mich irgendwie im Kreis drehe, denn meine ganze Frage an Dich war ob Du Dich vielleicht bei Deinem Code aus Versehen verschrieben hast denn imho setzt das den Cursor an den Anfang des Dokuments:

Code: Alles auswählen

viewcursor = doc.CurrentController.ViewCursor
    current = viewcursor.Start
    viewcursor.jumpToStartOfPage()
dann jedoch interiert:

Code: Alles auswählen

viewcursor.jumpToPreviousPage()
von quasi hinten nach vorne, sollte aber imho umgekehrt interrieren müssen weil der Cursor ja bereits ganz vorne ist.


Absolut garnicht geht es mir um schlechter oder besser, noch hätte ich behauptet mein Ansatz wäre besser, sondern allein darum Dein Script zu verstehen und dabei kann es sehr gut sein das Dein Script richtig funktioniert und ich die Arbeitsweise nur nicht verstehe, das hatte ich zum Ausdruck gebracht mit meiner rhetorischen Frage: "Oder frage ich jetzt dummes Zeug?"


Gruß
Stephan
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo
denn imho setzt das den Cursor an den Anfang des Dokuments:
Nein jumpToStartOfPage() bewegt den Cursor zum Anfang der Seite auf der er sich momentan befindet.

Karolus
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Stephan »

Nein jumpToStartOfPage() bewegt den Cursor zum Anfang der Seite auf der er sich momentan befindet.
und was tut current = viewcursor.Start?

Sorry, Karolus, ich verstehe es nicht. Ich zitiere 3 Codezeilen und Du greifst eine raus und meine Frage beantwortest Du weiterhin nicht, jedenfalls verstehe ich Deine Antwort nicht.

Meiner Meinung nach, bewegen diese 2 Zeilen den sichtbaren Cursor an den Dokumentanfang:

Code: Alles auswählen

viewcursor = doc.CurrentController.ViewCursor
current = viewcursor.Start
und diese Zeile den Cursor nochmals, quasi zusätzlich, an den Anfang der ersten Seite (wo der Cursor nach den vorangegangenen Zeilen imho ohnehin steht [1]):

Code: Alles auswählen

viewcursor.jumpToStartOfPage() 
Nach diesen 3 Zeile ist der Cursor, meiner Annahme also am Anfang (des Fliesstextbereiches) der ersten Seite.

meine Erwartung wäre deshalb das, nun der Cursor im Weiteren (in der Schleife) weiter nach hinten bewegt werden müsste (denn er ist ja anfangs vorne), also:

Code: Alles auswählen

...
viewcursor.jumpToNextPage()
...
in Deinem Code steht jedoch:

Code: Alles auswählen

...
viewcursor.jumpToPreviousPage()
...
und ich frage mich die ganze Zeit ob das ein simpler Schreibfehler sein könnte, falls nicht erkläre mir bitte den Ablauf des Scripts, das ist mein ganzes Anliegen.


Das ist von Anfang an die ganze Frage, weder habe ich Deinen Code schlecht geredet, noch meinen Code gut, noch bin ich Dir über den Mund gefahren, sondern habe gleich vorbeugend festgestellt das meine Frage dumm sein könne weil ich etwas Grundsätzliches übersehe oder nicht kapiere, einzig wollte ich Klarheit bezüglich des Codes, so das ich ihn verstehe.


Gruß
Stephan


[1]
Letzteres ist keine Kritik, sondern nur das was ich denke was die Zeile tut, und Du wirst von mir ebenfalls häufig Basic-Code der Form finden in dem das ebenfalls quasi doppelt ist, nämlich z.B. so:

Code: Alles auswählen

cur = ThisComponent.text.createtextcursor()
cur.gotoStart
cur.gotoStartofParagraph
hierbei ist die letztere Zeile meines Codes auch überflüssig, weil ich weiß das der Cursor schon am Absatzanfang ist
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo
current = viewcursor.Start
…Start resp. …End sind die Start-Position respective Ende-Position des Viewcursor die in der Regel identisch sind, solange man nicht mehrere Buchstaben etc. selektiert hat. Ich merke mir diese Stelle in der Variablen `current` um am Ende der Prozedur den viewcursor wieder dort zu platzieren wo er am Anfang war.
( Anmerkung: wenn ich nur `current = viewcursor` nehme funktioniert der Rücksprung am Ende nicht, k. A. warum :? )

Nochmal alles zusammen etwas aufgeräumter mit einer extra Funktion die sich ausschließlich um die Ermittlung der manuell eingestellten Seitennummerierung kümmert.

Code: Alles auswählen

def main():
    doc =XSCRIPTCONTEXT.getDocument()
    viewcursor = doc.CurrentController.ViewCursor
    current = viewcursor.Start
    viewcursor.jumpToStartOfPage()
    print( page_from_offset( viewcursor ) )
    viewcursor.gotoRange(current, False)
    
    
def page_from_offset( cursor ):
    """
    takes viewcursor and returns pagenumber
    countup from last  offset
    
    todo: Error-handling in case there is no
        manual pagebreak with PageOffset 
    """
    corr = 0
    while cursor.PageNumberOffset is None:
        # der Offset ist nur am Seitenanfang 
        # der Seite an dem er gesetzt wurde verfügbar.
        cursor.jumpToPreviousPage()
        cursor.jumpToStartOfPage()
        corr += 1
        
    return cursor.PageNumberOffset + corr
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Karolus
********
Beiträge: 7440
Registriert: Mo, 02.01.2006 19:48

Re: Writer - tatsächliche Seitennummer der Seite des ViewCusor ermitteln

Beitrag von Karolus »

Hallo

Und gleich nochmal eine Variante, die auch nicht vorhandene Seitenkorrekturen berücksichtigt.

Code: Alles auswählen

def main():
    doc =XSCRIPTCONTEXT.getDocument()
    viewcursor = doc.CurrentController.ViewCursor
    current = viewcursor.Start
    page = viewcursor.Page
    viewcursor.jumpToStartOfPage()
    print( page_from_offset( viewcursor ) or page )
    viewcursor.gotoRange(current, False)
    
    
def page_from_offset(cursor ):
    """
    takes viewcursor from current Selection
    and return pagenumber countup from last
    offset
    """
    corr = 0
    while cursor.PageNumberOffset is None:
        if cursor.Page == 1:
            return # Notaustieg falls nirgends ein Offset gesetzt wurde!
        cursor.jumpToPreviousPage()
        cursor.jumpToStartOfPage()                
        corr += 1
        
    return cursor.PageNumberOffset + corr
LO7.4.7.2 debian 12(bookworm) auf Raspberry4b 8GB (64bit)
LO7.6.2.1 flatpak debian 12(bookworm) auf Raspberry4b 8GB (64bit)
Antworten