You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Apps Script图片压缩转存至表格功能失效求助

Google Apps Script:修复表单提交图片转存压缩并插入合并单元格的问题

原有脚本的核心问题

Script1的问题

  • Drive图片权限错误:直接用UrlFetchApp.fetch()请求Drive图片链接,若图片未公开,会因权限不足抛出错误,导致Blob无法获取。
  • 图片插入位置偏离:insertImage(blob, 2, 10, 8, 15)指定的插入位置与目标合并单元格B11:H25完全不符。
  • 临时文件逻辑冗余:创建压缩后的临时文件后立即删除,后续插入的仍是原Blob,压缩效果未实际生效。

简化脚本的问题

  • 缩略图链接不稳定:getThumbnailLink()返回临时授权链接,过期后无法显示,且未处理权限验证。
  • 合并单元格插入逻辑错误:直接对合并单元格区域调用insertImage(),Spreadsheet无法识别正确插入位置,需指定起始单元格。
  • Blob转换错误:Utilities.newBlob(resizedImage)无法直接将ImagesService.Image对象转为Blob,需调用getBlob()方法。
  • Drive ID提取不严谨:正则表达式无法匹配所有Drive链接格式(如含?id=参数的链接)。

修复后的完整脚本

function onFormSubmit(e) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const respostasSheet = ss.getSheetByName("respostas");
  const evidenciasSheet = ss.getSheetByName("evidencias");
  
  // 优先用表单提交事件对象获取目标行,避免重复处理
  const targetRow = e ? e.range.getRow() : respostasSheet.getLastRow();
  const textContent = respostasSheet.getRange(targetRow, 2).getValue();
  const imgDriveUrl = respostasSheet.getRange(targetRow, 3).getValue();
  
  // 转存文本到evidencias的B7单元格
  evidenciasSheet.getRange("B7").setValue(textContent);
  
  // 无图片链接则终止处理
  if (!imgDriveUrl) return;
  
  try {
    // 提取Drive文件ID(兼容多种链接格式)
    const fileId = extractDriveFileId(imgDriveUrl);
    if (!fileId) throw new Error("无法提取Drive文件ID");
    
    const imgFile = DriveApp.getFileById(fileId);
    // 校验文件是否为图片类型
    if (!imgFile.getMimeType().startsWith("image/")) throw new Error("Drive文件不是图片");
    
    let resizedBlob;
    const originalBlob = imgFile.getBlob();
    const originalSize = originalBlob.getBytes().length;
    
    // 图片超过1MB时触发压缩
    if (originalSize > 1000000) {
      resizedBlob = resizeImage(originalBlob, 800, 600); // 最大宽800,高600
    } else {
      resizedBlob = originalBlob;
    }
    
    // 清空目标合并单元格并插入图片
    const targetRange = evidenciasSheet.getRange("B11:H25");
    targetRange.clear();
    
    // 插入到合并单元格起始位置,按比例适配区域大小
    const image = evidenciasSheet.insertImage(resizedBlob, targetRange.getColumn(), targetRange.getRow());
    const rangeWidth = targetRange.getWidth();
    const rangeHeight = targetRange.getHeight();
    
    // 保持图片比例,避免拉伸变形
    const imgRatio = image.getWidth() / image.getHeight();
    const rangeRatio = rangeWidth / rangeHeight;
    
    if (imgRatio > rangeRatio) {
      image.setWidth(rangeWidth);
      image.setHeight(rangeWidth / imgRatio);
    } else {
      image.setHeight(rangeHeight);
      image.setWidth(rangeHeight * imgRatio);
    }
    
  } catch (error) {
    console.error("图片处理错误:", error.message);
    // 在目标区域记录错误信息,方便排查
    evidenciasSheet.getRange("B11").setValue(`图片处理失败: ${error.message}`);
  }
}

// 兼容多种Drive链接格式的ID提取函数
function extractDriveFileId(url) {
  const regexPatterns = [
    /[-\w]{25,}/, // 基础ID匹配
    /id=([-\w]{25,})/, // ?id=xxx格式
    /d\/([-\w]{25,})\// // /d/ID/ 格式
  ];
  
  for (const pattern of regexPatterns) {
    const match = url.match(pattern);
    if (match) {
      return match[1] || match[0];
    }
  }
  return null;
}

// 按比例压缩图片的函数
function resizeImage(blob, maxWidth, maxHeight) {
  const image = ImagesService.getImage(blob);
  let width = image.getWidth();
  let height = image.getHeight();
  
  // 计算缩放比例,取最小比例保证图片完全适配限制
  const widthRatio = maxWidth / width;
  const heightRatio = maxHeight / height;
  const scaleRatio = Math.min(widthRatio, heightRatio);
  
  if (scaleRatio < 1) {
    width *= scaleRatio;
    height *= scaleRatio;
    const resizedImage = image.getScaledInstance(Math.round(width), Math.round(height));
    return resizedImage.getBlob().setName(blob.getName());
  }
  
  // 无需压缩则返回原Blob
  return blob;
}

关键修复说明

  1. 权限兼容的图片获取:通过DriveApp.getFileById()直接获取图片文件,避免UrlFetchApp的权限问题,需确保脚本拥有Drive访问权限。
  2. 精准的Drive ID提取:兼容多种Drive链接格式,避免因链接格式差异导致ID提取失败。
  3. 合并单元格图片适配:先清空目标区域,再插入到合并单元格起始位置,按比例调整图片大小,避免变形或超出区域。
  4. 严谨的错误处理:捕获每一步异常并在表格中记录,方便排查问题。
  5. 事件对象优先:使用表单提交事件对象获取目标行,避免手动编辑表格导致重复处理。

使用注意事项

  • 配置表单提交触发器:在脚本编辑器中,点击「编辑」→「当前项目的触发器」,添加「表单提交」类型触发器,关联onFormSubmit函数。
  • 授权权限:首次运行脚本时,需同意访问Drive和Spreadsheet的权限请求。
  • 提前设置合并单元格:确保evidencias标签页已创建B11:H25的合并单元格区域。

内容的提问来源于stack exchange,提问作者Casual Developer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 22:15:28