Ändern Sie 2 oder mehr LibreOffice-Dokumente so, dass sie exakt dasselbe Format haben

14

Angenommen, ich habe ein Verzeichnis mit etwa 100 .rtfDateien, die ich mit LibreOffice Writer bearbeite.

Ich wünsche mir, dass alle Dateien in diesem Verzeichnis genau die gleichen grundlegenden Rich-Text-Styling-Anweisungen haben, zum Beispiel:

* font-family: Ubuntu             # All text in all files is now Ubuntu;
* font-size: 12px                 # All text in all files is now 12px big;
h1: 28px                          # All h1's are now 28px big;
if font-size: 18px {make it 22px} # All text with font-size 18px is now 22px;

Und so weiter ... Also, im Grunde möchte ich alle Dateien auf einmal ändern. Ist ein solches "Bulk-Styling" möglich?

Vielleicht ist es mit der CLI irgendwie möglich?

JohnDoea
quelle
3
Ich denke, das wird keine leichte Aufgabe sein. Wenn sie alle gleich strukturiert sind, können Sie möglicherweise eine hackige Lösung verwenden, indem Sie Text in den RTF-Dateien über die Befehlszeile ersetzen. Dies hängt jedoch stark davon ab, wie die RTF-Dateien aussehen und wie ähnlich sie sind.
Sebastian Stark
In Stack Overflow habe ich Hilfe für ein ganz neues LibreOffice Writer-Makro gefunden, das heute Abend von vorne anfängt. Wir müssen nicht mehr jede mögliche vorhandene Schriftgröße kennen.
WinEunuuchs2Unix
In einem letzten Versuch habe ich die Experten von Stack Overflow gebeten, vor Ablauf der
Nachfrist
Ihr habt Zehntausende von Reputationspunkten. Ich schlage demütig vor, dass Sie in Betracht ziehen, 500-750 zu geben. Nur eine Überlegung. Einfach nur einfach.
JohnDoea

Antworten:

5

Verwenden Sie Libreoffice-Tools anstelle von CLI

Wenn Sie nur Befehlszeilentools haben, sieht alles wie ein Befehlszeilenproblem aus. Ich habe beschlossen, diese Antwort mit LibreOffice-Makros zu schreiben:

  1. Verwenden Sie eine Befehlszeilenschleife, um jedes Writer-Dokument in einer "kopflosen" Umgebung zu verarbeiten.
  2. Führen Sie ein Makro aus, um die .rtfWriter-Dokumentdatei (Rich Text Format) zu ändern .
  3. Makro speichert Datei und beendet
  4. Zurück zu 1.

Testdaten erstellen

Erstellen Sie zwei oder mehr Dateien mit:

richtext2.png

Erstelle ein Skript ~/Downloads/copy-rtf.shmit:

cp ~/Documents/*.rtf ~/Downloads

Als ausführbar markieren mit

chmod a+x ~/Downloads/copy-rtf.sh
  • Während der Entwicklung und des Testens werden die Makrodateien *.rtffür das ~/DownloadsVerzeichnis ausgeführt.
  • Vor jedem Testtyp cd ~/Downloadsund Lauf./copy-rtf.sh
  • Nachdem die Ausgabe perfekt ist, werden sie zurück in das Live-Verzeichnis kopiert.

Das Downloads-Verzeichnis wird verwendet, weil:

  • Jeder hat eine ~/Downloads
  • Es wird regelmäßig hinzugefügt und regelmäßig manuell geleert
  • Es ist dauerhafter als das /tmp/Verzeichnis, das bei einem Neustart möglicherweise nicht erhalten bleibt.

Makro in kopfloser Umgebung ausführen

Mit dieser Stack Exchange-Antwort rufen Sie Libreoffice Writer über die Befehlszeile auf und übergeben ihm einen globalen Makronamen, um Folgendes auszuführen:

soffice -headless -invisible "vnd.sun.star.script:Standard.Module1.MySubroutine? language=Basic&location=application"

Die obige Antwort funktioniert möglicherweise nicht, so dass eine andere Methode versucht werden kann:

soffice "macro:///Standard.SaveCSV.Main" $1

Installieren Sie Java Runtime Environment

Zum Ausführen von Makros muss Java Runtime Environment (JRE) installiert sein. Auf der Webseite des Entwicklers finden Sie Anweisungen zum manuellen Herunterladen und Installieren.

Diese AU-Fragen und Antworten: /ubuntu//a/728153/307523 legt jedoch nahe, dass dies so einfach ist wie:

sudo apt-add-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer oracle-java8-set-default

Ich habe die AU Q & A-Methode ausprobiert und nach dem ersten Schritt des Hinzufügens des PPA wird ein Begrüßungsbildschirm mit zusätzlichen Informationen angezeigt. Am hilfreichsten ist ein Link zum Einrichten von JRE 8 auf Debian-Systemen .

Für den dritten Schritt der Installation von JRE 8 müssen Sie die Lizenzvereinbarung verwenden Tabund Enterakzeptieren. Ihre Maschine wird während des größten Teils der Installationsroutine für einige Minuten angehalten.

Öffnen Sie nun LibreOffice und wählen Sie Extras -> Optionen -> LibreOffice -> Erweitert und richten Sie diesen Bildschirm ein:

LO JRE8 Advanced Setup.png

Klicken Sie auf die Optionen für:

  • Verwenden Sie eine Java-Laufzeitumgebung
  • Oracle Corporation 1.8.0_161
  • Makroaufzeichnung aktivieren (experimentell)
  • OK klicken
  • Sie werden aufgefordert, den Computer neu zu starten. Klicken Sie auf "Jetzt neu starten".

LibreOffice Writer-Makro

Das Makro liest das gesamte Dokument und:

  • Ändern Sie den Schriftnamen in Ubuntu.
  • Wenn Überschrift 1, setzen Sie die Schriftgröße auf 28
  • Andernfalls, wenn die Schriftgröße 18 auf 22 eingestellt ist
  • Andernfalls setzen Sie die Schriftgröße auf 12

Das Makro speichert das Dokument und beendet Libreoffice Writer.

Dialog ausschalten

Wenn Sie eine Datei speichern, wird der folgende Dialog angezeigt:

LO Writer schaltet RTF dialog.png aus

Schalten Sie diese Meldung aus, wie auf dem Bildschirm angezeigt. Das Makro wird möglicherweise nicht ordnungsgemäß ausgeführt, wenn diese Option aktiviert ist.

Makro-Inhalte

Ich habe einige Tage damit verbracht, ein Makro mit "Extras" -> "Makros" -> "Makro aufnehmen" -> "Grundeinstellungen" aufzunehmen. Anfangs schien es vielversprechend, aber das aufgezeichnete Makro zeigte ein inkonsistentes Verhalten und musste für ein handgeschriebenes Grundmakro aufgegeben werden. Eine gefundene Hilfe in Stack Overflow für einen Experten, der mir bei der grundlegenden Codierung hilft . Hier ist das Ergebnis:

Sub ChangeAllFonts
    rem - Change all font names to Ubuntu.
    rem - If heading 1 set font size to 28
    rem - else if font size is 18 set to 22
    rem - else set font size to 12
    rem - The macro will save document and exit LibreOffice Writer.
    Dim oDoc As Object
    Dim oParEnum As Object, oPar As Object, oSecEnum As Object, oSec As Object
    Dim oFamilies As Object, oParaStyles As Object, oStyle As Object
    oDoc = ThisComponent
    oParEnum = oDoc.Text.createEnumeration()
    Do While oParEnum.hasMoreElements()
      oPar = oParEnum.nextElement()
      If oPar.supportsService("com.sun.star.text.Paragraph") Then
        oSecEnum = oPar.createEnumeration()
        Do While oSecEnum.hasMoreElements()
          oSec = oSecEnum.nextElement()
          If oSec.TextPortionType = "Text" Then
            If oSec.ParaStyleName = "Heading 1" Then
                rem ignore for now
            ElseIf oSec.CharHeight = 18 Then
                oSec.CharHeight = 22.0
            Else
                oSec.CharHeight = 12.0
            End If
          End If
        Loop
      End If
    Loop
    oFamilies = oDoc.getStyleFamilies()
    oParaStyles = oFamilies.getByName("ParagraphStyles")
    oStyle = oParaStyles.getByName("Heading 1")
    oStyle.setPropertyValue("CharHeight", 28.0)
    FileSave
    StarDesktop.terminate()
End Sub

rem Above subroutine is missing call to UbuntuFontName ()
rem also it is calling oStyle.setPropertyValue("CharHeight", 28.0)
rem which may cause problems. Will test. Also StarDesktop.terminate ()
rem is known to cause problems and will likely be reworked with a
rem a dialog box telling operator the program is finished and maybe
rem to press <Alt>+<F4>.

rem ========= Original code below for possible recycling ===========

Sub AllFonts
rem - change all font names to Ubuntu.
rem - If heading 1 set font size to 28
rem - else if font size is 18 set to 22
rem - else set font size to 12

rem The macro will save document and exit Libreoffice Writer.

Dim CharHeight As Long, oSel as Object, oTC as Object
Dim CharStyleName As String
Dim oParEnum as Object, oPar as Object, oSecEnum as Object, oSec as Object
Dim oVC as Object, oText As Object
Dim oParSection        'Current Section

oText = ThisComponent.Text
oSel = ThisComponent.CurrentSelection.getByIndex(0) 'get the current selection
oTC = oText.createTextCursorByRange(oSel)           ' and span it with a cursor

rem Scan the cursor range for chunks of given text size.
rem (Doesn't work - affects the whole document)

oParEnum = oTC.Text.createEnumeration()
Do While oParEnum.hasMoreElements()
  oPar = oParEnum.nextElement()
  If oPar.supportsService("com.sun.star.text.Paragraph") Then
    oSecEnum = oPar.createEnumeration()
    oParSection = oSecEnum.nextElement()
    Do While oSecEnum.hasMoreElements()
      oSec = oSecEnum.nextElement()
      If oSec.TextPortionType = "Text" Then
        CharStyleName = oParSection.CharStyleName
        CharHeight = oSec.CharHeight
        if CharStyleName = "Heading 1" Then
            oSec.CharHeight = 28
        elseif CharHeight = 18 Then
            oSec.CharHeight = 22
        else
            oSec.CharHeight = 12
        End If
      End If
    Loop
  End If

Loop

FileSave
stardesktop.terminate()

End Sub


Sub UbuntuFontName
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------- Select all text ------------------------------------------
dispatcher.executeDispatch(document, ".uno:SelectAll", "", 0, Array())

rem ----------- Change all fonts to Ubuntu -------------------------------
dim args5(4) as new com.sun.star.beans.PropertyValue
args5(0).Name = "CharFontName.StyleName"
args5(0).Value = ""
args5(1).Name = "CharFontName.Pitch"
args5(1).Value = 2
args5(2).Name = "CharFontName.CharSet"
args5(2).Value = -1
args5(3).Name = "CharFontName.Family"
args5(3).Value = 0
args5(4).Name = "CharFontName.FamilyName"
args5(4).Value = "Ubuntu"

dispatcher.executeDispatch(document, ".uno:CharFontName", "", 0, args5())

end sub


sub FileSave
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:Save", "", 0, Array())

end sub
WinEunuuchs2Unix
quelle
2

Hier ist ein einmaliger Ansatz mit Libre Office. Es ist kein Los, aber es kann helfen, andere Antworten zu inspirieren.

Öffnen Sie eine RTF-Datei mit der Ubuntu-Schriftart H1 bei 28 pt, Text bei 12 pt und Text bei 18 pt.

Hier ist ein Beispiel:

Test rtf

Mit den folgenden Schritten wird die in Ihrer Frage angeforderte Änderung angewendet: "Wenn Schriftgröße: 18px {22px festlegen} # Der gesamte Text mit der Schriftgröße 18px ist jetzt 22px."

Klicken Sie im Menü auf Bearbeiten → Suchen & Ersetzen, oder CtrlHklicken Sie auf Andere Optionen. Klicken Sie auf Suchen nach Feld und dann auf die Schaltfläche Attribute. Kontrollkästchen Schriftgröße und dann auf die Schaltfläche Format. Wählen Sie 18 pt im Bildlauffeld ganz rechts aus Bildlauffeld ganz rechts

FindNreplace

Klicken Sie auf Alle ersetzen

Die zutreffende Zeile, die geändert wurde, war:

\ par \ pard \ plain \ s0 \ ql \ widctlpar \ hyphpar0 \ ltrpar \ cf1 \ kerning1 \ dbch \ af7 \ langfe1081 \ dbch \ af7 \ afs24 \ alang1081 \ loch \ f3 \ fs24 \ lang1033 \ ql \ widctlpar \ hyphpar0 \ ltrpar {\ rtlch \ ltrch \ loch \ fs36 \ loch \ f6

die fs36 änderte sich zu fs44

Das einzige andere Feld, das geändert wurde, war das Feld für die Umlaufzeit, das Sie möglicherweise aktualisieren möchten oder nicht:

{\ revtim \ yr2018 \ mo3 \ dy31 \ hr22 \ min19}

Wenn wir wissen, was sich geändert hat, erhalten wir ein Modell für die Entwicklung eines Batch-Ansatzes. Es ist wahrscheinlich möglich, ein Makro aufzuzeichnen, das dies beim Öffnen eines Dokuments ausführt, oder ein Skript zu entwickeln, das die gewünschten Änderungen vornimmt.

Elder Geek
quelle
1

In der RTF-Spezifikation gibt es einige gute Hinweise, wie man das anstellen könnte.

Hier ist meine Analyse des Problems.

Dies mithilfe der CLI zu erreichen, wie Sie vermuten, scheint der einfachste Ansatz zu sein, da ich keine GUI-basierten Anwendungen gesehen habe, die diese Art der Stapelkonvertierung handhaben können. Es scheint, dass Sie einfach die Kopfzeile ändern können:

Der Header hat die folgende Syntax:

<header>
    \rtf <charset> \deff? <fonttbl> <filetbl>? <colortbl>? <stylesheet>? <listtables>? <revtbl>?

Each of the various header tables should appear, if they exist, in the above order. Document properties can occur before and between the header tables. A property must be defined before being referenced. Specifically:

* The style sheet must occur before any style usage.

* The font table must precede any reference to a font.

* The \deff keyword must precede any text without an explicit reference to a font, because it specifies the font to use in such cases.

Persönlich fällt mir beim Überprüfen dieser Informationen auf, dass alles, was Sie versuchen, so aussieht, als würde es in der Kopfzeile unterstützt, von der Auswahl der Schriftart bis zum Stil.

Es stehen Tools zur Verfügung, die Ihnen bei diesem Vorgang helfen, da ich im Folgenden weder ein Beispiel für den von Ihnen verwendeten Dokumentstil noch für den von Ihnen gewünschten Dokumentstil habe und eine allgemeinere Antwort für die Community wahrscheinlich von größerem Nutzen sein wird als eine, die genau auf Ihre Situation zugeschnitten ist.

grepwird nützlich sein, um die zu konvertierenden vorhandenen Dateien und ein Beispiel des Zielstils für vorhandene Dateien <fonttbl>und
<stylesheet>Auswahlen zu analysieren . Nachdem Sie festgestellt haben, was Sie tatsächlich haben, sollten Sie in der Lage sein, ein einfaches Skript zu schreiben, indem Sie sedden vorhandenen Header-Inhalt durch den gewünschten Header-Inhalt ersetzen. Es gibt zahlreiche Beispiele für das Durchlaufen von Dateien in einem Bash-Skript ( Beispiel ) und für die Verwendung von sed ( Beispiel ), das frei verfügbar ist, wenn Sie mit diesen Konzepten nicht vertraut sind.

Es gibt auch einzeilige Optionen, um eine Zeichenfolge in einer Datei zu ersetzen. Einige funktionieren je nach Anwendungsfall möglicherweise besser als andere. Abhängig vom Inhalt Ihrer Dateien kann es sinnvoll oder nicht sinnvoll sein, einfach jede Instanz fs36durch fs44die von Ihnen verwendete Shell zu ersetzen. Dies kann sich auch darauf auswirken, wie Sie Ihre Ausdrücke am besten schreiben. In Abhängigkeit von der Komplexität und den Inhalt Ihrer Dokumente können Sie besser dran mit sed, perloder grepvielleicht sogar eine Kombination von ihnen. Da dies zu einer Programmierfrage geworden ist, verweisen Sie am besten auf /programming/15402770/how-to-grep-and-replace, wo Sie leicht ein halbes Dutzend verschiedener Ansätze finden, eine davon das wird wahrscheinlich perfekt zu Ihren Bedürfnissen passen.

Wenn Sie diese Änderungen beispielsweise systemweit anwenden möchten,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;wie von rezizter vorgesehen Ist wohl die beste.

Wenn Sie Ihre Änderungen in einem einzigen Verzeichnis speichern möchten,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'wie von billtian zur Verfügung gestellt ist eine ausgezeichnete Wahl.

Um auf der sicheren Seite zu sein, sollten Sie die Dateien vorverarbeiten, um sicherzustellen, dass alle Änderungen, die Sie vornehmen, keine unbeabsichtigten Folgen haben. Zum Beispiel:

<!-- language: lang-bash -->

    #!/bin/bash
    for f in *.rtf 
        do
        echo $f
        grep fs36
        done

Oben werden die Zeilen angezeigt, die die Suchzeichenfolge fs36 für jede RTF-Datei im Verzeichnis enthalten.

Bearbeiten:

Die aktuellste Spezifikation erhalten Sie hier. Ich sehe keine Änderungen, die sich auf diesen Ansatz auswirken könnten.

Elder Geek
quelle
1
Hallo, ich danke Ihnen, dass Sie zuerst eine CLI-Lösung beschrieben haben. Teilen Sie uns ein Codebeispiel mit, wie Sie eine rtfmit einer Überschrift und einem Text ändern, seddamit die Antwort in der Mitte angezeigt wird sed.
JohnDoea
@ JohnDoea Immer bemüht zu helfen. Ich hoffe, Sie und zukünftige Benutzer finden es nützlich.
Elder Geek