Google Sheets插入图片后调用assignScript等方法导致图片首次不显示
问题描述
用Google Apps Script插入图片后,只要调用assignScript()、setWidth()或setHeight()这类修改图片属性的方法,首次执行就会导致图片消失,必须手动刷新页面才能正常显示;但手动给图片分配脚本完全正常,且整个流程是通过自定义菜单触发的。
问题代码回顾
插入图片的基础代码能正常显示图片:
const data = Utilities.newBlob(Utilities.base64Decode("<my base64 string>"), "image/png") const image = sheet.insertImage(data, 1, 4)
但添加image.assignScript("show")后,图片就消失;后续测试发现只要调用任何图片属性修改方法都会触发这个问题,且仅首次执行出现,刷新后恢复。
完整触发流程是自定义菜单调用创建新工作表,插入模板数据后调用addRunButton插入带脚本的图片:
function onOpen(){ const ui = SpreadsheetApp.getUi() ui.createMenu('My menu') .addSubMenu(ui.createMenu('Templates') .addItem('Item 1', 'myFunctionForItem1') ).addToUi() } function myFunctionForItem1() { const ss = SpreadsheetApp.getActiveSpreadsheet() ss.insertSheet("title",0) const sheet = SpreadsheetApp.getActiveSheet() sheet.getRange(1,1,template.length,template[0].length).setValues(template) SpreadsheetApp.flush() addRunButton(2, 1, 'show') } function addRunButton(row, column, fun) { const sheet = SpreadsheetApp.getActiveSheet() // 注意:原代码此处参数顺序错误,已修正 const data = Utilities.newBlob(Utilities.base64Decode("<my base64 string>"), "image/png") const image = sheet.insertImage(data, column, row) SpreadsheetApp.flush() image.assignScript(fun) SpreadsheetApp.flush() }
解决方法
这个问题本质是Google Sheets的UI渲染速度跟不上脚本执行速度,脚本修改图片属性时,UI还没完成图片的渲染初始化,导致属性修改无法同步到UI。以下是几个可行的解决思路:
1. 插入图片后加短暂延迟
给UI足够的时间渲染图片,再执行属性修改:
function addRunButton(row, column, fun) { const sheet = SpreadsheetApp.getActiveSheet() const data = Utilities.newBlob(Utilities.base64Decode("<my base64 string>"), "image/png") const image = sheet.insertImage(data, column, row) SpreadsheetApp.flush() // 延迟1秒,确保UI完成图片渲染 Utilities.sleep(1000) image.assignScript(fun) SpreadsheetApp.flush() }
2. 切换工作表强制触发UI刷新
通过临时切换到其他工作表再切回来,让UI重新加载所有元素,无需手动刷新:
function myFunctionForItem1() { const ss = SpreadsheetApp.getActiveSpreadsheet() const newSheet = ss.insertSheet("title",0) // 插入模板数据 newSheet.getRange(1,1,template.length,template[0].length).setValues(template) SpreadsheetApp.flush() addRunButton(2, 1, 'show', newSheet) // 切换工作表触发UI刷新 const otherSheet = ss.getSheets().find(s => s.getSheetName() !== newSheet.getSheetName()) if (otherSheet) { otherSheet.activate() SpreadsheetApp.flush() newSheet.activate() SpreadsheetApp.flush() } } // 修改addRunButton,直接传入目标sheet,避免重复获取 function addRunButton(row, column, fun, sheet) { const data = Utilities.newBlob(Utilities.base64Decode("<my base64 string>"), "image/png") const image = sheet.insertImage(data, column, row) SpreadsheetApp.flush() image.assignScript(fun) SpreadsheetApp.flush() }
3. 先给Blob设置属性再插入(针对尺寸修改场景)
如果需要调整图片尺寸,可以先给Blob设置宽高,再插入到工作表,跳过后续修改图片属性的步骤:
function addRunButton(row, column, fun) { const sheet = SpreadsheetApp.getActiveSheet() const blob = Utilities.newBlob(Utilities.base64Decode("<my base64 string>"), "image/png") // 提前设置Blob的宽高 blob.setWidth(120) blob.setHeight(40) const image = sheet.insertImage(blob, column, row) image.assignScript(fun) SpreadsheetApp.flush() }
额外注意
原代码中Utilities.newBlob()的参数顺序有误,正确用法是Utilities.newBlob(字节数组, MIME类型),之前的错误写法可能也会导致图片加载异常,务必修正。
内容的提问来源于stack exchange,提问作者al1812
相关产品推荐
相关产品推荐

