LibreOffice Writer: Replace Paragraph Breaks with Line Breaks (Selection-Only Macro)
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:
- Reflowing pasted text that came in as one paragraph per line.
- Keeping line structure while avoiding paragraph-level formatting side effects.
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:
- Select only the body text you want to convert.
- Optional, copy it into a new document if you want maximum safety.
- Run the macro on the selection.
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
- Tools -> Macros -> Organize Macros -> LibreOffice Basic
- Under "My Macros", pick your library (or create one).
- Open an existing module (or create one), paste the macro, save.
- Assign it to a toolbar button or shortcut if you like.
Usage checklist
- Turn on non-printing characters (Ctrl+F10) to verify:
- Paragraph breaks: ¶
- Manual line breaks: ↵
- Always test on a copy first.
- If the selection includes tables/frames, keep the selection tighter.
What this does not do
- It does not "re-wrap" text. It only swaps the break type.
- It intentionally avoids touching headers/footers by working on selection only.
That's it: no extension, no black box, just a small, readable macro.