Libre Office

Zeilenumbruch in Makro ersetzen

WRITER hat alles, was Sie von einer modernen, voll ausgestatteten Textverarbeitung erwarten.
Antworten
Jörg
! Supporter - Spende !
Beiträge: 36
Registriert: So 11. Jul 2021, 13:33

Zeilenumbruch in Makro ersetzen

Beitrag von Jörg » Sa 6. Jun 2026, 00:56

Hallo,

in LO 26.2 unter Windows öffne ich mit Writer eine .txt-Datei, deren Zeilen alle mit einem harten Zeilenumbruch (<CR><LF>) enden. Diese Umbrüche möchte ich gerne durch ein Leerzeichen ersetzen und am Ende die mit einem Proportionalfont neu umbrochene Datei im .odt-Format speichern. Das lässt sich eigentlich leicht mit Bordmitteln machen (Suchen/Ersetzen mit RegEx $).
ABER:
An den "wahren" Absätzen möchte ich die Umbrüche erhalten, und dann wird's bei längeren Dateien schon etwas mühsam, weil ich bei jeder Zeile entsprechend klicken muss. Außerdem will ich auch Trennungen am Zeilenende aufheben, und spätestens dann kommt der Wunsch nach einem Makro auf.

Wegen der harten Zeilenumbrüche behandelt Writer jede einzelne Zeile als Abschnitt (paragraph). Somit gehe ich mit folgender Schleife durch den Text:

Code: Alles auswählen

sub Test
  dim c           as String
  dim line        as String
  dim document    as Object
  dim oTextCursor as Object
  dim count	  as Integer

  document= ThisComponent.CurrentController.Frame
  oTextCursor= ThisComponent.Text.createTextCursor()
  oTextCursor.gotoStart(false)

  Do
    oTextCursor.gotoEndOfParagraph(true)
    line= oTextCursor.getString()
    c= Right(line, 1) 'Hier hatte ich ein <LF> erwartet.
'    Print Instr(line, chr(13)) & " " & Instr(line, chr(10)) & " " & c  ' War immer 0 0 und letztes Zeichen der Zeile.
'   if (condition) then
'     Replace line break by Blank.
'   end if
    Print line
  Loop While oTextCursor.gotoNextParagraph(false)

  MsgBox "Count of lines: " & count, 0, "Result"
end sub
In "line" finde ich aber nur die sichtbaren Zeichen der Zeile, und die Control Codes am Ende sind weg. Komme ich an die noch irgendwie ran, um sie zu ersetzen, oder muss ich ganz anders vorgehen?

Wanderer
* LO-Experte *
Beiträge: 915
Registriert: Di 11. Feb 2014, 20:03
Wohnort: Berlin

Re: Zeilenumbruch in Makro ersetzen

Beitrag von Wanderer » So 7. Jun 2026, 17:48

Ich habe das vor Jahren mal 3-Stufig mit einem (erweiterten) aufgezeichneten Makro gelöst.
  • Zuerst die zu erhaltenden Zeilenumbrüche markieren (mit ewas , was sonst nicht vorkommt), also hier all "leeren" Absätze ^$ mit @@@@
  • dann alle Absatzmarken entfernen, wodurch ein einzelner Absatz entsteht. (Vorsicht hier gab es wohl irgendeine Obergrenze, was die Länge angeht ).
  • Die oben gesetzten Marke. @@@@ wieder durch Absatzmarken ersetzen
Ich schau mal, ob ich das Teil noch finde. Ich habe das lange nicht mehr gebraucht...
LO 6.0.7 (32Bit) Win8.1 Pro 32 Bit/ LO 6.3.2 Win10 64Bit / LO 6.0.7 Win7 Pro 64 Bit

Jörg
! Supporter - Spende !
Beiträge: 36
Registriert: So 11. Jul 2021, 13:33

Re: Zeilenumbruch in Makro ersetzen

Beitrag von Jörg » Mo 8. Jun 2026, 00:34

Danke, Wanderer, für die Idee und das in Aussicht gestellte Suchen.
Was die Obergrenze betrifft, könnte ich mir vorstellen, dass ein Absatz komplett
in einem String gespeichert wird. In Andrew Pitonyaks "OpenOffice.org Macros
Explained" lese ich aber (3.3.6), dass ein String maximal 65.535 Zeichen fasst -
das wären ca. 13 voll beschriebene A4-Seiten. Für meine Dateien mache ich mir da
keine Sorgen; aber es soll ja auch Leute geben, die überhaupt keine Absätze
machen.

Bei meinem Ansatz habe ich mittlerweile zwar rausgefunden, wie man an die
Steuerzeichen für den Zeilenumbruch kommt (CR, LF), nämlich durch ein
textCursor.goRight(1, true), wobei mir nicht nachvollziehbar ist, wie das
Vorrücken um nur ein Zeichen gleich zwei Zeichen erreichbar macht. Auch das
Ersetzen der Steuerzeichen durch ein Leerzeichen mithilfe der MID(...)-Funktion
scheint in den Daten der Zeile zu gelingen. Allerdings führt das in keiner Weise
zu einem sichtbaren neuen Umbruch. Entweder bleibt durch das Ersetzen von <CR>
<LF> die End-of-paragraph Information weiterhin erhalten, oder es bedarf noch
weiterer Befehle, um die Anzeige zu aktualisieren.

Code: Alles auswählen

  dim oText	  as Object
  dim oSaveCursor as Object
...
  oText= ThisComponent.Text
  oSaveCursor= oText.createTextCursor()
...
  Do
    oTextCursor.gotoEndOfParagraph(true)
    line= oTextCursor.getString()
    oTextCursor.gotoEndOfParagraph(true)
    oSaveCursor.gotoRange(oTextCursor, false)
    oViewCursor.gotoRange(oTextCursor, false)
    oTextCursor.goRight(1, true)
    count = count + 1
    line= oTextCursor.getString()
    oTextCursor.gotoRange(oSaveCursor, false)
    if (len(line)>2) then Print len(line) & " " & left(line, len(line)-2) & " > " & GetLastTwoCharsInASCII(line)
    if (NOT(len(line)=2 OR IsNextLineNewParagraph(oTextCursor))) then
      Mid(line, len(line)-1, 2, " ")
      Print "After repl.: " & len(line) & " " & left(line, 10) & " >> " & GetLastTwoCharsInASCII(line)
    else
      Print "Next is new §"
    end if
  Loop While oTextCursor.gotoNextParagraph(false)
  MsgBox "Count of lines: " & count, 0, "Result"
end sub


Function GetLastTwoCharsInASCII(s as String) As String
  dim ss as String
  if len(s)>0 then
    ss= right(s, 2)
    GetLastTwoCharsInASCII= ASC(left(ss, 1)) & ", " & ASC(right(ss, 1))
  else
    GetLastTwoCharsInASCII= ""
  end if
End Function


Function IsNextLineNewParagraph(textCursor as Object) As Boolean
  dim line As String
 
  IsNextLineNewParagraph= true
  if (textCursor.gotoNextParagraph(false)) then
    textCursor.gotoEndOfParagraph(true)
    line= textCursor.getString()
    if (NOT(len(line)=0 OR left(line, 1)=vbTab OR left(line, 3)="   ")) then
      IsNextLineNewParagraph= false
    end if
    textCursor.gotoPreviousParagraph(false)
' else ' EOT
  end if
End Function

mikele
* LO-Experte *
Beiträge: 2052
Registriert: Mo 1. Aug 2011, 20:51

Re: Zeilenumbruch in Makro ersetzen

Beitrag von mikele » Di 9. Jun 2026, 21:30

Hallo,
wenn ich den Code richtig lese, bedeutet ein "wahrer" Absatz einer, der leer ist oder mit einem Tabulator oder mit drei Leerzeichen beginnt. Dann sollte folgendes Makro funktionieren:

Code: Alles auswählen

Sub Main

	oText= ThisComponent.Text
	oTextCursor= oText.createTextCursor()
	oTextCursor.gotoEndOfParagraph(false)
	oTextCursor.goright(1,true)
	oTextCursor.String=""
	Do
		oTextCursor.gotoEndOfParagraph(true)
		line= oTextCursor.getString()
		if len(line)=0 then
			oTextCursor.collapsetostart()
			oText.insertControlCharacter(oTextCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK,false)
			else if asc(line)=9 or left(line, 3)="   " then
				oTextCursor.collapsetostart()
				oText.insertControlCharacter(oTextCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK,false)
			end if
		end if
		oTextCursor.gotoEndOfParagraph(false)
		oTextCursor.goright(1,true)
		oTextCursor.String=""
		oTmp=oText.createTextCursorByRange(oTextCursor)
	Loop While oTmp.gotoNextParagraph(False)
   
End Sub
Gruß,
mikele

Jörg
! Supporter - Spende !
Beiträge: 36
Registriert: So 11. Jul 2021, 13:33

Re: Zeilenumbruch in Makro ersetzen

Beitrag von Jörg » Mi 10. Jun 2026, 01:03

Mikele, ich bin echt überwältigt von deinem Code. Einmal von seiner Kürze, aber auch ganz wörtlich, weil ich ihn nicht wirklich nachvollziehen kann. Das liegt aber an meinen nur rudimentären Makro-Kentnissen von LO. Wenn du Lust und Zeit hast, bitte ich dich um eine "Nachhilfestunde" zu folgenden Fragen:

1. Was wird in oTextCursor.String gespeichert? Der TextRange des Cursors? - Und was für Folgen hat es, wenn du die Variable (im Code zwei Male) leerst? Hat der Cursor dann keinen Text mehr, sondern nur noch eine Position?

2. Was genau macht das oTextCursor.collapseToStart() im Code? Natürlich habe ich eine Vorstellung, wenn ich lese "Set the end position to the start position." Aber die Schleife fängt doch am Abschnittende an. Warum muss man (nach dem Collapse) gleich wieder ein PARAGRAPH_BREAK einfügen. Ist am EndOfParagraph nicht bereits ein PARAGRAPH_BREAK? Leider habe ich kein einziges Beispiel im Netz zu TextCursor.collapseToStart() gefunden.

Ich habe den Eindruck, wenn ich diese beiden Dinge nicht kapiere, werde ich den nächsten Schritt - das Einfügen eines Leerzeichens am Zeilenende bevor der Zeilenumbruch geschieht - nicht hinbekommen. Ich habe einfach mal oText.insertString(oTextCursor, " ", false) probiert. Das hatte aber keinerlei Auswirkung.

Falls du eine Seite im Netz oder Literatur kennst, wo ich was nachlesen kann, ist mir das natürlich ebenso eine Hilfe.
Hab für Bisheriges und vielleicht Zukünftiges jedenfalls vielen Dank.

Open Office
Antworten