Numbers, nulla è impossibile con apple script

numbers

A prima vista Numbers potrebbe sembrare Excel versione bimbo, inoltre sull’ultima versione si ha la senzazione che manchino molte funzioni a differenza dell’interfaccia ribbon di excel in cui ne troviamo millemila sparse nelle varie schede. Chiariamo subito, non farò un paragone di Numbers con excel, credo che il primo sia molto più orientato alla presentazione, piottosto che all’elaborazione dei dati.

Dando un’occhiata più approfondita invece ci si rende conto che Numbers può soddisfare la maggior parte degli utenti, le funzioni matematiche più importanti ci sono tutte e c’è la possibilità di utiilzzare apple script (con Yosemite è possibile usare anche javascript) per creare algoritmi che consentono  la manipolazione dei dati. Di seguito vedremo un esempio.

Supponiamo di avere la seguente tabella:

tabella numbersnella prima colonna possiamo notare la ripetizione di alcuni mesi come febbraio, marzo ecc. A questo punto, ammettiamo di avere l’esigenza che ogni mese compaia una sola volta e  venga associato  alla somma dei valori corrispondenti della colonna costo. Si dovrebbe creare una nuova tabella e fare i calcoli per ogni mese. Pertanto, ad esempio, partendo dal mese gennaio, metteremo nella cella a destra 33,00, poi  febbraio 118,00 (43+38+37), e così via. Insomma ci si perde un po’ di tempo, ma alla fine il risultato ottenuto dovrebbe essere grossomodo questo:

tabbella numbers categorizzata

Utilizzando invece lo script di seguito, Numbers farà tutto da solo (ovviamente i dati dovranno essere già ordinati, altrimenti non vi torneranno i conti e leggendo lo script capirete bene il perché):

Mi hanno segnalato problemi con il listato, il file originale lo trovate su Esempi-Script.zip

(****************** Category ******************)
(************* Sort data in category **********)
tell application “Numbers”
tell document 1

if (count (name of every sheet)) > 1 then

set this_sheet to the first item of (choose from list (name of every sheet) as list with prompt “Please select a sheet:”) as string
set this_sheet to sheet this_sheet
else
set this_sheet to sheet 1
end if

tell this_sheet
if (count (name of every table)) > 1 then
set this_table to the first item of (choose from list (name of every table) as list with prompt “Please select a table:”) as string
set this_table to table this_table
else
set this_table to table 1
end if

tell this_table
— the script require sorted data for correct result
display dialog “Warning! Category coloumn must be sorted, if it is sorted select OK to continue … “

— request the coloumn for category and data
set a to the first item of (choose from list (name of every column) as list with prompt “Select the category column:”) as string
set b to the first item of (choose from list (name of every column) as list with prompt “Select the datas column:”) as string
set a_values to my categorize((the value of cells 2 thru -1 in column a) as list)
set b_values to my categorizeSum((the value of cells 2 thru -1 in column a) as list, (the value of cells 2 thru -1 in column b) as list)
set a to name of this_sheet & ” :: ” & name of this_table & ” :: $” & a
set b to name of this_sheet & ” :: ” & name of this_table & ” :: $” & b
end tell
end tell

— Make new sheet with result table
set this_sheet to make new sheet
tell this_sheet
tell table 1
set the row count to (count a_values) + 1
set the column count to 2
repeat with t from 1 to (count a_values)
set the value of cell (t + 1) of column 1 to (item t of a_values) as text
end repeat

repeat with t from 1 to (count a_values)
set the value of cell (t + 1) of column 2 to (item t of b_values) as number
end repeat

end tell
end tell
end tell
end tell

— Categorize subroutine
on categorize(old_list)
set new_list to {}
repeat with element from 1 to (count old_list)
set currentElement to item element of old_list
if new_list does not contain (currentElement as text) then
copy (currentElement as text) to the end of new_list
end if
end repeat
return new_list as list
end categorize

— Sum data categorized
on categorizeSum(old_list, old_list_elements)
set new_list to {}
set new_list_elements to {}
repeat with i from 1 to (count old_list)
set currentElement to item i of old_list
if new_list does not contain (currentElement as text) then
copy (currentElement as text) to the end of new_list
set sum2 to item i of old_list_elements as number
set sum1 to sum2
copy sum1 to the end of new_list_elements
else
set sum1 to item i of old_list_elements as number
set sum2 to last item of new_list_elements as number
set new_list_elements to my removeLastItem(new_list_elements)
copy (sum1 + sum2) to the end of new_list_elements
end if
end repeat
return new_list_elements as list
end categorizeSum

— Remove last item of a list subroutine
on removeLastItem(listOfLists)
set newList to {}
repeat with i from 1 to ((count of listOfLists) – 1)
copy item i of listOfLists to the end of newList
end repeat
return newList
end removeLastItem

Da notare che il linguaggio applescript si avvicina molto al linguaggio naturale, questo rende molto leggibile il codice, l’unica pecca sta nel fatto che nelle liste (apple script chiama le collezioni di oggetti liste e non array), una volta inseriti gli oggetti questi non  possono più essere modificati, ma mediante l’uso delle subroutine (che non sono altro che delle funzioni), si può aggirare il problema.

Avrei potuto scrivere lo script anche con javascript, ma ritengo l’applescript più semplice e più chiaro, soprattutto per chi non ha mai visto una riga di codice, a patto però di conoscere almeno un po’ d’inglese elementare.

Potete modificare il codice a vostro piacimento e adattarlo alle vostre esigenze. Numbers non sarà excel, ma considerato il costo, ne potrebbe essere una valida e ben più economica alternativa.

Ulteriori approfondimenti su iworkautomation.com