W LibreOffice można za pomocą jednego kroku wyeliminować wszystkie tzw. 'sieroty' a więc zabezpieczyć wszystkie wystąpienia pojedynczych znaków alfabetycznych przed łamaniem na nich linii akapitu. W pracach edytorskich tekst, szczególnie ten justowany, fatalnie wygląda, jeśli na końcu linii w akapicie figuruje pojedynczy znak.
Można to wyeliminować zamieniając w całym tekście za pomocą wyrażeń regularnych wszystkie sekwencje znaków [spacja][pojedynczy znak][spacja] na: [spacja][pojedynczy znak][niełamliwa spacja]
Na potrzeby naszego wydawnictwa przygotowaliśmy odpowiednie makro dla aplikacji LibreOffice, która realizuje to zadanie.
Co robi nasze makro?
- oDoc.getText().createEnumeration() iteruje po głównym tekście dokumentu. Dzięki temu pomijamy przypisy itd. (przypisy są innymi obiektami w dokumencie).
- Dla każdego akapitu pobieramy jego tekst (getString()), wykonujemy zamiany za pomocą wbudowanej funkcji Replace i zapisujemy z powrotem (setString).
- Użycie Chr(160) wstawia NIEROZDZIELAJĄCĄ SPACJĘ (NBSP), co zapobiega pozostawianiu jednowyrazowych „sierot” na końcu wiersza.
Funkcja Replace działa globalnie na całym ciągu, więc zamiana wystąpi dla wszystkich wystąpień tej sekwencji w akapicie i tym samym działa nadmiarowo, ale dzięki temu zabezpieczenie przed wiszącymi ''sierotami" na końcu łamanego wiersza obejmuje cały dokument i nie ma potrzeby ręcznej korekty tekstu końcowego.
Poniżej naszego makra, który kod makra, który realizuje taką funkcjonalność. Wystarczy go zainstalować w aplikacji LibreOffice.
Sub UsunSieroty_TylkoGlowneAkapity
Dim oDoc As Object
Dim oEnum As Object
Dim oPara As Object
Dim s As String
Dim newS As String
Dim lettersLower As Variant
Dim lettersUpper As Variant
Dim i As Integer
oDoc = ThisComponent
If IsNull(oDoc) Then
MsgBox "Brak otwartego dokumentu.", 16, "Błąd"
Exit Sub
End If
' Lista jednopoznaniowych słów/sierot (małe i duże)
lettersLower = Array("a", "i", "o", "u", "w", "z")
ReDim lettersUpper(UBound(lettersLower))
For i = 0 To UBound(lettersLower)
lettersUpper(i) = UCase(lettersLower(i))
Next i
' Enumerator po elementach głównego tekstu dokumentu
oEnum = oDoc.getText().createEnumeration()
Dim changedCount As Long
changedCount = 0
While oEnum.hasMoreElements()
oPara = oEnum.nextElement()
' Tylko akapity (główny tekst). To zminimalizuje zmianę w nagłówkach, przypisach itp.
If oPara.supportsService("com.sun.star.text.Paragraph") Then
s = oPara.getString()
newS = s
' Zamiana: " spacja + litera + spacja " -> " spacja + litera + NBSP"
For i = 0 To UBound(lettersLower)
newS = Replace(newS, " " & lettersLower(i) & " ", " " & lettersLower(i) & Chr(160))
newS = Replace(newS, " " & lettersUpper(i) & " ", " " & lettersUpper(i) & Chr(160))
Next i
' Jeśli zaszła zmiana, ustaw nowy tekst akapitu
If newS <> s Then
oPara.setString(newS)
changedCount = changedCount + 1
End If
End If
Wend
MsgBox "Zmieniono sieroty w " & changedCount & " akapitach głównego tekstu.", 64, "Gotowe"
End Sub
P.S.
Wcześniej opublikowaliśmy instrukcje jak sobie z tym problemem radzić w innych środowiskach edycyjnych w tym w naszym miesięczniku:
- To samo jak powyżej w LibreOffice ale bez makra:
https://e-kreatywni.eu/index.php/tekst-responsywny-w-dokumentach-cyfrowych-likwidacja-sierot-w-libre-office - Rozwiązanie dla MS OFFICE 365:
https://e-kreatywni.eu/index.php/responsywna-poprawnosc-formatowania-akapitow-w-sieci-ciag-dalszy - Automatyzacja dla responsywnych akapitów w naszym miesięczniku:
https://e-kreatywni.eu/index.php/nasze-nowe-narzedzie-likwidacja-sierot-w-responsywnym-tekscie
