使用 Sheet 名称作为循环参数

Use Sheet Name as a Loop Parameter

描述: 我有一个价差 sheet,我称之为 'Applications',它是向客户提供的服务时间表以及提供这些服务的日期。我还有另一个名为 'Daily Activity' 的价差 sheet,我试图在其中创建为每个客户提供的成本和服务汇总。 Daily Activity Spreadsheet 每个客户都有一个标签,每个客户的标签名称是一个代码,用于在 Applications spreadsheet 中识别客户。我需要收集每天为每个客户提供的服务数量,以便我可以创建为每个客户提供的成本和服务的摘要,以便我可以更好地了解每个客户的盈利能力。

我的进步和问题: 我已经成功地利用 Google 脚本来收集所需的信息,但我一直 运行 陷入 最大执行时间问题 。我认为我的问题是我必须为每个客户端编写一个单独的脚本,因为我不知道如何将它们全部集成到一个脚本中。

我注意到我可以用这样的函数得到一个包含所有 sheet 的数组:

function loopingSheets() {
 var ss = SpreadsheetApp.openById("id");
 var sheets = ss.getSheets();
 var sh = [];
 for (i=0; i<sheets.length; i++) {
 var newSh = sheets[i].getName();
 sh.push(newSh);
  }
 return sh;
  }

但我不知道如何将其集成到我的脚本中,以便我可以只有 一个脚本来为所有客户端执行该过程

以下是真正重要的脚本

此脚本扫描 Applications Spreadsheet,它是在给定时间段内为每个客户提供的服务时间表。此脚本需要每天 运行 以便所有需要的数据都可以记录到 Daily Activity spreadsheet.

function countSheet1() { 
var ss=SpreadsheetApp.openById("ID");
var cntSh=ss.getSheetByName('Applications');
var cntRg=cntSh.getDataRange();
var vA=cntRg.getValues();
var today = new Date();
var toD = Utilities.formatDate(new Date(today), Session.getScriptTimeZone(), "dd/MM/yyyy");
var count=0;
var rowA = [];
var rowB = [];
for (i=2; i<vA.length; i++) {
rowA = vA[i][0];
rowB = vA[i][1];
var rowBb = Utilities.formatDate(new Date(rowB), Session.getScriptTimeZone(), "dd/MM/yyyy");
Logger.log(rowBb);
  if(rowA == "Sheet1" && rowBb == toD) {
    count++;
  }
}
return count;

}

除客户端不同外,这与上面的脚本相同

function countSheet2() {
 var ss=SpreadsheetApp.openById("ID");
 var cntSh=ss.getSheetByName('Applications');
 var cntRg=cntSh.getDataRange();
 var vA=cntRg.getValues();
 var today = new Date();
 var toD = Utilities.formatDate(new Date(today), Session.getScriptTimeZone(), "dd/MM/yyyy");
var count=0;
var rowA = [];
var rowB = [];
 for (i=2; i<vA.length; i++) {
rowA = vA[i][0];
rowB = vA[i][1];
var rowBb = Utilities.formatDate(new Date(rowB), Session.getScriptTimeZone(), "dd/MM/yyyy");
Logger.log(rowBb);
  if(rowA == "Sheet2" && rowBb == toD) {
    count++;
  }
}
 return count;

}

这是编写计数每个 sheet ...

的脚本
function runScript() {
 function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}

 var sheet1 = SpreadsheetApp
  .openById("id")
  .getSheetByName("Sheet1");
var sRange =  sheet1.getDataRange();
var values = sRange.getValues();
var newT = new Array();
var nr = 0;

 for (i = 0; i < values.length; i++){
  if (values[i][1]=='Total Number of Applications'){
  nr = i;
  newT.push(nr);
 }             
}
var client = newT[0];
var app = newT[1];
var today = toDateFormat(new Date());
var todaysColumn = values[3].map(toDateFormat).map(Number).indexOf(+today);

sheet1.getRange(client+1,todaysColumn+1,1,1).setValue(countSheet1());

 //Sheet2

var sheet2 = SpreadsheetApp
  .openById("ID")
  .getSheetByName("Sheet2");
var sRange =  sheet2.getDataRange();
var values = sRange.getValues();
var newT = new Array();
var nr = 0;
for (i = 0; i < values.length; i++){
if (values[i][1]=='Total Number of Applications'){
nr = i;
newT.push(nr);
 }             
}
var client = newT[0];
var app = newT[1];
var today = toDateFormat(new Date());
var todaysColumn = values[3].map(toDateFormat).map(Number).indexOf(+today);


sheet2.getRange(client+1,todaysColumn+1,1,1).setValue(countSheet2());
}

countSheet1 函数扫描 Applications spreadsheet 计算 Sheet1(A 列)和今天日期(B 列)的出现次数。然后它会将该计数保存在选项卡 'Sheet 1' 下的每日 Activity 中,我必须继续为每个客户端添加更多脚本。

我想知道是否有可能使用 getSheets() 数组来创建一个执行整个操作的脚本。

由于数据保护,我将无法提供对原始文件的访问....

我仍在努力提高我的 JavaScript 和 GAS 知识(尤其是我难以掌握的数组)....

非常感谢!!!

L.E. 我添加了 2 个 spreadsheet 作为模板

Daily Activity

Applications

应用程序提供的服务数量 sheet

这个版本没问题

我用 key/value 对创建了一个对象,其中键是一个选项卡或 sheet 名称(也是一个客户端 ID)。我对代码做了一些修改。我认为它的工作,但我会让你来判断。我在代码中留下了一些调试屏幕。我喜欢它们,因为它们比记录器更容易看到。但这可能只是老家伙的问题。

function countSheets() 
{ 
  var ss=SpreadsheetApp.openById('ID');
  var sh=ss.getSheetByName('Applications');
  var rg=sh.getDataRange();
  var vA=rg.getValues();
  var td = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "dd/MM/yyyy");
  var mbs=myBullSheets();
  //var s='';
  for (var i=2;i<vA.length;i++)
  {
    var d = Utilities.formatDate(new Date(vA[i][1]), Session.getScriptTimeZone(), "dd/MM/yyyy");
    for(var key in mbs)
    {
      //Logger.log('\n%s==%s && %s==%s',vA[i][0],key,d,td);
      //s+=Utilities.formatString('<br />%s==%s && %s==%s',vA[i][0],key,d,td);
      if(vA[i][0]==key && d==td) 
      {
        mbs[key]+=1;
        //Logger.log('\nmbs[%s]=%s',key,mbs[key]);
        //s+=Utilities.formatString('\nmbs[%s]=%s',key,mbs[key]);
      }
    }
  }
  //var ui=HtmlService.createHtmlOutput(s);
  //SpreadsheetApp.getUi().showModelessDialog(ui, 'My Logs');
  return mbs;
}

function myBullSheets()
{
  var ss=SpreadsheetApp.openById('ID');
  var allshts=ss.getSheets();
  var mbs=[];
  for(var i=0;i<allshts.length;i++)
  {
    mbs[allshts[i].getName()]=0;
  }
  return mbs;
}

希望对您有所帮助。

感谢您提供数据。这帮了很多忙。

顺便说一句..您需要这样的东西才能在记录器中查看输出。

function testcountSheets()
{
  var mbs=countSheets();
  for(var key in mbs)
  {
    Logger.log('\nmbs[%s]=%s',key,mbs[key]);
  }
}

这会将计数加载到 Daily Activity Spreadsheet

的选项卡中

这可能是您要找的。我根本没有测试过这个。但是一旦我们让它工作,我怀疑它会 运行 相当快。

function runScript() 
{
  var ss=SpreadsheetApp.openById('ID');
  var mbs=countSheets();
  for(var key in mbs)
  {
    var sh=ss.getSheetByName(key);
    var rg=sh.getDataRange();
    var vA=rg.getValues();
    for(var i=0;i<vA.length;i++)
    {
      if(vA[i][1]=='Total Number of Applications')
      {
        var nr=i;
        break;//by terminating as soon as we find a match we should get improved performance.  Which is something you cant do in a map.
      }             
    }
    if(typeof(nr)!='undefined')//If we don't find a match this is undefined
    {
      var today=new Date().setHours(0,0,0,0);
      for(var i=0;i<vA[3].length;i++)
      {
        if(vA[3][i])//Some cells in this range have no contents
        {
          if(today.valueOf()==new Date(vA[3][i]).valueOf())
          {
            sh.getRange(nr+1,i+1,1,1).setValue(Number(mbs[key]));
          }
        }
      }
    }
  }
}

哇!从超过最大执行时间到 25 秒...我喜欢