Runtime error 3061 too few parameters

David McAfee 20 Reputation points
2023-09-02T16:47:14.8633333+00:00

I'm exporting data from a joined table in MS Access to an Excel spreadsheet. When I use a SQL query (without criteria), it works fine but when I try to put a criteria in the code i get the run time error message. The following is the SQL query code:

SELECT CompsT.CompsID, CompsT.InspectionID, CompsT.Component, CompsT.[Location Grouping], CompsT.[Component Description], CompsT.[Make/Model/Type], CompsT.COD, CompsT.[Dimension Type], CompsT.Length, CompsT.LUnit, CompsT.Wide, CompsT.WUnit, CompsT.High, CompsT.HUnit, CompsT.Depth, CompsT.DUnit, CompsT.[Quantity Type], CompsT.[Quantity Unit], CompsT.Quantity, CompsT.[Work Complete], InspectionsT.[Damage#]

FROM InspectionsT INNER JOIN CompsT ON InspectionsT.[InspectionID] = CompsT.[InspectionID]

WHERE (((InspectionsT.[Damage#])=[Enter a Damage #]));

I think the problem stems from the dialogue requesting the user to input a Damage #. I need to create either a message box with the Damage # input field or perhaps a separate form that passes the post query data to the VBA code below. I'm not having much success with that so any help would be appreciated.

The following is my VBA code:

Private Sub Command0_Click()

    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim sSQL As String
    Dim SourceFile, DestinationFile
    
    Set db = CurrentDb
    SourceFile = "C:\SITemplates\BridgeTemplate.xlsx" & _
    DestinationFile = "C:\SITemplates\Export\BridgeTemplate.xlsx"
    FileCopy "C:\SITemplates\BridgeTemplate.xlsx", "C:\SITemplates\Export\BridgeTemplate.xlsx"
    
    sSQL = "CompsTExportQ"
    
    'Troubleshooting
    'Debug.Print ssql 'Copy/Paste and Test in QBE
    
    Set rs = db.OpenRecordset(sSQL, dbOpenSnapshot)
    
    Call ExportRecordset2XLS(rs, "C:\SITemplates\Export\BridgeTemplate.xlsx", "Input", 1, 6, False, False, False)
    
    rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub
Access Development
Access Development
Access: A family of Microsoft relational database management systems designed for ease of use.Development: The process of researching, productizing, and refining new or existing technologies.
859 questions
0 comments No comments
{count} votes

Accepted answer
  1. Ken Sheridan 2,756 Reputation points
    2023-09-05T21:27:16.32+00:00
    As I said earlier you will need to evaluate the querydef object's Parameters collection before establishing the recordset.  The relevant lines, in addition to the necessary object variable declarations, in the example I posted are:
    
        Set dbs = CurrentDb
        
        Set qdf = dbs.QueryDefs(strQuery)
        
        For Each prm In qdf.Parameters
            prm = Eval(prm.Name)
        Next prm
        
        Set rst = qdf.OpenRecordset
    
    Each parameter obviously must be exposed to the code, so cannot be a simple prompt like [Enter damage number:].  It should be a reference to a control in an open form, and of syntax such as Forms!NameOfFormGoesHere!NameOfControlGoesHere.
    
    
    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. David McAfee 20 Reputation points
    2023-09-08T13:39:52.9666667+00:00

    Ken,

    I used your prm code changes which got me further down the road. But I still could not select from a field (InspectionsID) to call specific records for the export to excel.

    I came up with a solution, which won't really help anyone else in this forum and is not ideal. It will require me to create multiple subforms (13) which I am willing to do, but wish there was another way. I changed my SQL query to the following:

    SELECT CompsT.Component, CompsT.[Location Grouping], CompsT.[Component Description], CompsT.[Make/Model/Type], CompsT.COD, CompsT.[Dimension Type], CompsT.Length, CompsT.LUnit, CompsT.Wide, CompsT.WUnit, CompsT.High, CompsT.HUnit, CompsT.Depth, CompsT.DUnit, CompsT.[Quantity Type], CompsT.[Quantity Unit], CompsT.Quantity, CompsT.[Work Complete]

    FROM CompsT

    WHERE (((CompsT.InspectionID)=[Forms]![BridgesF]![CompsTsubform]![InspectionID]));

    CompsTsubform (was) a shared form among 13 different types of inspections including BridgesF. Now I have to create 12 other subforms like "roads", "buildings", "bridges", etc. UNLESS there is some way to replace BridgesF with something more universal and I know of nothing that will work. [Forms]![BridgesF]![CompsTsubform]![InspectionID]

    I'm willing to create said number of forms however since this method doesn't require user input but operates off the current InspectionID in the open form.

    Sorry for the long reply, but at least I have a solution to what I wanted to accomplish.

    Thanks again for your help!

    0 comments No comments

  2. Ken Sheridan 2,756 Reputation points
    2023-09-02T17:58:43.6733333+00:00
    To establish a recordset from a query which takes one or more parameters, you firstly need to evaluate the members of the querydef object's Parameters collection, and then call the OpenRecordset method of the querydef object:
    
    The following is an example which does this when creating a text file for use as the data source for a Word mail merge.  The parameter will need to be a reference to a control in a currently open dialogue form:
    
    Public Function WordMerge(strQuery As String, _
                            strDataDoc As String, _
                            strMergeFile As String, _
                            Optional blnSuppressBlankLines As Boolean = True)
                            
        ' Merges data from query into Word document
        ' Accepts:  Name of Access query providing data for merge - String.
        '           Path to Word data file created from query - String.
        '           Path to Word document to be used for merge - String.
        '           Optional setting to suppress or show blank lines
        '           if data missing ( Default = True ) - Boolean
        
        Dim dbs As DAO.Database
        Dim rst As DAO.Recordset
        Dim qdf As DAO.QueryDef
        Dim prm As DAO.Parameter
        Dim wApp As Object
        Dim wDoc As Object
        Dim wActiveDoc As Word.Document
        
        Set dbs = CurrentDb
        
        Set qdf = dbs.QueryDefs(strQuery)
        
        For Each prm In qdf.Parameters
            prm = Eval(prm.Name)
        Next prm
        
        Set rst = qdf.OpenRecordset
        
        ' exit function if recordset is empty
        If rst.EOF Then
            MsgBox "No data to merge.", vbInformation, "Mail Merge"
            GoTo Exit_Here
        End If
        
        Set wApp = GetWordApp()
        
        ' close datasource document if open in Word
        For Each wDoc In wApp.Documents
            If wDoc.Path & "\" & wDoc.Name = strDataDoc Then
                wDoc.Close wdDoNotSaveChanges
            End If
        Next wDoc
        
        ' delete current Word data file.
        ' ignore error if file doesn't exist
        On Error Resume Next
        Kill strDataDoc
        On Error GoTo 0
        
        ' create new Word data file
        ExportToText strQuery, strDataDoc, ",", True
        
        'open word merge document
        Set wDoc = wApp.Documents.Open(strMergeFile)
            
        ' execute merge
        With wDoc.MailMerge
            .OpenDataSource strDataDoc
            .SuppressBlankLines = blnSuppressBlankLines
            .Destination = wdSendToNewDocument
            .Execute
        End With
        Set wActiveDoc = wApp.ActiveDocument
        
        ' show document in maximized window
        ShowWord wApp, wDoc, wActiveDoc
        
    Exit_Here:
        Set rst = Nothing
        Set dbs = Nothing
        
    End Function
    
    
    
    0 comments No comments

  3. David McAfee 20 Reputation points
    2023-09-05T13:19:59.5933333+00:00

    Ken, thanks for your reply. It's taken some time for me to analyze your code since I am not well versed in VBA. My code was adapted from Dan Pineault's "export to excel" code for what I am trying to accomplish. I have managed to get it to work so that it exports the recordset from the SQL query but I want to add user input for a specific damage number that selects only the records with that number (instead of all records). It is a union query. When I put a criteria that asks the user for a specific damage number, I get an error message "Too few parameters. Expected <number>. (Error 3061)". When I run the query by itself, it pulls up the correct records but when I call it with a command button through the code. That is the error message I get.