Can I do a "find and replace" on the targets of hyperlinks in a draw document?

… and if so, how?

1 Like

Guess that hyperlinks do not start with ‘http’ or ‘https’ or such?

Hello @PeterAlefounder,

pending the enhancement request here, which i assumed was also yours, please try if you could use the following macro to change your Hyperlinks in Draw:

( i have not tested this in all cases, please let us know if it works in your case ):

E.g. to change only the target URLs of all Hyperlinks, you could call:

Draw_Hyperlinks_ReplaceAll( “*”, “https://www.url_here.org”, 1 )

If you don’t know how to call a method with arguments, then you can put the above line inside your Main() method, and then call that Main() method via “Tools : Macros : Run Macro…”.

Sub Draw_Hyperlinks_ReplaceAll( strFind As String, strReplace As String, Optional iType As Integer )
REM Perform a Case-Sensitive Find/Replace on URL TextFields ( Hyperlinks ) inside the current Draw document.
REM <strFind>	: Case-Sensitive String to be found and replaced inside the Hyperlink's URL and/or its textual Representation.
REM <strReplace>: String to replace the found substring with, inside the Hyperlink's URL and/or its textual Representation.
REM <iType>		: [OPTIONAL] Determines which parts of the Hyperlink to Find/Replace; DEFAULT=0.
REM		0 = Find/Replace URL and Representation ; 1 = Find/Replace URL only ; 2 = Find/Replace Representation only.
REM NB. All occurrences of <strFind> within the specified parts of the Hyperlink will be replaced by <strReplace>.
REM The Search does not support Regular Expressions or wildcards.
REM But if you pass <strFind>="*" ( Unicode U+002A ASTERISK ), then all Hyperlinks will be replaced.
REM In that case <strReplace> should be a full URL.
	Dim oDoc As Object  :  oDoc = ThisComponent
	If oDoc.supportsService( "com.sun.star.drawing.GenericDrawingDocument" ) Then
		Const sTextFieldURLservice	As String = "com.sun.star.text.TextField.URL"
		Const sTextShapeType		As String = "com.sun.star.drawing.TextShape"
		Dim oDrawPages As Object : oDrawPages = oDoc.getDrawPages()
		Dim oDrawPage As Object
		Dim oShape As Object
		Dim oText As Object
		Dim oEnum As Object
		Dim oEnumRanges As Object
		Dim oTextContent As Object
		Dim oTextRange As Object
		Dim oTextField As Object
		Dim iReplacedCount As Integer
		Dim i As Integer, j As Integer
		If IsMissing( iType ) Then iType = 0
		For i = 0 To oDrawPages.getCount() - 1		REM Traverse all DrawPages.
			oDrawPage = oDrawPages.getByIndex( i )
			For j = 0 To oDrawPage.getCount() - 1		REM Traverse all Shapes.
				oShape = oDrawPage.getByIndex( j )
				If oShape.getShapeType() = sTextShapeType Then	REM Found a TextShape.
					oText = oShape.getText()
					oEnum = oText.createEnumeration()
					Do While oEnum.hasMoreElements()		REM Traverse all TextContents.
						oTextContent = oEnum.nextElement()
						oEnumRanges = oTextContent.createEnumeration()
						Do While oEnumRanges.hasMoreElements()		REM Traverse all TextRanges.
							oTextRange = oEnumRanges.nextElement()
							If Not IsNull( oTextRange.TextField ) Then	REM Found a TextField.
								oTextField = oTextRange.TextField
								If oTextField.supportsService( sTextFieldURLservice ) Then		REM Found URL TextField.
									If strFind = "*" Or Instr( 1, oTextField.URL, strFind, 0 ) > 0 Or Instr( 1, oTextField.Representation, strFind, 0 ) > 0 Then
										Dim oTextFieldURL As Object
										oTextFieldURL = oDoc.createInstance( sTextFieldURLservice )		REM Replace URL TextField.
										oTextFieldURL.URL = oTextField.URL
										oTextFieldURL.Representation = oTextField.Representation
										If strFind = "*" Then
											If iType = 0 Or iType = 1 Then oTextFieldURL.URL = ConvertToURL( strReplace )
											If iType = 0 Or iType = 2 Then oTextFieldURL.Representation = strReplace
										Else
											If iType = 0 Or iType = 1 Then oTextFieldURL.URL = ConvertToURL( Join( Split( oTextField.URL, strFind ), strReplace ) )
											If iType = 0 Or iType = 2 Then oTextFieldURL.Representation = Join( Split( oTextField.Representation, strFind ), strReplace )
										End If
										oText.removeTextContent( oTextField )
										oTextRange.Text.insertTextContent( oTextRange, oTextFieldURL, True )
										iReplacedCount = iReplacedCount + 1
									End If							
								End If
							End If
						Loop
					Loop
				End If
			Next j
		Next i
		Msgbox iReplacedCount & " Hyperlinks Found/Replaced.", MB_ICONINFORMATION, "LibreOffice Draw - Find/Replace Hyperlinks"
	End If
End Sub

With regards, lib

Thanks for the macro. I’ll see what I can do with it - not much experience with macros, so no promises!

Thanks for the comments. Over the holiday period, I found my own way to do this, to wit: save the drawing as Flat XML (.fogd) and do a global edit with a simple text editor. If there are a lot of files, use a programmable text editor and write a shell script.

1 Like