Cambie 2 o más documentos de LibreOffice para que tengan exactamente el mismo estilo / formato

14

Digamos que tengo un directorio con aproximadamente 100 .rtfarchivos que edito con LibreOffice Writer.

Deseo que todos los archivos en ese directorio tengan exactamente las mismas directivas básicas de diseño de texto enriquecido, por ejemplo:

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

Y así sucesivamente ... Entonces, básicamente quiero cambiar todos los archivos a la vez. ¿Es posible ese "estilo masivo"?

¿Tal vez es posible con la CLI de alguna manera?

JohnDoea
fuente
3
Esta no será una tarea fácil, creo. Si todos están estructurados de la misma manera, tal vez podría usar alguna solución hacky reemplazando el texto en los archivos .rtf desde la línea de comandos. Sin embargo, esto depende mucho de cómo se vean los archivos rtf y de cuán similares sean.
Sebastian Stark
He encontrado ayuda en Stack Overflow para una nueva macro de LibreOffice Writer a partir de cero esta noche. Ya no necesitamos saber cada tamaño de fuente existente posible.
WinEunuuchs2Unix
En un último esfuerzo, he pedido a los expertos de Stack Overflow que publiquen una respuesta aquí antes de que finalice el período de gracia: stackoverflow.com/questions/49640951/…
WinEunuuchs2Unix
Ustedes tienen decenas de miles de puntos de reputación. Humildemente sugiero que consideres dar algo como 500-750. Solo una consideración. Solo solo solo.
JohnDoea

Respuestas:

5

Use las herramientas de Libreoffice en lugar de la CLI

Cuando todo lo que tiene son herramientas de línea de comando, todo parece un problema de línea de comando. He decidido escribir esta respuesta usando las macros de LibreOffice:

  1. Utilice un bucle de línea de comando para procesar cada documento de Writer en un entorno "sin cabeza".
  2. Ejecute la macro para cambiar el .rtfarchivo de documento del Escritor (Formato de texto enriquecido).
  3. Macro guarda el archivo y sale
  4. Vuelve a 1.

Crear datos de prueba

Cree dos o más archivos que contengan:

richtext2.png

Crear script que ~/Downloads/copy-rtf.shcontenga:

cp ~/Documents/*.rtf ~/Downloads

Marcar como ejecutable usando

chmod a+x ~/Downloads/copy-rtf.sh
  • Durante el desarrollo y las pruebas, los *.rtfarchivos de modificación de macros se ejecutarán en el ~/Downloadsdirectorio.
  • Antes de cada tipo de prueba cd ~/Downloadsy ejecución./copy-rtf.sh
  • Una vez que la salida es perfecta, se vuelven a copiar en el directorio en vivo.

El directorio de descargas se usa porque:

  • todos tienen un ~/Downloads
  • se agrega regularmente y se vacía manualmente periódicamente
  • es más permanente que el /tmp/directorio que puede no persistir entre reinicios.

Ejecutar macro en un entorno sin cabeza

Usando esta respuesta de Stack Exchange, invoque Libreoffice Writer desde la línea de comando y pásele un nombre de macro global para ejecutar:

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

La respuesta anterior puede no funcionar, por lo que se puede probar otro método :

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

Instalar Java Runtime Environment

Para ejecutar macros, necesita tener instalado Java Runtime Environment (JRE). La página web del desarrollador tiene instrucciones para descargar e instalar manualmente.

Sin embargo, este AU Q&A: /ubuntu//a/728153/307523 sugiere que es tan simple como:

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

Probé el método AU Q&A y después del primer paso de agregar el PPA aparece una pantalla de bienvenida con información adicional. Lo más útil es un enlace para configurar JRE 8 en sistemas Debian .

El tercer paso para instalar JRE 8 requiere que use Taby Enteracepte el Acuerdo de licencia. Su máquina se detendrá durante unos minutos durante la parte más pesada de la rutina de instalación.

Ahora abra LibreOffice y seleccione Herramientas -> Opciones -> LibreOffice -> Avanzado y configure esta pantalla:

LO JRE8 Advanced Setup.png

Haga clic en las opciones para:

  • Use un entorno de tiempo de ejecución Java
  • Oracle Corporation 1.8.0_161
  • Habilitar grabación macro (experimental)
  • Haga clic en Aceptar
  • Se le pedirá que reinicie, haga clic en "Reiniciar ahora".

LibreOffice Writer Macro

La macro leerá todo el documento y:

  • cambie el nombre de la fuente a Ubuntu.
  • Si el título 1 establece el tamaño de fuente en 28
  • de lo contrario, si el tamaño de fuente es 18 establecido en 22
  • de lo contrario, establezca el tamaño de fuente en 12

La macro guardará el documento y saldrá de Libreoffice Writer.

Desactivar el diálogo

Guarde un archivo y aparecerá este cuadro de diálogo:

LO Writer apaga el diálogo RTF.png

Apague este mensaje como se muestra en la pantalla. Es posible que la macro no se ejecute correctamente si esta opción está activada.

Contenidos macro

Pasé unos días intentando grabar una macro usando "Herramientas" -> "Macros" -> "Grabar macro" -> "Básico". Al principio parecía prometedor, pero la macro grabada tenía un comportamiento inconsistente y tuvo que ser abandonada por una macro básica escrita a mano. Encontré ayuda en Stack Overflow para un experto que me ayudó con la codificación básica básica . Aquí está el resultado:

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
fuente
2

Aquí hay un enfoque único con Libre Office. No es un lote, pero puede ayudar a inspirar otras respuestas.

Abra un archivo rtf que tenga la fuente Ubuntu, H1 a 28 pt, algo de texto a 12pt y algo a 18 pt.

Aquí hay un ejemplo:

prueba rtf

Los siguientes pasos aplicarán el cambio solicitado en su pregunta "if size-font: 18px {make it 22px} # Todo el texto con font-size 18px ahora es 22px;"

Haga clic en Editar → Buscar y reemplazar en el menú o presione CtrlHOtras opciones Haga clic en el cuadro Buscar y luego en el botón de atributos Casilla de verificación Tamaño de fuente y luego en el botón Formato seleccione 18 pt del cuadro de desplazamiento en el extremo derecho Haga clic en Reemplazar con el cuadro y luego en el botón Formato y seleccione 22 pt del cuadro de desplazamiento en el extremo derecho

FindNreplace

Haga clic en Reemplazar todo

la línea aplicable que cambió fue:

\ 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

el fs36 cambió a fs44

el único otro campo que cambió fue el campo revtime que puede o no querer actualizar:

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

Saber lo que cambió nos proporciona un modelo para desarrollar un enfoque por lotes. Es probable que sea posible grabar una macro que haga esto al abrir un documento o desarrollar un script que realice los cambios que desee.

Elder Geek
fuente
1

Hay algunas pistas excelentes sobre cómo se puede hacer esto en la especificación RTF.

Aquí está mi análisis del problema.

Lograr esto usando la CLI como supones parece ser el enfoque más simple, ya que no he visto ninguna aplicación basada en GUI que pueda manejar este tipo de conversión por lotes. Parece que simplemente puede modificar el encabezado:

El encabezado tiene la siguiente sintaxis:

<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, al revisar esta información, se me ocurre que todo lo que intenta hacer parece admitido en el encabezado, desde la selección de fuente hasta el estilo.

Hay herramientas disponibles para ayudarlo con este proceso que resumiré a continuación, ya que no tengo un ejemplo del estilo de documento que tiene ni el estilo de documento que desea y una respuesta más genérica probablemente sea más útil para la comunidad que uno dirigido a su situación exacta.

grepserá útil para analizar los archivos existentes que se convertirán y una muestra del estilo de destino para los existentes <fonttbl>y las
<stylesheet>selecciones. Una vez que haya determinado lo que realmente tiene, debería poder escribir un script simple utilizando sedpara reemplazar el contenido del encabezado existente con el contenido del encabezado deseado. Existen numerosos ejemplos de cómo iterar a través de archivos en un script bash ( ejemplo ) y cómo utilizar sed ( ejemplo ) disponible gratuitamente si no está familiarizado con estos conceptos.

También hay opciones de una línea para reemplazar una cadena en un archivo. Algunos pueden funcionar mejor que otros dependiendo de su caso de uso. Dependiendo del contenido de sus archivos, puede tener sentido o no reemplazar simplemente cada instancia de fs36Con fs44qué shell que está utilizando también puede tener relación con la mejor manera de escribir sus expresiones. Dependiendo de la complejidad y contenido de los documentos puede ser mejor usar sed, perlo grepo tal vez incluso una combinación de ellos. Como esto se ha convertido en una pregunta de programación, es mejor remitirlo a /programming/15402770/how-to-grep-and-replace, donde encontrará fácilmente media docena de enfoques diferentes, uno de que es probable que se adapte perfectamente a sus necesidades.

Por ejemplo, si desea aplicar estos cambios en todo el sistema,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;según lo provisto por rezizter es probablemente el mejor.

Si desea contener sus cambios en un solo directorio,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'según lo provisto por billtian es una excelente opción.

Para estar seguro, debe preprocesar los archivos para asegurarse de que cualquier cambio que realice no tendrá consecuencias no deseadas. Por ejemplo:

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

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

Lo anterior mostrará las líneas que contienen la cadena de búsqueda fs36 para cada archivo .rtf en el directorio.

Editar:

La especificación más reciente se puede obtener aquí. No veo ningún cambio que deba afectar este enfoque.

Elder Geek
fuente
1
Hola, gracias por describir en primer lugar una solución CLI. Comparta un ejemplo de código de cómo cambiará un rtfcon un encabezado y un texto sedpara que la respuesta se centralice sed.
JohnDoea
@JohnDoea Siempre dispuesto a ayudar. Espero que tanto usted como futuros usuarios lo encuentren útil.
Élder Geek