【问题标题】:Transfer value from cell to ComboBox avoiding triggering said ComboBox change将值从单元格传输到 ComboBox 避免触发所述 ComboBox 更改
【发布时间】:2021-07-28 10:39:50
【问题描述】:

基本上这是我的问题。我的组合框会在更改时影响其他组合框,这一切都很完美,但我需要能够在单独的 Excel 文件打开时将值从单元格返回到组合框,就像我现在写的一样 - 它触发更改组合框和影响现在将是空的其他组合框,这很糟糕。我基本上需要的是在再次打开保存的工作簿后维护 ComboBoxes 中的选定项目。

我将它从 ComboBox 写入 Sheet 的方式:

'Paste value to sheet
Worksheets("Machine Specification").Range("C4").Value = UserForm_TVPM.Language_ComboBox.Text

以及我将其从工作表加载回 ComboBox 的方式:

UserForm_TVPM.Language_ComboBox.Value = Worksheets("Machine Specification").Range("C4").Value

卸载和显示用户窗体时也会出现同样的问题。因为我必须填充现在空的 ComboBoxes。

有人可以帮我解决这个问题吗?

附言

我有一个模块,其中包含许多具有加载功能的子例程,例如在原始帖子中为每个用户窗体提供的功能。这就是我从单元格到组合框的值。而且我有一个用户窗体初始化子例程,该子例程主要具有用于所述用户窗体中所有组合框的 additem 函数。稍后,当用户使用文件时 - 一切都很好,因为我可以隐藏用户表单而不会丢失其组合框中的日期,但是在以任何方式卸载用户表单时(天气关闭工作簿或只是转到另一个用户表单卸载前一个)数据将丢失,并且在用户窗体的下一次初始化时将重新加载。因为我有组合框,这些组合框的项目取决于其他组合框中的选择 - 在这种情况下,我会丢失用户窗体和工作表中的计算值。

我的理解是它的发生是因为在加载用户表单时,它都是空白的,并且在加载值时它会触发每个组合框更改事件,导致一些相关的组合框项目被清除重新计算以提供正确的选项范围可供选择,由于将组合框值传输到工作表,这反过来又删除了工作表中的相关组合框值。所以我通常需要维护所有的组合框值,因为它们在加载用户表单时被发送到工作表,就像我要隐藏用户表单然后再次显示它一样。 :)

【问题讨论】:

  • 您尝试过 Application.EnableEvents 吗? docs.microsoft.com/en-us/office/vba/api/…
  • 是的,我不确定我是否正确使用了它。我基本上在 change sub 中禁用了它,并且在所有功能启用它之后它没有任何效果
  • @АлексейР 不知何故 Application.EnableEvents 不会禁用来自用户表单及其控件的事件,而只会禁用来自工作表的事件。
  • 在这种情况下,我根本不理解它的概念。这不仅仅是关于保存......在卸载和显示现在空白的用户表单时也是如此,现在必须使用 Worksheet 中的值填充

标签: excel vba combobox


【解决方案1】:

您可以将 ComboBox 的 ControlSource 设置为您的单元格。因此它始终显示与单元格相同的值,您无需将其从 ComboBox 粘贴到单元格,反之亦然。

UserForm_TVPM.Language_ComboBox.ControlSource = "'Machine Specification'!C4"

或者在组合框的属性窗口中设置ControlSource

我唯一的另一个想法是有一个全局变量作为开关。

Option Explicit

Private SkipChangeEvent As Boolean

Private Sub Language_ComboBox_Change()
    If SkipChangeEvent Then Exit Sub
    
    'your code here
End Sub

Public Sub Example()
    SkipChangeEvent = True   'disable change event
    UserForm_TVPM.Language_ComboBox.Value = Worksheets("Machine Specification").Range("C4").Value
    SkipChangeEvent = False  'enable change event
End Sub

但我更喜欢第一种解决方案。


根据 cmets 我提出另一种解决方案:

在您想使用的每个用户表单中,放在最前面:

Option Explicit

Private IsInitialized As Boolean 'this is false by default and false after every unload too.

这必须是私有的,并且每个用户表单都需要自己的变量声明,否则它不适用于多个用户表单。

在你的变更事件中做

Private Sub Language_ComboBox_Change()
    If Not IsInitialized Then Exit Sub ' events don't run until you tell the userform IsInitialized is true.
    
    'your code here
End Sub

如果您有代码来初始化组合框的值,请在初始化完成后放置以下内容:

IsInitialized = True

【讨论】:

  • ControlSource 是我尝试的第一件事,但它不适用于互连的 ComboBoxes,其中一个 ComboBox 项目列表是从另一个 ComboBox 项目列表计算并动态更新工作表。就结果而言,它基本上是最不受欢迎的解决方案
  • @Eduards 那么你只能尝试我建议的第二种解决方案,在更改值的同时关闭事件。
  • 好的。我对将选项显式和私有布尔值放在哪里有点困惑,因为显然我的用户窗体包含多个 ComboBox
  • Option Explicit 是强制 VBA 在使用前声明 all 变量。这是一个非常好的做法,您应该将此行作为 every 模块和代码的第一行(请参阅here 并对其进行一些研究以获取更多信息)。然后Private SkipChangeEvent As BooleanOption Explicit 的正下方,在任何SubFunction 之前。这是声明一个全局变量,可以在您声明它的模块/用户表单的每个SubFunction 中使用(对全局变量进行一些研究)。
  • 然后在加载用户表单时使用 F8 逐步检查您的代码,以查看何时触发事件。所以你可以看到哪一行被执行。您需要进行一些调试以找出触发它们的原因。
猜你喜欢
  • 2015-03-13
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2017-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多