Setting columns and rows using column count/ row count in Numbers

I don’t understand this!
If I have a table with 5 columns and invoke the command:

set column count to 3

The column 4th and 5th are deleted. As expected.

If I have a table with 2 columns and invoke the command:

set column count to 3

A 3rd column is added to the table. As expected.

If I have a table with 3 columns and invoke the command:

set column count to 3

An error occurs: Invalid column count. I don’t understand !

The dictionary says “column count: get/set integer The number of columns in the table.

The same occurs with rows.

Interesting. It’s probably just an oversight on the developer’s part. If the current count’s unknown, you’ll have to put in a check for it:

if (column count is not 3) then set column count to 3

I don’t know if it’s better but I’m accustomed to use:

try
	set column count to nbCols
end try

Same behavior with row count.

try
	set row count to nbRows
end try

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 24 aout 2019 14:42:55

This surprises me. The ‘count’ command is almost always read-only, because changing a count of objects almost always implies unspecified and unpredictable behavior. Most developers force users to add or delete objects explicitly; they don’t let them just lop off arbitrary objects or generate new ones implicit by changing the count. I suspect the developer simply forgot to mark ‘count’ as read-only, so what you’re doing is not something s’he expected to allow, or designed the app to handle programmatically. The fact that it works at all is probably happenstance.

But is column count a property, not a command (that is, an application function) designed to add or remove columns? If this is a function, then it throws an error when the user has not indicated what to delete or add. And then the developers specifically introduced this error so that the user corrects his error.

The following code is equivalent to action Add column after of menu:

tell application "Numbers"
	activate
	tell document 1 to tell active sheet to tell table 1
		set column count to column count + 1
	end tell
end tell
tell application "Numbers" to activate

And set column count to column count - 1 is equivalent to action Delete column of menu.

So, if continue, set column count to column count is equivalent to action “Do nothing”, which has no sense and such an action, of course, is not on the menu.

There is a ‘count’ command as part of the standard scripting commands. Column count is a property, sure, but that’s usually interpreted as equivalent to the command ‘count columns of table …’. Usually to add a column we’d say something like ‘make new column at end of columns of table 1’, and we’d remove them with ‘delete column idx’. This is just poor design.

Thanks for the feedback.
The way in which I initially used:

set column count to X
set row count to Y

was a kind of quick re-set of the table structure to the number of columns/rows you need.
Which works fantastic unless you hit the exact current number of columns and/or rows.

It’s one of the “fun” aspects of AppleScript. :slight_smile: Apart from some basic syntax and a few standard keywords, application developers are free to implement their own scripting commands and structures according to the purposes and modi operandi of the applications themselves. I gather though that scriptability is sometimes added as an afterthought fairly late in an application’s development, which can lead to some awkward shoehorning. And developers, like scripters themselves, can have off days. “Non-standard” implementations are things with which we have to learn to deal. :slight_smile:

In the case of Numbers, it’s possible the developers were trying to make it quick and simple to set up a new document from a template or default. To be able simply to specify the number of columns and rows in a table is far less hassle than having to find out how many columns and rows there are already and then create or delete them individually. It’s also faster to let Numbers take care of everything in response to a single command than to micromanage with individual commands, with all the to-ing and fro-ing of events and the housekeeping that involves. But the error when setting a property to a value it already has is clearly unintentional and is probably one the developers could fix if it were brought to their attention.

It’s possible, sure, I don’t deny that. It comes down to a question of whether we think Apple developers (or maybe contractors, in this case) were more likely to forget to mark a scripting property read-only, or to miss the implementation of an unusual situation. The more I think about it, the more I suspect that you’re right — that they were doing this intentionally, and goofed the implementation — but I still think it’s bad design.

The reason I think it’s bad design is this… Say we have a table with a thousand rows and columns (a million cells’ worth of data). Say we have a handler like so:

on someHander(aTable, c)
    [...]
    set aTable's column count to c
end someHander

Then through some mis-design or coding error we send a call to that handler with c=0. Poof: a million data points gone. Or say we have a command the lops off the last ten rows, but then we have routines we occasionally call which reorder the table rows: how are we sure which rows we are actually deleting when we call the command? Data destruction should not be that easy or that arbitrary, and implementing code to check for and prevent this kind of arbitrary data destruction would offset any advantage we get from having a simpler way of adding or deleting rows.

Just sayin’…

on someHander(aTable, c)
	display dialog "Are you really sure sure you want to set the table's column count to " & c & "!?" buttons {"No! Stop!", "Yeah yeah. Relax."} cancel button 1 default button 1 with icon caution
	[...]
	set aTable's column count to c
end someHander

Conjures up a lovely alternative of using a handler for this which deletes or adds only one column at a time and displays the same dialog every single time. :lol:

Well what can I say? With scripting comes potentially destructive power, and with that a certain requirement for responsibility and competence. If you write a script which blindly removes the last ten rows of a table, and you apply it to a table whose contents’ disposition you don’t know, you deserve all you get. :stuck_out_tongue: And if you go on making the same mistake after that, you shouldn’t be scripting.

If that were the only potentially destructive operation, I could almost see your point. But scripting dictionaries are full of potentially destructive things. Does the save command warn you if a file by the same name already exists? Not in any app I’ve ever seen. Yet one little coding error allows you to lose a lot more than a few columns from a table.

In the case of column count, it’s important to have properties like that so that you can create objects using make new whatever with properties…. And yes, you can make properties writeable only at creation time – but in my experience that just creates more confusion.

(No, I haven’t actually used it in Pages. But tables in Adobe InDesign also have a property called column count, which is possibly the inspiration for the name here, and I’ve used it there a lot.)

Having a knife means accepting the possibility that we might cut ourselves, sure. But it’s still bad design to make a knife that slips out of people’s hands easily.

I imagine someone should report the overt bug to Apple, and then we can come back in three years or so (which seems to be Apple’s turn-around on bug fixes) and see which way they fixed it. Beyond that, if you want to see this as my personal aesthetic — i.e., that’s not how I would have designed it — that’s fine. Interface design is art as much as skill.

In fact I assumes that the developper wasn’t thinking that we would try to change the number of rows or columns as you do.
He offered four commands dedicated to these tasks:
[format]add column after v : Add a column to the table after a specified range of cells.
add column after range
→ specifier : A reference to the new column

add column before v : Add a column to the table before a specified range of cells.
add column before range
→ specifier : A reference to the new column

add row above v : Add a row to the table below a specified range of cells.
add row above range
→ specifier : A reference to the new row

add row below v : Add a row to the table below a specified range of cells.
add row below range
→ specifier : A reference to the new row[/format]

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 26 aout 2019 10:26:05

So here’s some further guidance:

https://iworkautomation.com/keynote/table.html

From the bottom of the page:

Interesting, given the author also designed the scripting interface.

Just for see, I tested with a table whose rows 4, 7 and 11 contained datas.
I ran this script:

tell application "Numbers" to tell document 1 to tell sheet 1 to tell table 1
	set row count to 8
end tell

No warning was issued and rows 9, 10, 11,…, 22 were removed.
I was foolishly hoping that it would remove empty rows so that the result would be a table with 8 rows whose 8th contain what was in original row 11.

In fact it did exactly as what would be done by:

tell application "Numbers" to tell document 1 to tell sheet 1 to tell table 1
	remove (rows 9 thru 22)
end tell

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 26 aout 2019 17:35:28

Interesting indeed. It’s possible he didn’t know (or didn’t consider) that read-only properties can be written to during a make command, and thought that he had to leave them as read-write. Or maybe he really did want to leave that resizing option open, but had the same concern I do.

Ah, well… Nothing’s perfect, I suppose.