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

Excel自定义函数键值对缓存实现及Office Runtime Storage替代方案咨询

在Excel自定义函数中实现键值对缓存

一、基础内存缓存实现(会话级)

如果只需要在当前Excel会话中缓存数据(关闭后清空),直接用全局对象存储最简便,无需依赖Excel API:

// 全局内存缓存,仅当前Excel会话有效
const memoryCache = {};

/**
 * @customfunction
 * @param {string} searchKey 搜索关键词
 * @returns {Promise<string>} 搜索结果
 */
async function SEARCH_WITH_CACHE(searchKey) {
  // 优先从缓存读取
  if (memoryCache.hasOwnProperty(searchKey)) {
    return memoryCache[searchKey];
  }
  
  // 执行实际搜索/计算逻辑(示例为模拟异步请求)
  const result = await fetchExternalData(searchKey);
  
  // 将结果存入缓存
  memoryCache[searchKey] = result;
  return result;
}

// 模拟外部数据请求(替换为你的实际逻辑)
async function fetchExternalData(key) {
  await new Promise(resolve => setTimeout(resolve, 1000));
  return `查询结果:${key}`;
}

二、Office Runtime Storage 类型错误排查

你遇到的"wrong data type"错误,通常是因为存储了不可序列化的数据类型(比如函数、Date对象、Symbol、循环引用对象等)。解决方法是将数据转换为可JSON序列化的基本类型:

  • 日期对象转ISO字符串:new Date().toISOString()
  • 复杂对象转JSON字符串:JSON.stringify(yourObject)
  • 读取时再反序列化:JSON.parse(storedValue)

示例修正代码:

// 存储时序列化
await OfficeRuntime.storage.setItem("user_data", JSON.stringify({name: "John", age: 30}));

// 读取时反序列化
const storedData = await OfficeRuntime.storage.getItem("user_data");
const userData = JSON.parse(storedData);

三、替代Office Runtime Storage的缓存方案

1. 隐藏工作表存储(持久化,跨会话)

将缓存数据存在隐藏工作表的单元格中,通过键值对映射存储,适合所有Excel版本:

// 从缓存工作表读取数据
async function getSheetCache(key) {
  return await Excel.run(async (context) => {
    const sheet = context.workbook.worksheets.getItemOrNullObject("CacheSheet");
    await context.sync();
    if (sheet.isNullObject) return null;
    
    const usedRange = sheet.getUsedRange();
    await context.sync();
    const values = usedRange.values;
    
    for (const row of values) {
      if (row[0] === key) return row[1];
    }
    return null;
  });
}

// 写入缓存工作表
async function saveSheetCache(key, value) {
  await Excel.run(async (context) => {
    let sheet = context.workbook.worksheets.getItemOrNullObject("CacheSheet");
    await context.sync();
    
    // 不存在则创建隐藏工作表
    if (sheet.isNullObject) {
      sheet = context.workbook.worksheets.add("CacheSheet");
      sheet.visibility = Excel.SheetVisibility.hidden;
    }
    
    // 找到最后一行写入新数据
    const lastRow = sheet.getRange("A:A").getLastCell().rowIndex + 1;
    sheet.getRange(`A${lastRow}`).values = [[key]];
    sheet.getRange(`B${lastRow}`).values = [[value]];
    await context.sync();
  });
}

2. 自定义XML部件(持久化,结构化存储)

在Excel文件中嵌入自定义XML部件存储键值对,不会被用户误编辑,适合结构化数据:

// 从XML部件读取缓存
async function getXmlCache(key) {
  return await Excel.run(async (context) => {
    const xmlParts = context.workbook.customXmlParts.getByNamespace("http://excel.cache.namespace");
    await context.sync();
    if (xmlParts.items.length === 0) return null;
    
    const xmlString = await xmlParts.items[0].getXml();
    const xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
    const entry = xmlDoc.querySelector(`entry[key="${key}"]`);
    
    return entry ? entry.textContent : null;
  });
}

// 写入XML部件缓存
async function saveXmlCache(key, value) {
  await Excel.run(async (context) => {
    let xmlParts = context.workbook.customXmlParts.getByNamespace("http://excel.cache.namespace");
    await context.sync();
    let xmlPart;
    
    // 不存在则创建新XML部件
    if (xmlParts.items.length === 0) {
      xmlPart = context.workbook.customXmlParts.add(`<cache xmlns="http://excel.cache.namespace"></cache>`);
    } else {
      xmlPart = xmlParts.items[0];
    }
    
    // 更新XML内容
    const xmlString = await xmlPart.getXml();
    const xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
    let entry = xmlDoc.querySelector(`entry[key="${key}"]`);
    
    if (!entry) {
      entry = xmlDoc.createElementNS("http://excel.cache.namespace", "entry");
      entry.setAttribute("key", key);
      xmlDoc.documentElement.appendChild(entry);
    }
    entry.textContent = value;
    
    const updatedXml = new XMLSerializer().serializeToString(xmlDoc);
    xmlPart.setXml(updatedXml);
    await context.sync();
  });
}

3. LocalStorage(仅Excel Web版可用)

如果只针对Web版Excel,可直接使用浏览器的localStorage,操作简单:

// 读取缓存
function getLocalCache(key) {
  return localStorage.getItem(`excel_cache_${key}`);
}

// 写入缓存
function saveLocalCache(key, value) {
  localStorage.setItem(`excel_cache_${key}`, value);
}

内容的提问来源于stack exchange,提问作者Shiv Yadav

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:35:23