【问题标题】:Moving google spreadsheet cursor to current date cell on open打开时将谷歌电子表格光标移动到当前日期单元格
【发布时间】:2014-04-15 16:17:25
【问题描述】:

我一直在尝试将打开电子表格时的视图移动到当前日期。

这是一个日程安排电子表格,每个月都有一张工作表,日期列在第一列向下。

我已使用以下代码成功地将工作表更改为当前月份:

function gotoCurrentMonth() {
  var monthTabs = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December" ];

  var month = (new Date()).getMonth();  
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName(monthTabs[month]);
  sheet.activate();
}

这在添加到 onOpen 函数时没有问题。

但是,以下代码仅在通过脚本编辑器手动触发时才有效,在 gotoCurrentMonth 函数之后调用时似乎不会触发。

function gotoCurrentDay() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();

  //Get current day value from the MATCH spreadsheet function
  //Example of cell value: 73
  var range = sheet.getRange(2, 2).getValue();

  //Go to bottom cell so that when it goes back up to current day, it's at the top of the screen
  sheet.setActiveCell(sheet.getRange(sheet.getLastRow(), 1));
  Logger.log("Select Last Row: " + sheet.getLastRow());

  //Go back up to current day cell
  sheet.setActiveCell(sheet.getRange(range, 1));
  Logger.log("Select Current Day Row: " + range);
}

当电子表格打开时,电子表格将切换到 March 工作表,但所选单元格不会移动。坐在三月表的顶部。

如果我随后将光标移回 1 月 1 日(就像打开时通常那样)并在全部加载后手动运行 onOpen 函数,那么它可以正常工作并正确选择当前日期。

我的 onOpen 函数:

function onOpen() {
  gotoCurrentMonth();
  gotoCurrentDay();
};

如果手动或通过自动触发器激活 onOpen 函数,为什么它的行为会有所不同?

【问题讨论】:

  • 我猜您的电子表格中的每张表格都有包含匹配公式的单元格 2,2?对吗?
  • 没错,但是匹配公式将在非当前月份的月份返回 #N/A。仅在 3 月,它目前有 73 个。
  • 也许尝试在两次调用之间添加一个电子表格App.flush() 以强制工作表转到正确的页面,然后再尝试获取单元格 2,2 中的值
  • flush似乎没有帮助,我把它放在gotoCurrentMonth和gotoCurrentDay之间的onOpen函数中。值得注意的是,gotoCurrentDay 甚至不会将活动单元格移动到最后一个单元格,这不依赖于从单元格中获取值。我将它移动到最后一个单元格并备份,以便当前日期将位于屏幕顶部。但正如我所说,即使那样也不会发生。
  • 好的,感谢测试。如果我有什么想法,我会尽快找到并通知你。

标签: google-apps-script google-sheets


【解决方案1】:

尝试将这两个功能合二为一...此代码似乎按您的预期工作:

function gotoCurrentMonthAndDay() {
  var monthTabs = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December" ];

  var month = (new Date()).getMonth();  
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName(monthTabs[month]);
  var row = sheet.getRange(2, 2).getValue();
  sheet.setActiveCell(sheet.getRange(sheet.getLastRow(), 1));//gets end of sheet
  SpreadsheetApp.flush();//update sheet
  Utilities.sleep(500);//pause 1/2 sec
  sheet.setActiveCell(sheet.getRange(row, 1));//activate on right date
}

作为任何想要测试的人的奖励,一个用于创建 12 个工作表并同时删除它们的小脚本:

function createSheets(){
  var monthTabs = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December" ];
  for(var n in monthTabs){
    SpreadsheetApp.getActiveSpreadsheet().insertSheet(monthTabs[n]);
    Utilities.sleep(500);
  }
  SpreadsheetApp.getActiveSpreadsheet().deleteSheet(SpreadsheetApp.getActiveSpreadsheet().getSheets()[0])
} 

function deleteSheets(){
  var monthTabs = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November" ];
  for(var n in monthTabs){
    var del = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(monthTabs[n]);
    try{
      SpreadsheetApp.getActiveSpreadsheet().deleteSheet(del);
    Utilities.sleep(500);
    }catch (err){Logger.log(err)};
  }
 SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].setName('Sheet1');
} 

编辑:

由于您的电子表格公式似乎引起了一些问题,因此这里有一种“纯 JavaScript”方法可以在正确的工作表中获取正确的日期。 正如他们在电视连续剧“边缘”中所说的那样,这些是“平行宇宙”或替代现实……从电子表格转到 JavaScript 和反向并不总是那么容易;)……

无论如何,一个简单的函数可以查看 col A 中的每个单元格并从日期中获取日期并返回该值,可以写成如下:

function getTodayRow(sheet){
  var colContent = sheet.getRange('A1:A').getValues();
  var today = new Date().getDate();
  var val=1;
  for(var n in colContent){
    if(new Date(colContent[n][0]).getDate() == today){val=Number(n)+1;break}
  }
  return val;// the +1 above is because arrays count from 0 and rows count from 1. (Number() is to avoid having 13+1=131 which is the default behavior unfortunately)
}

它将工作表对象作为参数并返回一个数字(如果没有找到匹配的日期则返回 1,这样在最坏的情况下您会转到工作表的顶部)。

你的主要功能也应该改变,它变成:

function onOpen() { // I decided to call it simply onOpen to use the simple trigger that is sufficient in this case. Note that the user must have edit right for the script to run. 
  var monthTabs = [ "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December" ];

  var month = (new Date()).getMonth();  
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName(monthTabs[month]);
  var row = getTodayRow(sheet);
  sheet.setActiveCell(sheet.getRange(sheet.getLastRow(), 1));//gets end of sheet
  SpreadsheetApp.flush();//update sheet
  Utilities.sleep(500);//pause 1/2 sec, I saw your comment about timing... In my tests it works with 500 millisecs but adjust to your needs.
  sheet.setActiveCell(sheet.getRange(row, 1));//activate on right date
}

【讨论】:

  • 睡眠是我一直在寻找的解决方法,我不知道你可以放一个。这当然取决于 PC,但 500 毫秒对我来说并不可靠。有时它会起作用,有时不会,将它提高到 2000 毫秒似乎使它对我来说 100% 可靠。但有一件事是,当我第一次发布问题时(3 月 11 日),它在运行时仍然返回到第 73 行。即使电子表格顶部的数字显示为 94... 就像它没有读取更新的值一样,我已将其设置为在电子表格设置中重新计算“每分钟更改时”;也许与此有关?
  • 我试过放入 SpreadsheetApp.flush();就在从 B2 单元格获取 Match 值之前,它仍然检索到错误的值。可能是实际电子表格系统的错误?
  • 您可以使用简单的 javascript 函数轻松获取当前日期,并在右侧列中进行迭代,直到找到匹配项。您使用哪一列作为日期?日期是“仅日期”吗?,表示小时分钟和秒=0?
  • 日期在第一列 (A) 中,它们在顶部的单元格/函数值中的格式为“3/1/2014”。虽然只有每张纸上的第一个日期是这样的,但如果这有什么不同的话,其余的就像“= A2 + 1”。只想对到目前为止的所有帮助表示感谢 Serge,你太棒了! :D
  • 感谢您的客气话,我用不使用 ss 公式的版本编辑了我的答案...我不喜欢公式!,还有一个不喜欢它们的理由;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 2023-01-03
  • 2023-01-22
  • 1970-01-01
  • 2015-08-16
  • 2018-09-16
相关资源
最近更新 更多