web-dev-qa-db-ja.com

2つ以上のLibreOfficeドキュメントを変更して、まったく同じスタイル/フォーマットを使用する

LibreOffice Writerで編集する約100個の.rtfファイルがあるディレクトリがあるとします。

そのディレクトリ内のすべてのファイルに、まったく同じ基本的なリッチテキストスタイリングディレクティブが含まれることを望みます。たとえば、

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

など...それで、基本的に、すべてのファイルを一度に変更したいです。そのような「一括スタイリング」は可能ですか?

たぶんCLIで可能ですか?

14
JohnDoea

CLIの代わりにLibreofficeツールを使用する

持っているのがコマンドラインツールだけであれば、すべてがコマンドラインの問題のように見えます。 LibreOfficeマクロを使用してこの答えを書くことにしました。

  1. コマンドラインループを使用して、「ヘッドレス」環境ですべてのWriterドキュメントを処理します。
  2. マクロを実行して、.rtf(リッチテキスト形式)ライタードキュメントファイルを変更します。
  3. マクロはファイルを保存して終了します
  4. 1にループバックします。

テストデータを作成する

以下を含む2つ以上のファイルを作成します。

richtext2.png

以下を含むスクリプト~/Downloads/copy-rtf.shを作成します。

cp ~/Documents/*.rtf ~/Downloads

を使用して実行可能としてマークする

chmod a+x ~/Downloads/copy-rtf.sh
  • 開発およびテスト中に、*.rtfファイルを変更するマクロは~/Downloadsディレクトリに対して実行されます。
  • 各テストの前にcd ~/Downloadsを入力し、./copy-rtf.shを実行します
  • 出力が完全になった後、それらはライブディレクトリにコピーされます。

次の理由で、ダウンロードディレクトリが使用されます。

  • 誰もが~/Downloadsを持っています
  • 定期的に追加され、定期的に手動で空にされます
  • /tmp/ディレクトリよりも永続的であり、再起動しても保持されない場合があります。

ヘッドレス環境でマクロを実行する

これを使用して Stack Exchange answer コマンドラインからLibreoffice Writerを呼び出し、実行するグ​​ローバルマクロ名を渡します。

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

上記の答えはうまくいかないかもしれません 別の方法 を試すことができます:

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

Java Runtime Environmentをインストールします

マクロを実行するには、Java Runtime Environment(JRE)がインストールされている必要があります。開発者のWebページには、手動でダウンロードおよびインストールするための instructions があります。

ただし、このAU Q&A: https://askubuntu.com/a/728153/30752 は、次のようにシンプルであることを示唆しています。

Sudo apt-add-repository ppa:webupd8team/Java
Sudo apt-get update
Sudo apt-get install Oracle-Java8-installer Oracle-Java8-set-default

AU Q&Aメソッドを試しましたが、PPAを追加する最初のステップの後、追加情報を含むスプラッシュ画面が表示されます。最も役立つのは DebianシステムでJRE 8をセットアップする へのリンクです。

JRE 8をインストールする3番目の手順では、使用する必要があります Tab そして Enter ライセンス契約に同意します。インストールルーチンの最も重い部分の間、マシンは数分間停止します。

LibreOfficeを開き、Tools->Options->LibreOffice->Advancedこの画面のセットアップ:

LO JRE8 Advanced Setup.png

次のオプションをクリックします。

  • Javaランタイム環境を使用する
  • Oracle Corporation 1.8.0_161
  • マクロ記録を有効にする(実験的)
  • OKをクリック
  • 再起動するように求められたら、[今すぐ再起動]をクリックします。

LibreOffice Writerマクロ

マクロはドキュメント全体を読み通し、次のことを行います。

  • フォント名をUbuntuに変更します。
  • 見出し1の場合、フォントサイズを28に設定します
  • それ以外の場合、フォントサイズが18で22に設定されている場合
  • それ以外の場合は、フォントサイズを12に設定します

マクロはドキュメントを保存し、Libreoffice Writerを終了します。

ダイアログをオフにする

ファイルを保存すると、このダイアログが表示されます:

LO Writer turn off RTF dialog.png

画面に表示されるこのメッセージをオフにします。このオプションがオンの場合、マクロは正しく実行されない場合があります。

マクロの内容

「ツール」->「マクロ」->「マクロの記録」->「基本」を使用してマクロを記録しようと数日費やしました。最初は有望に思えましたが、記録されたマクロは一貫性のない動作をし、手書きの基本マクロのために放棄されなければなりませんでした。 Stack Overflowの専門家が、基本的な 基本的なコーディング を手伝ってくれるヘルプを見つけました。結果は次のとおりです。

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
5

Libre Officeを使用した1回限りのアプローチを次に示します。バッチではありませんが、他の答えを引き出すのに役立つ場合があります。

Ubuntuフォント、28ポイントのH1、12ポイントのテキストと18ポイントのテキストを含むrtfファイルを開きます。

以下に例を示します。

test rtf

次の手順は、「if font-size:18px {make it 22px}#font-size 18pxのすべてのテキストが22pxになった」という質問で要求された変更を適用します。

メニューの[編集]→[検索と置換]をクリックするか、ヒット CtrlH その他のオプション[検索ボックス]、[属性]ボタン、[フォントサイズ]チェックボックス、[フォーマット]ボタンをクリックして、右端のスクロールボックスから18 ptを選択します。

FindNreplace

すべて置換をクリック

変更された該当する行は次のとおりです。

\ 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

fs36はfs44に変更されました

変更された他のフィールドは、更新する場合としない場合があるrevtimeフィールドのみでした。

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

変更点を知ることで、バッチアプローチを開発するためのモデルが得られます。文書を開いたときにこれを行うマクロを記録したり、必要に応じて変更を加えるスクリプトを開発したりすることが可能です。

2
Elder Geek

RTF仕様 でこれをどのように進めるかについて、いくつかの大きな手がかりがあります。

ここに私の問題の分析があります。

この種のバッチ変換を処理できるGUIベースのアプリケーションを見たことがないので、CLIを使用してこれを実現するのが最も簡単な方法のように思えます。ヘッダーを簡単に変更できるようです:

ヘッダーの構文は次のとおりです。

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

個人的に、この情報を確認すると、フォントの選択から style。 に至るまで、ヘッダーでサポートされているように見えることはすべてあるように見えます。

このプロセスを支援するために利用できるツールがあり、以下に概要を説明します私はあなたが持っている文書スタイルの例もあなたが望む文書スタイルもありませんそして、より一般的な答えは、あなたの正確な状況をターゲットにしたものよりも、コミュニティにとってより役立つでしょう。

grepは、変換する既存のファイルと既存の<fonttbl>のターゲットスタイルのサンプルを解析するのに役立ちます。
<stylesheet>選択。実際に何を持っているかを確認したら、sedを使用して既存のヘッダーコンテンツを目的のヘッダーコンテンツに置き換える簡単なスクリプトを作成できるはずです。これらの概念に慣れていない場合は、bashスクリプトでファイルを反復処理する方法の例( example )とsedを利用する方法( example )の多数の例があります。

ファイル内の文字列を置き換える1行のオプションもあります。ユースケースに応じて、他のものよりもうまく機能するものもあります。ファイルの内容に応じて、fs36のすべてのインスタンスをfs44に単純に置き換えるのが理にかなっているかもしれません。文書の複雑さと内容に応じて、sedPerl、またはgrep、あるいはそれらの組み合わせを使用した方がよい場合があります。これがプログラミングの質問になっているので、あなたを参照するのが最善です https://stackoverflow.com/questions/15402770/how-to-grep-and-replace 簡単に1/2ダースの異なるアプローチ。そのうちの1つは、ニーズに完全に適合する可能性があります。

たとえば、これらの変更をシステム全体に適用する場合、

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;提供 rezizter おそらく最適です。

単一のディレクトリへの変更を含める場合は、

_ billtian が提供するgrep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'asは優れた選択肢です。

安全のために、ファイルを前処理して、行った変更が意図しない結果にならないようにする必要があります。例えば:

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

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

上記は、ディレクトリ内の各.rtfファイルの検索文字列fs36を含む行を表示します。

編集:

最新の仕様を入手できます こちら このアプローチに影響を与えるような変更は見当たりません。

1
Elder Geek