Updating Record in a table VBA Access - vba

I am trying to update the record in an Access table using the below code and get an error that the data type is mismatch in criteria expression :
If Not (Me.frmdamagesub.Form.Recordset.EOF And Me.frmdamagesub.Form.Recordset.BOF) Then
With Me.frmdamagesub.Form.Recordset
Me.txtquantity = .Fields("Quantity")
Me.txtquantity.Tag = .Fields("Quantity")
Me.cmdedit.Caption = " Update"
CurrentDb.Execute " UPDATE damaged_card " & _
" SET Quantity='" & Me.txtquantity & "'" & _
" WHERE Quantity=" & Me.txtquantity.Tag
End With
End If

Since you are comparing to texts, try it like this:
CurrentDb.Execute " UPDATE damaged_card " & _
" SET Quantity='" & Me.txtquantity & "'" & _
" WHERE Quantity='" & Me.txtquantity.Tag & "'"
Notice the added '-s.
Debugging
If it still fails, check the values in runtime and try running the SQL manually and see if it works that way. To extract the statement in runtime, have VBA output it into the Immediate window (ctrl+g) like this:
debug.print " UPDATE damaged_card " & _
" SET Quantity='" & Me.txtquantity & "'" & _
" WHERE Quantity='" & Me.txtquantity.Tag & "'"
Do this before you try to execute it.
Then you can go to Access, create a new query, change the view to SQL view, and paste the produced SQL statement. Before executing it with Run, it is worth taking a look at the affected rows by clicking the View button and selecting Datasheet View.
This displays all the rows from the target table that will be affected by the change. If no rows are displayed, that means no row fits your criteria, and nothing will be changed.
To be honest, your query doesn't make much sense, as it says: "update the Quantity to 5 where the Quantity is 5". You might want to rethink you where clause.
Refine your query in Access, and once it works, paste it back to the VBA code.

Related

Finding/Marking Duplicate Values using SQL

I am trying to update a column in my table to specify if the record is a duplicate or not. To do this I added a field called 'DuplicateRecord'.
I can't use the query wizard in access as the duplicate option in this only allows for 10 fields to be checked as a duplicate and my table has more than 10 fields.
The below code works for me:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID] " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However this code just runs off one field and I need it to run off all fields in the table (there are about 15 fields).
As a test I tried using two fields to see if I could get this working using the following:
Call Module1.RunSQL("UPDATE myTable " & _
"SET myTable.DuplicateRecord = TRUE " & _
"WHERE myTable.[CompanyID] AND myTable.[Product] IN (" & _
"SELECT * FROM " & _
"(SELECT myTable.[CompanyID], myTable.[Product], COUNT(*) " & _
"FROM myTable " & _
"GROUP BY myTable.[CompanyID], myTable.[Product] " & _
"HAVING COUNT(*) > 1 ) T1 ) ")
However I get an error message saying "Run-time error '3306' You have written a subquery that can return more than one field without using the EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
I've tried googling the error but I can't seem to solve it as I don't fully understand it.
Does anyone know how I can apply the logic of testing for duplicates? Is there an easier way to do this then how I am currently trying? I will need to do this for the full record (15 fields), so I am a bit conscious that the way I am currently attempting this might not be the best fit.

MS Access DLookUp malfunction

I have a very weird problem occurring in MS Access which I can't seem to figure out.
Summary: I have a table from Sharepoint that is connected to my MS Access database and a Person table in my Ms Access db. I pull the information row by row from the Sharepoint table and add it to Person Table.
However, before adding the new data I must check if that specific Person already exists in my table. I check for 'Lastname', 'Firstname' and 'Date created' using DLookup function.
Here where everything goes side ways. DLookup returns me a NULL for almost half of the records that already exist in Person Table. After playing a lot with the condition in DLookup statement my conclusion is that there is a problem with the 'Date created' parameter, yet I have tried using "#" and CDate and even Format, nothing works.
I can't share the data, since it's sensitive, however the syntax for DLookup I'm using is the following:
sqlStr = "LastName=" & Chr(34) & rs![Last Name] & Chr(34)
& " AND FirstName=" & Chr(34) & rs![First Name] & Chr(34)
& " AND DateLastModified=" & Format(dateVar, "dd/mm/yyyy")
DLookup("LastName", "table_Person", sqlStr)
P.S: I have tried DCount, same thing happens. DCount returns 0 yet I know for a fact the record is there.
To build criterias BuildCriteria is your Friend.
Sub TestBuildCriteria()
Dim strCriteria As String
strCriteria = BuildCriteria("OrderDate", dbDate, [Date created])
MsgBox strCriteria
End Sub
Sub YourCode()
sqlStr = BuildCriteria("LastName", dbText, "=" & rs![Last Name]) & _
" AND " & BuildCriteria("FirstName", dbText, "=" & rs![First Name]) & _
" AND " & BuildCriteria("DateLastModified", dbDate, "=" & dateVar)
End Sub
This echoes the proper formated date. Also useful for other data-type. E.g. it escapes Quotation Marks in Strings. Read Custom Filters using BuildCriteria() too.
But there is a far easier alternative.
Create a unique composite index on LastName, FirstName and DateLastModified in the the table. Now you can't insert a duplicate as it has to be unique. If you try you will receive an error msg. Be aware of transaction rollbacks (e.g. Multiple inserts, one fails by key violation -> all actions will be reverted due transaction rollback if you use db.Execute SQL, dbFailOnError).
To check for dates use:
"DateLastModified=#" & FormatDateTime(dateVar, vbShortDate) & "#"
if dateVar can be null you need something like this:
FormatDateTime(Nz(dateVar,CDate("1/1/2000")), vbShortDate)
And of course that just checks the date part. If your dateVar can also have a time part then you have to use
DateValue(dateVar)
Your syntax is not correct. You should put square brackets around field names as is pointed out in documented examples at MSDN
sqlStr = "[LastName]=" & Chr(34) & rs![Last Name] & Chr(34)
& " AND [FirstName]=" & Chr(34) & rs![First Name] & Chr(34)
& " AND [DateLastModified]=#" & Format(dateVar, "dd/mm/yyyy") & "#"
DLookup("[LastName]", "table_Person", sqlStr)
In this situation, my advice would be to simplify the criteria part of the DLOOKUP/DCOUNT until you get something that works, and only then start to make the criteria more complex. I call this 'sanity checking'.
Date/Time criteria often cause problems, so first check that you can make it work without the Date part of the criteria.
For example, in your case, check that this works.
Use the Debug Window (Ctril+G) to test this:
? DCount("*", "table_Person", "LastName=" & Chr(34) & rs![Last Name] & Chr(34))
Then try:
? DCount("*", "table_Person", "LastName=" & Chr(34) & rs![Last Name] & Chr(34) & " AND FirstName=" & Chr(34) & rs![First Name] & Chr(34))
Once you have that working, add in the Date criteria.
Building the criteria up in stages like this, allows you to confirm which part is actually causing the problem.
I'm in the UK, and so I have my dates displayed in UK format - 'DD/MM/YYYY'.
However, when specifying a date criteria for a DLOOKUP/DCOUNT, I always have to format the date to US format. I've often used a simple function to swap the digits into the correct order for the criteria:
Function HashDate(dD As Date) As String
HashDate = "#" & Format$(dD, "MM/DD/YYYY") & "#"
End Function
In the the Debug Window:
? Date
09/03/2018
? HashDate(Date)
#03/09/2018#

Searching a table where the field doesnt exist - Access VBA

I am a data consultant who migrates data I am sent into our system. I have written code that compares the contents of my table against what has been put into oracle, as an extra test. The tables are a little convoluted due to how they relate to each other. But essentially here is my question:
When I look to match two field values and the field doesnt exist I get a parameter pop up box. I want to only run the code if the field exists.
I have tried many things, wrapping an if statement around it but I always get the parameter box, can anyone help there must be an easier way to do this!
If Not DoCmd.OpenQuery("SELECT TOP 1" & MatchValues!FieldName & " FROM " &
MatchValues!ORACLE_TABLE_NAME) Then
MsgBox "moomins"
' strSQL = "INSERT INTO 002_TableValueErrors(ORACLE_TABLE_NAME,TRANSFORM_TABLE_NAME,FIELD_NAME,ORACLE_FIELD_VALUE,TRANSFORM_FIELD_VALUE) "
' strSQL = strSQL & " VALUES (" & MatchValues!ORACLE_TABLE_NAME & "," & MatchValues!TRANSFORM_TABLE_NAME & "," & MatchValues!FieldName & ",'ORACLE: NOT FOUND','ORACLE: NOT FOUND')"
End If
If you deal with Oracle: Have you tried to check if the field exists by querying ALL_TAB_COLUMNS in Oracle?
"Select count(*) from ALL_TAB_COLUMNS where table_name = " & MatchValues!ORACLE_TABLE_NAME & " and COLUMN_NAME = " & MatchValues!FieldName
(Untestet cause currently I have no Oracle Instance available)

Updating a field dependent on a date range in Access with VisualBasic and SQL

A friend and I have been trying for hours with little progress to a get a piece of code right for an invoicing system we're designing as a project.
We are trying to update the field InvoiceNo to a value (worked out earlier in the VisualBasic code), where the CustomerNo is the is a specific value and the FinishDate is between two dates. At first I was trying to use TO_DATE but then we realized that wasn't the same in the SQL that Access uses (after much searching).
This has been the simple statement I've been using to just test and try to get something working to then translate into VisualBasic and put in our variables. It's a little easier to read so I thought I'd provide it.
UPDATE tblJob SET tblJob.InvoiceNo = '8' WHERE tblJob.CustomerNo = '1' AND (tblJob.FinishDate BETWEEN cdate(format('08/09/2013', '##/##/####')) AND cdate(format('03/10/2013', '##/##/####')));
I have a feeling after looking at a few examples that our date is meant to be without an forward slashes. So I tried that and it wasn't working either.
Here's the VisualBasic code that has come out of all of this, it's exactly the same but using some variables rather than our set values that I've been using for testing.
DoCmd.RunSQL ("UPDATE tblJob SET tblJob.InvoiceNo = '" & newInvoiceNo & "' WHERE tblJob.CustomerNo = '" & VbCustNo & "' AND (tblJob.FinishDate BETWEEN cdate(format('" & Forms![frmMainMenu][txtFirstDate] & "', '##/##/####')) AND cdate(format('" & Forms![frmMainmenu][txtEndDate] & "', '##/##/####')));")
We had a look at: Convert a string to a date in Access and it helped us realize that it was cdate(format()) rather than TO_DATE as it is in Oracle. But we just can't seem to get it to run properly, any help would be much appreciated.
If you will be running the query from within an Access application session, you can let the db engine use the Access expression service to grab the values from the text boxes on your form.
Dim db As DAO.Database
Dim strUpdate As String
strUpdate = "UPDATE tblJob" & vbCrLf & _
"SET InvoiceNo = '" & newInvoiceNo & "'" & vbCrLf & _
"WHERE CustomerNo = '" & VbCustNo & "'" & vbCrLf & _
"AND FinishDate BETWEEN Forms!frmMainMenu!txtFirstDate AND Forms!frmMainmenu!txtEndDate;"
Debug.Print strUpdate
Set db = CurrentDb
db.Execute strUpdate, dbFailOnError
Set db = Nothing
However, if you prefer to build the literal date values from those text boxes into your UPDATE statement, you can use Format().
"AND FinishDate BETWEEN " & _
Format(Forms!frmMainmenu!txtFirstDate, "\#yyyy-m-d\#") & _
" AND " & Format(Forms!frmMainmenu!txtEndDate, "\#yyyy-m-d\#") & ";"
Either way, using a string variable to hold your UPDATE statement gives you an opportunity to examine the completed statement you're asking the db engine to execute.
You can view the output from Debug.Print in the Immediate window (go there with Ctl+g). For troubleshooting, you can copy the statement text from there and then paste it into SQL View of a new Access query.

VBA select not returning any rows

Below query is not returning any rows into the listbox.There is no error message:
lstDiff.RowSource = "select TestScenario,TestId from tblTesting where empid= '" & Me.txtEmpId.Value & "' and testid= '" & Me.txtAutoNumber.Value & "'"
Could anyone help?
Your values in the field are numeric, so the extra single quotes aren't needed. Code should look like the following:
Me.lstDiff.RowSource = "select TestScenario,TestId from tblTesting where empid= " & Me.txtEmpId & " and testid= " & Me.txtAutoNumber & ";"
I've also dropped .Value from the field references, they're not harmful, but also aren't necessary.
And I've added a semi-colon to the end of your statement.
Depending on when/where you insert this code, you may need to add the following statement as well:
Me.lstDiff.Requery
You keep posting questions about the exact same WHERE clause with exactly the same apparent error in each one. SO users dutifully point out your error and then a few days later, you show up with a related question utilizing the same faulty WHERE clause.
DLookup Problem:
txtContSunStart1.Value = DLookup("Start1", "tblContract", _
"TestId = " & _
lstResults.Value & _
"" And "Day = 'Sunday'")
VBA Update Query:
DoCmd.RunSQL (" Update tbltesting set IsDiff ='Yes' where empid= " & Me.txtEmpId.Value & " and testid= " & Me.txtAutoNumber.Value & ";")
VBA SQL Problem
DoCmd.RunSQL ("insert into tbltesting (IsDiff)values ('Yes') where empid= '" & Me.txtEmpId.Value & "' and testid= '" & Me.txtAutoNumber.Value & "'")
And then in the current question:
lstDiff.RowSource = "select TestScenario,TestId from tblTesting where empid= '" & Me.txtEmpId.Value & "' and testid= '" & Me.txtAutoNumber.Value & "'"
You are having difficulties with exactly the same set of problems repeatedly.
Here are the rules for concatenating SQL strings with the correct delimiters in Access:
numeric values do not need delimiters:
"... AND testid= " & Me!txtAutoNumber
text values need quote delimiters. In Access, it's general practice to use double quotes, but much easier to use single quotes since it's a pain to type double quotes in a form that will work (typing """ or """" depending on context is counterintuitive and silly to me, so I always define a global constant that holds the double quote symbol and concatenate with that).
"... AND textfield=" & Chr(34) & Me!MyTextField & Chr(34)
date values use the # delimiter:
"... AND datefield=#" & Me!MyDateField & "#"
Boolean fields require no quotes and it works best to use True and False:
"... AND IsDiff=True"
These rules apply both to WHERE clause criteria and to SET statements in UPDATE queries. The rules apply in writing a SQL string that you pass to DoCmd.RunSQL or CurrentDB.Execute, as well as to writing SQL strings to be used as the recordsource of a form or report or as the rowsource of a combo box or listbox.
Personally, whenever I use SQL statements in code, I prefer to store the statement in a variable. While testing, on the line after you assign your statement to a variable, you can use Debug.Print to see what your SQL statement looks like after parsing your txtempid and txtautonumber. It would look something like this.
Dim sSQL as String
sSQL = "select TestScenario,TestId from tblTesting where empid= '" & Me.txtEmpId.Value & "' and testid= '" & Me.txtAutoNumber.Value & "'"
Debug.Print sSQL
lstDiff.RowSource = sSQL
Then as long as your immediate window is visible (Ctrl-G), you can see what your SQL statement really is. If it looks right in the immediate window, copy and paste it into the query builder and run it there.
Try running the query in your SQL Management Studio. Do you get any row(s) back?
Edit: Just noticed the access-tag. Are you sure your table contains at least one post with supplied ids?
My Access is a bit rusty, but if all else fails try using a recordset to capture the data from the SQL and loop through it adding the values to the list box. Example Code