Access, After Insert and the missing ID - ms-access

I'm have to create an access web database and running into a frustrating problem when inserting a record into a table.
I'm trying to use the After Insert macro to set a problem number field, thusly:
Edit Record
SetField
Name: [Problem Number]
Value =: [ID] (There is no more logic here but even this simplest case fails)
The problem is that ID doesn't have a value so Problem number ends up blank.
This logic works on an After Update which makes sense as it has an ID at that point.
Is there anyway I achieve this without switching to VB code.

A few things. You do not want to use the after update event to modify the current record since it would in theory cause the before update event and the after update event to fire AGAIN. This potentially would cause a circular loop.
And if you think about this it makes little sense RIGHT after you JUST saved the record all nice to the table then you edit the record again! In fact you find by design that the current record in context is read only in that after update event. So you cannot execute an edit record on the current record in context in the after update event and you get a "read only" error if you check the error log.
In the before change event, [id] is not available. However, you can most certainly pick up and use the [id] in the after update event.
However, if you are going to create a NEW record in another table, then the NEXT line outside of the create record block allows you to pick up the just created record with
[LastCreateRecordIdentity]
So the record write occurs on the next line outside of the create record block.
For example here is some code that creates a new record and note VERY careful the "indentation" of the code.
If fact if you click on the create record command in the above then the WHOLE create block of code will highlight. Note how the NEXT line of code is OUTSIDE of the blue code block and that is the code where we can use [LastCreateRecordIdentity].
The blue highlighted code is thus this:
So the NEXT line right outside of the create record is when you can pick up the new id. In the above I actually "return" the new id just created via the returnVars to the calling routine.

Related

Referencing Just Added Record When Using Call to VBA in AfterInsert DataMaco

Access 2016, table with a AfterInsert datamacro.
In a comment to a previous question that I can no longer find, Albert D. Kallal (user:10527) noted that if one uses the Set LocalVar approach to call a user-defined function in vba, that vba "session" does not see the newly inserted record.
Even if one passes in the identity of the newly added record, any queries referencing the table where the record was just added won't see the newly inserted record.
Has anyone developed a work around so that for example in building a closure-table, the newly added record is visible or can be used?
This is very similar to the problem Alberta Kallal has nicely shared solutions for of copying over an existing record using the "after update" approach to get around being unable to create a record within a for each loop. However, in this case I would like to use the result of a query as the basis for copying / inserting, not just copying over an existing row or 'hard coding' the business logic for the modifications into the datamacro (hence would be easy to do if vba approach could see the just added row).
Specific use case is trying to create a way of inserting "induced" records in an accounting application. One earns some money that has no tax deducted, so it is nice to have an automatic journal entry created showing a future liability to pay the tax. In other words, the presence of a record in a table should automatically generate additional records - and the business logic of those additional records is defined through queries.
Even more specifically, given a "transactions" table with fields RegisterID, AccountID, Amount, TrDate, and a "Induced Transaction Queries" table that specifies the queries to provide the induced transactions with fields AutoNumberId, QueryThatDefinesAdditionalTransactions (and multiple rows, e.g. "Query That adds self", "Query That Adds Tax Liability", "Query That Computes Sales Tax Portion"),
how can a datamacro create rows in a "Transactions For Analysis" Table based on iterating over the "Induced Transaction Queries" table and inserting the results of the query in each row applied to the newly added row in the original "transactions table"
Thx
Well, while calling VBA from the macro after insert event can’t get the row just inserted, that VBA routine can read + update as many OTHER rows as you please. And if that new row or data you write out in VBA has to include the data from the row just inserted?
Well pass the columns to the VBA routine. So it now can go add up all the other rows, and THEN include the values just passed from the data macro.
So the data macro (after insert) can look like this:
And the VBA code thus can look like this:
Public Function AfterU(vid As Variant, Amount As Variant)
Debug.Print vid, Amount
Dim rst As DAO.Recordset
' open table, sum data
' add Amount passed.
' write out data to some table.
' caution - don't add reocrds to this table that has the trigger
' else you wind up in a endless loop
End Function
The above of course has to be placed in a standard code module (not forms), and has to be defined as public as per above.
So while you find that the record JUST added is not yet committed to the table (it is about to be), you can still run + call some VBA code. You just not get your hands on the record just (about to be) inserted.
However, since you can pass the needed columns such as amount etc. to include in the final total? Then you are free to write as much VBA update and insert code as you wish. So you can pull some records, build a total, and now update some existing record, or even add a new record. Just include the new amount passed also.
As noted, you don’t want to “tangle” up writing to a table that has such a trigger with VBA inserts since you can easy get stuck a endless loop.
However, for adding up, or updating, or inserting to another table, you should be fine to do what you please in the VBA code.

MS Access "Write Conflict" error when adding new field to record source

I want to preface this by saying I don't have any real programming background, I'm just trying to update an existing database at work.
We have an access database and I want to add an additional Y/N checkbox to an existing form. The form updates a SQL table. Currently the record source is a SQL statement.
I can go to the SQL table, add a new field and make it Yes/No data type. There are other Yes/No fields in the table and the default settings for the new field are identical to the others. I next go and update the linked table through External Data in the ribbon. I can go into the table in Access and see the new field - so far, so good.
Next, go to the form design view and form properties, go to the record source, update the SQL statement to include the new field. (I've also tried this thru query builder, same result.) From here, I start to get the error.
If I go back to form view and change any data in the form and hit the next record button or save button, I get the Write Conflict error. "This record has been changed by another user since you started editing it..." The 'Save Record' button is greyed out. I am the only person accessing the database or SQL server.
I've tried to finish building the new button and linking it to the new field in control source (that went fine), but it didn't make any difference. If I go in to edit the record source and remove the new field, everything works again (but of course, the new field isn't in the control source list, so isn't linked to the check box).
Any ideas? Thanks.
A strong contender for the reason for your problem is the form itself.
Most likely the form is setup with a specific query as the Record Source. Its not to say that that is inherently incorrect, but it makes adding new columns to the source significantly more difficult.
The problem would likely be solved if you just changed the Record Source to reference the table itself, rather than a query, if that is in fact how it is referenced.
If Ms Access tries to pull data from a table using a query through a form it will inherently Pessimistically Lock the table in question, making it unable to be modified. However, you can usually still modify the table through the query itself, but you would need to add the column changes into that query first.
I'm not quite sure if I am making sense here, but something like this (for a table called "Table1"):
In theory, if the form is the problem... then if you closed it and tried to make modifications to the table, then the changes should work when the form is closed.
Someone else fixed it for me, but from what I understand, it was a communication issue between SQL and Access. Something with the setting of the null value in SQL not being set the way that Access could understand.
We had the issue narrowed down. When the new field was added to the table, you couldn't change any info directly in the table, but you could with the form.
If you added the new field to the form's record source, you couldn't edit any info at all.
Thanks for everyone's input.

Access Trigger - Create table row on update

i'm wondering if anyone has a solution for an issue i'm currently having with my Access database.
The database has a number of tables. Once a new record is added, i'd like to create a new entry (copying over the account name and phase automatically if it doesnt exist) into another table - saving others having to manually enter it & minimising the risk of incorrect data input.
I've tried an onChange update function, and while this works, it doesn't check if the entry currently exists in the other table, it just adds it.
Any ideas on implementing this?
If you can use VBA, this logic should work.
IF ISNULL(DLOOKUP("FieldName","TableName","WHERE CONDITION")) = True Then
DoCmd.OpenQuery "QUeryNameForAppendRecord"
Else:
DoCmd.OpenQuery "QueryNameForUpdateRecord"
End If
The DLookup is checking to see if the record exists, so substitute the field and table names accordingly. Use the Where condition to specify which record you are looking for and you will need to use it to reference your form controls. See link for further help in syntax/referencing.
DLookup Function

MS Access trigger?

I have two tables named [Insert_Record] and [Delete_Record] in MS Access. Both tables have the same fields but one table has records whereas another table has no record.
Question: I want, whenever I delete any record from the table [Insert_Record] that entire record should automatically insert into another table, i.e: [Delete Record].
How can I accomplish this?
Access 2010 introduced event-driven Data Macros that are similar to triggers. The process described in the question can easily be done with an After Delete data macro on the [Insert_Record] table:
As I understand it, Access doesn't have triggers.
The best you can probably do is put this sort of logic into the forms that edit the table. In other words, handle the deleted event at the form level and put your insert logic there.
If you want triggers, you'll want to use a proper RDMS that supports them (MySQL, MS SQL, Oracle, many others).
EDIT: Another way to do this (which may or may not work for you) would be to add a boolean column 'IsDeleted'. That way, you can just logically delete a record instead of moving it to another table. The downside of this approach is the deleted records stay in the main table which could cause performance woes if there are lots of deletes.
Create an append query, to add records into the second table, that is executed in the On Delete Confirm event of the form you are using to delete the record from the first table.
I imagine this 'Delete' is button driven...
So program the button to first Insert the record into one table before deleting it.
Just add the VBA for the insert above the delete.
Another method which nullifies your need for another table entirely is just one column that is a boolean... Active Yes/No (Default to yes.)
If Active then it is not actually deleted when they hit delete, just set the flag to False then nothing is actually deleted, no SQL code is required and there is no risk, you can even have a column with the user who updated it print in another column
Me.Active = False
Me.UserName = 'CurrentUser Location here
Me.RecordSet.Requery
Then there is no risk of actually losing anything is there and you have a record of who flagged it last.
In the continuous form just add the Where flag Active = True then no false flags will show and it looks to the user base as if it was deleted.

Is there a way to override automatic record updating of Access 2007 forms created with Form Wizard?

I'm new to Access VBA, and have created a form using the Form Wizard that displays records in a table. That's a piece of cake.
The behavior that I get with the form, though, is that updates to the records occur automatically when I move around records.
What I'd like is to have the updates occur only when I click an "Update" button that I put in the form.
It seems like I can construct the form from scratch, update all of the (unbounded) controls programmatically, and then update the record from the controls programmatically, but this seems like too much work.
Is there a way to "turn off" the automatic updating behavior from within Access, or using VBA code?
Thanks!
As Robert suggested, you can avoid saving a changed record by canceling the before update event. The code would look something like this:
Private Sub Form_BeforeUpdate(Cancel As Integer)
Me.Undo
Cancel = True
End Sub
However, that approach requires you discard any changes you've made to the record before you can move off it. Without Me.Undo, you can cancel the update, but Access won't allow you to move to a different record. You must either save or discard the changes to the current record before moving to another.
If you want to move to another record but not discard changes first, I think you need to try a disconnected recordset. It's an ADO recordset you create in memory, not bound to any data source. You can add a command button to save your changes on command. If it sounds useful, see this article by Danny Lesandrini at Database Journal: Create In-Memory ADO Recordsets
If users are accidentally changing data and moving record to record causing updates, maybe you should have an Edit button to only start editing when needed. You can use other suggested code to either undo the changes if they move to another record or prevent them from moving at all unless they save or cancel.
Is there a way to "turn off" the
automatic updating behavior from
within Access, or using VBA code?
You can try cancelling the Form.BeforeUpdate event, unless a flag is set. When the button is clicked, set the flag, set Form.Dirty to false (to save the data), and then clear the flag in the Form.BeforeUpdate event handler.
Why would you want to? Access works on a record by record basis. Not like Excel which only saves the spreadsheet when you choose to save or exit.
It sounds like you have a continuous form with multiple records on the screen. The only way to do this would be to use a "temporary" table and the save the contents of the "temporary" table to the permanent table once you're ready. However then you will lose the ability to determine if someone else has changed the records unless you do a lot more work.