Hi all,
first post...I'm sure I'm not posting in right place AND Im hoping someone will direct me
BUT; OK
I am trying to develop a script and I intend to use 'selected range' from number spreadsheet.
However, once the selected range is passed to the script, I want to do a few things with it.
First I'd like to show it is display alert
maybe something like: (BTW # placed to prevent system from trying to evaluate the script)
range is acquired by:
try
tell application "Numbers" to tell front document to tell active sheet
tell (first table whose selection range's class is range)
set sr to selection range
Then later
display alert "selected range is ' &s&
BUT when I try to run it, nothing shows up in the popup in fact the popup doesnt popup
I'd also like to tear it into its pieces and make changes to it. So for example if selected range turns out to be k5:l9, then maybe I'd like to 'reduce/increase by some number of columns or rows such as -1 so that the final range is actually j5:k9
I have been able to successfully "force" range to some value such as
set sr to range "k5:l9"
and when it shows in display it is fine, but when I try to use sr, it doesnt.
Hi @Capchap, this seems like predominantly an AppleScript question. There are plenty of AppleScript connoisseurs on this forum, so someone might chime in. But your best option for a question like this is to post it on Stackoverflow, which is the home of coding questions and answers.
However, bear in mind, you should format your posts properly to make them more readable. This includes (especially includes) the code sample: include the rest of the code, because it might be important to the problems you're experiencing without you being aware. It's also important because a person trying to help wants to just copy/paste your code sample into their editor, and have it compile and run straight away: currently, yours doesn't do this and for someone to get it running, they have to first write extra parts of the script themselves, which defeats the point of diagnosing a problem.
To illustrate this, I'm going to say that your script has two glaring errors in it, which is that display alert "selected range is ' &s& doesn't have anything after the second &. But, I'm guessing in your actual script, it does, and you just left it out here. (The second error is your mismatched quotes: the first is a double quote, the second is a single quote; they should both be doubles).
Also, I don't know what variable s is, because it never occurs in the script before that line.
Anyway, good luck with it and do let us know how your KM macro turns out, or perhaps consider sharing it if you think others will find it useful.
And also thanks for guiding me about providing full script. I didn’t think about how someone might actually use it too help me... guess I thought genius coders could mentally synthesize the rest ... I didn’t give whole code because I didn’t want to come across as asking someone to fix my code so much as I wanted to understand how things interacted.
For example when I wrote stuff in c (30 years ago) we had to pay attention to the variable type. So Type could be integer, real, float, char, etc each type had its own way of being able to display.
Anyway I’m rambling. Thanks again for directing me. Greatly appreciated.
I rarely use Apple Numbers (prefer Excel), so my Numbers AppleScript is suspect. But your AppleScript doesn't look right to me. I could very well be wrong, but try this:
tell application "Numbers"
-- activate
try
if not (exists document 1) then error number 1000
tell document 1
try
tell active sheet
set the selectedTable to ¬
(the first table whose class of selection range is range)
end tell
on error
error number 1001
end try
tell selectedTable
set the selectedRange to the selection range
set selRngName to name of selectedRange
display dialog "Selected Range is: " & selRngName buttons {"Cancel", "OK"} default button "OK"
-- get the parent columns and rows of the selection
set selectedCols to the columns of selection range
set selectedRows to the rows of selection range
end tell
end tell
end try
end tell
For more help/examples, do a 'net search of "applescript numbers get selection"
The big issue didn’t seem to be getting the selection range bc the app works. I couldn’t figure out how to show what the selected range was received (just in case it was wrong, or just wanted to have user confirm)
Thanks again, I’ll post kudos after checking it out
(() => {
'use strict';
const main = () => {
const
docs = Application('Numbers').documents,
lrChoice = bindLR(
0 < docs.length ? (
Right(docs.at(0))
) : Left('No documents open in Numbers.'),
// If we have a Right channel value,
// bind the name 'doc' to it.
// (Left channel values pass straight through to the end)
doc => {
const
tbls = filter(
tbl => Boolean(tbl.selectionRange()),
doc.activeSheet.tables()
);
return bindLR(
0 < tbls.length ? (
Right(tbls[0])
) : Left('Nothing selected in Numbers'),
// If we have a Right channel value,
// bind the name 'tbl' to it.
// (Left channel values pass straight through)
tbl => {
const
rngSeln = tbl.selectionRange(),
cellValues = rngSeln.cells.value(),
sa = standardSEAdditions(),
choice = (
sa.activate(),
sa.chooseFromList(
cellValues, {
withTitle: tbl.name(),
defaultItems: cellValues[0],
multipleSelectionsAllowed: true
}
)
);
return choice !== false ? (
Right(choice)
) : Left('User cancelled')
}
);
}
);
// Either a message string, or an Array of chosen cell values
return (
lrChoice.Left || lrChoice.Right
);
};
// GENERIC FUNCTIONS --------------------------------------
// Left :: a -> Either a b
const Left = x => ({
type: 'Either',
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: 'Either',
Right: x
});
// bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
const bindLR = (m, mf) =>
m.Right !== undefined ? (
mf(m.Right)
) : m;
// filter :: (a -> Bool) -> [a] -> [a]
const filter = (f, xs) => xs.filter(f);
// JXA --------------------------------------
// standardSEAdditions :: () -> Application
const standardSEAdditions = () =>
Object.assign(Application('System Events'), {
includeStandardAdditions: true
});
// MAIN ---
return main();
})();
-- numbersSelectionLR :: () -> Either String [a]
on numbersSelectionLR()
tell application "Numbers"
set docs to documents
if 0 < length of docs then
set lrDoc to my |Right|(item 1 of docs)
else
set lrDoc to my |Left|("No documents open in Numbers.")
end if
end tell
bindLR(bindLR(lrDoc, my selectedTableLR), my chosenCellsLR)
end numbersSelectionLR
on run
tell numbersSelectionLR()
if its |Right| is not missing value then
its |Right|
else
its |Left|
end if
end tell
end run
-- FUNCTIONS FOR NUMBERS ------------------
-- isSelected :: NumbersTable -> Bool
on isSelected(oTable)
using terms from application "Numbers"
missing value is not selection range of oTable
end using terms from
end isSelected
-- selectedTableLR :: NumbersDocument -> Either String NumbersTable
on selectedTableLR(doc)
using terms from application "Numbers"
set tbls to filter(my isSelected, tables of active sheet of doc)
if 0 < length of tbls then
|Right|(item 1 of tbls)
else
|Left|("Nothing selected in Numbers")
end if
end using terms from
end selectedTableLR
-- chosenCells :: NumbersTable -> Either String -> [a]
on chosenCellsLR(tbl)
using terms from application "Numbers"
set xs to value of cells of selection range of tbl
tell application "System Events"
activate
set choice to choose from list xs with title (name of tbl) ¬
default items (item 1 of xs) ¬
with multiple selections allowed
end tell
if choice is not false then
|Right|(choice)
else
|Left|("User cancelled")
end if
end using terms from
end chosenCellsLR
-- GENERIC FUNCTIONS --------------------------------------
-- https://github.com/RobTrew/prelude-applescript
-- Left :: a -> Either a b
on |Left|(x)
{type:"Either", |Left|:x, |Right|:missing value}
end |Left|
-- Right :: b -> Either a b
on |Right|(x)
{type:"Either", |Left|:missing value, |Right|:x}
end |Right|
-- bindLR (>>=) :: Either a -> (a -> Either b) -> Either b
on bindLR(m, mf)
if missing value is not |Right| of m then
mReturn(mf)'s |λ|(|Right| of m)
else
m
end if
end bindLR
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(f, xs)
tell mReturn(f)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if |λ|(v, i, xs) then set end of lst to v
end repeat
return lst
end tell
end filter
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
Here's a simpler JXA script that does exactly what you ask, but is perhaps easier to read and modify:
Example Output
var ptyScriptName = "Get Selected Range in Apple Numbers Table";
var ptyScriptVer = "1.0";
var ptyScriptDate = "2018-06-29";
var ptyScriptAuthor = "JMichaelTX";
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PURPOSE:
• Get Selected Range in Apple Numbers Table
RETURNS: Cell Range of Selection (B1:D3)
REQUIRED:
1. macOS 10.11.6+
2. Mac Applications
• Apple Numbers
TAGS: @CAT.Selection @SW.ANumbers @type.Example @Auth.JMichaelTX
REF: The following were used in some way in the writing of this script.
1. 2018-06-29, Keyboard Maestro Forum
How to Get the Selected Range in Numbers.app with AppleScript
https://forum.keyboardmaestro.com/t/how-to-get-the-selected-range-in-numbers-app-with-applescript/10657
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
(function myMain () {
'use strict';
var scriptResults = "TBD";
// --- Get Ref to Current App (needed for Dialogs, etc) ---
const app = Application.currentApplication()
app.includeStandardAdditions = true
const numApp = Application('Numbers');
const oDoc = numApp.documents[0]; // active document
const oSheet = oDoc.activeSheet(); // active sheet
var tableList = oSheet.tables(); // all tables on sheet
// --- Get FIRST Table That Contains the Selected Range ---
var oSelTable = tableList.filter(tbl => tbl.selectionRange())[0];
if (oSelTable) {
var oSelRange = oSelTable.selectionRange(); // Selection Range in Table
var selRngName = oSelRange.name(); // Name (cell ref) of Selection
scriptResults = "Selected Range is: " + selRngName;
} else { scriptResults = "❯❯❯ ERROR ❮❮❮\nNothing is selected in Numbers Sheet"; }
var msgTitleStr = "Get Selected Range";
app.beep()
var oAns = app.displayDialog(scriptResults,
{
withTitle: msgTitleStr
,withIcon: "caution"
,buttons: ["Cancel","OK"]
,defaultButton: "OK"
,cancelButton: "Cancel"
});
var btnStr = oAns.buttonReturned;
return selRngName;
})();