在Access 2007中实现多对多,子表单,复选框

时间:2012-04-24 20:50:37

标签: ms-access vba

人     Person_Pet     宠物

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

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

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

这是一个子表格吗?我有一个Person表,Pet表,Person_Pet(id / join)表。我试图用VBA来解决所有这些问题,但我认为我已经采取了艰难的方式,但是,改变方向还为时不晚。

编辑: 如果我从这开始怎么办?它会产生一些东西给我一个所有可能的宠物列表,如果p.personid为null,则不选中该复选框。如果它不为null则检查它。这可能吗? (原谅格式化,访问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宠物表中的相应字段....所以dog = chk1,serval = chk2 ... stuff
  3. 执行此vba(并从Form_Current()调用函数并将其传递给me.id):
  4. 函数update_checkboxes(issueID As Variant)     Dim query As String     Dim rs As DAO.Recordset     Dim db As Database     设置db = CurrentDb     D as a As String

    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的事情很讨厌我。抱歉。 UM。 issue = person,payer = pet。我知道相应的复选框的东西不是主意,我将不得不搜索/检查一个字符串字段,但这显示了我认为我可能最终使用的概念,除非.......... .........

    跟进问题:每次更改记录时,是否有任何严重的时间限制问题/后果/一切都在运行这些vba查询?

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

2 个答案:

答案 0 :(得分:1)

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

你需要一张桌子:

PersonID
PetID

PetID将是一个带有行源的组合框,列出了可能的宠物。 PersonID将是链接子和主字段。

您无需任何代码即可执行此操作。

答案 1 :(得分:1)

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

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

    在listboxes属性/ all中选择了multiselect = 1(Single) 表并修改以下代码 - >解开评论的行 并评论上面的那些

  2. 使用MSForms.Listbox(在Formcreation中选择activeX insert)
    在这里,您可以获得所需的复选框。

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

  3. 这是代码:

    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绑定到该表 - 但我还没有尝试(还)。