JSA复制图片到剪切板再嵌入单元格
曲折的做法,原始的写法。根据需要自行完善。
function copyPic(){
Range("A1:A4").Select()
Selection.CopyPicture();
}
function Clipboard(){
console.clear();
copyPic()
let DIB = ffi.Struct([
{ name: "biSize", type: "uint32" },
{ name: "biWidth", type: "uint32" },
{ name: "biHeight", type: "uint32" },
{ name: "biPlanes", type: "uint16" },
{ name: "biBitCount", type: "uint16" },
{ name: "biCompression", type: "uint32" },
{ name: "biSizeImage", type: "uint32" },
{ name: "biXPelsPerMeter", type: "uint32" },
{ name: "biYPelsPerMeter", type: "uint32" },
{ name: "biClrUsed", type: "uint32" },
{ name: "biClrImportant", type: "uint32" }
])
//let dib = new DIB(); //暂时没用
const {GlobalAlloc,GlobalLock,GlobalUnlock,RtlMoveMemory} = ffi.LoadLibrary('kernel32.dll', {
GlobalAlloc: { returnType: "pointer", parameters: ["uint32", "uint32"] },
GlobalLock: { returnType: "pointer", parameters: ["uint32"] },
GlobalUnlock: { returnType: "bool", parameters: ["uint32"] },
RtlMoveMemory: { returnType: "void", parameters: ["pointer", "pointer", "uint32"] }
});
const {CountClipboardFormats,EnumClipboardFormats,OpenClipboard,CloseClipboard,GetClipboardData,
EmptyClipboard,SetClipboardData,IsClipboardFormatAvailable} = ffi.LoadLibrary("user32.dll",{
CountClipboardFormats: { returnType: "uint32", parameters: []},
EnumClipboardFormats:{ returnType: "uint32", parameters: ["uint32"]},
OpenClipboard:{ returnType: "bool", parameters: ["pointer"]},
CloseClipboard:{ returnType: "bool", parameters: []},
GetClipboardData:{ returnType: "uint32", parameters: ["uint32"]},
EmptyClipboard: { returnType: "bool", parameters: [] },
SetClipboardData: { returnType: "pointer", parameters: ["uint32", "pointer"] },
IsClipboardFormatAvailable : { returnType: "bool", parameters: ["uint32"] }
})
let count = CountClipboardFormats();
console.log("剪切板格式总数:" + count);
OpenClipboard(null);
let hClipboard = GetClipboardData(49465);
console.log("图像数据句柄:" +hClipboard )
let mdib = GlobalLock(hClipboard);
//Console.log("图像大小:" + mdib.Read("uint8",48)); //从偏移0开始读取4字节数据 内存中为 89 50 4E 47 读出来后转换为 47 4E 50 89 => 1196314761
//la = hexToArr(numToHex(mdib.Read("uint32",32)));
let bytes = 32;
for(let index = 1;index<5;index++){
let la = hexToArr(numToHex(mdib.Read("uint32",bytes + 1)));
console.log(JSON.stringify(la))
if(la.length == 1){
bytes+=13
break;
}else{
off = la[0]+la[1]*256+la[2]*65536 + la[3]*16777216;
Console.log("块大小:" + (off));
bytes+=(off+12)
}
Console.log("指针位置:" + (bytes));
}
Console.log("图像大小:" + (bytes));
let str=''
let byteArray =[]
for(let i=0;i<bytes;i++){
byteArray.push(mdib.Read("uint8",i))
}
//console.log(JSON.stringify(byteArray))
let binaryString = ''
byteArray.forEach(i => binaryString += String.fromCharCode(i))
let pngpath = "D:/test.png"
FileSystem.writeAsBinaryString(pngpath,binaryString)
Range("E2").RangeEx.InsertCellPicture(pngpath);
try{
//Range("E2").RangeEx.InsertCellPictureRaw(binaryString); //不知道具体实现参数
}
catch{
console.log(1)
GlobalUnlock(hClipboard);
}
//Console.log("图像大小:" + mdib.DerefString());
GlobalUnlock(hClipboard);
//49161,13,1,49411,49804,49171,16,7,0 //单纯文本
// 和下一行对应: 49161, 49800, 49465, 49801, 49171 //复制一个单元格,格式为图片
// DataObject,Kingsoft Shapes Tag, Png, Et Embed Pic Formats,OLE Private DataView
//49161 == DataObject
// 49171 == OLE Private DataView
//13 == Unicode Text Format
//1 == Text
// 49465 == PNG ? C1 39
let nextFormat = EnumClipboardFormats(0);
console.log("第一个剪切板格式:"+nextFormat)
let available = IsClipboardFormatAvailable(49465)
console.log("剪切板格式是否存在:"+available)
CloseClipboard();
}
function numToHex(arg) {
try {
let a = arg.toString(16).toUpperCase();
return a.length % 2 == 1 ? "0" + a : a;
} catch (e) {
console.warn("数字转16进制出错:", e);
}
}
function hexToArr(str) {
// hex字符串长度通常都是2的倍数,但为了放止意外,判断一下长度,不是2的倍数就在最前面补0
if (str.length % 2) str = "0" + str
let arr=[]
for (let i = 0; i < str.length; i+=2) {
let a=parseInt(str.slice(i,i+2),16)
arr.push(a)
}
return arr
}