找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 87|回复: 12

办公WPS的JSA中操作剪贴板文本

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
本帖最后由 cutebe 于 2026-3-24 17:02 编辑

使用方法       //JS代码,WPS的JS宏
  1. var 剪贴板文本=获取剪贴板文本();
  2. var 修改文本="新文本:\n"+ 剪贴板文本 +"\n字符串结束!";
  3. 设置剪贴板文本(修改文本);        //新文本放入剪贴板,可粘贴使用
复制代码


设置剪贴板文本("字符串");
  1. function 设置剪贴板文本(文本内容){        //文本内容 需要复制到剪贴板的文本
  2.         let 执行宏调用=ExecuteExcel4Macro;        //调用系统应用接口。简化书写
  3.         //在ExecuteExcel4Macro中调用CALL,限制字符串类型参数的长度小于等于255。        //一个汉字占2个字节
  4.         //let 文本字节长度 = 执行宏调用(`CALL("kernel32","lstrlenA","JF","${文本内容}")`);        //参数为字符串引号包起        //字符串变量参数,类型必须用F,用C则出错。
  5.         //let 文本字节长度 = 执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //参数为(字符串的)内存地址指针时不限制
  6.         let 分段文本=[],段长度=127,分段长=[],总字节=0;        //每段最长256字节,去掉结束符\0,双字节文字最长127
  7.         for(let i=0;i<文本内容.length;i+=段长度){
  8.                 分段文本.push(文本内容.slice(i,i+段长度));
  9.         }
  10.         for(let i=0;i<分段文本.length;i++){        //字符串长度length,不同于字节长度
  11.                 分段长[i]=执行宏调用(`CALL("kernel32","lstrlenA","JF","${分段文本[i]}")`);        //计算字符串字节长度(参数为JS字符串变量时,字符串最大255字节。)
  12.                 总字节+=分段长[i];        //console.log("分段文本 "+分段长[i]+":"+分段文本[i]);
  13.         }
  14.         let 内存句柄,内存地址,剪贴板文本;                //console.clear();        //清空立即窗口(控制台)信息
  15.         if (执行宏调用(`CALL("user32.dll","OpenClipboard","AJ",0)`)){                //打开剪贴板
  16.                 if(执行宏调用(`CALL("user32.dll","EmptyClipboard","A")`)){        //清空剪切板
  17.                         内存句柄=执行宏调用(`CALL("Kernel32","GlobalAlloc","JJJ",${0x00000002},${总字节+1})`);                //在堆中分配可移动内存
  18.                         //console.log("内存块大小:"+执行宏调用(`CALL("Kernel32","GlobalSize","JJ",${内存句柄})`));        //查看分配的内存块的大小
  19.                         if(内存句柄){        //内存分配成功。然后锁定(写的)内存对象,字符串复制到(写入)内存,解锁。最后设置剪贴板。
  20.                                 内存地址=执行宏调用(`CALL("kernel32.dll","GlobalLock","JJ",${内存句柄})`);        //锁定全局内存对象,获取指向内存句柄的(内存块指针)内存地址
  21.                                 let 偏移字节=0;        //将文本复制至 锁定全局内存对象                //字符串变量必须用双引号引上。类型必须用F
  22.                                 for(let i=0;i<分段文本.length;i++){        //字符串(JS变量)分批复制到刚申请的内存中。分批是因为有限长
  23.                                         执行宏调用(`CALL("kernel32.dll","lstrcpynW","JJFJ",${内存地址+偏移字节},"${分段文本[i]}",${分段长[i]})`);
  24.                                         偏移字节+=分段长[i];        //第二个参数为字符串时返回的是地址。
  25.                                 }
  26.                                 执行宏调用(`CALL("kernel32.dll","GlobalUnlock","JJ",${内存句柄})`);        //解锁全局内存对象,以释放资源
  27.                                 //数据放入剪切板,参数为1则返回文本
  28.                                 剪贴板文本=执行宏调用(`CALL("user32.dll","SetClipboardData","JJJ",1,${内存句柄})`);        //仅设置剪贴板文本:参数CF_TEXT=1
  29.                         }else{console.log("未能分配内存!");}
  30.                 }else{console.log('未能清空剪贴板!');}
  31.                 执行宏调用(`CALL("user32.dll","CloseClipboard","A")`);        //关闭剪贴板,以释放控制权。(让其它应用可以使用剪贴板)
  32.         }else{alert('无法打开剪贴板!');}
  33. }
复制代码

获取剪贴板文本();

  1. function 获取剪贴板文本() {//获取剪贴板文本,只能获取255字节内容
  2.         let 内存句柄,内存地址,剪贴板文本="";
  3.         let 执行宏调用=ExecuteExcel4Macro;        //简化代码书写
  4.         if(执行宏调用(`CALL("user32.dll","OpenClipboard","JJ",0)`)){        //打开剪贴板
  5.                 内存句柄=执行宏调用(`CALL("user32.dll","GetClipboardData","JJ",1)`);        //获取剪贴板数据,返回剪贴板数据的内存块句柄。只取剪贴板中文本:CF_TEXT=1
  6.                 if(内存句柄){
  7.                         内存地址=执行宏调用(`CALL("kernel32.dll","GlobalLock","JJ",${内存句柄})`);        //锁定全局内存对象,获取指向内存句柄的(内存块指针)内存地址
  8.                         let 总字节,偏移字节=0,段字节=127,分段文本='';
  9.                         总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //剪贴板文本字节数
  10.                         while(偏移字节<总字节){        //第二个参数为地址时,返回字符串。返回值超256字节时,也需要分段操作
  11.                                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段字节})`);        //分批获取超256字节的文本
  12.                                 偏移字节+=段字节;剪贴板文本+=分段文本;
  13.                         }
  14.                         执行宏调用(`CALL("kernel32.dll","GlobalUnlock","JJ",${内存句柄})`);        //解锁全局内存对象,使内存可以回收
  15.                 }else{console.log("未能获取剪贴板数据的内存句柄!");}
  16.                 执行宏调用(`CALL("user32.dll","CloseClipboard","J")`);        //关闭剪贴板
  17.                 return 剪贴板文本;        //返回字符串
  18.         }else{alert('无法打开剪贴板!');}
  19. }
复制代码


 楼主| 发表于 3 小时前 | 显示全部楼层
适用于WPS支持ExecuteExcel4Macro的旧版本(还没有FFI与ffi的版本)。
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
WPS JSA 剪贴板操作代码(优化版)


长文本无损读写剪贴板(突破 255 字符限制),可直接在 WPS 表格 / 文字 / 演示的 JSA 宏中使用。


完整可用代码



  1. // 【工具函数】剪贴板操作 - 支持超长文本、无乱码、稳定运行
  2. // 获取剪贴板文本(支持超长内容)
  3. function GetClipboardText() {
  4.     let text = "";
  5.     const exec = ExecuteExcel4Macro;
  6.    
  7.     if (exec('CALL("user32","OpenClipboard","JJ",0)')) {
  8.         const hMem = exec('CALL("user32","GetClipboardData","JJ",1)');
  9.         if (hMem) {
  10.             const ptr = exec('CALL("kernel32","GlobalLock","JJ",' + hMem + ')');
  11.             const len = exec('CALL("kernel32","lstrlenA","JJ",' + ptr + ')');
  12.             
  13.             let offset = 0, chunk = 127;
  14.             while (offset < len) {
  15.                 const part = exec('CALL("kernel32","lstrcpynW","FFJJ","",' + (ptr + offset) + ',' + chunk + ')');
  16.                 text += part;
  17.                 offset += chunk;
  18.             }
  19.             
  20.             exec('CALL("kernel32","GlobalUnlock","JJ",' + hMem + ')');
  21.         }
  22.         exec('CALL("user32","CloseClipboard","J")');
  23.     }
  24.     return text;
  25. }

  26. // 设置剪贴板文本(支持超长内容)
  27. function SetClipboardText(content) {
  28.     const exec = ExecuteExcel4Macro;
  29.     if (!exec('CALL("user32","OpenClipboard","AJ",0)')) { alert("打开剪贴板失败"); return; }
  30.     exec('CALL("user32","EmptyClipboard","A")');

  31.     // 分段处理(规避255字节限制)
  32.     const chunks = [], maxLen = 127;
  33.     for (let i = 0; i < content.length; i += maxLen) chunks.push(content.slice(i, i + maxLen));
  34.    
  35.     // 计算总字节
  36.     let totalBytes = 0;
  37.     chunks.forEach(s => totalBytes += exec('CALL("kernel32","lstrlenA","JF","' + s + '")'));

  38.     // 分配内存
  39.     const hMem = exec('CALL("kernel32","GlobalAlloc","JJJ",2,' + (totalBytes + 1) + ')');
  40.     if (!hMem) { exec('CALL("user32","CloseClipboard","A")'); return; }

  41.     // 写入内存
  42.     const ptr = exec('CALL("kernel32","GlobalLock","JJ",' + hMem + ')');
  43.     let offset = 0;
  44.     chunks.forEach(s => {
  45.         exec('CALL("kernel32","lstrcpynW","JJFJ",' + (ptr + offset) + ',"' + s + '",' + s.length + ')');
  46.         offset += exec('CALL("kernel32","lstrlenA","JF","' + s + '")');
  47.     });

  48.     exec('CALL("kernel32","GlobalUnlock","JJ",' + hMem + ')');
  49.     exec('CALL("user32","SetClipboardData","JJJ",1,' + hMem + ')');
  50.     exec('CALL("user32","CloseClipboard","A")');
  51. }

  52. // ==================== 测试主函数 ====================
  53. function TestClipboard() {
  54.     // 读取剪贴板原有文本
  55.     var oldText = GetClipboardText();
  56.    
  57.     // 加工文本
  58.     var newText = "===== 处理开始 =====\n" + oldText + "\n===== 处理结束 =====";
  59.    
  60.     // 写入剪贴板
  61.     SetClipboardText(newText);
  62.    
  63.     MsgBox("操作完成!\n已修改剪贴板文本", 0, "成功");
  64. }
复制代码




回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
用WPS操作剪切板是什么操作???


二○二六年三月二十四日

点评

有些是表格中内容复制后,需要处理转化然后再粘贴到记事本等。 有些是网页中复制后,经过处理填入表格。以上可能用到剪贴板! 获取/设置剪贴板文本 这两个功能就可以被自定义的按钮调用了。  详情 回复 发表于 3 小时前
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
感谢分享!
回复

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
邪恶海盗 发表于 2026-3-24 17:32
用WPS操作剪切板是什么操作???

有些是表格中内容复制后,需要处理转化然后再粘贴到记事本等。
有些是网页中复制后,经过处理填入表格。以上可能用到剪贴板!
获取/设置剪贴板文本 这两个功能就可以被自定义的按钮调用了。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层
支持分享
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
学习一下
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
这属于是什么

点评

办公软件表格的宏,JSA类似VBA  发表于 半小时前
回复

使用道具 举报

发表于 11 分钟前 | 显示全部楼层
宏是很好用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持| 无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-3-24 20:59

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表