Zmień 2 lub więcej dokumentów LibreOffice, aby mieć dokładnie takie same style / formatowanie

14

Powiedzmy, że mam katalog z około 100 .rtfplikami, które edytuję za pomocą LibreOffice Writer.

Chciałbym, aby wszystkie pliki w tym katalogu miały dokładnie takie same podstawowe wytyczne dotyczące stylów tekstu sformatowanego, na przykład:

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

I tak dalej ... Zasadniczo chcę zmienić wszystkie pliki jednocześnie. Czy taka „stylizacja” jest możliwa?

Może jest to możliwe dzięki CLI?

JohnDoea
źródło
3
Myślę, że nie będzie to łatwe zadanie. Jeśli wszystkie są ustrukturyzowane w ten sam sposób, być może użyłbyś jakiegoś hackiego rozwiązania, zastępując tekst w plikach .rtf z wiersza poleceń. Jednak to bardzo zależy od tego, jak wyglądają pliki RTF i jak są podobne.
Sebastian Stark
Znalazłem pomoc w przepełnieniu stosu dla całego nowego makra LibreOffice Writer, zaczynając od zera dziś wieczorem. Nie musimy już znać każdego możliwego rozmiaru czcionki.
WinEunuuchs2Unix,
W ostatnim wysiłku, poprosiłem ekspertów Stack Overflow o opublikowanie tutaj odpowiedzi przed końcem okresu karencji: stackoverflow.com/questions/49640951/…
WinEunuuchs2Unix 6'18
Macie dziesiątki tysięcy punktów reputacji. Pokornie sugeruję rozważenie podania czegoś takiego jak 500-750. Tylko uwaga. Po prostu po prostu.
JohnDoea,

Odpowiedzi:

5

Użyj narzędzi Libreoffice zamiast CLI

Gdy wszystko, co masz, to narzędzia wiersza polecenia, wszystko wygląda jak problem z wierszem poleceń. Postanowiłem napisać tę odpowiedź za pomocą makr LibreOffice:

  1. Użyj pętli wiersza poleceń, aby przetworzyć każdy dokument Writer w środowisku „bezgłowym”.
  2. Uruchom makro, aby zmienić .rtfplik dokumentu Writer (Rich Text Format).
  3. Makro zapisuje plik i kończy działanie
  4. Powróć do 1.

Utwórz dane testowe

Utwórz dwa lub więcej plików zawierających:

richtext2.png

Utwórz skrypt ~/Downloads/copy-rtf.shzawierający:

cp ~/Documents/*.rtf ~/Downloads

Oznacz jako wykonywalny za pomocą

chmod a+x ~/Downloads/copy-rtf.sh
  • Podczas programowania i testowania *.rtfpliki modyfikujące makra będą działały w ~/Downloadskatalogu.
  • Przed każdym typem testu cd ~/Downloadsi uruchom./copy-rtf.sh
  • Po uzyskaniu idealnego wyniku są one kopiowane z powrotem do katalogu na żywo.

Katalog Pobrane jest używany, ponieważ:

  • każdy ma ~/Downloads
  • jest dodawany do regularnie i okresowo ręcznie opróżniany
  • jest bardziej trwały niż /tmp/katalog, który może nie utrzymywać się po ponownym uruchomieniu.

Uruchom makro w środowisku bezgłowym

Korzystając z odpowiedzi Stack Exchange, wywołaj Libreoffice Writer z wiersza poleceń i przekaż mu globalną nazwę makra, aby wykonać:

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

Powyższa odpowiedź może nie działać, więc można wypróbować inną metodę :

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

Zainstaluj środowisko Java Runtime Environment

Aby uruchomić makra, musisz zainstalować środowisko Java Runtime Environment (JRE). Strona internetowa programisty zawiera instrukcje dotyczące ręcznego pobierania i instalowania.

Jednak te pytania i odpowiedzi dotyczące AU: /ubuntu//a/728153/307523 sugerują, że jest to tak proste, jak:

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

Wypróbowałem metodę AU Q&A i po pierwszym kroku dodawania PPA pojawia się ekran powitalny z dodatkowymi informacjami. Najbardziej pomocny jest link do konfiguracji JRE 8 w systemach Debian .

Trzeci krok instalacji środowiska JRE 8 wymaga użycia Tabi Enterzaakceptowania umowy licencyjnej. Podczas najcięższej części procedury instalacji urządzenie zatrzyma się na kilka minut.

Teraz otwórz LibreOffice i wybierz Narzędzia -> Opcje -> LibreOffice -> Zaawansowane i skonfiguruj ten ekran:

LO JRE8 Advanced Setup.png

Kliknij opcje dla:

  • Użyj środowiska wykonawczego Java
  • Oracle Corporation 1.8.0_161
  • Włącz rejestrowanie makr (eksperymentalne)
  • Kliknij OK
  • Zostaniesz poproszony o ponowne uruchomienie, kliknij „Uruchom ponownie teraz”.

LibreOffice Writer Macro

Makro przeczyta cały dokument i:

  • zmień nazwę czcionki na Ubuntu.
  • Jeśli nagłówek 1 ustaw rozmiar czcionki na 28
  • w przeciwnym razie, jeśli rozmiar czcionki to 18, ustaw 22
  • w innym przypadku ustaw rozmiar czcionki na 12

Makro zapisze dokument i zamknie Libreoffice Writer.

Wyłącz okno dialogowe

Wykonaj zapis pliku, a pojawi się następujące okno dialogowe:

Program LO Writer wyłącza okno dialogowe RTF.png

Wyłącz tę wiadomość, jak pokazuje na ekranie. Makro może nie działać poprawnie, jeśli ta opcja jest włączona.

Zawartość makr

Spędziłem kilka dni próbując nagrać makro za pomocą „Narzędzia” -> „Makra” -> „Nagraj makro” -> „Podstawowy”. Na początku wydawało się to obiecujące, ale zarejestrowane makro nie zachowywało się niekonsekwentnie i musiało zostać porzucone, aby napisać ręcznie makro podstawowe. Znaleziona pomoc w przepełnieniu stosu dla eksperta, który pomoże mi w podstawowym podstawowym kodowaniu . Oto wynik:

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
źródło
2

Oto jednorazowe podejście z użyciem Libre Office. To nie jest partia, ale może zainspirować inne odpowiedzi.

Otwórz plik RTF z czcionką Ubuntu, H1 przy 28 pt, trochę tekstu przy 12pt, a niektóre przy 18 pt.

Oto przykład:

test rtf

W poniższych krokach zastosowana zostanie zmiana wymagana w pytaniu „if-font: size: 18px {make it 22px} # Cały tekst o rozmiarze czcionki 18px ma teraz 22px;”

Kliknij Edycja → Znajdź i zamień w menu lub wciśnij CtrlHInne opcje Kliknij Wyszukaj pole, a następnie przycisk atrybuty Pole wyboru Rozmiar czcionki, a następnie przycisk Formatuj wybierz 18 pkt z pola przewijania po prawej stronie Kliknij Zamień na pole, a następnie przycisk Formatuj i wybierz 22 pkt z pole przewijania po prawej stronie

FindNreplace

Kliknij Zamień wszystko

obowiązująca zmieniona linia to:

\ 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 zmieniono na fs44

jedynym innym polem, które się zmieniło, było pole revtime, które możesz lub nie chcesz aktualizować:

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

Wiedza o tym, co się zmieniło, daje nam model do opracowania podejścia wsadowego. Prawdopodobnie możliwe jest zarejestrowanie makra, które robi to po otwarciu dokumentu lub opracowanie skryptu, który wprowadza zmiany zgodnie z potrzebami.

Starszy Geek
źródło
1

Istnieje kilka świetnych wskazówek, jak można to zrobić w specyfikacji RTF.

Oto moja analiza problemu.

Osiągnięcie tego przy użyciu interfejsu CLI, jak się domyślacie, wydaje się być najprostszym podejściem, ponieważ nie widziałem żadnych aplikacji opartych na GUI, które mogłyby obsługiwać tego rodzaju konwersję wsadową. Wygląda na to, że możesz po prostu zmodyfikować nagłówek:

Nagłówek ma następującą składnię:

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

Osobiście po przejrzeniu tych informacji przychodzi mi do głowy, że wszystko, co próbujesz zrobić, wygląda tak, jakby było obsługiwane w nagłówku, od wyboru czcionki do stylu.

Dostępne są narzędzia, które pomogą ci w tym procesie, które opiszę poniżej, ponieważ nie mam przykładowego stylu dokumentu ani stylu dokumentu, którego chciałbyś, a bardziej ogólna odpowiedź będzie prawdopodobnie bardziej przydatna dla społeczności niż jeden ukierunkowany na twoją dokładną sytuację.

grepprzyda się do przeanalizowania istniejących plików do konwersji i próbki stylu docelowego dla istniejących <fonttbl>i
<stylesheet>selekcji. Po ustaleniu, co faktycznie masz, powinieneś być w stanie napisać prosty skrypt wykorzystujący seddo zastąpienia istniejącej zawartości nagłówka żądaną zawartością nagłówka. Istnieje wiele przykładów, jak iterować pliki w skrypcie bash ( przykład ) i jak korzystać z sed ( przykład ) swobodnie dostępnego, jeśli nie znasz tych pojęć.

Istnieje również jedna opcja wiersza zastępująca ciąg w pliku. Niektóre mogą działać lepiej niż inne w zależności od przypadku użycia. W zależności od zawartości plików może lub nie może mieć sens prostych zastąpić każde wystąpienie fs36z fs44których powłoka używasz może również mieć wpływ na jak najlepiej napisać wyrażeń. W zależności od stopnia złożoności i zawartości dokumentów może być lepiej wyłączyć za pomocą sed, perllub grepczy może nawet ich kombinacją. Ponieważ stało się to pytaniem programistycznym, najlepiej odnieść cię do /programming/15402770/how-to-grep-and-replace, gdzie łatwo znajdziesz 1/2 tuzina różnych podejść, jedno z który prawdopodobnie idealnie spełni twoje potrzeby.

Na przykład, jeśli chcesz zastosować te zmiany w całym systemie,

find /path/to/files -type f -exec sed -i 's/oldstring/newstring/g' {} \;jak zapewnia rezizter Jest prawdopodobnie najlepszy.

Jeśli chcesz zawrzeć swoje zmiany w jednym katalogu,

grep -rl matchstring somedir/ | xargs sed -i 's/fs36/fs44/g'jak zapewnia billtian jest doskonałym wyborem.

Aby zachować bezpieczeństwo, należy wstępnie przetworzyć pliki, aby upewnić się, że wszelkie wprowadzone zmiany nie będą miały niezamierzonych konsekwencji. Na przykład:

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

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

Powyżej wyświetli wiersze zawierające szukany ciąg fs36 dla każdego pliku .rtf w katalogu.

Edytować:

Najnowszą specyfikację można uzyskać tutaj. Nie widzę żadnych zmian, które powinny wpłynąć na to podejście.

Starszy Geek
źródło
1
Witam, dziękuję za pierwsze opisanie rozwiązania CLI. Podaj przykładowy kod, w którym zmienisz rtfnagłówek i tekst, sedaby odpowiedź była scentralizowana sed.
JohnDoea
@JohnDoea Zawsze chętny do pomocy. Mam nadzieję, że zarówno Tobie, jak i przyszłym użytkownikom okaże się przydatny.
Starszy Geek