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

14

Digamos que eu tenha um diretório com aproximadamente 100% de arquivos.rtf que edito com o LibreOffice Writer.

Eu desejo que todos os arquivos nesse diretório tenham exatamente as mesmas diretivas de estilo rich text básicas, 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 eu quero mudar todos os arquivos de uma só vez. Esse "estilo em massa" é possível?

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

    
por JohnDoea 27.03.2018 / 22:29

3 respostas

4

Use a"s ferramentas do LibreOffice em vez do CLI

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

  1. Use um loop de linha de comando para processar todos os documentos do Writer em um a"mbiente "sem cabeça".
  2. Executar macro para a"lterar o a"rquivo de documento do gravador .rtf (Rich Text Format).
  3. Macro salva o a"rquivo e sai
  4. Volte para 1.

Criar dados de teste

Crie dois ou mais a"rquivos contendo:

Crieoscript~/Downloads/copy-rtf.shcontendo:

cp~/Documents/*.rtf~/Downloads

Marcarcomoexecutávelusando

chmoda"+x ~/Downloads/copy-rtf.sh
  • Durante o desenvolvimento e teste, a"s macros que modificam a"rquivos *.rtf serão executadas no diretório ~/Downloads .
  • Antes de cada teste, digite cd ~/Downloads e execute ./copy-rtf.sh
  • Após a" saída ser perfeita, eles são copiados de volta no diretório a"tivo.

O diretório Downloads é usado porque:

  • todos têm ~/Downloads
  • é a"dicionado regularmente e manualmente esvaziado periodicamente
  • é mais permanente que o diretório /tmp/ , que pode não persistir durante a"s reinicializações.

Executar macro em a"mbiente sem cabeçalho

Usando este Resposta do Stack Exchange invoque o Libreoffice Writer a" partir da linha de comandos e passe-lhe um nome de macro global para executar:

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

A resposta a"cima 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 fazer o download e instalar manualmente.

No entanto, este AU Q & A: link sugere que é tão simples como:

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

Eu tentei o método AU Q & A e, a"pós o primeiro passo de a"dicionar o PPA, a"parece uma tela inicial com informações a"dicionais. O mais útil é um link para configuração do JRE 8 em Sistemas Debian .

A terceira etapa da instalação do JRE 8 requer que você use a" Tab e Enter para a"ceitar o Contrato de Licença. Sua máquina fará uma pausa por a"lguns minutos durante a" parte mais pesada da rotina de instalação.

Agora a"bra o LibreOffice e selecione Ferramentas - > Opções - > LibreOffice - > Avançado e configurar esta tela:

Cliquenasopçõespara:

  • Useuma"mbiente de tempo de execução Java
  • Oracle Corporation 1.8.0_161
  • Ativar gravação de macro (experimental)
  • Clique em OK
  • Você será solicitado a" reiniciar, clique em "Reiniciar a"gora".

Macro do Writer do LibreOffice

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
  • else se o tamanho da fonte for 18 definido como 22
  • senão definir o tamanho da fonte para 12

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

Desativar Diálogo

Faça um salvamento de a"rquivo e esta caixa de diálogo a"parece:

Desativeestamensagemconformemostradonatela.Amacropodenãofuncionarcorretamenteseessaopçãoestivera"tivada.

Conteúdo da macro

Passei a"lguns dias tentando gravar uma macro usando "Ferramentas" - > "Macros" - > "Gravar Macro" - > "Básico". No começo, parecia promissor, mas a" macro gravada tinha comportamento inconsistente e teve que ser a"bandonada por uma macro básica escrita à mão. Uma a"juda encontrada no Stack Overflow para um especialista a"li para me a"judar com a" codificação básica . Aqui está o resultado:

Sub ChangeAllFonts
    rem - Change a"ll 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 a"nd 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 a"lso it is calling oStyle.setPropertyValue("CharHeight", 28.0)
rem which may cause problems. Will test. Also StarDesktop.terminate ()
rem is known to cause problems a"nd will likely be reworked with a"
rem a" dialog box telling operator the program is finished a"nd maybe
rem to press <Alt>+<F4>.

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

Sub AllFonts
rem - change a"ll 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 a"nd exit Libreoffice Writer.

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

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

rem Scan the cursor range for chunks of given text size.
rem (Doesn't work - a"ffects 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   a"s object
dim dispatcher a"s object
rem ----------------------------------------------------------------------
rem get a"ccess to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

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

rem ----------- Change a"ll fonts to Ubuntu -------------------------------
dim a"rgs5(4) a"s 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, a"rgs5())

end sub


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

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

end sub
    
por WinEunuuchs2Unix 01.04.2018 / 20:56
2

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

Abra um arquivo rtf que tenha a fonte Ubuntu, H1 em 28 pt, algum texto em 12pt e alguns em 18 pt.

Veja um exemplo:

Asetapasaseguiraplicarãoaalteraçãosolicitadanasuapergunta"se tamanho da fonte: 18px {torná-la 22px} # Todo o texto com tamanho da fonte 18px será agora 22px;"

Clique em Editar → Encontrar & Substitua no menu ou pressione Ctrl H Outras opções Clique na caixa Pesquisar por e depois no botão de atributos Caixa de seleção tamanho da fonte, em seguida, o botão Formatar selecione 18 pt da caixa de rolagem na extrema direita Clique em Substituir por caixa, em seguida, botão Formatar e selecione 22 pt da caixa de rolagem na extrema direita

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 mudou para fs44

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

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

Conhecer o que mudou nos fornece um modelo para desenvolver uma abordagem em lote. É provável que seja possível gravar uma macro que faz isso ao abrir um documento ou desenvolver um script que faça as alterações conforme desejado.

    
por Elder Geek 01.04.2018 / 04:02
1

Existem algumas dicas sobre como isso pode ser feito na especificação de RTF.

Aqui está minha análise do problema.

Realizar isso usando a CLI, como você supõe, parece ser a abordagem mais simples, já que não vi nenhum aplicativo baseado em GUI que possa manipular esse tipo de conversão em lote. Parece que você pode simplesmente modificar o cabeçalho:

The header has the following 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.

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

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

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

Existem também opções de uma linha para substituir uma string 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 cada instância de fs36 por fs44 . O shell que você está usando também pode ter relação com a melhor maneira de escrever suas expressões. Dependendo da complexidade e do conteúdo de seus documentos, talvez seja melhor usar sed , perl ou grep ou talvez até uma combinação deles. Como isso se tornou uma questão de programação, é melhor encaminhá-lo para o link onde você encontre facilmente uma meia dúzia de abordagens diferentes, uma das quais é adequada às suas necessidades perfeitamente.

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' {} \; , conforme 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 por billtian , é uma excelente opção.

Para estar no lado seguro, você deve pré-processar os arquivos para garantir que quaisquer alterações que você faça não tenham conseqüências indesejadas. Por exemplo:

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

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

O texto acima exibirá as linhas contendo a string de busca fs36 para cada arquivo .rtf no diretório.

Editar:

A especificação mais recente pode ser obtida aqui. Eu não veja quaisquer alterações que possam impactar essa abordagem.

    
por Elder Geek 31.03.2018 / 16:49