Today's logic problem: I'm looking to dynamically generate an ncolumnta

Today's logic problem: I'm looking to dynamically generate an ncolumntable() for use in HTML documentation. For example, we collect task history in SQL and like to attach this in HTML emails and audit documents - each process may utilize a different set of history information, so I would like to build this table dynamically based on column header and field inputs, but can't seem to get the code working correctly. The idea is something like this:

load(
local!columns: {"Task","Owner"},
local!fields: {"task","owner"},
local!data: {{task: "Approval",owner: "Jim"},{task: "Submit",owner: "Steve"},{task: "Review",owner: "Joe"}},

ncolumntable(
local!columns,
apply(rule!test_getData(data: local!data, field: _),
local!fields
)
)
)

Where rule!test_getData() is defined simply as (data - Any Type, field - text):

index(ri!data,ri!field,null)

Since ncolumntable() is expecting a different array for each column, the...

OriginalPostID-195148

OriginalPostID-195148

  Discussion posts and replies are publicly visible

  • ... results are not as expected. I've also tried some tests such as returning the individual arrays as comma-delimited strings in test_getData(), then splitting back into arrays in the parent, but no luck there either.

    ncolumntable(
    local!columns,
    apply(fn!split,
    apply(rule!test_getData(data: local!data, field: _),
    local!fields
    ),",")
    )

    I'm missing something here, any input would be appreciated. Thanks!

  • Chris, it seems that you cannot pass a dynamic number of parameters into this function since it expects the parameters to be comma separated arrays of strings and not lists of variant i.e. ncolumn(string[] column_headers, string[] column, string[] column2...) for up to ten columns.

    There are two workarounds I see possible
    1) Make your own expression rule to dynamically generate the HTML (a bit clunky at first but may scale better)
    2) Based off the length of the result of the apply function, create a set of if conditionals and pass the parameters using the index function, i.e.

    local!columnArray: apply(rule!test_getData(data:local!data,field_),local!fields),

    if( length(local!columnArray) = 1,
    ncolumn(local!columns,index(local!columnArray,1,{}),
    if(length(local!columnArray = 2),
    ncolumn(local!columns,index(local!columnArray,1,{}),index(local!columnArray,2,{})),
    ...
    etc.
  • Thanks Matthew. I ended up with a variation of #2, this seems to work for a dynamic amount of columns:

    load(
    local!columns: {"Task","Owner"},
    local!fields: {"task","owner"},
    local!data: {{task: "Approval",owner: "Jim"},{task: "Submit",owner: "Steve"},{task: "Review",owner: "Joe"}},
    local!columnArray: apply(rule!test_getData(data:local!data,field: _),local!fields),
    local!items: length(local!columnArray),

    ncolumntable(
    columnHeaders: local!columns,
    column1: apply(fn!tostring,index(local!columnArray,1,null)),
    column2: if(local!items>1,apply(fn!tostring,index(local!columnArray,2,null)),{}),
    column3: if(local!items>2,apply(fn!tostring,index(local!columnArray,3,null)),{}),
    column4: if(local!items>3,apply(fn!tostring,index(local!columnArray,4,null)),{}),
    column5: if(local!items>4,apply(fn!tostring,index(local!columnArray,5,null)),{}),
    column6: if(local!items>5,apply(fn!tostring,index(local!columnArray,6,null)),{}),
    column7: if(local!items>6,apply(fn!tostring,index(local!columnArray,7,null)),{}),
    column8: if(local!items>7,apply(fn!tostring,index(local!columnArray,8,null)),{}),
    column9: if(local!items>8,apply(fn!tostring,index(local!columnArray,9,null)),{}),
    column10: if(local!items>9,apply(fn!tostring,index(local!columnArray,10,null)),{})
    )
    )
  • Yep that should also work! You can probably use touniformstring() as well instead of applying the tostring function.