LibreOffice Writer: Replace Paragraph Breaks with Line Breaks (Selection-Only Macro)

type: note | domain: technology | topic: software | lang: en | pub: 2025-12-17

LibreOffice Writer has a classic trap: you want to turn "hard" paragraph breaks (Enter) into "soft" line breaks (Shift+Enter). You try Ctrl+H, regex, $, \n, and nothing behaves like you expect.

An extension can solve it, but that also means handing over control. A tiny macro is fully transparent, local, and auditable. That is the route below.

The problem

You have text where every line ends with a paragraph mark (¶). You want to keep the text, but replace each paragraph break with a manual line break (↵).

Typical use cases:

Why Ctrl+H does not reliably work

Writer's Find & Replace looks like it supports regex anchors and newline escapes, but the paragraph boundary is not a normal character you can safely "replace" in the UI. You can find positions, but replacements often do nothing, or they replace the wrong character (the last character of the line), depending on version and context.

If you need this to be predictable, use a macro.

Safe strategy: operate on a selection

Do not run a "replace all" on the entire document. Writer documents may contain headers, footers, frames, tables, and other text containers. If you convert paragraph boundaries there, you can merge things that should never merge.

Instead:

The macro

This macro converts paragraph breaks to soft line breaks, but only inside the current selection.

It works "backwards" (from the end to the start), so it does not skip paragraphs as it edits the text.

Sub ParagraphsToLineBreaks
    Dim oDoc As Object, oSel As Object, oRng As Object
    Dim oText As Object, oEnum As Object
    Dim aEnds() As Object
    Dim n As Long, i As Long
    Dim oPara As Object, c As Object

    oDoc = ThisComponent
    oSel = oDoc.getCurrentController().getSelection()

    If oSel.getCount() = 0 Then Exit Sub
    oRng = oSel.getByIndex(0)

    oText = oRng.getText()
    oEnum = oRng.createEnumeration()

    ' Collect paragraph ends inside the selection
    n = 0
    While oEnum.hasMoreElements()
        oPara = oEnum.nextElement()
        ReDim Preserve aEnds(n)
        aEnds(n) = oPara.End
        n = n + 1
    Wend

    ' Walk backwards: replace paragraph break with manual line break
    ' Skip the last end marker
    For i = n - 2 To 0 Step -1
        c = oText.createTextCursorByRange(aEnds(i))
        On Error Resume Next
        c.goRight(1, True)     ' select paragraph break ()
        If Err = 0 Then
            c.String = Chr(10) ' replace with manual line break ()
        End If
        Err = 0
        On Error GoTo 0
    Next i
End Sub

How to add the macro in LibreOffice

Usage checklist

What this does not do

That's it: no extension, no black box, just a small, readable macro.