14

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

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

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

我发现的唯一解决方案是始终列出所有可用的选项。有什么创意答案吗?

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

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

4

13 回答 13

15

我也讨厌 Access,但你必须使用你收到的牌。连续表单在 Access 中是一件很棒的事情,直到您遇到任何常见的复杂性,例如在本例中。

这是我在遇到这种情况时会做的事情(我之前已经实施过类似的解决方法):

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

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

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

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

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

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

于 2008-09-18T02:20:53.987 回答
3

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

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

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

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

于 2008-09-17T22:01:32.363 回答
1

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

于 2008-09-17T19:41:28.737 回答
1

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

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

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

[MySubForm].[Form]!MyID

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

于 2008-09-17T23:51:03.053 回答
1

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

于 2008-09-18T11:05:56.567 回答
1

我有一个比吉利根更简单的方法。看起来工作量很大,但实际上并非如此。我的解决方案需要将我的连续表单作为子表单数据表。在我的子表单上,我有两个查找组合框,以及其他字段,称为设备和制造商。两者都只是在数据源中保存一个 Long Integer 键。制造商需要按设备中选择的内容进行过滤。我过滤 Manufacturer.RowSource 的唯一一次是在 Manufacturer_GotFocus 事件中。

私有子厂商_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

结束子

在 Manufacturer_LostFocus 中,我也将 Manufacturer.RowSource 重置为所有制造商。您需要这样做,因为当您第一次单击子窗体时,所有控件(包括制造商)都会触发 GotFocus 事件,即使您实际上并未更新任何字段。

私有子制造商_LostFocus()

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

结束子

在制造商的输入事件中,您必须检查是否选择了设备,如果没有将焦点设置为设备。

私有子制造商_Enter()

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

结束子

您还需要重新查询Form_Current 事件中的Manufacturer 组合框(即Me.Manufacturer.Requery),并且您应该将此子表单的Cycle 属性设置为“当前记录”。

看起来很简单,但你还没有完成。您还必须在父表单的 SubForm_Exit 事件中将 Manufacturer.RowSource 重置为所有制造商,以防用户转到制造商组合框但未进行选择并单击父表单上的某处。代码示例(以父形式):

Private Sub sFrmEquip_Exit(取消为整数)

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

结束子

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

于 2008-11-26T23:49:24.800 回答
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
于 2012-02-13T05:05:03.647 回答
0

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

于 2008-09-17T18:59:57.107 回答
0

更好的...

将您的组合框控制源设置为查询中的一列,组合框中的值将被存储在该列中。

于 2009-03-08T15:41:37.820 回答
0

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

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

我认为之后循环选择很容易,只需一个小循环即可从临时表中读取是/否字段。

我希望这个能帮上忙

于 2010-02-12T22:24:21.447 回答
0

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

于 2010-03-10T18:45:56.103 回答
0

我刚刚做过类似的。我的解决方案是使用绑定到查询的固定行源。查询的WHERE子句引用表单的控件,即Client=Forms!frmMain!ClientTextBox. 仅此一项就会用第一行的数据填充组合框。诀窍是设置一个 ' On Enter' 事件,它只是对组合框进行重新查询,例如ComboBox1.Requery,这将单独重新查询该组合框,并且只会拖入与该记录行相关的数据。

希望这也对你有用!

于 2016-01-08T16:19:59.877 回答
-1

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

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

基本上,您在这里所做的事情是遇到了 Access 不再适合您的项目的区域(但不能放弃,因为它已经代表了大量的工作)。

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

回复编辑:
但实际上,连续形式无法完成您想要的。这就是为什么我建议伪造你自己的连续形式,因为连续形式在它们可以做的事情上有真正的限制。不要太拘泥于某个特定的实现,以至于当它停止工作时你就放不下它。

于 2008-09-17T18:56:12.683 回答