2013-04-18 2 views
1

사용자가 변경 한 특정 필드를 중지하려고합니다. 그러나 그 필드가 어떤 열에 포함될 것인지, 처음에 포함될 값만 알 수 없습니다.VBA가 초기 셀 값만 참조하여 셀 값을 변경하는 것을 방지합니다.

나의 현재 접근이있다 :

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)  
    Dim columnHeaderRange As Range 
Set shtData = Worksheets("Data")  
Set columnHeaderRange = Union(shtData.Columns(ColumnNumber(5, "example1")), _ 
         shtData.Columns(ColumnNumber(5, "example2")), _ 
         shtData.Columns(ColumnNumber(5, "example3")))  
Set columnHeaderRange = Application.Intersect(Target, columnHeaderRange)  
    ElseIf Not (columnHeaderRange Is Nothing) Then  
    With Application 
     .EnableEvents = False 
     .Undo 
     MsgBox "Change is not possible.", 16 
     .EnableEvents = True 
    End With   
Else 
    Exit Sub 
End If 

상기 코드 내 ColumnNumber 함수는 변수로서 로우 및 필드의 값을 취하고 열 번호를 반환한다. 고정 필드 값을 사용하고 있기 때문에 필드가 변경되어 내 공용 호출이 실패하면이 작업은 실패합니다.

사용자가 셀 값을 변경하려고했지만이 셀의 실제 값이 변경되기 전에이 코드를 실행하는 방법이 있습니까? 또는 누구든지 더 나은 접근법을 제안 할 수 있습니까?

+0

현재 시트에서 확인해야 할 값/필드 목록이 있고 변경되지 않았는지 확인하십시오. –

+0

예 값 목록이 있습니다 – db579

+0

샘플을 볼 수 있습니까? 또한 코드가 여러 시트에 대해 작동하도록 하시겠습니까? –

답변

2

을 잠에 다음> 형식 세포가> 보호> 상자을 선택합니다 을 마우스 오른쪽 버튼으로 클릭하여 개별 셀, 또는 범위의 보호 잠금을 설정

List이라는 시트를 만들어 값을 저장합니다. 이 방법의 가장 중요한 부분은 목록에서 항목을 추가/삭제할 때마다 코드를 수정할 필요가 없다는 것입니다.

페이지의 스크린 샷

enter image description here

그리고의는이 시트 코드 지역

Dim rngList As Range, aCell As Range 
Dim RowAr() As Long 

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim i As Long 

    On Error GoTo Whoa 

    Application.EnableEvents = False 

    For Each aCell In Target 
     If aCell.Row = 5 Then 
      With Application 
       For i = LBound(RowAr) To UBound(RowAr) 
        If RowAr(i) = aCell.Column Then 
         MsgBox "Change is not possible." 
         .Undo 
         GoTo Letscontinue 
        End If 
       Next 
      End With 
     End If 
    Next 

Letscontinue: 
    Application.EnableEvents = True 
    Exit Sub 
Whoa: 
    MsgBox Err.Description 
    Resume Letscontinue 
End Sub 

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    Dim wsList As Worksheet 
    Dim n As Long, lrow As Long 

    Set wsList = ThisWorkbook.Sheets("list") 

    With wsList 
     lrow = .Range("A" & .Rows.Count).End(xlUp).Row 
     Set rngList = .Range("A1:A" & lrow) 
    End With 

    n = 0 
    ReDim RowAr(n) 

    For Each aCell In Range("5:5") 
     If Len(Trim(aCell.Value)) <> 0 Then 
      If Application.WorksheetFunction.CountIf(rngList, aCell.Value) > 0 Then 
       n = n + 1 
       ReDim Preserve RowAr(n) 
       RowAr(n) = aCell.Column 
       Debug.Print aCell.Column 
      End If 
     End If 
    Next 
End Sub 

,857에이 코드를 붙여 주 시트

enter image description here

라고하자

enter image description here

예 2

액션에서3210

코드는이 하드 코딩 된 목록을 사용합니다.

Option Explicit 

Dim RowAr() As Long, aCell As Range 

Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
    Dim MyList As String, MyAr() As String 
    Dim n As Long, i As Long 

    '~~> This is the list 
    MyList = "Header 1,Header 2" 
    MyAr = Split(MyList, ",") 

    n = 0 
    ReDim RowAr(n) 

    For Each aCell In Range("5:5") 
     If Len(Trim(aCell.Value)) <> 0 Then 
      For i = LBound(MyAr) To UBound(MyAr) 
       If aCell.Value = MyAr(i) Then 
        n = n + 1 
        ReDim Preserve RowAr(n) 
        RowAr(n) = aCell.Column 
       End If 
      Next 
     End If 
    Next 
End Sub 

Private Sub Worksheet_Change(ByVal Target As Range) 
    Dim i As Long 

    On Error GoTo Whoa 

    Application.EnableEvents = False 

    For Each aCell In Target 
     If aCell.Row = 5 Then 
      With Application 
       For i = LBound(RowAr) To UBound(RowAr) 
        If RowAr(i) = aCell.Column Then 
         MsgBox "Change is not possible." 
         .Undo 
         GoTo Letscontinue 
        End If 
       Next 
      End With 
     End If 
    Next 

Letscontinue: 
    Application.EnableEvents = True 
    Exit Sub 
Whoa: 
    MsgBox Err.Description 
    Resume Letscontinue 
End Sub 
1

수식을 셀의 사용자에게 표시하지 않으려면 변경하지 않을 수도 있습니다. 숨김으로 표시 할 수도 있습니다.

VBA 솔루션

당신은 2 단계 스크립트 수 :

  1. 변경 후에 참조 (숨겨진) 시트에 시트의 사본을 저장합니다 첫 번째 단계는 그 제작된다 시트 및 2 단계 후에도 실행됩니다.

  2. Target 범위에 워크 시트 사본의 대상 범위에있는 모든 셀의 행/열 좌표를 조회하여 원래 값 중 하나가 포함되었는지 확인하는 Worksheet_Change (대상) 스크립트를 작성하십시오. 특수 값이 포함 된 경우 시트 복사본에서 해당 값을 다시 가져옵니다. 이것은 크게 당신이 이미 가지고있는 스크립트 ...

워크 시트 보호 솔루션

당신이 (시트 보호>검토) 워크 시트 보호 기능을 사용하여 고려 가지고 있습니다 만 그 세포의 보호 잠금을 해제 사용자는 변경할 수 있습니까? 그런 식으로 코딩을하지 않아도 컨트롤을 유지할 수 있습니다. 이미이 셀을 이미 선행으로 사용할 수있는 논리가 있습니다. 또는 스크립트로 각 변경 한 후에 VBA 스크립트를 실행하여 해당 값이있는 모든 셀을 조회하고 잠긴 속성 = True을 설정 한 다음 워크 시트 보호를 다시 적용합니다.

수동으로 내 의견에

예 1

을 추가
+0

나는이 방법으로 시도 할 때 사용자 메시지를 표시 할 수 없다고 생각합니다. 셀을 변경하거나 열 삽입과 같은 것을 허용합니까? – db579

+0

해당 이벤트의 검사도 포함 할 수 있습니다. 일반적으로 시트 및 통합 문서를 보호하고 사용자가 내가 원하는 몇 가지 것을 제외하고는 아무 것도 할 수 없도록합니다. 이러한 예방 메커니즘을 사용하지 않으려면 (사용자가) VBA 스크립트에서 수행 할 수있는 모든 작업을 고려해야합니다. 이는 진정한 악몽이며 전 세계의 모든 행운을 빕니다. –

+0

다음과 같이 : 사용자가 열을 삽입하고 시트의 잠금을 해제 한 다음 다시 잠그기위한 점검을 포함합니까? – db579

관련 문제