我有一个谷歌表单文档,有两个选项卡,一个称为内部选项卡,另一个名为外部选项卡。如何向其他用户隐藏内部选项卡?锁定功能已经不够好了,我只希望我公司的人能够看到两个选项卡,客户应该只能看到外部选项卡。
function validUsers() {
String[] adminUsers = {”email1@gmail.com”,”email2@gmail.com”,”email3@gmail.com”};
if (adminUsers.indexOf(Session.getEffectiveUser().getEmail()) >= 0) {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Internal').showSheet()
else
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Internal').hideSheet()
}
}
问题:
- 您希望根据访问电子表格的用户在电子表格中隐藏或显示工作表
解决方案:
您可以执行以下操作:
- 安装onOpen触发器,每当用户打开电子表格时,该触发器都会执行一个函数(我们称之为
fireOnOpen
( - 函数
fireOnOpen
应该检查哪个用户正在访问电子表格,并根据此情况隐藏或显示某个工作表(称为Internal
( - 为了检查访问电子表格的当前用户,可以使用getActiveUser(((而不是getEffectiveUser((,它将返回安装触发器的用户(
工作流:
- 触发器可以手动安装,也可以编程安装。要以编程方式执行此操作,请将此函数复制到脚本编辑器并执行一次:
function createOnOpenTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger("fireOnOpen")
.forSpreadsheet(ss)
.onOpen()
.create();
}
- 这将导致每次用户访问电子表格时都会执行
fireOnOpen
。fireOnOpen
函数可以是这样的:
function fireOnOpen() {
const adminUsers = ["email1@gmail.com","email2@gmail.com","email3@gmail.com"];
const currentUser = Session.getActiveUser().getEmail();
const internalSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Internal");
if (adminUsers.includes(currentUser)) internalSheet.showSheet();
else internalSheet.hideSheet();
}
重要注意事项:
- 您不能为某些用户隐藏工作表,但不能为其他用户隐藏。隐藏的工作表对所有用户都是隐藏的,可见的工作表对于所有用户都可见。因此,只有当内部和外部用户不同时访问电子表格时,这才有效。如果这样做,外部用户可能能够访问
Internal
工作表 - getActiveUser((并不总是被填充,正如你在这个答案中看到的那样,所以请确保所有管理员用户都来自同一个G Suite域。否则,这是行不通的
- 如果
Internal
工作表的隐私至关重要,并且内部和外部用户当时有可能访问电子表格,我不建议使用此解决方案
编辑:
如评论中所述,针对管理员和非管理员用户当时访问文件的情况,可能的解决方法如下:
- 当管理员用户访问该文件时,存储发生该事件的时间
- 创建一个时间驱动的触发器来定期执行一个函数(比如说每5分钟(,它将检查管理员是否在短时间前(比如说30分钟(访问了该文件。如果管理员已经这样做了,请删除不同非管理员域的权限。如果不是这样,请将这些权限添加回
- 在这种情况下,需要启用驱动器高级服务
更新的代码示例:
function fireOnOpen() {
const adminUsers = ["email1@gmail.com","email2@gmail.com","email3@gmail.com"];
const currentUser = Session.getActiveUser().getEmail();
const internalSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Internal");
if (adminUsers.includes(currentUser)) {
internalSheet.showSheet();
const documentProperties = PropertiesService.getDocumentProperties();
documentProperties.setProperty("lastAdminAccess", new Date().getTime()); // Store time of admin access
} else internalSheet.hideSheet();
}
function createOnOpenTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger("fireOnOpen")
.forSpreadsheet(ss)
.onOpen()
.create();
}
function updatePermissions() {
const fileId = SpreadsheetApp.getActive().getId();
const lastAdminAccess = PropertiesService.getDocumentProperties().getProperty("lastAdminAccess"); // Last time of admin access in ms
const now = new Date().getTime(); // Current time in milliseconds
const thirtyMinutes = 1000 * 60 * 30; // 30 minutes in milliseconds
if (now - lastAdminAccess < thirtyMinutes) {
const currentPermissions = Drive.Permissions.list(fileId)["items"];
const publicPermissionIds = currentPermissions.filter(permission => permission["type"] === "anyone")
.map(permission => permission["id"]);
publicPermissionIds.forEach(permissionId => Drive.Permissions.remove(fileId, permissionId));
} else {
const resource = {
type: "anyone",
role: "reader"
}
Drive.Permissions.insert(resource, fileId);
}
}
function createTimeTrigger() {
ScriptApp.newTrigger("updatePermissions")
.timeBased()
.everyMinutes(5)
.create();
}
一旦共享工作表,就应该假设任何人都可以看到其中的数据。即使有人不应该看到internal
选项卡,他们也可以复制工作表,从而获取数据。
您可以尝试创建一个单独的图纸,并使用=IMPORTRANGE()
引用原始图纸。但要知道,一旦允许两张图纸之间的连接,任何能够访问第二张图纸的人都可能能够访问第一张图纸中的任何内容。也许可以用三张纸来解决这个问题:
-
内部+外部-您当前的工作表
-
中间的图纸,只有您才能访问。它有一个单独的选项卡
Internal
,使用=IMPORTRANGE()
访问来自1(的数据 -
客户端的
External
工作表。通过=IMPORTRANGE()
链接到2(
这种方式3(只能访问2(中的数据,而2(中只包括到1(的链接。
我不承诺这将使数据安全,不让那些不应该看到它的人看到。但它至少是安全的。