duplicate a Numbers's sheet ?

As the function DUPLICATE refuse to duplicate a sheet, I tried to use GUI scripting.

With this script:

--[SCRIPT]
set mySheet to "Name1"
tell application "Numbers" to activate

tell application "System Events" to tell (first process whose title is "Numbers")
	tell window 1 to tell splitter group 1 to tell splitter group 1 to tell scroll area 1 to tell outline 1
		
		get properties of UI elements
		
		set nbr to get count of rows
		set sheetPos to {0, 0}
		
		repeat with r from 1 to nbr
			tell static text 1 of row r
				if value is mySheet then
					set sheetPos to position
					exit repeat
				end if
			end tell -- static text 1 of row r
		end repeat
		if sheetPos is {0, 0} then error "the "" & mySheet & "" is missing ! "
		--click static text 1 of row r
		set value of attribute "AXFocused" of static text 1 of row r to true
		delay 0.1
		click static text 1 of row r
		--keystroke "d" using {command down}
	end tell -- outline .
end tell

--[/SCRIPT]

I am able to put the focus on the thumbnails dedicated to the sheet whose name is defined by mySheet.

Alas after that, the menu Duplicate remains grayed so I can’t apply the keystroke command to duplicate the sheet.

Is one of you able to tell what is wrong ?

Yvan KOENIG (from FRANCE vendredi 20 février 2009 22:41:21)

Thanks
but you read too fast.

I’m not trying to duplicate a table but a sheet. :wink:
And of course as the goal is to create 60 copies of the original sheet, triggering the name by hand is not an option.

Oops, I was fooled by the fact that you named the variable “aTable”.
In fact it duplicate perfectly the sheet.

THANKS.

But
is there a way to get rid of the requirement: an item must be already selected in the thumbnails area ?
When the selection is in the main window the script’ log states

get focused of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 of process 1 whose title = “Numbers”
false
set focused of outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1 of process 1 whose title = “Numbers” to true
"the “theSheet” is missing ! "

So, I made some changes and now it works.

--=====

property theApp : "Numbers"

--=====

my duplicateSheet("theSheet", "Clément")
my duplicateTable("Feuille 1", "Tableau 2", "La Joconde")

--=====

on duplicateSheet(sourceSheet, newName)
	tell application "Numbers"
		activate
		tell document 1 to set lesFeuilles1 to name of sheets
	end tell
	if sourceSheet is not in lesFeuilles1 then
		if my parleFrancais() then
			error "La feuille "" & sourceSheet & "" n'existe pas ! "
		else
			error "The sheet "" & sourceSheet & "" is missing ! "
		end if
	end if
	(*
Calculates the index of the source sheet name in the thumbnails area.
A sheet may have the same name than a table *)
	if newName is not in lesFeuilles1 then
		tell application "Numbers" to tell document 1
			set indx to 0
			repeat with s from 1 to count of lesFeuilles1
				set indx to indx + 1
				set nSheet to item s of lesFeuilles1
				if nSheet is sourceSheet then
					exit repeat
				else
					set indx to indx + (count of tables of sheet nSheet)
				end if
			end repeat
		end tell (*
here indx is the index of the source sheet in the list of rows *)
		
		tell application "System Events" to tell (first process whose title is "Numbers")
			tell outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1
				select row 1
				set value of attribute "AXFocused" to true
				select row indx
			end tell
			keystroke "d" using command down
		end tell
		
		tell application "Numbers" to tell document 1
			set lesFeuilles2 to name of sheets
			repeat with f in lesFeuilles2
				if f is not in lesFeuilles1 then
					set name of sheet f to newName
					exit repeat
				end if
			end repeat
		end tell
	end if -- newName is not
end duplicateSheet


--=====

on duplicateTable(sourceSheet, sourceTable, newName)
	tell application "Numbers"
		activate
		tell document 1
			set lesFeuilles1 to name of sheets
			if sourceSheet is in lesFeuilles1 then
				tell sheet sourceSheet to set lesTables1 to name of tables
				if sourceTable is not in lesTables1 then
					if my parleFrancais() then
						error "La table "" & sourceTable & "" de la feuille "" & sourceSheet & "" n'existe pas ! "
					else
						error "The sheet "" & sourceTable & "" of sheet "" & sourceSheet & "" is missing ! "
					end if
				end if -- sourceTable is not
			else
				if my parleFrancais() then
					error "La feuille "" & sourceSheet & "" n'existe pas ! "
				else
					error "The sheet "" & sourceSheet & "" is missing ! "
				end if
			end if -- sourceSheet is in
		end tell -- document
	end tell -- application 
	(*
Calculates the index of the source table name in the thumbnails area.
A sheet may have the same name than a table *)
	if newName is not in lesTables1 then
		tell application "Numbers" to tell document 1
			set indx to 0
			set found to false
			repeat with s from 1 to count of lesFeuilles1
				set indx to indx + 1 (* add the sheet's row *)
				set nSheet to item s of lesFeuilles1
				if nSheet is sourceSheet then
					repeat with t from 1 to count of lesTables1
						set indx to indx + 1 (* add the table's row *)
						if item t of lesTables1 = sourceTable then
							set found to true
							exit repeat
						end if
					end repeat
				else
					set indx to indx + (count of tables of sheet nSheet) (* add every rows of the sheet *)
				end if
				if found then exit repeat
			end repeat
		end tell (* 
			here indx is the index of the source table in the list of rows *)
		
		tell application "System Events" to tell (first process whose title is "Numbers")
			tell outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1
				select row 1
				set value of attribute "AXFocused" to true
				select row indx
			end tell
			keystroke "d" using command down
		end tell
		
		tell application "Numbers" to tell document 1 to tell sheet sourceSheet
			set lesTables2 to name of tables
			repeat with t in lesTables2
				if t is not in lesTables1 then
					set name of table t to newName
					exit repeat
				end if
			end repeat
		end tell
	end if -- newName is not
end duplicateTable

--=====

on parleFrancais()
	local z
	try
		tell application theApp to set z to localized string "Cancel"
	on error
		set z to "Cancel"
	end try
	return (z = "Annuler")
end parleFrancais

--=====


Yvan KOENIG (from FRANCE samedi 21 février 2009 11:33:04)

The late script assumed that every sheet was ‘expanded’ in the thumbnails area.
Here is an enhanced version which requires that only for the sheet containing the table to be duplicated.

--[SCRIPT duplicate Sheet and Table]

(*
CAUTION:
the sheet containing the table to be duplicated MUST be 'expanded' !
 
Yvan KOENIG (Vallauris, FRANCE)
21 février 2009
*)

--=====

property theApp : "Numbers"

--=====

my duplicateSheet("theSheet", "Clément")
my duplicateTable("Feuille 1", "Tableau 2", "La Joconde")

--=====

on duplicateSheet(sourceSheet, newName)
	local lesFeuilles1, listOfRows, i, itmI, lesFeuilles2
	tell application "Numbers"
		activate
		tell document 1 to set lesFeuilles1 to name of sheets
	end tell -- Numbers
	
	if sourceSheet is not in lesFeuilles1 then
		if my parleFrancais() then
			error "La feuille "" & sourceSheet & "" n'existe pas ! "
		else
			error "The sheet "" & sourceSheet & "" is unavailable ! "
		end if -- my parleFrancais
	end if -- sourceSheet
	
	if newName is not in lesFeuilles1 then
		(* 
Now, an ugly workaround to duplicate the sheet *)
		tell application "System Events" to tell (first process whose title is "Numbers")
			tell outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1
				select row 1
				set value of attribute "AXFocused" to true
				set listOfRows to name of static text of every row
				repeat with i from 1 to count of listOfRows (*
We know that there is a sheet named sourceSheet
but maybe there is a table with the same name.
We check that we are really pointing the sheet item.  *)
					set itmI to item 1 of item i of listOfRows
					if (itmI = sourceSheet) and my isItAsheet(itmI) then
						select row i
						exit repeat
					end if -- my isItAsheet.
				end repeat
			end tell -- outline
			keystroke "d" using command down
		end tell -- application
		(*
Rename the new sheet according to the passed name: newName *)
		tell application "Numbers" to tell document 1
			set lesFeuilles2 to name of sheets
			repeat with i in lesFeuilles2
				if i is not in lesFeuilles1 then (*
Here i is the name of the newly created sheet *)
					set name of sheet i to newName
					exit repeat
				end if -- i is not.
			end repeat
		end tell -- document 1 of Numbers
	end if -- newName is not.
end duplicateSheet

--=====

on duplicateTable(sourceSheet, sourceTable, newName)
	local lesFeuilles, lesTables1, found, listOfRows, cor, i, nameI, j, lesTables2
	tell application "Numbers"
		activate
		tell document 1
			set lesFeuilles to name of sheets
			if sourceSheet is in lesFeuilles then
				tell sheet sourceSheet to set lesTables1 to name of tables
				if sourceTable is not in lesTables1 then
					if my parleFrancais() then
						error "La table "" & sourceTable & "" de la feuille "" & sourceSheet & "" n'existe pas ! "
					else
						error "The sheet "" & sourceTable & "" of sheet "" & sourceSheet & "" is unavailable ! "
					end if
				end if -- sourceTable is not
			else
				if my parleFrancais() then
					error "La feuille "" & sourceSheet & "" n'existe pas ! "
				else
					error "The sheet "" & sourceSheet & "" is unavailable ! "
				end if
			end if -- sourceSheet is in
		end tell -- document
	end tell -- application
	
	if newName is not in lesTables1 then
		tell application "System Events" to tell (first process whose title is "Numbers")
			tell outline 1 of scroll area 1 of splitter group 1 of splitter group 1 of window 1
				select row 1
				set value of attribute "AXFocused" to true
				set found to false
				set listOfRows to name of static text of every row (* CAUTION, it's a list of lists !
{{"Feuille 2"}, {"Tableau 1"}, {"theSheet"}, {"Feuille 1"}, {"Tableau 2"}, {"Clément"}, {"Feuille 4"}} *)
				set cor to count of listOfRows
				repeat with i from 1 to cor (*
Scan the thumbnails *)
					set nameI to (item 1 of item i of listOfRows)
					if (sourceSheet = nameI) and my isItAsheet(nameI) then (*
Here we reached the thumbnail of sourceSheet *)
						if (i < cor) and not my isItAsheet(item 1 of item (i + 1) of listOfRows) then (*
Here we may scan the thumbnails of tables of sourceSheet *)
							repeat with j from i + 1 to i + (count of lesTables1)
								if sourceTable = item 1 of item j of listOfRows then
									select row j
									set found to true
									exit repeat
								end if -- sourceTable
							end repeat
						else
							if my parleFrancais() then
								error "La table "" & sourceTable & "" de la feuille "" & sourceSheet & """ & return & " n'est pas affichée dans les vignettes ! "
							else
								error "The sheet "" & sourceTable & "" of sheet "" & sourceSheet & """ & return & " is not revealed in thumbnails ! "
							end if -- my parleFrancais
						end if -- i < .
					end if -- (sourceSheet = 
					if found then exit repeat
				end repeat -- i
			end tell -- outline .
			keystroke "d" using command down
		end tell -- System Events.
		
		tell application "Numbers" to tell document 1 to tell sheet sourceSheet
			set lesTables2 to name of tables
			repeat with i in lesTables2
				if i is not in lesTables1 then (*
Here i is the name of the newly created table *)
					set name of table i to newName
					exit repeat
				end if
			end repeat
		end tell
	end if -- newName is not.
end duplicateTable

--=====

on isItAsheet(s)
	try
		tell application "Numbers" to tell document 1
			count of tables of sheet s (* 
Post an error if s is not a sheet *)
		end tell
		return true
	on error
		return false
	end try
end isItAsheet

--=====

on parleFrancais()
	local z
	try
		tell application theApp to set z to localized string "Cancel"
	on error
		set z to "Cancel"
	end try
	return (z = "Annuler")
end parleFrancais

--=====
--[/SCRIPT]

Yvan KOENIG (from FRANCE lundi 23 février 2009 15:42:46)