ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
12
返回列表 发新帖
楼主: yylucke

[求助] Worksheet_SelectionChange中有代码后,工作表不能复制粘贴

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-8-2 16:47 | 显示全部楼层
原文地址:Excel中Worksheet_SelectionChange事件与粘贴冲突作者:nichosen
     在Excel2003中如果你在"Worksheet_SelectionChange"事件中写了VBA代码的话粘贴功能就会失效.还没有一个很好的解决方案,据说是2003的Bug,下面的代码可以暂时解决这个问题,不过这个代码本身有一些小Bug:整行选的话会报错,把它catch掉就可以了:-)。

但是对正常使用不会有太大影响。

There is a temp solution for this problem:

//------------------------------------------------------------------------------------

Extra code in Worksheet_SelectionChange:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

On Error GoTo err

'/错误处理,发生异常时转到err

Dim rngCutCopy As Range
Dim iCutCopymode As Integer
If CutCopyMode Then
Set rngCutCopy = CutCopyRange
Else
Set rngCutCopy = Nothing
End If
iCutCopymode = CutCopyMode

//Your Code


If iCutCopymode = xlCopy Then
rngCutCopy.Copy
ElseIf iCutCopymode = xlCut Then
rngCutCopy.Cut
End If

err:

'/异常时不做任何处理,只是为了屏蔽对话框

End Sub

//-------------------------------------------------------------------------------

Extra code in modules

Option Explicit
'/锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处
Private Declare Function GlobalLock _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/解锁先前被锁定的内存,使得指向内存块的指针无效
Private Declare Function GlobalUnlock _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/得到的是内存块的大小
Private Declare Function GlobalSize _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/打开剪切板
Private Declare Function OpenClipboard _
Lib "user32" ( _
ByVal hwnd As Long) _
As Long
'/关闭剪切板
Private Declare Function CloseClipboard _
Lib "user32" () _
As Long
'/获取剪切板数据
Private Declare Function GetClipboardData _
Lib "user32" ( _
ByVal wFormat As Long) _
As Long
'/将一块内存的数据从一个位置复制到另一个位置
Private Declare Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long)
'//--------------------------------------------------------------------------------------//
'//-----用于取得处于复制或者剪切状态的单元格区域的函数------//
'//--------------------------------------------------------------------------------------//
Public Function CutCopyRange () As Range
On Error GoTo Hanlder
Dim bytData() As Byte, hMem As Long, nClipsize As Long, lpData As Long
Dim sSource As String, sTemp() As String
Dim sWorkbook As String, sSheet As String, sRange As String
'/打开剪切板
OpenClipboard 0&
'/取得剪切板中有关Excel单元格复制的信息数据
hMem = GetClipboardData (49154)
'/假如存在数据
If CBool(hMem) Then
'/取得数据内存的大小
nClipsize = GlobalSize (hMem)
'/锁定此内存块,并返回内存块的起始地址
lpData = GlobalLock (hMem)
If lpData <> 0 Then
'/从新定义数组大小
ReDim bytData(0 To nClipsize - 1) As Byte
'/将内存复制到数组中
CopyMemory bytData(0), ByVal lpData, nClipsize
'/将二进制数组转换成字符串
sSource = StrConv (bytData, vbUnicode)
'/拆分字符串
sTemp = Split(sSource, Chr(0))
'/假使在拆分得到的字符串2中找到""(即工作薄已经保存)
If InStr (sTemp(1), "") Then
'/取得工作薄的名称
sWorkbook = Mid(sTemp(1), InStrRev (sTemp(1), "") + 1)
Else
'/取得工作薄的名称
sWorkbook = sTemp(1)
End If
'/取得工作表的名称
sSheet = Left(sTemp(2), InStr (sTemp(2), "!") - 1)
'/取得单元格区域的地址
sRange = R1C1 _To_A1(Mid(sTemp(2), InStr (sTemp(2), "!") + 1))
'/取得处于剪切或者复制状态的单元格
Set CutCopyRange = Workbooks(sWorkbook).Sheets(sSheet).Range(sRange)
End If
'/解锁 内存
GlobalUnlock hMem

'/假如未处于复制或者剪切状态
Else
Set CutCopyRange = Nothing
End If
'/关闭剪切板
CloseClipboard
Exit Function
Hanlder:
Debug.Print err.Number & err.Description
End Function
'//--------------------------------------------------------------------------
'//----用于将单元格的R1C1引用样式转换为A1样式------
'//--------------------------------------------------------------------------
Private Function R1C1 _To_A1(RgStr As String) As String
Dim sTemp() As String
If InStr (RgStr , ":") Then
sTemp = Split(RgStr , ":")
R1C1 _To_A1 = R1C1 _To_A1(sTemp(0)) & ":" & R1C1 _To_A1(sTemp(1))
Else
RgStr = Mid(RgStr , 2)
sTemp = Split(RgStr , "C")
R1C1 _To_A1 = Chr(64 + sTemp(1)) & sTemp(0)
End If
End Function

TA的精华主题

TA的得分主题

发表于 2024-2-28 17:58 | 显示全部楼层
类模块中内容,注意是类模块!!!!!



Option Explicit
'/锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处
Private Declare PtrSafe Function GlobalLock _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/解锁先前被锁定的内存,使得指向内存块的指针无效
Private Declare PtrSafe Function GlobalUnlock _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/得到的是内存块的大小
Private Declare PtrSafe Function GlobalSize _
Lib "kernel32" ( _
ByVal hMem As Long) _
As Long
'/打开剪切板
Private Declare PtrSafe Function OpenClipboard _
Lib "user32" ( _
ByVal hwnd As Long) _
As Long
'/关闭剪切板
Private Declare PtrSafe Function CloseClipboard _
Lib "user32" () _
As Long
'/获取剪切板数据
Private Declare PtrSafe Function GetClipboardData _
Lib "user32" ( _
ByVal wFormat As Long) _
As Long
'/将一块内存的数据从一个位置复制到另一个位置
Private Declare PtrSafe Sub CopyMemory _
Lib "kernel32" _
Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long)
'//--------------------------------------------------------------------------------------//
'//-----用于取得处于复制或者剪切状态的单元格区域的函数------//
'//--------------------------------------------------------------------------------------//
Public Function CutCopyRange() As Range
On Error GoTo Hanlder
Dim bytData() As Byte, hMem As Long, nClipsize As Long, lpData As Long
Dim sSource As String, sTemp() As String
Dim sWorkbook As String, sSheet As String, sRange As String
'/打开剪切板
OpenClipboard 0&
'/取得剪切板中有关Excel单元格复制的信息数据
hMem = GetClipboardData(49154)
'/假如存在数据
If CBool(hMem) Then
'/取得数据内存的大小
nClipsize = GlobalSize(hMem)
'/锁定此内存块,并返回内存块的起始地址
lpData = GlobalLock(hMem)
If lpData <> 0 Then
'/从新定义数组大小
ReDim bytData(0 To nClipsize - 1) As Byte
'/将内存复制到数组中
CopyMemory bytData(0), ByVal lpData, nClipsize
'/将二进制数组转换成字符串
sSource = StrConv(bytData, vbUnicode)
'/拆分字符串
sTemp = Split(sSource, Chr(0))
'/假使在拆分得到的字符串2中找到""(即工作薄已经保存)
If InStr(sTemp(1), "") Then
'/取得工作薄的名称
sWorkbook = Mid(sTemp(1), InStrRev(sTemp(1), "") + 1)
Else
'/取得工作薄的名称
sWorkbook = sTemp(1)
End If
'/取得工作表的名称
sSheet = Left(sTemp(2), InStr(sTemp(2), "!") - 1)
'/取得单元格区域的地址
sRange = R1C1_To_A1(Mid(sTemp(2), InStr(sTemp(2), "!") + 1))
'/取得处于剪切或者复制状态的单元格
Set CutCopyRange = Workbooks(sWorkbook).Sheets(sSheet).Range(sRange)
End If
'/解锁 内存
GlobalUnlock hMem

'/假如未处于复制或者剪切状态
Else
Set CutCopyRange = Nothing
End If
'/关闭剪切板
CloseClipboard
Exit Function
Hanlder:
Debug.Print err.Number & err.Description
End Function
'//--------------------------------------------------------------------------
'//----用于将单元格的R1C1引用样式转换为A1样式------
'//--------------------------------------------------------------------------
Private Function R1C1_To_A1(RgStr As String) As String
Dim sTemp() As String
If InStr(RgStr, ":") Then
sTemp = Split(RgStr, ":")
R1C1_To_A1 = R1C1_To_A1(sTemp(0)) & ":" & R1C1_To_A1(sTemp(1))
Else
RgStr = Mid(RgStr, 2)
sTemp = Split(RgStr, "C")
R1C1_To_A1 = Chr(64 + sTemp(1)) & sTemp(0)
End If
End Function






Private Sub Worksheet_SelectionChange(ByVal Target As Range)

On Error GoTo err

'/错误处理,发生异常时转到err

Dim rngCutCopy As Range
Dim iCutCopymode As Integer
If CutCopyMode Then
Set rngCutCopy = CutCopyRange
Else
Set rngCutCopy = Nothing
End If
iCutCopymode = CutCopyMode


    自己代码


If iCutCopymode = xlCopy Then
rngCutCopy.Copy
ElseIf iCutCopymode = xlCut Then
rngCutCopy.Cut
End If

err:

'/异常时不做任何处理,只是为了屏蔽对话框

End Sub


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-18 16:47 , Processed in 0.027146 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表