PDF report linking

Hi all,

I’m not sure if you’ve come across the need to link within a pdf but I have.

My pdf report is over 70 pages due to the nature of the site, and as the report goes out to multiple people I have an index page at the front of my pdf. What I would like to do is on the index page have the pdf generated with links, so they user can click on page 35 and be taken to that page. The other thing is I’d also like to have hyperlinks to email addresses and our website within the pdf. This is as our reports go out to our clients. If any one has done anything similar I’d love to hear about it.

Also I have submitted this as a feature request should anyone else be interested in this.

https://inductiveautomation.canny.io/ignition-features-and-ideas/p/report-pfd-linking

You completely nerd-sniped me with this topic - I definitely shouldn’t have spent as much time on this as I did. But, this is actually possible with the existing reporting module. We’ll definitely have to see about adding this capability in a better way.
Basically, the workaround I came up with relies on the fact that objects in reporting can be copied to the clipboard and show up as XML representations of the underlying Java object. So, to use this (extremely janky) workaround:
0. Paste the script below into the script console and execute it. Nothing will happen - that’s intentional.

  1. Copy the desired component (I’ve only really tested text shapes) to the clipboard.
  2. Go back to the script console, and in the interactive interpreter, run addURLToClipboardObject(<someURL>). To link to a specific page, use addURLToClipboardObject("Page:3"). You can also use Page:Next and Page:Back.
  3. Click back to the reporting workspace, and specifically click into the editor/visible page. Then paste your modified object.

If everything went correctly, the hyperlink should be active on the preview tab:

And, without further ado, the hacky monstrosity that will do all this. It’s pretty unlikely this will break any existing report, but it may throw all kinds of errors into the console. I would recommend copying your report to a new project, going through this process to add the links, and once you’ve verified it works copy the report back to your original project.

def addURLToClipboardObject(url):
	from java.awt import Toolkit
	from java.awt.datatransfer import DataFlavor, Transferable
	from java.io import ByteArrayInputStream
	from java.lang import String
	import re
	
	class MockReportMillClipboard(Transferable):
		RMDataFlavor = DataFlavor("application/reportmill", "ReportMill Shape Data")
		def __init__(self, data):
			self.data = String(data).getBytes()
		
		def isDataFlavorSupported(self, flavor):
			return flavor == self.RMDataFlavor
		
		def getTransferData(self, flavor):
			if flavor == self.RMDataFlavor:
				return ByteArrayInputStream(self.data)

		def getTransferDataFlavors(self):
			return self.RMDataFlavor.getTransferDataFlavors()
	        
	clip = Toolkit.getDefaultToolkit().getSystemClipboard()
	
	dataflavor = None
	for df in clip.getAvailableDataFlavors():
		if df.mimeType == 'application/x-java-serialized-object; class=java.lang.String':
			dataflavor = df
			break
	if dataflavor:
		data = clip.getData(dataflavor)
		regex = r"<text(.*)>"
		subst = r'<text\g<1> url="%s">' % url
		result = re.sub(regex, subst, data, re.MULTILINE)
		print "Added URL to clipboard object"
		clip.setContents(MockReportMillClipboard(result), None)
3 Likes

Hello Paul,

Thank you so much for spending time on this, I really do appreciate it. In fact its what’s so great about Ignition that we have this community. I will definitely give this a bash and let you know how I get along. It’s certainly going to make the reporting that much more powerful for us.

Hello Paul,

This worked like a charm in the report preview and in the report viewer window.

I then realised that my question was not as well defined as I thought, and I do apologise for this. You see the old reports were done in Microsoft Word with a table of contents, and when they were exported to PDF the table of contents was “clickable”. This is what I was after so that when the user generates the report then saved it and emailed it to the client the table of contents still had hyperlinks in it.

I have a button along side my report viewer, and once I use it to save to pdf, the links don’t work once the pdf is saved to the local computer and opened in the adobe pdf viewer.

Hmm, that’s interesting - when I was testing this I specifically tried saving the output and was still able to click the links.

EDIT: Looks like there’s a limitation - when the objects get copied to subsequent pages due to table wrapping, they don’t get clickable links in a PDF export, even though they do in the report viewer/preview. Unfortunately, I don’t know if that’s going to be solveable. I was able to put multiple clickable links onto the first page, which do come out clickable when opened using Chrome’s built-in PDF viewer, so they should work in other PDF viewers.

Linking 7-19-18 08AM.pdf (4.9 KB)

Hello Paul,

Your document links are working in my Chrome browser as well, so its strange in acrobat its not working, maybe I have a setting somewhere that is causing this. I will play around more with this next week, please do excuse the disjointed responses, as our time zones are far apart. I’ll have more feedback for you next week.

Hello Paul,

Some great news, after playing with the reports a bit more your solution is working on adobe and chrome, I think I must’ve made a mistake somewhere when working between the links. I really can’t thank you enough for your assistance with this.

1 Like

I'm trying to get this to run using "Page:2" in the arguments but I'm getting the following error in the interpreter. Any ideas?

>>> addURLToClipboardObject("Page:2")
Added URL to clipboard object
Traceback (most recent call last):
File "", line 1, in
File "", line 33, in addURLToClipboardObject
NotImplementedError: 'MockReportMillClipboard' object does not implement abstract method 'getTransferDataFlavors' from 'java.awt.datatransfer.Transferable'

Hm, it definitely used to work, I'm not sure why that's required now. But I updated the original post to implement that method as well.

Thanks for the quick response!

I've just tried it again and now the error has changed to:

Added URL to clipboard object
Traceback (most recent call last):
File "", line 1, in
File "", line 36, in addURLToClipboardObject
File "", line 21, in getTransferDataFlavors
AttributeError: 'java.awt.datatransfer.DataFlavor' object has no attribute 'getTransferDataFlavors'

Maybe make it

		def getTransferDataFlavors(self):
			return [self.RMDataFlavor]

Good news! In 8.1.19 this will finally be directly possible:

Plus some fixed bugs with link generation that this workaround would never have helped with :slight_smile:

2 Likes

Hello, this is awesome to hear, thank you so much!