JS宏上手实例——账龄分析表
Lv.2潜力创作者
前两天论坛里发起投票,发现只有少数朋友愿意尝试JS宏
正好弄了个例子,尽量列出JS宏最常见的套路,方便大家上手
今天的题目是,生成应收账款的账龄分析表。
上年的表是这样:
客户 | 本年增加 | 本年减少 | 1年以内 | 2年以内 | 3年以内 | 4年以内 | 5年以内 | 5年以上 |
A | 0 | 0 | 100 | 101 | 102 | 103 | 104 | 105 |
B | 0 | 0 | 101 | 102 | 103 | 104 | 105 | 106 |
C | 0 | 0 | 102 | 103 | 104 | 105 | 106 | 107 |
D | 0 | 0 | 103 | 104 | 105 | 106 | 107 | 108 |
E | 0 | 0 | 104 | 105 | 106 | 107 | 108 | 109 |
F | 0 | 0 | 105 | 106 | 107 | 108 | 109 | 110 |
G | 0 | 0 | 106 | 107 | 108 | 109 | 110 | 111 |
H | 0 | 0 | 107 | 108 | 109 | 110 | 111 | 112 |
I | 0 | 0 | 108 | 109 | 110 | 111 | 112 | 113 |
J | 0 | 0 | 109 | 110 | 111 | 112 | 113 | 114 |
今年的数据是这样:
客户 | 本年增加 | 本年减少 |
F | 600 | 100 |
G | 700 | 200 |
H | 800 | 300 |
J | 1000 | 500 |
A | 100 | 600 |
B | 200 | 700 |
C | 300 | 800 |
D | 400 | 900 |
“本年增加”要作为新的“1年以内”
去年的账龄要整体右移1年
“本年减少”要先抵扣账龄最长的,因为先进先出
规则很简单,要据此生成新的账龄表
第一步 获取上年数据
const 上年工作簿 = Workbooks.Open(`${ThisWorkbook.Path}/2024应收账款.xlsx`, false, true)
const 上年明细表 = 上年工作簿.Sheets("明细表")
const 上年数组 = 上年明细表.Range(`A2:I${上年明细表.Range(`A${上年明细表.Rows.Count}`).End(xlUp).Row}`).Value2
const 上年字典 = {}
for (const i of 上年数组) {
上年字典[i[0]] = i.slice(3)
}
上年工作簿.Close()整体的套路是,打开xlsx,获取“明细表”,将数据存入字典,关闭xlsx:
Open第三个参数是只读打开,可以加快速度
End(xlUp).Row相当于按ctrl加方向键,是为了找到A列里有数据的最后一行行号
因为今年的客户名称和去年的顺序不同,需要查询,而这种类似vlookup、filter的操作一般都用字典,所以将“上年数组”里的数据以“上年字典”的形式重新存了一份
第二步 获取今年数据
const 今年明细表 = ActiveWorkbook.Sheets("明细表")
const 今年数组 = 今年明细表.Range(`A2:C${今年明细表.Range(`A${今年明细表.Rows.Count}`).End(xlUp).Row}`).Value2和第一步一样,获取“今年数组”即可
第三步 逐行处理数据
const 今年账龄数组 = []
for (const i of 今年数组) {
const 单行账龄 = 上年字典[i[0]]
单行账龄.unshift(i[1])
单行账龄[单行账龄.length - 2] += 单行账龄[单行账龄.length - 1]
单行账龄.pop()
let j = 单行账龄.length - 1
while (i[2] > 0) {
if (j === 0 || 单行账龄[j] > i[2]) {
单行账龄[j] -= i[2]
i[2] = 0
}
else {
i[2] -= 单行账龄[j]
单行账龄[j] = 0
}
j--
}
今年账龄数组.push(单行账龄)
}
今年明细表.Range(`D2`).Resize(今年账龄数组.length, 今年账龄数组[0].length).Value2 = 今年账龄数组第一行新建空白数组
最后一行写入结果
中间是个for循环,逐行处理上年数据,并生成结果,处理的过程是
通过查询字典,获得当前行对应的去年客户的账龄数组
将“本年增加”加入账龄数组的头部
账龄数组的倒数第二项要累加倒数第一项,然后删除倒数第一项,因为这一列表示“5年以上”
然后是一个while循环,用“本年减少”的值,从数组的尾部逐项抵扣
最后将处理后的行,加入结果
这个例子里包含了JS宏上手时最常用的几个套路:
通过Value2读取数据
通过Value2写入结果
数组的push、pop、unshift等操作
把对象{}当作字典进行查询
在知道总次数时用for循环
在不知道总次数时用while循环
如果这个过程用表格公式来写,三天以后我就看不懂自己写的是啥了🤣
JS宏却方便后续的修改,比如对于数组里的未定义项,需要用0填充等
更重要的是,可以在代码里进行更详细的检查
而且,只要会了一个JS方法,就可以定时、批量、有条件、连续的用这个方法
再加上AI的帮助,真的不需要在乎细节的语法,知道要做什么结果是啥样的就行
例子在这里: https://pan.baidu.com/s/1CS21SKoLMzJ1DBSHD2644A?pwd=yb1e
写的不好,权当抛砖引玉,希望更多的朋友尝试或来讨论
