首页 > 解决方案 > MS Access SQL:带有复选框的选择列表的左连接

问题描述

我正在尝试按照此处提供的示例(https://www.databasedevelopment.co.uk/examples.htm)获取带有复选框的 MS Access 子表单以供选择。

tbl_Employee_Selected

ID 员工ID 姓名
1 1234 约翰·史密斯
2 1235 简·史密斯

tbl_Simple_selected

选定ID 员工ID 已选中
1 是/否
2 是/否
SELECT tbl_Employee_Selected.ID, tbl_Employee_Selected.EmployeeID, tbl_Employee_Selected.FirstName, tbl_Employee_Selected.LastName, tbl_Simple_selected.Selected
FROM tbl_Employee_Selected 
LEFT JOIN tbl_Simple_selected ON tbl_Employee_Selected.ID = tbl_Simple_selected.EmployeeID;

问题是,使用上面的 SQL,我在创建的表中得到了“SelectedID”,而不是实际的员工 ID。如果我尝试任何其他联接条件,我将无法更新记录集,因为我没有使用主键。

标签: sqlms-access

解决方案


你在乎,还是需要一个临时表?

您可以从“网格”(连续形式)中选择行,而无需复选框列。

因此,我们构建了一个“集合”来跟踪所选行的表单代码。

代码如下所示:

  Option Compare Database
  Option Explicit
  
  Public CheckItems As New Collection
  
  Public Function MySel(vID As Variant) As Boolean
  
     If IsNull(vID) Then
        MySel = False
        Exit Function
     End If
     ' check if id exists in colleciton.
     On Error Resume Next
     Dim mydummy As Variant
     mydummy = CheckItems(CStr(vID))
     If Err.Number = 0 Then
        ' found it, return true!!
        MySel = True
        Exit Function
     End If
     
     MySel = False
  
  End Function
  
  
  Private Sub cmdCheck_Click()
  
     ' check in our list
     If MySel(Me!ID) Then
        ' already in list - remove
        CheckItems.Remove CStr(Me!ID)
     Else
        ' not in the list - add it
        CheckItems.Add Me!ID.Value, CStr(Me!ID)
     End If
     
     Me.ckSel.Requery
  
  End Sub

所以,这里的“技巧”是我们将复选框绑定到 MySel 函数。因为复选框现在绑定到该函数,所以我们不能单击该复选框。

因此,复选框现在绑定如下:

在此处输入图像描述

因此,SelChk 函数将传递给定行的 PK。

现在,要选中/取消选中,我们在复选框的顶部放置一个按钮(不可见)。

像这样:

在此处输入图像描述

不要忘记将此按钮放在前面 - 我们确保它位于复选框的顶部。

因此:

在此处输入图像描述

因此,将以上所有内容放在一起,我们就有了:

在此处输入图像描述

当然,我们现在需要一个最终按钮来进行选择,我们可以运行报告,甚至处理记录。代码可以是这样的:

Dim strWhere      As String
Dim v             As Variant

For Each v In CheckItems
  If strWhere <> "" Then strWhere = strWhere & ","
  strWhere = strWhere & v
Next

' 根据选择打开报告

DoCmd.OpenReport "rptHotelsInvoice", acViewPreview, , "ID IN (" & strWhere & ")"

或者,我们可以在代码中处理记录,如下所示:

  Dim strWhere      As String
  Dim v             As Variant
  
  For Each v In CheckItems
     If strWhere <> "" Then strWhere = strWhere & ","
     strWhere = strWhere & v
  Next
  
  Dim strSQL As String
  
  strSQL = "SELECT * from tblHotels where ID IN (" & strWhere & ")"
  Debug.Print strSQL
  
  Dim rst     As DAO.Recordset
  Set rst = CurrentDb.OpenRecordset(strSQL)

  Do While rst.EOF = False
  
      ' process reocrds
      rst.Edit
      rst("FirstName") = rst("FirstName") & "z"
      
      rst.Edit
      rst("FirstName") = rst("FirstName") & "z"
      
      rst.Update
      rst.MoveNext
  Loop
  rst.Close

现在,我们假设 PK 有一个“ID”,但如果您的 pk id 不同,则更改此:

MySql([ID])  to whatever your PK row ID is. the rest of the code should work as is.

上面创建 WHERE 子句的最后一段代码将再次被更改。

所以,总而言之?

你真的不需要临时表,使用上面的自定义集合和驱动复选框的函数意味着你不需要额外的表。

上面的美?

您可以将其用于链接的 Excel 工作表、SharePoint 表、SQL 服务器表 - 没关系,因为我们不会弄乱或处理额外的表。


推荐阅读