使用 VBA 在 Access 2010 中的窗体上显示记录集

发布于 2024-11-10 11:38:56 字数 196 浏览 4 评论 0原文

我正在 Access 2010 中开发一个数据检索应用程序,用户可以通过选择列表框条目来选择要查看的表、列和行。 VBA 代码根据这些选择生成 SQL 语句,然后由此创建 ADBDB.Recordset 对象。

如何在Access中显示记录集记录?所有网格控件都无法在 Access 2010 中工作,并且子窗体也不是为此目的而设计的。有人可以推荐另一种策略吗?

I'm developing a data retrieval application in Access 2010 in which the user chooses which table, columns, and rows to view by selecting listbox entries. The VBA code generates a SQL statement from these choices and then creates an ADBDB.Recordset object from this.

How can I display the recordset records in Access? None of the grid controls work in Access 2010 and the subform just isn't designed for this purpose. Can someone recommend another strategy?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

暮光沉寂 2024-11-17 11:38:56

您可以将 SELECT 语句保存为命名查询,然后将该查询作为数据表打开。它并不是真正的形式,但有点像形式。

Call DatasheetFromSql(strSql)

Public Sub DatasheetFromSql(ByVal pSql As String)
    Const cstrQuery As String = "qryDiscardMe"
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strMsg As String

On Error GoTo ErrorHandler

    Set db = CurrentDb
    db.QueryDefs.Delete cstrQuery
    Set qdf = db.CreateQueryDef(cstrQuery, pSql)
    DoCmd.OpenQuery cstrQuery, , acReadOnly

ExitHere:
    On Error GoTo 0
    Set qdf = Nothing
    Set db = Nothing
    Exit Sub

ErrorHandler:
    Select Case Err.Number
    Case 3265 ' Item not found in this collection. '
        Resume Next
    Case Else
        strMsg = "Error " & Err.Number & " (" & Err.description _
            & ") in procedure DatasheetFromSql"
        MsgBox strMsg
        GoTo ExitHere
    End Select
End Sub

我以只读方式打开查询。如果您希望允许用户编辑自定义查询返回的数据,我不推荐这种方法。相反,我会将精力投入到 HK1 提供的方法上,因为它可以支持更好地控制用户数据更改。

将查询作为数据表打开后,您可以使用 Screen.ActiveDatasheet 检查其属性。至少其中一些方法也可供您使用。例如,您可以像这样调整数据表的大小/位置:

Screen.ActiveDatasheet.Move Left:=0, Top:=0, Width:=(4 * 1440), Height:=(3 * 1440)

单位为缇(1440 缇/英寸),因此宽度为 4 英寸,高度为 3 英寸,并将其移动到 Access 窗口的左上角。

You could save the SELECT statement as a named query, then open the query as a datasheet. It's not really a form, but somewhat form-like.

Call DatasheetFromSql(strSql)

Public Sub DatasheetFromSql(ByVal pSql As String)
    Const cstrQuery As String = "qryDiscardMe"
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strMsg As String

On Error GoTo ErrorHandler

    Set db = CurrentDb
    db.QueryDefs.Delete cstrQuery
    Set qdf = db.CreateQueryDef(cstrQuery, pSql)
    DoCmd.OpenQuery cstrQuery, , acReadOnly

ExitHere:
    On Error GoTo 0
    Set qdf = Nothing
    Set db = Nothing
    Exit Sub

ErrorHandler:
    Select Case Err.Number
    Case 3265 ' Item not found in this collection. '
        Resume Next
    Case Else
        strMsg = "Error " & Err.Number & " (" & Err.description _
            & ") in procedure DatasheetFromSql"
        MsgBox strMsg
        GoTo ExitHere
    End Select
End Sub

I opened the query read-only. If you want to allow users to edit the data returned by their custom queries, I would not recommend this approach. Instead I would invest the effort in the approach HK1 offered because it can support better control of the user data changes.

With the query opened as a datasheet, you can use Screen.ActiveDatasheet to inspect its properties. At least some of the methods are also available to you. For example you could resize/reposition the datasheet like this:

Screen.ActiveDatasheet.Move Left:=0, Top:=0, Width:=(4 * 1440), Height:=(3 * 1440)

The units are twips (1440 twips / inch), so that would make the width 4 in., height 3 in., and move it to the upper left corner of the Access window.

撩动你心 2024-11-17 11:38:56

我认为您需要执行以下操作才能获得此类功能。

您首先需要在表单上创建足够的正确控件来处理每种可能的情况。然后,您需要将表单设置为数据表表单,以便它显示为网格。

现在将控件上的控件源设置为与记录集中的字段之一相对应。每个未使用的控件都需要将其 ColumnHidden 属性设置为 true。您还必须更改关联标签的标题,以显示每个可见控件的相应列名称。

现在,将该表单绑定到您的 ADO 记录集对象。

Me.Recordset = rst
'or
Me.Subform1.Form.Recordset = rst

这是一个完美的解决方案吗?肯定不是。 Access 没有任何东西可以与.Net 中的DataGridView 甚至VB6 中使用的网格控件相比。在我看来,您确实在突破 Access 的限制来尝试获得此类功能。就像逆流而上一样。你会发现你所做的一切都会相当困难,有些事情根本不可能。

Here's what I think you'll have to do to get this kind of functionality.

You'll first need to create enough of the correct controls on a form to handle every possible scenario. You'll then need to set the form to be a datasheet form so that it appears as a grid.

Now set the controlsource on your controls to correspond with one of the fields in the recordset. On every control that is not in use needs to have it's ColumnHidden property set to true. You'll also have to change the caption of the associated label to show the appropriate column name for each control that will be visible.

Now, bind that form to your ADO recordset object.

Me.Recordset = rst
'or
Me.Subform1.Form.Recordset = rst

Is this a perfect solution? Most certainly not. Access doesn't have anything that compares to the DataGridView in .Net or even to the Grid controls that are used in VB6. In my opinion, you're really pushing the limits of Access to try to get this sort of functionality. It's like swimming upstream. You'll find that everything you do is going to be fairly difficult and some things just aren't going to be possible.

烟燃烟灭 2024-11-17 11:38:56

对于无法拥有本地 MS Access 查询定义的 ADP 项目,您可以创建一个数据表表单,其中包含多个名为 txt1、txt2、.... txt30 的文本框和名为 lbl1 ... lb30 的标签,此代码将设置该表单.recordsource 并将 textbox.controlsource 和 label.caption 设置为 ADO 记录集对象中的相应字段。此表单将允许您查看 ADO Recordset,类似于 Docmd.OpenQuery 方法。

您必须使用表单的 OpenArgs 属性将 ADO 记录集的 SQL 语句传递到表单。下面的代码显示了调用\打开表单(它像查询一样显示 ADO 记录集)并传递 sql 字符串的 VBA 代码。表单加载事件上的 vba 代码将设置所有控件属性、调整具有数据的列的大小并隐藏 ado 记录集中没有相应字段的列:

'stevekirchner 09/29/2012  Replace Access parameterized query with SQL Server in-line function 
'DoCmd.OpenQuery "qry_SearchMaster_CaseTitles", , acReadOnly

 strsql = "Select * from dbo.UDF__qry_SearchMaster_CaseTitles ('%" & Me.tbxSearchTerm.Value & "%') "

Call Display_ADO_Recordset_from_Datasheet_Form(strsql, "frm_Display_ADO_Recordset_Result1")

'create a non-form module and put the code for the sub Display_ADO_Recordset_from_Datasheet_Form 
'and function fIsLoaded in it (this will allow you make several forms to view ADO recordset and 
'call the code from one place\module):

Sub Display_ADO_Recordset_from_Datasheet_Form(sSQL As String, sFormName As String)

On Error GoTo Error_Handler

    If fIsLoaded(sFormName) Then

        DoCmd.Close acForm, sFormName

    End If

    DoCmd.OpenForm sFormName, acFormDS, , , acFormReadOnly, , OpenArgs:=sSQL

Exit_Sub:

    Exit Sub

Error_Handler:

    MsgBox Err.Description & " Error No: " & CStr(Err.Number)

    Resume Exit_Sub

End Sub

Function fIsLoaded(ByVal strFormname As String) As Boolean

On Error GoTo Error_Handler

    'Returns False if form is not open or True if Open
    If SysCmd(acSysCmdGetObjectState, acForm, strFormname) <> 0 Then

        If Forms(strFormname).CurrentView <> 0 Then
            fIsLoaded = True
        End If

    End If

Exit_Function:

    Exit Function

Error_Handler:

    MsgBox Err.Description & " Error No: " & CStr(Err.Number)

    fIsLoaded = False

    Resume Exit_Function

End Function

'Create a datasheet view form (named frm_Display_ADO_Recordset_Result1) with 30 textboxes and 30
'30 labels named txt1 - txt30 and lbl1 - lbl30 and put this code in the form's module:

Option Compare Database

Private Sub Form_Load()

On Error GoTo Error_Handler

    Dim conn        As ADODB.Connection
    Dim rs          As ADODB.Recordset
    Dim rsClone     As ADODB.Recordset
    Dim strsql      As String

    Set conn = CurrentProject.Connection
    Set rs = New ADODB.Recordset

    strsql = Me.OpenArgs   
    rs.Open strsql, conn, adOpenStatic, adLockOptimistic

    Set rsClone = rs.Clone

    Call Update_Form_Controls("your text goes here", strsql, rsClone)

Exit_Sub:

    rs.Close
    conn.Close
    Set rs = Nothing
    Set conn = Nothing

    Exit Sub

Error_Handler:

    MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly

    Resume Exit_Sub
End Sub

Sub Update_Form_Controls(Header_Label As String, SQL As String, CloneRS As Recordset)

    Dim rsCount As Integer
    Dim i As Integer

On Error GoTo Error_Handler

    Me.Form.Caption = Replace(SQL, "Select * From ", "Display: ")

    rsCount = CloneRS.RecordCount

    If rsCount <= 0 Then

        MsgBox "The Query did not return any data to view", vbOKOnly

        DoCmd.Close
    Else

        Me.Form.SetFocus

        Me.RecordSource = SQL

        i = 1

        Do Until i = 31

            Me("lbl" & i).Caption = ""
            Me("txt" & i).ControlSource = ""
            Me("txt" & i).ColumnHidden = True

            i = i + 1

        Loop

        i = 1

        With CloneRS

        For Each Field In .Fields
        On Error Resume Next

            Me("lbl" & i).Caption = .Fields(i - 1).Name
            Me("txt" & i).ControlSource = .Fields(i - 1).Name
            Me("lbl" & i).Visible = True
            Me("txt" & i).ColumnHidden = False
            Me("txt" & i).SizeToFit

            i = i + 1

            'Debug.Print Field.Name

            On Error GoTo 0
        Next Field
        End With

    End If

Exit_Sub:

    Me.Requery

    Exit Sub


Error_Handler:

    MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly

    Resume Exit_Sub


End Sub

for an ADP Project where you can't have local MS Access query definitions, you can create a datasheet form with multiple textboxs named txt1, txt2,.... txt30 and labels name lbl1 ... lb30 and this code will set the form.recordsource and set the textbox.controlsource and the label.caption to the appropriate fields from an ADO recordset object. This form will allow you to view your ADO Recordset similar to the Docmd.OpenQuery method.

You must pass the ADO recordset's SQL statement to the form using the OpenArgs property of the form. the code below shows the VBA code to call\open the form (which shows the ADO Recordset like a query) and pass your sql string. The vba code on the form's load event will set all the control properties, resize the columns that have data and hide the columns that do not have a corresponding field from the ado recordset:

'stevekirchner 09/29/2012  Replace Access parameterized query with SQL Server in-line function 
'DoCmd.OpenQuery "qry_SearchMaster_CaseTitles", , acReadOnly

 strsql = "Select * from dbo.UDF__qry_SearchMaster_CaseTitles ('%" & Me.tbxSearchTerm.Value & "%') "

Call Display_ADO_Recordset_from_Datasheet_Form(strsql, "frm_Display_ADO_Recordset_Result1")

'create a non-form module and put the code for the sub Display_ADO_Recordset_from_Datasheet_Form 
'and function fIsLoaded in it (this will allow you make several forms to view ADO recordset and 
'call the code from one place\module):

Sub Display_ADO_Recordset_from_Datasheet_Form(sSQL As String, sFormName As String)

On Error GoTo Error_Handler

    If fIsLoaded(sFormName) Then

        DoCmd.Close acForm, sFormName

    End If

    DoCmd.OpenForm sFormName, acFormDS, , , acFormReadOnly, , OpenArgs:=sSQL

Exit_Sub:

    Exit Sub

Error_Handler:

    MsgBox Err.Description & " Error No: " & CStr(Err.Number)

    Resume Exit_Sub

End Sub

Function fIsLoaded(ByVal strFormname As String) As Boolean

On Error GoTo Error_Handler

    'Returns False if form is not open or True if Open
    If SysCmd(acSysCmdGetObjectState, acForm, strFormname) <> 0 Then

        If Forms(strFormname).CurrentView <> 0 Then
            fIsLoaded = True
        End If

    End If

Exit_Function:

    Exit Function

Error_Handler:

    MsgBox Err.Description & " Error No: " & CStr(Err.Number)

    fIsLoaded = False

    Resume Exit_Function

End Function

'Create a datasheet view form (named frm_Display_ADO_Recordset_Result1) with 30 textboxes and 30
'30 labels named txt1 - txt30 and lbl1 - lbl30 and put this code in the form's module:

Option Compare Database

Private Sub Form_Load()

On Error GoTo Error_Handler

    Dim conn        As ADODB.Connection
    Dim rs          As ADODB.Recordset
    Dim rsClone     As ADODB.Recordset
    Dim strsql      As String

    Set conn = CurrentProject.Connection
    Set rs = New ADODB.Recordset

    strsql = Me.OpenArgs   
    rs.Open strsql, conn, adOpenStatic, adLockOptimistic

    Set rsClone = rs.Clone

    Call Update_Form_Controls("your text goes here", strsql, rsClone)

Exit_Sub:

    rs.Close
    conn.Close
    Set rs = Nothing
    Set conn = Nothing

    Exit Sub

Error_Handler:

    MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly

    Resume Exit_Sub
End Sub

Sub Update_Form_Controls(Header_Label As String, SQL As String, CloneRS As Recordset)

    Dim rsCount As Integer
    Dim i As Integer

On Error GoTo Error_Handler

    Me.Form.Caption = Replace(SQL, "Select * From ", "Display: ")

    rsCount = CloneRS.RecordCount

    If rsCount <= 0 Then

        MsgBox "The Query did not return any data to view", vbOKOnly

        DoCmd.Close
    Else

        Me.Form.SetFocus

        Me.RecordSource = SQL

        i = 1

        Do Until i = 31

            Me("lbl" & i).Caption = ""
            Me("txt" & i).ControlSource = ""
            Me("txt" & i).ColumnHidden = True

            i = i + 1

        Loop

        i = 1

        With CloneRS

        For Each Field In .Fields
        On Error Resume Next

            Me("lbl" & i).Caption = .Fields(i - 1).Name
            Me("txt" & i).ControlSource = .Fields(i - 1).Name
            Me("lbl" & i).Visible = True
            Me("txt" & i).ColumnHidden = False
            Me("txt" & i).SizeToFit

            i = i + 1

            'Debug.Print Field.Name

            On Error GoTo 0
        Next Field
        End With

    End If

Exit_Sub:

    Me.Requery

    Exit Sub


Error_Handler:

    MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly

    Resume Exit_Sub


End Sub
弃爱 2024-11-17 11:38:56

我不使用 ADO,而只是使用 VBA,在这种情况下,上述方法是错误的:不需要任何方法来在表单中显示现有记录集,但相反应该在内 表格!

无需创建 MyDataBase.OpenRecordset ("SELECT … [SQL query] ;"),只需将表单的 RecordSource 设置为完全相同的查询定义:

Forms![ MyDisplayForm].RecordSource = "SELECT … [SQL 查询] ;"
Forms![MyDisplayForm].Requery

对我来说这非常有效(Windows 7 pro ×64 / MS Office pro ×64)

I don't use ADO but simply VBA, in which case above approach is wrong: one doesn't need any means for displaying an existing recordset in a form, but should on the contrary define an adequate recordset within the form !

Instead of creating MyDataBase.OpenRecordset ("SELECT … [SQL query] ;"), just set the form's RecordSource to the very same query definition:

Forms![MyDisplayForm].RecordSource = "SELECT … [SQL query] ;"
Forms![MyDisplayForm].Requery

For me this works perfectly (Windows 7 pro ×64 / MS Office pro ×64)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文