Измените 2 или более документов LibreOffice, чтобы они имели одинаковый стиль / форматирование

14

Скажем, у меня есть каталог с около 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 как-то?

JohnDoea
источник
3
Это не будет легкой задачей, я думаю. Если они все структурированы одинаково, возможно, вы могли бы использовать какое-то хакерское решение с заменой текста в файлах .rtf из командной строки. Однако это очень сильно зависит от того, как выглядят RTF-файлы и насколько они похожи.
Себастьян Старк
Я нашел помощь в переполнении стека для целого нового макроса LibreOffice Writer, начинающегося сегодня с нуля. Нам больше не нужно знать все возможные размеры шрифта.
WinEunuuchs2Unix
В последний раз я попросил экспертов Stack Overflow опубликовать здесь ответ до
истечения
У вас, ребята, десятки тысяч очков репутации. Я скромно предлагаю вам рассмотреть возможность дать что-то вроде 500-750. Просто соображение. Просто просто.
JohnDoea

Ответы:

5

Используйте инструменты Libreoffice вместо CLI

Когда все, что у вас есть, это инструменты командной строки, все выглядит как проблема командной строки. Я решил написать этот ответ, используя макросы LibreOffice:

  1. Используйте цикл командной строки для обработки каждого документа Writer в «безглавой» среде.
  2. Запустите макрос для изменения .rtf(Rich Text Format) файла документа Writer.
  3. Макрос сохраняет файл и выходит
  4. Вернитесь к 1.

Создать тестовые данные

Создайте два или более файлов, содержащих:

richtext2.png

Создать скрипт, ~/Downloads/copy-rtf.shсодержащий:

cp ~/Documents/*.rtf ~/Downloads

Пометить как исполняемый файл, используя

chmod a+x ~/Downloads/copy-rtf.sh
  • Во время разработки и тестирования *.rtfфайлы макросов будут работать с~/Downloads каталогом.
  • Перед каждым типом теста cd ~/Downloadsи запуска./copy-rtf.sh
  • После того, как вывод завершен, они копируются обратно в директорию live.

Каталог загрузок используется потому что:

  • у каждого есть ~/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 Runtime Environment

Для запуска макросов вам нужно установить Java Runtime Environment (JRE). На веб-странице разработчика есть инструкции по загрузке и установке вручную.

Однако эти вопросы и ответы AU: /ubuntu//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 Q & A, и после первого шага добавления PPA появляется заставка с дополнительной информацией. Наиболее полезной является ссылка на настройку JRE 8 в системах Debian .

Третий этап установки JRE 8 требует от вас использования Tabи Enterпринятия лицензионного соглашения. Ваша машина остановится на несколько минут во время самой тяжелой части процедуры установки.

Теперь откройте LibreOffice и выберите Сервис -> Параметры -> LibreOffice -> Дополнительно и настройте этот экран:

LO JRE8 Advanced Setup.png

Нажмите на опции для:

  • Используйте среду выполнения Java
  • Корпорация Oracle 1.8.0_161
  • Включить запись макроса (эксперимент)
  • Нажмите ОК
  • Вам будет предложено перезагрузить, нажмите «Перезагрузить сейчас».

Макрос LibreOffice Writer

Макрос прочитает весь документ и:

  • изменить имя шрифта на Ubuntu.
  • Если заголовок 1, установите размер шрифта 28
  • иначе, если размер шрифта 18 установлен на 22
  • иначе установите размер шрифта на 12

Макрос сохранит документ и выйдет из Libreoffice Writer.

Выключить диалог

Сохраните файл, и появится этот диалог:

LO Writer отключить 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
WinEunuuchs2Unix
источник
2

Вот одноразовый подход с использованием Libre Office. Это не партия, но это может помочь вдохновить другие ответы.

Откройте файл RTF, который имеет шрифт Ubuntu, H1 на 28 пунктов, некоторые текст на 12 пунктов, а некоторые на 18 пунктов.

Вот пример:

тест RTF

Следующие шаги будут применять изменения, запрошенные в вашем вопросе "if font-size: 18px {make it 22px} # Весь текст с размером шрифта 18px теперь равен 22px;"

Нажмите «Правка» → «Найти и заменить» в меню или нажмите « CtrlHДругие параметры». Нажмите «Найти поле», затем кнопку «Атрибуты», установите флажок «Размер шрифта», затем кнопку «Формат», выберите 18 пт из поля прокрутки в правом нижнем углу. поле прокрутки справа

FindNreplace

Нажмите Заменить все

применимая строка, которая изменилась, была:

\ par \ pard \ plain \ s0 \ ql \ widctlpar \ hyphpar0 \ ltrpar \ cf1 \ kerning1 \ dbch \ af7 \ langfe1081 \ dbch \ af7 \ afs24 \ alang1081 \ loch \ f3 \ fs24 \ lang1033 \ ql \ widctlpar \ hypp \ hphp {\ rtlch \ ltrch \ loch \ fs36 \ loch \ f6

FS36 изменился на FS44

единственное другое поле, которое изменилось, было полем revtime, которое вы можете или не хотите обновлять:

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

Знание того, что изменилось, дает нам модель для разработки пакетного подхода. Вероятно, можно записать макрос, который делает это при открытии документа, или разработать скрипт, который вносит изменения по желанию.

Старейшина Гик
источник
1

Есть некоторые отличные подсказки о том, как это можно сделать в спецификации RTF.

Вот мой анализ проблемы.

Достигнуть этого с помощью 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.

Лично после просмотра этой информации мне приходит в голову, что все, что вы пытаетесь сделать, выглядит так, как будто оно поддерживается в заголовке, от выбора шрифта до стиля.

Существуют инструменты, которые помогут вам в этом процессе, и я обрисую их ниже, поскольку у меня нет примера стиля документа, который у вас есть, или стиля документа, который вы хотите, и более общий ответ, вероятно, будет более полезен для сообщества, чем один нацеленный на вашу конкретную ситуацию.

grepбудет полезно проанализировать существующие файлы для конвертации и образец целевого стиля для существующих <fonttbl>и
<stylesheet>выбранных. Определив, что у вас есть на самом деле, вы сможете написать простой скрипт, sedкоторый заменит существующее содержимое заголовка желаемым содержимым заголовка. Существует множество примеров того, как перебирать файлы в скрипте bash ( пример ) и как использовать sed ( пример) ), свободно доступный, если вы не знакомы с этими концепциями.

Есть также одна строка для замены строки в файле. Некоторые из них могут работать лучше, чем другие, в зависимости от вашего варианта использования. В зависимости от содержания файлов может или не может иметь смысл простой замены каждый экземпляр fs36с fs44какой оболочки используется также может иметь отношение , как лучше писать свои выражения. В зависимости от сложности и содержания документов может быть лучше использовать sed, perlили , grepили , возможно , даже их сочетание. Поскольку это стало вопросом программирования, лучше всего направить вас на /programming/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

Выше будут отображаться строки, содержащие строку поиска fs36 для каждого файла .rtf в каталоге.

Редактировать:

Самую последнюю спецификацию можно получить здесь. Я не вижу каких-либо изменений, которые должны повлиять на этот подход.

Старейшина Гик
источник
1
Здравствуйте, я благодарю вас за первое описание решения CLI. Пожалуйста, поделитесь примером кода для того, как вы будете менять rtfзаголовок и текст, sedчтобы ответ был централизованным sed.
JohnDoea
@JohnDoea Всегда готов помочь. Я надеюсь, что и вы, и будущие пользователи найдут это полезным.
Старейшина Гик