Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >仿Excel的撤销功能

仿Excel的撤销功能

作者头像
fanjy
发布于 2024-05-13 08:08:18
发布于 2024-05-13 08:08:18
25200
代码可运行
举报
文章被收录于专栏:完美Excel完美Excel
运行总次数:0
代码可运行

标签:VBA,工作表事件

这是在www.vbaexpress.com中看到的一个示例,实现了自己以前想做而未做的事情。

也就是,模仿Excel的撤销功能,特别是当VBA代码对工作表进行操作后,使用Excel原始的撤销功能是无法恢复的,但可以使用VBA代码来实现,似乎就像Excel的撤销功能一样。

主要思路是使用一个工作表,来记录对工作表所做的修改,如果要撤销这些修改,就从这个工作表取出原来的值来恢复。注意,本文的示例只针对特定区域,且只能撤销两次。

在ThisWorkbook模块中,输入下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Private Sub Workbook_Open()
 Dim endRow As Long
 
 With Sheets("UNDO")
   endRow = .Cells(Rows.Count, 1).End(xlUp).Row
   If endRow > 1 Then
     .Range("A2:D" & endRow).ClearContents
   End If
 End With
End Sub

在操作的工作表相应的代码模块中输入下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Dim i As Long
Private Sub Worksheet_Change(ByVal Target As Range)
 Dim rngToProcess As Range
 Dim sNewValue
 Dim sOldValue
 Dim rCell As Range
 Dim nr As Long
 
 Set rngToProcess = Intersect(Target, Range("C5:C14")) '设置可编辑的单元格区域
 If Not rngToProcess Is Nothing Then
   Application.EnableEvents = False
   sNewValue = Target.Value
   sOldValue = Target.Offset(, 1).Value
   Application.UNDO ' 撤销最后一次输入
   Target.Offset(, 1).Value = Target.Value
  ' 将之前的值放置到目标单元格右侧的单元格
   i = i + 1 ' 增加实例, 用于UNDO过程
   For Each rCell In rngToProcess ' 遍历目标区域中的单元格
     With Sheets("UNDO")
       nr = .Cells(Rows.Count, 1).End(xlUp).Row + 1
       .Range("A" & nr) = i
       .Range("B" & nr) = rCell.Address
       .Range("C" & nr) = rCell.Offset(, 1).Value
       .Range("D" & nr) = sOldValue
     End With
   Next rCell
   Target.Value = sNewValue
   Application.EnableEvents = True
 End If
End Sub

插入一个标准模块,输入下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Sub UNDO()
 Dim wsU As Worksheet
 Dim ws1 As Worksheet
 Dim x As Long
 Dim wsUend As Long
 Dim inst As Long
 Dim rCell As Range
 
 Application.EnableEvents = False ' 关闭事件以便下面的代码不会触发Worksheet_Change事件
 Set wsU = Sheets("UNDO") ' 名为UNDO的隐藏工作表
 Set ws1 = Sheets("Sheet1") ' 要撤销操作的工作表
 wsUend = wsU.Cells(Rows.Count, 1).End(xlUp).Row ' 工作表UNDO的最后有数据的行
 On Error GoTo JumpOut ' 如果下一行的代码产生错误则跳转到过程底部的JumpOut处
 inst = wsU.Range("A" & wsUend).Value ' 添加到UNDO工作表中的最新实例
 On Error GoTo 0 ' 恢复错误处理
 
 For x = wsUend To 2 Step -1 ' 向前遍历UNDO工作表
   If wsU.Range("A" & x) = inst Then ' 检查UNDO工作表的当前行是否是最新实例
     Set rCell = ws1.Range(wsU.Range("B" & x)) ' 创建对ws1单元格区域的引用
     rCell.Value = wsU.Range("C" & x).Value ' 将之前的值写回ws1
     rCell.Offset(, 1) = wsU.Range("D" & x).Value ' 将之前的值写回ws1
     wsU.Range("A" & x & ":D" & x).ClearContents ' 清空UNDO工作表中的行, 这允许有更多的撤销
   Else
     Exit For ' 退出循环
   End If
 Next x
 Application.EnableEvents = True ' 恢复事件触发
 Exit Sub
JumpOut:
 Application.EnableEvents = True ' 恢复事件触发
 MsgBox "没有什么可以撤销", vbInformation, "UNDO"
End Sub

有兴趣的朋友,可以到原网站搜索并下载该示例工作簿。

或者,在完美Excel微信公众号中发送消息:

仿撤销功能

获取示例工作簿下载链接。

或者,直接到知识星球APP完美Excel社群中下载该工作簿。

欢迎在下面留言,完善本文内容,让更多的人学到更完美的知识。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 完美Excel 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Excel事件示例(二)
Excel工作表中有时有单元格的值希望被锁定,输入密码后才能修改,通常我们使用”审阅“的“保护工作簿”功能来实现,那下面通过vba代码也来实现一下。
无言之月
2019/10/13
1K0
VBA技巧:记住单元格更改之前的值
当工作表单元格中的值被修改后,我需要将修改前的值放置到其右侧单元格中。例如,单元格A1中输入有数值1,当我将其内容修改为2之后,之前的数值1被放置到单元格B2中。可以使用工作表Change事件来实现。
fanjy
2024/03/26
7320
VBA技巧:记住单元格更改之前的值
Excel实战技巧83: 制作动态的笑脸图
这是在contexturesblog.com中看到的一个技巧,非常有意思,稍作整理和修改,在这里和大家分享。
fanjy
2020/07/14
1.2K0
Excel事件(二)工作表事件
大家好,上节介绍了excel事件的基础知识,后面就按照事件的分类来介绍,本节将首先介绍vba程序开发中最常用的工作表事件。
无言之月
2019/10/13
3.8K0
Excel实战技巧84: 让形状生动起来
我们可以将《Excel实战技巧83:制作动态的笑脸图》中介绍的技术运用到其他类型的形状中。下面再举一个例子,如下图1所示。
fanjy
2020/07/24
4510
Excel实战技巧84: 让形状生动起来
Excel VBA编程
在Excel中,数据只有文本,数值,日期值,逻辑值和错误值五种类型。但是在VBA中,数据类型跟Excel不完全相同。根据数据的特点,VBA将数据分为布尔型(boolean),字节型(byte),整数型(integer),单精度浮点型(single),双精度浮点型(double),货币型(currency),小数型(decimal),字符串型(string),日期型(date),对象型等等
全栈程序员站长
2022/08/11
46.9K0
Excel VBA编程
工作表事件示例:输入数据后锁定单元格
打开VBE,在工程资源管理器中双击该工作表名称打开其代码模块,在其中输入下面的代码:
fanjy
2024/06/18
2130
工作表事件示例:输入数据后锁定单元格
Excel实战技巧59: 使用VBA让用户仅能在指定单元格或单元格区域中输入数字
通常,我们可以使用Excel的“数据验证”功能来设置指定单元格或单元格区域仅能输入指定范围的整数或者小数,如下图1所示。
fanjy
2019/11/07
2.6K1
Excel实战技巧59: 使用VBA让用户仅能在指定单元格或单元格区域中输入数字
EXCEL VBA语句集300
        定制模块行为 (1) Option Explicit ‘强制对模块内所有变量进行声明 Option Private Module ‘标记模块为私有,仅对同一工程中其它模块有用,在宏对话框中不显示  Option Compare Text ‘字符串不区分大小写  Option Base 1 ‘指定数组的第一个下标为1 (2) On Error Resume Next ‘忽略错误继续执行VBA代码,避免出现错误消息 (3) On Error GoTo ErrorHandler ‘当错误发生时跳转到过程中的某个位置 (4) On Error GoTo 0 ‘恢复正常的错误提示 (5) Application.DisplayAlerts=False ‘在程序执行过程中使出现的警告框不显示 (6) Application.ScreenUpdating=False ‘关闭屏幕刷新 Application.ScreenUpdating=True ‘打开屏幕刷新 (7) Application.Enable.CancelKey=xlDisabled ‘禁用Ctrl+Break中止宏运行的功能  工作簿 (8) Workbooks.Add() ‘创建一个新的工作簿 (9) Workbooks(“book1.xls”).Activate ‘激活名为book1的工作簿 (10) ThisWorkbook.Save ‘保存工作簿 (11) ThisWorkbook.close ‘关闭当前工作簿 (12) ActiveWorkbook.Sheets.Count ‘获取活动工作薄中工作表数 (13) ActiveWorkbook.name ‘返回活动工作薄的名称 (14) ThisWorkbook.Name ‘返回当前工作簿名称 ThisWorkbook.FullName ‘返回当前工作簿路径和名称 (15) ActiveWindow.EnableResize=False ‘禁止调整活动工作簿的大小 (16) Application.Window.Arrange xlArrangeStyleTiled ‘将工作簿以平铺方式排列 (17) ActiveWorkbook.WindowState=xlMaximized ‘将当前工作簿最大化  工作表 (18) ActiveSheet.UsedRange.Rows.Count ‘当前工作表中已使用的行数 (19) Rows.Count ‘获取工作表的行数(注:考虑向前兼容性) (20) Sheets(Sheet1).Name= “Sum” ‘将Sheet1命名为Sum (21) ThisWorkbook.Sheets.Add Before:=Worksheets(1) ‘添加一个新工作表在第一工作表前 (22) ActiveSheet.Move After:=ActiveWorkbook. _ Sheets(ActiveWorkbook.Sheets.Count) ‘将当前工作表移至工作表的最后 (23) Worksheets(Array(“sheet1”,”sheet2”)).Select ‘同时选择工作表1和工作表2 (24) Sheets(“sheet1”).Delete或 Sheets(1).Delete ‘删除工作表1 (25) ActiveWorkbook.Sheets(i).Name ‘获取工作表i的名称 (26) ActiveWindow.DisplayGridlines=Not ActiveWindow.DisplayGridlines ‘切换工作表中的网格线显示,这种方法也可以用在其它方面进行相互切换,即相当于开关按钮 (27) ActiveWindow.DisplayHeadings=Not ActiveWindow.DisplayHeadings ‘切换工作表中的行列边框显示 (28) ActiveSheet.UsedRange.FormatConditions.Delete ‘删除当前工作表中所有的条件格式 (29) Cells.Hyperlinks.Delete ‘取消当前工作表所有超链接 (30) ActiveSheet.PageSetup.Orientation=xlLandscape 或ActiveSheet.PageSetup.Orientation=2 ‘将页面设置更改为横向 (31) ActiveSheet.PageSetup.RightFooter=ActiveWorkbook.FullName ‘在页面设置的表尾中输入文件路径 ActiveSheet.PageSetup.Le
Tony老师
2020/03/05
2.3K0
VBA程序:列出指定工作表中的所有公式
下面的VBA过程在指定的新工作表中列出指定工作表中的所有公式,包含具体的公式、所在工作表名称及其所在单元格地址。
fanjy
2024/01/15
5570
VBA程序:列出指定工作表中的所有公式
Excel应用实践14:合并多个工作簿中的数据—示例3
要合并工作簿的情形有许多种,但最终的目的只有一条,将繁锁的手工操作自动化,让程序快速帮助我们完成这些重复的工作。
fanjy
2019/07/19
1.7K0
一起学Excel专业开发21:Excel工时报表与分析系统开发(3)——自定义用户界面
一起学Excel专业开发20:Excel工时报表与分析系统开发(3)——自定义用户界面
fanjy
2019/11/07
2.1K0
一起学Excel专业开发21:Excel工时报表与分析系统开发(3)——自定义用户界面
使用VBA创建相关联的数据有效性列表
如下图1所示,当选择工作表Sheet2列A中的单元格下拉列表项后,其相邻列B中的单元格下拉列表项会与列A中选择项相关联,也就是说,列A中选择不同的项,列B中也会呈现相应的项。
fanjy
2024/06/18
2750
使用VBA创建相关联的数据有效性列表
问与答95:如何根据当前单元格中的值高亮显示相应的单元格?
Q:这个问题很奇怪,需要根据在工作表Sheet1中输入的数值高亮显示工作表Sheet2中相应的单元格。具体如下:
fanjy
2021/03/12
4.4K0
VBA实战技巧:快速返回最后一次编辑的单元格
在有些情况下,我们可能需要快速返回到最后一次编辑的单元格。例如,最后一次编辑的单元格是单元格K112,然而我的当前单元格在单元格C1,如何定位这个最后编辑的单元格并快速返回到该单元格呢?
fanjy
2022/11/16
1K0
VBA实战技巧:快速返回最后一次编辑的单元格
VBA实战技巧35:使用VBA组织图形2
引言:本文的代码与昨天发表的《VBA实战技巧34:使用VBA组织图形1》一样,都整理自mrexcel.com,一个很好的令人兴奋的示例,有兴趣的朋友可以仔细研究。
fanjy
2021/09/22
1.8K0
Excel事件(四)事件顺序
对于Excel事件的五种类别,已经分别介绍了工作表事件和工作簿事件。而不与对象相关的事件(即ontime方法和onkey方法)也在application主程序对象方法介绍过。(可通过蓝字链接查看。)
无言之月
2019/10/13
2.5K0
Excel应用实践22: 比较并合并工作表
有两个工作表,均含有相同的数据,但最后一列名称和产品的数量不同,如下图1和图2所示。
fanjy
2019/10/22
7760
Excel应用实践22: 比较并合并工作表
使用VBA合并工作表
从多个Excel工作表(子工作表)中获取信息,并用子工作表中的所有数据填充汇总工作表(父工作表),这是很多朋友会提到的常见要求。如果部分数据是从添加新工作表到工作簿中而增长的,那么获得这些数据的汇总非常方便,例如,添加单独的工作表,包含新月份的数据。
fanjy
2022/11/16
2.2K0
使用VBA合并工作表
Excel应用实践11:合并多个工作簿中的数据——示例2
在上一篇文章《Excel应用实践10:合并多个工作簿中的数据》中,我们使用代码快速合并超过50个Excel工作簿文件,然而,如果要合并的工作簿中工作表的名称不相同,但位于每个工作簿的第1个工作表;并且,要在合并后的工作表的第1列中输入相对应的工作簿文件名,以便知道合并后的数据来自哪个工作簿文件。
fanjy
2019/07/19
2.9K0
推荐阅读
相关推荐
Excel事件示例(二)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验