Hallo Freunde/Freundinnen,
meinen ersten Versuch habe ich wohl nicht im rechten Forum gestartet, hier bin ich hoffentlich nun richtig.
Arbeite mit LibreOffice Version: 6.0.7.3 unter macOS Catalina Version 10.15.1 im Writer-Modul und Base-Modul. Mittels Makro gelingt es mir aus den Daten einer Datenbank den Text eines umfangreicheren Writer-Dokumentes zu generieren. Der Text wird mit benutzerdefinierten Formatvorlagen formatiert (Überschriften in zwei Ebenen, Textkörper und Textkörper mit Einzug). Der Textkörper enthält Worte, die als als Querverweis auf eine Überschrift stehen. Ein Inhaltsverzeichnis ist nicht Bestandteil des Dokumentes.
Manuell gelingt das Einfügen des Querverweises auf eine Überschrift ohne Probleme. Der Viewcursor führt beim Anklicken des Verweistextes den erwarteten Sprung zur ausgewählten Überschrift sichtbar aus.
Da im Dokument aber mehr Querverweise der beschriebenen Art anzubringen sind, als manuell in vertretbarer Zeit zu bewältigen ist, will ich auch diesen Teil meiner Arbeit ein Makro erledigen lassen.
Andrew Pitonyak beschreibt in "BASIC-Makros für OpenOffice und LibreOffice" mit Listing 405. wie ein GetReference-Feld einzufügen ist. Mir gelingt dies in der Form
oField = oDoc.createInstance("com.sun.star.text.textfield.GetReference") oField.ReferenceFieldPart = com.sun.star.text.ReferenceFieldPart.TEXT oField.ReferenceFieldSource = com.sun.star.text.ReferenceFieldSource.BOOKMARK oField.SequenceNumber = oReferencedField.SequenceValue
oField.SourceName = sSeqName
oText.insertTextContent(oCurs, oField, True)
wenn ich für SequenceNumber und SourceName auslesbare Werte manuell eingefügter Querverweise benutze, um mein Makro zu testen. Woher nehme ich aber für alle anderen Querverweise die entsprechenden Werte?
Die als Sprungziel vorhandenen Überschriften erreiche ich zwar über oDoc.getLinks() kann aber die dort vermuteten Werte nicht finden.
Wer kann mir helfen? Danke.
Writer - Querverweis auf Überschriften
Moderator: Moderatoren
-
- Beiträge: 6
- Registriert: Fr, 22.11.2019 12:36
Re: Writer - Querverweis auf Überschriften
Ich fürchte Du machst einen Denkfehler, denn es gibt die Werte erst nachdem Du manuell einen Querverweis eingefügt hast, denn das Ziel eines Querverweises der auf eine Überschrift gesetzt wird ist eine (speziell benannte) Textmarke die LO erst beim Erzeugen des Querverweises automatisch einfügt.wenn ich für SequenceNumber und SourceName auslesbare Werte manuell eingefügter Querverweise benutze, um mein Makro zu testen. Woher nehme ich aber für alle anderen Querverweise die entsprechenden Werte?
WAs LO Dir im Dialog anzeigt sind tatsächlich NUR die Texte der Überschriften und falls es buchstabengleiche Überschriften gleicher Ebene gäbe/gibt ist die einzige Unterscheidung deren Reihenfolge die LO im Dialog genauso wiedergibt wie im Dokument vorhanden.
Ich habe das einmal getestet und hänge unten zwei Screenshots meines Testdokuments an, die das Gesagte verdeutlichen.
Ich weiß garnicht ob Du LO per Makro zwingen kannst 'seine' dafür verwendeten automatisch benannten Bookmarks (Textmarken) zu erzeugen und ich weiß auch nicht ob LO per Makro erzeugte speziell benannte Bookmarks adäquat behandeln würde, das müsste man mal testen.
Nötig ist das alles auch nicht, denn Du selbst kannst per Makro gezielt eigene Textmarken bei den Überschriften erzeugen und dann darauf Querverweise setzen. Um das zu tun gehst du so vor: mache eine Enumeration über den gesamten Text des Dokuments und prüfe ob der jeweils aktuelle Absatz die passende Absatzvorlage für Überschrift hat (das können wenn Du mehrere Überschriftenebenen mit Querverweisen anspringen willst auch mehrere sein) und wenn ja dann setze eine Textmarke passenden Namens, also ungefähr:
Code: Alles auswählen
cur = ThisComponent.text.createTextCursor
absaetze = ThisComponent.Text.createEnumeration()
Do While absaetze.hasMoreElements()
akt_absatz = absaetze.nextElement()
If akt_absatz.ParaStyleName <> "DeineÜberschriftenvorlage" Then
a_index = a_index + 1
oBookmark = tc.createInstance("com.sun.star.text.Bookmark")
cur.gotoRange(akt_absatz.getAnchor, False)
oBookmark.setName("xyz-" & a_index & "_" & cur.String)
tc.Text.insertTextContent(cur, oBookmark, False)
End If
Loop
Code: Alles auswählen
tc = ThisComponent
oField = tc.createInstance("com.sun.star.text.textfield.GetReference")
oField.ReferenceFieldPart = com.sun.star.text.ReferenceFieldPart.PAGE
oField.ReferenceFieldSource = com.sun.star.text.ReferenceFieldSource.BOOKMARK
oField.SourceName = "Der Name der gewünschten Textmarke"
tc.text.insertTextContent(curx, oField, True)
Wie Du auf "Der Name der gewünschten Textmarke" zugreifst hängt von den Umständen ab, z.B. kannst Du beim Setzen der Textmarken, alle Namen in ein Array schreiben und das dann abarbeiten.
Der Vorteil der besonderen Benennung der Textmarken (s.o.) ist auch das Du weist welche Textmarke zu welcher Überschrift gehört und welche Textmarken im Gesamtdokument überhaupt die relevanten sind (alle deren Name vorne "xyz-" hat)
Gruß
Stephan
- Dateianhänge
-
- Querverweis_contentXML.gif (36.21 KiB) 2875 mal betrachtet
-
- Querverweis_Bildschirmdarstellung.gif (9.59 KiB) 2875 mal betrachtet
-
- Beiträge: 6
- Registriert: Fr, 22.11.2019 12:36
Re: Writer - Querverweis auf Überschriften
Hallo Stephan,
danke für die rasche Antwort auf meine Frage. Deinen Lösungsvorschlag werde ich aufgreifen und testen. Ich bin zuversichtlich. Die Aufgabe bleibt übersichtlich, weil nur in einer Überschriftenebene die Verknüpfung hergestellt wird und die Texte der Überschriften frei von Duplikaten sind.
Es war dann wohl tatsächlich mein Irrtum anzunehmen, dass mit der Formatierung eines Textes als Überschrift zugleich auch die erwartete Einrichtung der Textmarke durch LO erfolgt, die ich leider nur vergeblich suchen konnte.
danke für die rasche Antwort auf meine Frage. Deinen Lösungsvorschlag werde ich aufgreifen und testen. Ich bin zuversichtlich. Die Aufgabe bleibt übersichtlich, weil nur in einer Überschriftenebene die Verknüpfung hergestellt wird und die Texte der Überschriften frei von Duplikaten sind.
Es war dann wohl tatsächlich mein Irrtum anzunehmen, dass mit der Formatierung eines Textes als Überschrift zugleich auch die erwartete Einrichtung der Textmarke durch LO erfolgt, die ich leider nur vergeblich suchen konnte.
Re: Writer - Querverweis auf Überschriften
Korrektur
statt:
muss es natürlich heissen:
aber mein geposteter Code war ja ohnehin nur eine Lösungsskizze und nicht eine komplett fertige Lösung.
Gruß
Stephan
statt:
Code: Alles auswählen
If akt_absatz.ParaStyleName <> "DeineÜberschriftenvorlage" Then
Code: Alles auswählen
If akt_absatz.ParaStyleName = "DeineÜberschriftenvorlage" Then
Gruß
Stephan
-
- Beiträge: 6
- Registriert: Fr, 22.11.2019 12:36
Re: Writer - Querverweis auf Überschriften
Hallo Freunde,
rechtzeitig zum Weihnachtsfest hatte ich endlich die funktionierende Lösung im iMac. Das Ergebnis ist das erwartete Dokument mit Funktionalität. Auch der Export als PDF-Datei gelingt.
Es hat etwas länger gedauert, weil ich zunächst nicht erkannt hatte, dass die beiden Befehlszeile oZiel = ofbDoc.createInstance("com.sun.star.text.ReferenceMark") und oQuerverweis = ofbDoc.createInstance("com.sun.star.text.textfield.GetReference") für jedes Ziel und jeden Querverweis einzeln aufgerufen werden müssen, die Namen des Zieles nicht das Zeichen # enthalten dürfen und ein Querverweis nur eingefügt werden kann, wenn zuvor das Sprungziel eingefügt wurde.
Soweit mein vorläufiges Endergebnis, würde mich natürlich auch über ergänzende Hinweise zum Thema freuen. Mich interessiert noch die Frage, wie kann ich das Erscheinungsbild der Sprungziele und Querverweise im Dokument verändern, wenn die Standardeinstellungen nicht befriedigen.
Fröhliche Weihnacht und ein gesunden neues Jahr 2020 wünscht allen Freunden - Opa Eckhard
rechtzeitig zum Weihnachtsfest hatte ich endlich die funktionierende Lösung im iMac. Das Ergebnis ist das erwartete Dokument mit Funktionalität. Auch der Export als PDF-Datei gelingt.
Es hat etwas länger gedauert, weil ich zunächst nicht erkannt hatte, dass die beiden Befehlszeile oZiel = ofbDoc.createInstance("com.sun.star.text.ReferenceMark") und oQuerverweis = ofbDoc.createInstance("com.sun.star.text.textfield.GetReference") für jedes Ziel und jeden Querverweis einzeln aufgerufen werden müssen, die Namen des Zieles nicht das Zeichen # enthalten dürfen und ein Querverweis nur eingefügt werden kann, wenn zuvor das Sprungziel eingefügt wurde.
Soweit mein vorläufiges Endergebnis, würde mich natürlich auch über ergänzende Hinweise zum Thema freuen. Mich interessiert noch die Frage, wie kann ich das Erscheinungsbild der Sprungziele und Querverweise im Dokument verändern, wenn die Standardeinstellungen nicht befriedigen.
Fröhliche Weihnacht und ein gesunden neues Jahr 2020 wünscht allen Freunden - Opa Eckhard
Code: Alles auswählen
sub SprungzieleEintragen
REM Sprungziele zu den Familien eintragen
'private ofbDoc as object
'private oText as object
dim oCur as object 'ein Textcursor
dim oAbsText as string
dim oZiel as object 'ein Sprungziel
dim oZielName as string
dim i as long 'Zählt die Anzahl der eingetragenen Sprungziele
i = 0
oCur = ofbDoc.text.createTextCursor()
oCur.gotoStart(false) 'Bewegt den Cursor zum Anfang des Textes
do
'der Cursor steht am Anfang eines Absatzes und markiert den Absatz
oCur.gotoEndOfParagraph(true)
if oCur.ParaStyleName = "ofbÜberschrift 5" then
oAbsText = oCur.String
if oAbsText <> "#9999" then
'ein manuell eingetragenes Sprungziel erhielt im Test den Text #9999
'Sprungzielnamen dürfen das Zeichen # nicht enthalten
i = i + 1
oZielName = Right(oAbsText,4)
oZiel = ofbDoc.createInstance("com.sun.star.text.ReferenceMark")
oZiel.setName(oZielName)
ofbDoc.Text.insertTextContent(oCur, oZiel, true)
end if
end if
loop while oCur.gotoNextParagraph(false)
ofbDoc.store()
end sub
sub QuerverweiseEintragen
REM Das Dokument ofbDoc soll Textfelder enthalten der Art GetReference
'berücksichtigt, dass ein Sprungziel aus mehreren Querverweisen erreicht werden kann
'suchen nach regulärem Ausdruck "#...." im Dokument als Ort des einzufügenden Querverweises
'private ofbDoc as object
'private oText as object
dim oQuerverweis as object
dim oCur as object
dim oSuche as object
dim aktGefunden as object
dim aktWort as string
oText = ofbDoc.Text
oCur = ofbDoc.Text.createTextCursor()
oCur.gotoStart(false) 'Bewegt den Cursor zum Anfang des Textes
oQuerverweis = ofbDoc.createInstance("com.sun.star.text.textfield.GetReference")
oSuche = ofbDoc.createSearchDescriptor()
With oSuche
.SearchString = "#...." 'es fehlt ein Ausschluss der Überschriften im
.SearchRegularExpression = true
end with
'liefert die erste Fundstelle im Text, ungeachtet der Formatierung
aktGefunden = ofbDoc.findFirst(oSuche)
do while not isnull(aktGefunden)
'nur an gefundenen Textstellen im Text aber nicht in Überschriften ein Querverweis-Objekt einfügen,
'wenn dafür auch ein Sprungziel bereitsteht
'Zeichenformat unterscheidet Überschriften vom Text
aktWort = aktGefunden.String
if aktGefunden.CharWeight = 150 then
'Fundstelle ist Überschrift und Sprungziel
else
if aktGefunden.CharWeight = 100 then
'100 steht für ofbEinzug Textkörper und ofbTextkörper
'bei vollständigenm Text des OFB kann auf SprungzielTest verzichtet werden
if SprungzieleTest(right(aktWort,4)) then
'Sprungzieltest bestanden
'einen Querverweis an Cursorposition einfügen, wo steht der TextCursor ?
oCur.gotoRange(aktGefunden,false) 'Cursor markiert den gesuchten Text
oCur.collapseToStart()
oCur.goRight(5,true)
'ein einzelnes Querverweis-Objekt bereitstellen
oQuerverweis = ofbDoc.createInstance("com.sun.star.text.textfield.GetReference")
oQuerverweis.ReferenceFieldSource = com.sun.star.text.ReferenceFieldSource.REFERENCE_MARK
oQuerverweis.ReferenceFieldPart = com.sun.star.text.ReferenceFieldPart.TEXT
oQuerverweis.SequenceNumber = 0
oQuerverweis.SourceName = right(aktWort,4)
oQuerverweis.CurrentPresentation = aktWort
oText.insertTextContent(oCur, oQuerverweis, true)
else
'Sprungzieltest nicht bestanden
end if
else
'Formatvorgabe nicht erfüllt
end if
end if
aktGefunden = ofbDoc.findNext(aktGefunden.End, oSuche)
loop
ofbDoc.store()
end sub
function SprungzieleTest(aktName as string) as boolean
REM Querverweise benötigen reale Sprungziele
'private ofbDoc as object
dim oZiele as object 'alle Sprungziele
dim nn()
dim j as long
oZiele = ofbDoc.getReferencemarks()
nn = oZiele.ElementNames 'Array der Elementnamen
j = 0
SprungzieleTest = false
for j = Lbound(nn()) to Ubound(nn())
if nn(j) = aktName then SprungzieleTest = true
if SprungzieleTest = true then exit for
next
end function