【2.使用VBA自动填充Excel工作表】

目录

  • 前言
  • 什么是VBA
  • 如何使用Excel中的VBA
  • 简单基础入门
    • 控制台输出信息
    • 定义过程(功能)
    • 定义变量
    • 常用的数据类型
    • Set
    • 循环
      • For To
  • 我的需求
  • 开发过程
    • 效果演示
    • 文件情况
      • 测试填充源文件
      • 测试填充目标文件
    • 全部完整的代码
      • sheet1中的代码,对应A公司工作表
      • UserForm1的代码
  • 待续
    • 基础逻辑完善
      • 获取行号
      • 遍历日期算法逻辑
      • 提升对单元格等对象的操作知识
    • 功能升级

前言

上一篇文章我使用了Excel中的Index和Match函数实现可以根据之前打过的数据去自动填充内容。在对账的时候可以帮助我们节省很多时间。但是,这样不够直接、更不够快
做过对账单和送货单的人都知道,送货单在出货的时候要打,可能一天一个公司打个一两次。要是我在打送货单的时候,对账单也能自动根据送货单的内容自动填充就好啦

如此细致的功能,我目前只想到了使用Python和VBA。

如果要实现日常的使用,VBA应该就够用了。

什么是VBA

VBA是Visual Basic for Applications的缩写,它是一种事件驱动的编程语言,由微软公司开发。VBA主要用于Microsoft Office套件中的应用程序,如Excel、Word、Access、PowerPoint等,允许用户通过编写宏和自定义函数来自动化任务和扩展应用程序的功能

VBA基于Visual Basic编程语言,它提供了一套丰富的编程工具和对象模型,使得开发者可以创建复杂的自动化脚本和自定义用户界面。使用VBA,用户可以:

自动化重复性任务:通过编写宏来减少手动操作,提高工作效率。
数据处理和分析:在Excel中进行复杂的数据操作和分析。
用户界面定制:在Word或Excel中创建自定义的对话框和表单
与其他应用程序交互:通过VBA编写的代码可以与其他应用程序或数据库进行交互

发明背景

VBA的发明时间可以追溯到1994年左右,当时随着Office 95的发布,VBA作为其宏语言的一部分被引入。它与传统的宏语言不同,提供了面向对象的程序设计方法,并拥有相当完整的程序设计语言。VBA易于学习掌握,可以使用宏记录器记录用户的各种操作并将其转换为VBA程序代码,从而实现工作自动化

VBA与Visual Basic(VB)具有相似的语言结构,从语言结构上讲,VBA是VB的一个子集,它们的语法结构是一样的。VB是一种独立的开发工具,而VBA则必须依附于Office应用程序。VBA专门用于Office的各应用程序中,如Word、Excel、Access等,它与主应用程序之间的通信变得简单而高效。

VBA的编程能力介于低级语言和高级语言之间,它继承了Visual Basic的部分特性和语法,因此具有更强的编程能力和灵活性。然而,VBA的运行速度相对较慢,因为它是通过解释执行而非编译执行的。此外,VBA主要用于Office软件的宏编程和自动化处理,对于其他领域的开发可能不太适用。

如何使用Excel中的VBA

参考链接小步教程
首先,要想使用VBA,需要新建启用宏的工作簿文件后缀名是xlsm
然后再文件-选项中-自定义功能区 选中开发工具

在这里插入图片描述

简单基础入门

控制台输出信息

使用

Debug.Print ""

以及立即窗口(控制台)

定义过程(功能)

Sub 函数名End Sub

定义变量

Dim 变量名 As 数据类型
Dim a As String

常用的数据类型

  • Workbook 工作簿 表示整个Excel文件,包括所有的工作表
  • Worksheet 工作表 表示单个工作表
  • String 字符串
  • Long 存储大整数,比如行号 (-2,147,483,648 到 2,147,483,647)

Set

给自己定义的变量指向一个对象

' 设置源工作表Set wsSource = ThisWorkbook.Sheets(sourceSheetName)' 打开目标工作簿Set wbTarget = Workbooks.Open("C:\Users\Administrator\Desktop\nosee\EXCEL\测试填充目标文件.xlsm")

循环

VBA循环结构包括四类结构:For To、For Each、While、Do While。

For To

在这里插入图片描述
在这里插入图片描述
退出当前循环

在这里插入图片描述
退出整个循环
在这里插入图片描述

我的需求

要有图形化界面

  • 可以自己选择需要对账的工作表和送货表
  • 自己可以选择要对账的日期和范围 (可能要用到正则表达式)
  • 使用用户界面交互 选择送货单的位置和工作表 对账单的位置和表

开发过程

效果演示

视频如下:

文件情况

测试填充源文件

(这是代码里的名称,在实际工作中就对应送货单)
在这里插入图片描述

如上图,比较值得注意的点是:

  • 序号那种字段名称居然占了两行,这就导致有效数据是日期行加3,不知道做这个送货单的人怎么想的🙄,当时没注意看坑死我了。
  • 还有就是第九行的内容看起来横跨了很多单元格,但是其实只是在A列而已,只是没有展开
  • 还有一个细节就是,对比一下可以看出,在DATE 2024/8/31的下面三行就是有用的数据,而且有用的数据那一行的C、D列都有数据,这些都是我后面用来判断数据有效性的依据

测试填充目标文件

(这个也是代码里的名称,实际中对应的是对账单)
在这里插入图片描述
这个没什么好说的,以后希望也能把日期附在内容前以方便分开

全部完整的代码

sheet1中的代码,对应A公司工作表

    '全局变量 用来接收文件信息Public targetSheetName As StringPublic sourceSheetName As StringPublic targetFilePath As StringPublic dateToCheck As StringSub UserForm_Initialize()UserForm1.Show '打开用户界面
End SubSub CopyDataBasedOnDate() '定义函数  用户界面Dim wsSource As Worksheet '定义变量 Worksheet 是Excel中工作表的对象类型,表示单个工作表。源工作簿不用设置Dim wbTarget As Workbook  'Workbook 是Excel中工作簿的对象类型,表示整个Excel文件,包括所有的工作表。Dim lastRow As LongDim targetRowA As LongDim targetRowC As LongDim targetRow As Long 'Long 是VBA中的一种数据类型,用于存储较大的整数(-2,147,483,648 到 2,147,483,647)' 设置源工作表Set wsSource = ThisWorkbook.Sheets(sourceSheetName)' 打开目标工作簿Set wbTarget = Workbooks.Open(targetFilePath)' 找到目标工作表Dim wssTarget As Worksheet' ############设置异常?On Error Resume Next '这行代码是一个错误处理语句,它告诉VBA在遇到错误时不要显示错误消息,而是继续执行下一行代码。这是错误处理的开始。Set wssTarget = wbTarget.Sheets(targetSheetName) '通过 wsTarget 工作簿对象来访问名为 targetSheetName 的工作表,If wssTarget Is Nothing Then ' Nothing 表示一个变量没有引用任何对象。MsgBox "目标工作表不存在"Exit Sub  '这行代码会立即退出当前正在执行的子程序(Sub)。如果没有找到工作表,程序将不会继续执行后面的代码。End IfOn Error GoTo 0 '这行代码用于关闭之前启用的错误处理。在遇到错误时停止执行并显示错误消息。这行代码通常放在错误处理代码的最后,以确保错误处理的范围仅限于特定的代码块。' ############获取源工作表的最后一行  这里可能要调lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).RowtargetRowA = wssTarget.Cells(wssTarget.Rows.Count, "A").End(xlUp).RowtargetRowC = wssTarget.Cells(wssTarget.Rows.Count, "C").End(xlUp).RowtargetRow = Application.Max(targetRowA, targetRowC) + 2    '因为最后一行也是两行合并' ##############遍历源工作表中的所有行  应该要换个判断条件或者方式 根据日期,直到下一个日期Dim i As LongFor i = 1 To lastRow '遍历循环If wsSource.Cells(i, "A").Value = dateToCheck Then '如果第i行是要对账的日期For j = i + 3 To lastRow '日期内循环If j - i > 13 Then '3是必要的内容 因为有客套话 假如内容十行的话 就够了'最好的办法还是判断日期内循环有没有到下一个日期 到了就直接跳 结束了i = j - 1Exit ForEnd IfIf wsSource.Cells(j, "A").Value = dateToCheck Then '如果已经碰到下一个日期 比如同一天的 还有可能不是同一天的i = j - 1 '节省遍历循环的时间 跳出循环Exit ForEnd IfIf Not IsEmpty(wsSource.Cells(j, "C").Value) And Not IsEmpty(wsSource.Cells(j, "D").Value) Then'如果没有到下一个日期并且数据有效  c列d列不都为空就可以了wsSource.Rows(j).Copy Destination:=wssTarget.Rows(targetRow) 'targetRow = targetRow + 1End IfNext jEnd IfNext i' ############保存并关闭目标工作簿wbTarget.Save
'    wbTarget.CloseMsgBox "数据复制完成"
End Sub

UserForm1的代码

Sub dateToCheckCommandButton_Click()Sheet1.dateToCheck = dateToCheckTextBox.Text
End SubSub sourceSheetNameCommandButton_Click()Sheet1.sourceSheetName = sourceSheetNameTextBox.Text ' 把文本框的内容赋值给源工作表名字变量
End Sub
Sub targetFilePathCommandButton_Click()Sheet1.targetFilePath = targetFilePathTextBox.Text
End SubSub targetSheetNameCommandButton_Click()Sheet1.targetSheetName = targetSheetNameTextBox.Text ' 把文本框的内容赋值给目标工作表名字变量
End SubSub CommitCommandButton_Click()Sheet1.CopyDataBasedOnDate '调用复制程序
End Sub

待续

基础逻辑完善

获取行号

获取源文件行号是从下往上找获取A、C两个必定会有内容的列的单元格不为空的逻辑,但是别人的工作表不一定是这样的

  • 现在使用的是cell和max函数
lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
targetRowA = wssTarget.Cells(wssTarget.Rows.Count, "A").End(xlUp).Row
targetRowC = wssTarget.Cells(wssTarget.Rows.Count, "C").End(xlUp).Row
targetRow = Application.Max(targetRowA, targetRowC) + 2    '因为最后一行也是两行合并

搜了一下还可以用下面这些方法,日后试试

  • 使用UsedRange属性:
    UsedRange属性可以返回工作表中使用过的范围,然后可以通过这个范围来找到最后一行。
Dim lastRow As Long
lastRow = ThisWorkbook.Worksheets("Sheet1").UsedRange.Rows.Count
  • 使用SpecialCells方法:
    这个方法可以用来找到最后一行,特别是当表格中有空行时。
Dim lastRow As Long
On Error Resume Next ' 如果没有找到单元格,避免错误
lastRow = ThisWorkbook.Worksheets("Sheet1").Cells.SpecialCells(xlCellTypeLastCell).Row
On Error GoTo 0 ' 重新启用错误报告

遍历日期算法逻辑

For i = 1 To lastRow '遍历循环If wsSource.Cells(i, "A").Value = dateToCheck Then '如果第i行是要对账的日期For j = i + 3 To lastRow '日期内循环If j - i > 13 Then '3是必要的内容 因为有客套话 假如内容十行的话 就够了'最好的办法还是判断日期内循环有没有到下一个日期 到了就直接跳 结束了i = j - 1Exit ForEnd IfIf wsSource.Cells(j, "A").Value = dateToCheck Then '如果已经碰到下一个日期 比如同一天的 还有可能不是同一天的i = j - 1 '节省遍历循环的时间 跳出循环Exit ForEnd IfIf Not IsEmpty(wsSource.Cells(j, "C").Value) And Not IsEmpty(wsSource.Cells(j, "D").Value) Then'如果没有到下一个日期并且数据有效  c列d列不都为空就可以了wsSource.Rows(j).Copy Destination:=wssTarget.Rows(targetRow) 'targetRow = targetRow + 1End IfNext jEnd IfNext i

我在源文件遍历日期的方法是从第一行查找到最后一行,如果遇到匹配的字符串,就再内嵌一个循环,因为一个日期内有很多数据需要一行行地复制过去,还要判断数据的有效性

这里解释一下
For j = i +3是因为序号那一行是两行合并,所以有效数据是日期+3行 ,j-i>13是因为一般来说一次送货不会超过十种货,也就是对应十行数据了

提升对单元格等对象的操作知识

可以看出我对对单元格本身不了解 内置函数和属性不熟 所以判断数据有效性的条件很抽象

功能升级

  • 目前可以实现在页面不关闭的情况下一次插入一天的对账信息,但是这样也不够快,要是能一次插入一个时间范围内的对账信息就好了,估计要新增很多判断逻辑,以及对字符串的一些操作处理(因为有时候你的源工作表不一定就是2024/8/31这样的数据),最好是再做一个控件。

  • 输入文件路径有点麻烦,尝试改进成浏览文件的方式选中。

  • 未来要加入判断插入的数据是否是已有数据的逻辑才行,否则会重复插入 而且最好能提示用户“重复插入了”

  • 从送货单复制的数据到对账单并不是会完美一一对应,因为对账单和送货单所需要的信息不一定是一一对应的,可能会多或者少或者顺序不对,还有一些比较奇葩的是粘贴的目标列合并了,所以要怎么匹配列去进行粘贴 是一个问题

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 键值对数据库学习

目录 一、介绍 二、安装以及连接 三、设置连接密码 四、连接报错 五、redis 操作字符串以及过期时间 六、 redis 列表操作 七、redis 集合操作 八、hash 哈希操作 九、redis 发布和订阅操作 十、RDB和AOF的两种数据持久化机制 十一、 其他机器连接redis 十二、 pyt…

CentOS8.5.2111(3)实验之DHCP服务器架设

一、实验目标 1.掌握DHCP服务器的主配置文件各项申明参数及操作及其含义 2. 具备DHCP 服务器、中继服务器的配置能力 3. 具备测试客户端正常获取服务器分配地址的能力 4. 具备DHCP服务器故障排除能力 二、实训原理/流程 (一)项目背景 …

Golang | Leetcode Golang题解之第443题压缩字符串

题目: 题解: func compress(chars []byte) int {write, left : 0, 0for read, ch : range chars {if read len(chars)-1 || ch ! chars[read1] {chars[write] chwritenum : read - left 1if num > 1 {anchor : writefor ; num > 0; num / 10 {…

Unity3D入门(四) : Android和Unity3D交互 - Unity调用Android

1. 前言 上篇文章,我们讲了如何通过Android调用Unity3D。这篇文章,我们来讲一下Unity3D怎么调用Android。 1.1 unity和Android的三种通信方式 Unity官方提供的接口 : 有一个弊端,它有一个传输内容量的一个限制,传输内容过大或过…

安装管理K8S的开源项目KubeClipper介绍

安装管理K8S的开源项目KubeClipper介绍 1. 概述 KubeClipper是九州云开源的一个图形化界面 Kubernetes 多集群管理工具,旨在提供易使用、易运维、极轻量、生产级的 Kubernetes 多集群全生命周期管理服务。让运维工程师从繁复的配置和晦涩的命令行中解放出来&#…

02-ZYNQ linux开发环境安装,基于Petalinux2022.2和Vitis2022.2

petalinux安装 Petalinux 工具是 Xilinx 公司推出的嵌入式 Linux 开发套件,包括了 u-boot、Linux Kernel、device-tree、rootfs 等源码和库,以及 Yocto recipes,可以让客户很方便的生成、配置、编译及自定义 Linux 系统。Petalinux 支持 Ver…

Linux集群部署RabbitMQ

目录 一、准备三台虚拟机,配置相同 1、所有主机都需要hosts文件解析 2、所有主机安装erLang和rabbitmq 3、修改配置文件 4、导入rabbitmq 的管理界面 5、查看节点状态 6、设置erlang运行节点 7、rabitmq2和rabbitmq3重启服务 8、查看各个节点状态 二、添加…

解锁初中学习新境界 —— 初中通关宝典速记手册

在初中这个学习生涯的关键阶段,掌握扎实的基础知识是取得优异成绩的关键。为此,我们特别推荐《初中通关宝典》——一本专为初中生打造的各科基础知识速记手册,它将成为你学习路上的得力助手。 文章目录 1. 全科覆盖,精准速记2.科学…

socket.io-client实现实前后端时通信功能

这里我使用的后端 基于node.js的koa框架 前端使用的是vite {"name": "hou","version": "1.0.0","description": "","main": "app.js","scripts": {"test": "echo …

老古董Lisp实用主义入门教程(12):白日梦先生的白日梦

白日梦先生的白日梦 白日梦先生已经跟着大家一起学Lisp长达两个月零五天! 001 粗鲁先生Lisp再出发002 懒惰先生的Lisp开发流程003 颠倒先生的数学表达式004 完美先生的完美Lisp005 好奇先生用Lisp来探索Lisp006 好奇先生在Lisp的花园里挖呀挖呀挖007 挑剔先生给出…

手游和应用出海资讯:三七新游首月收入突破700万元;领英尝试推出游戏功能以增加用户使用时长

NetMarvel帮助游戏和应用广告主洞察全球市场、获取行业信息,以下为9月第四周资讯: ● 《AFK Journey》收入突破 1.5 亿美元 ● 《黑神话:悟空》IGN年度游戏投票第一掉至第三 ● 三七发布新游首月收入突破700万元 ● 开罗游戏《哆啦A梦的铜锣烧…

Java SPI 原理、样例

在 Java 中,SPI(Service Provider Interface)全称为服务提供者接口,它是一种用于实现框架扩展和插件化的机制。 一、SPI 作用 允许在运行时动态地为接口查找服务实现,而不需要在代码中显式地指定具体的实现类。 这使得…

关系模型与关系代数——数据库原理 总结2

2.1 关系模型 关系数据结构 关系模型的数据结构是二维表,亦称为关系。关系数据库是表的集合,即关系的集合。表是一个实体集,一行就是一个实体,它由有关联的若干属性的值所构成。 关系模型的相关概念 列就是数据项 或 字段 或 属…

基于SpringCloud的微服务架构下安全开发运维准则

为什么要进行安全设计 微服务架构进行安全设计的原因主要包括以下几点: 提高数据保护:微服务架构中,服务间通信频繁,涉及到大量敏感数据的交换。安全设计可以确保数据在传输和存储过程中的安全性,防止数据泄露和篡改。…

Study--Oracle-09--部署Openfiler存储服务器

免费的存储服务器软件有FreeNAS 和 Openfiler。 其中Freenas的网站上只有i386及amd64的版本,也就是说Freenas不能支持64位版本的Intel CPU,而Openfiler则提供更全面的版本支持,在其网站上可以看到支持多网卡、多CPU,以及硬件Raid的支持,还有10Gb网卡的支持。 Openfiler能把…

【RocketMQ】RocketMQ发送不同类型消息

🎯 导读:本文介绍了RocketMQ消息队列系统中的几种消息发送模式及其应用场景,包括同步消息、异步消息以及事务消息。同步消息确保了消息的安全性,但牺牲了一定的性能;异步消息提高了响应速度,适用于对响应时…

演示:基于WPF的DrawingVisual开发的频谱图和律动图

一、目的:基于WPF的DrawingVisual开发的频谱图和律动图 二、效果演示 波形图 极坐标 律动图极坐标图 律动图柱状图 Dock布局组合效果 三、环境 VS2022,Net7,Win10,NVIDIA RTX A2000 四、主要功能 支持设置起始频率,终止频率,中心…

【HTTP 和 HTTPS详解】3

HTTP 状态代码 HTTP 状态代码是服务器发送给客户端的三位数字,用于指示客户端请求的结果。它们分为五类:信息性(100-199)、成功(200-299)、重定向(300-399)、客户端错误&#xff08…

【移植】Combo解决方案之W800芯片移植案例

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 本方案基于 OpenHarmony LiteOS-M 内核,使用联盛德 W80…

[论文精读]Membership Inference Attacks Against Machine Learning Models

中文译名:针对机器学习模型的成员推理攻击 会议名称:2017 IEEE Symposium on Security and Privacy (SP) 发布链接:Membership Inference Attacks Against Machine Learning Models | IEEE Conference Publication | IEEE Xplore CODE:Git…