首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Excel VBA -通过Worksheet_Change事件调用UserForm后项目重置

Excel VBA -通过Worksheet_Change事件调用UserForm后项目重置
EN

Stack Overflow用户
提问于 2018-12-13 02:02:06
回答 1查看 199关注 0票数 -2

我有一个带有Worksheet_Change事件的电子表格,该事件调用模块中的sub。worksheet_change代码为:

代码语言:javascript
复制
Private Sub Worksheet_Change(ByVal Target As Range)
Dim itemType As String, material As String, size As Variant, rating As Variant, weldType As String
Dim rowNum, i, iMax, j As Double

If Target.Count > 1 Then Exit Sub
Disable_Slowdowns

'....code for other columns which is not triggered....

    If Target.Column = 4 And Target.row > 4 Then
         If Len(Target.Value2) > 0 Then AutoFill_By_PN Target
    End If
Enable_Slowdowns
End Sub

Enable_Slowdowns和Disable_Slowdowns subs的代码,存储在一个模块中:

代码语言:javascript
复制
Sub Disable_Slowdowns()
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
End Sub

Sub Enable_Slowdowns()
    If Application.EnableEvents = False Then Application.EnableEvents = True
    If Application.ScreenUpdating = False Then Application.ScreenUpdating = True
    If Application.Calculation = xlCalculationManual Then Application.Calculation = xlCalculationAutomatic
End Sub

然后,执行这项工作的子模块名为AutoFill_by_PN (一个变量在子模块外部声明,名为selectedPartIndex):

代码语言:javascript
复制
Public selectedPartIndex As Integer

Public Sub AutoFill_By_PN(ByVal rngPN As Range)
Dim vCell As Variant
Dim wb, costingWB As Workbook
Dim strTemp, PN, sName, sPrice, sSize, sType As String
Dim quotePosR, spacePosL, counter, i, k As Integer
Dim priceL, priceR As Variant
Dim dict As Object

Disable_Slowdowns
Set dict = CreateObject("Scripting.Dictionary")
PN = rngPN.Value2
Set costingWB = ActiveWorkbook
Set wb = Workbooks.Open(Filename:="Z:\Shared\Materials\Parts Book\New Parts Book - Official.xlsx", UpdateLinks:=1, ReadOnly:=1)
counter = 0
selectedPartIndex = -1

For Each vCell In wb.Sheets("PARTS BOOK").Range("$F$260:$F$3872")
    With vCell
        If InStr(1, .Value2, PN, vbTextCompare) > 0 Then
            sName = "name" & counter
            sType = "type" & counter
            sPrice = "price" & counter
            sSize = "size" & counter
            dict.Add sName, .Value2
            dict.Add sType, .Offset(, -2).Value2

            quotePosR = InStr(1, .Value2, """", vbTextCompare)
            If quotePosR > 0 Then
                spacePosL = InStrRev(.Value2, " ", quotePosR, vbBinaryCompare)
                strTemp = Evaluate(Replace(Mid(.Value2, spacePosL + 1, quotePosR - spacePosL - 1), "-", "+", compare:=vbTextCompare))
                dict.Add sSize, strTemp
            Else
                dict.Add sSize, ""
            End If

            priceR = .Offset(, 3).Value2
            priceL = .Offset(, 2).Value2
            If IsNumeric(priceL) And IsNumeric(priceR) Then
                If priceL - priceR <= 0 Then
                    dict.Add sPrice, priceR
                Else
                    dict.Add sPrice, priceL
                End If
            ElseIf IsNumeric(priceL) Then
                dict.Add sPrice, priceL
            ElseIf IsNumeric(priceR) Then
                dict.Add sPrice, priceR
            Else
                dict.Add sPrice, ""
            End If
            counter = counter + 1
        End If
    End With
Next vCell
If counter - 1 <= 0 Then
    With rngPN
        .Offset(, 3).Value2 = dict(sName)
        .Offset(, 4).Value2 = dict(sType)
        .Offset(, 6).Value2 = dict(sSize)
        .Offset(, 13).Value2 = dict(sPrice)
    End With
Else
    For i = 0 To counter - 1
        UF_PartSelection.LB_PartList.AddItem dict("name" & i), i
    Next i
    UF_PartSelection.Show
End If

If selectedPartIndex >= 0 Then
    With rngPN
        .Offset(, 3).Value2 = dict("name" & selectedPartIndex)
        .Offset(, 4).Value2 = dict("type" & selectedPartIndex)
        .Offset(, 6).Value2 = dict("size" & selectedPartIndex)
        .Offset(, 13).Value2 = dict("price" & selectedPartIndex)
    End With
End If

Enable_Slowdowns
End Sub

其思想是在单元格中输入零件编号,然后搜索零件手册,并在其他列中填充一些值。重要的是,有时会在多个部件的文本中找到部件号,此时会显示一个用户表单,让用户选择正确的部件。表单正在显示,所有涉及到的代码运行都没有错误,直到最后一行(字面上),当worksheet_change代码到达"End Sub“时-然后我收到一条消息”此操作将重置项目“。

为什么会发生这种情况?下面用户表单的代码(字段已正确填充,所选项目已正确捕获)

代码语言:javascript
复制
Private Sub cmd_ok_Click()
Dim i, indexNo As Integer, vItem As Variant
indexNo = -1
For i = 0 To Me.LB_PartList.ListCount
    If Me.LB_PartList.Selected(i) = True Then indexNo = i
Next i
If indexNo >= 0 Then capture_ListBox_Index indexNo Else capture_ListBox_Index -1
Unload Me
End Sub

以及捕获列表框选择的代码,位于与AutoFill_by_PN子模块相同的模块中:

代码语言:javascript
复制
Public Sub capture_ListBox_Index(indexNo As Integer)
    selectedPartIndex = indexNo
End Sub

任何帮助都是非常感谢的。我似乎无法确定是什么操作特别触发了项目重置-每次在调试模式下单步执行代码时,它都会发生在worksheet_change代码的"End Sub“行上。

编辑:我发现当只有一个匹配的部件号时,代码运行得很好。这让我相信它一定与用户表单代码有关,因为只有当有多个匹配时才会显示用户表单。此外,单元格值都会根据用户在用户表单中选择的部分正确更新,即使我收到“项目必须重置”消息也是如此。非常奇怪。

编辑2:我试着在AutoFill_By_PN子模块中运行这段代码,仍然有同样的问题:

代码语言:javascript
复制
If counter - 1 <= 0 Then
    With rngPN
        .Offset(, 3).Value2 = dict(sName)
        .Offset(, 4).Value2 = dict(sType)
        .Offset(, 6).Value2 = dict(sSize)
        .Offset(, 13).Value2 = dict(sPrice)
    End With
Else
    Dim ui As New UF_PartSelection
    For i = 0 To counter - 1
        ui.LB_PartList.AddItem dict("name" & i), i
        ui.LB_PartList.List(i, 1) = FormatCurrency(dict("price" & i), 2)
    Next i
    ui.Show
End If

编辑3:感谢您的评论。在重写上面所示的"else“块中的代码之后,问题就解决了!代码如下:

代码语言:javascript
复制
Else
    Dim ui As UF_PartSelection
    Set ui = New UF_PartSelection
    For i = 0 To counter - 1
        ui.LB_PartList.AddItem dict("name" & i), i
        ui.LB_PartList.List(i, 1) = FormatCurrency(dict("price" & i), 2)
    Next i
    ui.Show
End If
EN

回答 1

Stack Overflow用户

发布于 2018-12-13 03:43:58

我已经解决了这个问题,尽管我一点也不理解它。由于某些原因,当worksheet_change子进程终止时,打开VBE窗口会导致项目重置。关闭VBE窗口可消除此问题。有人知道为什么吗?我以前从来没有遇到过这样的事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53748850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档