Modifiez 2 documents LibreOffice ou plus pour avoir exactement le même style / formatage

14

Disons que j'ai un répertoire avec environ 100 .rtffichiers que je modifie avec LibreOffice Writer.

Je souhaite que tous les fichiers de ce répertoire aient exactement les mêmes directives de style de texte riche de base, par exemple:

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

Et ainsi de suite ... Donc, fondamentalement, je veux changer tous les fichiers en même temps. Un tel "style en vrac" est-il possible?

Peut-être que c'est possible avec la CLI d'une manière ou d'une autre?

JohnDoea
la source
3
Ce ne sera pas une tâche facile, je pense. S'ils sont tous structurés de la même manière, vous pouvez peut-être utiliser une solution hacky en remplaçant le texte dans les fichiers .rtf à partir de la ligne de commande. Cependant, cela dépend beaucoup de l'apparence des fichiers rtf et de leur similitude.
Sebastian Stark
J'ai trouvé de l'aide dans Stack Overflow pour une toute nouvelle macro LibreOffice Writer à partir de zéro ce soir. Nous n'avons plus besoin de connaître toutes les tailles de police existantes possibles.
WinEunuuchs2Unix
Dans un dernier effort, j'ai demandé aux experts de Stack Overflow de publier une réponse ici avant la fin du délai de grâce: stackoverflow.com/questions/49640951/…
WinEunuuchs2Unix
Vous avez des dizaines de milliers de points de réputation. Je vous suggère humblement d'envisager de donner quelque chose comme 500-750. Juste une considération. Juste juste juste.
JohnDoea

Réponses:

5

Utilisez les outils Libreoffice au lieu de CLI

Lorsque vous ne disposez que d'outils de ligne de commande, tout ressemble à un problème de ligne de commande. J'ai décidé d'écrire cette réponse en utilisant les macros LibreOffice:

  1. Utilisez une boucle de ligne de commande pour traiter chaque document Writer dans un environnement "sans tête".
  2. Exécutez une macro pour modifier le .rtffichier de document Writer (Rich Text Format) Writer.
  3. La macro enregistre le fichier et quitte
  4. Retournez à 1.

Créer des données de test

Créez deux fichiers ou plus contenant:

richtext2.png

Créer un script ~/Downloads/copy-rtf.shcontenant:

cp ~/Documents/*.rtf ~/Downloads

Marquer comme exécutable en utilisant

chmod a+x ~/Downloads/copy-rtf.sh
  • Pendant le développement et les tests, les *.rtffichiers de modification des macros s'exécuteront dans le ~/Downloadsrépertoire.
  • Avant chaque type de test cd ~/Downloadset exécution./copy-rtf.sh
  • Une fois la sortie parfaite, ils sont recopiés dans le répertoire en direct.

Le répertoire Téléchargements est utilisé car:

  • tout le monde a un ~/Downloads
  • il est ajouté périodiquement et vidé manuellement périodiquement
  • il est plus permanent que le /tmp/répertoire qui peut ne pas persister lors des redémarrages.

Exécuter une macro dans un environnement sans tête

À l'aide de cette réponse Stack Exchange, appelez Libreoffice Writer à partir de la ligne de commande et passez-lui un nom de macro global à exécuter:

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

La réponse ci-dessus peut ne pas fonctionner, donc une autre méthode peut être essayée:

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

Installer Java Runtime Environment

Pour exécuter des macros, vous devez installer Java Runtime Environment (JRE). La page Web du développeur contient des instructions pour télécharger et installer manuellement.

Cependant, cette Q&A AU: /ubuntu//a/728153/307523 suggère qu'elle est aussi simple que:

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

J'ai essayé la méthode AU Q&A et après la première étape de l'ajout du PPA, un écran de démarrage apparaît avec des informations supplémentaires. Le plus utile est un lien vers la configuration de JRE 8 sur les systèmes Debian .

La troisième étape de l'installation de JRE 8 nécessite que vous utilisiez Tabet Enteracceptiez le contrat de licence. Votre machine s'arrêtera pendant quelques minutes pendant la partie la plus lourde de la routine d'installation.

Maintenant, ouvrez LibreOffice et sélectionnez Outils -> Options -> LibreOffice -> Avancé et configurez cet écran:

LO JRE8 Advanced Setup.png

Cliquez sur les options pour:

  • Utiliser un environnement d'exécution Java
  • Oracle Corporation 1.8.0_161
  • Activer l'enregistrement macro (expérimental)
  • Cliquez sur OK
  • Il vous sera demandé de redémarrer, cliquez sur "Redémarrer maintenant".

LibreOffice Writer Macro

La macro lira tout le document et:

  • changez le nom de la police en Ubuntu.
  • Si l'en-tête 1 définit la taille de police à 28
  • sinon si la taille de la police est de 18 réglée sur 22
  • sinon définissez la taille de la police sur 12

La macro enregistrera le document et quittera Libreoffice Writer.

Désactiver la boîte de dialogue

Faites un enregistrement de fichier et cette boîte de dialogue apparaît:

LO Writer désactive RTF dialog.png

Désactivez ce message comme indiqué à l'écran. La macro peut ne pas s'exécuter correctement si cette option est activée.

Contenu de la macro

J'ai passé quelques jours à essayer d'enregistrer une macro en utilisant "Outils" -> "Macros" -> "Enregistrer la macro" -> "Basique". Au début, cela semblait prometteur, mais la macro enregistrée avait un comportement incohérent et a dû être abandonnée pour une macro de base manuscrite. Une aide trouvée dans Stack Overflow pour un expert là-bas pour m'aider avec le codage de base de base . Voici le résultat:

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
la source
2

Voici une approche unique en utilisant Libre Office. Ce n'est pas un lot, mais cela peut aider à inspirer d'autres réponses.

Ouvrez un fichier rtf qui a la police Ubuntu, H1 à 28 pt, du texte à 12 pt et certains à 18 pt.

Voici un exemple:

test rtf

Les étapes suivantes appliqueront la modification demandée dans votre question "si taille de police: 18px {faites-le 22px} # Tout le texte avec la taille de police 18px est maintenant 22px;"

Cliquez sur Édition → Rechercher et remplacer dans le menu ou appuyez sur CtrlHAutres options Cliquez sur la case Rechercher, puis sur le bouton Attributs Taille de la police, puis sur le bouton Format, sélectionnez 18 pt dans la boîte de défilement à l'extrême droite Cliquez sur Remplacer par, puis sur le bouton Format et sélectionnez 22 pt dans la boîte de défilement à l'extrême droite

FindNreplace

Cliquez sur Remplacer tout

la ligne applicable qui a changé était:

\ 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

le fs36 a changé en fs44

le seul autre champ qui a changé était le champ revtime que vous souhaitiez ou non mettre à jour:

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

Savoir ce qui a changé nous fournit un modèle pour développer une approche par lots. Il est probablement possible d'enregistrer une macro qui le fait à l'ouverture d'un document ou de développer un script qui apporte les modifications souhaitées.

Elder Geek
la source
1

Il y a quelques excellents indices sur la façon dont on pourrait s'y prendre dans la spécification RTF.

Voici mon analyse du problème.

Réaliser cela en utilisant la CLI comme vous le supposez semble être l'approche la plus simple car je n'ai vu aucune application basée sur une interface graphique pouvant gérer ce type de conversion par lots. Il semble que vous pouvez simplement modifier l'en-tête:

L'en-tête a la syntaxe suivante:

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

Personnellement, après examen de ces informations, il me semble que tout ce que vous essayez de faire semble être pris en charge dans l'en-tête, de la sélection de la police au style.

Il y a des outils disponibles pour vous aider dans ce processus que je vais décrire ci-dessous car je n'ai pas d'exemple du style de document que vous avez ni du style de document que vous voulez et une réponse plus générique sera probablement plus utile à la communauté que un ciblé sur votre situation exacte.

grepsera utile pour analyser les fichiers existants à convertir et un échantillon du style cible pour existantes <fonttbl>et
<stylesheet>sélections. Après avoir déterminé ce que vous avez réellement, vous devriez pouvoir écrire un script simple en utilisant sedpour remplacer le contenu d'en-tête existant par le contenu d'en-tête souhaité. Il existe de nombreux exemples sur la façon de parcourir les fichiers dans un script bash ( exemple ) et comment utiliser sed ( exemple ) librement disponible si vous n'êtes pas familier avec ces concepts.

Il existe également une option de ligne pour remplacer une chaîne dans un fichier. Certains peuvent fonctionner mieux que d'autres en fonction de votre cas d'utilisation. Selon le contenu de vos fichiers, il peut ou non être judicieux de remplacer simplement chaque instance de fs36Avec fs44quel shell vous utilisez peut également avoir une incidence sur la meilleure façon d'écrire vos expressions. En fonction de la complexité et le contenu de vos documents , vous pouvez être mieux d'utiliser sed, perlou greppeut - être même une combinaison d'entre eux. Comme cela est devenu une question de programmation, il est préférable de vous référer à /programming/15402770/how-to-grep-and-replace où vous trouverez facilement une 1/2 douzaine d'approches différentes, l'une des qui est susceptible de répondre parfaitement à vos besoins.

Par exemple, si vous souhaitez appliquer ces modifications à l'échelle du système,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;tel que fourni par rezizter est probablement le meilleur.

Si vous souhaitez contenir vos modifications dans un seul répertoire,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'tel que fourni par billtian est un excellent choix.

Pour être sûr, vous devez prétraiter les fichiers pour vous assurer que les modifications que vous apporterez n'auront pas de conséquences inattendues. Par exemple:

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

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

Ce qui précède affichera les lignes contenant la chaîne de recherche fs36 pour chaque fichier .rtf du répertoire.

Éditer:

La spécification la plus récente peut être obtenue ici. Je ne vois aucun changement qui devrait avoir un impact sur cette approche.

Elder Geek
la source
1
Bonjour, je vous remercie d'avoir d'abord décrit une solution CLI. Veuillez partager un exemple de code pour savoir comment vous allez modifier un rtfavec un en-tête et un texte sedafin que la réponse soit centralisée sed.
JohnDoea
@JohnDoea Toujours désireux d'aider. J'espère que vous et les futurs utilisateurs le jugerez utile.
Elder Geek