本帖最后由 imnnoii 于 2021-12-4 12:46 编辑
大多数人用的WPS应该跟我一样,官网首页直接下载的。 它存在一个已知BUG,当我用VBA的习惯把单元格的值放入数组的时候,数组并不像我们理想中的一样行列对应。 本贴在当前版本试图解决这个问题,现将我的思路分享给大家。 谁叫个人版那么容易得到呢,害!
在VBA中,我们单元格到数组显得轻松,直接用Range的区域就可以为数组赋值,并且得到的数组行列对应。也可以直接从数组放回单元格区域。 - Sub R2A()
- Dim R As Variant
- R = Range("A1:C1000") '取单元格到数组
- Range("E1").Resize(UBound(R), UBound(R, 2)) = R '数组放回单元格
- End Sub
复制代码 在JSA中我也同样尝试这样操作,发现不仅取出来的数组不对应之外还放不回去。通过Console.log(JSON.stringify(mArr))的方法调试发现WPS在用Range.Value2属性取值时,顺序为先向下再向右的顺序,并且生成的二维数组的大小为:行数*列数(a*b)。它确实十分具有迷惑性,会让你觉得取出来的数组行列对应,然而并不是。
数组取值顺序
既然有规律,那就好办了。我们将其展开为一维R[] - function R2A(){
- let st = new Date().getTime();
- let mArr = Range("A1:C5").Value2;
- Console.log(JSON.stringify(mArr))
- let len = mArr.length, len2 = mArr[0].length
- let R = []
- for(i = 0; i < len; i++){
- R = R.concat(mArr.shift())
- }
- Console.log(JSON.stringify(R))
- }
复制代码 我们希望得到的数组行列应对应,大致结构应该和WPS一行一列类似。 通过观察计算,假设目标数组为R2,那么可以发现规律: - R2[i][j] == R[a*j + i] //对于任意 i,j (i < a,j < b)存在关系
复制代码 代码实现:- function R2Aitr(mRNG,R=[]){
- if (mRNG.length == 1) return R.concat(mRNG.shift());
- return R2Aitr(mRNG,R.concat(mRNG.shift()));
- //尝试优化,失败。
- //可能时写法问题,并不实用。。。
- //测试“A1:C65536”单元格时疑似栈溢出,WPS重载
- }
- function R2A(){
- let st = new Date().getTime();
- let mArr = Range("A1:C5").Value2;
- Console.log(JSON.stringify(mArr))
- let len = mArr.length, len2 = mArr[0].length
- let R = []
- for(i = 0; i < len; i++){
- R = R.concat(mArr.shift())
- }
- Console.log(JSON.stringify(R))
- //let R = R2Aitr(mArr)
- for(let i = 0; i < len; i++){
- mArr[i] = []
- for(let j = 0; j < len2; j++){
- mArr[i][j] = R[len*j + i]
- }
- }
- Console.log(JSON.stringify(mArr))
- et = new Date().getTime();
- Console.log(et - st + "ms");
- }
复制代码 听说有版本已经更新了这个问题,但我用不了只能暂时用此方法转换一下。
方法显得十分拙略,如果有大佬知道更好的方法,还请不吝告知。 本来打算在一个for循环内找到对应关系,数学能力有限,想了两小时没啥思路。作罢。 测试用时: A1:C5--> 1ms A1:C1000--> 11ms A1:C10000--> 520 ms 速度也越来越慢。在实际使用中并不用完成转换,知道关系可以直接参与计算。 |