找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 28|回复: 0

[转载代码] 在办公软件WPS的JSA中操作剪贴板文本

[复制链接]
发表于 昨天 17:38 | 显示全部楼层 |阅读模式
使用方法:        //JS代码,在WPS的JSA宏中使用
  1. var 剪贴板文本=获取剪贴板文本();
  2. var 修改文本="新文本:\n"+ 剪贴板文本 +"\n字符串结束!";
  3. 设置剪贴板文本(修改文本);        //新文本放入剪贴板,可粘贴使用
复制代码


办公软件WPS的JSA宏无法直接使用系统剪贴板,但可以通过ExecuteExcel4Macro的CALL来调用系统功能以实现剪贴板操作。
最新版本的WPS可以用FFI/ffi方便实现,但没有这些的中间版本就需要ExecuteExcel4Macro了。

使用ExecuteExcel4Macro调用CALL时有所限制。CALL的函数其 参数/返回值 如果是字符串,则最大只到255字节(缓冲区256字节,包含有一字节结束符)。所以只要调用的函数(系统API)有其中一个参数是字符串,或是返回值是字符串,都需要切成小段逐段处理。

设置剪贴板文本("文本/字符串");
  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. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-25 03:27

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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