Navigation

    OpenIAP

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    NodeRED Flow accessing OpenRPA Data Table...

    General Discussion
    2
    14
    84
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      Colby Cruwys last edited by

      I am trying to make a Flow in the demo environment that runs a robot on my machine to extract some data out of a CSV file for use.

      My robot looks like this:
      fdc88f68-0667-4237-8ea8-168901a6cf08-image.png

      And my flow is looking something like this:
      1d8e360a-adf3-49ea-a90e-e5c047092eb1-image.png

      But I'm not getting anything in the payload? I'm sure I'm missing something obvious but I'm struggling to find the right documentation to read or example to play with that helps explain how to have my NodeRED Flow access the "studentNamesDT" Data Table from my robot?

      Any pointers in the right direction would be much appreciated.

      Allan Zimmermann 1 Reply Last reply Reply Quote 0
      • Allan Zimmermann
        Allan Zimmermann @Colby Cruwys last edited by

        Hi @colby-cruwys
        Go to the arguments tab in the workflow in the robot
        64cb7e94-da20-452a-9395-e60a9ca690fb-image.png
        Here you can add one or more arguments, you can use those as variables inside the workflow. "In" means you are receiving it from NodeRED ( or another robot workflows, or PowerShell etc ), "out" means you and sending it back (but not receiving) .. and in/out means you can both receive and return a value.
        b33d3c8b-4190-44f2-b77b-d02ad234df0d-image.png

        in NodeRED you can send the value using msg.payload.
        Add a function node, before the "robot" node, and inside it add
        msg.payload = {customerid: 12}
        return msg
        And if you inside the workflow then assign a value to name and address, you will see those from your debug node
        PS: In your example, you are missing a "workflow out" node. If you have an "workflow in" you must always complete it, with a "workflow out" node.

        C 1 Reply Last reply Reply Quote 1
        • C
          Colby Cruwys @Allan Zimmermann last edited by

          Thanks @allan-zimmermann, I've altered my robot workflow so it reads the CSV into a DataTable in the Arguments tab instead of the Variables Tab now:

          4339f75d-8488-4434-9afc-f99975847c87-image.png

          But the Flow outputs a single empty CSV row:

          3c5ed01b-17de-4bef-8baf-0b69c08e5f41-image.png

          Perhaps my settings in the Robot or CSV nodes aren't quite right?!? I'm basically trying to adapt this tutorial from the Node-RED Website to grab a CSV file from my computer instead of the web. Perhaps I'm just going about it all wrong though?

          C 1 Reply Last reply Reply Quote 0
          • C
            Colby Cruwys @Colby Cruwys last edited by

            I just found this section in the documentation. Am I reading this correctly that I just can't pass a DataTable into a NodeRED flow?

            Does this mean in my robot workflow I have to convert the content of the CSV into an array of some kind to pass to NodeRED?

            All I want is for my app.openiap.io NodeRED flow to have access to the contents of a CSV file on my local machine?

            C 1 Reply Last reply Reply Quote 0
            • C
              Colby Cruwys @Colby Cruwys last edited by

              Literally did nothing, and it works now?!?

              c4bc1b59-486a-4116-b40c-895a389cdb2f-image.png

              Not sure if something changed behind the scenes?

              C 1 Reply Last reply Reply Quote 0
              • C
                Colby Cruwys @Colby Cruwys last edited by

                One last pointer if at all possible...how do I now insert the data I've retrieved into the Select Component of my form?
                53ee633f-2955-4438-98bb-52c68b03914b-image.png

                Do I write JavaScript in the custom data field of the Select Form itself (something like this for instance):
                53ad2f2e-e630-466f-a6a0-0e6c923d2fda-image.png

                Or do I write a function in NodeRED that injects it into the Select Component:
                4bae1f7a-cd0f-4729-b2c4-ccca6fac5147-image.png

                I can't find examples of this kind of thing anywhere.

                Allan Zimmermann 2 Replies Last reply Reply Quote 0
                • Allan Zimmermann
                  Allan Zimmermann @Colby Cruwys last edited by

                  Generally you should never send a data table between robot workflows and/or NodeRED workflows.
                  But since having an array with some json objects is a common way to keep data, I added support for serializing a data table back and forth between OpenRPA workflows and NodeRED ( but do NOT use this for larger amount of data )
                  I do not know all the different things you tried, for comparing your first screenshot with your second, you have a csv parser node added in the first. You are not getting a csv file in NodeRED, you are getting an array of json objects, witch is also the "result" of using the csv parser node.

                  You example link assumes NodeRED is running local, I'm going to assume you started a NodeRED in my cloud. A NodeRED i my cloud can never access your local files, but a robot you installed locally can. But you can also install NodeRED locally (and have it be connected to my cloud or you can install OpenFlow you self, and connect to that ) using this guide.

                  Options:

                  1. you can keep doing what you just did, but that is primarily made for a handful of rows, not bigger data sets.
                  2. OpenFlow is a database. You can get data out of OpenFlow into a dataset, and you can load data from csv, excel, various database or you can create data tables your self, and commit the data ( insert/update/deletes) toward OpenFlow as well ( see examples here )
                  3. You can save files in Openflow, in the robot use "get file" activity / "save file" activity and similar you have "api download" "api upload" nodes in NodeRED
                  4. you are creating a processs that involved picking up a different file that you want to process in nodered a better solution would be to use workitems. You can create workitems from both the robot and nodered, and you can "pop" workitems and process them from both of those as well. Workitems handles all the files for you ( on the robot it automaticly upload/downloads the files for you, in nodered you get an easy to use buffer back (or give it) The robor side of Workitems are described here, I'll add a section later about how to do the same inside nodered and how to combine those.
                  1 Reply Last reply Reply Quote 0
                  • Allan Zimmermann
                    Allan Zimmermann @Colby Cruwys last edited by Allan Zimmermann

                    Hi @colby-cruwys
                    When you send a response to a web form from NodeRED, it maps anything in msg.payload to the corresponding form element. So if you add a textbox with the api name "firstname" and set msg.payload.firstname = "Allan" the form will have the value Allan. Same the other way around, so if the user fills out the form, you get all the values in msg.payload
                    But you are not asking to set a value, you want to pre-populate some default values, you do that by referencing the form element name, just like i msg.payload, but in msg.payload.values
                    If you add a function node, and insert this, it should give you an idea, this assumes your select has api name "select"

                    if(!msg.payload) msg.payload = {}
                    if(!msg.payload.values) msg.payload.values = {}
                    msg.payload.values.select = [
                        {"label": "Allan", "value": "allan"},
                        {"label": "Lone", "value": "lone"},
                        {"label": "Lars", "value": "lars"},
                        ]
                    return msg;
                    

                    In the select on the form, you can change how it reads the values, so you do not need to transform your data to match the above, you can simply read other fields in each object ( or use an array of string )

                    So with your data it might be
                    e60c84fc-fa6a-4dab-adb8-3c978f27cc66-image.png

                    <span>{{ item.FIRSTNAME  }} {{ item.SURNAME }}</span>
                    

                    You do need to add a "value" property to each object, ( the select will be empty if the value field is missing )

                    C 1 Reply Last reply Reply Quote 0
                    • C
                      Colby Cruwys @Allan Zimmermann last edited by

                      Thank you for your time @allan-zimmermann. I feel guilty repeatedly coming back to you but I'm really struggling to find the right documentation/resources/examples to explore in order to gain the understanding I need.

                      So in a function node I did as you said and the textbox example you explained works perfectly, but the Select Values remain empty:
                      df5101d0-7350-4577-82a8-e953e5ef3236-image.png
                      c07c0983-309e-4fa1-965c-293fef572b31-image.png

                      I've been trying to investigate "msg.payload.values" but am finding practically nothing on it. You mention that I need to have a Value Property for each object, this too is very difficult to investigate. I've set up my Select Component in the following way:

                      dd1f1fb9-ca97-4e24-b145-6c0c8cdebff9-image.png

                      Hopefully once I get this step better understood I won't be so needy 🙂

                      Allan Zimmermann 1 Reply Last reply Reply Quote 0
                      • Allan Zimmermann
                        Allan Zimmermann @Colby Cruwys last edited by

                        you where not suppose to change anything in the select, except make sure api name matches what you use in msg.payload.values.apiname
                        So delete "value property" and then change data source back to Values

                        C 1 Reply Last reply Reply Quote 0
                        • C
                          Colby Cruwys @Allan Zimmermann last edited by

                          Unfortunately, I am still having no success. I've deleted the Select Component and made one from scratch, I've kept it's default name so it matches your sample code exactly, I've removed every erroneous element of my NodeRED flow, I've put up the Chrome Console (which shows no errors) and I can't find where I might have gone wrong?!?

                          022ad405-ed28-40c3-a9df-ed7923facbf5-image.png

                          f706f5cc-31a6-4518-b064-537b91d0eae3-image.png

                          Allan Zimmermann 1 Reply Last reply Reply Quote 0
                          • Allan Zimmermann
                            Allan Zimmermann @Colby Cruwys last edited by Allan Zimmermann

                            Nodered workflow

                            [
                                {
                                    "id": "5f7c31e9.c7a99",
                                    "type": "workflow in",
                                    "z": "cb80dcfe.45aae",
                                    "queue": "selectdemo",
                                    "rpa": false,
                                    "web": true,
                                    "exchange": false,
                                    "name": "",
                                    "x": 170,
                                    "y": 480,
                                    "wires": [
                                        [
                                            "46767982ec77ca97",
                                            "09d847482f123875"
                                        ]
                                    ]
                                },
                                {
                                    "id": "cfe8590f.43a8e8",
                                    "type": "workflow out",
                                    "z": "cb80dcfe.45aae",
                                    "name": "",
                                    "form": "62654ebc835f9c7b512468da",
                                    "state": "idle",
                                    "removestate": false,
                                    "x": 670,
                                    "y": 460,
                                    "wires": [
                                        []
                                    ]
                                },
                                {
                                    "id": "8038a1b1.874cf",
                                    "type": "switch",
                                    "z": "cb80dcfe.45aae",
                                    "name": "",
                                    "property": "payload.select",
                                    "propertyType": "msg",
                                    "rules": [
                                        {
                                            "t": "empty"
                                        },
                                        {
                                            "t": "null"
                                        },
                                        {
                                            "t": "else"
                                        }
                                    ],
                                    "checkall": "true",
                                    "repair": false,
                                    "outputs": 3,
                                    "x": 510,
                                    "y": 480,
                                    "wires": [
                                        [
                                            "cfe8590f.43a8e8"
                                        ],
                                        [
                                            "cfe8590f.43a8e8"
                                        ],
                                        [
                                            "baafd858.a86a98"
                                        ]
                                    ]
                                },
                                {
                                    "id": "baafd858.a86a98",
                                    "type": "workflow out",
                                    "z": "cb80dcfe.45aae",
                                    "name": "",
                                    "form": "",
                                    "state": "completed",
                                    "removestate": false,
                                    "x": 670,
                                    "y": 500,
                                    "wires": [
                                        []
                                    ]
                                },
                                {
                                    "id": "46767982ec77ca97",
                                    "type": "debug",
                                    "z": "cb80dcfe.45aae",
                                    "name": "",
                                    "active": true,
                                    "tosidebar": true,
                                    "console": false,
                                    "tostatus": false,
                                    "complete": "false",
                                    "x": 350,
                                    "y": 420,
                                    "wires": []
                                },
                                {
                                    "id": "09d847482f123875",
                                    "type": "function",
                                    "z": "cb80dcfe.45aae",
                                    "name": "",
                                    "func": "if(!msg.payload) msg.payload = {}\nif(!msg.payload.values) msg.payload.values = {}\nmsg.payload.values.select = [\n    {\"label\": \"Allan\", \"value\": \"allan\"},\n    {\"label\": \"Lone\", \"value\": \"lone\"},\n    {\"label\": \"Lars\", \"value\": \"lars\"},\n    ]\nreturn msg;",
                                    "outputs": 1,
                                    "noerr": 0,
                                    "initialize": "",
                                    "finalize": "",
                                    "libs": [],
                                    "x": 340,
                                    "y": 480,
                                    "wires": [
                                        [
                                            "8038a1b1.874cf"
                                        ]
                                    ]
                                }
                            ]
                            

                            Edit json on select
                            687126c0-291a-4a9b-87b6-2f7c2869b897-image.png

                            {
                              "label": "Select",
                              "widget": "choicesjs",
                              "tableView": true,
                              "key": "select",
                              "type": "select",
                              "input": true
                            }
                            

                            Gives this form
                            d8031134-4f1f-42b8-842d-ac7f9e3a02b4-image.png

                            C 1 Reply Last reply Reply Quote 1
                            • C
                              Colby Cruwys @Allan Zimmermann last edited by

                              Thank you so much @allan-zimmermann! When I go back to work tomorrow I can show my bosses a neat POC with various elements.

                              ELEMENT #1: Robot that creates a CSV with always accurate Student information

                              I have the building blocks for a theoretical robot that can extract a CSV import from somewhere and sanitise it into a simple student list that is stored in a location of our choosing. Currently I'm having that all run on my local machine at home because I don't yet have approval to install OpenIAP at work (which I'm sure this POC will now allow):
                              d8eee4db-24c5-44bd-aec3-7aad16058688-image.png

                              ELEMENT #2: Robot that reads the CSV into a DataTable

                              This is only a temporary solution while I don't have OpenIAP installed on my work machine but since I want the app.openiap.io demo environment to demonstrate this POC, I needed a way to have it collect the CSV file from a non-web location. This works a treat (provided I have my home machine on and OpenRPA running):
                              df134a98-c506-4b07-8e24-2e6b74ca3828-image.png

                              ELEMENT #3 Populate a WebForm Select Component with always accurate Student Information

                              For this I'm running a NodeRED Flow that is triggered from OpenFlow that will collect the data from my robot and then insert it into the WebForm I created.

                              The Flow looks like this:
                              9ca9dbc5-de10-48b2-ab03-d9904787c096-image.png

                              The code in my function looks like this (it's just a POC, I'll make this better later :-):
                              d688848d-cc82-42a3-b5e9-1e1e0d0bb325-image.png

                              And when I run the Form WorkFlow from OpenFlow, I now get Select Options that list the names from an always correct list of Students (all fake data for now):
                              e56334b9-ce20-4aa2-9ed7-bad3629bf3f7-image.png

                              With this POC I'm confident I can get approval to start exploring exactly what our College can do with OpenIAP. Thank you so much @allan-zimmermann for your tips and advice, I'm going to explore the other things you've spoken about above (workitems and item templates for instance)

                              BTW the reason my attempt didn't work is that my Select Component was inside a Panel Component. I'm still not sure how to rectify that programmatically but it doesn't matter for this POC anyway.

                              Allan Zimmermann 1 Reply Last reply Reply Quote 1
                              • Allan Zimmermann
                                Allan Zimmermann @Colby Cruwys last edited by

                                Hi @colby-cruwys Thank you the the explanation of your PoC. I hope you succussed in convincing your stake holders 🙂
                                2 small notes

                                1. You should remove the "create datatable" before read range. Read range will create the datatable.
                                2. app.openiap.io is not a demo environment, but you are free to use it as such.
                                1 Reply Last reply Reply Quote 1
                                • First post
                                  Last post