Private Sub Form_Current()
Dim bytoffcut As Byte
Dim strCriteria
strCriteria = "[WOID] = " & Forms![frmAddStockBooking]![MouldWO]
bytoffcut = Nz(DMax("OffcutNo", "dbo_tblOffcuts", strCriteria), 0) + 1
MsgBox bytoffcut
Me.txtOffcut.Value = bytoffcut
Me.WOID.Value = Forms![frmAddStockBooking]![MouldWO]
Me.txtdate.Value = Now()
End Sub
Can anyone tell me why this is not working? The variable is behaving as expected where bytoffcut increments by one when i create a new record. But when I check the table the field bound to txtOffcut the field reads 1 instead of the incremented value.
EDIT: This code is being used in the On current property of the form. When I create a new record using a button on the form Dmax is used to find the highest offcut No value in a table and add one to it.
This appear to work in the form as the offcut no txtbox increments. But when i look at the table instead of having records with an increasing offcut no Instead all records read 1
Try sending your where clause in the DMax like this, assuming the WOID field in the table is an number type and not text or date.
"[WOID] = " & Forms![frmAddStockBooking]![MouldWO]
It would be better to evaluate your DMax() expression only once, especially if dbo_tblOffcuts is a large linked table without a usable index on [WOID].
If your DMax() expression can return a Null, use Nz() to transform the Null to zero. Then add one.
Dim bytoffcut As Byte
Dim strCriteria
strCriteria = "[WOID] = " & Forms![frmAddStockBooking]![MouldWO]
'Debug.Print strCriteria '
bytoffcut = Nz(DMax("OffcutNo", "dbo_tblOffcuts", _
strCriteria), 0) + 1
MsgBox bytoffcut
Me.txtOffcut.value = bytoffcut
This may not give you what you want when other users are editing dbo_tblOffcuts.
I have managed to solve the issue of multiple records being updated by creating a primary key for the table I am writing to.
I think that because Access could not uniquely identify the record it would edit all the records that met the criteria or something of the ilk. I am not entirely sure myself.
Related
I been working on the following code to when the user click on the button to save and go new record that Access locates the highest client id used by set location and then adds 1 to it. Prior to saving the record and moving on to new record. While work through other errors, but I can not get past error object required on this line. "Me.ClientID = IIf(DMax("[ClientID]", "tClientinfo", "[CorpsName]=" & "'defaultcorps'") Is Null, 0, DMax("[ClientID]", "tClientinfo", "[CorpsName]=" & "'defaultcorps'")) + 1"
The more i look at the similar questions more confused I get as to what is wrong with the code. Thank you in advance for any suggestions David
Private Sub Save_Record_Click()
'declare variables for default values
Dim defaultinterviewr As String
Dim defaultcorps As String
'Variables get their values
defaultinterviewr = Me.Interviewer.Value
defaultcorps = Me.Corps.Value
'Check to see if ClientID field is Blank.
If IsNull(Me.ClientID) Then
'Check that Corps field is filled in
If IsNull(Me.Corps) Then
MsgBox "Corps must be entered before saving record.", vbOKOnly
Me.Corps.SetFocus
'set client id base on corps by finding the highest id and adding 1 to that number
Else
Me.ClientID = IIf(DMax("[ClientID]", "tClientinfo", "[CorpsName]=" & "'defaultcorps'") Is Null, 0, DMax("[ClientID]", "tClientinfo", "[CorpsName]=" & "'defaultcorps'")) + 1
End If
End If
MsgBox "Done", vbOKOnly
'save record
'DoCmd.RunCommand acCmdSaveRecord
'Me.stateidnum1 = ""
'open new record
'DoCmd.GoToRecord , , acNewRec
'set field default value
'Me.Interviewer.Value = defaultinterviewr
'Me.Corps.Value = defaultcorps
'Me.Child_Subform.Form.AllowAdditions = True
End Sub
I think you need to start off by figuring out if your DMAX() statement is correctly producing results. The next thing I see and which is probably your main culprit is the fact that you are using the Expression IIf() inside VBA. The IIf() expression you are using will work inside a query or in a textbox but VBA has it's own If statement block which you are correctly using in the lines preceding it.
I would actually use the Nz Function to simplify it even more as follows:
UPDATED Based off of your comment below I re-looked at your overall code and noticed that "defaultcorps" is a variable and not a value I originally thought you were trying to filter by. You were wrapping the variable in quotes. My updated answer should work for you.
Me.ClientID = (Nz(DMax("[ClientID]", "tClientinfo", "[CorpsName]= '" & defaultcorps & "'"),0)+1)
I want to populate a combo box with the results of a query in Access. I'm just not seeing how to do it. As far as I understand, one must first create a record set, read the query results into the record set, then write the record set to the combo box's row source property. Is this correct? is there a simple example somewhere that I can follow? I haven't found one in any of the other threads.
Here's my attempt so far:
Dim RS As Recordset
Dim myDB As Database
Set RS = myDB.OpenRecordset("SourcesNotDisposed", dbOpenDynaset)
Do While Not RS.EOF
With Me.cmbSN
RowSource.AddItem
End With
Loop
With this code, I'm getting an "Object required" error at the RowSource line. cmbSN has data properties:
Row source Type = Table/Query
Bound Column = 0
Limit to List = Yes
Allow value list edits = Yes
Inherit value list = Yes
Show only row source = No
The query only has one visible column called "Serial Number"
Thanks in advance
Thanks for all the suggestions everyone. I've worked it out and found a very simple solution. With the combo box's Row Source Type property set to Table/Query, all I needed to do was set the Row Source property to a valid SQL string. e.g.:
strSQL = "SELECT Sources.[Serial Number] FROM Sources " & _
"WHERE (((Sources.Nuclide)='Cf-252') " & _
"AND ((Sources.[Location / Status])<>'Disposed')) " & _
"ORDER BY Sources.[Serial Number];"
Me.cmbItem.RowSource = strSQL
Me.cmbItem.Requery
Below code insert table fields into combo box. Add this code under onEnter event of combo
Private Sub CM_Enter()
'CM is combobox name
Dim strItem1 As String
Dim strItem2 As String
On Error Resume Next
Dim i As Integer 'Index for loop
With Me.CM
.RowSourceType = "Value List" 'Set rowsource type as Value list
.RowSource = "" 'Clean combo contents
End With
'Loop through field names of table and add them to your combo:
For i = 1 To CurrentDb.TableDefs("table1").Fields.Count - 1
Me.CM.AddItem (CurrentDb.TableDefs("table1").Fields(i - 1).Name)
Next i
'/***Delete unwanted items from the combo
strItem1 = "col1"
strItem2 = "col2"
'CM.RemoveItem strItem1
'CM.RemoveItem strItem2
End Sub
I think you might need to do a 'first read a record' before starting the loop.
Try using a RS.MoveFirst before the Do-While loop?
I think you may also need to do a .MoveNext inside your loop, just before the Loop statement; it's been a long while since I did anything like this in VBA, but it looks to me like it'll just add the same item over and over until it runs out of memory? I don't think the AddItem moves the record pointer to the next record by itself.
You may also need to check what happens if you MoveNext off the end of the record set...
HTH :)
I need to set the default value for a textbox in an ms access 2010 form. The default value needs to be the most recent date in CommunicationTable where the ClientNumber is the same as the ClientNumber associated with the current record in the form. The code below references the correct ClientNumber, but I am not sure how to get the most recent date. I am concerned that DMax might not be the appropriate function for getting the most recent date. How should I change the following to get the most recent date?
=DMax("DateOfCommunication","[CommunicationTable]","[ClientNumber]= "
& [Forms]![Main]![NavigationSubform].[Form]![ClientNumber] & "")
I realize I should also post the larger function in which the above function is nested:
=DLookUp("[Level]","[CommunicationTable]","DateOfCommunication= "
& DMax("DateOfCommunication","[CommunicationTable]","[ClientNumber]= "
& [Forms]![Main]![NavigationSubform].[Form]![ClientNumber] & ""))
Also, the form itself is bound to CommunicationTable. This VBA function is in the DefaultValue dialog box, which I get into via the property sheet for the text box. So I am not sure that creating a sql query will work in this case.
EDIT:
I have uploaded a stripped down copy of the database which reproduces the problem at this file sharing site.
To locate the code:
1.) Open the CommunicationEntryForm and
2.) open the AfterUpdate() event procedure for the ClientNumber field.
Next, to reproduce the problem:
1.) close `CommunicationEntryForm`
2.) In the Main form(which should already be open), click the View tab to open
the most recent CommunicationForm for any Client you want. Note the Level
number for that Communication.
3.) Click on the Communication tab. This will leave the form and show a list
of CommunicationForms for that Client.
4.) Click the Create New Form button. This will open up CommunicationEntryForm.
The value for Level should be the same as the value you noted in step 1 above.
The problem is that this is blank.
Can someone show me how to fix this problem?
#CodeMed - I did download the database but found you have issues other than what you are describing- such as when you 'add' a new communication you simply overwrite an existing record. I managed to get the result you were looking for, but it just changes the 3 records around. Does your non-sample program actually have the ability to create and add new records? As it is, I just changed your existing code to this:
Private Sub cmdNewCommForm_Click()
Dim cNum As Long
Dim strSQL As String
Dim rs As Recordset
Dim db As Database
Set db = CurrentDb
cNum = Forms!Main!NavigationSubform.Form!ClientNumber
strSQL = "SELECT Top 1 Co.Level AS MaxOfLevel " & _
"FROM CommunicationTable co Where Co.ClientNumber = " & cNum
Set rs = db.OpenRecordset(strSQL)
Forms!Main!NavigationSubform.Form!NavigationSubform.SourceObject = "CommunicationEntryForm"
Forms!Main!NavigationSubform.Form!NavigationSubform!ClientNumber = cNum
Forms!Main!NavigationSubform.Form!NavigationSubform!DateOfCommunication = Date
If rs.RecordCount > 0 Then
Forms!Main!NavigationSubform.Form!NavigationSubform!Level = rs!MaxOfLevel
Else
Forms!Main!NavigationSubform.Form!NavigationSubform!Level = 0
End If
Set rs = Nothing
Set db = Nothing
End Sub
What I would do is first grab the date by doing something like:
Dim db as Database
Dim rec as Recordset
Set db = CurrentDB
Set rec = db.OpenRecordset("SELECT Top 1 DateOfCommunication FROM CommunicationTable WHERE ClientNumber= " & [Forms]![Main]![NavigationSubform].[Form]![ClientNumber] & " ORDER BY DateOfCommunication DESC")
This will get the most recent date. Then, in your above VBA, you can just stick rec(0) in where your calculation was:
Me.MyDateField = DLookUp("[Level]","[CommunicationTable]","DateOfCommunication= #" & rec(0) & "#")
Substitute "MyDateField" with whatever that name of your date field actually is.
I'm pretty sure you need the pound signs (or "hashtags" as the kids call them today...) in order for Access to do the calculation on a date value.
I am working on a MS-Access database to keep track of last names and addresses and several other records. I am making a table and would like for it to be updated by the user by inputting info from a form. The question I have is can I have several key items that would warn if a duplicate is found. Mainly if a duplicate is found in the last name and the address fields. I need the form to accept the duplicate because how the info is being obtained duplicates are possible but need to be able to enter the duplicate and warn the user while entering the data that a previous entry has already been made that is similar.
Is this possible in Access, and easy to implement that many different users may be entering the data? I haven't used Access for some time, sorry if I'm not using the correct terms, as I'm still learning the basics of Access, as I mainly work in Excel. Excel is the current solution that is being used, but finding quickly that a better solution is needed.
Thanks
Names aren't good candidates for primary keys and it seems that you have set the name as the primary key of one of your tables. You should either use a better candidate key (social insurance number, for example) or create a surrogate (artificial, if you want) key with no meaning other than being a key for your table.
Without more detail about your table structure it's hard to be more specific.
Warn the user but allow her to proceed if she wishes?
If so, a key constraint would be too, ahem, constraining. Just check for the duplicates manually (by explicitly querying existing data from your code). You may wish to index the field(s) being searched.
Yes, you can validate through this code:
If Nz(DCount("FieldName", "table", "FieldName= '" & Me.FieldName.Value & "'"), 0) > 0 Then
If MsgBox("The FieldName already exist", vbOKCancel, "Duplicate Warning") = vbCancel Then Cancel = True
Me.Undo
Exit Sub
End If
End If
In general terms, Access (and relational databases generally) are about preventing duplicate data from being entered in the first place. If you merely want to 'warn', then it will take a bit of custom code. So, say the table is called Customers and it has fields such as CustomerID (AutoNumber, primary key) and LastName (Text). The form then has a text box called txtLastName that is bound to the LastName field. In this situation, you could handle the text box's BeforeUpdate event like this:
Option Compare Database
Option Explicit
Const DuplicateWarningTitle = "Duplicate Record"
Const DuplicateValueWarning = "A record already exists with " + _
"the value you have entered. Are you sure you want to continue?"
Function GetSQLLiteral(Value As Variant) As String
Select Case VarType(Value)
Case vbNull
GetSQLLiteral = "Null"
Case vbString
GetSQLLiteral = "'" + Replace(Value, "'", "''") + "'"
Case Else
GetSQLLiteral = CStr(Value)
End Select
End Function
Sub HandleKeyFieldBeforeUpdate(Control As Access.TextBox, Cancel As Integer)
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset( _
"SELECT 1 FROM Customers " + _
"WHERE " + Control.ControlSource + " = " + GetSQLLiteral(txtLastName.Value) + _
" AND CustomerID <> " & Me.CustomerID)
If Not RS.EOF Then
Select Case MsgBox(DuplicateValueWarning, vbExclamation + vbYesNo, DuplicateWarningTitle)
Case vbYes
' just proceed
Case vbNo
Cancel = True
Control.Undo ' if desired!
End Select
End If
End Sub
Private Sub txtLastName_BeforeUpdate(Cancel As Integer)
HandleKeyFieldBeforeUpdate txtLastName, Cancel
End Sub
By pushing the duplicate checking code into a generic helper routine, other key fields can be handled in the same way easily:
Private Sub txtAddress_BeforeUpdate(Cancel As Integer)
HandleKeyFieldBeforeUpdate txtAddress, Cancel
End Sub
I have a sub form in Access:
The CopyNo is a combobox that lets me select from the MovieCopies table. When I select one, I want the Title field to show the correct movie title associated to that copy's movie ID. I also want the format to show. When I select from DaysRented combobox, if I select 1 and the movie is New, I want it to display the price, if it is regular for 3 days display the correct price etc.
I'm just not sure how to give logic to the comboboxes.
If anyone could point me in the right direction of how to do this sort of thing in Access 2007 I'd really appreciate it.
Thanks
Something like this:
Private Sub cboCopyNo_AfterUpdate()
If Nz(Me.cboCopyNo, "") <> "" Then
Me.txtTitle = DLookup("Title", "MovieMaster", "MovieID = " & Me.cboCopyNo)
End If
End Sub
Private Sub cboDaysRented_AfterUpdate()
If Nz(Me.cboDaysRented, 0) > 0 Then
Dim strType as String
strType = DLookup("[Type]", "MovieMaster", "MovieID = " & Me.cboCopyNo)
If Me.cboDaysRented = 1 Then
Me.txtPrice = DLookup("Price1Day", "Price", "[Type] = '" & strType & "'")
Else
Me.txtPrice = DLookup("Price3Day", "Price", "[Type] = '" & strType & "'")
End If
End If
End Sub
Couple notes. Some of your field names are reserved words in certain databases, such as "Type". I highly recommend you try to use field names that are not reserved words in Access or SQL server.
DLookups are not necessarily the fastest way to lookup data but will likely be fast enough for what you're trying to do here. Sometimes I create my own DAO recordset and lookup the values I want rather than using DLookup. It's basically like writing your own DLookup function.
DLookup uses SQL language so your syntax in the third argument, the WHERE clause, needs to match SQL. If the field in your WHERE clause is text/string you'll need to use a single quote on either side of the value (as shown above around the strType variable). If it is a number field you will not need the quotes. If it's a date you'll need hash signs (#).