在Access中以连续形式自定义组合框的行源

时间:2008-09-17 18:45:17

标签: ms-access

我一直在搜索,似乎这是MS Access中的一个限制,所以我想知道其他人在这个难题中找到了哪些创意解决方案。

如果您有一个连续的表单,并且您希望某个字段是特定于该行的选项的组合框,则Access无法提供;组合框行源仅在表单的开头查询一次,因此显示表单其余部分的错误选项。

当然,我们所有尝试的下一步是使用onCurrent事件来重新查询组合框,这实际上限制了给定行的选项。但是,在这一点上,Access变得疯狂,并且为每一行重新查询所有组合框,结果通常是在其他行中消失和重新出现的选项,这取决于他们是否已选择一个对当前记录的行源有效的选项。

我找到的唯一解决方案就是始终列出所有可用选项。那里有创意答案吗?

编辑另外,我应该注意组合框的原因是将查询作为查找表,需要隐藏和存储实际值,同时显示人类可读的版本...组合框行源中的多个列。因此,将限制更改为列表没有帮助,因为不在当前行源查询中的id将不具有匹配的人类可读部分。

在这种特殊情况下,连续形式很有意义,所以请不要告诉我这是错误的解决方案。我要求任何有创意的答案。

13 个答案:

答案 0 :(得分:15)

我也讨厌Access,但你必须玩你发牌的牌。 连续表单在Access中是一件很棒的事情,直到你遇到任何类型的复杂性,就像在这种情况下一样。

以下是面对这种情况时我会做的事情(之前我已经实施过类似的解决方法):

在表单上放置一个UNBOUND组合框。然后为要编辑的字段放置一个BOUND文本框。

确保组合框隐藏在textBox后面(不可见,只是隐藏)。

在OnCurrent事件中,使用必要的数据填充listBox。继续并“限制列出”它。

在textBox的OnEnter或OnClick事件中,给出组合框焦点。这将把组合框带到最前沿。当焦点离开组合框时,它将再次隐藏自己。

在组合框的AfterUpdate事件中,文本框的值等于组合框的值。

根据您的情况,可能会有其他一些细节可以解决,但这应该或多或少地实现您的目标,而不会增加太多的复杂性。

答案 1 :(得分:3)

绝对使用连续形式。实际上,您可以使用基于连续表单的出色且直观的用户界面构建整个应用程序。不要听Toast!

列出所有可用选项的解决方案是正确的。事实上,没有其他清洁解决方案。但是当你说Acccess发疯的时候,你错了。在连续的表单上,您可以将每一行视为详细信息部分的实例,其中组合框是详细信息部分的所有实例共有的属性。您可以为所有实例更新此属性,但不能为一个特定实例设置它。这就是为什么Access必须在组合框中为所有记录显示相同的数据!

如果您只需要在此组合框中接受特定于记录的值,请使用beforeUpdate事件添加控制过程。如果无法接受新值,您可以取消数据更新,并返回字段中的先前值。

您无法将limitToList属性设置为“No”,其中隐藏了链接数据(存储在控件中的数据)。这是合乎逻辑的:当链接字段(不可见)保持空白时,机器如何接受新数据行的输入?

答案 2 :(得分:1)

您还可以将组合框的值设置为不可编辑的文本字段,然后启动弹出/模式窗口以编辑该值。但是,如果我这样做,我可能倾向于在其中一个窗口中编辑整个记录。

答案 3 :(得分:1)

我认为Access连续表格根本不应受到谴责,但我绝对认为应该避免编辑数据。它们非常适合列表,并且比纯粹的列表框提供更多的格式化功能(并且更容易使用,当然,虽然它们不允许多选)。

如果要使用连续表格导航到记录进行编辑,请使用显示详细数据进行编辑的子表单,并使用子表单中的PK值作为链接字段。这可以通过连续的形式完成,您可以在页眉或页脚中放置一个细节子表单,链接在连续表单后面的表格的PK上。

或者,如果您使用连续表单以父表单显示子数据,则可以将详细信息子表单与连续子表单中的PK引用链接起来,如:

[MySubForm].[Form]!MyID

这将是链接主属性,而MyID将是链接子属性。

答案 4 :(得分:1)

我们的应用程序中也经常遇到这种情况。我们发现了一个很好的解决方案: 只显示组合框中的所有行。 然后,只要用户在特定行中输入组合框,就调整rowsource(使用该行的过滤器)。当组合框失去焦点时,您可以重新设置rowsource来显示所有内容。

答案 5 :(得分:1)

我有比Gilligan更简单的方法。这似乎很多工作,但实际上并非如此。我的解决方案需要将我的连续表单作为子表单数据表。在我的子表单上,我有两个查找组合框,其中包括设备和制造商。两者都只是在数据源中持有Long Integer键。制造商需要按照设备中选择的内容进行过滤。我唯一一次过滤Manufacturer.RowSource是在Manufacturer_GotFocus事件中。

Private Sub Manufacturer_GotFocus()

If Nz(Me.Equipment, 0) > 0 Then
    Me.Manufacturer.RowSource = GetMfrSQL()  '- gets filtered query based on Equipment
Else
    Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"
End If

End Sub

在Manufacturer_LostFocus中,我还将Manufacturer.RowSource重置为所有制造商。您需要执行此操作,因为当您第一次单击子窗体时,即使您实际上没有更新任何字段,也会触发所有控件(包括制造商)的GotFocus事件。

Private Sub Manufacturer_LostFocus()

Me.Manufacturer.RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"

End Sub

在制造商的Enter事件中,您必须检查是否已选择设备,如果未将焦点设置为设备。

Private Sub Manufacturer_Enter()

If Nz(Me.EquipmentID, 0) = 0 Then
    '-- Must select Equipment first, before selecting Manufacturer
    Me.Equipment.SetFocus
End If

End Sub

您还需要在Form_Current事件(即Me.Manufacturer.Requery)中重新查询Manufacturer组合框,并且应将此子窗体的Cycle属性设置为“Current Record”。

看起来很简单,但你还没有完成。如果用户转到“制造商”组合框但未进行选择并单击父窗体上的某个位置,则还必须将Manufacturer.RowSource重置为父窗体中SubForm_Exit事件中的所有制造商。代码示例(以父格式):

Private Sub sFrmEquip_Exit(取消为整数)

Me.sFrmEquip.Controls("Manufacturer").RowSource = "SELECT MfgrID, MfgrName FROM tblManufacturers ORDER BY MfgrName"

End Sub

还有一部分不干净。当您单击“制造商”并在数据表网格中有多行时,“制造商”字段将在其他行中显示为空白(组合框下方的数据仍然完好无损),而您在当前行中更改了制造商。离开此字段后,其他“制造商”字段中的文本将重新出现。

答案 6 :(得分:1)

这似乎运作良好。 CBOsfrmTouchpoint8是一个缩短为下拉方块的组合框。 CBOsfrmTouchpoint14是构成剩余空间的文本框。 永远不要说永远:

  Private Sub CBOsfrmTouchpoint8_Enter()  

  If Me.CBOsfrmTouchpoint8.Tag = "Yes" Then  
  CBOsfrmTouchpoint14.SetFocus  
  Me.CBOsfrmTouchpoint8.Tag = "No"  
  Exit Sub  
  End If  

  Me.CBOsfrmTouchpoint8.Tag = "No"  
  Me.CBOsfrmTouchpoint8.RowSource = "XXX"  
  Me.CBOsfrmTouchpoint8.Requery  
  Me.CBOsfrmTouchpoint8.SetFocus  
  End Sub 

  Private Sub CBOsfrmTouchpoint8_GotFocus()  
  Me.CBOsfrmTouchpoint14.Width = 0  
  Me.CBOsfrmTouchpoint8.Width = 3420  
  Me.CBOsfrmTouchpoint8.Left = 8580  
  Me.CBOsfrmTouchpoint8.Dropdown  
  End Sub

  Private Sub CBOsfrmTouchpoint8_LostFocus()  
  Me.CBOsfrmTouchpoint8.RowSource = "XXX"  
  Me.CBOsfrmTouchpoint8.Requery  
  End Sub 

  Private Sub CBOsfrmTouchpoint8_Exit(Cancel As Integer)  
  Me.CBOsfrmTouchpoint14.Width = 3180  
  Me.CBOsfrmTouchpoint8.Width = 240  
  Me.CBOsfrmTouchpoint8.Left = 11760  
  Me.CBOsfrmTouchpoint8.Tag = "Yes"  
  End Sub

答案 7 :(得分:0)

如果您关闭“限制列表”选项,并在更新前进行一些验证以确认用户可能输入的内容与您提供的列表中的内容匹配,该怎么办?

答案 8 :(得分:0)

...更好

将组合框控件来源设置为查询中将存储组合框值的列。

答案 9 :(得分:0)

对于我来说,我认为最好的方法和最简单的方法是创建一个临时表,其中包含所有绑定字段以及一个额外的字段,该字段是一个是/否字段。

然后您将使用此表作为连续for的数据源。您可以使用onLoad用您想要的数据填充临时表。

我觉得在循环选择之后很容易,只需要一个小循环来从临时表中读取yeas / no字段。

我希望这会有所帮助

答案 10 :(得分:0)

使用OnEnter事件填充组合框,不要使用固定的rowsource

答案 11 :(得分:0)

我刚刚完成了类似的事情。我的解决方案是使用绑定到查询的固定行源。查询的WHERE条款引用了表单的控件,即Client=Forms!frmMain!ClientTextBox。仅这一点就会在第二行的数据中填充组合框。然后诀窍是设置一个' On Enter'简单地在组合框上进行重新查询的事件,例如ComboBox1.Requery,这将仅重新查询该组合框,并且只会拖动与该记录行相关的数据。

希望这对你有用!

答案 12 :(得分:-1)

免责声明:我非常讨厌Access。

不要使用连续表格。对于你想要完成的事情,它们是一个红色的鲱鱼。连续形式是使用不同数据反复重复的相同形式。它已经是Access的正常操作模式的一部分,因为您不能多次打开相同的表单。您看到的行为在Access中“按设计”。每个ComboBox控件实际上都是相同的控件。你不能在不影响其他人的情况下影响他人。

基本上,你在这里所做的就是进入Access不再适合你的项目的区域(但不能因为它代表了大量的工作而放弃)。

这里似乎最有可能采取的行动是将其伪造得很好。对数据运行查询,然后根据结果以编程方式创建表单元素。这是相当多的工作,因为您将自己复制一些Access的数据处理功能。

回复编辑:
但就像它们一样,连续的形式无法实现你想要的。这就是为什么我建议伪造自己的连续形式,因为连续形式在他们能做的事情上有实际限制。不要那么坚持一个特定的实现,当它停止工作时你不能放弃它。