Это работает:
Предположим, я хочу использовать в ArrayFormula()
функцию indirect()
, которая не работает.То есть, если я наберу это в ячейке E1
, =ArrayFormula(indirect(address(row(E:E),column(A:A))))
, это вернет значение ячейки A1
во всех ячейках в column E
.Чтобы обойти это, я создал пользовательскую функцию ниже:
function retValue(cell){
if(cell.map) {
return cell.map(retValue);
} else {
var cellRang = SpreadsheetApp.getActive().getRange(cell);
return cellRang.getValue();
}
}
Теперь, когда я введу этот =ArrayFormula(retValue(address(row(E:E),column(A:A))))
в ячейку E1
, каждая ячейка в column E
будет иметь соответствующее значение ячейки вта же строка column A
.
Моя проблема:
Мне нужно иметь пользовательскую функцию, которая получает 2 аргумента, например function retValue2(cell, anotherRange)
, но я тольковсе равно, если cell
это массив, так как anotherRange
должен быть массивом в любом случае.Что происходит, когда я итеративно вызываю cell.map(retValue2)
, аргумент anotherRange
теряется, и я не совсем уверен, как это сделать.
Я пытался придумать это:
function retValue2(cell, anotherRange) {
if (cell.map) {
return cell.map(retValue2);
} else {
var range = SpreadsheetApp.getActive().getRange(anotherRange);
var nrRows = range.getNumRows();
var nrCols = range.getNumColumns();
return cell + ',' + nrRows + ',' + nrCols;
}
}
Но он терпит неудачу, потому что anotherRange
не распознается внутри итерации, я думаю.Как мне решить эту проблему?
PS .: в примере, который работает, почему он вообще работает?Я понимаю, что когда я делаю это return cell.map(retValue);
, он будет использовать мою собственную функцию в качестве обратного вызова, которая будет возвращать все значения в массиве, но в электронной таблице он показывает только одно значение в той же строке.В чем здесь магия?
РЕДАКТИРОВАТЬ:
Моя конечная цель - создать собственную функцию поиска, в которой я передаю ключ поиска и двумерный массив (строкии столбцы), а затем он находит координаты этого ключа в массиве.
Посмотрите здесь:
function retCoord(sKey, sIRange) {
try {
var key = SpreadsheetApp.getActive().getRange(sKey).getValue();
}
catch(e) {
var key = sKey;
}
var range = SpreadsheetApp.getActive().getRange(sIRange).getValues();
nbRow = range.length;
nbColumn = range[0].length;
for(var i = 0; i<nbRow; i++){
for(var j = 0; j<nbColumn; j++){
if(range[i][j] == key){
return i + ", " + j;
}
}
}
}
Если в моей электронной таблице я введу что-то вроде =retCoord("K4","A:L")
, он будет искатьсодержимое ячейки K4
в моем 2-мерном массиве A: L и возвращаемое значение в массиве, например 1, 2
.Это также работает, если я использую =retCoord(K4,"A:L")
или =retCoord("term searched","A:L")
, и в этом последнем случае я непосредственно ввожу искомый термин.Это работает нормально, пока я не использую его в ArrayFormula()
.
Во-первых, вместо =retCoord("K4","A:L")
я мог бы очень хорошо использовать, например, =retCoord(address(4, 11),"A:L")
, и мой метод .getRange()
мог бы получить ячейку K4
простохорошо.
Теперь вот большая проблема.Я хочу использовать свою функцию в ArrayFormula()
и, поместив курсор в O1
и надеясь найти элементы от column D
в columns E
до L
, которые я хочу передать как один из входовaddress()
, row(O:O)
, например: =ArrayFormula(retCoord(address(row(O:O),4,4),"E:L"))
, что означает, что для каждой строки передается новый адрес.то есть в ячейке O1
должен возвращаться результат retCoord(D1,"E:L")
, в O2
должно быть retCoord(D2,"E:L")
, в O3
должно быть retCoord(D3,"E:L")
и т. д.
Проблемапроисходит из-за того, что в моей функции sKey
является массивом, и если я пытаюсь использовать тот же подход, что и моя функция retValue
(здесь, выше, в разделе , это работает: ), то происходит сбой, потому что теперь в retCoord
, у меня есть 2 входа, и функция самоанализа, вызываемая ранее, не работает из-за второго входа.Конечно, я что-то упускаю, и всегда есть лучший и более элегантный способ решения проблемы.Но сейчас, может ли кто-нибудь помочь мне с этим?
EDIT2:
Я немного изменил код и, кажется, я продвинулся вперед, но пока не совсем.Проверьте комментарий ниже для строки, обозначенной (*):
function retCoord(sKey, sIRange) {
var key = '';
try {
key = SpreadsheetApp.getActive().getRange(sKey).getValue();
return key;
}
catch(e) {
if (sKey.map) {
var objKey = sKey.map(retCoord);
return objKey; // (*) <--- comments below
key = objKey;
} else {
key = sKey;
}
}
var range = SpreadsheetApp.getActive().getRange(sIRange).getValues();
nbRow = range.length;
nbColumn = range[0].length;
for(var i = 0; i<nbRow; i++){
for(var j = 0; j<nbColumn; j++){
if(range[i][j] == key){
return key + " = "+ i + ", " + j;
}
}
}
}
Эту (*) строку я добавил только, чтобы увидеть, что возвращалось с карты.Удивительно (в некотором смысле), это объект со всеми элементами этого столбца, и это ожидается.Чего я не ожидал, так это того, что если я верну этот объект в свою ячейку электронной таблицы, он вернет только значение этой конкретной ячейки (как я хотел, но не совсем так, как ожидалось).Но проблема в том, что я не могу использовать этот объект для сравнения со строкой, поскольку он будет расширяться и становиться чем-то другим и никогда не будет совпадать.Посмотрите:
- Если я сделаю
return objKey
в своей пользовательской функции, то через ячейку O1 он возвращает «a», в O2 он возвращает «b», в O3 он возвращает «c», как и ожидалось, потому что тезначения моих клеток D1, D2, D3 соответственно. - Если я делаю
return "-> " + objKey
в моей пользовательской функции вместо возврата -> a
, -> b
, -> c
в O1, O2, O3 соответственно, он возвращает -> =A:A,a,b,c,d,e,f
для всех ячеек в column O
, что, кажется, имело какой-то тип objKey.toString()
под капотом перед конкатенацией с "->"
Вывод: как "принудительно" привести видимый результат objKey
в строку, сохраняя видимый результат при возврате объекта без его изменения?Проще говоря, я хочу, чтобы конкатенация «некоторая строка» + была равна «некоторой строке» + «одна строка, представляющая значение в этой строке вместо объекта».Другими словами, что, черт возьми, здесь происходит?Как Google Sheets теперь, когда в этой строке этот элемент представляет тот, который я хочу?Это то, что я спросил в «PS».в первой части этого поста.