在函数中实现vlookup和match

时间:2019-07-02 00:23:34

标签: google-apps-script google-sheets gs-vlookup

我正在尝试在表格中创建一个函数,该函数结合了我经常使用的“ Vlookup”和“ Match”组合。

我想使用我的函数“ Rates”接受1个参数,并返回始终使用相同值的Vlookup和Match的组合。

Vlookup(参数,DEFINED RANGE(始终保持相同的定义范围),match(A1(总是A1单元格,DIFFERENT DEFINED RANGE,0),FALSE)

我尝试创建脚本,但是没有编码经验,并且收到错误消息“未定义vlookup”

function ratesearch(service) {
  return vlookup(service, Rates, Match($A$1,RatesIndex,0),FALSE);
}

实际结果:#ERROR!

  

ReferenceError:未定义“ vlookup”。 (第2行)。

可以使用以下方法解决我的问题:

function findRate() {
  var accountName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1).getValue(); //determine the account name to use in the horizontal search
  var rateTab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Rates'); //hold the name of the rate tab for further dissection
  var rateNumColumns =rateTab.getLastColumn(); //count the number of columns on the rate tab so we can later create an array
  var rateNumRows = rateTab.getLastRow(); //count the number of rows on the rate tab so we can create an array
  var rateSheet = rateTab.getRange(1,1,rateNumRows,rateNumColumns).getValues(); //create an array based on the number of rows & columns on the rate tab
  var currentRow = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getRow(); //gets the current row so we can get the name of the rate to search
  var rateToSearch = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(currentRow,1).getValue(); //gets the name of the rate to search on the rates tab
  for(rr=0;rr<rateSheet.length;++rr){
    if (rateSheet[rr][0]==rateToSearch){break} ;// if we find the name of the 
      }
  for(cc=0;cc<rateNumColumns;++cc){
    if (rateSheet[0][cc]==accountName){break};
      }
  var rate = rateSheet[rr][cc] ; //the value of the rate as specified by rate name and account name
  return rate;
}

4 个答案:

答案 0 :(得分:0)

vlookup不能在脚本的函数中使用,它是电子表格公式。

Google脚本使用JavaScript,因此您需要使用JS编写代码,然后将其输出到相关的单元格中。

如果您可以分享表格/脚本,我们可以帮助您解决。

答案 1 :(得分:0)

function findRate() {
  var accountName = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1,1).getValue(); //determine the account name to use in the horizontal search
  var rateTab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Rates'); //hold the name of the rate tab for further dissection
  var rateNumColumns =rateTab.getLastColumn(); //count the number of columns on the rate tab so we can later create an array
  var rateNumRows = rateTab.getLastRow(); //count the number of rows on the rate tab so we can create an array
  var rateSheet = rateTab.getRange(1,1,rateNumRows,rateNumColumns).getValues(); //create an array based on the number of rows & columns on the rate tab
  var currentRow = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell().getRow(); //gets the current row so we can get the name of the rate to search
  var rateToSearch = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(currentRow,1).getValue(); //gets the name of the rate to search on the rates tab
  for(rr=0;rr<rateSheet.length;++rr){
    if (rateSheet[rr][0]==rateToSearch){break} ;// if we find the name of the 
      }
  for(cc=0;cc<rateNumColumns;++cc){
    if (rateSheet[0][cc]==accountName){break};
      }
  var rate = rateSheet[rr][cc] ; //the value of the rate as specified by rate name and account name
  return rate;
}

答案 2 :(得分:0)

Alex's answer的优化点:

  1. 永远不要忘记使用varconstletrrcc)来declare variables。如果省略关键字,则变量将是全局变量,并且会给您带来很多麻烦(因为在循环结束后它们不会重置)。最好的方法是使用块范围的let
  2. 在#1之后,不要依赖范围外的变量(rateSheet[rr][cc])。
  3. 您不需要多次调用SpreadsheetApp.getActiveSpreadsheet(),这就是变量的用途。呼叫一次,然后重用。
  4. getRange(1,1,<last row>, <last col>)等效于单个getDataRange调用。
  5. 使用findfindIndex方法来避免冗长的循环。

应用这些要点后,您将获得一个干净且优化的功能以供使用:

const findRate = () => {
  const ss = SpreadsheetApp.getActiveSpreadsheet();

  const accountName = ss.getActiveSheet().getRange(1, 1).getValue();

  const rateTab = ss.getSheetByName("Rates");

  const rates = rateTab.getDataRange().getValues();

  const currentRow = ss.getActiveSheet().getActiveCell().getRow();

  var rateToSearch = ss.getActiveSheet().getRange(currentRow, 1).getValue();

  const rr = rates.findIndex((rate) => rate === rateToSearch);

  const [firstRates] = rates;

  const cc = firstRates.findIndex((rate) => rate === accountName);

  return rates[rr][cc];
};


请注意,"vlookup" is not defined错误表明作用域中没有vlookup变量/函数声明。显然是这种情况,因为没有内置的Google Apps脚本vlookup函数。

答案 3 :(得分:0)

您无法从自定义函数访问随机范围,因此您必须向该函数提供数据,此处使用获取活动电子表格的其他一些解决方案无法作为自定义函数使用,我猜是OP 正在寻找什么,这里是一个脚本示例,但是在你走这条路之前警告的话,自定义函数比内置函数慢得多,所以这样做会比 vlookup 和 match 慢得多,如果您在工作表中只有几个这样的函数,您会没事的,但如果您使用自定义函数构建包含数十行的大型表格,则会大大减慢您的电子表格速度。

// Combines VLOOKUP and MATCH into a single function
// equivalent to VLOOKUP(rowValue, tableData, MATCH(columnName, tableHeader))
// but in this version tableData includes tableHeader
function findInTable(tableData, columnName, rowValue) {
  if (rowValue === "") {
    return "";
  }
  if (tableData.length == 0) {
    return "Empty Table";
  }
  const header = tableData[0];
  const index = header.indexOf(columnName);
  if (index == -1) {
    return `Can't find columnName: ${columnName}`;
  }

  const row = tableData.find(row => row[0] == rowValue);
  if (row === undefined) {
    return `Can't find row for rowValue: ${rowValue}`;
  }
  return row[index];
}

我建议你做的另一个优化是使用命名范围,它允许你转换如下内容: =VLOOKUP(C5, 'Other Sheet'!A2:G782, MATCH("Column Name", 'Other Sheet'!A1:G1)) 变成更具可读性和更易于查看的内容: =VLOOKUP(C5, someTableData, MATCH("Column Name", someTableHeader))

对于自定义函数表单,这将如下所示: =findInTable(A1:G782, "Column Name", C5) 请注意,我通过合并数据和标题缩短了参数列表,这对表结构做出了一些假设,例如有一个标题行并且查找值在第一列中,但它使其更短且更易于阅读。 但正如之前提到的,这是以速度变慢为代价的。 由于 VLOOKUP 和 MATCH 是内置函数,所以我最终放弃使用它来满足我的需要,因为它有多慢,而且速度有多快。