Excel·VBA自动生成日记账的对方科目

news/2024/11/30 8:43:54/

在这里插入图片描述
如图:根据日记账/序时账的日期、凭证号为一组,按借贷方向生成相反的科目,并写入H列。可能存在一对一、一对多、多对多等情况的账目

目录

    • 数组法遍历、判断、写入
        • 测试结果
      • 多对多问题处理
        • 测试结果

数组法遍历、判断、写入

适用日期凭证号连续的日记账

按照判断难易程度从简单开始,先判断科目一对一的同向/反向情况;再判断科目一对多且借方和贷方数组剩余数据刚好相等的情况;最后再判断多对多的情况,由于多对多可能涉及组合求和问题,耗时会比较长,因此以下代码注释了多对多的情况,另写一个sub专门处理多对多问题。(数据匹配后,对应的数组该数据会清空,方便后续判断)

组合求和问题调用了combin_arr1函数,代码详见《Excel·VBA数组组合函数、组合求和》(如需使用代码需复制)

Sub 生成对方科目()'适用日期凭证号连续的日记账,完整版代码Dim arr, d, e, f, res, i&, j&, x&, m, brr, b, write_col$write_col = "h"    '结果写入列号tm = TimerWith ActiveSheetarr = .[a1].CurrentRegion: start_end = Array(2, 2)  '开始结束行号DoReDim d(1 To 100): ReDim e(1 To 100): ReDim f(1 To 100)s = arr(start_end(0), 1) & arr(start_end(0), 2): x = 0For i = start_end(0) To UBound(arr)ss = arr(i, 1) & arr(i, 2)If s = ss Thenx = x + 1: d(x) = arr(i, 4): e(x) = arr(i, 5): f(x) = arr(i, 6)ElseReDim Preserve d(1 To x): ReDim Preserve e(1 To x): ReDim Preserve f(1 To x)start_end(1) = i - 1: ReDim res(1 To x): Exit ForEnd IfIf i = UBound(arr) Then start_end(1) = i: ReDim res(1 To x): Exit ForNext'金额判断科目For t = 1 To 2  '执行2次循环,尽可能多配对For i = 1 To x    '一对一If Len(e(i)) Then    '一借一贷m = Application.Match(e(i), f, 0)If TypeName(m) <> "Error" Then res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): e(i) = "": f(m) = ""End IfIf Len(f(i)) Then    '一借一贷m = Application.Match(f(i), e, 0)If TypeName(m) <> "Error" Then res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): f(i) = "": e(m) = ""End IfIf Len(e(i)) Then    '同方向一正一负m = Application.Match(-e(i), e, 0)If TypeName(m) <> "Error" Then res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): e(i) = "": e(m) = ""End IfIf Len(f(i)) Then    '同方向一正一负m = Application.Match(-f(i), f, 0)If TypeName(m) <> "Error" Then res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): f(i) = "": f(m) = ""End IfIf Len(e(i)) Then    '一借多贷,剩余金额相等;计算精度问题ts = WorksheetFunction.sum(f)If e(i) = ts Or Abs(Round(e(i) - ts, 6)) < (0.1 ^ 6) ThenFor j = 1 To xIf Len(f(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i): e(i) = "": f(j) = ""NextEnd IfEnd IfIf Len(f(i)) Then    '多借一贷,剩余金额相等ts = WorksheetFunction.sum(e)If f(i) = ts Or Abs(Round(f(i) - ts, 6)) < (0.1 ^ 6) ThenFor j = 1 To xIf Len(e(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i): f(i) = "": e(j) = ""NextEnd IfEnd IfNextNext
'            For i = 1 To x  '一借一贷,一对多
'                If x > 20 Then Debug.Print "数据太多,求和速度慢": Exit For
'                If Len(e(i)) Then    '一借一贷,一对多
'                    For j = x - 1 To 2 Step -1
'                        brr = combin_arr1(f, j)  '调用函数返回组合,一维嵌套数组
'                        For Each b In brr
'                            temp_sum = WorksheetFunction.sum(b)
'                            If temp_sum = e(i) Then
'                                For Each bb In b
'                                    If Len(bb) Then
'                                        m = Application.Match(bb, f, 0)
'                                        res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): f(m) = ""
'                                    End If
'                                Next
'                                e(i) = "": Exit For
'                            End If
'                        Next
'                        If e(i) = "" Then Exit For
'                    Next
'                End If
'                If Len(f(i)) Then    '一借一贷,一对多
'                    For j = x - 1 To 2 Step -1
'                        brr = combin_arr1(e, j)
'                        For Each b In brr
'                            temp_sum = WorksheetFunction.sum(b)
'                            If temp_sum = f(i) Then
'                                For Each bb In b
'                                    If Len(bb) Then
'                                        m = Application.Match(bb, e, 0)
'                                        res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): e(m) = ""
'                                    End If
'                                Next
'                                f(i) = "": Exit For
'                            End If
'                        Next
'                        If f(i) = "" Then Exit For
'                    Next
'                End If
'            Next
'            If Len(Join(e, ",")) >= x Or Len(Join(f, ",")) >= x Then
'                For i = 1 To x    '多借多贷,无法组合求和
'                    If Len(e(i)) Then
'                        For j = 1 To x
'                            If Len(f(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i)
'                        Next
'                    End If
'                Next
'            End IfFor i = 1 To x    '清除开头的","If Len(res(i)) Then res(i) = Mid(res(i), 2)Next.Cells(start_end(0), write_col).Resize(x, 1) = WorksheetFunction.Transpose(res)start_end(0) = start_end(0) + xLoop Until start_end(0) > UBound(arr)End WithDebug.Print "用时:" & Format(Timer - tm, "0.00")  '耗时
End Sub

测试结果

在15248行日记账中,生成了12787行的对方科目,用时0.55秒

多对多问题处理

考虑到多对多问题,涉及组合求和问题,耗时会比较长,因此添加limit参数控制代码运行行数

Sub 生成对方科目_多对多()'适用日期凭证号连续的日记账,多对多Dim arr, d, e, f, res, i&, j&, x&, m, brr, b, write_col$, limit&limit = 3111: write_col = "h"   '代码运行结束行数限制,结果写入列号tm = TimerWith ActiveSheetarr = .[a1].CurrentRegion: start_end = Array(2, 2)  '开始结束行号DoFor i = start_end(0) To UBound(arr)  'h列为空If Len(.Cells(i, "h")) = 0 Then start_end(0) = i: Exit ForNextReDim d(1 To 100): ReDim e(1 To 100): ReDim f(1 To 100)s = arr(start_end(0), 1) & arr(start_end(0), 2): x = 0For i = start_end(0) To UBound(arr)ss = arr(i, 1) & arr(i, 2)If s = ss Thenx = x + 1: d(x) = arr(i, 4): e(x) = arr(i, 5): f(x) = arr(i, 6)ElseReDim Preserve d(1 To x): ReDim Preserve e(1 To x): ReDim Preserve f(1 To x)start_end(1) = i - 1: ReDim res(1 To x): Exit ForEnd IfIf i = UBound(arr) Then start_end(1) = i: ReDim res(1 To x): Exit ForNext'金额判断科目For i = 1 To x  '一借一贷,一对多If x > 20 Then Debug.Print "数据太多,求和速度慢": Exit ForIf Len(e(i)) Then    '一借一贷,一对多For j = x - 1 To 2 Step -1brr = combin_arr1(f, j)  '调用函数返回组合,一维嵌套数组For Each b In brrtemp_sum = WorksheetFunction.sum(b)If temp_sum = e(i) ThenFor Each bb In bIf Len(bb) Thenm = Application.Match(bb, f, 0)res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): f(m) = ""End IfNexte(i) = "": Exit ForEnd IfNextIf e(i) = "" Then Exit ForNextEnd IfIf Len(f(i)) Then    '一借一贷,一对多For j = x - 1 To 2 Step -1brr = combin_arr1(e, j)For Each b In brrtemp_sum = WorksheetFunction.sum(b)If temp_sum = f(i) ThenFor Each bb In bIf Len(bb) Thenm = Application.Match(bb, e, 0)res(i) = res(i) & "," & d(m): res(m) = res(m) & "," & d(i): e(m) = ""End IfNextf(i) = "": Exit ForEnd IfNextIf f(i) = "" Then Exit ForNextEnd IfNextIf Len(Join(e, ",")) >= x Or Len(Join(f, ",")) >= x ThenFor i = 1 To x    '多借多贷,无法组合求和If Len(e(i)) ThenFor j = 1 To xIf Len(f(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i)NextEnd IfNextEnd IfFor i = 1 To x    '清除开头的","If Len(res(i)) Then res(i) = Mid(res(i), 2)Next.Cells(start_end(0), write_col).Resize(x, 1) = WorksheetFunction.Transpose(res)start_end(0) = start_end(0) + xLoop Until start_end(0) > UBound(arr) Or start_end(0) > limitEnd WithDebug.Print "用时:" & Format(Timer - tm, "0.00")  '耗时
End Sub

测试结果

由于耗时较长,仅部分测试
在这里插入图片描述
存在问题
在这里插入图片描述
从特殊情况可知,多对多问题一方数据量较大时,耗时增长明显;而数据量在10以内时,即便需要组合求和耗时也很少,因此编写代码时可以考虑优先处理数据量较小的部分,跳过数据量较多的部分

扩展阅读
《excelhome-如何通过VBA自动生成对方科目》


http://www.ppmy.cn/news/109096.html

相关文章

Baumer工业相机堡盟工业相机测试使用InsCodeAI创作助手进行技术博客相关问题的创作与测试

Baumer工业相机堡盟工业相机测试使用InsCodeAI创作助手进行技术博客相关问题的创作与测试 一、使用AI写作类工具进行创作的利弊 由于目前大语言数据模型越来越广泛&#xff0c;应用的工具也是越来越多&#xff0c;从AI绘画到AI咨询等等&#xff0c;这些方式可以将很多领域的专…

Linux [权限]

Linux 权限 Linux用户分类切换成root方法例子 切换成普通用户方法例子 短暂提权 什么是权限理论知识展示区域 修改权限(1)修改文件属性1. 采用 w/r/x的形式2. 采用八进制的形式 (2)修改身份1. 修改拥有者2. 修改所属组3. 修改拥有者 && 所属组 问题区问题1问题2问题3 L…

图解系列 图解Spring Boot 最大连接数及最大并发数

文章目录 概序架构图TCP的3次握手4次挥手时序图核心参数AcceptCountMaxConnectionsMinSpareThread/MaxThreadMaxKeepAliveRequestsConnectionTimeoutKeepAliveTimeout 内部线程AcceptorPollerTomcatThreadPoolExecutor 测试参考 每个Spring Boot版本和内置容器不同&#xff0c;…

正规文法、正规表达式、有限自动机及其之间的转换(笔记)

The Equivalent Transforming among RG, RE and FA 正规文法 A Grammar G is a quadruple (四元组):G (VN, VT, S, P ) Where, VN is a finite set of nonterminals.VT is a finite set of terminals.S is the start symbol, S ∈ \in ∈ VN.P is a finite set of product…

ProtoBuf 语法(三)

系列文章 ProtoBuf 语法&#xff08;一&#xff09; ProtoBuf 语法&#xff08;二&#xff09; 文章目录 九、option 选项9.1 选项分类9.2 常用选项 十、ProtoBuf 与 JSON 的性能对比10.1 序列化能力对比10.2 总结 九、option 选项 .proto文件中可以声明许多选项&#xff0c;使…

《商用密码应用与安全性评估》第四章密码应用安全性评估实施要点4.1密码应用方案设计

4.1设计原则 密码应用方案设计是信息系统密码应用的起点&#xff0c;它直接决定着信息系统的密码应用能否合规、正确、有效地部署实施。 ①总体性原则&#xff1a;密码在信息系统中的应用不是孤立的&#xff0c;必须与信息系统的业务相结合才能发挥作用。 ②科学性原则&#xf…

STM32单片机(三)第三节:GPIO输入

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

Ethercat学习-从站FOE固件更新(QT上位机)

文章目录 简介1、源码简介1、ec_FOEread2、ec_FOEwrite3、ec_FOEdefinehook 2、程序思路3、修改实现1、ecx_FOEwrite_gxf2、ecx_FOEread_gxf 4、其他5、结果6、源码连接 简介 FOE协议与下位机程序实现过程之前文章有提到&#xff0c;这里不做介绍了。这里主要介绍1、QT上位机通…