I'm trying to prevent circular (or even cascading) references in my data, and it seems it's only working part of the time.
In Access 2007, I have the following table:
create table mfr (
mfr_id Autonumber,
mfr_nm Text(255),
mfr_is_alias_for_id Long Integer
)
I'm importing a bunch of data from Excel, and the mfr_nm is one of the columns from the worksheet. I can't control how data gets entered into Excel, so I want a way of capturing alternate spellings as being "really" same thing. So far, so good (I think...).
Now I've built a form off of this table. I've got a ComboBox for the alias--again, so far, so good. However, when I add this code to the BeforeUpdate event, things get "interesting" (error handling omitted):
If Not IsNull(cboMfrAlias) Then
If Not IsNull(DLookup("mfr_is_alias_for_id", "mfr", "mfr_id=" & cboMfrAlias)) Then
MsgBox """Alias for"" must not also be an alias.", vbExclamation
Cancel = True
End If
End If
This works exactly as I expect it to when the form is in Form View, but if I'm in Datasheet View my MsgBox is immediately followed by an Access-generated "No current record" error that is not caught by error handling within the BeforeUpdate sub.
Can I catch this error? Where?
Your dropdown list should filter out entries that are aliases. In other words, don't display a choice the user can't make.
You'd do this by simply eliminating from the dropdown the choices where mfr_is_alias_for_id Is Not Null.
I've implemented this in various guises and it works fine.
I'm addressing the "No Current Record" error part of your question, from so long ago. After checking google for an answer, I found this link which was helpful. However, instead of using NZ() to transform the troublesome binary field in an aggregate query, I used troublesomefield: IIF([troublesomefield] IS NULL,NULL,[troublesomefield]) and this worked to banish the error. So my solution is only a small variation on the original answer I found, but it gets around the error and let you keep nulls if you want to...
Related
I am working on a database to store a heap of animal behavioural observation data and am working on creating a form to input data (one of many forms). The main form feeds into a table called "FocalSample" and the subform feeds into a "FocalData" table.
This is the form at present
There will be multiple records in the subform to a single overarching sample, a sample is a 10 minute period and a single animals behaviour is documented over that 10 minutes, noting time in minutes and seconds to calculate duration of time spent in each behaviour.
I need popup forms to come up depending on what is selected in the "Behaviour Type" field of the subform, as the kind of data recorded for a "feed" observation compared to a "social" observation is very different. I have created separate tables for the different behaviour types of data and forms that are set as "popup" forms, but need help with the code to get it to do what I need! :P
I have been trying a variation of the following code that I found here (http://www.justskins.com/forums/pop-up-form-based-238440.html)
Private Sub Campaign_AfterUpdate()
Dim strFormName As String
Select Me.Campaign.Value
Case "In Honor", "In Memory"
strFormName = "HonorMemory"
Case "In-Kind"
strFormName = "InKind"
End Select
DoCmd.OpenForm strFormName, , , , , acDialog
End Sub
But I keep getting an error message after the first row.
Here is the error and code screen
Similar to the other forum link I attached, I also need the popup form to draw a lot of info from the main form, but I'd just be happy to be able to get the popup forms working at the moment.
Sorry for so much detail - I am in a remote area of Africa and only have limited access to internet so am trying to give as much info up front!
Example of popup form - you might be able to determine fields that will feed off the focalsample form
Another example of a popup form - different behaviour type to the previous
EDIT
I have jigged the code now based off previous response but am not getting a different error.This is the code with the error line highlighted - I am not sure what table name to add if any
Error code
The line Select Me.Campaign.Value should read Select Case Me.Campaign.Value.
I have a table in my Access database where I keep track of my jobs. I have a form based on a query based on this table. In my table there is a field called [file_path]. This is a field that controls a web browser on my form.
I would like this field [File_path]to be updated when I update my field [customer_Id] on the form. It should be updated to reflect the customer name together with the file path e.g. C:\Users\Windows8\Documents\Projects\Doe John.
How do I pull the [Customers]![Last_Name] and [Customers]![first_name] into my string in field [file_path]?
I think that I have to use VBA code, but not sure how. I have started with this:
Private Sub Customer_AfterUpdate()
Me.File_path = Me.Last_Name
End Sub
I know that this is a feeble beginning. Does someone know how to help me? Please tell me if my question is not clear.
Beside all this the above code is returning Invalid outside procedure in Private Sub Customer_AfterUpdate(). Why?
Me refers to the form. You are correct that using Me is best practice (speed, ease of coding, etc.), but when I was starting out or even now in a complicated application I like to write it out, because that reminds me not to make little mistakes like this. Or, maybe your memory is better than mine, in which case ignore and read on.
[file_path] is in the table, so you need to access it in the table. Your code looks for it in the form, and realizes that it isn't inside Me, and throws this error.
I am going to give you a line of code below that should be a good starting point for you, but I think you may need to examine your calling event. AfterUpdate is cool, because it just seems to happen automatically, but I don't think you want your field updated every single time anything in the whole "Customer" form is updated. If there is a specific textbox that is always updated last (last_name?), you could try that one instead, but I would be nervous about trying to remember to always make sure that was the last one that I updated... I mean, if one day I accidentally did the name before the customer_id, I would have some serious confusion on my hands later on. Might I suggest a command button, and using the Click event instead?
No matter what event you end up using, you really only need one line of code inside your event. There are plenty of ways of doing this. Might I suggest something along the lines of CurrentDb.Execute "update " & myAwesomeTableNameHere & " set file_path='"C:\Users\Windows8\Documents\Projects\" & forms("customers").controls("last_name").text & " " & forms("customers").controls("first_name").text & "' where customer_id='" & forms("customers").controls("customer_id").text & "'"
Now, a caution: data is precious, and beautiful. The names of the people who pay you are even more so. Changing data in a pre-populated table by free-typing into a textbox on a form sounds like disaster waiting to happen to me. If it were me, I would either 1)make backups very often (easist), or 2)validate your entries multiple ways before writing anything to the table.
There are a sequence of forms A -> B -> C etc.
In A, parameters are asked from the users that will work as a where-condition for the table subset shown in B (with the DoCmd.OpenForm and "Detail"-method).
I also use the parameters in A to make a nice caption in B.
Problem 1: If there is no hit whatsoever in B (0 records shown), the parameter used for the caption (i.e. the search keyword for B's table contents) is lost, so I get an error. I tried to work around this by sending the parameter as an "open argument" as well - that will give the correct caption, only no search result (that is, correct result, if there is no hit). But, then, if you open the form from any other place, like the form menu in Access, you get the error.
Problem 2: I would like a "Back" button (A <- B, B <- C, etc.). I did it with just close first, but then I sometimes ended up in unexpected places. To use the above solution backward - well, first, it doesn't even work forward, second, even if it did, it seems so inefficient because that part of the search has already been done.
I described the problem from my view and experience, but don't feel "locked" by that. If you know an altogether different approach, please tell me.
Perhaps you can eliminate the error in the OpenArgs approach if you revise the code to only attempt to use OpenArgs when a value has been passed.
If Not IsNull(Me.OpenArgs) Then
' do something with OpenArgs
End If
Creating a simple UI using MS Access, hoping to do minimal actual coding (actually helping a friend who is not a coder).
Simplified requirement: Single table, primary key is phone number, lots of other non-mandatory fields. Display a form allowing just the phone number to be entered, if a record with that key exists display the full record, if a record with that key does not exist bring up an form allowing the other fields to be entered for this phone number and hence create a new record.
Q1: Any simple way to achieve this kind of function? Example?
We've got some of this going with a standard form, can execute code if insertion fails, but a standard dialogue box is displayed warning about the duplciate key violation.
Q2: How can we trap that attempted insertion, avoid having the dialogue come up?
You will have to get your hands dirty and write some code to get this outcome. A starting point would be something like this presto code. Post back if you get stuck on any of the parts.
If fCheckIfRecordExists(lYourKey)=True then
Docmd.OpenForm “frmEditExistingRecord”
Else
Docmd.OpenForm “frmEnterNewRecord”
End if
Public function fCheckIfRecordExists (lYourKey as Long) as Boolean
‘Code to check if a record exists, simple method is to use dLookup or a count SQL statement with the criteria as the key you are trying to find
End function
EDIT:
First things first make a form with 1 text box called txtPhone_number and a command button called cmdSearch.
Next put this bit of code in the module behind the form
Public Function fDoes_record_exist(strPhone_number As String) As Boolean
If DCount("Phone_number", "tblYour_table", "Phone_number=" & strPhone_number) > 0 Then
fDoes_record_exist = True
Else
fDoes_record_exist = False
End If
End Function
Next you need to put some code behind the click event of the command button. This code can be expanded on to check for a valid phone number later if you want
If fDoes_record_exist(Me.txtPhone_number) = True Then
DoCmd.OpenForm "frmShow_existing_record"
Else
DoCmd.OpenForm "frmEnter_new_record"
End If
That should set you on your way nicely but post back if you run into problems
Here is an overview of the process with Access logic:
You need an unboud control labelled Phone in the form header, where user will be able to enter the phone number to search. You need to use the After_Update event of that control to trigger your search. There will be a second Phone control, bound this time, in the Detail section of the form for effective data entry/update.
Use the Form_Error event to intercept the error message when user tries to save a duplicate key, in order to display a nice message, and eventually Cancel his changes.
The advice from Kevin Ross to use VB Code is clearly one approach, and I think is appropropriate if we anticipate less trivial requirements in future. However I'm in a situation where I'm helping someone with zero coding background and hence if possible I'd prefer to let them use simple Macros rather than full-scale VB.
As it happens the functionality I require can be implemented with just Macros, and it depends on the suggestion from iDevelop.
The outline of the solution I used:
Create an InitialEntry form with no association to any particular table, it has:
a data entry field for the telephone number
a read-only text box where I can display a message
a button labelled Add
a button labelled Show
I write three macros:
A macro AlreadyExists that displays a message saying "We already that one"
A macro NewEntry that opens a data entry form for my table, in Add mode, and which copies the phone number from InitialEntry!TelephoneNumber
A macro TestForExisting this uses a condition
DCount("*","MyTable","[PhoneNumber] = [FormPhoneNumber] " ) > 0
to control whether to execute AlreadyExists, and a similar test to control whether to call NewEntry.
While this is not as efficient as VB, it does seem to be understandable by a non-coder, so at least we can implement our application.
Ok so I hope the title of the question matches what I about to ask, but here is what I am trying to get at:
So I have an access database that uses a number of unbound forms, and the purpose of the forms are to collect data and save to various tables with VBA click events using SQL statements (INSERT or UPDATE based on whether the ID of the record is present on the form in a hidden text box). When entering a new record (via INSERT), I get the row number with
MyRow = db.openrecordset("SELECT ##Identity")(0) 'thanks David
So you maybe getting the picture. If I have another form that relates to the first form in terms of the record, I just open a recordset and pass that value to another hidden text box.
So my question is, is there a better way to do this regarding passing that value (or just using that value) using a variable instead of this awkward method. So I realize a lot of folks are going to go with the obvious answer of, "Why not just make your forms bound instead of all this code"...and I am sure that is a valid answer, however I inherited this database which was already put together like this, and re-structuring it would be a daunting task.
Any and all advice, or learning resources are greatly appreciated, as they always are!
I use unbound controls on forms for all these kinds of values. The current solution of using an unbound form is sounder than using global or form level variables. If I recall the details correctly while debugging code and you hit the stop button you lose all global or form level variables. Or if the user hits an unhandled error.
Have you looked at OpenArgs?
DoCmd.OpenForm "Form1", , , , , , "Hello"