【问题标题】:Implementing Many to Many, Subforms, Checkboxes in Access 2007在 Access 2007 中实现多对多、子表单、复选框
【发布时间】:2012-05-05 13:19:27
【问题描述】:

人 人_宠物 宠物

我需要制作一个数据输入表单。假设我们有一个名为 Person 的表,其中包含适当的字段。在我的表单上,我需要允许用户从(一个或多个)复选框中进行选择,这些复选框代表他们可能拥有的所有可能的宠物(固定的项目列表:狗、薮猫、美洲驼、鹿角羚、鸸鹋、龙、蜘蛛......) .

对于表单,需要有一个复选框来代表每个可能的选择。如果该人确实有一只宠物狗,则该复选框必须为真,如果他们没有狗,则该复选框必须为假(我想我说的是显而易见的,因为我试图将其作为子表单“多对多”和显示“假”值的东西。他们可以选择不止一个。

最终我需要制作一个新表格或重新使用数据输入表格进行修改等。

这是一个子表单吗?我有一个 Person 表、Pet 表、Person_Pet(id/joining)表。我正在尝试使用 VBA 完成这一切,但我认为我选择了艰难的方式,但是,现在改变方向还为时不晚。

编辑: 如果我从这个开始呢?这将导致给我一个所有可能宠物的列表,如果 p.personid 为空,则不选中该复选框。如果它不为空,则对其进行检查。这可能吗? (请原谅格式,访问 sql 编写器显然不知道选项卡是什么,请原谅 sytanx 错误,因为我必须快速查找和替换表名)

select pet.*, p.personid
from pet pet 
left outer join
(select pi.petID, pi.personid
from    person,
        pet_person pi,
        pet 
where   person.id = pi.personID and
        pet.id = pi.petID) as p
on p.petID = pet.id

编辑:

好的。那里有一个巨大的答案。我也解决了。我还没有看过你的答案,但我会稍微看一下。这是我的答案...(没有子表单,都在主表单上,“人”表单)

  1. 制作复选框...并将它们命名为 chk1、chk2、chk3...等等。
  2. 确保它们对应于我的 lil pet 表中的适当字段....所以 dog = chk1, serval = chk2... stuff
  3. 执行此 vba(并从 Form_Current() 调用函数并将其传递给 me.id):

函数 update_checkboxes(issueID As Variant) 暗淡查询作为字符串 Dim rs As DAO.Recordset 将 db 作为数据库 设置 db = CurrentDb 暗淡作为字符串

If Not IsNull(issueID) Then
    query = "SELECT iif(joined.issueid is null, 0, 1) as binval, payer.* " & _
            "FROM payer AS payer LEFT JOIN (select ri.issueid, ri.payerid " & _
                    "from  issue i, payer r, payer_issue ri " & _
                    "where i.id = ri.issueid and r.id = ri.payerid and ri.issueid = " & issueID & _
                    ")  AS joined ON joined.payerid = payer.id;"
Else
    query = "select 0 as binval, payer.* from payer"
End If

Set rs = db.OpenRecordset(query)
rs.MoveFirst

Do While Not rs.EOF
    s = rs.Fields("CorrespondingChkboxNumber")
    Me.Controls("chk" & s).Value = rs.Fields("binval")
    rs.MoveNext
Loop

rs.Close
End Function

是的。复制粘贴代码格式stackoverflow的东西讨厌我。对不起。嗯。问题=人,付款人=宠物。我知道相应的复选框不知道,我将不得不搜索/检查一个字符串字段,但这显示了我认为我最终可能会使用的概念,除非............ .........

后续问题:每次更改记录时运行这些 vba 查询是否存在严重的时间限制问题/后果/总结?

顺便说一句。供参考。用选定的答案显示可能的答案的愿望是因为有时事物不是什么与事物是什么同样重要。一些地区/县/市不允许比特犬。整个加利福尼亚州显然取缔了雪貂。我确实有一只比特犬。我没有雪貂。我们都只希望我们有宠物龙可以训练。所有这些都在某些地区的禁止宠物清单上,所以......这两个东西都需要展示。一个列表框可以做到这一点,但我觉得它看起来有点尴尬。通过明显列出我所有可能的宠物,我知道哪些会升旗。虽然最后只有我所拥有的才是真正重要的......仍然。但显然我并没有为人和宠物以及他们可以居住的地方制作一个可爱的小访问数据库。

【问题讨论】:

  • 关于您的跟进:当您从一个数据集移动到另一个数据集时,幕后会发生很多事情,以至于这个小 vbacode 没有任何区别。真正耗时的部分是 SQL——它可以很好地扩展(即,如果你在 pet_person 中有更多数据集,它不会花费更长的时间)——并且只有在有数千个数据集的情况下,运行整个 petlistbox 才会成为问题宠物桌首先会给您的设计带来其他问题;)
  • 另一种想法:有些人会花时间思考您的问题,做出 - 希望 - 有价值的贡献,有时会免费帮助您。如果您第一次没有正确回答问题,您可以在编辑问题时向他们表示尊重 - 甚至更好:将其写入本地编辑器并在您拥有它时将其粘贴......只是一个评论 - 没有冒犯

标签: ms-access vba


【解决方案1】:

使用 VBA,您可以使用以下代码。有两种选择:

  1. 使用“本机”访问列表框:这将您的选择显示为 常规列表框中突出显示的行

    在列表框属性/全部中选择 multiselect=1 (Single)
    工作表并修改以下代码 -> 取消注释行 并评论上面的内容

  2. 使用 MSForms.Listbox(在 Formcreation 中选择 activeX 插入)
    在这里你可以得到你想要的复选框。

    选择 Multiselect:multi 和 ListStyle:option。这里没有点击事件,所以我选择了退出事件。一世 到目前为止还没有遇到任何问题,但有条不紊地点击 活动会更好。

这是代码:

Option Compare Database
Option Explicit

Dim pPetListBox As MSForms.ListBox

Private Sub FillPetListbox() 
  pPetListBox.Clear
  Dim rst As DAO.Recordset
  Set rst = CurrentDb.OpenRecordset("select * from pet order by id")
  While Not rst.EOF
    pPetListBox.AddItem rst!ID
    pPetListBox.List(pPetListBox.ListCount - 1, 1) = rst!petname
    rst.MoveNext
  Wend
  rst.Close
End Sub

Private Sub Form_Current()
  Dim rst As DAO.Recordset
  Dim indx As Long
  Set rst = CurrentDb.OpenRecordset("select * from person_pet where personid=" & Me.ID)
  For indx = 0 To pPetListBox.ListCount - 1
    rst.FindFirst "petID = " & pPetListBox.Column(0, indx)
'    rst.FindFirst "petID = " & petList.ItemData(indx)
    pPetListBox.Selected(indx) = Not rst.NoMatch
  Next
  rst.Close
End Sub

Private Sub UpdateLinkTable()
  Dim rst As DAO.Recordset
  Dim indx As Long
  Set rst = CurrentDb.OpenRecordset("select * from person_pet where personid=" & Me.ID)
  indx = pPetListBox.ListIndex
  rst.FindFirst "petID = " & pPetListBox.List(indx, 0)
  'rst.FindFirst "petID = " & petList.ItemData(indx)
  If (pPetListBox.Selected(indx) And rst.NoMatch) Then
    rst.AddNew
    rst!personID = Me.ID
    rst!petID = pPetListBox.Column(0, indx)
    rst.Update
  Else
    If ((Not pPetListBox.Selected(indx)) And (Not rst.NoMatch)) Then
      rst.Delete
    End If
  End If
  rst.Close
End Sub

Private Sub Form_Load()
  Set pPetListBox = Me.msfPetListBox.Object
  FillPetListbox
End Sub

Private Sub msfPetListBox_Exit(Cancel As Integer)
'Private Sub petList_Click()
  UpdateLinkTable
End Sub

如果您使用本机访问列表框,则不必以编程方式加载列表框内容 (FillPetListBox)。相反,您可以将 rowsource-property 设置为 pet-table。我认为甚至可以将 MSForms.listbox 绑定到该表 - 但我还没有尝试过(还)。

【讨论】:

    【解决方案2】:

    使用子表单。多个复选框边框疯狂:)

    你需要一张桌子:

    PersonID
    PetID
    

    PetID 将是一个组合框,其中包含列出可能宠物的行源。 PersonID 将是链接子字段和主字段。

    您不需要任何代码来执行此操作。

    【讨论】:

    • 这种方法的问题是,你最终可能会让一个人与同一类宠物有多个关系。如果没关系,那么我会推荐这种方法。我在您的问题中看到的是,您只想说“是的-我有那只宠物”或“不,我没有它”。这将是自 acc2007 以来 Access 支持的多对多关系 - 但大多数专业人士建议不要使用它,因为它会在隐藏表上中继,并且只要您想以编程方式访问数据或在非访问解决方案变得丑陋。
    • 是的。我对 vba 很满意,但我认为 access 试图让我的工作“更轻松”,但我现在必须在 access 的上下文中学习所有这些绑定和子形式的东西,才能做出任何事情。我宁愿从后面攻击,但我敢打赌,如果我了解所见即所得的组件/控件访问提供的内容,这最终会节省时间......我觉得我几乎让我定义自己的加入 id 表变得更加困难有一个规范化的数据库,我可以在其中看到所有使用的表......(当访问修复我的多对多关系时,隐藏的连接表让我有点害怕)
    • 组合框和列表框确实有明确的优点和缺点......我不确定我是否真的喜欢任何一个选项。
    • 如果您不想要多个关系,那么只需在表上设置一个唯一的 Persion_Id、Pet_id 复合键,您将无法添加多个实例
    • 多个复选框...我可能是疯了,但我想我明白了:o)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 2010-09-09
    • 1970-01-01
    • 2019-07-24
    相关资源
    最近更新 更多