Report Designer XML Copy and Paste

It would be extremely helpful to be able to Copy out of the Report Designer, edit the XML file and paste it back in. This topic hints to a solution but I do not know how to make his code work for this propose.

I would appreciate an explanation of the script or an outright solution.

Thank you,

Reporting only expects data to be pasted in in a certain ā€œdataflavorā€ - that’s the cross-platform abstraction Java/Swing uses to interact with the system clipboard. So the script I have there is mostly boilerplate to create a ā€˜MockReportMillClipboard’ Java object, which then gets copied to the system clipboard.
This section at the end is the only part that actually does anything with the data in the clipboard:

	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)

First, it tries to extract the data from reportmill as a string (this will be the XML). clip.getData(dataflavor) returns that as a string. Then at the end, clip.setContents is used with the ā€˜MockReportMillClipboard’ to create an object that acts the same as real ReportMill data, which means the rest of the system just accepts it and lets you paste it in.

I recommend running that script in the designer, since the script console is available and gives you ~easy access to running scripts at the same time you’re editing a report.

I am giving this a try and get this error. I am trying to copy a Table component.
This actually did work for graph component.

19:50:40.927 [AWT-EventQueue-0] WARN reporting.ReportMill.Editor - Exception encountered when retrieving shapes from clipboard
com.inductiveautomation.rm.base.RMException: Element type "text" must be followed by either attribute specifications, ">" or "/>".
	at com.inductiveautomation.rm.archiver.RXElement.getElement(RXElement.java:66)
	at com.inductiveautomation.rm.archiver.RXArchiver.readObject(RXArchiver.java:137)
	at com.inductiveautomation.rm.editor.RMEditorClipboard.getShapesFromClipboard(RMEditorClipboard.java:243)
	at com.inductiveautomation.rm.editor.RMEditorClipboard.paste(RMEditorClipboard.java:141)
	at com.inductiveautomation.rm.editor.RMEditorClipboard.paste(RMEditorClipboard.java:121)
	at com.inductiveautomation.rm.editor.RMEditor.paste(RMEditor.java:707)
	at com.inductiveautomation.reporting.designer.workspace.design.DesignerPanel.doRMPaste(DesignerPanel.java:120)
	at com.inductiveautomation.reporting.designer.workspace.ReportingResourceWorkspace$ReportDesignerEditActionHandler.doPaste(ReportingResourceWorkspace.java:759)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner$Handler.handlePaste(IgnitionDesigner.java:2863)
	at com.inductiveautomation.ignition.designer.IgnitionDesigner$Handler$15.actionPerformed(IgnitionDesigner.java:2421)
	at java.desktop/javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at java.desktop/javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at java.desktop/javax.swing.AbstractButton.doClick(Unknown Source)
	at java.desktop/javax.swing.AbstractButton.doClick(Unknown Source)
	at java.desktop/javax.swing.plaf.basic.BasicMenuItemUI$Actions.actionPerformed(Unknown Source)
	at java.desktop/javax.swing.SwingUtilities.notifyAction(Unknown Source)
	at java.desktop/javax.swing.JComponent.processKeyBinding(Unknown Source)
	at java.desktop/javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
	at java.desktop/javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
	at java.desktop/javax.swing.JMenuBar.processBindingForKeyStrokeRecursive(Unknown Source)
	at java.desktop/javax.swing.JMenuBar.processKeyBinding(Unknown Source)
	at java.desktop/javax.swing.KeyboardManager.fireBinding(Unknown Source)
	at java.desktop/javax.swing.KeyboardManager.fireKeyboardAction(Unknown Source)
	at java.desktop/javax.swing.JComponent.processKeyBindingsForAllComponents(Unknown Source)
	at java.desktop/javax.swing.JComponent.processKeyBindings(Unknown Source)
	at java.desktop/javax.swing.JComponent.processKeyEvent(Unknown Source)
	at com.inductiveautomation.rm.viewer.RMViewer.processKeyEvent(RMViewer.java:943)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at com.inductiveautomation.rm.editor.RMEditor.processEvent(RMEditor.java:1029)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
	at java.desktop/java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at com.inductiveautomation.snap.swing.RibsEventQueue.dispatchEvent(RibsEventQueue.java:99)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Caused by: com.inductiveautomation.rm.base.RMException: Element type "text" must be followed by either attribute specifications, ">" or "/>".
	at com.inductiveautomation.rm.archiver.RXElementParser.fatalError(RXElementParser.java:184)
	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.seekCloseOfStartTag(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
	at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
	at com.inductiveautomation.rm.archiver.RXElementParser.parse(RXElementParser.java:74)
	at com.inductiveautomation.rm.archiver.RXElement.getElement(RXElement.java:64)
	... 61 common frames omitted
Caused by: org.xml.sax.SAXParseException: Element type "text" must be followed by either attribute specifications, ">" or "/>".
	at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
	... 78 common frames omitted


Reviving a dead topic after having the displeasure of trying to match a report in ignition to an existing report in a differnet scada and needing to make things precise sizes. Right now the only way to make a row an exact size in the simple table is by dragging the row or column dividers still, you cannot manually set the pixels which makes getting exact sizing very difficult.

There are obvious xml properties that seem like changing would make this simple

  <cell-table x="72" y="409" width="485" height="72" format-template-style="5" header-row-count="1" header-column-count="0">
    <column width="243" />
    <column width="242" />
    <row height="18" />
    <row height="18" />
    <row height="18" />
    <row height="18" />

Luckily my situation I know the rows were all identical heights so I just made the size correct from the start and then modified the number of rows and it was smart enough to equally divide. But width wise I was still left dragging column dividers. The normal table works a bit better but if I had many rows that were not repeating out of a dataset, I’d still be stuck doing each cell by hand.

It would be very very nice if we could edit the XML of the report design directly. I also ran into the situation mentioned in a prior post where font’s were not rendering correctly in PDF Viewer and I had to go and change 100’s of labels by hand with what could have otherwise been a control+F.

XML can be edited in 8.3.3

New in 8.3.3

By holding the Shift key and right-clicking on the report, the Copy XML To Clipboard and Set XML From Clipboard options will be available at the bottom of the right-click menu. These allow you to copy the contents of a report in an XML format, and then paste the XML into another report.

2 Likes