Trying to make a macro for pasting URLs in Writer

Sorry if this has been addressed before, but I cannot find anything on the matter pertaining to Writer.
I am trying to create a macro in LO Basic, which will do a simple task: I select a piece of text in Writer, I have copied a URL (address string “http://www…”) in the clipboard, and the macro will paste the URL as a link in the selected text. Note: not replace text, just convert the selected text to a hyperlink and set the target URL to the one in the clipboard.
I’ve already tried multiple things I’ve found on-line, but nothing seems to work, especially in getting the selected text from Writer. I’ve tried “ThisComponent.GetCurrentSelection()” but I can’t find how to extract the selected text/string. Also, I cannot find how to inject the URL in a piece of text – well, apart from Ctrl-K, Ctrl-V which is what I want to avoid.

Here’s a snippet of code I’m using, but multiple errors crop up:

Sub PasteURLInSelection
	Dim sel As Object, doc As Object, txt as String
	
	doc = ThisComponent
	sel = doc.getCurrentSelection()
REM	print sel.getStart()
REM	print sel.getString()
	txt = getClipboardText()
 	print getClipboardText()
End Sub

The “getClipboardText()” subroutine is something I found and it works in returning the contents of the clipboard as plain text.
Any help would be most appreciated.

Copy URL to clipboard, select the word (or words) in your ODT and test this macro:

Sub addUrlFormClipboardAsText
	dim oDoc as object, oSels as object, oSel as object, undoMgr as object
	const cUndo="Make hyperlink" 'tetx for Undo/Redo
	oDoc=ThisComponent
	undoMgr=oDoc.UndoManager
	undoMgr.enterUndoContext(cUndo) 'only one step in Undo/Redo
	oSels=oDoc.CurrentController.Selection
	if oSels.supportsService("com.sun.star.text.TextRanges") then 'there are TextRanges in selection
		for each oSel in oSels
			if oSel.supportsService("com.sun.star.text.TextRange") then
			 	if Len(oSel.String)>0 then
					with oSel
						.HyperlinkURL=getTextFromClipboard() 'get URL from clipboard
						.CharStyleName="Internet link"
					end with
				end if
			end if
		next
	end if
	undoMgr.leaveUndoContext(cUndo)
End Sub

Function getTextFromClipboard() as string
	dim oClip as object, oConv as object, oCont as object, oTyps as object, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	on error resume next
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
	on error goto 0
End Function

It is final solution fixed according to remarks below.

1 Like

Wow, thank you so much for this. I don’t think I’d be able to do this myself; while I understand the code you provided, I have so many gaps in my knowledge of the inner workings of LibreOffice to create such code. I’ve done something similar with Microsoft Word and it only took a couple of lines of code. This is much MUCH more complicated!
Thank you!

I think this should be
AND Len(oSel.String)>0 then
right?

Note that there is no Boolean short-cirquiting in Basic. Hence, this line is incorrect, because it will evaluate oSel.String regardless of if it supports TextRange service or not. And if it does not, oSel may not have String property - raising a run-time error.

You need to use nested ifs:

if oSel.supportsService("com.sun.star.text.TextRange") then
  if Len(oSel.String)>0 then
2 Likes

@skagon >0) was my typing error. The fix is as @mikekaganski mentioned.

if oSel.supportsService("com.sun.star.text.TextRange") then
	if Len(oSel.String)>0 then
		with oSel
			.HyperlinkURL=getTextFromClipboard() 'get URL from clipboard
			.CharStyleName="Internet link"
		end with
	end if
end if
1 Like