Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Numbers applescript copy paste (confirm)

Scenario: using applescript, with iWork 09, I just want to copy the contents of one table in one sheet from one numbers file to the second column of a table in another sheet in an existing numbers file.

I've read through and understand Yvan's utility for copy and paste and setting basic values in the post below, but I would like to confirm there's no easier way - something like "set the value of cell 2 of row 2 to (thetableIselected overthere).. ?

http://discussions.info.apple.com/thread.jspa;jsessionid=1D206B51803204C500A5C6C F4A5832D3.node0?messageID=11543511&#11543511

It's very surprising that with all the functionality of Applescript, they didn't implement simple commands like "copy" and "paste" - but, I've only been working with it for a few days, am I missing something?

Background: I've developed a basic script to grab extended Yahoo Quotes into a csv file using Yahoo's api, and open the quote results in Numbers (if you save the file as a .csv extension, Numbers nicely automatically parses it.) Now I simply want to append each row of the quotes table to the original table with the list of symbols I'm tracking (which are in column 1).

FC

Macbook Pro (13"), Mac OS X (10.6.4)

Posted on Oct 13, 2010 11:39 AM

Reply
6 replies

Oct 13, 2010 12:46 PM in response to FlyingCircus10

What you describe may be done easily with this kind of script :

--

set document_source to "Document1.numbers"
set feuille_source to "Feuille 1"
set table_source to "Tableau 1"
set colonne_source to 5
set ligne_source to 3
set document_destination to "Document2.numbers"
set feuille_destination to "Feuille 2"
set table_destination to "Tableau 5"
set colonne_destination to 6
set ligne_destination to 5
set nbr to 10 -- number of cells to copy/paste
tell application "Numbers"
tell document document_source to tell sheet feuille_source to tell table table_source
set les_valeurs to value of cells ligne_source thru (ligne_source + nbr - 1) of column colonne_source
end tell -- document…

tell document document_destination to tell sheet feuille_destination to tell table table_destination
tell column colonne_destination
repeat with r from 1 to nbr
set value of cell (ligne_destination + r - 1) to item r of les_valeurs
end repeat
end tell -- column
end tell -- document…

end tell -- Numbers
--


In this bare draft, I make no check upon the availability of two opened numbers documents named document_sources and document_destination.
I make no check upon the availability of table table_source sheet feuille_source of document document_source.
I make no check upon the availability of table table_destination sheet feuille_destination of document document_destination.
I make no check upon the existence of nbr cells starting from row ligne_source in column colonne_source.
I make no check upon the existence of nbr cells starting from row ligne_destination in column colonne_destination.

I don't take care of possible blank cells in the source range.
If some of them exist, the destination cell will not be blank but will contain 0.0.

You may use this kind of script.
I just dislike such ones.

The unique advantage of such scripts (I already posted some of them but it seems that you missed them), is that they doesn't require that the source table and/or the target one are visible.

In most of the scripts which I post, the parameters describing the manipulated objects are extracted on the fly. The values are not "set" but transferred thru Copy then Paste Applying Style.
Doing that, a blank cell remains a blank cell.
The counterpart is that I must use GUI Scripting and use a bit complicated pieces of code to make the manipulated objects visibles because GUI scripting requires that.

You are free to use the scheme which you want.
I feel free to write the kind of scripts which I feel better.

Search in the area "Numbers '09" in the range "All" with the keystring "script AND koenig" and you will find several scripts working on two documents. I wrote koenig, not yvan because this way you will not get links to thread in which my scripts are simply named by a helper.

In the returned scripts, you will find some embedded pieces of code checking what I didn't check in the one passed today. In some, datas are passed with "get value" and "set value" as I did here. In most of them, they are passed with Copy / Paste.

From my point of view, the best script is the one which match the needs of the user.
When I worked as a potter I made only what I decided to do, never taking care of customers requirements.
When I build a script, I try to give an efficient response to the askers problem, but I feel free to apply my own choices. As the scripts which I post are signed with my true name, not with a pseudo, I have to preserve my dignity. I'm fond of well done job.

Yvan KOENIG (VALLAURIS, France) mercredi 13 octobre 2010 21:46:03
You will find in them the pieces of code required by the checks which I didn't coded here.

Oct 13, 2010 1:02 PM in response to KOENIG Yvan

Here is a slightly modified version.

--

--[SCRIPT barescriptv2]
(*
Yvan KOENIG (VALLAURIS, France)
2010/10/13
*)
property les_valeurs : {}
on run
set document_source to "Document1.numbers"
set feuille_source to "Feuille 1"
set table_source to "Tableau 1"
set colonne_source to 5
set ligne_source to 3

set document_destination to "Document2.numbers"
set feuille_destination to "Feuille 2"
set table_destination to "Tableau 5"
set colonne_destination to 6
set ligne_destination to 5

set nbr to 10 -- number of cells to copy/paste

tell application "Numbers"
tell document document_source to tell sheet feuille_source to tell table table_source
set my les_valeurs to value of cells ligne_source thru (ligne_source + nbr - 1) of column colonne_source
end tell -- document…

tell document document_destination to tell sheet feuille_destination to tell table table_destination
tell column colonne_destination
set r to 0
repeat with une_valeur in my les_valeurs
set value of cell (ligne_destination + r) to une_valeur
set r to r + 1
end repeat
end tell -- column
end tell -- document…

end tell -- Numbers
set my les_valeurs to {}
end run
--[/SCRIPT]
--


(1) it defines the list les_valeurs as a property which is an efficient way to fasten execution as long as the script triggers the list with the prefix my.

(2) it use a different structure for the loop setting the values in the target table.
This loop doesn't use an index to extract values from the list of extracted values.
It use the structure "repeat with une_valeur in my les_valeurs.
This kind of loop is faster than the ones using an index.
Here, the benefit is partially dropped by the fact that we must index the target cells
but, if the number of values to transfer is large, it will be time saver.

Don't forget, this kind of script is really more efficient if the source and the target tables aren't visibles.
If you may, reveal other sheets so that the used tables being invisibles, the script will run faster (I often see the speed doubled or tripled with such a tip).

Yvan KOENIG (VALLAURIS, France) mercredi 13 octobre 2010 22:01:30

Oct 13, 2010 7:56 PM in response to FlyingCircus10

For posterity, I used that pattern to get a working script. Readers should be aware, if it's not obvious, that the example copies one column of data, cell-wise. For my use case, I put a repeat loop around the process, to step through multiple columns. A user could transpose the logic of rows and columns and do it to step row by row.

FC

Oct 14, 2010 12:05 AM in response to FlyingCircus10

Here is an enhanced version which copy several rows of several columns.

--

--[SCRIPT barescriptv3]
(*
Yvan KOENIG (VALLAURIS, France)
2010/10/13
*)
property les_valeurs : {}
on run
set document_source to "Document1.numbers"
set feuille_source to "Feuille 1"
set table_source to "Tableau 1"
set colonne_source to 5
set ligne_source to 3

set document_destination to "Document2.numbers"
set feuille_destination to "Feuille 2"
set table_destination to "Tableau 5"
set colonne_destination to 6
set ligne_destination to 5

set nb_lignes to 10 -- number of cells to copy/paste
set nb_colonnes to 3 -- number of columns to paste

tell application "Numbers"
tell document document_source to tell sheet feuille_source to tell table table_source
set my les_valeurs to value of cells colonne_source thru (colonne_source + nb_colonnes - 1) of rows ligne_source thru (ligne_source + nb_lignes - 1)
end tell -- document…

tell document document_destination to tell sheet feuille_destination to tell table table_destination

set r to 0
repeat with une_ligne in my les_valeurs
tell row (ligne_destination + r)
set c to 0
repeat with une_valeur in une_ligne
set value of cell (colonne_destination + c - 1) to une_valeur
set c to c + 1
end repeat -- column
end tell -- row
set r to r + 1
end repeat -- row

end tell -- document…

end tell -- Numbers
set my les_valeurs to {}
end run
--[/SCRIPT]
--


The range is supposed to be a monolithic one.

Yvan KOENIG (VALLAURIS, France) jeudi 14 octobre 2010 09:04:50

Oct 15, 2010 2:03 AM in response to KOENIG Yvan

Here is a version with the checks missing in the first versions.

--

--[SCRIPT fromdoc1_todoc2]
(*
Enregistrer le script en tant que Script : fromdoc1_todoc2.scpt
déplacer le fichier ainsi créé dans le dossier
<VolumeDeDémarrage>:Users:<votreCompte>:Library:Scripts:Applications:Numbers:
Il vous faudra peut-être créer le dossier Numbers et peut-être même le dossier Applications.
Les documents document_source et document_destination doivent être ouverts.
document_source doit contenir la feuille feuille_source qui doit contenir la table table_source.
document_destination doit contenir la feuille feuille_destination qui doit contenir la table table_destination.
Numbers est lent lorsqu'il travaille sur une table visible,
le script est plus efficace si les tables manipulées ne sont pas visibles !
Aller au menu Scripts , choisir Numbers puis choisir fromdoc1_todoc2
--=====
L'aide du Finder explique:
L'Utilitaire AppleScript permet d'activer le Menu des scripts :
Ouvrez l'Utilitaire AppleScript situé dans le dossier Applications/AppleScript.
Cochez la case "Afficher le menu des scripts dans la barre de menus".
Sous 10.6.x,
aller dans le panneau "Général" du dialogue Préférences de l'Éditeur Applescript
puis cocher la case "Afficher le menu des scripts dans la barre des menus".
--=====
Save the script as a Script: fromdoc1_todoc2.scpt
Move the newly created file into the folder:
<startup Volume>:Users:<yourAccount>:Library:Scripts:Applications:Numbers:
Maybe you would have to create the folder Numbers and even the folder Applications by yourself.
The documents document_source and document_destination must be open.
document_source must contain the sheet feuille_source which much contain the table table_source.
document_destination must contain the sheet feuille_destination which much contain the table table_destination.
Numbers is slow when it works on a visible table so, the script is more efficient if the tables to use aren't visibles !
Go to the Scripts Menu, choose Numbers, then choose "fromdoc1_todoc2"
--=====
The Finder's Help explains:
To make the Script menu appear:
Open the AppleScript utility located in Applications/AppleScript.
Select the "Show Script Menu in menu bar" checkbox.
Under 10.6.x,
go to the General panel of AppleScript Editor’s Preferences dialog box
and check the “Show Script menu in menu bar” option.
--=====
Yvan KOENIG (VALLAURIS, France)
2009/10/15
*)
--=====
(* Edit these twelve properties to fit your needs *)
property document_source : "Document1.numbers"
property feuille_source : "Feuille 1"
property table_source : "Tableau 1"
property colonne_source : 5
property ligne_source : 3
property document_destination : "Document2.numbers"
property feuille_destination : "Feuille 2"
property table_destination : "Tableau 5"
property colonne_destination : 6
property ligne_destination : 5
property nb_lignes : 10 -- number of rows to read/insert
property nb_colonnes : 3 -- number of columns to read/insert
--=====
property les_valeurs : {}
--=====
on run
local availables, message1, message2, c, r, une_ligne, une_valeur

tell application "Numbers"
activate
set availables to name of documents
set message1 to ""
if document_source is not in availables then
set message1 to "The document " & document_source & " is not open !" & return
else
tell document document_source
if feuille_source is not in (name of sheets) then set message1 to "the sheet " & feuille_source & " is unavailable in the document " & document_source & " !" & return
tell sheet feuille_source
if table_source is not in (name of tables) then set message1 to "The table " & table_source & " is unavailable in the sheet " & feuille_source & " of the document " & document_source & " !" & return
end tell -- feuille_source
end tell -- document source
end if -- document_source…

set message2 to ""
if document_destination is not in availables then
set message2 to "The document " & document_destination & " is not open !"
else
tell document document_destination
if feuille_destination is not in (name of sheets) then set message2 to "the sheet " & feuille_destination & " is unavailable in the document " & document_destination & " !"
tell sheet feuille_destination
if table_destination is not in (name of tables) then set message2 to "The table " & table_destination & " is unavailable in the sheet " & feuille_destination & " of the document " & document_destination & " !"
end tell -- feuille_destination
end tell -- document _destination
end if -- document_destination…
if (message1 > "") or (message2 > "") then error (message1 & message2)

tell document document_source to tell sheet feuille_source to tell table table_source
set my les_valeurs to value of cells colonne_source thru (colonne_source + nb_colonnes - 1) of rows ligne_source thru (ligne_source + nb_lignes - 1)
end tell -- document source…

tell document document_destination to tell sheet feuille_destination to tell table table_destination
(*
Add rows if necessary *)
set c to row count
set r to ligne_destination + nb_lignes - 1
if c < r then
repeat (r - c) times
add row below row -1
end repeat
end if
(*
Add columns if necessary *)
set c to column count
set r to colonne_destination + nb_colonnes - 1
if c < r then
repeat (r - c) times
add column after column -1
end repeat
end if

set r to 0
repeat with une_ligne in my les_valeurs
tell row (ligne_destination + r)
set c to 0
repeat with une_valeur in une_ligne
set value of cell (colonne_destination + c - 1) to une_valeur
set c to c + 1
end repeat -- column
end tell -- row
set r to r + 1
end repeat -- row
end tell -- document _destination…
end tell -- Numbers
set my les_valeurs to {}
end run
--=====
--[/SCRIPT]
--


Yvan KOENIG (VALLAURIS, France) vendredi 15 octobre 2010 11:03:00

Numbers applescript copy paste (confirm)

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.