2013-11-23 38 views
2

好奇,如果有人有解决这个问题。下面是我的代码,我认为它工作正常。我们已经使用了很长时间,有人向我指出他们一直在做的事情,这会导致脚本错误。Excel VB错误Application.Undo&ActiveSheet.Protect

该代码的功能是防止某人一次更新多个单元格。如果有人复制一大块数据,并粘贴到Excel中时占用多行或多列,例如应对电子邮件并将其粘贴到电子表格中,则会收到一个弹出式警报,指出不会更改多个单元格在一次,然后它将撤消粘贴。这部分工作很好。

某人正在做什么导致错误,他们会选择一个单元格,并在单元格右下角有一个正方形,您可以点击并拖动以填满或者覆盖,他们会选择并填补下来。如果只填充一个单元格,则不存在问题。问题是当他们对两个或更多个单元执行此操作时,即发生错误时。更具体地说,就是Application.Undo

所以这个问题真的不是线Application.Undo,它实际上是电子表格被锁定。如果我想删除表示ActiveSheet.UnprotectActiveSheet.Protect的行,那么代码工作正常。不过,我确实希望它受到保护。还有更多的代码,然后我在这里,但这只是它的一个片段,我确实格式正确,所以正确的单元格被锁定,其他单元格不是。你应该能够把代码粘贴到一个新的电子表格中,它可以工作,所以你可以看到我在说什么,但是,确保你先解锁一些单元格,以便编辑它们。一旦你这样做了,看到错误,请将Protect/unprotect行删除以再次尝试,并且代码无任何问题。

请让我知道如果有人有解决方案,所以我仍然可以保持电子表格的保护,并感谢您的帮助!

Private Sub Worksheet_Change(ByVal Target As Range) 

    Application.EnableEvents = False 
    ActiveSheet.Unprotect 


    Dim vClear As Variant 
    Dim vData As Variant 
    Dim lFirstRow As Long 
    Dim lLastRow As Long 

    'This prevents more than one cell from being changed at once. 
    'If more than one cell is changed then validation checks will not work. 
    If Target.Cells.Count > 1 Then 
     vData = Target.Formula 
     For Each vClear In vData 
      If vClear <> "" Then 'If data is only deleted then more than one cell can be changed. 
       MsgBox "Change only one cell at a time", , "Too Many Changes!" 
        Application.Undo 
        Exit For 
      Else 
       'If data is deleted this will check to see what columns are being deleted. 
       'Deleting certain columns will also allow for the automatic deletion of other columns not selected. 
       If vClear = "" Then 

        'If the target includes columns D, it will also clear columns M & N. 
        If Not Intersect(Target, Columns("D")) Is Nothing Then 
         'Gets the first row in the target range. 
         lFirstRow = Target.Rows(1).Row 
         'Gets the last row in the target range. 
         lLastRow = lFirstRow + Target.Rows.Count - 1 
         'Clears the contents of corresponding rows in column M & N. 
         ActiveSheet.Range(Cells(lFirstRow, 13), Cells(lLastRow, 13)).ClearContents 
         ActiveSheet.Range(Cells(lFirstRow, 14), Cells(lLastRow, 14)).ClearContents 
        End If 

        'If the target includes columns G, it will also clear columns I & K & N. 
        If Not Intersect(Target, Columns("G")) Is Nothing Then 
         'Gets the first row in the target range. 
         lFirstRow = Target.Rows(1).Row 
         'Gets the last row in the target range. 
         lLastRow = lFirstRow + Target.Rows.Count - 1 
         'Clears the contents of corresponding rows in column I & K & N. 
         ActiveSheet.Range(Cells(lFirstRow, 9), Cells(lLastRow, 9)).ClearContents 
         ActiveSheet.Range(Cells(lFirstRow, 11), Cells(lLastRow, 11)).ClearContents 
         ActiveSheet.Range(Cells(lFirstRow, 14), Cells(lLastRow, 14)).ClearContents 
        End If 

        'If the target includes columns H, it will also clear columns I & K. 
        If Not Intersect(Target, Columns("H")) Is Nothing Then 
         'Gets the first row in the target range. 
         lFirstRow = Target.Rows(1).Row 
         'Gets the last row in the target range. 
         lLastRow = lFirstRow + Target.Rows.Count - 1 
         'Clears the contents of corresponding rows in column I & K. 
         ActiveSheet.Range(Cells(lFirstRow, 9), Cells(lLastRow, 9)).ClearContents 
         ActiveSheet.Range(Cells(lFirstRow, 11), Cells(lLastRow, 11)).ClearContents 
        End If 

        'If the target includes column J, it will also clear column K. 
        If Not Intersect(Target, Columns("J")) Is Nothing Then 
         'Gets the first row in the target range. 
         lFirstRow = Target.Rows(1).Row 
         'Gets the last row in the target range. 
         lLastRow = lFirstRow + Target.Rows.Count - 1 
         'Clears the contents of corresponding rows in column K. 
         ActiveSheet.Range(Cells(lFirstRow, 11), Cells(lLastRow, 11)).ClearContents 
        End If 

       End If 
      End If 
     Next 
     End If 

    ActiveSheet.Protect 

    Application.EnableEvents = True 

    End Sub 


    Private Sub Worksheet_SelectionChange(ByVal Target As Range) 

Application.EnableEvents = False 
ActiveSheet.Unprotect 

Dim iFirstCol As Integer 
Dim iLastCol As Integer 
Dim iFirstRow As Integer 
Dim iLastRow As Integer 
Dim iColor As Integer 

'''Only adjust the below numbers to fit your desired results.''' 
iFirstCol = 1 'Change this number to the number of the first column that needs to be highlighted. Column A = 1. 
iLastCol = 15 'Change this number to the number of the last column that needs to be highlighted. Column A = 1. 
iFirstRow = 7 'Change this number to the number of the first row that needs to be highlighted. 
iLastRow = 500 'Change this number to the number of the last row that needs to be highlighted. 
iColor = 20 'Change this number to use a different highlight color. 
'''End of changes, do not change anything else.''' 


If Target.Count = 1 Then 
'The row highlight will only be applied if the selected range is within this if statement criteria. 
If Target.Row > iFirstRow - 1 And Target.Row < iLastRow + 1 And Target.Column > iFirstCol - 1 And Target.Column < iLastCol + 1 Then 

    'Resets the color within the full range when cell selection changed. 
    ActiveSheet.Range(ActiveSheet.Cells(iFirstRow, iFirstCol), ActiveSheet.Cells(iLastRow, iLastCol)).Interior.Color = xlNone 

    'Applies the colors to the row. 
    For counter = iFirstCol To iLastCol 
     With ActiveSheet.Cells(Target.Row, iFirstCol).Interior 
      .ColorIndex = iColor 
      .Pattern = xlSolid 
     End With 
     iFirstCol = iFirstCol + 1 
    Next counter 

End If 
End If 

ActiveSheet.Protect 
Application.EnableEvents = True 

End Sub 
+0

拖动允许用户吗?如果拖动导致此问题,为什么不禁用单元格拖动? –

+0

是的,如果他们拖动到一个单元格以允许单个更改,但它并不是真的需要,但如果用户更喜欢使用它,则可以。如果没有其他的选择,我可以禁用它,尽管我不确定你能否确认它,但是有点想到同样的事情,并且想到查找可能的代码来禁用它。我宁愿这是最后的手段。如果你应该知道如何禁用它,如果我应该走这条路线,你可以发布代码吗?这将是我的最后一个选择。谢谢 – Chris

+0

'应用程序。CellDragAndDrop = False',并且不确定为什么当有一个简单的可用解决方案时,你试图寻找一个困难的解决方案。你的整个想法更多的是允许用户单独进入到工作表上。不是吗? –

回答

0

好吧,我现在觉得有点愚蠢。我找出了这个问题。不敢相信这花了很长时间。由于我的代码的后半部分,电子表格受到保护,我所在的部分突出显示了它所在的行。我必须将Target.Count部分移动到该子标题的顶部。因此,在Private Sub Worksheet_SelectionChange(ByVal Target As Range)之前的所有内容都没有改变,但之后我不得不修改位置以检查选中的单元格的数量,以防止电子表格受到保护。显然,当你拖下来时,就像是单独地选择单元格,并且同时选择所有单元格。这就是为什么当我在电子表格中粘贴数据时,代码无误地工作,因为它只读取一次SelectionChange类别,但是如果我拖动它,则每次拖动时都会读取此部分。我以前不知道,但我想这一定是如何工作的。

所以我只是在SelectionChange部分修改了代码,看起来像这样,它现在可以工作。也感谢所有为我留下评论和建议的人。

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 

If Target.Cells.CountLarge = 1 Then 

Application.EnableEvents = False 
ActiveSheet.Unprotect 

Dim iFirstCol As Integer 
Dim iLastCol As Integer 
Dim iFirstRow As Integer 
Dim iLastRow As Integer 
Dim iColor As Integer 

'''Only adjust the below numbers to fit your desired results.''' 
iFirstCol = 1 'Change this number to the number of the first column that needs to be highlighted. Column A = 1. 
iLastCol = 15 'Change this number to the number of the last column that needs to be highlighted. Column A = 1. 
iFirstRow = 7 'Change this number to the number of the first row that needs to be highlighted. 
iLastRow = 500 'Change this number to the number of the last row that needs to be highlighted. 
iColor = 20 'Change this number to use a different highlight color. 
'''End of changes, do not change anything else.''' 


'The row highlight will only be applied if the selected range is within this if statement criteria. 
If Target.Row > iFirstRow - 1 And Target.Row < iLastRow + 1 And Target.Column > iFirstCol - 1 And Target.Column < iLastCol + 1 Then 

    'Resets the color within the full range when cell selection changed. 
    ActiveSheet.Range(ActiveSheet.Cells(iFirstRow, iFirstCol), ActiveSheet.Cells(iLastRow, iLastCol)).Interior.Color = xlNone 

    'Applies the colors to the row. 
    For counter = iFirstCol To iLastCol 
     With ActiveSheet.Cells(Target.Row, iFirstCol).Interior 
      .ColorIndex = iColor 
      .Pattern = xlSolid 
     End With 
     iFirstCol = iFirstCol + 1 
    Next counter 

End If 


ActiveSheet.Protect 
Application.EnableEvents = True 

End If 

End Sub