【问题标题】:Excel VBA Macro Help - Mandatory CellsExcel VBA 宏帮助 - 必填单元格
【发布时间】:2020-03-13 01:42:40
【问题描述】:

新用户,被友好的团队成员推荐到您的有用网站。

问题:试图强制 excel 中的用户在填写 I-L 列中的单元格之前先填写列(O 列)中的单元格。问题在于,并非列中的每个单元格都需要填写。我发现了一个有一定帮助的 VBA 代码,但问题是如果在只有一个文本之前填写 O 列,仍然会出现弹出窗口I-L 列中的单元格(因此除非填写该行中的所有 4 个单元格,否则会发生错误)。如前所述,目标是(例如)在填写 I、J、K 或 L264 列中的任何单元格之前先填写 O264。

进一步加剧了这个问题,我需要将它应用到多行,相信这是范围适合的地方。但是,在 excel 中使用范围线并不能像我尝试的那样工作。

代码如下:

Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("I:L")) Is Nothing Then
If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
If Target.Offset(, -1).Value = "" Then
MsgBox "You must first enter feedback in column ""O"""
Target.Value = ""
Target.Offset(, -1).Select
End If
End If
End Sub

【问题讨论】:

  • 您应该以简单明了的格式发布问题。 (我猜你希望任何人打开此工作表来首先填充 O 列,而不是将任何内容放在同一行的其他列中,这是真的吗?)永远不要让其他人随时猜测真正的问题。只是直接强调问题。
  • 正确,这是我的问题陈述的第一行?试图强制 excel 中的用户在填写 I-L 列中的单元格之前先填写列(O 列)中的单元格。

标签: excel vba


【解决方案1】:

在这种情况下,您可能需要为用户提供更多帮助。你可以通过隐藏依赖单元格、锁定它们、将它们变灰等来做到这一点。我的感觉是,每当用户以错误的顺序输入数据时显示一个消息框有点太被动了。

在下面的示例中,目标单元格被锁定并显示为灰色,直到在“O”列中输入内容。如果您有多个目标行,您还需要创建一个目标行列表。

在相应工作表后面的代码中,下面的框架代码应该可以帮助您入门。我已经包含了几个帮助函数,以使您的代码更清晰:

Option Explicit

Private Const SHEET_PASSWORD As String = "xyz" 'whatever password you choose.
Private Const TARGET_ROWS As String = "2,4,6" 'your target rows, separated by commas.
Private Const TARGET_COLUMN As String = "O"
Private Const DEPENDENT_COLUMNS As String = "I:L"

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rng As Range, cell As Range

    Set rng = Intersect(Target, Me.Columns(TARGET_COLUMN))
    'Exit routine if we're not in the target column.
    If rng Is Nothing Then Exit Sub

    'Process the target column cells.
    For Each cell In rng.Cells
        If IsTargetRow(cell.Row) Then
            SetDependentStates cell
        End If
    Next
End Sub

Private Sub SetDependentStates(cell As Range)
    Dim DependentRange As Range

    'Define the Dependent range based on passed cell row.
    Set DependentRange = Intersect( _
        cell.EntireRow, _
        Me.Range(DEPENDENT_COLUMNS) _
    )

    'Lock/unlock and paint Dependent rows, based on
    'contents of passed cell.
    Application.EnableEvents = False 'prevent capture of change event.
    Me.Unprotect SHEET_PASSWORD
    With DependentRange.Cells
        If Len(cell.Value) = 0 Then
            .ClearContents
            .Locked = True
            With .Interior
                .Pattern = xlSolid
                .PatternColorIndex = xlAutomatic
                .ThemeColor = xlThemeColorDark1
                .TintAndShade = -0.249977111117893
                .PatternTintAndShade = 0
            End With
        Else
            .Locked = False
            With .Interior
                .Pattern = xlNone
                .TintAndShade = 0
                .PatternTintAndShade = 0
            End With
        End If
    End With
    Me.Protect SHEET_PASSWORD
    Me.EnableSelection = xlUnlockedCells
    Application.EnableEvents = True
End Sub

Private Function IsTargetRow(rowNum As Long) As Boolean
    Dim v As Variant

    'Tests if the pass row number is in the target row list.
    For Each v In Split(TARGET_ROWS, ",")
        If CLng(v) = rowNum Then
            IsTargetRow = True
            Exit Function
        End If
    Next
End Function

Public Sub InitialiseDependentStates()
    Dim v As Variant
    Dim cell As Range

    'Define your unlocked cells.
    'This is a simple example, adjust as you wish.
    With Me
        .Unprotect SHEET_PASSWORD
        .Cells.Locked = False
        .Protect SHEET_PASSWORD
        .EnableSelection = xlUnlockedCells
    End With

    For Each v In Split(TARGET_ROWS, ",")
        Set cell = Me.Range(TARGET_COLUMN & v)
        SetDependentStates cell
    Next
End Sub

您可能希望在打开工作簿时初始化相关状态。在工作簿后面的代码中执行此操作:

Private Sub Workbook_Open()
    Sheet1.InitialiseDependentStates 'use whichever sheet you're using.
End Sub

【讨论】:

  • 非常感谢安比!这行得通!您能否查看我的评论以了解我在类似但不相同的问题上遇到的另一个问题?