前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >仿Excel的撤销功能

仿Excel的撤销功能

作者头像
fanjy
发布2024-05-13 16:08:18
930
发布2024-05-13 16:08:18
举报
文章被收录于专栏:完美Excel完美Excel

标签:VBA,工作表事件

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

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

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

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

代码语言:javascript
复制
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
复制
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
复制
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 删除。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档