我有一个受保护的工作表,用户希望将其复制并粘贴到其中。我无法控制他们正在复制的工作簿。
受保护的工作表包含一些可用于数据输入的行,以及其他被锁定并显示给用户的行。用户希望能够从另一个随机工作簿粘贴整个工作表的顶部,并且可以填充所有可用于数据输入的单元格,而锁定的单元格不受干扰。在当前状态下,用户在尝试粘贴时会收到错误,因为它无法粘贴到锁定的单元格上。
示例:
工作表1:
Act1 100 100 100
Act2 100 100 100
Act3 100 100 100
工作表2 :(第二行被锁定)
Act1 300 300 300
Act2 200 200 200
Act3 100 100 100
复制/粘贴后,工作表2应如下所示:
Act1 100 100 100
Act2 200 200 200
Act3 100 100 100
填充工作表1中的值,锁定的行不受干扰。
答案 0 :(得分:2)
要求:
方法:
我参考Jan Karel的Catch Paste样本作为参考。您可能希望添加他捕获粘贴操作的所有方法。
在ThisWorkbook模块中添加以下代码
Private mdNextTimeCatchPaste As Double
Private Sub Workbook_Activate()
REM Add Paste event handler
CatchPaste
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
REM Restore Paste event handler
StopCatchPaste
mdNextTimeCatchPaste = Now
Application.OnTime mdNextTimeCatchPaste, "'" & ThisWorkbook.Name & "'!UnProtectPasteToSheet"
End Sub
Private Sub Workbook_Deactivate()
REM Restore Paste event handler
StopCatchPaste
On Error Resume Next
REM Cancel scheduled macroREM s,
REM because we might be closing the file
Application.OnTime mdNextTimeCatchPaste, "'" & ThisWorkbook.Name & "'!UnProtectPasteToSheet", , False
End Sub
Private Sub Workbook_Open()
REM Add Paste event handler
CatchPaste
End Sub
添加新模块并添加以下代码
REM Add Paste event handler
Public Sub CatchPaste()
REM these are the ways you can Paste in to Excel
REM refer to http://www.jkp-ads.com/articles/catchpaste.asp for more details
Application.OnKey "^v", "UnProtectPasteToSheet"
Application.OnKey "^{Insert}", "UnProtectPasteToSheet"
Application.OnKey "+{Insert}", "UnProtectPasteToSheet"
Application.OnKey "~", "UnProtectPasteToSheet"
Application.OnKey "{Enter}", "UnProtectPasteToSheet"
End Sub
REM restore all default events
Public Sub StopCatchPaste()
Application.OnKey "^v", ""
Application.OnKey "^{Insert}", ""
Application.OnKey "+{Insert}", ""
Application.OnKey "~", ""
Application.OnKey "{Enter}", ""
End Sub
REM Here we will check the sheet is protected, if it is then paste to a temp sheet,
REM unprotect main sheet, paste the values, and restore locked cells
Private Sub UnProtectPasteToSheet()
On Error GoTo ErrHandler
Dim bProtected As Boolean, oSheet As Worksheet, oTempSheet As Worksheet, sPasteLocation As String
Dim oCell As Range, oCollAddress As New Collection, oCollValue As New Collection, iCount As Integer
REM check protection status
If Not ThisWorkbook.ActiveSheet.ProtectContents Then
Selection.PasteSpecial Paste:=xlAll
Else
bProtected = True
Set oSheet = ThisWorkbook.ActiveSheet
REM save paste location
sPasteLocation = Selection.Address
REM unprotecting clears Clipboard in Excel!! strange but true..
REM So paste it to a new sheet before unprotecting
Set oTempSheet = ThisWorkbook.Worksheets.Add
REM oSheet.Visible = xlSheetVeryHidden
oTempSheet.Paste
REM unprotect the sheet
oSheet.Unprotect
REM make a note of all locked cells
For Each oCell In oSheet.UsedRange
If oCell.Locked Then
oCollAddress.Add oCell.Address
oCollValue.Add oCell.Value
End If
Next
REM paste
oTempSheet.UsedRange.Copy
oSheet.Activate
oSheet.Range(sPasteLocation).Select
REM you need to paste only values since pasting format will lock all those cells
REM since in Excel default status is "Locked"
Selection.PasteSpecial xlValues
REM remove temp sheet
Application.DisplayAlerts = False
oTempSheet.Delete
Application.DisplayAlerts = True
REM restore locked cells
For iCount = 1 To oCollAddress.Count
Range(oCollAddress.Item(iCount)) = oCollValue.Item(iCount)
Next
REM restore protection
oSheet.Protect
End If
Exit Sub
ErrHandler:
Debug.Print Err.Description
If bProtected Then
ThisWorkbook.ActiveSheet.Protect
End If
End Sub
注意:我正在添加REM
而不是'
以保持Stackoverflow格式化程序的满意度。
试一试,让我知道它是怎么回事......
答案 1 :(得分:0)
在处理了许多剪切和粘贴问题后,我可以说问题的简单解决方案是创建一个按钮来完成整个副本。只有当他们总是从同一个工作簿中复制时,这才会(轻松)工作(尽管如果需要,你可以编写一个更复杂的界面)。
代码可以调查锁定的单元格,然后有选择地将复制的单元格分解为连续的范围,并粘贴每个单独的范围。
答案 2 :(得分:0)
如果检测到粘贴区域与锁定的单元格重叠,则实际上可以中止粘贴操作。 事实上,Office-2007会为您执行此操作,如果要粘贴的任何单元格被锁定且工作表受到保护,则Office-2007将无法执行粘贴操作,并会抛出错误消息。
在以前版本的Excel和未受保护的工作表中(但锁定单元格很少,不起任何作用),如果要修改的任何单元格被锁定,您可以使用函数来撤消更改。
Private Sub Worksheet_Change(ByVal Target As Range)
Dim oCell As Range
For Each oCell In Target
If oCell.Locked = True Then
'disable events to prevent recursive function call
Application.EnableEvents = False
'undo the paste
Application.Undo
'enable events
Application.EnableEvents = True
Exit For
End If
Next
End Sub
编辑:在发布该答案后,我意识到在Excel中,默认情况下所有呼叫都被标记为已锁定。因此,如果他们从普通纸张粘贴,那么目标单元格可能会读取“已锁定”,因为过去只是锁定它!所以我有一个改进的方法,它允许你将一些东西粘贴到一张纸上,它只会保持“锁定”单元格完好无损。
这里的想法是我们将在粘贴后捕获新状态,然后撤消所有更改。然后我们将遍历刚更改的单元格并检查它们是否在粘贴操作之前被锁定。如果不是,那么我们将重新填充粘贴的值。使用此代码,您将获得您在示例中询问的结果。
Private Sub Worksheet_Change(ByVal Target As Range)
Dim oCell As Range, oCollAddress As New Collection, oCollValue As New Collection, iCount As Integer
'get all pasted content in to a collection
For Each oCell In Target
oCollAddress.Add oCell.Address
oCollValue.Add oCell.Value
Next
'undo the changes done, and re-paste it for unlocked cells
'disable events to prevent infinite calls
Application.EnableEvents = False
Application.Undo
For iCount = 1 To oCollAddress.Count
If Range(oCollAddress.Item(iCount)).Locked = False Then
Range(oCollAddress.Item(iCount)) = oCollValue.Item(iCount)
End If
Next
Application.EnableEvents = True
End Sub
编辑2010年5月27日:好的,那么您需要捕获粘贴操作(事件),并手动处理它而不是Excel。我正在添加一个新答案,因为它太大了。
答案 3 :(得分:0)
我认为关键是优雅地阻止标准粘贴功能并以受控方式重做粘贴
我听说在以后的Excel版本中有一个“On-Paste”事件(不确定),但这在2003年不可用。我在2003年通过以下代码捕获粘贴动作(由适当的事件调用像Sheet_Activate())这样的过程:
Sub SetPasteTrap(Mode As Boolean)
' TRUE sets the trap, FALSE releases trap
If Mode Then
Application.CommandBars("Edit").Controls("Paste").OnAction = "TrappedPaste"
Application.CommandBars("Edit").Controls("Paste Special...").OnAction = "TrappedPaste"
Application.CommandBars("Cell").Controls("Paste").OnAction = "TrappedPaste"
Application.CommandBars("Cell").Controls("Paste Special...").OnAction = "TrappedPaste"
Application.OnKey "^v", "TrappedPaste"
Else
Application.CommandBars("Edit").Controls("Paste").OnAction = ""
Application.CommandBars("Edit").Controls("Paste Special...").OnAction = ""
Application.CommandBars("Cell").Controls("Paste").OnAction = ""
Application.CommandBars("Cell").Controls("Paste Special...").OnAction = ""
Application.OnKey "^v"
End If
End Sub
通过这个我们捕获主菜单,上下文菜单和Ctrl-V键 - 这应该足够了。 OnAction属性转移到参数
中包含的子Sub TrappedPaste()
If ActiveSheet.ProtectContents Then
' as long as sheet is protected, we don't paste at all
MsgBox "Sheet is protected, all Paste/PasteSpecial functions are disabled." & vbCrLf & _
"At your own risk you may unprotect the sheet." & vbCrLf & vbCrLf & _
"When unprotected, you can copy/paste from other text, WORD, HTML or EXCEL files." & vbCrLf & _
"All Paste operations will implicitly be executed as PasteSpecial/Values", _
vbOKOnly, "Paste"
Exit Sub
End If
' silently do a PasteSpecial/Values
On Error GoTo TryExcel
' try to paste text
ActiveSheet.PasteSpecial Format:="Text", Link:=False, DisplayAsIcon:=False
Exit Sub
TryExcel:
On Error GoTo DoesntWork
Selection.PasteSpecial xlPasteValues
Exit Sub
DoesntWork:
MsgBox "Sorry - wrong format for pasting", vbExclamation + vbOKOnly, "PasteSpecial ..."
End Sub
我添加这个是因为它表明你必须关心缓冲区中的内容(excel,text,html等)
您需要使用
代码替换TrappedPaste()例程的核心1)将内容粘贴到隐藏的工作表/范围内(您可以使用上面的代码)
2)取消保护目标表
3)在
的条件下逐个单元地将内容移动到目标范围4)目标细胞满足没有锁定,验证或类似的条件
5)重新保护目标表
6)清空隐藏的工作表/范围
请注意,使用这样的构造,用户将无法使用UNDO函数!
希望有所帮助 - 祝你好运MikeD