从不同的电子表格导入数据 - 缓存问题谷歌应用程序脚本

时间:2015-03-13 08:29:11

标签: google-apps-script google-sheets

*,

规格:

  • 将数据从目标工作表(A)导入另一个Google电子表格中的另一个(B);
  • B表上的数据需要由用户过滤/排序而不影响A表
  • 当数据发生变化时,B数据也应该更新(现场或至少在刷新/按下按钮时)
  • (可选)将B张便签导入A表

纸张的结构(然后是基本上是镜子的B纸张)是一个项目列表,其中每个项目都有一列" ID"。

最初我尝试过IMPORTRANGE,它可以很好地进行实时更新,但不幸的是,B表用户不能使用本机过滤器来排序/过滤数据。 我写了这个自定义函数:

function importSingleItemData(idItem) {
   //vars for debugging
   //var idItem = 1; 

  // Id of spreadsheet where data are contained
  var inKey = "xxxxx";

  // Actual code
  var outData;
  var idItemColumn;
  var ss        = SpreadsheetApp.openById(inKey);  // target sheet

  // 1. Import idItemColumn
  if (ss) {
    idItemColumn = ss.getRange("sheet1!A1:A500").getValues();
      // 2. find id_property row 
    for (var i = 0; i < idItemColumn.length; i++){
      if(idItemColumn[i][0] == idItem){
        var idFound = idItemColumn[i][0];
        // 3. import property availability range
        var row = i+1;
        var RangeString = "sheet1!B"+row + ":AM"+row;
        var range = ss.getRange(RangeString);

        // copy formatting
        // range.copyFormatToRange(range.getGridId(), 3, 4,5,7); !not working
        outData = range.getValues();
        break;
      }
  }

   return outData;
  }
}

我尝试找到项目的ID并导入该行的感兴趣数据。然后我使用= importSingleItemData(A1)在B表上应用它,其中A1包含item = 1的id; A2 = 2等,如

  • ID ItemData
  • 1 = importSingleItemData(A1)
  • 2 = importSingleItemData(A2)

...

这很好用,问题是当A更改时它不会更新B表上的数据。我在stackoverflow上阅读了关于这个缓存beaviour的一些帖子并尝试了一些没有运气的东西(比如添加导入的时间,不再支持),也尝试了setValue方法,它不能与自定义函数一起使用。

我现在认为VLookup / Hlookup与IMPORTRANGE的组合,不确定这是否有效。

如何解决这个问题?

提前致谢!!

2 个答案:

答案 0 :(得分:1)

如果您在两个不同区域之间处理大量数据并匹配大量信息。我做了基于脚本的vlookup。它可能在将来有用。

//-------------------------------------------------(Script Vlookup)------------------------------------------------//
/*
Benefit of this script is:
-That google sheets will not continually do lookups on data that is not changing with using this function
-Unlike Vlookup you can have it look at for reference data at any point in the row.  Does not have to be in the first column for it to work like Vlookup.

Useage:

var LocNum    = SpreadsheetApp.openById(SheetID).getSheetByName('Sheet1').getRange('J2:J').getValues();
FinderLookUpReturnArrayRange_(LocNum,0,'Data','A:G',[3],'test',1,1,'No');


-Loads all Locations numbers from J2:J into a variable 
--looks for Location Numbers in Column 0 of Referance sheet and range eg "Data!A:G"
---Returns results to Column 3 of Target Sheet and range eg "test!A1" or "1,1"

*/


function FinderLookUpReturnArrayRange_(Search_Key,SearchKey_Ref_IndexOffSet,Ref_Sheet,Ref_Range,IndexOffSetForReturn,Set_Sheet,Set_PosRow,Set_PosCol,ReturnMultiResults)   
{
  var twoDimensionalArray = [];
  var data = SpreadsheetApp.getActive().getSheetByName(Ref_Sheet).getRange(Ref_Range).getValues();         //Syncs sheet by name and range into var
  for (var i = 0, Il=Search_Key.length; i<Il; i++)                                                         // i = number of rows to index and search  
  {
    var Sending = [];                                                                                      //Making a Blank Array
    var newArray = [];                                                                                     //Making a Blank Array
    var Found ="";
    for (nn=0,NNL=data.length;nn<NNL;nn++)                                                                 //nn = will be the number of row that the data is found at
    {
      if(Found==1 && ReturnMultiResults=='No')                                                                                         //if statement for found if found = 1 it will to stop all other logic in nn loop from running
      {
        break;                                                                                             //Breaking nn loop once found
      }
      if (data[nn][SearchKey_Ref_IndexOffSet]==Search_Key[i])                                              //if statement is triggered when the search_key is found.
      {
        var newArray = [];
        for (var cc=0,CCL=IndexOffSetForReturn.length;cc<CCL;cc++)                                         //cc = numbers of columns to referance
        {

          var iosr = IndexOffSetForReturn[cc];                                                             //Loading the value of current cc
          var Sending = data[nn][iosr];                                                                    //Loading data of Level nn offset by value of cc
          if(isEmpty_(Sending)==true)                                                                      //if statement for if one of the returned Column level cells are blank
          {
          var Sending =  "#N/A";                                                                           //Sets #N/A on all column levels that are blank
          }
          if (CCL>1)                                                                                       //if statement for multi-Column returns
          {

            newArray.push(Sending);
            if(CCL-1 == cc)                                                                                //if statement for pulling all columns into larger array
            {
              twoDimensionalArray.push(newArray);
              Logger.log(twoDimensionalArray);
              var Found = 1;                                                                              //Modifying found to 1 if found to stop all other logic in nn loop
              break;                                                                                      //Breaking cc loop once found
            }
          }
          else if (CCL<=1)                                                                                 //if statement for single-Column returns
          {
            twoDimensionalArray.push(Sending);
            var Found = 1;                                                                                 //Modifying found to 1 if found to stop all other logic in nn loop
            break;                                                                                         //Breaking cc loop once found
          }
        }
      }
      if(NNL-1==nn && isEmpty_(Sending)==true)                                                             //following if statement is for if the current item in lookup array is not found.  Nessessary for data structure.
      {
        for(var na=0,NAL=IndexOffSetForReturn.length;na<NAL;na++)                                          //looping for the number of columns to place "#N/A" in to preserve data structure
        {
          if (NAL<=1)                                                                                      //checks to see if it's a single column return
          {
            var Sending = "#N/A";
            twoDimensionalArray.push(Sending);
          }
          else if (NAL>1)                                                                                  //checks to see if it's a Multi column return
          {
            var Sending = "#N/A";
            newArray.push(Sending);
          }
        }
        if (NAL>1)                                                                                         //checks to see if it's a Multi column return
        {
          twoDimensionalArray.push(newArray);  
        }
      }
    }
  }
  if(typeof Set_PosRow != "number")                                                                        //checks to see if what kinda of variable Set_PosRow is.  if its anything other than a number it will goto next avaible row
  {
    var Set_PosRow = getFirstEmptyRowUsingArray_(Set_Sheet);                                               //for usage in a database like entry without having to manually look for the next level.
  }
  for (var l = 0,lL=Search_Key.length; l<lL; l++)                                                          //Builds 2d Looping-Array to allow choosing of columns at a future point
  {
    if (CCL<=1)                                                                                            //checks to see if it's a single column return for running setValue
    {
      SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_PosRow + l,Set_PosCol).setValue(twoDimensionalArray[l]);
    }
  }
    if (CCL>1)                                                                                             //checks to see if it's a multi column return for running setValues
    {
      SpreadsheetApp.getActive().getSheetByName(Set_Sheet).getRange(Set_PosRow,Set_PosCol,twoDimensionalArray.length,twoDimensionalArray[0].length).setValues(twoDimensionalArray);
    }
  SpreadsheetApp.flush();
}
//*************************************************(Script Vlookup)*************************************************//

一些辅助函数

//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//Copy this block of fucnctions as they are used in the Vlookup Script
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

//-------------------------------------------------(Find Last Row on Database)------------------------------------------------//

function getFirstEmptyRowUsingArray_(sheetname) 
    {
      var data = SpreadsheetApp.getActive().getSheetByName(sheetname).getDataRange().getValues();
      for(var n = data.length ; n<0 ;  n--)
      {
        if(isEmpty_(data[n][0])=false)
        {
          n++;
          break;
        }
      }
      n++
        return (n);
    }
//*************************************************(Find Last Row on Database)*************************************************//


//-------------------------------------------------(Blank Array Extractor/Rebuilder)------------------------------------------------//
function cleanArray_(actual)
{
    var newArray = new Array();
    for(var i = 0; i<actual.length; i++)
    {
        if (isEmpty_(actual[i]) == false)
        {
            newArray.push(actual[i]);
        }
    }
    return newArray;
}
//*************************************************(Blank Array Extractor/Rebuilder)*************************************************//


//-------------------------------------------------(Even/Odd)------------------------------------------------//
function isEven_(value) {
    if (value%2 == 0)
        return true;
    else
        return false;
}
//*************************************************(Even/Odd)*************************************************//


//-------------------------------------------------(Array Col Sum Agent)------------------------------------------------//
function SumColArray_(sumagent)
{
    var newArray = new Array();
    for(var i = 0; i<sumagent.length; i++)
    {
       var totalsum = 0
       var CleanForSum = cleanArray_(sumagent[i]);
       for(var d = 0; d<CleanForSum.length; d++)
       {  
        totalsum += CleanForSum[d];
       }
      newArray.push(Math.round(totalsum));
    }
    return newArray;
}
//*************************************************(Array Col Sum Agent)*************************************************//


//-------------------------------------------------(Empty String Check)------------------------------------------------//
function isEmpty_(string) 
{

    if(!string)             return true;         
    if(string == '')        return true;
    if(string === false)    return true; 
    if(string === null)     return true; 
    if(string == undefined) return true;
    string = string+' '; // check for a bunch of whitespace
    if('' == (string.replace(/^\s\s*/, '').replace(/\s\s*$/, ''))) return true;       
    return false;        
}
//*************************************************(Empty String Check)*************************************************//

答案 1 :(得分:0)

最终,我通过id

对单行进行了本机函数过滤
=IFERROR(FILTER(IMPORTRANGE("key";"sheet1!B1:AN300");IMPORTRANGE("key";"sheet1!A1:A300") = id))