Eliminacja 'edycyjnych 'sierot' polskojęzycznego tekstu w LibreOffice

Eliminacja 'edycyjnych 'sierot' polskojęzycznego tekstu w LibreOffice

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: