The AddRow method requires a table reference and a column reference. If a table alias is created using WithName, said alias works as a table target, but column references on that table cause AddRow to fail.
See here:
The AddRow method requires a table reference and a column reference. If a table alias is created using WithName, said alias works as a table target, but column references on that table cause AddRow to fail.
See here:
Hi @Christian_Rodriguez3,
it’s a good point and it needs some clarification; but I don’t think this is a bug.
The WithName()
function does take the value of the expression.
In your case, [Ex. WithName].WithName(exName, exName)
→ exName
is the actual instance of the table; i.e. the full set or rows (and therefore you can access all its properties).
However - as you correctly pointed out - when referring to a column in the typical [Table].[Column]
syntax, [Table]
(and [Column]
) is an object reference (not its value).
(You can omit the table reference at all, if there are not naming conflicts).
[Ex. WithName].AddRow(
[Ex. WithName].[Col 1], // or simply [Col 1] - is the column reference
4
)
and
[Ex. WithName].WithName(exTable,
extTable.AddRow( // here it's valid because you are adding a row to a set of rows (the value of exTable)
[Col 1], 4
)
)
To better clarify:
[Ex WithName].[Col 1]
as first parameter, is an object reference[Ex WithName].[Col 1]
→ is a list of [Col 1]
values extTable.[Col 1]
→ always outputs a list of [Col 1]
values (as above).I hope this helps.
Cheers!
Yeah @Federico.Stefanato has the right of it. Although, I’m also bummed by this. Wish Coda could identify when I mean a pointer and when I mean a value. Clearly, if I’m putting something in the first slot of AddRow
I mean a pointer to a column.
Thanks for the response. If I understand the argument you’re making correctly, I still think the behavior is inconsistent. Apologies in advance if I’m missing or misunderstanding!
This is the signature of the AddRow method. In this context, it expects that expressions passed for the table
and column
are both references:
AddRow(table <reference>, column <reference>, columnValue)
You stated that:
The
WithName()
function does take the value of the expression.
So here’s the question: why is the value of a table an instance of that table (which is still a reference to the table) but the value of a column is just the list of its rows and not an instance of that column?
For consistent behavior I would assume that both are either “passed by value” / greedily evaluated or both are “passed by reference” / lazily evaluated based on the context in which the expression is used.
Put more clearly (I hope):
WithName(Table,...)
returns a shallow copy (i.e. duplicate table data instead of create table view) whose data can be accessed, but changes made to the copy don’t impact the original table
WithName(Column,...)
returns a shallow copy of the column whose data can be accessed (current behavior)
WithName(Table,...)
returns a pointer to a table whose data can be accessed and any changes made to it do impact the original table (current behavior)
WithName(Column,...)
returns a pointer to the column and depending on the context may be used as a pointer (like for AddRow) or for its values (for lookups, filters, etc).
It may be the case that there is no “value / shallow copy” version of a table, only views or new tables, and that’s why the behavior seems to make sense from your perspective, but to me it looks like WithName
is behaving inconsistently.
Hi @Christian_Rodriguez3,
sorry for the late reply.
I recognize there is a misunderstanding: every time you have the same notation for different purposes, the risk of this happening is high…
I’m not finding that specific signature for the AddRow()
method
In the Formula Reference, we have AddRow(table, column, columnValue)
.
The table
parameter is actually an instance, i.e. a set of rows of the same table: as a matter of fact, you can have a View or the result of a Filter()
and access all rows operations (AddRow()
, AddOrModifyRows()
, DeleteRows()
).
Meaning that:
MyTable.Filter(...).ModifyRows(column, ColumnValue)
and
MyTable.Filter(...).withName(myTable,
myTable.ModifyRows(column, ColumnValue)
are the same thing.
On the other hand, the column
parameter is indeed a reference to its meta-information.
And the only way to get its reference is through the notation [Base Table Name].[Column Name]
.
You can’t even using a [View Name].[Column Name]
for that table (you can try and you’ll get an error saying “AddRow expects parameter column to be a column, but found value” for that specific reason).
This is maybe the crucial point of the misunderstanding:
Anywhere else if you use [Base Table Name].[Column Name]
, you’ll get a list of Column Name
values.
However, within [Modify-|AddOrModify-|AddRow-]s()
methods - as a column parameter - it has a different meaning.
But it’s not WithName()
's fault per se, it’s this single way to address two things related to a column.
I hope I clarified the point and not messed up things worse.
I was also expecting lazy evaluation. What I thought would happen is that Coda would say, “Hey, looks like you referenced a column, I’ll hold onto that for you.”
And then when I went to use the column in a non-action formula it would say something to me like, “Ohh… you want to use formulas on the data. Let me go grab the list of data for you.”
But of course, if I were to use that column reference in an action like AddRow
I expect it to instead say, “Ha! This formula requires a reference to a table. I’ll pass the reference itself instead of grabbing the data that the reference points to.”
Hi guys, I’m reviving this topic to discuss something I went through using WithName and maybe it is related.
In a simple test,
WithName(Concatenate("AB,C",",1,23").Split(","),list, list.Nth(4))
Is going to output: 23
So far so good, and if I do this
WithName(Concatenate("A,B",",C,D",",E,F").Split(","),oneList,
WithName(Concatenate("A,B",",C,D").Split(","),anotherList ,
oneList.contains(anotherList.Nth(4))))
It outputs true!
But when I use it to store values from a list of lists, or rather all values from a table with their values splitted split()
, it behaves differently. I’ll share the document, but here is the main thing:
Every row has an address (like 1.7.14 or 1.43.67). I want to select all the children that have the selected row’s last address ( so 1.43.67 would look for addresses that have 67 in them, aka the children and below)
Then I tried to store some lists with WithName. Below is a formula that shows the rows related to a “zoomed” row.
//store a list with addresses turned to a list
WithName([Sorted Table 2].Address.Split("."), addresses,
//store the address of the zoomed row as a list
WithName([Sorted Table 2].Filter([zoom toggle]).First().Address.Split("."), thisAddress,
If(
//if the lookup has all selected
[filter lookup control].Count() = [Sorted Table 2].Count(),
"all"
,//else
// this part right here is where the problems starts, using the stored values it outputs everything
Filter([Sorted Table 2], addresses.Contains(thisAddress.Nth(thisAddress.Count())))
// but splitting the address in the iterations of currentValues, like below, then it works
Filter([Sorted Table 2], Address.Split(".").Contains(thisAddress.Nth(thisAddress.Count())))
)
)
)
I wonder if this is because WithName stores lists of lists as a listCombine or something?
Should I try to use different separators?
Thanks
Here is the doc