powershell 简单实现核算单位往来(对账)
01 前言
核算单位(或部门)之间往来账,也说对账,是很多财务或者审计工作中都会涉及的。下面用powershell
简单实现一把,需要的可以拿去用,格式有要求。
02 正文
1、准备CSV文件
格式说明
- 文件编码为
ASCII
(一般系统默认)- 列名要求至少包含
挂账单位
、对方单位
、金额
、方向
四个(名字不要改),其他列可选。取值的时候要注意的是:
金额——可以含逗号
方向——简单说,这笔账对于挂账单位
来说是收入还是支出,+
表示收入,-
表示支出
如图:
2、执行脚本
<#
环境:powershell 5.1
2018-11-18 By Hokis
.NOTES
CSV格式(5列,其中 挂账单位,对方单位,金额,方向 必须有):
挂账单位,对方单位,科目, 金额,方向
df,i,应收账款,"42,217.00",+
......
思路:
1.先归类
2.再汇总
.DESCRIPTION
核对往来
#>
function Main-Do{
param(
[string]$filePath
)
#导入
if (Test-Path $filePath)
{
[Object[]]$records = Import-Csv -Path $filePath -Encoding Default | Sort-Object -Property 挂账单位, 对方单位
if ($records -and $records -is [system.array])
{
$units = @{} #所有单位
#分类
foreach ($r in $records)
{
if($r.对方单位 -and $r.挂账单位){
if ($units.keys -contains ($r.对方单位 + "|" + $r.挂账单位)) #先判断有无反过来的情况
{
$units[($r.对方单位 + "|" + $r.挂账单位)][1] += $r
}
elseif($units.Keys -contains ($r.挂账单位 + "|" + $r.对方单位)){
$units[($r.挂账单位 + "|" + $r.对方单位)][0] += $r
}
else #无此挂账单位
{
$units += @{ ($r.挂账单位 + "|" + $r.对方单位) = @(@($r),@()) }
}
}
}
#汇总
$info = New-Object 'object[][]' $units.Count,4 | Out-Null #二维数组,4列
foreach($k in $units.Keys){
$sum1 = ([decimal[]]($units[$k][0]|Where-Object{$_.方向 -eq "+"}|Select-Object -Property "金额").金额 | Measure-Object -Sum).Sum
$sum2 = ([decimal[]]($units[$k][0]|Where-Object{$_.方向 -eq "-"}|Select-Object -Property "金额").金额 | Measure-Object -Sum).Sum
$ownerU,$otherU = $k -split "\|" #转义
$info += ,@($ownerU,$otherU,$sum1,$sum2) #此处二维数组有个小坑,前面加逗号,以免被合并成一维数组
if($units[$k][1]){ #反过来的情况
$sum1 = ([decimal[]]($units[$k][1]|Where-Object{$_.方向 -eq "+"}|Select-Object -Property "金额").金额 | Measure-Object -Sum).Sum
$sum2 = ([decimal[]]($units[$k][1]|Where-Object{$_.方向 -eq "-"}|Select-Object -Property "金额").金额 | Measure-Object -Sum).Sum
$otherU,$ownerU = $k -split "\|" #转义
$info += ,@($ownerU,$otherU,$sum1,$sum2)
}else{ #加一个金额为0的配对
$info += ,@($otherU,$ownerU,0,0)
}
}
$oldU1,$oldU2 = $info[0][0],$info[0][1] #设一个默认值
$tol1,$tol2 = 0 #合计量
$wholeTol1,$wholeTol2 = 0 #最后的合计
#输出
$output = New-Object System.Text.StringBuilder
$output.AppendLine("序号,挂账单位,对方单位,应收(+),应付(-),差异") | Out-Null
$index = 1
$info | ForEach-Object{
if(-not (($oldU1 -eq $_[0] -and $oldU2 -eq $_[1]) -or ($oldU1 -eq $_[1] -and $oldU2 -eq $_[0]))){
$output.AppendLine(",,小计,$tol1,$tol2,"+($tol1-$tol2)) | Out-Null
$oldU1,$oldU2 = $_[0],$_[1]
$wholeTol1 += $tol1
$wholeTol2 += $tol2
$tol1,$tol2,$allTol = 0 #重置
$index ++
}
$output.AppendLine("$index,"+$_[0]+","+$_[1]+","+$_[2]+","+$_[3]+","+($_[2]-$_[3])) | Out-Null
$tol1 += $_[2]
$tol2 += $_[3]
}
#再加最后一次
$output.AppendLine(",,小计,$tol1,$tol2,"+($tol1-$tol2)) | Out-Null
$wholeTol1 += $tol1
$wholeTol2 += $tol2
$output.AppendLine(",,合计,$wholeTol1,$wholeTol2,"+($wholeTol1-$wholeTol2)) | Out-Null
$outputFile = (Split-Path -Path $filePath).ToString()+"\result.csv"
$output.ToString() | Out-File -FilePath $outputFile -Encoding default
Write-Host "完成!!生成文件:$outputFile"
}
else
{
write-host "无内容!"
}
}
else
{
write-host "找不到文件!"
}
}
#csv路径
#$path = "D:\powershell\tt.csv"
#Main-Do -filePath $path
Main-Do -filePath $args[0]
以上代码另存为.ps1
文件(此处笔者存为D:\powershell\myscript01.ps1
)。在DOS窗口中输入如下命令后回车等待:
powershell.exe -file "D:\powershell\myscript01.ps1" "D:\powershell\tt.csv"
脚本执行完成会有提示,生成结果result.csv
文件,格式如图:
如果脚本不能执行,参考【此处】解决。
03 后记
有条件可以自己修改脚本。
其他复杂一点的情况,也可以留言交流。