我有一张Excel表格,其中D列(第4列)是每行有2个选项的下拉列表:
当我点击“否”时,我会弹出一个Userform,其中包含一个简单的"文本区域"要求输入一个值和一个"提交按钮"验证。
当"提交按钮"单击,我想要来自"文本区域的值#34;要在右边的单元格中实现:offset(0,1)。
示例:D5:"否" - > "在Userform"中输入5 - > E5:" 5"
到目前为止,这是我的代码:
工作表:
Private Sub Worksheet_Change(ByVal Target As Range)
If ActiveCell.Column = 4 Then
If ActiveCell.Value = "no" Then
UserForm1.Show
End If
End If
End Sub
UserForm:
Private Sub CommandButton1_Click()
ActiveCell.Offset(0, 1).Value = TextBox1.Value
UserForm1.Hide
End Sub
如果我将UserForm1.Hide放在ActiveCell之前,它会按照我想要的方式执行,但UserForm不会关闭。 如果我取出ActiveCell,UserForm会关闭,但我似乎无法同时使用它们。
答案 0 :(得分:1)
您正在更改Worksheet_Change处理程序中的单元格,这意味着如果您没有用于阻止UI的表单,您很快就会破坏调用堆栈并遇到“Out of堆栈空间“错误,也称为... 堆栈溢出。
您需要阻止Worksheet_Change
处理程序以递归方式调用自身。
这可以通过在进行更改之前关闭Application.EnableEvents
并在之后切换回来来完成:
Application.EnableEvents = False
ActiveCell.Offset(0, 1).Value = TextBox1.Value
Application.EnableEvents = True
现在,看看问题是什么?表单如何知道它是从Worksheet_Change
处理程序调用的,因此它需要切换Application.EnableEvents
? 不知道 - 现在,假设它。
这是一个问题,只是因为表单正在运行show 。翻转周围的东西,并使表单保持尽可能愚蠢,并使Worksheet_Change
处理程序负责使表单更改和切换Application.EnableEvents
状态:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 4 And Not IsError(Target.Value) Then
If Target.Value = "no" Then
With New UserForm1
.Show
If .Proceed Then
Application.EnableEvents = False
Target.Offset(0, 1).Value = .Contents
Application.EnableEvents = True
End If
End With
End If
End If
End Sub
有几件事:
Target
- 使用 而不是ActiveCell
。#N/A
或任何其他单元格错误值,则代码会爆炸。使用IsError
验证是否可以安全地将单元格的值与任何内容进行比较。Proceed
和Contents
属性,不允许自毁。Contents
是如何填充的 - 这是表单的关注点。那么表单的代码隐藏现在会是什么样的呢?
Option Explicit
Private mProceed As Boolean
Private mContents As String
Public Property Get Proceed() As Boolean
Proceed = mProceed
End Property
Public Property Get Contents() As String
Contents = mContents
End Property
Private Sub TextBox1_Change()
mContents = TextBox1.value
End Sub
Private Sub CommandButton1_Click()
mProceed = True
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
Me.Hide
End If
End Sub
现在所有表单都是收集数据,并将其公开给调用代码看:它不知道或不关心任何ActiveCell
或工作表 - 它收集数据,并为调用公开它代码看。 没有更多,没有更少。