【问题标题】:Google App Scripts & Google Sheets - Equivalent of VLOOKUP/IMPORTRANGE - Using multiple spreadsheetsGoogle App Scripts & Google Sheets - 相当于 VLOOKUP/IMPORTRANGE - 使用多个电子表格
【发布时间】:2021-11-03 01:30:49
【问题描述】:

目标: 我想避免使用公式(数组公式、importranges 和 vlookups)。相反,我想使用 Google App Script 来填充子数据库电子表格中的列。 这是因为当前我每次打开工作表时都会出现性能问题,以及 Google Data Studio 在提取数据时超时的问题。


我有 2 个电子表格。

#1 - 主数据库(~1,000,000 行)- 100% 手动输入

A (Manual Input) B (Manual Input) C (Manual Input)
1 X123456 John Doe JohnDoe@examplecom
2 X987654 Jane Smith JaneSmith@examplecom
3 X543210 Sarah Smith SarahSmith@examplecom



#2 - 子数据库(约 10,000 行)

其用途:在 Col A 中手动输入 ID,公式将自动填充 Col B:C(姓名和电子邮件)

  • 这是使用 GAS 而不是当前公式的预期结果。
A (Manual Input) B (Auto-Populate) C (Auto-Populate)
1 X543210 Sarah Smith SarahSmith@examplecom
2 X123456 John Doe JohnDoe@examplecom
  • Col A - 手动输入 ID。
  • Col B1 包含公式=ARRAYFORMULA(VLOOKUP(A2:A,IMPORTRANGE("URL","MasterDB!A2:C"),{2,3},FALSE)) 从 Col A 获取 ID,搜索主数据库电子表格,并返回名称和电子邮件。


什么是最好的解决方案?

这是我想出的,到目前为止......

function myFunction() {
  //Source Info.
  const sss = SpreadsheetApp.openById('ABC');
  const ssh = sss.getSheetByName("MasterDB");
  const mDB = ssh.getRange("A2:A").getValues; //Get's ID's from Master Spreadsheet

  //Destination Info.
  const dss = SpreadsheetApp.openById('XYZ');
  const dsh = dss.getSheetByName("ChildDB");
  const cDB = dsh.getRange("A2:A").getValues; //Get's ID's from Child Spreadsheet

  [Some Code Here]
  - Return Col B,C from Master Sheet, if Col A matches in both Master & Child Sheet.

}

感谢您的任何意见、指导和帮助 :)

【问题讨论】:

  • "A2:A" 这样的范围会在数据末尾生成大量空值,从而导致问题。替换为getRange(row,col,numrow,numcols)

标签: javascript google-apps-script google-sheets google-sheets-formula vlookup


【解决方案1】:

修改点:

  • 在你的脚本中,需要添加const mDB = ssh.getRange("A2:A").getValues;const cDB = dsh.getRange("A2:A").getValues;()来执行getValues的功能。
  • 看来函数名的import是保留名。所以请修改函数名。使用 V8 运行时时。

当这些点反映到脚本中时,变成如下。

修改脚本:

function myFunction() {
  const sss = SpreadsheetApp.openById('ABC');
  const ssh = sss.getSheetByName("MasterDB");
  const mDB = ssh.getRange("A2:C" + ssh.getLastRow()).getValues(); //Get's ID's from Master Spreadsheet

  const dss = SpreadsheetApp.openById('XYZ');
  const dsh = dss.getSheetByName("ChildDB");
  const cDB = dsh.getRange("A2:A" + dsh.getLastRow()).getValues(); //Get's ID's from Child Spreadsheet

  // Create an object for searching the values of column "A".
  const obj = mDB.reduce((o, [a, ...bc]) => ((o[a] = bc), o), {});
  
  // Create an array for putting to the Spreadsheet.
  const values = cDB.map(([b]) => obj[b] || ["", ""]);
  
  // Put the array to the Spreadsheet.
  dsh.getRange(2, 2, values.length, 2).setValues(values);
}
  • 为了实现您的目标,我在this thread修改了示例脚本。

注意:

  • 此脚本用于 V8 运行时。因此,当您禁用 V8 运行时,请启用它。
  • 如果这不是您期望的结果,您能否提供示例电子表格?通过这个,我想修改脚本。

参考资料:

补充:

关于你新提出的3个问题,我回答如下。

[问题 #1] 我假设 o 只是一个占位符,可以是我想要的任何字母。真的吗?还是字母o有什么意义?

是的。您可以使用除o 之外的其他变量名。在这个脚本中,o 的初始值为{}Ref

[问题 #2] 3 个点有什么作用? [a, ...bc] ?

... 是扩展语法。 Ref

[问题 #3] 如何跳过返回的列?目前它返回 b,c。我将如何返回 c,d?

在这种情况下,示例脚本如下。

function Q69818704_myFunction() {
  const sss = SpreadsheetApp.openById('ABC');
  const ssh = sss.getSheetByName("MasterDB");
  const mDB = ssh.getRange("A2:D" + ssh.getLastRow()).getValues();

  const dss = SpreadsheetApp.openById('XYZ');
  const dsh = dss.getSheetByName("ChildDB");
  const cDB = dsh.getRange("A2:A" + dsh.getLastRow()).getValues();

  const obj = mDB.reduce((o, [a,, ...cd]) => ((o[a] = cd), o), {});
  const values = cDB.map(([b]) => obj[b] || ["", ""]);
  dsh.getRange(2, 2, values.length, 2).setValues(values);
}

【讨论】:

  • 哇,这个脚本的性能非常快,但我不知道你的高级代码是如何工作的/如何编辑它哈哈。感谢您的解决方案!我将研究 reduce() 和 map() 的工作原理。
  • [问题 #1] 我认为o 只是一个占位符,可以是我想要的任何字母。真的吗?还是o这封信有什么意义?
  • [问题 #2] 3 个点有什么作用? [a, ...bc] ?
  • [问题 #3] 如何跳过返回的列?目前它返回 b,c。我将如何返回 c,d?
  • @JamesReed68 感谢您的回复。我很高兴你的第一个问题得到了解决。关于您的新 3 个问题,我添加了 3 个答案。你能确认一下吗?如果我对您另外 3 个问题的 3 个回答没有用,我深表歉意。
猜你喜欢
  • 1970-01-01
  • 2018-01-21
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多