代码之家  ›  专栏  ›  技术社区  ›  DGM

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

  •  12
  • DGM  · 技术社区  · 16 年前

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

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

    当然,下一步我们都会尝试使用oncurrent事件重新查询组合框,这实际上会将选项限制在给定的行中。然而,在这一点上,访问变得疯狂,需要 全部的 对于组合框中的每一行,结果通常是在其他行中消失和重新显示选项,这取决于它们是否选择了对当前记录的行源有效的选项。

    我找到的唯一解决方案就是随时列出所有可用的选项。有什么创造性的答案吗?

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

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

    13 回复  |  直到 16 年前
        1
  •  15
  •   Gilligan    16 年前

    我也不喜欢进入,但你必须玩你发的牌。 在访问中,连续形式是一件很好的事情,直到遇到通常情况下的任何类型的复杂性,就像在本例中一样。

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

    在窗体上放置未绑定的组合框。然后为要编辑的字段放置绑定文本框。

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

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

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

    在ComboBox的AfterUpdate事件中,将文本框的值设置为ComboBox的值。

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

        2
  •  3
  •   Philippe Grondier    12 年前

    使用连续形式。一定地。事实上,您可以使用构建在连续表单上的强大而直观的用户界面构建整个应用程序。别听祝酒词!

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

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

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

        3
  •  1
  •   BIBD    16 年前

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

        4
  •  1
  •   David-W-Fenton    16 年前

    我认为访问连续表单根本不应该受到谴责,但我绝对认为编辑数据时应该避免使用它们。它们对列表非常有用,并且给您提供了比单纯的列表框更大的格式化能力(当然,它们不允许多重选择,但也更容易使用)。

    如果要使用连续表单导航到要编辑的记录,请使用显示要编辑的详细数据的子表单,并使用子表单中链接字段的pk值。这可以通过一个连续表单来实现,在该表单的页眉或页脚中放置一个细节子表单,链接到连续表单后面的表的pk上。

    或者,如果使用连续窗体在父窗体中显示子数据,则可以通过引用连续子窗体中的pk来链接细节子窗体,如下所示:

    [MySubForm].[Form]!MyID
    

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

        5
  •  1
  •   Birger    16 年前

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

        6
  •  1
  •   Geoff Glick    16 年前

    我有比吉利根更简单的方法。这看起来工作量很大,但实际上不是。我的解决方案要求将连续窗体作为子窗体数据表。在我的子窗体上,我有两个查找组合框,其中一个字段称为设备和制造商。两者都只是在数据源中保存一个长整型键。制造商需要根据设备中选择的内容进行筛选。我筛选manufacturer.rowsource的唯一时间是在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
    

    结束子

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

    私有子制造商lostfocus()。

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

    结束子

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

    私有子制造商

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

    结束子

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

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

    私有子sfrmequip_exit(取消为整数)

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

    结束子

    还有一件东西不干净。当您单击“制造商”并在“数据表”网格中有多行时,当您在当前行中更改制造商时,“制造商”字段将在其他行中变为空白(组合框下面的数据仍然保持不变)。离开此字段后,其他制造商字段中的文本将重新出现。

        7
  •  1
  •   XXX    13 年前

    这似乎很管用。 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
    
        8
  •  0
  •   BIBD    16 年前

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

        9
  •  0
  •   GeneB    16 年前

    更好…

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

        10
  •  0
  •   community wiki Basel Juma    15 年前

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

    然后您将使用此表作为连续的数据源。可以使用onload将所需数据填充到临时表中。

    我认为之后很容易循环选择,只需要一个小循环就可以从临时表中读取Yes/No字段。

    我希望这会有帮助

        11
  •  0
  •   Jérôme Verstrynge    13 年前

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

        12
  •  0
  •   maxshuty Fatih Hayrioğlu    9 年前

    我也做过类似的事情。我的解决方案是使用绑定到查询的固定行源。查询的 WHERE 条款引用了表格的控制,即 Client=Forms!frmMain!ClientTextBox . 仅此一项就可以用第一行的数据填充组合框。接下来的诀窍是设置一个' On Enter '对组合框进行重新查询的事件,例如 ComboBox1.Requery ,这将单独重新查询该组合框,并且只在与该记录行相关的数据中进行拖动。

    希望这对你也有用!

        13
  •  -1
  •   Benjamin Autin Andrés Bonilla    16 年前

    免责声明:我讨厌充满激情的访问。

    不要使用连续形式。他们是你想要达到的目标的红鲱鱼。连续形式是同一种形式,用不同的数据反复重复。它已经是Access正常操作模式的组合,因为不能多次打开同一表单。您看到的行为在Access中是“按设计”的。每个组合框控件实际上都是相同的控件。你不能不影响别人就影响别人。

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

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

    回复编辑:
    但实际上,连续形式不能实现你想要的。这就是为什么我建议假装出你自己的连续形式,因为连续形式在他们能做的事情上有真正的局限性。不要在一个特定的实现上如此执着,以至于当它停止工作时,你不能放开它。