JSA里的FFI(9)——通达信

wils
wils

创作者俱乐部成员

昨天有朋友问,wps表格能否联动股票软件,比如点击某个单元格,就打开对应的股票行情

首先,不推荐炒股,据说98%的小散是亏损的。。。

不过,搜了一下,用ahk自动化操作通达信这些软件的帖子真多啊,简直流量密码


先试一下JS宏打开通达信某只股票行情页

function aa()
{
    const user32 = FFI.LoadLibrary('user32')
    const RegisterWindowMessageA = user32.LoadFunction('', 'RegisterWindowMessageA', '', 'uint32', ['string'])
    const PostMessageA = user32.LoadFunction('', 'PostMessageA', '', 'bool', ['int32', 'uint32', 'int32', 'int32'])

    const UWM_STOCK = RegisterWindowMessageA.Call('Stock')
    PostMessageA.Call(0xFFFF, UWM_STOCK, 7600050, 0)
}
  • 沪市代码前加7,其它市场股票代码前面加6,这里的7600050是中国联通600050

  • 其实只是用PostMessage发了个消息


再来试一下读取日线数据,比如sh600050.day

function bb()
{
    const d = FileSystem.ReadFileAsArrayBuffer(`${ThisWorkbook.Path}\\sh600050.day`)
    const b = new ArrayBuffer(d.byteLength)
    const v = new Uint8Array(b)
    for (let i = 0; i < b.byteLength; i++) {
        v[i] = d[i]
    }
    const p = FFI.RefPointer(b.slice(-32))
    console.log(p.Read('int32', 0))
    console.log((p.Read('int32', 4) / 100).toFixed(2))
    console.log((p.Read('int32', 8) / 100).toFixed(2))
    console.log((p.Read('int32', 12) / 100).toFixed(2))
    console.log((p.Read('int32', 16) / 100).toFixed(2))
    console.log(p.Read('float', 20))
    console.log((p.Read('int32', 24) / 100).toFixed(2))
    console.log(p.Read('int32', 28))
}
  • 每天的数据占用8个4字节共32字节数据

  • 分别代表日期、开盘、最高、最低、收盘、成交额、成交量、未知🤣

  • 这里用slice取了最后一天的数据,也可以循环读取所有数据

  • 这里不使用FFI也可以,用DataView一样的


但有个问题,FileSystem.ReadFileAsArrayBuffer读取出来的不应该是ArrayBuffer吗

却不能直接作为FFI.RefPointer的参数

也不能作为DataView的参数

需要手动重新构建一个ArrayBuffer

这是不是bug啊。。。

海南省
浏览 85
收藏
3
分享
3 +1
4
+1
全部评论 4
 
王子陶
王子陶

@金山办公

看起来这文件结构与C语言式结构体完全相同。可以把day文件写成一个ffi.Struct结构体,把ArrayBuffer拷贝到一个C式结构体上来读取,这样可以大幅提高代码可读性。ffi.Struct返回值也是Type,可以利用Type.decoder来把ArrayBuffer转成ffi的值。
· 广东省
回复
wils
wils

创作者俱乐部成员

非常感谢 我也是在等新版本 猜测有了ffi可以定义结构体,会方便很多 感谢给出了具体办法,到时候我再试试
· 海南省
回复
 
王子陶
王子陶

@金山办公

jside里面的FileSystem.ReadFileAsArrayBuffer返回值应该是个Uint8Array,不是ArrayBuffer。
· 广东省
1
回复
wils
wils

创作者俱乐部成员

非常感谢 试了一下直接用d.buffer就可以了,这样就方便多了
· 海南省
回复