Today I'm breaking my rule of never manually (or automatically) editing a workspace file, in order to dynamically update a choice-type user parameter.
Question of the WeekThis question was asked by @philippeb who needs to send a list of names to a survey choice field.Â
Q) Our employees fill a weekly survey about their health and their kids going to summer camp activities.
The survey fields] change in time, depending on the kids that subscribed. The subscribed kids are exported into an Excel file every week.Â
Â
I thought to read the file with FME and push the kids into the survey every week. That way the list of kids in the survey could change without our help. And the kid (or his parent) could select his name to fill the survey.
The issue is that we don't know any survey platform able to change automatically from a script. Do you know if any kind of platform could change when FME pushes new values into it?
A) I know of a platform that could be used to provide a weekly survey: FME Server! After all, that's what I use for the weekly FME Quiz. A simple Server app takes the place of a survey tool, and you could set up the underlying workspace to carry out all sorts of tasks (like calculating statistics or emailing participants).
Â
The question is, can we set up a Choice parameter in FME that updates the list of choices dynamically?
What I Tried First Of AllIs there a way to do this "officially" in FME? Well, the Choice type parameter has an import option, but it's static. You can import a list when you create the parameter, but you can't force it to automatically regenerate the list from a source when you run the workspace.
A Scripted parameter also sounds like it might work, but it doesn't present options at all to the users. So it could take a name from the Choice parameter and check the name's validity, but it can't restrict the choice in the first place.
So is there a way to do this "semi-officially".
What Is Pretty Cool, But Doesn't Quite FitThese are the types of hack that I love, where you use functionality intended for one purpose, in a completely different way.
Let's see... are any user parameter types dynamic?Â
Actually, yes. The Feature Types to Read parameter is dynamic. Let's say I set up a processing workspace that reads the list of children's names from Phillipe's Excel file. I could then create a database table for each child.
Then the actual workspace, instead of using a Choice parameter, uses the Feature Types to Read parameter:
The end-user thinks they are picking from a list of names, when in fact we're dynamically giving them a list of database tables! The difference doesn't matter because we only want to know what their selection is. We don't even need to read from the database tables, just use the value of the parameter.
The problem is... this isn't a Single Choice parameter, but a Multiple Choice parameter. I could select multiple names from the list, when really we want only one.
So it's a really nice, hacky idea, but it's not going to work here.
But there is a very "unofficial" method that will work...
What I'm Reluctant To Do, But Works!I'm generally against editing a workspace file manually; like opening your fmw file in a text editor and making changes. It's not as simple as you'd think and you could cause some major problems.
However... the definition for user parameters is pretty straightforward, so let's risk it in this case!
So my method is this. I have a base workspace that runs my survey. It has a whole bunch of questions, like:
- Select Child Name
- Enter Child Age
- Select Preferred Activity Date
I have that set up in an FME Server app, like so:
The important parameter is the one Select Child Name. Opening up the fmw file in a text editor, I can see it is defined in two places:
#!   GUI_LINE="GUI CHOICE_OR_ATTR kidName DEFAULT Name of Child:"
GUI CHOICE kidName DEFAULT Name of Child:
I set it up with a single choice of DEFAULT, so what I have to do is substitute that line with one that replaces DEFAULT with the list of proper names, read from the Excel dataset.
I obviously do that with a second workspace, which looks like this:
I read from the Excel file (actually I'm using a plain text file) and aggregate the names together. The Aggregator will kindly concatenate all the names together, separating them with a % character, which is what the parameter definition expects.
The AttributeCreator creates my replacements for the above lines, i.e. this:
GUI CHOICE kidName @Value(text_line_data) Name of Child:
#!   GUI_LINE="GUI CHOICE_OR_ATTR kidName @Value(text_line_data) Name of Child:"
The AttributeFileReader reads the contents of the base workspace, the StringReplacer updates the two strings, and then the AttributeFileWriter writes the file back again.
I write to a new file name so that I always have the original as a template.
Finally, I publish the base workspace back to FME Server, and the app automatically updates with the new names from the Excel file.
Voila!
SummarySo the original question asked only about using FME to write values to an existing survey platform; but I believe that with FME Server apps, you can do the same sort of thing, but with the added value of FME data transformation and automation.
I'm not wild about doing edits to a workspace outside of Workbench, but it's fairly risk-free for this scenario.
Overall - even without the dynamic parameters - I think this is a great example of the sort of non-spatial project that you can use FME for.
Other Notable QuestionsHere are a few other interesting questions from this week:
- Dynamically created a WFS XML query
- More dynamics, this time dynamically creating an XML query for @redgeographics with the XMLTemplater. I really love the XQuery content from @ebygomm that solves the requirement. Great work!
- Cannot select Hub formats and Custom Formats in 2020
- There was a problem in early 2020.0 versions where you couldn't use or install a custom format from the FME Hub. This is now fixed in the latest .0 updates.
- Clip Vector Data from Multiple Shapes
- @ienesaglam60 asked how to clip data across tile boundaries, but keep the clipped features whole. @markatsafe demonstrates how to do that, by assessing which part of the clipped feature is the largest, and rebuilding the feature in that tile. Now there's a need to keep the same feature in both tiles, which I suspect will be quite straightforward.
- BulkAttributeRenamer not renaming
- This transformer is actually one of my favourites, mostly because it renames so many attributes, in so many ways, and exposes all of the renamed attributes in the canvas. I think that's great. Why wasn't it working for @jlbaker2779? Because the prefix being added was determined by a user parameter. This goes back to a very early question-of-the-week, which dealt with why you can't see attributes created dynamically when you are still authoring the workspace. It also talked about how you also need to set up a dynamic writer, which will also be needed in this question.
- Read Only Changed Rows From a Database
- This is older than a week, but I find it a very interesting question from @benros. I think I recently discussed in a question about Change Detection how to do change detection to find these rows; and @benros has an adequate solution anyway. But recently I came across the idea of using system logs to do this sort of task. For example, Write-Ahead Logging is meant to keep a record of what is about to be written, just in case there is a system failure. But could those logs be used to identify changed records? Wikipedia tells me that "some 1databases] provide programmatic interfaces to their transaction logs" so you might be able to use those, or we might even be able to create a new reader to get that information! Anyone with more database knowledge than I know how these work?