【代码分享】【本地表JS宏】将Base64编码的图片插入到WPS表格指定单元格位置

标题写的很清楚,用到的朋友可以直接拿去,不想写太多文字了今天搞累了。。。

function test() {Console.clear()
    图片base64 = 'data:image/png;base64,iVBORw0KGgo。。。'
    InsertBase64ImageToCell(图片base64, Range("e4"),300,200)
}

/**by theMath404 & 各种AI 花了好几个小时!
 * 在 WPS12.1.0.25860 本地表格的JSA 能成功运行,后续版本自行测试
 * 引用还望注明出处,谁说AI写代码很强了?我都是一把屎一把尿搞出来的!
 * 最后编辑:2026.04.29
 
 * 【功能说明】将Base64编码的图片插入到WPS表格指定单元格位置(纯原生兼容版)
 */
function InsertBase64ImageToCell(base64Str, targetCell, imgWidth=-1, imgHeight=-1, placement=xlMoveAndSize) {
    Console.log("==================== 开始执行图片插入 ====================");
    
    try {
        if (!base64Str || typeof base64Str !== "string") {
            throw new Error("参数错误:base64Str不能为空且必须为字符串类型");
        }
        if (!targetCell || typeof targetCell.Left === "undefined" || typeof targetCell.Top === "undefined" || typeof targetCell.Address !== "function") {
            throw new Error("参数错误:targetCell必须为Range对象(例如Range('B2')),请勿直接传单元格地址字符串");
        }
        if (imgWidth !== -1 && (typeof imgWidth !== "number" || imgWidth <= 0)) {
            throw new Error("参数错误:imgWidth必须为正整数或-1");
        }
        if (imgHeight !== -1 && (typeof imgHeight !== "number" || imgHeight <= 0)) {
            throw new Error("参数错误:imgHeight必须为正整数或-1");
        }
        // ========== 2. 处理Base64前缀 ==========
        if (base64Data.length === 0) {
            throw new Error("Base64内容为空,可能是格式错误");
        }
        // ========== 3. 生成两种格式的临时文件路径(已修复斜杠不一致问题) ==========
        // 第一步:先把临时目录所有斜杠统一转成反斜杠,再去除末尾的斜杠,最后补一个反斜杠,确保目录格式100%纯反斜杠
        const tempDir = Env.GetTempPath().replace(/\//g, "\\").replace(/\\+$/, "") + "\\";
        const fileName = "temp_img_" + Date.now() + ".png";
        // writePath:全程纯反斜杠,用于写入、删除
        const writePath = tempDir + fileName;
        // readPath:全程纯正斜杠,仅用于AddPicture
        const readPath = tempDir.replace(/\\/g, "/") + fileName;
        // ========== 4. 直接Base64转二进制字符串(恢复原自定义函数,适配WPS环境) ==========
        const binaryStr = base64ToBinary(base64Data);
        if (binaryStr.length < 100) {
            throw new Error("Base64解析失败,内容过短,可能是Base64格式错误");
        }
        // ========== 5. 写入临时文件(核心修复:使用writeAsBinaryString纯二进制写入,严格遵循官方API) ==========
        FileSystem.writeAsBinaryString(writePath, binaryStr);
        // ========== 6. 插入图片到工作表(用readPath正斜杠路径) ==========
        const msoTrue = -1;
        const msoFalse = 0;
        const shape = targetCell.Worksheet.Shapes.AddPicture( readPath,
            msoFalse, msoTrue,targetCell.Left, targetCell.Top,imgWidth, imgHeight
        );
        if (!shape) {
            throw new Error("Shapes.AddPicture调用失败,未返回Shape对象(可能是路径格式错误或文件损坏)");
        }
        // ========== 7. 后续设置与清理(用writePath反斜杠路径删除) ==========
        shape.Placement = placement;
        
        // 删除临时文件
        try {
            // 修复:使用官方API FileSystem.Remove 替代 Kill
            FileSystem.Remove(writePath);
            Console.log("✅ 临时文件已删除");
        } catch(e) {
            // 修复:使用 Console.log 替代不支持的 Console.warn
            Console.log("⚠️ 临时文件删除失败,路径:" + writePath);
        }
        Console.log("==================== 图片插入全部完成 ====================");
        return shape;
    } catch (err) {
        Console.log(`❌ 执行失败,错误位置:${err.stack || '未知位置'}`);
        Console.log(`❌ 错误信息:${err.message}`);
        Console.log("==================== 执行异常终止 ====================");
        return null;
    }
    /**
     * 辅助函数:Base64直接转二进制字符串(适配WPS写入,无需数组中转)
     * @param {string} base64 - 无前缀的Base64字符串
     * @returns {string} 二进制字符串
     */
    function base64ToBinary(base64) {
        const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        let binary = "";
        let i = 0;
        
        base64 = base64.replace(/\s/g, "").replace(/=+$/, ""); // 去除空白和填充符
        
        while (i < base64.length) {
            const enc1 = chars.indexOf(base64.charAt(i++));
            const enc2 = chars.indexOf(base64.charAt(i++));
            const enc3 = i < base64.length ? chars.indexOf(base64.charAt(i++)) : -1;
            const enc4 = i < base64.length ? chars.indexOf(base64.charAt(i++)) : -1;
            
            if (enc1 === -1 || enc2 === -1) {
                throw new Error(`Base64解析错误,位置${i}存在非法字符:${base64.charAt(i-1)}`);
            }
            
            // 直接拼接二进制字符,无需数组中转,减少编码问题
            binary += String.fromCharCode((enc1 << 2) | (enc2 >> 4));
            if (enc3 !== -1) binary += String.fromCharCode(((enc2 & 15) << 4) | (enc3 >> 2));
            if (enc4 !== -1) binary += String.fromCharCode(((enc3 & 3) << 6) | enc4);
        }
        
        return binary;
    }
}
广西
浏览 136
收藏
7
分享
7 +1
5
+1
全部评论 5
 
wils
wils Lv.2 潜力创作者

Lv.2潜力创作者

赞赞赞👍 用剪贴板可以避免临时文件,但仍然不够简单 https://bbs.wps.cn/topic/48329 incertcellpicture那几个类似方法不知道是做什么的能不能简化操作
· 海南省
回复
λ公式探索者
①剪贴板AI说过会清除用户复制过的信息,体验感不好,所以没用 ②已阅https://bbs.wps.cn/topic/48329,得空试试 ③incertcellpicture试过了本地表没有可惜了,不知道是哪里的但是看着很熟悉。。。
· 广西
1
回复