Google表格查询-动态构建数组源

时间:2018-12-11 09:28:42

标签: google-sheets google-sheets-query

我的电子表格中有很多工作表(sheet1,sheet2,sheet3 ...),我想将它们全部添加到数组中,也许基于任何调用范围?现在,我手动添加它们,如下所示:

=query( 
{ 
INDIRECT("sheet1!$A$3:$V"); 
INDIRECT("sheet2!$A$3:$V"); 
INDIRECT("sheet3!$A$3:$V") };
"SELECT Col2, Col3, Col4, ...[etc]")

我要创建任何“设置”工作表,并将所有应放在数组中的工作表放在此处,如下所示:

=query( 
    { 
    get_all_sheets_names_from('settings!A1:A100'); // something like this
 };
    "SELECT Col2, Col3, Col4, ...[etc]")

有可能吗?

2 个答案:

答案 0 :(得分:2)

1)我的想法

我认为不可能在查询参数中使用“ INDIRECT”,因为“ INDIRECT”返回一个单元格引用和参数{(); ()}是固定对象。
出于相同的原因,也无法对完整查询使用“间接”查询:查询不会在单元格上返回引用。

2)有限的成就

原理:case1:在G列的第三行(第三个来源)中查看,如果为空,则测试案例2,否则将公式应用于三个来源。

情况2:如果第二个来源为空,则转到情况1,否则将公式应用于两个来源

情况1:如果为空,则显示“无来源”,否则将公式应用于1个来源

公式

请注意1 ISBLANK (eng)代替ESTVIDE (fr)! 注意2:您可以使用(G2 =“ source1”和G3 =“ source2)进行测试,
但可与G2 =“ source3”和G3 =“ source1”

一起使用
=SI(ESTVIDE($G$4); SI(ESTVIDE($G$3); SI(ESTVIDE($G$1); "no source(s)";query({((INDIRECT("'"&G2&"'!A1:A5")))};"SELECT Col1")) ;query({(INDIRECT("'"&G2&"'!A1:A5"));(INDIRECT("'"&G3&"'!A1:A5"))};"SELECT Col1")) ;query({(INDIRECT("'"&G2&"'!A1:A5"));(INDIRECT("'"&G3&"'!A1:A5"));(INDIRECT("'"&G4&"'!A1:A5"))};"SELECT Col1"))

在线工作表

https://docs.google.com/spreadsheets/d/1sCwwFjpYKKzzAvVwmbMUWcmHSc1wY52XnHlFdT00A3U/edit?usp=sharing

限制

当然,这是一个最多包含3个来源的公式! 它将有更多资源,而且非常庞大……

脚本

宏是唯一的解决方案?

用宏解决

附加此脚本, 它从G2:G30获取值源值(您还需要更多...放入G100 ..)
它创建公式并将其放在H2上
它读取每个源中的最大50值(请参见源代码中的A1:A50) 并不难理解,

注意:使用GSheet管理宏是另一个问题,如果您需要建议,请发表评论。

链接到活动表: https://docs.google.com/spreadsheets/d/14XaR-UsADUpCUCVWqeg0zCbfGy3CCvnwVxUhozjYocc/edit?usp=sharing

function formula6() {
  var spreadsheet = SpreadsheetApp.getActive();

  var values=spreadsheet.getRange('G2:G30').getValues();

  var acSources="{";
  for (var i = 0; (i < values.length) && (values[i]!=""); i++) {
    if (i>0) {  acSources+=";" }
    acSources=acSources+'INDIRECT("'+values[i]+'!A1:A50")';
  }
  acSources=acSources+"}";

  var formula='query('+acSources+';"SELECT Col1")';

  spreadsheet.getRange('H2').activate();
  spreadsheet.getCurrentCell().setFormula('='+formula);

};

答案 1 :(得分:1)

INDIRECT函数粘贴到Google表格中的家伙完全无法理解它的潜力,因此他们不遗余力地对其进行了改进,并涵盖了在这个数组时代至关重要的显而易见的逻辑。 / p>

换句话说,INDIRECT 不能摄取多个数组:

=INDIRECT("Sheet1!A:B"; "Sheet2!A:B")

也不会将数组化的字符串转换为活动引用,这意味着任何串联尝试都将是徒劳的:

=INDIRECT(MasterSheet!A1:A10)
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{Sheet1!A:B; Sheet2!A:B}")
————————————————————————————————————————————————————————————————————————————————————
={INDIRECT("Sheet1!A:B"; "Sheet2!A:B")}
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}")

唯一可能的方法是在每个范围的每个末端使用INDIRECT,例如:

={INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}

这意味着您最好的办法是预编程这样的数组,如果只有部分工作表/选项卡存在(让我们假设从一个工作表仅创建2个工作表的情况)总共4个):

=QUERY(
 {IFERROR(INDIRECT("Sheet1!A1:B5"), {"",""}); 
  IFERROR(INDIRECT("Sheet2!A1:B5"), {"",""}); 
  IFERROR(INDIRECT("Sheet3!A1:B5"), {"",""}); 
  IFERROR(INDIRECT("Sheet4!A1:B5"), {"",""})}, 
 "where Col1 is not null", 0)

因此,即使工作表名称是可预测的(并非总是如此),这样预编程100多个工作表也会很痛苦(即使有各种偷偷摸摸的方法如何在30秒内编写这样的公式)


一种替代方法是使用脚本转换字符串并将其作为公式注入

A1是创建类似于真实公式的字符串的公式:

=ARRAYFORMULA("=QUERY({"&TEXTJOIN("; "; 1; 
 FILTER(SNAME(1); SNAME(1)<>SNAME(0))&"!A1:A20")&"}; ""where Col1 is not null""; 0)")

然后该脚本将从A1单元格中获取字符串,并将其作为有效公式粘贴到A2单元格中:

function onEdit() { 
var sheet = SpreadsheetApp.getActive().getSheetByName('query');  // MASTER SHEET NAME
var src = sheet.getRange("A1");                                  // COPY STRING FROM
var str = src.getValue();
var cell = sheet.getRange("A2");                                 // PASTE AS FORMULA INTO 
cell.setFormula(str);
}
function SNAME(option) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
var thisSheet = sheet.getName(); 
if(option === 0){                  // ACTIVE SHEET NAME =SNAME(0)
return thisSheet;
}else if(option === 1){            // ALL SHEET NAMES   =SNAME(1)
var sheetList = [];
ss.getSheets().forEach(function(val){
   sheetList.push(val.getName())
});
return sheetList;
}else if(option === 2){            // SPREADSHEET NAME  =SNAME(2)
return ss.getName();

}else{
return "#N/A";                     // ERROR MESSAGE
};
}

0

当然,可以将脚本更改为onOpen触发器,或者使用自定义菜单或通过按钮触发的自定义名称(但是无法直接将自定义函数用作公式)

这将满足您的所有需要​​,即在添加新工作表时不添加参考即可编辑公式。唯一的缺点是要重新计算工作表名称脚本...为此,您需要拆除A1公式,例如,在前导'之前按回车键之前添加=,然后将其删除以修复公式< / p>

spreadsheet demo