【问题标题】:Implementing vlookup and match in function在函数中实现 vlookup 和 match
【发布时间】:2019-07-02 00:23:34
【问题描述】:

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

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

Vlookup(argument, 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 行)。

【问题讨论】:

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


    【解决方案1】:
    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】:

      Alex's answer的优化点:

      1. 永远不要忘记declare variablesvarconstletrrcc)。如果省略关键字,变量将是全局的,会给您带来很多麻烦(因为它们不会在循环结束后重置)。最好的方法是使用块范围的let
      2. 遵循 #1,不要依赖范围外的变量 (rateSheet[rr][cc])。
      3. 您不需要多次调用SpreadsheetApp.getActiveSpreadsheet() - 这就是变量的用途。调用一次,然后重复使用。
      4. getRange(1,1,&lt;last row&gt;, &lt;last col&gt;) 相当于单个 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 Script vlookup 函数。

      【讨论】:

        【解决方案3】:

        您无法从自定义函数访问随机范围,因此您必须向函数提供数据,此处使用获取活动电子表格的其他一些解决方案将无法用作自定义函数,我猜是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 是内置函数,所以我最终放弃了使用它来满足我的需求。

        【讨论】:

          【解决方案4】:

          vlookup 不是您可以在脚本中的函数中使用的东西,它是一个电子表格公式。

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

          如果您可以分享您的工作表/脚本,我们可以帮助您解决问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-22
            • 2013-01-26
            • 1970-01-01
            • 2021-07-30
            相关资源
            最近更新 更多