用户窗体和范围(UserForm and Range)

2019-10-30 11:54发布

我有一个Excel片与柱d(第4列)是用于与2个选择每一行的下拉列表:

  • 没有

当我点击不,我有一个窗体弹出一个简单的“文本区”要求输入一个值和一个“提交按钮”来验证。

当“提交按钮”被点击时,我想从“文本区”,以实现进入细胞,以权值:(0,1)所抵消。

例如:D5: “否” - > “进入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

用户窗体:

Private Sub CommandButton1_Click()
    ActiveCell.Offset(0, 1).Value = TextBox1.Value
    UserForm1.Hide
End Sub

如果我把UserForm1.Hide的ActiveCell之前,我想要做什么,但用户窗体不会关闭。 如果我参加了ActiveCell用户窗体关闭,但我似乎无法一下子使双方的工作。

Answer 1:

你改变细胞的Worksheet_Change处理程序 ,如果你没有一个形式阻止用户界面,这意味着,你会迅速吹向调用堆栈,并运行到一个“堆栈空间不足”的错误,也被称为。 .. 堆栈溢出

您需要防止您的Worksheet_Change处理器从自称递归。

而这可以通过关闭来完成Application.EnableEvents你做出改变之前,并切换回上算账:

Application.EnableEvents = False
ActiveCell.Offset(0, 1).Value = TextBox1.Value
Application.EnableEvents = True

现在,看到的问题是什么? 怎样的形式知道它正在从一个调用Worksheet_Change处理程序等,它需要切换Application.EnableEvents ? 它知道-而现在,它的假设它。

这是一个问题,只是因为形式正在运行的表演 。 翻转周围的事物,并留下愚蠢,因为它都不可能是这样的形式,使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

几件事情:

  1. 触发事件的细胞是Target - 使用ActiveCell
  2. 如果该单元格的值是#N/A或任何其它细胞误差值,您的代码鼓起。 使用IsError以验证它是否是安全的第一比较单元的任何东西的价值。
  3. 窗体现在需要ProceedContents属性,不能被允许自毁。
  4. 调用代码不关心任何文本框:它不知道如何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或工作表-它收集数据,并公开它的调用代码看。 仅此而已,无所不及



文章来源: UserForm and Range