本文于2023年3月9日首发于本人同名公众号:Excel活学活用,敬请关注!
在个人所得税筹划方面,有一种方案,就是利用“一次性年终奖"的优惠政策,将年度总收入划分为按月发放的工资+一次性年终奖,对于高收入人群人说,节税空间还是比较大的,基于这样的需求,我做了一个将总收入拆分为工资和年终奖的表格,并且通过Excel VBA来实现最优方案的自动选择,对于人数较多的情况,能够节省不少时间。下面我们看一下效果:
我们可以看到,当以100元为最小拆分单位的时候,运行速度很快(我的表中有100条记录),当以10元为最小拆分单位的时候,就有点慢了,这也正常,运算量变成了10倍,当然会慢一点。
下面我分享一下实现这个功能的逻辑:
逻辑其实很简单,在拆分前先对应纳税所得额按综合所得方式计算税金,存于变量a,然后把“应纳税所得额"以一个较小的金额单位,拆分成两个金额,一个作为"拆分_综合所得",一个作为“拆分_一次性年终奖",对这两个金额分别使用相应的计税方法计算税金并求和,记为b,比较a和b的大小,取其小值给a,再进入下个循环,最终取得一个最小的合计税额a,同时记录其对应的"拆分_综合所得",“拆分_一次性年终奖",这样就求得一个人的拆分方案,然后再继续下一个人......
我们来看一下代码:
Sub 工资奖金拆分() '按固定金额单位拆分 Dim arr() As Variant Dim iRow As Integer Dim Stp Dim SJ1 As Double, SJ2 As Double, SJ3 As Double, SJ4 As Double, Gz As Double Dim arrT() Sheets("最佳税负").Activate iRow = ActiveSheet.UsedRange.Rows.Count ReDim arr(1 To iRow, 1 To 14) Stp = InputBox("请输入最小拆分单位金额:", "输入", 100) If Stp = "" Then Exit Sub arr = Range("A1:N" & iRow) For i = 2 To iRow Step 1 arr(i, 8) = 0 arr(i, 9) = 0 arr(i, 10) = 0 arr(i, 11) = 0 arr(i, 12) = 0 arr(i, 13) = 0 arr(i, 14) = 0 arr(i, 7) = zhsdTax(arr(i, 6)) If arr(i, 6) > 36000 Then SJ4 = arr(i, 7) For Gz = Stp To Int(arr(i, 6) / Stp) * Stp Step Stp SJ2 = zhsdTax(arr(i, 6) - Gz) SJ1 = nzjTax(Gz) SJ3 = SJ1 + SJ2 If SJ3 < SJ4 Then SJ4 = SJ3 arr(i, 10) = Gz arr(i, 9) = SJ2 arr(i, 8) = arr(i, 6) - Gz arr(i, 11) = SJ1 arr(i, 12) = SJ4 arr(i, 13) = arr(i, 7) - arr(i, 12) arr(i, 14) = arr(i, 13) / arr(i, 7) End If Next End If Next ReDim arrT(1 To iRow, 1 To 8) '为了保留表中“应纳税所得额”的计算公式,重新建一个数组 For i = 1 To iRow For j = 1 To 8 arrT(i, j) = arr(i, j + 6) Next Next Range("g1:N" & iRow) = arrT Erase arr Erase arrT MsgBox ("拆分完成")End SubFunction zhsdTax(应税工资 Optional 扣除 = 0) Dim 税率 扣除数 Select Case 应税工资 Case Is <= 0 税率 = 0: 扣除数 = 0 Case Is <= 36000 税率 = 3: 扣除数 = 0 Case Is <= 144000 税率 = 10: 扣除数 = 2520 Case Is <= 300000 税率 = 20: 扣除数 = 16920 Case Is <= 420000 税率 = 25: 扣除数 = 31920 Case Is <= 660000 税率 = 30: 扣除数 = 52920 Case Is <= 960000 税率 = 35: 扣除数 = 85920 Case Else 税率 = 45: 扣除数 = 181920 End Select zhsdTax = Round(应税工资 * 税率 / 100 - 扣除数 + 0.00000001, 2)End FunctionFunction nzjTax(应税工资 Optional 扣除 = 0) Dim 计税基础 税率 扣除数 计税基础 = Round(应税工资 / 12, 2) If 计税基础 <= 0 Then Exit Function Select Case 计税基础 Case Is <= 3000 税率 = 3: 扣除数 = 0 Case Is <= 12000 税率 = 10: 扣除数 = 210 Case Is <= 25000 税率 = 20: 扣除数 = 1410 Case Is <= 35000 税率 = 25: 扣除数 = 2660 Case Is <= 55000 税率 = 30: 扣除数 = 4410 Case Is <= 80000 税率 = 35: 扣除数 = 7160 Case Else 税率 = 45: 扣除数 = 15160 End Select nzjTax = Round(应税工资 * 税率 / 100 - 扣除数 + 0.00000001, 2)End Function
简单解释一下:
Sub工资奖金拆分(),首先把数据读入数组,然后在数组中通过两层循环计算出每一个人的各项拆分金额与税金等数据,最后再回写到表格中。说到数组,我前些天也分享过一篇Excel VBA 数组定义/数组赋值/数组输出/数组转置/数组ReDim,如果没有对数组的掌握与运用,今天这个拆分功能几乎不可能实现,当然,如果是一个人或者是几个人,不用VBA代码,也是可以算出来的,我也模拟了一张表,将“拆分_综合所得",从"拆分单位"逐步增加到“应纳税所得额",对应的“拆分_年终奖"则为“应纳税所得额"-“拆分_综合所得",然后分别计算税金,并与“拆分前应纳税额”相减,找到最大值对应的“拆分_综合所得"、“拆分_年终奖",就是我们要的结果啦。不过,速度是相当的慢,还需要手工调整一些参数,公式等,不过,将就将就也能用。
Function zhsdTax(应税工资, Optional 扣除 = 0),这是一个自定义函数,用来根据应纳税所得额来计算个人所得税的,可以在做工资表的时候使用,代替那一长串的计税公式。
FunctionnzjTax(应税工资, Optional 扣除 = 0),这是计算一次性年终奖的自定义函数。
今天的分享就到这里了,根据我上面提供的代码、表样,如果有实际的筹划需求,应该能搞得成功。