javascript - Google表格撤消/重做功能

标签 javascript google-sheets stack

我正在查看“网络”标签,以查看是否将重做/撤消数据发送到Google表格中的服务器,似乎不是-似乎是本地用户/设备正在修改信息。

数据结构如何实现撤消/重做功能?我的猜测是它将是一个堆栈(即数组),最后一个可撤消的操作被推入堆栈,如下所示:

actions = [
    action_1,
    action_2
]


但是,对于每个操作而言,实际的数据结构将是什么样?我猜想可以对单元格进行基本修改,但可以存储文本,但是Google表格中有太多可能要做的事情,因此看起来“动作”几乎是无限复杂的。

最佳答案

您想要实现Google Spreadsheet的撤消和重做功能。
您可以使用Google Apps脚本。


我可以像上面那样理解。为此,该示例脚本如何?因此,请仅将此作为几种可能的答案之一。

用法:

请执行以下流程以使用示例脚本。


创建新的电子表格并打开脚本编辑器。


如果第一个选项卡不是Sheet1的名称,请将其更改为Sheet1。在此示例脚本中,作为测试情况,撤消和重做功能将运行到活动电子表格中的Sheet1表。请注意这一点。

将以下示例脚本复制并粘贴到脚本编辑器,然后保存脚本。
将可安装的OnEdit事件触发器安装到函数installedOnEdit


您可以在here上查看有关此操作的文档。请设置installedOnEdit作为OnEdit事件触发器。
安装可安装的OnEdit事件触发器时,将打开授权屏幕。因此,请授权范围。

请关闭电子表格,然后重新打开电子表格。这样,onOpen()由简单触发器运行。并且offset被清除。然后,请打开脚本编辑器。
在电子表格上,手动将“ foo”放入单元格“ A1”。


这样,将logSpreadsheet的电子表格创建到根文件夹。这用作日志。
因此,只有这一次,请等待创建电子表格。

在根文件夹中确认创建的电子表格后,将“栏”手动放在单元格“ A1”中。
手动将“ baz”放入单元格“ A1”。


这时,当您看到日志电子表格时,可以在单元格“ A1:A3”中看到以下值。这用于撤消和重做功能。

{"range":"A1","value":"foo","oldValue":""}
{"range":"A1","value":"bar","oldValue":"foo"}
{"range":"A1","value":"baz","oldValue":"bar"}


在脚本编辑器上运行功能undo


这样,单元格“ A1”的值从baz更改为bar

在脚本编辑器上运行功能undo


这样,单元格“ A1”的值从bar更改为foo

在脚本编辑器上运行功能undo


这样,单元格“ A1”的值从foo更改为空。因为最初的情况是空的。

在脚本编辑器上运行功能redo


这样,单元格“ A1”的值从foo更改为bar

在脚本编辑器上运行功能redo


这样,单元格“ A1”的值从bar更改为baz

在脚本编辑器上运行功能redo


这样,单元格“ A1”的值不变。因为这种情况是最新的。



示例脚本:

var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var prop = PropertiesService.getScriptProperties();

function onOpen() {
  prop.setProperty("offset", "0");
}

function getSheet() {
  var logId = prop.getProperty("logSpreadsheetId");
  if (logId) {
    return SpreadsheetApp.openById(logId).getSheets()[0];
  }
  throw new Error("Please edit a cell in the Spreadsheet. By this, the Spreadsheet for logging is created.");
}

// Undo function
function undo() {
  var logsheet = getSheet();
  var offset = Number(prop.getProperty("offset"));
  var lastRow = logsheet.getLastRow();
  if (lastRow + offset > 0) {
    var log = logsheet.getRange(lastRow, 1).offset(offset, 0).getValue();
    var obj = JSON.parse(log);
    sheet.getRange(obj.range).setValue(obj.oldValue);
    prop.setProperty("offset", offset - 1);
  }
}

// Redo function
function redo() {
  var logsheet = getSheet();
  var offset = Number(prop.getProperty("offset")) + 1;
  var lastRow = logsheet.getLastRow();
  if (lastRow + offset <= lastRow) {
    var log = logsheet.getRange(lastRow, 1).offset(offset, 0).getValue();
    var obj = JSON.parse(log);
    sheet.getRange(obj.range).setValue(obj.value);
    prop.setProperty("offset", offset);
  }
}

// Please set the installable OnEdit event trigger to this function.
function installedOnEdit(e) {
  var logId = prop.getProperty("logSpreadsheetId")
  var ss;
  if (logId) {
    ss = SpreadsheetApp.openById(logId);
  } else {
    ss = SpreadsheetApp.create("logSpreadsheet");
    prop.setProperty("logSpreadsheetId", ss.getId());
  }
  var log = {range: e.range.getA1Notation(), value: "value" in e ? e.value : "", oldValue: "oldValue" in e ? e.oldValue : ""};
  ss.getSheets()[0].appendRow([JSON.stringify(log)]);
}


注意:


这是一个简单的示例脚本。不幸的是,复杂的动作可能无法使用。例如,在当前脚本中不能使用来编辑多个单元格。我对此深表歉意。当您想添加更复杂的操作时,需要针对每种情况修改脚本。请注意这一点。
在当前阶段,当通过单击删除按钮删除单元格值时,旧值不包括在事件对象中。因此,当您要测试值的删除时,请单击该单元格,然后使用Backspace按钮删除该单元格中的每个字符。这样,旧值将包含在事件对象中。请注意这一点。
我认为,如果要执行更复杂的操作,使用修订数据覆盖电子表格可能是合适的。 Ref


参考:


Installable Triggers

关于javascript - Google表格撤消/重做功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59078734/

相关文章:

javascript - 无法重定向另一个页面中的输出(HTML、Javascript)

javascript - 使用 Slick 时无法读取未定义的属性 'slickAdd'

javascript - 尝试使用 jquery 从本地目录加载图像

Python 我可以使用gspread删除由谷歌表单创建的谷歌表中的行吗?

c++ - 当在 C++ 中重新分配对象变量时,原始对象会发生什么?

java - 在 Java 中将二维整数数组压入堆栈

javascript - 如何为HTTP GET 请求设置header,并触发文件下载?

javascript - 超过最大执行时间谷歌表格脚本解决方法

在 Google Apps 脚本中调试自定义函数

assembly - x86组件集 'push'和 'pusha'的区别