OpenRecordSet in a function with Query Parameters - ms-access

I am trying to create a function that returns the number of rows (records) in a query. This function will be used in an MS Access macro. Essentially: if numrecords([QUERY NAME]) > 0, then do something. The following query works great if [QUERY NAME] doesn't have any parameters.
Function numrecords(sRs As String) As Long
Dim dbDb As Database
Dim rsRs As Recordset
Set rsRs = dbDb.OpenRecordset(sRs, dbOpenSnapshot)
numrecords = rsRs.RecordCount
I now have a form that allows users to set a date to subset the outcoming data; thus I am introducing parameters to the mix. Enough googling tells me I need to use QueryDefs. The following code 'should' work as it has the green check mark of approval for similar questions on Stack Overflow but I keep getting the Error 3219 ' Invalid Operation'. The error occurs at:
Set rsRs = qdf.OpenRecordset(dbOpenSnapshot)
Function numrecords(sRs As String) As Long
Dim dbDb As Database
Dim rsRs As Recordset
Dim qdf As DAO.QueryDef
Dim prm As DAO.Parameter
Set dbDb = CurrentDb
Set qdf = dbDb.QueryDefs(sRs)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next
Set rsRs = qdf.OpenRecordset(dbOpenSnapshot) ' ERROR OCCURS HERE!
numrecords = rsRs.RecordCount
Lastly, I am trying to run this function on a query, let's call it query 2 that is built off another query (query 1) that takes in a parameter from a form. The SQL of query 1 is:
PARAMETERS [Forms]![Frm_EIM_Submisions]![Last_Data_Entry_Date] DATETIME;
SELECT SampleID.Matrix
, ​SampleID.Location
, SampleID.SampleID
, SampleID.DateSampled AS [DATE Sampled]
, LU_Analytes.CASnum
, LU_Analytes.[Analyte code]
, LU_Analytes.Analyte
, LU_Units.[Units code]
, LU_Units.Units
, LU_Methods.[Method code]
, LU_Methods.Method
FROM Location
INNER JOIN (SampleID
INNER JOIN (LU_Units
INNER JOIN (LU_Methods
INNER JOIN (LU_Analytes
INNER JOIN Data ON LU_Analytes.[Analyte code] = Data.[Analyte code]) ON LU_Methods.[Method code] = Data.[Method code]) ON LU_Units.[Units code] = Data.[Units code]) ON SampleID.SampleID = Data.[Sample ID]) ON Location.Location = SampleID.Location
WHERE ((SampleID.DateSampled)>[Forms]![Frm_EIM_Submisions]![Last_Data_Entry_Date])```
Any input would be much appreciated.

First, find out what value you feed:
For Each prm In qdf.Parameters
Debug.Print prm.Name, Eval(prm.Name)
' prm.Value = Eval(prm.Name)
Next
Next, try to feed that value manually:
For Each prm In qdf.Parameters
' Set realistic date value (mm/dd/yyyy):
prm.Value = #04/01/2021#
Next
That should give you a hint what to correct.

Related

Runtime Error 3061 too few parameters expected 1 DAO declarations

I have been looking for some code that creates a calendar year and will take data from a table and place it in the corresponding date on the calendar. I found some code online (from an older version of access) that pretty much fit the bill, with some modifications it does exactly what I need it to do. Originally, the code pulled data from one table and it was set up to run on the current year. I use two queries, qr_SafetyCal and qr_SafetyCal2, to refine data from the one table. The first query prioritizes the data and eliminates multiple events on any given day. The second query uses the results from the first and specifies the year in the query criteria.
The code works flawlessly as long as I set the year criteria in the qr_SafetyCal2 and specify the first day, ex. 1/1/2017 (datStart) in the underlying code of the calendar year I want displayed.
After getting the code squared away I created a pop up form the user to select the year for the report but when I run the report I get the following error, Runtime Error 3061 too few parameters expected 1.
From what I have been able to research, I believe I changed the dynamic of the code when I referenced the form in the query criteria that the DAO Recordset Used.
As I understand it, the criteria in the query is not passed to the rs and therefore needs to be declared in the code. What I can't figure out is how to declare the variables in the code through reference to the form. I hope that makes some sense to somebody, long explanation but hard to describe something you don't understand.
Below is all the code and you will see some things I've rem'd out that I have tried but did not work. Any help would be greatly appreciated. I apologize ahead of time if the code is not formatted correctly.
Option Compare Database
Option Explicit
Private m_strCTLLabel As String
Private m_strCTLLabelHeader As String
Private colCalendarDates As Collection
Function getCalendarData() As Boolean
Dim rs As DAO.Recordset
Dim strDate As String
Dim strCode As String
Dim i As Integer
'Dim qdf As DAO.QueryDef
'Set qdf = CurrentDb.QueryDef("qr_SafetyCal2")
'qdf.Parameters("[Forms]![fr_SafetyCal]![cboYear]") = [Forms]![fr_SafetyCal]![cboYear]
'Set rs = qdf.OpenRecordset("qr_SafetyCal2", dbOpenDynaset)
Set rs = CurrentDb.OpenRecordset("qr_SafetyCal2", dbOpenDynaset)
Set colCalendarDates = New Collection
With rs
If (Not .BOF) Or (Not .EOF) Then
.MoveLast
.MoveFirst
End If
If .RecordCount > 0 Then
For i = 1 To .RecordCount
strDate = .Fields("Date")
strCode = .Fields("ShortName")
colCalendarDates.Add strCode, strDate
.MoveNext
Next i
End If
.Close
End With
'Return of dates and data collection form qr_SafetyCal2
Set rs = Nothing
End Function
Public Sub loadReportYearCalendar(theReport As Report)
Dim i As Integer
Dim datStart As Date
Dim rptControl As Report
m_strCTLLabel = "labelCELL"
m_strCTLLabelHeader = "labelDAY"
'Load calendar data for the specified year into the collection
Call getCalendarData
With theReport
'Get the first month of the specified year
datStart = "1/1/2017" '"1/1/" & Year(Date), "1/1/" & Forms!
[fr_SafetyCal]![cboYear], Forms![fr_SafetyCal]![txtCalYear]
'Add the specified year to the report's label
.Controls("labelCalendarHeaderLine2").Caption = Year(datStart) & "
iCalendar"
For i = 1 To 12
'Set pointer to subreport control hosting the mini-calendar
Set rptControl = .Controls("childCalendarMonth" & i).Report
'Run procedure to populate control with it's respective year
Call loadReportCalendar(rptControl, datStart)
'Reset and obtain first day of the following month
datStart = DateAdd("m", 1, datStart)
Next i
End With
'Clean up
Set colCalendarDates = Nothing
Set rptControl = Nothing
End Sub
Public Sub loadReportCalendar(theReport As Report, Optional StartDate As
Date, Optional theHeaderColor As Variant)
Dim i As Integer
Dim intCalDay As Integer
Dim datStartDate As Date
Dim intWeekDay As Integer
datStartDate = StartDate
intWeekDay = Weekday(datStartDate)
With theReport
.Controls("labelMONTH").Caption = Format(StartDate, "mmmm")
'Change the day label's backcolor if necessary
If Not (IsMissing(theHeaderColor)) Then
For i = 1 To 7
.Controls("labelDayHeader" & i).BackColor = theHeaderColor
Next
End If
For i = 1 To 42
With .Controls(m_strCTLLabel & i)
If (i >= intWeekDay) And (Month(StartDate) =
Month(datStartDate)) Then
If (datStartDate = Date) Then
.BackColor = 14277081
End If
On Error Resume Next
Dim strCaption As String
Dim strKey As String
strKey = datStartDate
strCaption = ""
strCaption = colCalendarDates.Item(strKey)
colCalendarDates.Remove strKey
'Set back color to grean on days in the past that have
no corresponding event
If (datStartDate < Date) And (strCaption = vbNullString) Then
.Caption = Day(datStartDate)
.Bold = False
.BackColor = vbGreen
.ForeColor = vbWhite
.Heavy = True
'Do not set a back color for days in the future
ElseIf (datStartDate > Date) And (strCaption = vbNullString) Then
.Caption = Day(datStartDate)
.Bold = False
'Set the corresponding labels and formats for each specified event
Else
.Caption = strCaption
.Bold = True
Select Case strCaption
Case "FA"
.BackColor = vbYellow
.ForeColor = 0
.LeftMargin = 0
.TextAlign = 2
Case "FAM"
.BackColor = vbYellow
.ForeColor = 0
.LeftMargin = 0
.TextAlign = 2
.Heavy = True
Case "LTA"
.BackColor = vbRed
.ForeColor = vbWhite
.LeftMargin = 0
.TextAlign = 2
Case "MED"
.BackColor = vbRed
.ForeColor = vbWhite
.LeftMargin = 0
.TextAlign = 2
End Select
End If
datStartDate = DateAdd("d", 1, datStartDate)
Else
.Caption = ""
End If
End With
Next i
End With
End Sub
Here is SQL for the two queries, the first is qr_SafetyCal and the second is qr_SafetyCal2:
SELECT tb_CaseLog.Date, Max(tb_Treatment.Priority) AS MaxOfPriority,
Count(tb_Treatment.TreatmentID) AS CountOfTreatmentID
FROM tb_Treatment INNER JOIN tb_CaseLog ON tb_Treatment.TreatmentID =
tb_CaseLog.Treatment
GROUP BY tb_CaseLog.Date;
SELECT qr_SafetyCal.Date, tb_Treatment.ShortName,
qr_SafetyCal.CountOfTreatmentID AS [Count], Year([Date]) AS CalYear
FROM qr_SafetyCal INNER JOIN tb_Treatment ON qr_SafetyCal.MaxOfPriority =
tb_Treatment.Priority;
No need to reference QueryDef.
Open the recordset object with filtered dataset by referencing the combobox like:
Set rs = CurrentDb.OpenRecordset("SELECT * FROM qr_SafetyCal2 WHERE CalYear=" & [Forms]![fr_SafetyCal]![cboYear], dbOpenDynaset)
or if the code is behind the form:
Set rs = CurrentDb.OpenRecordset("SELECT * FROM qr_SafetyCal2 WHERE CalYear=" & Me.[cboYear], dbOpenDynaset)
Both examples assume the field is a number type.
If there is no field in query with the year value, it can be extracted from date value field in the VBA construct:
Set rs = CurrentDb.OpenRecordset("SELECT * FROM qr_SafetyCal2 WHERE Year([YourFieldnameHere])=" & [Forms]![fr_SafetyCal]![cboYear], dbOpenDynaset)
Code for setting datStart variable:
'Get the first month of the specified year
datStart = "1/1/" & Forms![fr_SafetyCal].[cboYear]

combine values from multiple records based on common ID

I've tried many different methods to join the following from;
StockCode Finished_Goods_Codes
100137 2105109
100137 2105110
100137 2105111
To;
StockCode Finished_Goods_Codes
100137 2105109, 2105110, 2105111
My Current Code is as follows;
Public Function ListQuery()
Dim curr As Database
Dim rs As Recordset
Dim SQLCmd As String
Dim productList As String
Set curr = CurrentDb()
SQLCmd = "SELECT Finished_Goods_Codes FROM TEMP_codes WHERE [StockCode] = """ & StockCode & """"
Set rs = curr.OpenRecordset(SQLCmd)
If Not rs.EOF Then
rs.MoveFirst
End If
Do While Not rs.EOF
productList = productList & rs(0) & ", "
rs.MoveNext
Loop
ListQuery = productList
End Function
My Query currently runs the following;
SELECT TEMP_codes.StockCode, ListQuery([Products]) AS [List of Products]
FROM TEMP_codes
GROUP BY TEMP_codes.StockCode;
Could you please help as i'm really stuck on this.
Many Thanks in advance.
Based on the answer given for the question Microsoft Access condense multiple lines in a table, here are the steps:
1 Create the following function
Public Function GetList(SQL As String _
, Optional ColumnDelimeter As String = ", " _
, Optional RowDelimeter As String = vbCrLf) As String
'PURPOSE: to return a combined string from the passed query
'ARGS:
' 1. SQL is a valid Select statement
' 2. ColumnDelimiter is the character(s) that separate each column
' 3. RowDelimiter is the character(s) that separate each row
'RETURN VAL: Concatenated list
'DESIGN NOTES:
'EXAMPLE CALL: =GetList("Select Col1,Col2 From Table1 Where Table1.Key = " & OuterTable.Key)
Const PROCNAME = "GetList"
Const adClipString = 2
Dim oConn As ADODB.Connection
Dim oRS As ADODB.Recordset
Dim sResult As String
On Error GoTo ProcErr
Set oConn = CurrentProject.Connection
Set oRS = oConn.Execute(SQL)
sResult = oRS.GetString(adClipString, -1, ColumnDelimeter, RowDelimeter)
If Right(sResult, Len(RowDelimeter)) = RowDelimeter Then
sResult = Mid$(sResult, 1, Len(sResult) - Len(RowDelimeter))
End If
GetList = sResult
oRS.Close
oConn.Close
CleanUp:
Set oRS = Nothing
Set oConn = Nothing
Exit Function
ProcErr:
' insert error handler
Resume CleanUp
End Function
2 Add a Reference for the function in the Module (Tools -> References). Add the Reference Micorosft ActiveX Data Objects 6.1 Library (or the most recent one available).
3 Save the Module with a name different from the function name, say Concatenation
4 Run the following query
SELECT T.StockCode, GetList("Select Finished_Goods_Codes From TEMP_codes As T1 Where T1.StockCode = " & [T].[StockCode],"",", ") AS Finished_Goods_Codes
FROM TEMP_codes AS T
GROUP BY T.StockCode;

Dynamic Query Criteria

I'm trying to make a Microsoft Access query depend on a value in another form's textbox.
This is the criteria, as it is now. Basically, any date between April 1st 2014, and March 31st 2015. This works well.
>=#2014-04-01# And <#2015-04-01#
I'd like to have a textbox with the year (with the current example 2014), and make the query criteria (2014, 2014+1) depend on this value.
I've tried to split the above syntax, then concatenate in the criteria, as such:
">=#" & "2014" & "-04-01# And <#" & "2015" & "-04-01#"
And I get an error "Data types in the criterion expression are incompatible".
1. Is it possible to concatenate in the query criteria?
I have also tried the SQL CONCAT(string1,string2,string3,..), to no avail.
If this is possible, then I guess I can use [Forms]![Form1].[Textbox1] and ([Forms]![Form1].[Textbox1] + 1) to replace the years.
If this is not possible...
2. Is there a better way to make the query criteria dynamic?
I tried to make the following solution work by creating a module with similar code:
Private m_varQueryParam As Variant
Public Function SetQueryParam(ByVal sValue as Variant)
m_varQueryParam = sValue
End Function
Public Function GetQueryParam() As Variant
GetQueryParam = m_varQueryParam
End Function
Query:
SELECT * FROM tblYourTable WHERE [FilterField] = GetQueryParam()
The VBA Code to launch the query will look like this.
SetQueryParam "your value here"
DoCmd.OpenQuery "qryYourQueryHere"
But I simply do not understand how to get this to work.
EDIT: I created a simple access database, to try to get this to work.
Textbox1, default value =Date()
bSave, button
tDateInfo, table: date (date/time), info (text) with random dates and info.
Query1:
SELECT tDateInfo.date, tDateInfo.info
FROM tDateInfo
WHERE (((tDateInfo.date)=GetQueryParam()));
Here's the form's vba code
Option Compare Database
Private Sub bSave_Click()
sValue = Me.TextBox1.Value
SetQueryParam (sValue)
End Sub
Here's the modules vba code
Option Compare Database
Option Explicit
'is this necessary?
Private m_varQueryParam As Variant
Public Function SetQueryParam(ByVal sValue As Variant)
m_varQueryParam = sValue
End Function
Public Function GetQueryParam() As Variant
GetQueryParam = m_varQueryParam
End Function
And the query criteria is GetQueryParam()
Thank you for your help.
Handling parameters and form fields is a little tricky with VBA. I created a simple table similar to yours as follows:
CREATE TABLE DateCalc (
ID AutoNumber,
FilterField DateTime
)
The following code will return your desired results:
Sub testthis()
Dim db As dao.database
Set db = CurrentDb ' use current database
Dim qd As dao.QueryDef
Set qd = db.CreateQueryDef("") ' create anaonymous querydef
' the SQL statement correctly concatenates the parameter (Useyear) and mm/dd strings
qd.sql = "SELECT * FROM DateCalc WHERE [FilterField] >= [UseYear]" & "-04-01 And [FilterField] < [UseYear]+1" & "-04-01"
qd!UseYear = Forms!DateCalc!txtYear ' set the value of se year from the Form WHICH MUST BE OPEN
' AND the TetBox filled with the year you desire - 2014 for this example.
Dim rs As dao.recordSet
Set rs = qd.OpenRecordset
MsgBox "ID=" & rs(0) & ", Date=" & rs(1)
End Sub
NEW VERSION
Sorry, there were a couple of date formatting problems with the first solution that the following code resolves. There are a number of other reasons for the error, so be sure the FormName is "DateCalc" and the TextBox is named "txtYear".
You should be able to generalize the following code for all your queries (do those actually work?). I pass the TableName in now as an example:
Sub DateFilter(TableName As String)
Dim db As dao.database
Set db = CurrentDb ' use current database
Dim qd As dao.QueryDef
Set qd = db.CreateQueryDef("") ' create anaonymous querydef
' the SQL statement correctly concatenates the parameter (Useyear) and mm/dd strings
Dim UseYear As Integer
UseYear = Forms!DateCalc!txtYear
Dim BegDate As Date
BegDate = CDate(UseYear & "-04-01")
Dim EndDate As Date
EndDate = CDate((UseYear + 1) & "-04-01")
qd.sql = "SELECT * FROM " & TableName & " WHERE [FilterField] >= [UseBegDate] And [FilterField] < [UseEndDate]"
qd!UseBegDate = BegDate
qd!UseEndDate = EndDate
Dim rs As dao.recordSet
Set rs = qd.OpenRecordset
Do While Not rs.EOF
MsgBox "ID=" & rs(0) & ", Date=" & rs(1)
rs.MoveNext
Loop
End Sub
I think I found a solution.
The following code defines the SQL as I require it, and changes the SQL for the Access query.
It's not ideal, because it requires me to rewrite all the SQL for the queries, but it works.
Sub ChangeQuery()
Dim Year, sqlTwo, StartDate, EndDate As String
Year = Me.txtYear.Value
StartDate = "4/1/" & Year
EndDate = "4/1/" & (Year + 1)
sqlTwo = "SELECT DateCalc.ID, DateCalc.FilterField FROM DateCalc WHERE (((DateCalc.FilterField)>=#" & StartDate & "# And DateCalc.FilterField<#" & EndDate & "#));"
tbTest.Value = sqlTwo
Dim oDB As Database
Dim oQuery As QueryDef
Set oDB = CurrentDb
Set oQuery = oDB.QueryDefs("Query1")
oQuery.SQL = sqlTwo
Set oQuery = Nothing
Set oDB = Nothing
End Sub
Private Sub Button_Click()
ChangeQuery
End Sub

How to search a field in a table in Access

Using VBA, how can I search for a text string, for example "CHIR", in a table called "ServiceYES", in the field "Service".
After that, I would like to save the neighboring field for all the rows that "CHIR" exists in the table "ServicesYES". The "ServiceYES" table is below:
I basically, want to find all the "CHIR" in "Service" column and then save the names which are on the left of the CHIR, eg "FRANKL_L", "SANTIA_D" as an array.
Thanks for all your help in advance.
Start by creating a SELECT query.
SELECT Code_Perso
FROM ServicesYES
WHERE Service = 'CHIR';
Use SELECT DISTINCT Code_Perso if you want only the unique values.
Add ORDER BY Code_Perso if you care to have them sorted alphabetically.
Once you have a satisfactory query, open a DAO recordset based on that query, and loop through the Code_Perso values it returns.
You don't need to load them directly into your final array. It might be easier to add them to a comma-separated string. Afterward you can use the Split() function (assuming you have Access version >= 2000) to create your array.
Here's sample code to get you started. It's mostly standard boiler-plate, but it might actually work ... once you give it "yourquery".
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strItems As String
Dim varItems As Variant
Set db = CurrentDb
Set rs = db.OpenRecordset("yourquery", dbOpenSnapshot)
With rs
Do While Not .EOF
strItems = strItems & "," & !Code_Perso
.MoveNext
Loop
.Close
End With
If Len(strItems) > 0 Then
' discard leading comma '
strItems = Mid(strItems, 2)
varItems = Split(strItems, ",")
Else
MsgBox "Oops. No matching rows found."
End If
Set rs = Nothing
Set db = Nothing
I tested this and it seems to work. This function will pull all records where ServiceYes='CHIR' and dump the Code_Person value into an array which it will return:
Function x() As String()
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset( _
"Select * from ServiceYES where Service='CHIR'")
Dim Arr() As String
Dim i As Integer
While rst.EOF = False
ReDim Preserve Arr(i)
Arr(i) = rst.Fields("Code_Person")
i = i + 1
rst.MoveNext
Wend
x = Arr
End Function
Sample Usage:
Debug.Print x()(0)
Paolo,
Here is something I threw together in a few minutes. You can add it to the VBA editor in a module. It uses a trick to get the RecordCount property to behave properly. As for returing the array, you can update the function and create a calling routine. If you need that bit of code, just post a comment.
Thanks!
Option Compare Database
Function QueryServiceYES()
Dim db As Database
Dim saveItems() As String
Set db = CurrentDb
Dim rs As DAO.Recordset
Set rs = db.OpenRecordset("SELECT Code_Perso, Service, Favorites " & _
"FROM ServiceYES " & _
"WHERE Service = 'CHIR'")
'bug in recordset, MoveFirst, then MoveLast forces correct invalid "RecordCount"
rs.MoveLast
rs.MoveFirst
ReDim Preserve saveItems(rs.RecordCount) As String
For i = 0 To rs.RecordCount - 1
saveItems(i) = rs.Fields("Code_Perso")
rs.MoveNext
Next i
'print them out
For i = 0 To UBound(saveItems) - 1
Debug.Print saveItems(i)
Next i
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Function

'Undefined function' when using DAO QueryDef in VBA

I'm assigning an Access 2007 query to a QueryDef in Excel VBA. My query calls a user-defined function, because it performs a calculation on the results of evaluating a field with a regular expression. I'm using a QueryDef because I'm collecting values in a UserForm and want to pass them to the query as parameters.
When I run my VBA code, I get an error: "Run-time error '3085': Undefined function 'regexFunc' in expression."
This question suggests that the problem is that DAO is unable to call Access UDFs from Excel, so I copied my UDF into the Excel VBA module, but I still get the error.
Access query:
select field1 from dataTable where regexFunc(field1)=[regexVal]
Here's the Excel VBA code:
'QueryDef function
Sub makeQueryDef (str As String)
Dim qdf As QueryDef
Dim db As Database
Set db = OpenDatabase(DBpath)
Set qdf = db.QueryDefs("paramQuery")
qdf.Parameters("regexVal") = (str="test")
doSomething qdf
End Sub
'Regex function copied from Access VBA module to Excel VBA module
Function regexFunc(str As String) As Boolean
Dim re As RegExp
Dim matches As MatchCollection
regexFunc = False
Set re = New RegExp
re.Pattern = "\reg[ex](pattern)?"
Set matches = re.Execute(str)
If matches.Count <> 0 Then
regexFunc = True
End If
End Function
This is how I would do it... just tested it and it works fine with my UDF:
One thing - are you required to not use New Access.Application?
Sub GetMyDataWithUDF()
Dim oApp As Access.Application
Dim qd As QueryDef
sFileName = "C:\Users\AUser\Desktop\adatabase.mdb"
Set oApp = New Access.Application
oApp.OpenCurrentDatabase (sFileName)
Set qd = oApp.CurrentDb.QueryDefs("Query1")
If oApp.DCount("*", "MSysObjects", "Name='dataTableResults'") > 0 Then _
oApp.CurrentDb.TableDefs.Delete "dataTableResults"
qd.Parameters("avalue") = "4"
qd.Execute
oApp.Quit
Set oApp = Nothing
Dim oRS As ADODB.Recordset
sConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sFileName & ";User Id=admin;Password=;"
Set oRS = New ADODB.Recordset
oRS.Open "SELECT * FROM dataTableResults", sConn
Sheet1.Cells.Clear
Sheet1.Range("A1").CopyFromRecordset oRS
oRS.Close
Set oRS = Nothing
End Sub
Note that I made my underlying query a SELECT ... INTO query that creates a table called 'dataTableResults'
This is my query (QueryDef) in Access:
SELECT dataTable.Field1, dataTable.Field2 INTO dataTableResults
FROM dataTable
WHERE mysqr(dataTable.Field1)=[avalue];
My MS-Access DB has a function called "mysqr", which gets used in the SQL above.
Function mysqr(Num)
mysqr = Num * Num
End Function
The table "dataTable" I'm querying against is just a list of numbers, so if my parameter "avalue" is "16", then I get the row "4" back. If I enter "4" (as in my code), I get "2" back.
I've solved this. Here's how I did it.
First I change the query into a recordset and pass it to my filtering function:
function filteredQDF(qdf As QueryDef, boolVal As Boolean) As Variant
Dim rs As Recordset
Dim rows_rs As Variant
Dim rs_new As Recordset
Dim filtered As Variant
Set rs = qdf.OpenRecordset
rs.MoveLast
rs.MoveFirst
rows_rs = rs.GetRows(rs.RecordCount)
rows_rs = Application.WorksheetFunction.Transpose(rows_rs)
filtered = filterFunction(rows_rs, boolVal)
filteredQDF = filtered
End Function
And here's the filtering function, which creates a new array, populates it with rows that pass the UDF's boolean check, and returns it:
Function filterFunction(sourceArray As Variant, checkValue As Boolean) As Variant
Dim targetArray As Variant
Dim cols As Long
Dim targetRows As Long
Dim targetCursor As Long
'get # of columns from source array
cols = UBound(sourceArray, 2)
'count total number of target rows because 2D arrays cannot Redim Preserve
'checking sourceArray(r,2) because that's the criterion column
targetRows = 0
For r = 1 To UBound(sourceArray, 1)
If myUDF(CStr(sourceArray(r, 2))) = checkValue Then
targetRows = targetRows + 1
End If
Next
'set minimum target rows to 1 so that function will always return an array
If targetRows = 0 Then
targetRows = 1
End If
'redim target array with target row count
ReDim targetArray(targetRows, cols)
'set cursor for assigning values to target array
targetCursor = 0
'iterate through sourceArray, collecting UDF-verified rows and updating target cursor to populate target array
For r = 1 To UBound(sourceArray, 1)
If myUDF(CStr(sourceArray(r, 2))) = checkValue Then
For c = 1 To cols
targetArray(targetCursor, c - 1) = sourceArray(r, c)
Next
targetCursor = targetCursor + 1
End If
Next
'assign return value
filterFunction = targetArray
End Function