Transferring Data from dropdowns and numeric entry fields to a query table

I have a view in perspective that is intended to be a way for production workers to submit downtime. I have 2 numeric entry fields and one drop down. I am trying to figure out how to store all the data that is input by the worker into a table in my SQL database whenever the submit button is clicked. Could anyone provide guidance on how I could accomplish this?

Downtime Entry View:

Table "downtime_data":

Structure of table:
image

Overall I'd like the downtime information submitted by the worker to be stored in my "downtime_data" table. I'd like to capture the following information: Downtime reason, downtime in minutes, timestamp of when it was submitted, employee number, ip address of the plc.

Create a named query with an insert statement and parameters for the information you want to log and call that named query from your button action, where you can bind the parameters to your input fields.
I usually do the timestamp on the database side, it will depend on your flavor of sql.

1 Like

Whatever about anything else, t_stamp should be a DATE or DATETIME object.
It might also be useful to,

  1. Add an auto-increment integer field to provide a unique record ID for each row.
  2. Create an index or several indexes on columns or column combinations likely to be used in SELECT queries. It will speed them up.
  3. For IP addresses there are several ways to do this. Saving as text is messy and requires validation unless it's automatic. The most flexible seems to be to save the four octets as TINYINT. See the thread below for more ideas.
    Datatype for IP addresses – SQLServerCentral Forums

This is what I have currently but I can't seem to get the data to store in the table. I'm very new to this type of work in general so I'm having trouble tracing where my error is. If anyone has any suggestions or sees any mistakes I would greatly appreciate it.
PLEASE SELECT A DOWNTIME CODE is named "Code"
PLEASE INPUT AMOUNT OF DOWNTIME (MINUTES) is named "DowntimeMinutes"
PLEASE INPUT EMPLOYEE # is named "EmployeeNumber"

Database Query Browser view:

Named Query View:

Script from onClick even on my "SUBMIT" button

def runAction(self, event):
# Fetch values from your Perspective components
downtimeReason = self.getSibling("Code").props.value
employeeNumber = self.getSibling("EmployeeNumber").props.value
timedown = self.getSibling("DowntimeMinutes").props.value

# Generate the current timestamp
from java.util import Date
tStamp = str(Date())

# Prepare parameters for the named query
params = {
    "Code": downtimeReason,
    "EmployeeNumber": employeeNumber,
    "DowntimeMinutes": timedown,
    "tStamp": tStamp
}

# Run the named query to insert data into the downtime_data table
system.db.runNamedQuery("InsertDowntimeData", params)

Tyler, please see Wiki - how to post code on this forum. Then hit the pencil icon link below your post and format the block of code using the </> button.

1 Like

It looks like you have your parameters and database fields reversed in your named query.
edit:
my mistake, disregard

  1. You don't need to use the Java library. Ignition's built in system.date functions should do everything you need, will be simpler and faster.
  2. Don't convert dates to strings. Keep them in DateTime format for as long as possible.
  3. You did convert your date to a string but your named query is expecting a DateTime parameter.
3 Likes

Tip: this stuff can get ragged quite quickly when you start using nested containers. A simpler, less brittle solution is:

  • Create custom properties on the view for downtimeReason, employeeNumber and timedown.
  • Bind each of the controls on your downtime form bidirectionally to the custom properties.
  • Now reference the custom properties in your script.
    It's much easier to follow, you can move stuff around and you can monitor all the values in Designer in the view's custom properties.
1 Like

Regarding the layout, consider something a bit more polished. Remember that your users are used to Windows / Mac / Android / iOS, etc.

Downtime form

I've opened up the vertical spacing more than the defaults in case you're using touch screen and you have users with phat phingers.

Put an expression binding on the Save button's enabled property so that it only works when all the fields have valid data.

Use the onActionPerformed event on the Save button, not the onClick event. onClick fires whether the button is enabled or not. onActionPerformed only fires when the button is enabled.

Use color sparingly and with purpose. The massive green SUBMIT button in your screengrab is confusing. Why is it green? Is something on? What color will it turn if I press it? Gray (or whatever your theme is) will be fine and the operators will quickly get used to good consistent HMI. Try to make buttons the same size and same location, where appropriate. Note that in my sample the user starts at the top and does four steps in a vertical sequence. Yours requires a horizontal reverse motion to reach the SUBMIT button.

2 Likes

This is the plan for the future. My team is trying to learn how everything works before finalizing any designs. Some very good suggestions that I hadn't thought about yet though so I appreciate it!

Does your second bullet imply that I should bind each value of my dropdown to my custom property I create? @Transistor

No, just the value prop which is the selected value (or null, I think).

Get the team to style as much as possible using the built-in themes and define styles rather than setting styles on individual components. It makes consistency and modification far, far easier. Hammer it into them!

1 Like

I believe I have made all of the modifications you suggested but I am still only getting null values in my table.

Custom property on main view:

Value of each component is bound to corresponding custom property:

Named Query Settings:

updated onActionPerformed event script:

def runAction(self, event):
    # Fetch values from your Perspective components
    downtimeReason = self.custom.Dropdown
    employeeNumber = self.custom.EmployeeNumber
    timedown = self.custom.DowntimeMinutes

    # Generate the current timestamp using Ignition's built-in function
    tStamp = system.date.now()

    # Prepare parameters for the named query
    params = {
        "Code": downtimeReason,
        "EmployeeNumber": employeeNumber,
        "DowntimeMinutes": timedown,
        "tStamp": tStamp
    }

    # Run the named query to insert data into the downtime_data table
    system.db.runNamedQuery("InsertDowntimeData", params)

These 3 things all have to match:

image

image

2 Likes

I have them all matching now and still showing as null. I actually don't even think it's sending to the table anymore.

The have to match every where.

The keys in the parameters dictionary that you send to system.db.runNamedQuery() have to match exactly what you used as the names in the NamedQuery. The parameters also have to match in the query.

change the query to a Select type query and run it in the testing tab and insure you are getting the expected columns and values returned, then check it as an update.


When I execute my named query it will fill the table with 0's. But the actually data I'm inputting is not being sent whenever the submit button is clicked.

Button onActionPerformed script:

def runAction(self, event):

  

  # Fetch values from your Perspective components
    downtimeReason = self.custom.Dropdown
    employeeNumber = self.custom.EmployeeNumber
    timedown = self.custom.DowntimeMinutes

    # Generate the current timestamp using Ignition's built-in function
    tStamp = system.date.now()

    # Prepare parameters for the named query
    params = {
        "Code": downtime_reason,
        "EmployeeNumber": employee_number,
        "DowntimeMinutes": timedown,
        "tStamp": t_stamp
    }

    # Run the named query to insert data into the downtime_data table
    system.db.runNamedQuery("InsertDowntimeData", params)

First, I would expect your Integer values in the DB to be Int4 not Int2.

Second, t_Stamp is not defined, you changed it to tStamp.

Third, your tStamp column in the Database is a REAL, not a Date.

Try:

tStamp = system.date.toMillis(system.date.now())

Add some logging into the script and see if you can find where the script's execution is stopping.

t_stamp is the name of the column in the downtime_data table that the timestamp from ignition should be sent to. I changed values to Int4. I'll play around with some logging.

Sure, but in your script, it's an undeclared identifier. So the value you're sending to the query is most likely None.