Cambia 2 o più documenti di LibreOffice per avere esattamente lo stesso stile / formattazione


14

Supponiamo di avere una directory con circa 100 .rtffile che modifico con LibreOffice Writer.

Vorrei che tutti i file in quella directory avessero esattamente le stesse direttive di base per lo styling rich text, ad esempio:

* 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;

E così via ... Quindi, sostanzialmente, voglio cambiare tutti i file contemporaneamente. È possibile una tale "messa in piega"?

Forse è possibile con la CLI in qualche modo?


3
Non sarà un compito facile, credo. Se sono tutti strutturati nello stesso modo, potresti forse usare qualche soluzione caotica con la sostituzione del testo nei file .rtf dalla riga di comando. Tuttavia, questo dipende molto dall'aspetto dei file rtf e dalla loro somiglianza.
Sebastian Stark,

Ho trovato aiuto in Stack Overflow per una nuova macro di LibreOffice Writer a partire da zero stasera. Non abbiamo più bisogno di conoscere ogni possibile dimensione del carattere esistente.
WinEunuuchs2Unix

In un ultimo disperato tentativo Ho chiesto a esperti di overflow dello stack di inviare una risposta qui prima di termine del periodo di grazia: stackoverflow.com/questions/49640951/...
WinEunuuchs2Unix

Ragazzi, avete decine di migliaia di punti reputazione. Consiglio vivamente di prendere in considerazione l'idea di dare qualcosa come 500-750. Solo una considerazione. Solo
JohnDoea,

Risposte:


5

Usa gli strumenti di Libreoffice invece della CLI

Quando tutto ciò che hai sono strumenti da riga di comando, tutto sembra un problema da riga di comando. Ho deciso di scrivere questa risposta usando le macro di LibreOffice:

  1. Utilizzare un ciclo da riga di comando per elaborare tutti i documenti di Writer in un ambiente "senza testa".
  2. Esegui macro per modificare il .rtffile del documento Writer (Rich Text Format).
  3. La macro salva il file ed esce
  4. Ripeti a 1.

Crea dati di test

Crea due o più file contenenti:

richtext2.png

Crea script ~/Downloads/copy-rtf.shcontenente:

cp ~/Documents/*.rtf ~/Downloads

Segna come eseguibile utilizzando

chmod a+x ~/Downloads/copy-rtf.sh
  • Durante lo sviluppo e il test, le macro che modificano i *.rtffile verranno eseguite nella ~/Downloadsdirectory.
  • Prima di ogni tipo di test cd ~/Downloadsed esecuzione./copy-rtf.sh
  • Dopo che l'output è perfetto, vengono copiati nuovamente nella directory live.

La directory Download viene utilizzata perché:

  • ognuno ha un ~/Downloads
  • viene aggiunto periodicamente e svuotato manualmente periodicamente
  • è più permanente della /tmp/directory che potrebbe non persistere durante i riavvii.

Esegui macro in ambiente senza testa

Usando questa risposta di Stack Exchange invoca Libreoffice Writer dalla riga di comando e passagli un nome macro globale per eseguire:

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

La risposta sopra potrebbe non funzionare, quindi è possibile provare un altro metodo :

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

Installa Java Runtime Environment

Per eseguire le macro è necessario che Java Runtime Environment (JRE) sia installato. La pagina web dello sviluppatore contiene istruzioni per il download e l'installazione manuale.

Tuttavia, queste domande e risposte AU: /ubuntu//a/728153/307523 suggeriscono che è semplice come:

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

Ho provato il metodo di domande e risposte AU e dopo il primo passaggio dell'aggiunta del PPA viene visualizzata una schermata iniziale con ulteriori informazioni. Il più utile è un collegamento alla configurazione di JRE 8 su sistemi Debian .

Il terzo passaggio dell'installazione di JRE 8 richiede l'utilizzo Tabe Enterl'accettazione del Contratto di licenza. La macchina si fermerà per alcuni minuti durante la parte più pesante della routine di installazione.

Ora apri LibreOffice e seleziona Strumenti -> Opzioni -> LibreOffice -> Avanzate e imposta questa schermata:

LO JRE8 Advanced Setup.png

Fai clic sulle opzioni per:

  • Utilizzare un ambiente runtime Java
  • Oracle Corporation 1.8.0_161
  • Abilita registrazione macro (sperimentale)
  • Clicca OK
  • Ti verrà chiesto di riavviare, fai clic su "Riavvia ora".

Macro di LibreOffice Writer

La macro leggerà l'intero documento e:

  • cambia il nome del carattere in Ubuntu.
  • Se l'intestazione 1 imposta la dimensione del carattere su 28
  • altrimenti se la dimensione del carattere è 18 impostata su 22
  • altrimenti imposta la dimensione del carattere su 12

La macro salverà il documento e uscirà da Libreoffice Writer.

Disattiva la finestra di dialogo

Salva un file e viene visualizzata questa finestra di dialogo:

LO Writer disattiva RTF dialog.png

Disattiva questo messaggio come mostrato sullo schermo. La macro potrebbe non funzionare correttamente se questa opzione è attiva.

Contenuti macro

Ho trascorso alcuni giorni a tentare di registrare una macro utilizzando "Strumenti" -> "Macro" -> "Registra macro" -> "Base". All'inizio sembrava promettente, ma la macro registrata aveva un comportamento incoerente e doveva essere abbandonata per una macro di base scritta a mano. Un aiuto trovato in Stack Overflow per un esperto lì per aiutarmi con la codifica di base di base . Ecco il risultato:

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

2

Ecco un approccio unico che utilizza Libre Office. Non è un batch, ma può aiutare a ispirare altre risposte.

Apri un file rtf con il carattere Ubuntu, H1 a 28 pt, del testo a 12 pt e alcuni a 18 pt.

Ecco un esempio:

test rtf

I seguenti passaggi applicheranno la modifica richiesta nella tua domanda "se la dimensione del carattere: 18px {renderlo 22px} # Tutto il testo con dimensione del carattere 18px ora è 22px;"

Fai clic su Modifica → Trova e sostituisci nel menu o seleziona CtrlHAltre opzioni Fai clic su Cerca per casella quindi pulsante Attributi casella di controllo Dimensione carattere quindi pulsante Formato seleziona 18 pt dalla casella di scorrimento all'estrema destra Fai clic su Sostituisci con casella quindi Formato pulsante e seleziona 22 pt dal casella di scorrimento all'estrema destra

FindNreplace

Fai clic su Sostituisci tutto

la riga applicabile che è stata modificata era:

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

la fs36 è cambiata in fs44

l'unico altro campo che è stato modificato è stato il campo revtime che potresti voler aggiornare o meno:

{\ Revtim \ yr2018 \ MO3 \ dy31 \ HR22 \ min19}

Conoscere ciò che è cambiato ci fornisce un modello per lo sviluppo di un approccio batch. È probabilmente possibile registrare una macro che lo fa all'apertura di un documento o sviluppare uno script che apporti le modifiche desiderate.


1

Ci sono alcuni grandi indizi su come si potrebbe fare questo nella specifica RTF.

Ecco la mia analisi del problema.

Realizzare questo usando la CLI come si suppone sembrerebbe l'approccio più semplice in quanto non ho visto alcuna applicazione basata sulla GUI in grado di gestire questo tipo di conversione batch. Sembra che puoi semplicemente modificare l'intestazione:

L'intestazione ha la sintassi seguente:

<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.

Personalmente, dopo aver esaminato queste informazioni, mi viene in mente che tutto ciò che stai tentando di fare sembra supportato nell'intestazione, dalla selezione del carattere allo stile.

Ci sono strumenti disponibili per aiutarti in questo processo che illustrerò di seguito in quanto non ho un esempio dello stile del documento che hai né dello stile del documento che desideri e una risposta più generica sarà probabilmente più utile alla comunità di uno mirato alla tua situazione esatta.

grepsarà utile per analizzare i file esistenti da convertire e un campione dello stile di destinazione per quelli esistenti <fonttbl>e le
<stylesheet>selezioni. Dopo aver determinato ciò che hai effettivamente, dovresti essere in grado di scrivere un semplice script utilizzando sedper sostituire il contenuto dell'intestazione esistente con il contenuto dell'intestazione desiderato. Esistono numerosi esempi su come scorrere i file in uno script bash ( esempio ) e su come utilizzare sed ( esempio ) liberamente disponibili se non si ha familiarità con questi concetti.

Esistono anche opzioni di una riga per sostituire una stringa in un file. Alcuni potrebbero funzionare meglio di altri a seconda del caso d'uso. A seconda del contenuto dei tuoi file, può o non ha senso sostituire semplicemente ogni istanza di fs36Con fs44quale shell stai usando potrebbe anche avere un impatto sul modo migliore di scrivere le tue espressioni. A seconda della complessità e il contenuto dei documenti potrebbe essere meglio utilizzare sed, perlo grepo forse anche una loro combinazione. Poiché questa è diventata una domanda di programmazione, è meglio rimandarti a /programming/15402770/how-to-grep-and-replace dove troverai facilmente una mezza dozzina di approcci diversi, uno dei che probabilmente soddisfa perfettamente le tue esigenze.

Ad esempio, se desideri applicare queste modifiche a livello di sistema,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;come fornito da rezizter è probabilmente il migliore.

Se desideri contenere le modifiche in una singola directory,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'come fornito da billtian è una scelta eccellente.

Per essere al sicuro, è necessario preelaborare i file per assicurarsi che eventuali modifiche apportate non abbiano conseguenze indesiderate. Per esempio:

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

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

Quanto sopra mostrerà le righe contenenti la stringa di ricerca fs36 per ciascun file .rtf nella directory.

Modificare:

Le specifiche più recenti sono disponibili qui. Non vedo alcun cambiamento che dovrebbe influire su questo approccio.


1
Ciao, ti ringrazio per aver descritto una soluzione CLI. Per favore condividi un esempio di codice per come cambierai un rtfcon un'intestazione e un testo in sedmodo che la risposta sia centralizzata sed.
JohnDoea,

@JohnDoea Sempre pronto ad aiutare. Spero che sia tu che i futuri utenti lo troviate utile.
Elder Geek
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.