【问题标题】:How to restrict value entry/input in a cell based on another cell value in excel?如何根据excel中的另一个单元格值限制单元格中的值输入/输入?
【发布时间】:2021-10-15 13:54:52
【问题描述】:

我有这样的事情

A B
Q? Y or N
Number number or zero

我想做的是:

如果 B1 = “Y”,则让用户在 B2 中输入一个数字。 如果 B1 = “N”,则将 B2 中的值更改为零,并且不允许用户在 B2 中输入任何数字,除非用户将 B1 的值更改回“Y”。 基本上,当且仅当 B1=”Y” 时,才允许用户在 B2 中输入数字。

到目前为止我做了什么:

  1. 数据 -> 数据验证 -> 自定义,这是我编写的公式

=OR(AND(B1="Y",ISNUMBER(B2)),AND(B1="N",B2=0))

此解决方案并不理想,因为当 B1 被选为 N 时,它不会将 B2 更改为零。此外,当 B1 更改为 Y 时,它不会强制用户在 B2 中输入新值。

  1. 我已尝试使用 VBA 解决问题。这是我写的代码
ActiveSheet.Unprotect
Range("B2").Locked = False
If Target.Address = "$B$1" Then
    Dim myValue As Variant
    If Range("B1").Value = "N" Then
        Range("B2").Value = 0
    Else
        myValue = InputBox("Give me some input")
        Range("B2").Value = myValue
    
    End If
    
End If
Range("B2").Locked = True
ActiveSheet.Protect
End Sub

此解决方案工作正常,只是当代码尝试再次锁定 B2 以防止用户直接在 B2 单元格中输入数字(不使用输入框)​​时出现错误。另外,我需要添加一些代码来将数据输入限制为数字。

Error when changing the B1

知道如何解决这个问题吗?

PS:我在 SJR 的帮助下成功解决了上述代码

Private Sub Worksheet_Change(ByVal Target As Range)

Worksheets("Sheet1").Unprotect

If Target.Address = "$B$1" Then
    Dim myValue As Variant
    If Range("B1").Value = "N" Then
        Range("B2").Value = 0
    Else
    myValue = "no"
        Do Until IsNumeric(myValue)
                myValue = InputBox("Enter a number > 0")
        Loop
        Range("B2").Value = myValue
    End If
    
End If
Worksheets("Sheet1").Protect
End Sub

【问题讨论】:

  • 您不需要锁定或解锁单元格。将 B2 格式设置为锁定,然后您只需要取消保护并保护工作表。然后检查isnumeric(myvalue)

标签: excel vba


【解决方案1】:

使用样式可能会有所帮助。

创建一个名为“InputData”的样式,将locked设置为false(在受保护的选项卡(?)上)并将填充设置为例如黄色以区分输入单元格和其他单元格。

将此样式分配给 B2

为 B2“问题”和 B3“答案”添加工作表名称。

将以下代码粘贴到工作表模块中:

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
If hasName(Target.Cells(1, 1)) Then
    If Target.Cells(1, 1).Name.Name Like "*Question*" Then
       lockUnlockAnswer
    End If
End If
End Sub


Private Sub lockUnlockAnswer()

Me.Unprotect

Application.EnableEvents = False

If Me.Range("Question") = "Y" Then
    With Me.Range("Answer")
        .Style = "InputData"  'this style
        .Value = vbNullString
    End With
Else
    With Me.Range("Answer")
        .Style = "Normal"
        .Value = 0
    End With
End If
    
Application.EnableEvents = True
    
Me.Protect
End Sub


Public Function hasName(ByVal c As Range) As Boolean
On Error Resume Next
hasName = CBool(c.Name.Name <> vbNullString)
If Err = 0 Then hasName = True
Err.Clear
On Error GoTo 0
End Function

每当用户更改工作表上的任何内容时,都会触发 on_change 事件。

如果更改发生在“问题”lockUnlockAnswer 被调用。

如果 Question = "Y",则 Style "InputData" 应用于 B3(= Answer)。单元格是可编辑的!

如果问题 “Y”,则样式“正常”应用于 B3。单元格被锁定并设置为 0。

为防止再次调用 worksheet_change,EnableEvents 设置为 false。

(大概你会有更多应该像这样工作的问题/答案 - 你可以简单地为单元格名称添加一个索引。添加一个参数“index”到 lockUnlockAnswer 并将索引添加到范围名称......然后该例程适用于不同的问题/答案范围)

【讨论】:

  • 我正在按照您的提示使用看起来很有趣的样式。我已尝试遵循您的 cmets 和代码,但收到“运行时错误 1004”错误。我应用了这些更改,但仍然遇到相同的错误 - B1“问题”和 B2“答案”的名称 - 将第二行从 If Not Target.Cells(1, 1).Name Is Nothing Then 更改为 If Not Target.Cells (1, 2).Name Is Nothing 那我很感谢您的反馈。
  • hmm - 你从哪里得到错误?更改If Not Target.Cells(1, 2).Name Is Nothing 绝对不是正确的解决方案,因为通常目标仅包含一个单元格。
  • 我收到了来自If Not Target.Cells(1, 1).Name Is Nothing Then 行的错误。我还将“InputData”样式应用于“答案”单元格。
  • 对不起,我错过了 hasName 功能。我将它添加到上面的代码中。现在它应该可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
  • 2020-10-03
  • 2021-08-02
相关资源
最近更新 更多