Access VBA DCount data type mismatch in criteria expression when data types are obviously the same (both Text) - vba

I'm doing a simple DCount, just looking for how many people have signed up for the same date and time. At the moment I'm just using a single date and a single time to prove the process, then I'll have it loop through all possible dates and times.
Private Sub Get_Singles()
Dim TestDate As String
Dim TestTime As String
AloneCnt = 0
Dinc = 0
Tinc = 0
TestDate = vStartDate
TestTime = "0700"
If (DCount("[ID]", VigilTable, "[fldTime] = " & TestTime) = 1) Then
' "[fldDate] = " & TestDate) & " And
AloneCnt = AloneCnt + 1
End If
End Sub
It works fine for the date (I've moved it to a different line and commented it out so I can focus on the time.).
In the table, fldDate and fldTime are both set for text (shows up as Field Size
= 255 in the properties list) and, as you can see, TestDate and TestTime are both dimmed as String.
And it works if I change the DCount line to:
(DCount("[ID]", VigilTable, "[fldTime] = '0700'")
So where's the error?
Thanks.

The error is, that you must handle date and time as data type Date. So change the data type of the fields to DateTime and:
Dim TestDate As Date
Dim TestTime As Date
Dim AloneCnt As Long
TestDate = vStartDate
TestTime = TimeSerial(7, 0, 0)
If DCount("*", "VigilTable", "[fldTime] = #" & Format(TestTime, "hh\:nn\:ss") & "# And [fldDate] = #" & Format(TestDate, "yyyy\/mm\/dd") & "#") = 1 Then
AloneCnt = AloneCnt + 1
End If

Because you hold all date/time bits as text/string, you should use the text syntax in the criteria as you showed: with quotes (notice the quotes around time string):
(DCount("[ID]", VigilTable, "[fldTime] = '" & TestTime & "'")
You could also keep Date/times in date types like #Gustav's answer.
Update:
You must be doing something wrong; here is my suggested version in VBA window, and it is not Red.

OK, I found the fix after searching several other sites; it was, as I suggested above, a problem of handling variables:
If (DCount("[ID]", VigilTable, "[fldDate]='" & TestDate & "'" & " AND [fldTime] = '" & TestTime & "'") = 1) Then
I always have trouble with those damned single quotes and can never get them in the right place (I'd tried placing single quotes several times but never got them where they are here.); I don't know if the rules are different in different places or I just don't understand the rules or both.
Thanks for all your suggestions; even things that don't work help.

Related

Using VBA in Access how do I use Dcount to count the number of record that contain this formula - DatePart("y", Now)?

I want to go through the records in a table to see how many already contain the Julian date of today. I want it to be a wildcard search because my project numbers will be in this format "16-2101". The Julian date is in the middle (210).
My code is:
Private Sub AddProjectNum_Click()
TwoDigitYear = Mid$(CStr(DatePart("yyyy", Now)), 3, 2)
dayOfyear = DatePart("y", Now)
CountofProjectsToday = DCount("[ProjectNumber]", "Table1", "[ProjectNumber] Like '*dayOfyear*'")
If CountofProjectsToday = 0 Then
Me.ProjectNum.Value = TwoDigitYear & "-" & dayOfyear & 1
Else
Me.ProjectNum.Value = TwoDigitYear & "-" & dayOfyear & CountofProjectsToday + 1
End If
End Sub
If I were to type the actual Julian date (210) in the place of "dayOfyear" the code works. It doesn't like the reference and I don't know how to get around it.
Try
CountofProjectsToday = DCount("[ProjectNumber]", "Table1", "[ProjectNumber] Like '*" & CStr(dayOfyear) & "*'")
' ^^^^^^^^^^^^^^^^^^^^^^^
That converts your VBA dayOfYear into a string (using CStr), then pastes the resulting string into your query (& ... &).

VBA ACCESS Comparing String as they are integer

I am trying to prompt the user to input a range and display all the instruments that are within that range in a subform.
Problem: The upper and lower range is a text field (because some of the range cannot be expressed in integer). As seen in the screenshot, the comparison only compare the first character of the field.
User's input: 5 - 3
On the subform: 36 - 4
It compares 5 and 3 instead of 36
I know vba is doing what it has been told but how can I achieve the result I want?
Here is my code for requering the subform:
Dim Up As Integer
Dim Low As Integer
If Me.Text_L = "" Or IsNull(Me.Text_L) Or Me.Text_U = "" Or IsNull(Me.Text_U) Then
MsgBox ("Please choose a valid range!")
Else
Up = Me.Text_U
Low = Me.Text_L
SQL = SQL_Origin & " WHERE [qry_View_Search].[Upper_Range] <= '" & Up & "' " _
& "AND [qry_View_Search].[Lower_Range] >= '" & Low & "';"
subform_View_Search.Form.RecordSource = SQL
subform_View_Search.Form.Requery
End If
so what i did is made a new column in the query for
IIf(IsNumeric([Upper]), Val([Upper]), Null)
to get all the numeric result.
Then in the vba, I re query the subform as below
SQL = SQL_Origin & " WHERE [qry_View_Search].[Upper] <= cint(Forms![frm_View_Search]![Text_U]) " _
& "AND [qry_View_Search].[Lower] >= cint(Forms![frm_View_Search]![Text_L]);"
Thanks #HansUp !
I have successfully for those cases used Val only:
Value: Val([FieldName])
or:
Value: Val(Nz([FieldName]))

ERR conversion from string to type 'double' is not valid. vb.net

I have a label name annual it display number from table in the database , this number is displayed like this 27.9828272.
I want just the 2 decimals.
I tried
If FrmLogin.CBformState.Text = "User" Then
com1.CommandText = "select * from balance where UserID = '" & FrmLogin.txtUserName.Text & "'"
com1.Connection = cn1
dr2 = com1.ExecuteReader
If dr2.Read Then
Dim b As Double
annual.Text = b
b = Math.Round(b, 2)
FirstName.Text = "'" & LCase(dr2(0)).ToString() & "'"
sick.Text = "'" & LCase(dr2(1)).ToString() & "'"
Maternety.Text = "'" & LCase(dr2(2)).ToString() & "'"
floating.Text = "'" & LCase(dr2(3)).ToString() & "'"
b = "'" & LCase(dr2(4)).ToString() & "'"
Comptime.Text = "'" & LCase(dr2(5)).ToString() & "'"
End If
any help?????????????????????
Label.Text = String.Format("{0:0}", b)
Will take the number (b) and display it in the label rounded to 0 decimal places, if that's what you mean?
Also, get into the habit of using OO principles, not procedural ones (eg insftead of LCase(Blah) do Blah.ToLower(). Then you'll be learning the .Net Framework, not VB.Net helper methods.
Finally, and most importantly, make sure you turn Option Strict on in project settings. It will force you to use the correct data types but it makes learning easier and gives you ~30% performance boost. Do not code with this setting off.
Edit: Some clarification re: String.Format...
Dim Number = 12345.6789
String.Format("{0}", Number) '12345.6789
String.Format("{0:#,##0}", Number) '12,345
String.Format("{0:0.0}", Number) '12345.7
String.Format("{0:0.00}", Number) '12345.68
String.Format("{0:000,000.00}", Number) '012,345.68
'You can also combine multiple variables...
Dim Number 2 = 10
String.Format("{0}: {1}", Number, Number2) '12345.6789: 10
Ok, editing your code...
If dr2.Read Then
Dim MyNumber = 12345.6789
annual.Text = String.Format("{0:0.00}", MyNumber) '' <-- Setting a string variable (`.Text`) with a number fails. Use the formatted string instead...
FirstName.Text = String.Format("'{0}'", dr2(0).ToLower())
sick.Text = String.Format("'{0}'", dr2(1).ToLower())
Maternety.Text = String.Format("'{0}'", dr2(2).ToLower())
floating.Text = String.Format("'{0}'", dr2(3).ToLower())
'Not sure what you're trying to do here but `b` was a Double and you're trying to set it to a string. If you just want the number do. See below.
b = "'" & LCase(dr2(4)).ToString() & "'"
Comptime.Text = "'" & LCase(dr2(5)).ToString() & "'"
End If
If you have a string containing a number ("123.456") like the one from the database, you can convert it to a double as follows:
Dim InputString = "123.456"
Dim MyNumber = Double.Parse(InputString)
If you want to format a number as a string for display, that's when you use the String.Format I mentioned above.
Incidentally, instead of using Dim without an As (which means create a variable and determine what type it is from how I use it), use specific types until you're familiar with them. Then you'll have a better mental/visual representation of what you're trying to store where...
Also, since you're putting quotes around all your variables, it would make sense to factor that out into a different method...
Public Function QuoteLower(Input as String) As String
Return String.Format("'{0}'", Input.ToLower())
End Function
Then Maternety.Text = String.Format("'{0}'", dr2(2).ToLower()) would become Maternety.Text = QuoteLower(dr2(2))
Be Warned: Quoting strings never works reliably. There are too many edge-cases and someone malicious will be able to exploit your code (What happens when someone's surname is O'Connelly or when they type SQL into your form?). Really you want to be using Parameterised Queries or an ORM (Object Relational Mapping) framework. The most common ones in .Net are the Entity Framework and nHibernate. Something to bear in mind for next time.

query in Vba using cdate function with variable

Using the following query in microsoft access sql view works nice and easy with a hard coded date
SELECT Salary.First, Salary.Last,FROM Salary, allowances
WHERE Salary.PayThroughDate = CDate("2014-05-06") AND Salary.SSN = allowances.SSN
but embedding this query in Vba using a variable instead of a hard coded date is another business. It is just not working:
Dim ddate As Variant
Dim getDay As Integer
Dim getMonth As Integer
Dim getYear As Integer
getDay = Day(Me.DTPicker2.Value)
getMonth = Month(Me.DTPicker2.Value)
getYear = Year(Me.DTPicker2.Value)
ddate = getDay & "/" & getMonth & "/" & getYear
ddate = Format(ddate, "dd/mm/yyyy")
query1 = "SELECT Salary.First, Salary.Last FROM Salary, allowances WHERE Salary.PayThroughDate = " & CDate(ddate) & " AND Salary.SSN =
allowances.SSN
Any ideas in this Vba Sql mix? Am I missing single or double quotes?
When you send the SQL directly to JET and not running it from the normal user-interface of MS Access, you will need to make the date-format in the American format. I have had this problem a lot long time ago, but solved it by using this function to format my date in to text, the way that JET expects it to be:
Function SQLDate(varDate As Date) As String
'---------------------------------------------------------------------------------------
'Purpose Formats a date in the american way so that it can be used in
' SQL (by the JET-engine)
'Accepts varDate - the date that should be converted to text
'Returns The date converted to text, in american format with both the day and
' the month using 2 characters. (01 is january)
'---------------------------------------------------------------------------------------
'Changelog
'HANY 20100407: Stopped using the FORMAT-function for the date-value, as I found some
' cases where the format did not return the date as specified.
'---------------------------------------------------------------------------------------
'SQLDate = "#" & Format$(varDate, "mm\/dd\/yyyy") & "#"
SQLDate = "#" & Format(Month(varDate), "00") & "/" & Format(Day(varDate), "00") & "/" & Format(Year(varDate), "0000") & "#"
End Function
In your example above, you now add the date like this & SQLDate(CDate(ddate)) & instead of & CDate(ddate) &
The equivilant query is:
query1 = "SELECT Salary.First, Salary.Last
FROM Salary, allowances
WHERE (Salary.PayThroughDate =Cdate(" & ddate & ") )
AND (Salary.SSN = allowances.SSN)"
The problem you had is that when you constructed the sql string, the cdate value was converted into a string value first. It was just the same as
WHERE (Salary.PayThroughDate =" & format(ddate,"general date") & ")
If you do the cdate conversion later it works. Another almost equivilant query is
...
WHERE Salary.PayThroughDate =#" & ddate & "#
...
Both Cdate and the # tags take a string date, and convert to a date type (using slightly different rules). Since a date type is actually stored as the integer part of a double, you can also do:
WHERE Salary.PayThroughDate =cdbl(#" & ddate & "#)
or
WHERE Salary.PayThroughDate =clng(#" & ddate & "#)
or
WHERE Salary.PayThroughDate =" & clng(cdate(ddate) & "
--the number will be converted into a string to be part of the sql string, but numbers work correctly in SQL: they don't need to have # tags or conversion functions to make them work.
but you started out with a date value:
v =Me.DTPicker2.Value
so you can convert that directly to a number without converting it to a string first:
d = clng(Me.DTPicker2.Value)
...
WHERE (Salary.PayThroughDate = " & d & ")
which is the fastest and least error prone of handling dates in Access/VBA, but comes undone when you start working with SQL server, which stores dates differently.
Also, I see that you correctly used ISO date format when constructing your test example, but switched to American date format when constructing a string from the date value. That was a mistake. To avoid errors and 'evil date guessing' in SQL, you should stick to the ISO format:
v =Me.DTPicker2.Value
sdate = format(v,"yyyy-mm-dd")

How to run query, automate using VBA Macro and Excel, make "loading" feature while reconciling?

I am building a reconciliation tool via VBA that automates queries from my oracle database and a worksheet. When I run the query I want the user to input what ITEM (in this case pipeline) to query (the worksheet has many items) and the end/start dates. I am having trouble figuring out the following:
1) It is querying - if the value is NULL, how may I tell it to print out "DATA NOT AVAILABLE"
2) How can I clear up the old output from pipeline A, when I am querying pipeline B?
3) My dates are saved as strings in Oracle - how can I convert that to date?
Thank you!
Here is what I have so far:
Option Explicit
Option Base 1
Dim cnnObject As ADODB.Connection
Dim rsObject As ADODB.Recordset
Dim strGPOTSConnectionString As String
Dim startDate As Date
Dim endDate As Date
Dim strPipelineName As String
Dim strQuery As String
Sub ClickButton2()
Debug.Print ("Button has been clicked")
Dim Pipeline As String
Dim DateStart As Date
Dim DateEnd As Date
Pipeline = InputBox("Enter PipeLine", "My Application", "Default Value")
DateStart = InputBox("Enter Start Date", "My Application", DateTime.Date)
DateEnd = InputBox("Enter End Date", "My Application", DateTime.Date + 1)
Pipeline = Range("B1").Value
DateStart = Range("B2").Value
DateEnd = Range("B3").Value
strQuery = "select pipelineflow.lciid lciid, ldate, volume, capacity, status, " & _
"pipeline, station, stationname, drn, state, county, owneroperator, companycode, " & _
"pointcode, pottypeind, flowdirection, pointname, facilitytype, pointlocator, " & _
"pidgridcode from pipelineflow, pipelineproperties " & _
"where pipelineflow.lciid = piplineproperties.lciid " & _
"and pipelineflow.audit_active = 1 " & _
"and pipelineproperties.audit_active =1 " & _
"and pipelineflow.ldate >= '" & Format(DateStart, "dd-MMM-yyyy") & "' and pipelineflow.ldate < '" & Format(DateEnd, "dd-MMM-yyyy") & "' " & _
"and pipelineflow.ldate >= '" & DateStart & "' and pipelineflow.ldate < '" & DateEnd & "' " & _
"and pipelineproperties.pipeline = '" & Pipeline & "' "
Call PullZaiNetData(strQuery)
Call TieOut
End Sub
Sub PullZaiNetData2(ByVal strQry As String)
Set cnnObject = New ADODB.Connection
Set rsObject = New ADODB.Recordset
strGPOTSConnectionString = "DRIVER={Microsoft ODBC for Oracle}; SERVER=hhh; PWD=hhhh; UID=hhh"
cnnObject.Open strGPOTSConnectionString
rsObject.Open strQry, cnnObject, adOpenStatic
Worksheets("ZaiNet Data").Cells(1, 1).CopyFromRecordset rsObject
rsObject.Close
cnnObject.Close
Set rsObject = Nothing
Set cnnObject = Nothing
End Sub
Sub TieOut()
End Sub
Since you changed your questions, I'll add another answer.
1) It is querying - if the value is NULL, how may I tell it to print out "DATA NOT AVAILABLE"
Which value? I suspect that you mean when the query returns no records. To check this, test for rsObject.RecordCount = 0:
Dim ws As Worksheet
Set ws = Worksheets("ZaiNet Data")
ws.UsedRange.Clear '' remove results of previous query if any
If rsObject.RecordCount = 0 Then
ws.Cells(1, 1) = "DATA NOT AVAILABLE"
Else
ws.Cells(1, 1).CopyFromRecordset rsObject
End If
You can also test for one or both of rsObject.BOF or rsObject.EOF being true ("Beginning Of File" or "End Of File" respectively).
When developing things in VBA, especially when using new features that I'm unfamiliar with, I do lots of tests that output things to the Immediate Window. To help with this, I use the following little routine:
Sub Say(s as String)
Debug.Print s
End Sub
It makes it a little easier to generate testing output that typing "Debug.Print" all the time (even slightly easier than typing "Debug.P" + Enter using Intellisense).
So when you open your recordset, show the record count after it:
rsObject.Open strQry, cnnObject, adOpenStatic
Say rsObject.RecordCount & " records"
Do something like this any time you want to verify a value.
Later on, if you want to capture your debugging statements in a text file, you just need to change the operation of the Say() routine.
2) How can I clear up the old output from pipeline A, when I am querying pipeline B?
As shown in context above:
ws.UsedRange.Clear '' remove results of previous query if any
3) My dates are saved as strings in Oracle - how can I convert that to date?
You don't technically need to convert the resulting date strings to date values, you may find that just by putting them in a cell, Excel will treat them as date values.
You just need to make sure that the user's dates get converted to the format that the database is expecting.
Your query string as it stands above still shows two lines incorporating the user's dates. The one that uses Format() to convert them to "dd-MMM-yyyy" format is the one you want to keep. Delete the other line, making sure your string concatenating syntax is still correct.
To actually convert the date string to a date value though, you would use the CDate() function:
Sub DateTest()
Dim sDate As String
Dim dDate As Date
sDate = "09-Jul-2009"
dDate = CDate(sDate)
Say "sDate = " & sDate
Say "dDate = " & dDate
dDate = dDate + 1
Say "dDate = " & dDate
End Sub
Immediate Window output:
sDate = 09-Jul-2009
dDate = 7/9/2009
dDate = 7/10/2009
We can verify that it converted the string to a date value because it shows up in the default date format for my machine, and responds to date math (adding 1 day).
Answers to previous questions (paraphrased):
1) "how to make sure end date is after start date":
Valid date values are floating point numbers, so DateEnd should be >= DateStart. The whole number part is the number of days since 1900-01-01. The fractional part is the current time of day (eg 12 noon = 0.5).
2) "use fancy calendar entry controls for dates"
Look at the controls available under the Insert> Object menu (in Excel 2003 and earlier - it's in 2007 too, but in a different place). One of them is a Calendar control. Double-clicking it in the Objects list will insert it into the current cell and put the sheet into Design Mode. Right click the control and choose Properties. Type a cell address into the LinkedCell field. Then click the "Exit Design Mode" button from the little toolbar that should have popped up. Now when you select a date on the control, it will show the value in the cell you linked it to.
Similarly there is a drop down list control that you can use to select your pipeline types.
3) "why am I getting an error on DateEnd = Range("B3").Value?"
The DateEnd error is probably due to a missing or invalid value in the cell you specified, as I asked in my comment.
What version of Excel are you doing this in? Excel 2003