You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

将Excel VBA的WinHttpRequest令牌获取代码迁移至Office Scripts的Fetch API时遭遇Failed to fetch错误

将Excel VBA的WinHttpRequest令牌获取代码迁移至Office Scripts的Fetch API时遭遇Failed to fetch错误

问题分析

从你的代码对比来看,VBA版本能正常工作是因为它正确处理了请求体编码、请求头和URL,但Office Scripts版本存在几个关键错误,导致了Failed to fetch异常:


关键错误点与修复方案

1. URL和请求体的取值错误

  • 你用Dsheet.getRange("TokenURL").getValue()得到的是string[]类型,但单个单元格的getValue()应该返回string,直接用数组作为fetch的URL会导致请求地址无效。
  • 同样,URLPW = Dsheet.getRange("BBody").getValues()返回的是二维数组,而不是字符串,后续的编码逻辑完全错误。

修复: 单个单元格用getValue()(返回单个值),而非getValues()(返回二维数组)。

2. 请求体的编码与格式错误

VBA里用ADODB.Stream把UTF-8文本转成带BOM的二进制,但Office Scripts里你手动拼接BOM数组的方式不对,而且fetchbody不能直接传普通数字数组,需要传Uint8Array或者符合application/x-www-form-urlencoded格式的内容。

另外,application/x-www-form-urlencoded格式的请求体,其实不需要手动转二进制,直接传编码后的字符串即可,浏览器会自动处理编码(如果是UTF-8的话)。

3. 错误的请求头设置

你添加了"Access-Control-Allow-Origin": "*"请求头,这个头是服务器用来返回给客户端的,不是客户端发送给服务器的。客户端发送这个头不仅无效,还可能干扰正常的请求处理,应该移除。


修正后的Office Scripts代码

async function main(workbook: ExcelScript.Workbook) {
  const setupSheet = workbook.getWorksheet("Setup");
  
  // 1. 正确获取单个单元格的值(非数组)
  const tokenUrl = setupSheet.getRange("TokenURL").getValue() as string;
  const bodyText = setupSheet.getRange("BBody").getValue() as string;

  try {
    // 2. 处理请求体:还原VBA里的UTF-8 BOM + 文本二进制逻辑
    const encoder = new TextEncoder();
    const bom = new Uint8Array([239, 187, 191]); // UTF-8 BOM
    const bodyBytes = encoder.encode(bodyText);
    // 拼接BOM和正文二进制
    const fullBody = new Uint8Array(bom.length + bodyBytes.length);
    fullBody.set(bom, 0);
    fullBody.set(bodyBytes, bom.length);

    // 3. 发送请求:移除错误的CORS头,对齐VBA的请求头设置
    const response = await fetch(tokenUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        "Accept": "application/json"
      },
      body: fullBody
    });

    console.log("Response Status:", response.status);

    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status} - ${response.statusText}`);
    }

    // 4. 正确解析JSON响应(替代VBA里的字符串截取,更可靠)
    const jsonResponse = await response.json();
    // 假设响应格式为 {"token": "your-token-value"},根据实际结构调整属性名
    const token = jsonResponse.token;
    setupSheet.getRange("Token").setValue(token);

  } catch (error) {
    console.error("Error retrieving token:", error);
    // 弹窗提示错误(适配Office Scripts的通知机制)
    await workbook.getApplication().displayAlert(
      "Token获取失败", 
      `错误信息: ${error instanceof Error ? error.message : String(error)}`, 
      ExcelScript.AlertType.error
    );
  }
}

额外注意事项

关于CORS错误

如果修复后仍然出现Failed to fetch,大概率是CORS跨域限制

  • Office Scripts运行在浏览器环境中,遵循浏览器的CORS政策。如果目标API的服务器没有配置允许Excel Online的域名跨域请求,浏览器会拦截请求。
  • 这种情况下,你需要联系API提供方,让他们在服务器响应头中添加Access-Control-Allow-Origin: https://office.live.com(生产环境不建议用通配符*)。
  • 或者,你可以搭建一个后端中转服务,让中转服务调用目标API,再由Office Scripts请求你的中转服务,绕过跨域限制。

关于JSON解析

VBA里用字符串截取的方式提取Token很容易因为响应格式变化失效,Office Scripts里直接解析JSON后通过属性访问会更稳定。如果不确定响应结构,可以先在console.log(jsonResponse)里查看完整响应内容,再调整提取逻辑。

火山引擎 最新活动