用JSA做表格分段排序
Lv.2潜力创作者
昨天有朋友问,类似下表中,有合并单元格的情况下,如何将每个月的xyz按照z进行排序
年度 | 月份 | x | y | z |
2025 | 11月 | a | a | 2 |
b | b | 1 | ||
c | c | 3 | ||
12月 | d | d | 3 | |
e | e | 2 | ||
f | f | 1 |
想了半天,对于这种需要在原表上进行修改的情况,似乎特别适合写JS宏处理
正好借此介绍一下简单的套路,吸引更多朋友来讨论JS宏
function tt()
{
const r = Range(`B${Rows.Count}`).End(xlUp).Row
let i = 2
while (i <= r) {
const m = Range(`B${i}`).MergeArea
const n = m.Offset(0, 1).Resize(m.Rows.Count, 3)
n.Value2 = n.Value2.sort((x, y) => parseFloat(y[2]) - parseFloat(x[2]))
i += m.Rows.Count
}
}| 🔔 | const r = Range(`B${Rows.Count}`).End(xlUp).Row |
这是个套路,`B${Rows.Count}`实际就是"B1048576",即B列最后一行,然后End(xlUp)就相当于在表格里按ctrl + 向上,也就是跳转到B列有数据的最后一行,最后获得这一行的行号,存入变量r
| 🔔 | let i = 2 while (i <= r) { |
这是个最常用的循环,变量i表示现在关注第几行,我们要从第2行开始处理到第r行
| 🔔 | const m = Range(`B${i}`).MergeArea |
MergeArea属性用来获取当前单元格所在合并单元格的整体范围,当i是2,也就是获取B2:B4这个范围
| 🔔 | const n = m.Offset(0, 1).Resize(m.Rows.Count, 3) |
和常用公式里的offset和resize类似,这里将上面的范围m,向右移动1列,然后扩展为3列,当i是2,也就是获取到C2:E4范围
| 🔔 | n.Value2 = n.Value2.sort((x, y) => parseFloat(y[2]) - parseFloat(x[2])) |
这也是套路,Value2获取到的是范围里的数值组成的二维数组,这也是JS比VBA方便的一点,JS里的二维数组是十分灵活的,这里先取得C2:E4里值组成的二维数组,第一维里对应每一行,这里对每一行进行排序,依据是每一行里第三个元素转为浮点数的值,最后将排序后的数据写入原位
| 🔔 | i += m.Rows.Count |
完成一次之后,关注的行号要加上合并单元格范围的行数,也就是行数从2变成了5,之后继续下一次循环
其实,常见的JS宏都是这个套路,用各种循环,逐个处理表格中的各种对象,可以是表格的行列,也可以是图片等等,在循环的过程中,用Value2等属性读写数据,就这么简单
有更多需求时,在这样的结构里做修改是十分方便的
尤其是这种原地修改表格的情况,只要想清楚要怎么循环,写JS宏处理,要比写公式简单清晰很多,也希望更多朋友关注讨论JS宏