ACCESS VBA Preventing duplicate value creation based on two criteria - ms-access

I have a listbox which gets populated from an other listbox1 . The user selects the data from the listbox and clicks on button which results in the data being enetered in the table. I have one problem that is i dont want the same values being enterd in the table again that is
One fiels is an ID and the other field is a Text value and only when both the values are equla I want a message box to pop up saying a duplicate value is created.
can someone help me on this?

You'll have to split this process into two sections - checking for duplications, then adding to the table. You can check using the following, which compares the listbox to the textbox:
Dim text As String
Dim i As Integer
If me.ListBox1.MultiSelect = 0 'only one selection
if me.ListBox1.Value = me.textbox1.value
msgbox "Multiple Values. Please try again", vbOkOnly
End
end if
elseif 'multiple selections
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i)=me.textbox1.value Then
msgbox "Multiple Values. Please try again", vbOkOnly
End
End If
Next i
end if
'now add rows to table

Related

Unique Membership Number in Access Database

I have a Database in Access 2010 where the 1st field is a unique membership number. The field is set Indexed, no duplicates. If a duplicate is entered on the input form no error message is displayed and nothing else works until a unique number is entered. I need the code that would trap the error on the number field losing focus so that a message box would tell the user the problem and then set focus back to the number field or let the user cancel all input.
This is what I have and it causes Datatype errors
Private Sub Grumpy_No_BeforeUpdate(Cancel As Integer)
If DLookup(Str("[Grumpy_No]"), "Grumpy", Str("[Grumpy_No]") = Me!Str(Grumpy_No)) Then
MsgBox "Number has already been entered in the database."
Cancel = True
Me!Grumpy_No.Undo
End If
End Sub
Any clues as to where I am going wrong would be very much appreciated
Looks to me like you're heading in the right direction but you need to fix your DLookup expression. Its third argument must be a single string. I don't see why Str() is useful --- just build a string. Actually I would use DCount instead of DLookup, but then the same issues still apply.
Private Sub Grumpy_No_BeforeUpdate(Cancel As Integer)
If DCount("[Grumpy_No]", "Grumpy", "[Grumpy_No] = " & Me!Grumpy_No.Value) > 0 Then
MsgBox "Number has already been entered in the database."
Cancel = True
'Me!Grumpy_No.Undo '<- consider allowing the user to see the value which failed
End If
End Sub
Note, if you can make Grumpy_No an autonumber primary key, Access will supply unique values automagically, so you wouldn't need your own code to check those values.

How to restrict deleting specified items from listbox using access vba

I have a listbox that contains 18 items. The selected item can be deleted from the listbox by clicking a 'Delete' button. How can I prevent a user from deleting certain items that I specify?
Private Sub cmdDelete_Click()
Dim i As Integer
With Me.listbox1
For i = .ListCount - 1 To 0 Step -1
If .Selected(i) = True Then
.RemoveItem i
End If
Next i
End With
End Sub
You could store the values in a table? Then you could have a column in the table which specified whether the field could be deleted or not, which would be easy to build into your VBA.
Edit for further explanation:
Have you listbox be unbound (i.e. no specific field as its datasource).
Create a table which contains columns for an ID (as an autonumber), the values you want to appear in your listbox (as a textbox), and a final column you can tick yes or no on (as a boolean or yes/no field). E.g.
ID Values Allow deletion?
1 Example Yes
2 Another example No
3 Yes another example Yes
In your listbox's rowsource, select that table.
Your delete sub could now run the following code.
dim qry as string
dim strLookup as string
strLookup = dlookup("[Allow deletion]","[Your Table]", YOURSELECTEDFIELDHERE & "=[Values]")
if strLookup = "No" Then
msgbox "You're not allowed to delete this field."
exit sub
else
qry = "DELETE * FROM [Your Table] WHERE [Values] = YOURSELECTEDFIELDHERE"
CurrentDB.Execute qry
Me.YourListBoxName.Requery
end if
This will look for the value you've grabbed from your listbox, match it against the Allow deletions field, delete it if that field is marked as Yes or leave it be if it's marked as No.
If you want to only temporarily delete the field and have it appear next time you load the form - in effect, hide it, you'd have to add a further column to the table called "Show", which would also be a Yes/No field, and set the default to Yes.
You'd then set your rowsource to SELECT * FROM [YOURTABLE] WHERE [Show] = "Yes".
Then qry in the above code should instead be set to:
UPDATE [YOURTABLE] SET [YOURTABLE].[Show] = "No" WHERE ((([YOURTABLE].[Values])=YOURSELECTEDFIELD));
This will then change the value of Show to No, so when the listbox is requeried, it'll no longer appear.
You'll need to run another query to change all of them back to Yes on the form exit.

MS Access 2007 - Changing a checkbox to be unchecked

I have an unbound text box that I want to enter a number in and then it would go in a form. When I do this, I want to change the status of checkbox in another form as well. So it is like inventory. When I add this item to this box, I need the checkbox value to change because it's no longer in inventory. So the form I have is 'Info' and the checkbox is named 'ChkboxAvailableUse'. I have the checkbox correlated to a kit number and location and stuff too. So when I enter the number in an unbound text box called 'AssignKit', I want that number to look for the same kit number the 'Info' form and the 'InvKitNumber' text field, and then change that records checkbox (ChkboxAvailableUse) to change to false. I hope this makes sense. I have the line of code I thought would work below. Any help would be fantastic. Thank you
CurrentDb.Execute " UPDATE Info SET ChkboxAvailableUse = FALSE WHERE InvKitNumber = " & Me.AssignKit & ""
If you just want that form to uncheck or check in the table to match your form or subfrom then you could use a recordset.
Dim myR as Recordset
Dim strSQL as String
'This SELECT string will pull from the assignkit field in the subform
'and will be used find the matching record in the table
strSQL = "SELECT * FROM info WHERE InvKitNumber = '" & Me!subformnamehere.Form.AssignKit & "'"
'This will make your recordeset variable the one record you want to modify
Set myR = db.OpendRecordset(strSQL, dbOpenDynaset)
'Now that the recordset is pointing to that row, you can change the checkbox
'with something like this, and even use an IF statement
myR.Edit
myR![ChkboxAvailable] = True
myR.Update
'Then close the recordeset when done
Set myR = Nothing
I hope this helps, let me know if you need me to tweek it.
The sql UPDATE statement updates fields in a table. Tables don't have checkboxes, forms do, and I assume that the field (in the table) is not called ChkboxAvailableUse ?
If the field is named AvailableUse then you would update this field with:
CurrentDb.Execute "UPDATE Info SET AvailableUse = FALSE WHERE InvKitNumber = " & Me.AssignKit
Then you could ReQuery the (other) form (or a control on the form) so that it reflects these changes.

How To Refer To Continuous Subform Contol

I have an Access 2003 form with one subform, set to continuous forms, in a subform control. For one record in the main form, 1 to many records will appear in the sub form. The data displays properly.
The main form is named Widgets and the sub form is named Transactions. There are 5 textbox controls that display the data in the subform. The one in question is ReceiptDate.
What I would like to do is look at the values and determine if there was a receipt for the year 2009, and if so then change the background of that row to yellow so it stands out when the user encounters that condition. Maybe even change the date field's font to boldface..
I tried many ways of referencing the subform's controls. When I have tried Me.Transactions.ReceiptDate I have only received the first record in that subform. I'd like to be able to loop through them and see if the condition is met. I tried Me.Transactions.ReceiptDate(1) and Me.Transactions.ReceiptDate(0) and so forth.
I tried the For Each ctl In Form.Controls route as well. It worked for a few iterations and then I received a run-time error 2455 "You entered an expression that has an invalid reference to the property Form/Report".
I had the subform in "datasheet" mode but thought that was causing me not to be able to read through an array of subform controls. So I changed it to "continuous" mode. I get the same errors for either.
Is there a way to reference specific "rows" in the subform and do something based on a value found? Also, I am performing this in the On Current event as I dont know where else to put the code. The subform loads before the parent form so its possible that these controls arent even fully "there" but then I do get the first row's date when I try it in the Immediate Window.
UPDATE 12.23.2010:
With the gracious help of #Remou I am able to debug.print the ReceiptDate fields from the RecordSet. This is great because now I can evaluate the data and do certain things based on the values.. The #Remou's code helped me put this into the OnCurrent event:
Dim i As Long
Dim frm As Form
Dim rs As DAO.Recordset
' Get the form and its recordset.
Set frm = Me.Form
Set rs = frm.RecordsetClone
' Move to the first record in the recordset.
rs.MoveFirst
' Move to the first selected record.
rs.Move frm.SelTop - 1
' Enumerate the list of selected records presenting the ReceiptDate field
For i = 1 To rs.RecordCount
Debug.Print rs![ReceiptDate]
rs.MoveNext
Next i
So now that I am able to know which row in my subform has a receipt from 2009, I need to be able to highlight the entire row or rows as I come across them in that for loop. How can I reference the actual row? Datasheet view or Continuous Forms view - I have tried both.
Conditional Formatting is great but it only allows me to highlight one particular record and I'd much rather be able to do this via VBA because...... from here I will want to give the use the ability to click on any record in the subform and get the receipt details and potentially print them.
Any ideas?
In this situation, it is best to use conditional formatting.
To refer to a control on a subform, refer to the subform control by name, then the form property to get the form contained, then the control by name:
Me.MySubformControlName.Form.MyControl
See: http://www.mvps.org/access/forms/frm0031.htm
I have finally got it. The frm.SelTop = x will set the selected record and from there I can set the background or font style, etc.. Very cool. A simple test for 2009 and setting the selected record:
Dim i As Long
Dim frm As Form
Dim rs As DAO.Recordset
' Get the form and its recordset.
Set frm = Me.Form
Set rs = frm.RecordsetClone
' Move to the first record in the recordset.
rs.MoveFirst
' Move to the first selected record.
rs.Move 0
' Enumerate the list of selected records presenting
' the CompanyName field in a message box.
For i = 1 To rs.RecordCount
If Year(rs![ReceiptDate]) = 2009 Then
frm.SelTop = i '<-----------------------------
End If
rs.MoveNext
Next i
In order for me to get the email off the bottom of my continuous form, I used this much simpler code (as I avoided the RecordsetClone code)
Me.[email subform].Form.SelTop = Me.[email subform].Form.Count 'selects the last row
str = Me.[email subform].Form.Email 'capture the value of the last row
MsgBox str

Tagging Records in a Continuous Form

In a continuous subform, I display records based on a DISTINCT query. Because it's distinct, each row does not include a record ID.
Does anyone know of a way to add a checkbox (or similar), so that a user can select any of the records, which will then be used to create new records via code?
I prefer to use a subform to a list, as it features lots of column sorting and filtering functions.
MTIA
Depending on what you need to create the records, something like this sample may suit:
Function DisplaySelectedCompanyNames()
Dim i As Long
Dim F As Form
Dim RS As Recordset
'' Get the form and its recordset.
Set F = Forms![Customers1]
Set RS = F.RecordsetClone
'' Move to the first record in the recordset.
RS.MoveFirst
'' Move to the first selected record.
RS.Move F.SelTop - 1
'' Enumerate the list of selected records presenting
'' the CompanyName field in a message box.
For i = 1 To F.SelHeight
MsgBox RS![CompanyName]
RS.MoveNext
Next i
End Function
Further information: http://support.microsoft.com/kb/208502
FYI, I decided to use the Windows ListView OCX control, as it offers the ability to add a checkbox for each row.