By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,491 Members | 1,168 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,491 IT Pros & Developers. It's quick & easy.

Scan QR code to either add a record or if record exists add +1 to [count]

P: 12
I am working on an reagent inventory db.

Currently I have 2 tables
1) Roche with [UPC][Count] and some calculated fields based off of [UPC]
2) MaterialNum which provides the name of the reagent based on the calculated data from Roche Table.

I have a form that I can search for the UPC and if it exists populates the form and I can modify the [Count] and save from there.
If the record is not found through the search box I can add a new record and add it, and adjust the [Count] from there.

This really is inefficient. What I want to be able to do is scan the QR, that check for record, if not found add it. And once added or found to be there a +1 is added to the [Count].
1 Week Ago #1

✓ answered by twinnyfo

1) When setting the Var strUPC, why the Nz?
Whould strUPC = NULL if textUPCSearch is not found in[OrgUPC] and if found returns the value of textUPCSearch?
Yes, it would be Null. However, whenever working with variables, I always try to avoid those variables having a Null value. They can sometimes be tricky and some variable types will even throw an error if you try to assign Null to them. By using the Nz() function, you control the value of your variable. Then you know that it will be either a known value or "".

2) Why put the insert statement into a var?
First, this is an excellent question. Second, I am glad you noticed and that you asked.

The primary reason for assigning the SQL string to a variable is for troubleshooting. Let's say you simply build your string within the function itself and each time you execute that query, you come up with an error? How do you troubleshoot something you don't know the value of? But, if it is a variable, you can always comment out the execution of the SQL and then Debug.Print strSQL to see the actual value of your SQL string. Then, you tweak the actual string until it works, then tweak your code so that it produces an identical string.

This is a best practice among DBAs--at least those on this forum.

Incrementing the [Count].
First: change the name of your field. Count is a reserved word within Access and you are simply asking for trouble. For the code below, I am assuming you've changed the field name to "Inventory". Modify the code approriately to suit your changes.

So.......... Even though we have used a DLookup() in this code, a "general" but not hard and fast rule is to try to avoid Domain Aggregate functions in your code. This is not because they are bad, but because they are generally less efficient than working directly with your tables.

So let me throw this question out to you. What if you could open your table, find the UPC you were looking for, and if you found it, just add one to the inventory, but if you don't find it, add it to the table? WHAT IF........?

Prepare to have your mind blown:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtUPCSearch_AfterUpdate()
  2.     Dim db      As DAO.Database
  3.     Dim rst     As DAO.Recordset
  4.  
  5.     Set db = CurrentDb()
  6.     Set rst = db.OpenRecordset("Roche")
  7.     With rst
  8.         If Not (.BOF And .EOF) Then
  9.             Call .MoveFirst
  10.             .FindFirst "OrgUPC = '" & Me.txtUPCSearch & "'"
  11.             If Not .NoMatch Then
  12.                 'Found it!
  13.                 Call .Edit
  14.                 !Inventory = !Inventory + 1
  15.                 Call .Update
  16.             Else
  17.                 'Didn't find it
  18.                 Call .AddNew
  19.                 !OrgUPC = Me.txtUPCSearch
  20.                 !Inventory = 1
  21.                 Call .Update
  22.             End If
  23.         End If
  24.         Call .Close
  25.     End With
  26.     Call db.Close
  27.     Set rst = Nothing
  28.     Set db = Nothing
  29.  
  30. End Sub
This brief snippet of code is the sum total of everything you need to solve this problem. Notice again its elegance and simplicity! Open the table. Search for the UPC. Found it: add 1; Not found : new record.

Any questions, let me know!

Hope this hepps!

Share this Question
Share on Google+
19 Replies


twinnyfo
Expert Mod 2.5K+
P: 3,054
Abhean,

I am really confused. You say that your current process is really inefficient, but your proposed solution performs the same exact functions.

Exactly what, specifically, are you asking for in this thread?
1 Week Ago #2

P: 12
It would do the same function. The trouble is the process. User will not like having to scan an item twice if it is not found in the table. Once for the search and then again for the add record.

To be able to scan once, run it through the logic of looking for the record then adding if not there and not trowing an error if it is there, then adding a +1 in the [count] of the selected record. This would be more user friendly and faster for the user.

Attached Images
File Type: png dbaseFrm.PNG (11.3 KB, 52 views)
1 Week Ago #3

twinnyfo
Expert Mod 2.5K+
P: 3,054
Then, I am still confused. If you have the code that you are looking for, why do you need to scan it twice?

But again, I still don't know exactly what you are asking from us here.

You need to help us out and ask a specific question.
1 Week Ago #4

P: 12
I am using the built in functions of the combo box to check to see if a record is existing. If I do so within the text box (Stock Number)and the record is already there it will throw an error stating that the record already exists (which it should).
I have conditional formatting in place between the search box and stock number, green tells the user that the record is already there and they can simply modify the record they see in the count field. Red tells them that they will have to click on the add record button and scan the item in again in the Stock number text field.

Now, the specific Question. Is there a way to code the text box so that it will scan the records to see if the # placed in it (the text box) is there, if the record exists, simply add +1 to the count field of that record? If the record does not exist add it and add +1 to the count on that new item?

And thank you for taking time with me. My Access is very weak. :)
1 Week Ago #5

twinnyfo
Expert Mod 2.5K+
P: 3,054
Thank you for the clarification. So, here is where the inefficiency comes:

Abhean:
Red tells them that they will have to click on the add record button and scan the item in again in the Stock number text field.
The process is not inefficient; it has been designed inefficiently. I think you have all the working parts to make this work. I still have a few more questions to clarify for myself, and a recommendation at the end, which I think will get you moving along the right path.

Question:
I am using the built in functions of the combo box to check to see if a record is existing. If I do so within the text box (Stock Number)and the record is already there it will throw an error stating that the record already exists (which it should).
What? How are you using the combo box? Does someone click on the combo box and scroll through all the stock numbers to find the one they want?

Second, why would you ever weant your DB to throw an error when it has found a record that you want to update? Very unclear how this is intended to work.

However, you say:
green tells the user that the record is already there and they can simply modify the record they see in the count field.
Are you saying that if the DB finds the stock number, all you are doing is finding the record and the user increments the toal on hand by one?

Finally,
Red tells them that they will have to click on the add record button and scan the item in again in the Stock number text field.
Here is the big question--which also leads to my final recommendation--So, you have a method of scanning in a code and that code then populating a text box, yes?

The recommendation is quite simple. It appears you've put the cart before the horse. Why not simply begin by scanning in a code. PERIOD. If you have a means of scanning a code into a text box, then do it. ONCE. The user scans a code, clicks "Add item"--or whatever you want to have on the button. The DB uses the scanned in code. First, it looks for the existence of that code. If it exists--no errors here--it simply increments the stock by one. If it cannot find that stock number, it creates a new record, with an inventory of 1. If the DB requires additional information on new items, then a form would pop up requesting the desired information. Clicking save would close that form and add that record.

It's really quite straightforward. I think you just got your process steps out of place.
1 Week Ago #6

P: 12
You sir, are bang on!

Combo boxes make very easy search boxes when based on a single primary key. Basing a form from a table, again easy and straight forward. The combo box came after I attempted to scan a number into the Stock number text box and received the error that the number entered was already in the database. In can the combo box as the first step (now) to make sure the user would check # before going to the records. The green and red background were just as a double check.

But, your summary is dead on. How would I code a text box to check a number entered, if there simply do a ++ to the count field, and if not add it as a record and do the ++

And again thanks for your patients.
1 Week Ago #7

twinnyfo
Expert Mod 2.5K+
P: 3,054
I will return to this on the morrow, if you can wait.
1 Week Ago #8

P: 12
oh absolutely! Again thanks.
1 Week Ago #9

twinnyfo
Expert Mod 2.5K+
P: 3,054
So, I think the easy solution is to use some of the code you already use. It would be helpful to post the procedures you currently use, but I suspect these will change significantly during this overhaul.

So, again, the first thing ht user should do is scan the code. When that code is entered into a text box, then, simply add a button that initiates the process.

First, it checks to see if there is no value in the code text box (we don't want to do anything if there is nothing there).

Second, it searches for that code in your table. If it finds it, then it simply adds one to the inventory.

Third, if the search does not find anything, it brings up a product form, which is similar to the form you are currently using (wihtout the search stuff on it), which should really just be bound to your products table, and move to a new record (you should have data entry set to true on this form, so folks can't change records that already exist). The default value for inventory should be one (because you have one and only one--this does not even need to be displayed). Save that record and scan another code.
1 Week Ago #10

P: 12
Ok Here is what I am attempting to work with currently.

It appears that it does find the Duplicates and the records that need to be added.

I do get a syntax error that something is not correct in the INSERT INFO

the Text40 is the textbox I am using to scan in the numbers.

Expand|Select|Wrap|Line Numbers
  1. Private Sub Text40_AfterUpdate()
  2.     'Search finds record in table
  3.     If (DLookup("[OrgUPC]", _
  4.                       "[Roche]", _
  5.                       "[OrgUPC]='" & Me!Text40 & "'")) Then
  6.         MsgBox "Duplicate!"
  7.     'Search does not find record
  8.     Else
  9.         MsgBox "New Record"
  10.         DoCmd.RunSQL "INSERT INTO [Roche] " & _
  11.                      "([OrgUPC] " & _
  12.                      "VALUES ('" & Me.Text40 & "')"
  13.     End If
  14.  
  15.     'clear the text box
  16.     Me.Text40 = Null
  17.     'ready for next scan
  18.     Me!Text40.SetFocus
EDIT: Ok I have changed the ELSE section to
Expand|Select|Wrap|Line Numbers
  1. Else
  2.         MsgBox "New Record"
  3.         DoCmd.RunSQL "INSERT INTO Roche (OrgUPC)Values (Text2)"
I also am doing this on a new form so the the text has changed to "Text2"
This seems to be working, but is there anyway to stop the warning box that makes sure I wish to append the record?
1 Week Ago #11

twinnyfo
Expert Mod 2.5K+
P: 3,054
Abhean:
This seems to be working, but is there anyway to stop the warning box that makes sure I wish to append the record?
Just delete the line that calls for the message box!

Here is a modified version of what you have. Please note that I have renamed your text box to something that actually makes sense. Notice also that I use your INSERT statement to also include a number of inventory (I don't know what hte field name is, so I simply used "Inventory".

Also note that it is a good habit to use variables for things like this. Notice that there is a variable for the UPC, then we evaluate that variable. We also check to see if the search finds anything--and if not, we set the variable to a predefined value. There is also a variable for the SQL statmeent. Then we use that variable. In the long run, this helps you with troubleshooting.

Expand|Select|Wrap|Line Numbers
  1. Private Sub txtUPCSearch_AfterUpdate()
  2.     Dim strUPC  As String
  3.     Dim strSQL  As String
  4.  
  5.     strUPC = Nz( _
  6.                 DLookup("[OrgUPC]", _
  7.                         "[Roche]", _
  8.                         "[OrgUPC]='" & Me.txtUPCSearch & "'"), _
  9.                 "")
  10.     If Not strUPC = "" Then
  11.         'Add one to the counter
  12.         'Add your code here
  13.         'Probably an UPDATE query......
  14.     Else
  15.         'Add new record
  16.         strSQL = _
  17.             "INSERT INTO Roche ( OrgUPC, Inventory ) " & _
  18.             "Values ( " & txtUPCSearch & ", 1 );"
  19.         DoCmd.RunSQL strSQL
  20.     End If
  21.  
  22.     'clear the text box
  23.     Me.txtUPCSearch = Null
  24.     'ready for next scan
  25.     Me!txtUPCSearch.SetFocus
  26.  
  27. End Sub
Hope this hepps!
1 Week Ago #12

P: 12
Ohh yea! Almost there! The data appears to be passing but is being changed.
Example: Scan in 010401563093975610315914021719073124007027664190
But it is entering 1.04015630939756E+46 in the field.
The field is set as short text.
1 Week Ago #13

twinnyfo
Expert Mod 2.5K+
P: 3,054
Chang line 18:

Expand|Select|Wrap|Line Numbers
  1. "Values ( '" & txtUPCSearch & "', 1 );"
Forgot to treat it as text.
1 Week Ago #14

P: 12
Working like a dream. Couple of questions.
1) When setting the Var strUPC, why the Nz?
Whould strUPC = NULL if textUPCSearch is not found in[OrgUPC] and if found returns the value of textUPCSearch?

2) Why put the insert statement into a var?

I am just trying to understand how things are working. :)

Now, a question about incrementing the count.I am trying:
Expand|Select|Wrap|Line Numbers
  1. [Count] = DMax("[Count]", "Roche") + 1
Roche being the table, count being the field. This is done within the "If Not" statement. Getting error that it cant write to this field.

Edit: Found "Count" was reserved word so changed it to OnHand. Now passes through but does not add to the count.
1 Week Ago #15

twinnyfo
Expert Mod 2.5K+
P: 3,054
1) When setting the Var strUPC, why the Nz?
Whould strUPC = NULL if textUPCSearch is not found in[OrgUPC] and if found returns the value of textUPCSearch?
Yes, it would be Null. However, whenever working with variables, I always try to avoid those variables having a Null value. They can sometimes be tricky and some variable types will even throw an error if you try to assign Null to them. By using the Nz() function, you control the value of your variable. Then you know that it will be either a known value or "".

2) Why put the insert statement into a var?
First, this is an excellent question. Second, I am glad you noticed and that you asked.

The primary reason for assigning the SQL string to a variable is for troubleshooting. Let's say you simply build your string within the function itself and each time you execute that query, you come up with an error? How do you troubleshoot something you don't know the value of? But, if it is a variable, you can always comment out the execution of the SQL and then Debug.Print strSQL to see the actual value of your SQL string. Then, you tweak the actual string until it works, then tweak your code so that it produces an identical string.

This is a best practice among DBAs--at least those on this forum.

Incrementing the [Count].
First: change the name of your field. Count is a reserved word within Access and you are simply asking for trouble. For the code below, I am assuming you've changed the field name to "Inventory". Modify the code approriately to suit your changes.

So.......... Even though we have used a DLookup() in this code, a "general" but not hard and fast rule is to try to avoid Domain Aggregate functions in your code. This is not because they are bad, but because they are generally less efficient than working directly with your tables.

So let me throw this question out to you. What if you could open your table, find the UPC you were looking for, and if you found it, just add one to the inventory, but if you don't find it, add it to the table? WHAT IF........?

Prepare to have your mind blown:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtUPCSearch_AfterUpdate()
  2.     Dim db      As DAO.Database
  3.     Dim rst     As DAO.Recordset
  4.  
  5.     Set db = CurrentDb()
  6.     Set rst = db.OpenRecordset("Roche")
  7.     With rst
  8.         If Not (.BOF And .EOF) Then
  9.             Call .MoveFirst
  10.             .FindFirst "OrgUPC = '" & Me.txtUPCSearch & "'"
  11.             If Not .NoMatch Then
  12.                 'Found it!
  13.                 Call .Edit
  14.                 !Inventory = !Inventory + 1
  15.                 Call .Update
  16.             Else
  17.                 'Didn't find it
  18.                 Call .AddNew
  19.                 !OrgUPC = Me.txtUPCSearch
  20.                 !Inventory = 1
  21.                 Call .Update
  22.             End If
  23.         End If
  24.         Call .Close
  25.     End With
  26.     Call db.Close
  27.     Set rst = Nothing
  28.     Set db = Nothing
  29.  
  30. End Sub
This brief snippet of code is the sum total of everything you need to solve this problem. Notice again its elegance and simplicity! Open the table. Search for the UPC. Found it: add 1; Not found : new record.

Any questions, let me know!

Hope this hepps!
1 Week Ago #16

P: 12
OMG Yea questions I will have.
First off the getting error line 10. Operation is not supported for this type of object.
Expand|Select|Wrap|Line Numbers
  1. .FindFirst "OrgUPC = '" & Me.txtUPCSearch & "'"
The commands like .movefirst and .NoMatch those are just built in functions?

And the commands like !Onhand or !OrgUPC make those fields active?
1 Week Ago #17

twinnyfo
Expert Mod 2.5K+
P: 3,054
When you go to your VBA Editor: Debug | Compile, is that also the error that pops up? You shouldn't have to, but you may have to add Microsoft DAO 3.6 Object Library. Mine is not added but it compiles and functions fine without it.

.MoveFirst etc. are all built in to the DAO library.

!OnHand etc. - this is how you refer to fields within a DAO Recordset when it is open.

You may note that there is a funny little statement With rst ... End With at lines 7 and 25. This means that anything wthin these bounds has an implied rst leading it. So, within the code, Call .MoveFirst is iinterpreted and understood as Call rst.MoveFirst.

I'm puzzled over the error, but you may have to play with it. Mine works fine.
1 Week Ago #18

P: 12
Wahooo! Twinnyfo, thank you so much for your time and effort! Everything appears to be working and more importantly I have learned & relearned so much from this.

I was able to take care of that 3251 run time error by adding dbOpenDynaset to the "set rst" on line 6 Ill post the code below.

Expand|Select|Wrap|Line Numbers
  1. Private Sub txtUPCSearch_AfterUpdate()
  2.    Dim db      As DAO.Database
  3.     Dim rst     As DAO.Recordset
  4.  
  5.     Set db = CurrentDb()
  6.     Set rst = db.OpenRecordset("Roche", dbOpenDynaset)
  7.     With rst
  8.         If Not (.BOF And .EOF) Then
  9.             Call .MoveFirst
  10.             .FindFirst "OrgUPC = '" & Me.txtUPCSearch & "'"
  11.             If Not .NoMatch Then
  12.                 'Found it!
  13.                 Call .Edit
  14.                 !OnHand = !OnHand + 1
  15.                 Call .Update
  16.             Else
  17.                 'Didn't find it
  18.                 Call .AddNew
  19.                 !OrgUPC = Me.txtUPCSearch
  20.                 !OnHand = 1
  21.                 Call .Update
  22.             End If
  23.         End If
  24.         Call .Close
  25.     End With
  26.     Call db.Close
  27.     Set rst = Nothing
  28.     Set db = Nothing
  29.  
  30. End Sub
1 Week Ago #19

twinnyfo
Expert Mod 2.5K+
P: 3,054
Yep, sometimes your recordsets will require the , dbOpenDynaset argument--you can include it always if you want. I just omitted it this time because it was working with my table without it.

Glad I could hepp!

Let us know if you need anything else.
1 Week Ago #20

Post your reply

Sign in to post your reply or Sign up for a free account.