将 2 个或更多 LibreOffice 文档更改为具有完全相同的样式/格式

将 2 个或更多 LibreOffice 文档更改为具有完全相同的样式/格式

假设我有一个目录,其中包含大约 100 个.rtf使用 LibreOffice Writer 编辑的文件。

我希望该目录中的所有文件都具有完全相同的基本富文本样式指令,例如:

* 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 来实现?

答案1

使用 LibreOffice 工具而不是命令行

当您只有命令行工具时,一切看起来都像是命令行问题。我决定使用 LibreOffice 宏来编写此答案:

  1. 使用命令行循环在“无头”环境中处理每个 Writer 文档。
  2. 运行宏来更改.rtf(富文本格式)Writer 文档文件。
  3. 宏保存文件并退出
  4. 循环回到 1。

创建测试数据

创建两个或多个包含以下内容的文件:

丰富文本2.png

创建~/Downloads/copy-rtf.sh包含以下内容的脚本:

cp ~/Documents/*.rtf ~/Downloads

使用标记为可执行文件

chmod a+x ~/Downloads/copy-rtf.sh
  • 在开发和测试期间,修改文件的宏将针对目录*.rtf运行。~/Downloads
  • 每次测试类型cd ~/Downloads和运行之前./copy-rtf.sh
  • 输出完美后,它们被复制回实时目录。

使用该Downloads目录是因为:

  • 每个人都有~/Downloads
  • 它会定期添加并定期手动清空
  • 它比/tmp/目录更永久,目录在重启后可能无法继续存在。

在无头环境中运行宏

使用这个Stack Exchange 答案,从命令行运行 Libreoffice Writer 并传递一个要执行的全局宏名:

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

如果上述方法不起作用,另一种方法可以尝试:

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

安装Java运行环境

要运行宏,您需要安装 Java 运行时环境 (JRE)。开发人员的网页有指示用于手动下载和安装。

然而,这个 AU 问答:https://askubuntu.com/a/728153/307523建议它很简单:

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

我尝试了 AU 问答方法,在添加 PPA 的第一步之后,会出现一个带有附加信息的启动画面。最有帮助的是在 Debian 系统上设置 JRE 8

安装 JRE 8 的第三步要求您使用TabEnter接受许可协议。在安装程序最繁重的部分,您的机器将暂停几分钟。

现在打开 LibreOffice 并选择工具->选项->自由办公室->先进的并设置此屏幕:

LO JRE8 高级设置.png

单击以下选项:

  • 使用 Java 运行时环境
  • 甲骨文公司 1.8.0_161
  • 启用宏录制(实验性)
  • 单击“确定”
  • 系统将要求您重新启动,请单击“立即重新启动”。

LibreOffice Writer 宏

该宏将读取整个文档并:

  • 将字体名称更改为 Ubuntu。
  • 如果标题 1 设置字体大小为 28
  • 否则,如果字体大小为 18,则设置为 22
  • 否则将字体大小设置为 12

该宏将保存文档并退出 LibreOffice Writer。

关闭对话

保存文件后会出现以下对话框:

LO Writer 关闭 RTF 对话框.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

答案2

这是使用 Libre Office 的一次性方法。它不是批处理,但它可能有助于启发其他答案。

打开一个具有 Ubuntu 字体的 rtf 文件,H1 为 28 pt,一些文本为 12pt,一些文本为 18 pt。

以下是一个例子:

测试 rtf

以下步骤将应用您在问题中请求的更改“如果字体大小:18px {使其成为22px} # 所有字体大小为18px的文本现在都是22px;”

单击菜单上的编辑→查找和替换,或点击CtrlH其他选项单击搜索框,然后单击属性按钮字体大小复选框,然后单击格式按钮从最右侧的滚动框中选择 18 pt 单击替换为框,然后单击格式按钮并从最右侧的滚动框中选择 22 pt

查找替换

单击“全部替换”

适用的改变是:

\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}

了解更改的内容为我们提供了开发批处理方法的模型。有可能录制一个在打开文档时执行此操作的宏,或者开发一个根据需要进行更改的脚本。

答案3

关于如何做到这一点,有一些很好的线索RTF 规范。

以下是我对这个问题的分析。

正如您所猜测的那样,使用 CLI 完成此操作似乎是最简单的方法,因为我还没有看到任何基于 GUI 的应用程序可以处理这种批量转换。看来您只需修改标题即可:

标头具有以下语法:

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

就我个人而言,在审查这些信息时,我发现你试图做的一切看起来都得到了标题的支持,从字体选择到风格。

有一些工具可以帮助您完成此过程,我将在下面概述我没有您拥有的文档样式的示例,也没有您想要的文档样式而一个更通用的答案可能比针对您具体情况的答案对社区更有用。

grep<fonttbl>将有助于解析要转换的现有文件以及现有和选择的目标样式示例
<stylesheet>。确定您实际拥有的内容后,您应该能够编写一个简单的脚本,利用该脚本将sed现有标题内容替换为所需的标题内容。有许多关于如何在 bash 脚本中迭代文件的示例(例子) 以及如何利用 sed (例子) 如果您不熟悉这些概念,可以免费获取。

还有一些单行选项可以替换文件中的字符串。根据您的使用情况,有些选项可能比其他选项更好。根据文件的内容,简单地用 替换每个实例可能有意义,也可能没有意义。您使用的fs36shellfs44也可能与如何最好地编写表达式有关。根据文档的复杂性和内容,您最好使用sedperl或 ,grep或者甚至两者的组合。由于这已成为一个编程问题,最好参考https://stackoverflow.com/questions/15402770/how-to-grep-and-replace您可以轻松找到六种不同的方法,其中一种很可能完全适合您的需要。

例如,如果您希望在系统范围内应用这些更改,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;提供雷齐茨特可能是最好的。

如果您希望将更改包含在单个目录中,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'提供比尔蒂安是一个很好的选择。

为了安全起见,您应该对文件进行预处理,以确保所做的任何更改不会产生意外后果。例如:

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

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

以上命令将显示目录中每个 .rtf 文件包含搜索字符串 fs36 的行。

编辑:

可以获得最新的规范这里。我没有看到任何会影响这种方法的变化。

相关内容