Altere 2 ou mais documentos do LibreOffice para ter exatamente o mesmo estilo / formatação


14

Digamos que eu tenha um diretório com cerca de 100 .rtfarquivos que edito com o LibreOffice Writer.

Desejo que todos os arquivos nesse diretório tenham exatamente as mesmas diretivas básicas de estilo de rich text, por exemplo:

* 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 assim por diante ... Então, basicamente, quero alterar todos os arquivos de uma só vez. É possível "estilo em massa"?

Talvez seja possível com a CLI de alguma forma?


3
Esta não será uma tarefa fácil, eu acho. Se todos estiverem estruturados da mesma maneira, talvez você possa usar alguma solução hacky com a substituição de texto nos arquivos .rtf na linha de comando. No entanto, isso depende muito da aparência dos arquivos rtf e da semelhança entre eles.
Sebastian Stark

Encontrei ajuda no Stack Overflow para uma nova macro do LibreOffice Writer a partir do zero hoje à noite. Não precisamos mais conhecer todos os tamanhos possíveis de fontes existentes.
WinEunuuchs2Unix

Em um último esforço Pedi especialistas Stack Overflow para deixar uma resposta aqui antes de terminar o período de graça: stackoverflow.com/questions/49640951/...
WinEunuuchs2Unix

Vocês têm dezenas de milhares de pontos de reputação. Eu humildemente sugiro que você considere dar algo como 500-750. Apenas uma consideração. Apenas apenas.
JohnDoea

Respostas:


5

Use as ferramentas do Libreoffice em vez da CLI

Quando tudo o que você tem são ferramentas de linha de comando, tudo parece um problema de linha de comando. Decidi escrever esta resposta usando as macros do LibreOffice:

  1. Use um loop de linha de comando para processar todos os documentos do Writer em um ambiente "sem cabeça".
  2. Execute a macro para alterar o .rtfarquivo de documento do Writer Format (Rich Text Format).
  3. Macro salva arquivo e sai
  4. Volta para 1.

Criar dados de teste

Crie dois ou mais arquivos contendo:

richtext2.png

Crie um script ~/Downloads/copy-rtf.shcontendo:

cp ~/Documents/*.rtf ~/Downloads

Marcar como executável usando

chmod a+x ~/Downloads/copy-rtf.sh
  • Durante o desenvolvimento e o teste, os *.rtfarquivos de modificação de macros serão executados no ~/Downloadsdiretório
  • Antes de cada tipo de teste cd ~/Downloadse execução./copy-rtf.sh
  • Depois que a saída é perfeita, eles são copiados de volta para o diretório ativo.

O diretório Downloads é usado porque:

  • todo mundo tem um ~/Downloads
  • é adicionado ao esvaziado regularmente e manualmente periodicamente
  • é mais permanente que o /tmp/diretório que pode não persistir durante as reinicializações.

Executar macro em ambiente sem cabeça

Usando esta resposta do Stack Exchange, invoque o Libreoffice Writer na linha de comando e passe um nome de macro global para executar:

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

A resposta acima pode não funcionar, então outro método pode ser tentado:

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

Instalar o Java Runtime Environment

Para executar macros, você precisa do Java Runtime Environment (JRE) instalado. A página da web do desenvolvedor tem instruções para baixar e instalar manualmente.

No entanto, este Q&A da UA: /ubuntu//a/728153/307523 sugere que é tão simples quanto:

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

Tentei o método de perguntas e respostas da AU e, após o primeiro passo da adição do PPA, uma tela inicial aparece com informações adicionais. O mais útil é um link para configurar o JRE 8 nos sistemas Debian .

A terceira etapa da instalação do JRE 8 requer que você use Tabe Enteraceite o Contrato de Licença. Sua máquina fará uma pausa por alguns minutos durante a parte mais pesada da rotina de instalação.

Agora abra o LibreOffice e selecione Ferramentas -> Opções -> LibreOffice -> Avançado e configure esta tela:

LO JRE8 Advanced Setup.png

Clique nas opções para:

  • Use um Java Runtime Environment
  • Oracle Corporation 1.8.0_161
  • Ativar gravação de macro (experimental)
  • Clique OK
  • Você será solicitado a reiniciar, clique em "Reiniciar agora".

Macro do LibreOffice Writer

A macro lerá todo o documento e:

  • mude o nome da fonte para o Ubuntu.
  • Se o cabeçalho 1 definir o tamanho da fonte para 28
  • caso contrário, se o tamanho da fonte for 18, definido como 22
  • caso contrário, defina o tamanho da fonte como 12

A macro salvará o documento e sairá do Libreoffice Writer.

Desativar a caixa de diálogo

Salve o arquivo e essa caixa de diálogo será exibida:

O LO Writer desativa o RTF dialog.png

Desative esta mensagem como mostra a tela. A macro pode não funcionar corretamente se esta opção estiver ativada.

Conteúdo da macro

Passei alguns dias tentando gravar uma macro usando "Ferramentas" -> "Macros" -> "Gravar macro" -> "Básico". A princípio, parecia promissor, mas a macro gravada tinha um comportamento inconsistente e teve que ser abandonada para uma macro básica escrita à mão. Uma ajuda encontrada no Stack Overflow para um especialista lá para me ajudar com a codificação básica básica . Aqui está o 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

2

Aqui está uma abordagem única usando o Libre Office. Não é um lote, mas pode ajudar a inspirar outras respostas.

Abra um arquivo rtf com a fonte Ubuntu, H1 em 28 pt, algum texto em 12pt e outros em 18 pt.

Aqui está um exemplo:

teste rtf

As etapas a seguir aplicarão a alteração solicitada na sua pergunta "se o tamanho da fonte: 18 px {make 22px} # Todo o texto com tamanho da fonte 18 px for agora 22 px;"

Clique em Editar → Localizar e substituir no menu ou clique em CtrlHOutras opções. Clique na caixa Procurar e, em seguida, no botão Atributos. Tamanho da fonte. Em seguida, no botão Formatar, selecione 18 pt na caixa de rolagem à direita. caixa de rolagem à direita

FindNreplace

Clique em Substituir tudo

a linha aplicável que mudou foi:

\ 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

o FS36 foi alterado para FS44

o único outro campo que mudou foi o campo revtime que você pode ou não querer atualizar:

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

Saber o que mudou nos fornece um modelo para o desenvolvimento de uma abordagem em lote. Provavelmente, é possível gravar uma macro que faz isso ao abrir um documento ou desenvolver um script que faça as alterações conforme desejado.


1

Existem algumas ótimas pistas sobre como alguém pode fazer isso na especificação RTF.

Aqui está a minha análise do problema.

Conseguir isso usando a CLI como você supõe parecer a abordagem mais simples, pois eu não vi nenhum aplicativo baseado em GUI que possa lidar com esse tipo de conversão em lote. Parece que você pode simplesmente modificar o cabeçalho:

O cabeçalho tem a seguinte sintaxe:

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

Pessoalmente, após a revisão dessas informações, ocorre-me que tudo o que você está tentando fazer parece ter suporte no cabeçalho, da seleção da fonte ao estilo.

Existem ferramentas disponíveis para ajudá-lo nesse processo, que descreverei abaixo, pois não tenho um exemplo do estilo de documento que você tem nem do estilo de documento que você deseja, e uma resposta mais genérica provavelmente será mais útil para a comunidade do que um direcionado à sua situação exata.

grepserá útil analisar os arquivos existentes a serem convertidos e uma amostra do estilo de destino para os existentes <fonttbl>e as
<stylesheet>seleções. Depois de determinar o que você realmente tem, você poderá escrever um script simples utilizando sedpara substituir o conteúdo do cabeçalho existente pelo conteúdo do cabeçalho desejado. Existem inúmeros exemplos de como iterar através de arquivos em um script bash ( exemplo ) e como utilizar o sed ( exemplo ) disponível gratuitamente se você não estiver familiarizado com esses conceitos.

Há também opções de uma linha para substituir uma sequência em um arquivo. Alguns podem funcionar melhor que outros, dependendo do seu caso de uso. Dependendo do conteúdo de seus arquivos, pode ou não fazer sentido substituir simples todas as instâncias de fs36Com fs44qual shell você está usando também pode ter influência na melhor forma de escrever suas expressões. Dependendo da complexidade e do conteúdo dos seus documentos você pode ser melhor fora de usar sed, perlou grepou talvez até mesmo uma combinação deles. Como essa se tornou uma questão de programação, é melhor encaminhá-lo para /programming/15402770/how-to-grep-and-replace, onde você encontrará facilmente meia dúzia de abordagens diferentes, uma das o que provavelmente atenderá perfeitamente às suas necessidades.

Por exemplo, se você deseja aplicar essas alterações em todo o sistema,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;como fornecido pelo rezizter É provavelmente o melhor.

Se você deseja conter suas alterações em um único diretório,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'conforme fornecido pelo billtian é uma excelente escolha.

Para garantir a segurança, você deve pré-processar os arquivos para garantir que quaisquer alterações que você possa fazer não tenham consequências indesejadas. Por exemplo:

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

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

O exemplo acima exibirá as linhas que contêm a cadeia de pesquisa fs36 para cada arquivo .rtf no diretório

Editar:

A especificação mais recente pode ser obtida aqui. Não vejo nenhuma alteração que deva impactar essa abordagem.


1
Olá, agradeço por descrever primeiro uma solução CLI. Compartilhe um exemplo de código de como você alterará a rtfcom um cabeçalho e um texto sedpara que a resposta seja centralizada sed.
31418 JohnDoea

@JohnDoea Sempre ansioso para ajudar. Espero que você e os usuários futuros o considerem útil.
Elder Geek
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.