DLookup 3075 Missing Operator Around NZ? - ms-access

This is my code:
Private Sub Form_Current()
Set rs = CurrentDb.OpenRecordset("Sites", dbOpenDynaset, dbSeeChanges)
rs.Requery
rs.MoveFirst
If Nz(Me.Site_ID.Value) > 0 Then
Me.H2OBillingIDlbl.Caption = DLookup("H2OBillingIDNum", "Sites", "H2OBillingIDNum = " & Me.txtHotelID)
Else
Me.H2OBillingIDlbl.Caption = ""
End If
End Sub
The DLookup line is throwing the error.
Me.txtHotelID box is a text entry box on the form and is used to enter numbers only.
The H2OBillingIDNum field in the recordset is Long.
I have tried putting brackets around H2OBillingIDNum; .Value at the end of H2OBillingIDNum and Me.txtHotelID alternatively and combined; entering the data as a string in which case I get data mismatch error.
I don't believe I can use a SQL query because it is a text entry field, but if I'm wrong, I'll happily take the information as I've never heard of a SQL query like that and it's a faster and more accurate method of pulling the data.
I'm out of ideas. Any suggestions? Is it the NZ? Is there a better way of writing that? Should that not be included at all? If it helps, this is a DAO db.

The error must be that Me.txtHotelID is empty, therefore your DLookup call is incomplete
DLookup("foo", "bar", "myValue = ")
gives Runtime error 3075: Syntax error (missing operator) in 'myValue = '
Here is a guide on how to debug problems like this.
Take the code apart (one command per line), and use intermediate variables. Their values can be seen in break mode by hovering the mouse on the variable name, or in the Watch window.
Recommended reading: Debugging VBA Code
If you use DLookup, there is no need at all for a recordset, so I have removed it.
Run (or step through) this code, and the error will become clear:
Private Sub Form_Current()
Dim SiteID As Long
Dim HotelID As Long
Dim strCaption As String
SiteID = Nz(Me.Site_ID.Value, 0)
If SiteID > 0 Then
' Intentionally without Nz(), will throw error
HotelID = Me.txtHotelID
' Nz() will be needed here too!
strCaption = DLookup("H2OBillingIDNum", "Sites", "H2OBillingIDNum = " & HotelID)
Else
strCaption = ""
End If
Me.H2OBillingIDlbl.Caption = strCaption
End Sub

You can reduce it to:
Private Sub Form_Current()
Dim rs As DAO.Recordset
Dim SQL As String
Dim Caption As String
If Nz(Me!Site_ID.Value, 0) > 0 Then
SQL = "Select Top 1 H2OBillingIDNum From Sites Where H2OBillingIDNum = " & Nz(Me!txtHotelID.Value, 0) & ""
Set rs = CurrentDb.OpenRecordset("SQL", dbOpenDynaset, dbSeeChanges)
Caption = rs!Fields(0).Value
End If
Me!H2OBillingIDlbl.Caption = Caption
Set rs = Nothing
End Sub
As you can see, it doesn't make much sense, as you look up H2OBillingIDNum which you already have as Me!txtHotelID.Value, so it probably should read:
SQL = "Select Top 1 SomeTextField From Sites Where H2OBillingIDNum = ...

Sorry misunderstod you
I don't really see the purpose, but one thing is sure - if your Dlookup returns a Null you get ant error. You cannot load the caption with null.
An NZ around the Dlookup is needed. But i don't know if it is possible that the Dlookup doesn't find anything

Related

Change WHERE clause using VBA based on form control

So, being newish to access and only using VBA in excel up until a few months ago there are quite a few commands I have absolutely 0 idea on how to use/correctly write syntax.
Problem: I have a saved query (qry_ExcelExport) which at the moment is just:
SELECT '*' FROM tbl_Contacts
What I want to do is use VBA to add/change the WHERE clause based on a user form control.
Something like:
If me.txt_Flag = "DP Delegate" then 'WHERE [DP-DEL] = True' (or = -1)
Elseif me.txt_Flag = "DP Sponsor" then 'WHERE [DP-SPON] = True' (or = -1)
And so on. (I understand that the syntax above is 100% incorrect, that's just what I'm hoping to achieve)
Using the power of the internet I managed to come across this code:
‘To change the Where clause in a saved query
Dim qdf as QueryDef
Dim db as Database
Set db = CurrentDB
Set qdf = db.QueryDefs("YourQueryName")
qdf.SQL = ReplaceWhereClause(qdf.SQL, strYourNewWhereClause)
set qdf = Nothing
set db = Nothing
Public Function ReplaceWhereClause(strSQL As Variant, strNewWHERE As Variant)
On Error GoTo Error_Handler
‘This subroutine accepts a valid SQL string and Where clause, and
‘returns the same SQL statement with the original Where clause (if any)
‘replaced by the passed in Where clause.
‘
‘INPUT:
‘ strSQL valid SQL string to change
‘OUTPUT:
‘ strNewWHERE New WHERE clause to insert into SQL statement
‘
Dim strSELECT As String, strWhere As String
Dim strOrderBy As String, strGROUPBY As String, strHAVING As String
Call ParseSQL(strSQL, strSELECT, strWhere, strOrderBy, _
strGROUPBY, strHAVING)
ReplaceWhereClause = strSELECT &""& strNewWHERE &""_
& strGROUPBY &""& strHAVING &""& strOrderBy
Exit_Procedure:
Exit Function
Error_Handler:
MsgBox (Err.Number & ": " & Err.Description)
Resume Exit_Procedure
End Function
And that first line... that very first line "To change the Where clause in a saved query" indicates that this is EXACLY what I need.
But, there is no walk-through or step-by-step beginners guide to understanding this code, the syntax or more importantly how to tie it in with a form control and it is not one I've ever used or heard of before.
EDIT: The saved query qry_ExcelExport is used in a funtion to export data
Call exportTable("qry_ExportExcel")
Where I'm calling
Public Sub exportTable(tName As String)
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, tName, saveFileAs, True
End Sub
I need the ability to modify the where so that when I export it includes that clause as at the moment there is no WHERE clause so exports just take all the data.
It is normally neither needed nor practical to modify saved queries for filtering.
What you do instead is apply the filter to the form:
If me.txt_Flag = "DP Delegate" then
strFilter = "[DP-DEL] = True"
Elseif me.txt_Flag = "DP Sponsor" then
strFilter = "[DP-SPON] = True"
Else
strFilter = ""
End If
Me.Filter = strFilter
Me.FilterOn = (strFilter <> "")
Or if you need the query for something else, you can apply the filter to the query.
Set rs = DB.OpenRecordset("Select * From MySavedQuery Where " & strFilter)
Edit
If the query is used for export, it is actually one of few situations, where modifying the query is useful.
If the query is as simple as in your question, you can simply set the full SQL:
strSql = "SELECT * FROM tbl_Contacts WHERE " & strFilter
db.QueryDefs("qry_ExportExcel").SQL = strSql
Call exportTable("qry_ExportExcel")
or if the base query is more complex, use two queries: a constant one (qry_ExportExcel_Base) and a dynamic one (qry_ExportExcel)
strSql = "SELECT * FROM qry_ExportExcel_Base WHERE " & strFilter
etc. as above

Me.Requery appears to be doing no action on form

I have searched and have found a lot of information on using requery on a subform, but I can't seem to find anything that indicates attempting to requery the active form with a new recordset.
I have a form based on a query. I am using an unbound text box to capture the address which needs to be searched then changing the sql statement in the query to locate the records then attempting to use me.requery to load the new results.
The code is updating the sql statement, but the form is not requerying with the new record results. My code is below.
I am fairly new to access and VBA, and appreciate any wisdom you may have. Also, is there ANYTHING that I could be doing in other code which would cause this to fail?
Private Sub Command51_Click()
Dim d As DAO.Database
Dim q As DAO.QueryDef
Dim Addy As String
Dim Search As String
Set d = CurrentDb()
Set q = d.QueryDefs("SQL_Search")
If IsNull(Me!Addy) Then
MsgBox ("Please select a valid address from the list and try again.")
GoTo CleanUp
Else: End If
Addy = Me!Addy
Search = "select * from dbo_ECNumberVerify Where (((dbo_ECNumberVerify.invalidrecord)=False) AND ((dbo_ECNumberVerify.updated)=False) AND ((dbo_ECNumberVerify.Locations) Like '*" & Addy & "*'));"
'Send SQL SP execute command.
q.SQL = Search
Me.Requery
CleanUp:
Set q = Nothing
Set db = Nothing
End Sub
In your example you have a query, but the query is never set or attached to the forms record source in "any way". So the “query” acts independent from the form data source.
You can simply stuff the sql directly into the forms reocrdsouce like this:
Me.RecordSource = Search
(so you don’t need all of your existing code, nor do you need the queryDef.
And when you set the forms SQL directly as per above, then a requery is done automatic for you. So the code required will look like this:
Dim strSearch As String
If IsNull(Me.Addy) Then
MsgBox ("Please select a valid address fromthe list and try again.")
Exit Sub
End If
strSearch = "select * from dbo_ECNumberVerify WHERE " & _
"(invalidrecord = False) AND (updated = False) AND " _
"(Locations Like '*" & Addy & "*')"
Me.RecordSource = strSearch
So you don't need much code, and you really don't need to use + declare the querydef at all.

Get Record based on form textbox value

I am trying to get a record based on the value contain within the textbox on a form. i.e i type in the information into the textbox and other values associated with that value are returned to other textbox on the form.
I thought this would be easy but can't seem to get it to work.
Currently I was trying
Dim rst As DAO.Recordset
Dim SQL As String
Dim SQL2 As String
SQL = "SELECT tblmytbl.[IDCODE]"
"FROM tblmytbl " & _
"WHERE (((tblmytbl.[IDCODE]) = forms!myform!mybox.value "
Set db = CurrentDb
Set rst = db.OpenRecordset(SQL)
If Not ((rst.BOF = True) And (rst.EOF = True)) Then
Forms!myform!Text102 = rst.Fields("[Name]")
Forms!myform!Text103 = rst.Fields("[Surname]")enter code here
Note: The search information is alphanumeric and i have tried without the .value
Any help would be appreciated.
Thanks
The SQL you send to the server can't access the form. However, you can concatenate the value into the string that you send like:
" WHERE (((mytable.myfield) = '" & FixQuotes(Forms!myform!mybox.value) & "') " & _
Note, you may need to defend yourself against SQL injection, a simple (but not complete) defense would be something like:
Public Function FixQuotes(input as string) As String
FixQuotes = Replace(input,"'","''")
End Function
EDIT:
Based on your updated code, there's quite a number of changes you need to make. Beyond my statement above, the .OpenRecordset only applies to full tables, you can't use it with a SELECT statement. Instead, you have to instantiate a QueryDef. On top of that, you try to reference fields you didn't include in the query. Also, you can simplify the expression Forms!myform! to Me (which could help if you want to reuse the code somewhere else) So your code should look something like this:
Dim db as Database 'always dim everything, you should use Option Explicit'
Dim rst as Recordset 'DAO is the default anyway'
Dim qdf as QueryDef 'this object is required for queries'
Set db = CurrentDb
'prepare single-use query, to return the values you're going to use
'as mentioned before, the query doesn't have access to the form
'we can use Me since it references the form'
' use TOP 1 since you only expect 1 record'
Set qdf = db.CreateQueryDef("","SELECT TOP 1 Name,Surname FROM tblmytbl " & _
"WHERE IDCODE = '" & FixQuotes(Me.mybox.value) & "';")
Set rst = qdf.OpenRecordset(DbOpenForwardOnly)
'forwardonly since you only care about the first record'
If Not rst.EOF Then 'ForwardOnly has to start at the first record'
Me.Text102.Value = rst!Name
Me.Text103.Value = rst!Surname
'I highly suggest giving these boxes better names'
Else
'no record found'
End if
rst.Close
qdf.Close
db.Close 'close these objects, it can sometimes cause memory leaks otherwise'

Access subform, how to resize columns to best fit?

I have a form with a subform. This subform displays the results of a query that is created dynamically (user enters criteria, I build the SQL, then update the querydef and display). Problem is since the columns are dynamic the width of the columns isn't working out, some are cutting off text.
Is there a way to programmatically loop through the columns (or do the same without loop) and set them all to bestfit width after the query is refreshed?
EDIT: Here is what my code looks like now:
CurrentDb.QueryDefs("SearchResults").sql = sql
CurrentDb.QueryDefs.Refresh
Dim qdf1 As DAO.QueryDef
Dim fld1 As DAO.Field
Set qdf1 = CurrentDb.QueryDefs("SearchResults")
For i = 0 To qdf1.Fields.Count - 1
Set fld1 = qdf1.Fields(i)
fld1.CreateProperty "ColumnWidth", dbInteger
fld1.Properties("ColumnWidth") = -2 'Throws error
Set fld1 = Nothing
Next i
Me.Child20.SourceObject = "Query.SearchResults"
You can set column widths like so:
Sub SetColumnWidth()
Dim qdf1 As DAO.QueryDef
Dim fld1 As DAO.Field
Set qdf1 = CurrentDb.QueryDefs("query3")
For i = 0 To qdf1.Fields.Count - 1
Set fld1 = qdf1.Fields(i)
fld1.CreateProperty "ColumnWidth", dbInteger
'very narrow indeed
'fld1.Properties("ColumnWidth") = 200
'Or -2 : Sizes the column to fit the visible text
'but it is not quite as useful as it would seem
fld1.Properties("ColumnWidth") = -2
Set fld1 = Nothing
Next i
End Sub
See also http://support.microsoft.com/kb/210427
So I've run into this same problem just now. I was fortunate enough to have half of my queries work and the other half not. I've been using this code:
Sub QueryData(strSQL As String)
Dim qryData As DAO.QueryDef
Dim intcount As Integer
Set qryData = CurrentDb.QueryDefs("DataQuery")
qryData.SQL = strSQL
qryData.CreateProperty "ColumnWidth", dbInteger
qryData.Fields(0).Properties("ColumnWidth") = 5760
DoCmd.OpenQuery "DataQuery", , acReadOnly
End Sub
Which generated the error on half of the queries I tried to run with it. I traced it back to this odd, but simple truth: Columns built using an Alias (i.e. all formula columns and expressions) kick out this error. If the column is just a straight data pull, it works fine. If the column is, however, a formulated display.... it spits the no columwidth property error.
Hopefully this'll help someone out! I know this questions about a year old, but it was the first result Google found for me on the topic.
I was able to make this grab the open forms and autofit the selected subform within that form. If you have multiple forms/subforms you would just call the function with the new names using the lines of code at the end of the function and pasting them in your program.
Public Function AutoSizeSbCtrl(frmNameTar, sbCtrlNameTar)
For Each frm In Forms
frmName = frm.Name
If frmName = frmNameTar Then
For Each frmCtrl In frm.Controls
frmCtrlName = frmCtrl.Name
If frmCtrlName = sbCtrlNameTar Then
For Each sbfrmCtrl In frmCtrl.Controls
sbfrmCtrlName = sbfrmCtrl.Name
On Error Resume Next
sbfrmCtrl.ColumnWidth = -2
On Error GoTo 0
Next sbfrmCtrl
End If
Next frmCtrl
End If
Next frm
' paste the lines below in your code where you want it to trigger (i did on an update)
'frmNameTar= "frm12345" ' where frm12345 is the name of the form the subform is in
'sbCtrlNameTar="sbfrm67890" ' where sbfrm67890 is the name of the subform you are trying to autofit
'auSize = AutoSizeSbCtrl(frmNameTar, sbCtrlNameTar)
'end paste
End Function

ACCESS/VBA: can't get Dcount to work correctly

here is a portion of code I'm using to enable/disable a button (which allows to create a new revision) depending on the result.
If the dcount returns 0, it means the next revision doesn't exist yet (and thus can be created)
if the dcount returns 1, it means the next revision already exists (and thus the button will be disabled)
DCount("index_rit", "t_données_rit", "[RITn°]=" & Me.RITn°.Value & " AND [Revision]=" & Me.Revision.Value + 1)
My problem is that for some reason, even if a record corresponds to the values entered in the dcount, it still returns 0.
I tried both with ant without the [] for the fields.
I also tried using * instead of index_rit...
What did I get wrong ?
got it.
it was a format problem:
RITn° is of the form xx-xx, so I had to put it like this:
"[RITn°]='" & Me.RITn°.Value & "' AND [Revision]=" & Me.Revision.Value + 1)
(added the single quotes)
First thing is that the DCount (and other ‘D’ functions) are generally considered to be a bit of a performance drag. Try replacing it with this quick function. You just pass it a query and it will return the record count
Private Function GetRecordCount(strSearch as String) as Long
Dim rst As ADODB.Recordset
Dim RecCount As Long
Set rst = New ADODB.Recordset
With rst
.ActiveConnection = CodeProject.Connection
.CursorType = adOpenForwardOnly
.LockType = adLockReadOnly
.Source = strSearch
.Open Options:=adCmdText
if .EOF = true then
RecCount=0
else
RecCount=.Collect(0)
End If
.Close
End With
GetRecordCount = RecCount
Set rst = Nothing
End Function
This uses ADO but could/should use DAO if you are just using access tables but that is another question for another time!