ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 950|回复: 1

[原创] JSA数组与单元格——试图用VBA的方式获取行列对应的数组

[复制链接]

TA的精华主题

TA的得分主题

发表于 2021-12-4 12:00 | 显示全部楼层 |阅读模式
本帖最后由 imnnoii 于 2021-12-4 12:46 编辑

大多数人用的WPS应该跟我一样,官网首页直接下载的。
它存在一个已知BUG,当我用VBA的习惯把单元格的值放入数组的时候,数组并不像我们理想中的一样行列对应。
本贴在当前版本试图解决这个问题,现将我的思路分享给大家。
谁叫个人版那么容易得到呢,害!

  在VBA中,我们单元格到数组显得轻松,直接用Range的区域就可以为数组赋值,并且得到的数组行列对应。也可以直接从数组放回单元格区域。
  1. Sub R2A()
  2.     Dim R As Variant
  3.     R = Range("A1:C1000") '取单元格到数组
  4.     Range("E1").Resize(UBound(R), UBound(R, 2)) = R '数组放回单元格
  5. End Sub
复制代码
  JSA中我也同样尝试这样操作,发现不仅取出来的数组不对应之外还放不回去。通过Console.log(JSON.stringify(mArr))的方法调试发现WPS在用Range.Value2属性取值时,顺序为先向下再向右的顺序,并且生成的二维数组的大小为:行数*列数(a*b)。它确实十分具有迷惑性,会让你觉得取出来的数组行列对应,然而并不是。

数组取值顺序

数组取值顺序
  既然有规律,那就好办了。我们将其展开为一维R[]
  1. function R2A(){
  2.     let st = new Date().getTime();
  3.     let mArr = Range("A1:C5").Value2;
  4.     Console.log(JSON.stringify(mArr))
  5.     let len = mArr.length, len2 = mArr[0].length
  6.     let R = []
  7.     for(i = 0; i < len; i++){
  8.         R = R.concat(mArr.shift())
  9.     }
  10.     Console.log(JSON.stringify(R))
  11. }
复制代码
  我们希望得到的数组行列应对应,大致结构应该和WPS一行一列类似。
  通过观察计算,假设目标数组为R2,那么可以发现规律:
  1. R2[i][j] == R[a*j + i]     //对于任意 i,j (i < a,j < b)存在关系
复制代码
  代码实现:
  1. function R2Aitr(mRNG,R=[]){
  2.     if (mRNG.length == 1) return R.concat(mRNG.shift());
  3.     return R2Aitr(mRNG,R.concat(mRNG.shift()));
  4. //尝试优化,失败。
  5. //可能时写法问题,并不实用。。。
  6. //测试“A1:C65536”单元格时疑似栈溢出,WPS重载
  7. }
  8. function R2A(){
  9.     let st = new Date().getTime();
  10.     let mArr = Range("A1:C5").Value2;
  11.     Console.log(JSON.stringify(mArr))
  12.     let len = mArr.length, len2 = mArr[0].length
  13.     let R = []
  14.     for(i = 0; i < len; i++){
  15.          R = R.concat(mArr.shift())
  16.      }
  17.     Console.log(JSON.stringify(R))
  18.     //let R = R2Aitr(mArr)
  19.     for(let i = 0; i < len; i++){
  20.         mArr[i] = []
  21.         for(let j = 0; j < len2; j++){
  22.             mArr[i][j] = R[len*j + i]
  23.         }
  24.     }
  25.     Console.log(JSON.stringify(mArr))
  26.     et = new Date().getTime();
  27.     Console.log(et - st + "ms");
  28. }
复制代码
  听说有版本已经更新了这个问题,但我用不了只能暂时用此方法转换一下。

  方法显得十分拙略,如果有大佬知道更好的方法,还请不吝告知。
本来打算在一个for循环内找到对应关系,数学能力有限,想了两小时没啥思路。作罢。
  测试用时:
A1:C5--> 1ms
A1:C1000--> 11ms
A1:C10000--> 520 ms
  速度也越来越慢。在实际使用中并不用完成转换,知道关系可以直接参与计算。

TA的精华主题

TA的得分主题

发表于 2021-12-7 03:19 | 显示全部楼层
你这个问题以后就不存在了
关于JSA从单元格区域读取到数组,行列和VBA不一致的情况,后面都会改。WPS专业版(还没发布的版本,我已经拿到了)已经修复了这个问题。和VBA一样
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-21 19:04 , Processed in 0.035454 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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