Google表格无法通过事件获取用户的电子邮件地址
任务是:几位用户编辑Google Sheets表格。所有用户都拥有Editor(编辑者)角色。有些用户是masterusers——他们可以编辑一切。另一些是客户——他们只能编辑空的时间槽以及为他们的公司保留的时间槽。
我用一个对象创建了配置对象(Config)。
var CONFIG = {
SPREADSHEET_URL:*** '*/edit',
OWNER_EMAIL: ['[email protected]', '[email protected]'],
EDITORS_TO_REMOVE: {"Агама":['[email protected]'],"Юнифрост":['[email protected]']}
};
EDITORS_TO_REMOVE: - 用户及其所属公司数组OWNER_EMAIL: - 可以编辑一切的masterusers数组
然后我尝试处理编辑事件——当客户端尝试编辑某些内容时,代码应该检查所编辑的时间槽是否为空,或是否未被其他客户端预留。
于是,我通过onEdit(e) 函数捕捉编辑事件并记录结果。当我使用自己的账户操作时——它运行良好且
userEmail
是我的邮箱地址,一切正常
但如果用其他账户执行,userEmail就为空。AI也没用。
function onEdit(e) {
const sheet = e.source.getActiveSheet();
const row = e.range.rowStart;
const col = e.range.columnStart;
const userEmail = Session.getActiveUser().getEmail();
// Определяем диапазоны ворот (Клиент, Ворота, Вид окна)
const gateRanges = [
{ clientCol: 3, gateCol: 4, windowCol: 5, name: 'Ворота 1' }, // C-E
{ clientCol: 6, gateCol: 7, windowCol: 8, name: 'Ворота 2' }, // F-H
{ clientCol: 9, gateCol: 10, windowCol: 11, name: 'Ворота 3' } // I-K
];
let processed = false;
for (const range of gateRanges) {
if ([range.clientCol, range.gateCol, range.windowCol].includes(col)) {
handleGateEdit(sheet, row, range, userEmail);
processed = true;
break;
}
}
if (!processed) return; // Если изменение не в нужных колонках — выходим
}
问题是——如何在编辑事件中捕获编辑表格的用户邮箱?简单触发器在你不是表格创建者时,通常无法访问用户邮箱。可安装触发器也无法获取用户邮箱——我创建了一个函数
function handleEditEvent(e) {
if (e && e.range) { // Проверка наличия данных события
const userEmail = Session.getActiveUser().getEmail();
Logger.log("current user is="+userEmail);
honEdit(e);
} else {
Logger.log('handleEditEvent вызван без корректного события');
}
}
它没有返回任何结果。如何判断用户没有编辑其他用户的数据?
解决方案
Simple triggers such as onEdit(e) run in a restricted context where the identity of the user at the keyboard is usually not available. "他们可能能够也可能无法确定当前用户的身份,这取决于一系列复杂的安全限制。"
Installable triggers run under the account of the user who created the trigger, rather than under the account of the user at the keyboard.
请参阅 Session.getActiveUser() 与 Session.getEffectiveUser()。
如何检查用户是否没有编辑其他用户的数据?
使用 range protections。你可以手动设置让每个用户拥有自己的一行或一列,或者使用一个 onEdit(e) 简单触发器,在用户逐步编辑时逐个保护单元格。建议采用前者,因为这样更易于管理。
请注意,电子表格的所有者始终可以编辑表格中的所有内容。
在进行保护单元格的示例代码:
'use strict';
/**
* Simple trigger that runs each time the user manually edits the spreadsheet.
*
* @param {Object} e The "on edit" event object.
*/
function onEdit(e) {
if (!e) throw new Error('Please do not run the onEdit(e) function in the script editor window. It runs automatically when you manually edit the spreadsheet.');
try {
autoProtect_(e);
} catch (error) {
SpreadsheetApp.getActive().toast(error.message, 'autoProtect_', 30);
throw error;
}
}
/**
* Protects ranges so that they cannot be changed by another user later.
*
* @param {Object} e The "on edit" event object.
*/
function autoProtect_(e) {
if (e.range.getSheet().getName().match(/^(Shared|Temp|Playground)$/i)) return;
protectRange_(e.range);
}
/**
* Protects a range.
* When warningOnly is truthy, editing the range will show a warning to all users.
* Otherwise, the account who runs the script retains edit rights to the range, but
* the range is write-protected for others accounts, except the account that owns
* the spreadsheet. The owner can always edit everything in the spreadsheet.
*
* @param {Range} range The range to protect.
* @param {Boolean} warningOnly Determines whether to protect the range with "show a warning" or "restrict who can edit".
* @return {Range} The same range, for chaining.
*/
function protectRange_(range, warningOnly) {
// version 1.3, written by --Hyde, 13 June 2026
var me = Session.getEffectiveUser();
var protection = range.protect();
if (warningOnly) {
protection.setWarningOnly(true);
} else {
try {
protection.addEditor(me);
} catch (error) {
console.log(error);
}
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
return range;
}