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

news2024/11/28 9:39:57

在这里插入图片描述
如图:根据日记账/序时账的日期、凭证号为一组,按借贷方向生成相反的科目,并写入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 = Timer
    With ActiveSheet
        arr = .[a1].CurrentRegion: start_end = Array(2, 2)  '开始结束行号
        Do
            ReDim 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 = 0
            For i = start_end(0) To UBound(arr)
                ss = arr(i, 1) & arr(i, 2)
                If s = ss Then
                    x = x + 1: d(x) = arr(i, 4): e(x) = arr(i, 5): f(x) = arr(i, 6)
                Else
                    ReDim 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 For
                End If
                If i = UBound(arr) Then start_end(1) = i: ReDim res(1 To x): Exit For
            Next
            '金额判断科目
            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 If
                    If 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 If
                    If 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 If
                    If 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 If
                    If Len(e(i)) Then    '一借多贷,剩余金额相等;计算精度问题
                        ts = WorksheetFunction.sum(f)
                        If e(i) = ts Or Abs(Round(e(i) - ts, 6)) < (0.1 ^ 6) Then
                            For j = 1 To x
                                If Len(f(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i): e(i) = "": f(j) = ""
                            Next
                        End If
                    End If
                    If Len(f(i)) Then    '多借一贷,剩余金额相等
                        ts = WorksheetFunction.sum(e)
                        If f(i) = ts Or Abs(Round(f(i) - ts, 6)) < (0.1 ^ 6) Then
                            For j = 1 To x
                                If Len(e(j)) Then res(i) = res(i) & "," & d(j): res(j) = res(j) & "," & d(i): f(i) = "": e(j) = ""
                            Next
                        End If
                    End If
                Next
            Next
'            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 If
            For 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) + x
        Loop Until start_end(0) > UBound(arr)
    End With
    Debug.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 = Timer
    With ActiveSheet
        arr = .[a1].CurrentRegion: start_end = Array(2, 2)  '开始结束行号
        Do
            For i = start_end(0) To UBound(arr)  'h列为空
                If Len(.Cells(i, "h")) = 0 Then start_end(0) = i: Exit For
            Next
            ReDim 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 = 0
            For i = start_end(0) To UBound(arr)
                ss = arr(i, 1) & arr(i, 2)
                If s = ss Then
                    x = x + 1: d(x) = arr(i, 4): e(x) = arr(i, 5): f(x) = arr(i, 6)
                Else
                    ReDim 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 For
                End If
                If i = UBound(arr) Then start_end(1) = i: ReDim res(1 To x): Exit For
            Next
            '金额判断科目
            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 If
            For 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) + x
        Loop Until start_end(0) > UBound(arr) Or start_end(0) > limit
    End With
    Debug.Print "用时:" & Format(Timer - tm, "0.00")  '耗时
End Sub

测试结果

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/590440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTTPS的加密流程——巨详细!

文章目录 前言HTTPS的工作过程引入对称加密引入非对称加密引入证书完整的加密流程总结 前言 HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况. 比如&#xff1a;臭…

民宿预订系统的设计与实现(ASP.NET,SQLServer)

这个民宿预订系统是由第三方的运营公司来运营&#xff0c;他提供了一个民宿和客户都使用的一个信息平台&#xff0c;民宿注册之后把自己的民宿信息发布到网站平台上&#xff0c;然后发布自己的房间信息&#xff0c;打折信息等供客户查看和选择。客户可以在网站平台上查看民宿信…

深度学习:大模型的正则化

l1l2正则和dropout正则化[https://youzipi.blog.csdn.net/article/details/75307522] LN和BN归一化 [深度学习:批归一化Batch Normalization] 主流大模型使用的Normalization主要有三类,分别是Layer Norm,RMS Norm,以及Deep Norm。 Post-Norm和Pre-Norm 根据Normalizat…

网工内推 | 快手、瑞芯微招运维,思科、红帽认证优先

01 快手 招聘岗位&#xff1a;IT系统运维 职责描述&#xff1a; 1、负责IT基础架构运维体系的建设和优化改进&#xff1b; 2、负责IT核心基础服务&#xff08;如DNS、负载均衡、容器&#xff09;的架构设计、平台建设和运维&#xff1b; 3、负责IT内部日志系统、监控系统、报警…

SpringCloud微服务框架(通俗易懂,一秒上手)

&#x1f381;&#x1f381;资源&#xff1a;https://pan.baidu.com/s/1zRmwSvSvoDkWh0-MynwERA&pwd1234 SpringCloud微服务框架 &#xff08;一&#xff09;认识微服务服务架构演变SpringCloud &#xff08;二&#xff09;微服务拆分案例服务拆分服务间调用 &#xff08;三…

ROS:订阅者Subscriber的编程实现(C++)

目录 一、话题模型二、创建功能包三、创建Subscriber代码四、编译代码五、运行 一、话题模型 图中&#xff0c;我们使用ROS Master管理节点。 有两个主要节点&#xff1a; Publisher&#xff0c;名为Turtle Velocity&#xff08;即海龟的速度&#xff09; Subscriber&#xff0…

Rocketmq面试(一) Rocketmq同一个消费组订阅不同的Tag,会有什么问题?

先说结果&#xff1a;会造成数据丢失 再说依据&#xff1a; RocketMQ要求同一个消费者组内的消费者必须订阅关系一致&#xff0c;如果订阅关系不一致会出现消息丢失的问题。 官网入口&#xff1a;订阅关系一致 | RocketMQ 不想看官网的&#xff0c;直接看结论 什么叫订阅关…

复杂SQL实践-MYSQL

MySQL 8.0窗口函数 MySQL从8.0版本开始支持窗口函数。 窗口函数总体上可以分为序号函数, 分布函数, 前后函数, 首尾函数和其他函数。 描述 题目&#xff1a;现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。 示例1 drop table if exist…

对远程http服务的拨测体验

背景&#xff1a; 过程是这样的&#xff0c;需要与合作方数据进行交互&#xff08;肯定是不允许直接连对方数据源的&#xff09;&#xff0c;对方提供了两台server&#xff0c;后端同事在server上面作了proxy搭建了桥接的应用&#xff08;两台server没有公网ip&#xff0c;通过…

Eclipse 教程Ⅹ

本次内容会涉及到Eclipse 重构菜单、Eclipse 添加书签和Eclipse 任务管理&#xff0c;老规矩&#xff0c;直接开始吧&#xff01; Eclipse 重构菜单 使用Eclipse重构 在项目开发中我们经常需要修改类名&#xff0c;但如果其他类依赖该类时&#xff0c;我们就需要花很多时间去…

机器学习模型的生命周期

动动发财的小手&#xff0c;点个赞吧&#xff01; 您的模型如何变化&#xff1f;Source[1] 诞生 当我们构建、训练、拟合或估计我们的模型时&#xff0c;这些数字工具就诞生了。这个阶段几乎从拥有分析目标、数据、计算机、算法以及数据科学家现在已经非常了解的其他一切开始。…

Linux [权限]

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

实在智能携手各高校打造高端数字化技能教育平台

百年大计&#xff0c;教育为本。2021年在《教育部办公厅关于印发高等职业教育专科英语、信息技术课程标准&#xff09;的通知中把机器人流程自动化列入专科信息技术课程学习计划之中&#xff0c;进一步明确职业教育中数字化人才发展方向。 一、为什么要大力培养数字化人才&…

毕业5年的同学突然告诉我,他已经是年薪30W的自动化测试工程师,我愣住了...

作为一名程序员&#xff0c;都会对自己未来的职业发展而焦虑。一方面是因为IT作为知识密集型的行业&#xff0c;知识体系复杂且知识更新速度非常快&#xff0c;“一日不学就会落后”。 另外一方面&#xff0c;IT又是劳动密集型的行业&#xff0c;不仅业人员多&#xff0c;而且个…

随机梯度下降法

梯度下降法有两个比较大的缺点&#xff1a; --计算花时间 --容易陷入局部最优解 比如以下形状的函数&#xff0c;最优解取决于初始值的选取。 梯度下降法的表达式如下&#xff0c;这个表达式使用了所有训练数据的误差&#xff1a; 随机梯度下降法表达式&#xff1a; 在随机梯…

Cmake学习记录(九)--使用Cmake交叉编译.so库

文章目录 一、前言二、相关代码三、参考链接 一、前言 目前Android编译.so的话使用Android Studio比较简单&#xff0c;但是有时候时候Android Studio的话还需要创建一个Android的项目&#xff0c;这里记录下脱离Android Studio单纯使用Cmake和C开发工具Clion(或者其他的开发工…

Prometheus+grafana+node_exporter环境搭建

原理&#xff1a; node_exporter采集数据&#xff0c;Prometheus通过配置文件Prometheus.yml配置node_exporter信息获取采集到的数据并做展示&#xff0c;grafana将Prometheus作为数据源展示node_exporter采集到的数据 拓扑图 问题&#xff1a; 1&#xff09;为什么不直接用…

万众瞩目的Nautilus Chain即将上线主网,生态正式起航

Zebec Protocol 是以流支付为定位 Web3 生态&#xff0c;该生态旨在构建一个全新的支付方式&#xff0c;以进一步丰富加密支付场景&#xff0c;并推动加密支付的大规模采用&#xff0c;该生态此前在 Solans 生态中曾取得了十分亮眼的成绩。目前&#xff0c;Zebec Protocol 正在…

Unity MVC实现背包系统(2)

在上一篇中&#xff0c;我们写了背包系统的伪代码&#xff0c;也说了mvc的设计思路&#xff0c;那么这一篇的任务就是将伪代码补全。 首先制作一个背包面板&#xff0c;我这里比较简单&#xff0c;就是一个滚动视图&#xff0c;还有一个提示文本&#xff0c;外加两个按钮&…

20230530论文整理·1-课题组1

个人观点&#xff0c;现在的NLP文章&#xff0c;有些是在做积木&#xff0c;微创新&#xff0c;有些文章&#xff0c;是可以的&#xff0c;读起来很美&#xff0c;有些&#xff0c;太过逆了&#xff0c;吃起来没味道&#xff0c;反胃。 文章目录 1.CODEIE: Large Code Generat…