Google Apps Script部署版无法获取Google Docs选中内容问题求助
问题:部署后无法获取Google Docs选中文本
问题详情
在Google Apps Script编辑器中直接运行脚本时,能正常获取Google Docs里的选中文本;但通过部署版本测试,或者点击扩展程序的“从Google Docs提取文本”按钮调用时,脚本返回的JSON结果总是“未选中任何内容”(对应代码里的else分支)。
用户怀疑问题出在var selection = DocumentApp.getActiveDocument().getSelection();这行代码——因为selection变量为空,所以没进入if分支。已经在appsscript.json里配置了所有需要的权限范围,也试过改成var selection = DocumentApp.openById(docId).getSelection();的写法,但问题还是没解决,想知道原因。
相关代码
function doGet() { var selection = DocumentApp.getActiveDocument().getSelection(); Logger.log(selection); if (selection && selection.getRangeElements().length > 0) { console.log("Document loaded.") var elements = selection.getRangeElements(); var firstElement = elements[0].getElement().asText().getText(); console.log(firstElement); console.log(typeof(firstElement)); var text = JSON.parse('{"output":"'+firstElement+'"}'); console.log(text); console.log("we passed line 10"); } else { var text = JSON.parse('{"output":"Nothing is selected"}'); } console.log(text); var jsonString = JSON.stringify(text); console.log(jsonString); return ContentService.createTextOutput(jsonString).setMimeType(ContentService.MimeType.JSON); }
原因与解决办法
核心原因
当你通过部署版本(Web App)或扩展按钮调用脚本时,脚本是在服务器端独立运行的,并非绑定在当前打开的Google Docs会话里:
- 编辑器里直接运行时,脚本处于当前文档的上下文,
getActiveDocument()能拿到你正在操作的文档实例,自然能获取选中内容; - 部署后调用时,服务器端的脚本没有绑定任何打开的文档会话,
getActiveDocument()要么返回空,要么返回脚本关联的默认文档(不是你当前选中内容的那个),所以getSelection()必然为空。
可行解决思路
要获取用户当前打开的Google Docs中的选中文本,不能用Web App的doGet()方式,得用Google Docs插件的侧边栏/对话框交互模式:
改用客户端-服务端交互模式
- 先创建侧边栏前端页面(比如
sidebar.html):<!-- sidebar.html --> <button onclick="getSelectedText()">提取选中文本</button> <script> function getSelectedText() { google.script.run.withSuccessHandler(showResult).fetchSelection(); } function showResult(result) { alert(result.output); } </script> - 服务端代码改为绑定文档的函数,而非
doGet():// 服务端GS代码 function showSidebar() { var html = HtmlService.createHtmlOutputFromFile('sidebar'); DocumentApp.getUi().showSidebar(html); } function fetchSelection() { var selection = DocumentApp.getActiveDocument().getSelection(); if (selection && selection.getRangeElements().length > 0) { var firstElement = selection.getRangeElements()[0].getElement().asText().getText(); return {"output": firstElement}; } else { return {"output": "未选中任何内容"}; } } - 部署为Google Docs绑定插件,用户打开文档后通过插件菜单唤起侧边栏,点击按钮即可获取当前选中内容。
- 先创建侧边栏前端页面(比如
关键注意点
- 不要用Web App部署,而是选择发布为Google Docs插件;
- 确保appsscript.json中正确声明权限,比如
https://www.googleapis.com/auth/documents。
另外,你之前尝试的DocumentApp.openById(docId)方案无效,因为服务器端脚本无法获取用户当前打开的文档ID,即便拿到ID,打开的文档实例也没有用户的选中状态——选中状态仅存在于用户浏览器的会话中,服务器端无法直接读取。
内容的提问来源于stack exchange,提问作者S. Jilani
相关产品推荐
相关产品推荐

