System.file.writeFile issue with Perspective

This is probably a documentation issue.

https://docs.inductiveautomation.com/display/DOC80/system.file.writeFile

https://docs.inductiveautomation.com/display/DOC80/system.file.saveFile

When I try to use the code snippet from the documentation (in Perspective) it tells me that saveFile isn’t an attribute of system.file. If I use the ctrl+space suggestions of system.file from a button’s onClick event in Perspective there is no saveFile method. The code examples show using saveFile to create the file and then system.file.writeFile to write to the file.

It’s been a few years since I wrote to a file from Ignition so I don’t remember how it’s supposed to work.

Ultimately, I’m just trying to export data from historical tag data to a .csv. I’m starting with the “easy stuff” so I’m just trying to write a text string to a file.

saveFile doesn’t actually save a file. It opens a file chooser dialog looking at the local filesystem to allow the user to construct a file path+name. That string is the return value. It only works in Vision because browsers don’t permit this kind of action.

writeFile is then used to actually perform the save operation. Again, it only works (locally) in Vision because browsers don’t permit this kind of action. The alternative in Perspective is to construct a downloadable file first, then place a link to it in your view. Following that link uses the browser’s download mechanism, which may or may not automatically offer a dialog to select a location and name to save under.

Perspective is fundamentally different from Vision. This is one of those differences.

1 Like

To add onto @pturmel’s response, please look at the available scopes for the functions you’re attempting to use; saveFile() is only available in Vision Client scripting - not Perspective Sessions.

The writeFile() function IS available in Perspective, but ALL functions in Perspective run on the Gateway (so that’s where the file is written to), so you will never see a file on your local machine as a result of using writeFile().

There’s no mechanism in Perspective as of today that allows for exporting or downloading files of any type - short of coupling with the WebDev Module.

1 Like

@pturmel
Thanks for the clarification. I vaguely remember that from training now that you mention it.

@cmallonee I saw your other response on this about the file being saved on the server. It threw me a bit when I tried to use the example from the help and it blew up. The scope makes sense.

I was having trouble getting it to accept my path. I had to escape “” in my path. It’s been a while since I did this and after figure out the problem it was kinda obvious. It’s not every year I have to write to a file from an HMI.

Thanks for your help.

1 Like

I figured out a pretty good solution for what I need to do. The customer wants to be able to select data points and have them displayed in a grid. Then they want to be able to hit a button to download a CSV file of the data from the grid.

This code got it done:
dataset = self.getSibling(“Table”).props.data
export = system.dataset.toCSV(dataset, 1, 0, 0)
system.perspective.download(filename=“test.csv”, data=export)

system.perspective.download isn’t documented on the official documentation yet. I found it on the intellisence thing and poked it until it worked.

Of course, selecting data points to display on the grid is the next fun challenge. I suspect this code will export all datapoints in the dataset whether I have them hidden or not.

6 Likes

It’s not documented because no one here knows about it (the dev who placed it is out right now). I’ll request it be added to the documentation.

1 Like

Thanks. This was a dumb luck situation.

I appreciate your help as always. I have been developing better stuff in general thanks to your help. I’m still using some of the stuff you showed me to muddle my way through unrelated things. My general approach to developing Perspective projects has improved thanks to your feedback.

I also appreciate the feature. It is EXACTLY what I needed. So thumbs up to that developer also :slight_smile:

1 Like

Is this an official way to save a table to CSV on the local machine ?

system.perspective.download is an official option. It just didn’t seem to be communicated to everyone when it rolled out.

Documentation can be found below.

https://docs.inductiveautomation.com/display/DOC80/system.perspective.download

1 Like

That’s what I thought, but when i tried the code posted above on a table in my program it doesn’t work. So wasn’t sure if that was an official method.

I put the following code in a button script referencing a table.

dataset = self.getSibling(“Table”).props.data
export = system.dataset.toCSV(dataset, 1, 0, 0)
system.perspective.download(filename=“test.csv”, data=export)

The error in the gateway log shows…

org.python.core.PySyntaxError: SyntaxError: (u"no viable alternative at character '\u201c'", ('', 4, 38, u'\tsystem.perspective.download(filename=\u201ctest.csv\u201d, data=export)\n'))

at org.python.core.ParserFacade.fixParseError(ParserFacade.java:95)

at org.python.core.ParserFacade.parse(ParserFacade.java:205)

at org.python.core.Py.compile_flags(Py.java:2205)

at com.inductiveautomation.ignition.common.script.ScriptManager.compileFunction(ScriptManager.java:841)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.compileFunctionSuper(ProjectScriptLifecycle.java:526)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.getOrCreateDelegate(ProjectScriptLifecycle.java:565)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.(ProjectScriptLifecycle.java:556)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.compileFunction(ProjectScriptLifecycle.java:515)

at com.inductiveautomation.ignition.common.script.ScriptManager.compileFunction(ScriptManager.java:822)

at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:68)

at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:65)

at com.inductiveautomation.perspective.gateway.action.ActionDecorator.runAction(ActionDecorator.java:18)

at com.inductiveautomation.perspective.gateway.action.SecuredAction.runAction(SecuredAction.java:51)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:257)

at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:246)

at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:215)

at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)

at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)

at java.base/java.util.concurrent.FutureTask.run(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)

That’s a pure syntax error, not a problem with the logic. I can’t tell from your code block precisely what the problem is, but it isn’t a problem with system.perspective.download(). Possibly it is the paired quotation marks. You must use the straight quote marks in code.

3 Likes

Or the fact that the variable dataset is a list, whereas the function call expects a Dataset.

1 Like

I’m using Ignition version 8.1.4 and this method doesn’t seem to work anymore?

I put the following code in a button script referencing a table, similar to a post above:

dataset = self.getSibling("Table").props.data
csv = system.dataset.toCSV(dataset, showHeaders = True, forExport = False)
system.perspective.download(filename=“test.csv”, data=csv)

But on button press I get the following error:

Unable to run action 'component.onActionPerformed' on Main Views/TagHistory@D/root/Button: code could not be compiled.

That error generally means a syntax error. I see curly quotes in your code’s third line around test.csv. Those should be ASCII straight double quotes. This commonly occurs when someone posts code without proper formatting marks, and this forum tries to “prettify” the “paragraphs”, like here. Don’t cut and paste from improperly formatted code on forums.

4 Likes

You’re completely right. Thank you.