Re. subject: how do I do this?
I want to modify the value of a field on a record when the OnInsert trigger for that record is run. But I need to do it using RecordRef/FieldRef and I can't seem to get my head around it.
For instance, say I want to set "Prices Including VAT" on the Customer table to TRUE when running the OnInsert trigger. Usually you would simply insert a line saying
"Prices Including VAT" := TRUE;
But if I try to obtain the same functionality using RecordRef and FieldRef I run into the classic problems:
1) I cannot do a RecordRef.MODIFY because the record has not yet been created.
2) If I do a RecordRef.INSERT I get an error when NAV tries to insert the record .
How do I get the changes made in RecordRef copied back into Rec?
Brian Rocatis
Senior NAV Developer
Elbek & Vejrup
0
Comments
You can't modify what has not been created yet.
The OnInsertRecord function actually has to return (exit) TRUE before the system even considers inserting the record.
I would look into OnNewRecord for anything remotely close to what you're trying to do. (Even though you most likely still wont be able to accomplish what you are trying to do there)
RIS Plus, LLC
I know...
This is on the form. I'm working on the table which kind of limits my options to the OnInsert trigger.
Still on the form.
I'm afraid you might be right.
Senior NAV Developer
Elbek & Vejrup
The field is dynamically referenced (i.e. the user selects which of a set of fields should be populated using a setup table). By doing it this way I don't have to change any code if new fields are added to the table.
Senior NAV Developer
Elbek & Vejrup
Here is a partial solution to do the job. :-k
Suppose we are dealing with Item Table.
In OnInsert() at the last
Name--- DataType--- Subtype
ItRef--- RecordRef
FldRef--- FieldRef
It--- Record ---Item
PrimaryKeyFieldRef--- FieldRef
1)So, after executing this code it has inserted one line in the table with the required field(s) value changed. O:)
2) Another record (blank) will be inserted in the table as (CLEAR(Rec)) :-#
Again, when the user inserts a new record , then
a) the blank line will be deleted
b) A record with desired field(s) values will be created
c) one blank record would be created.
Problem : 1) Blank Record
possible solution : delete blank record from the onTimer() in regular interval OR deleting from the onValidate() of a field of the Item Card for which user is most likely to update value after the default record Insert. Or a batch Job.
Problem : 1) After insert the form shows the blank line inserted corresponding to "rec" instead of corresponding to "ItRef".
possible solution : some kind of tag and/or filter work
I hope it helps O:)
Technical Consultant, MS Dynamics NAV
RIS Plus, LLC
RecordRef works works fine even if the record has not been inserted yet.
If you add the line "RecRef.GETTABLE(Rec)" in the OnInsert trigger, RecRef will contain any fields populated at that time - even though the record hasn't been inserted yet.
The problem is that there doesn't seem to be any way of transferring the modifications done to RecRef back into Rec. The normal way to do this would be to use RecRef.MODIFY but of course this won't work in this case because Rec has yet to be inserted.
It's basically that exact function that I'm missing and therefore trying to find a workaround for :-k
Senior NAV Developer
Elbek & Vejrup
RIS Plus, LLC
RIS Plus, LLC
Well, you're right of course, but why would I want to do that? The problem is not knowing which fields are available/defined, the problem is transferring a value from a RecRef to a Rec which hasn't been inserted yet.
Senior NAV Developer
Elbek & Vejrup
RIS Plus, LLC
I was actually in the middle of writing that I could see no point in what you suggested but then.... :idea:
I'm not sure if this was actually your idea, but this is how I've dealt with the problem:
OnInsert trigger:
In FunctionThatDoesStuff I basically change the value of my dynamically defined field to the desired value (this also worked before) but the twist now is that I clear all the primary key fields before doing a RecRef.INSERT.
Part 2 then retrieves the new (temporarily created) record and transfers all the field values except the primary key fields. It then deletes the temporarily inserted record...
I'm not saying it's the most beautiful piece of code and it has some built-in caveats (like, it won't work if blank primary keys are allowed in the table) but it works, it's simple and the code is fairly generic.
Thanks, everybody! \:D/
Senior NAV Developer
Elbek & Vejrup
could you please share, at what point your "part 2" gets executed. I mean can you elaborate the solution. ("part 2" is also in the OnInsert() ...???) O:)
Technical Consultant, MS Dynamics NAV
Another thought, does recref work with temp records?
RIS Plus, LLC
SETTABLE doesn't work
Let me quote the online help:
GETTABLE (RecordRef)
Use this function to make a recordref variable use the same table instance as a record variable.
Compare that to SETTABLE:
SETTABLE (RecordRef)
Use this function to make a recordref variable use the same table instance as a record variable.
Any filters that are applied to the record are also applied to the recordref. If you change the filter that is applied to the record, you must call SETTABLE again to apply the new filter to the recordref.
It's basically the same function although one applies filters and the other does not. If you ask me it should've been a single function with an "ApplyFilters" parameter.
Also, they should've implemented a PUTTABLE function :P
Senior NAV Developer
Elbek & Vejrup
If I remember correctly from past posts and personal experience, I'm pretty sure this function doesn't work. (it's bugged)
The "Part X" comments are only there for me to use as reference in the text... All of the code lines have been added at the bottom of the OnInsert trigger.
Senior NAV Developer
Elbek & Vejrup
In any case, none of them will transfer information from RecRef to Rec, only the other way round.
Senior NAV Developer
Elbek & Vejrup
Well, Microsoft haven't given us the option to make it pretty ](*,)
I agree with you in principle, but you would need to pass the generated key between the OnInsert trigger and the FunctionThatDoesStuff in order to get that to work. Which in turn means that you would need to code a specific FunctionThatDoesStuff for each unique type of primary key... #-o (i.e. Code20, Code20+Integer, Code20+Code20+Code10+Integer etc.). That's even uglier :sick:
Simply put a LOCKTABLE before Part 1 of my code and that's sorted.
Well, it is... (it would make absolutely no sense at all to keep it - it's basically just a backwards way to transfer parameters).
It does.
Senior NAV Developer
Elbek & Vejrup
You haven't actually tested this, have you? [-X
COMMIT will NOT "flush"/complete the INSERT in progress which means that RecRef.MODIFY will fail with "Rec does not exist". The same fate awaits DELETE.
Senior NAV Developer
Elbek & Vejrup
But I realize now you can't do this only because you're placing this code in the table itself rather than doing it from a form. (Which you could do this from a form)
Yep. Placing the code on the form will result in more modified objects and eventually somebody will forget to add the code to a form where the users insert records and then the sh*t's gonna hit the fan.
Senior NAV Developer
Elbek & Vejrup
RIS Plus, LLC
Perhaps you can give us an example of what exactly you're trying to implement this code for.
This could very well lead to a heated debate
Anyway, I don't agree. Fact is, the code I'm trying to get to work will actually work ANYWHERE in NAV EXCEPT on the OnInsert trigger.
It could also be argued that SETTABLE/GETTABLE really should have a counterpart for moving information the other way (RecRef->Rec as opposed to Rec->RecRef).
But I'm sure we could debate this ad nauseum.
No, I don't. Consider this code (which is part of the now infamous FunctionThatDoesStuff):
This clears all primary key fields regardless of how many there are and which types they are. What this means is that I can use a simple GET without any parameters at all for ALL tables.
:shock: That's exactly what LOCKTABLE was made for... I would think not trusting it to do that would make your life unnecessarily cumbersome.
Yeah, and I appreciate it! =D>
Well, yes, but compared to your earlier suggestion where a separate function for each unique key type needed to be created, this is even worse: in order to get this to work you would need to pass the temporary record (as a VAR) to the FunctionThatDoesStuff. That means that you'll have to write a function for each table (although you'd get rid of the unique key type problem as you'll now have a function for each table).
Again, consider the code that I need to add to each of the tables I want to support my function:
I need to copy/paste these 6 lines verbatim into the OnInsert trigger on tables I need to support and create 2 local variables - RecRef (which doesn't change) and DummyRec which is a record of the table I'm currently working on. I don't need to change any code and I only have 1 function to maintain. DummyRec is inserted and deleted within the same LOCKTABLE, it's not COMMIT'ed, and FunctionThatDoesStuff is close to instantaneous.
As far as I can see there's simply no contest. But hey, we're talking religion here. [-o<
Senior NAV Developer
Elbek & Vejrup
It's part of a generic synchronization functionality I'm developing. That's why I need the code to be absolutely generic.
Consider this: I now have a system which allows any table to be synchronized across companies, complete with options to prevent users in the synchronized companies from creating, modifying or deleting records OR allowing them to create "local" records which they have full control over. This has been obtained with fully transparent code added to 5 functions in Codeunit 1 and the 6 lines shown earlier added to the OnInsert trigger ONLY for the tables where I want the users in the synchronized companies to be able to create "local" records. Additionally, a single non-editable Boolean field needs to created on these tables.
Specifically, I need the functionality we've been discussing because I don't know which tables will need to have "local" functionality (and I'm not very keen on creating a Boolean on all tables :roll: ) and I don't know what number that field will eventually have. So in my setup table I need to be able to specify which field is the "local" denominator for the tables that need "local" functionality - and I need to populate that field when the user creates a "local" record. I.e. in the OnInsert trigger.
There's some complex hokey pokey going on in order to get all this to work, and it's not flawless, but it solves a LOT of the problems we run into on a daily basis with a minimal amount of modifications.
Senior NAV Developer
Elbek & Vejrup
Anyway this is starting to turn into a pissing match, and I have no desire to win that. Good luck with your solution, I hope you'll get it to work.
RIS Plus, LLC