get last record in navision 2009

I am using navision 2009 and want to get the last record of a table. I try it like this:

//Begin insert contact:

IF “”.“Digital shipment” = TRUE THEN BEGIN

//MESSAGE(‘ja’);

KlantContact.INIT;

KlantContact.Type := 1;

KlantContact.“No.” := KlantContact.“No.”.FINDLAST; //‘1127’;

MESSAGE(KlantContact.“No.”.FINDLAST);

KlantContact.Name := ‘Crediteuren administratie’;

//MESSAGE(KlantContact.“No.”);

// END;

KlantContact.VALIDATE(KlantContact.“Company No.”, BussinesContactName.“Contact No.”);

KlantContact.INSERT;

END;

Thank you

Hi

Presuming KlantContact is the contact table so why are you trying to get the last record on the whole table? By the look of the FINDLAST code you are assigning the contact number as the same as the last number in the table.

Sorry not sure what you are trying to achieve.

Neil

Niels, it seems you are trying to do your best, but, if I may say so, you have to learn a lot about C/AL programming (join of my classes :wink:

Like Neil, I am also not fully sure what you want to accomplish, because why do you want to find the last record and then based on that create (i.e. insert) a new one?

In NAV master data like contacts, customers, etc. (and also documents) get a value in their primary key field (called No.) by means of the number series functionality (see for example https://community.dynamics.com/nav/b/navmarkbrummel/archive/2014/03/07/tip-21-implementing-no-series).

But just looking at your code as is, I would have written it like this:

Some additional tips and remarks:

  • Use only English in your variable names: CustomerContact instead of KlantContact; or maybe just Contact
  • The first parameter in VALIDATE doesn’t need a reference to the record variable again
  • Leave out-commented code away when asking for help
  • FINDLAST returns a boolean so it doesn’t make sense to assign it to a Code type field/variable
  • The Type field on the Contact (presuming it is table 5050) is an option field, so do not use a numerical value to assign to it, but use the option value. See https://msdn.microsoft.com/en-us/library/dd355166.aspx
  • Only use alphanumerical characters in variable names. should then be Customer

But … using the number series functionality the code could just simply come down to:

IF Customer.“Digital shipment” = TRUE THEN BEGIN
Contact.“No.”:= ‘’;
// Empty primary key field
Contact.Type = Contact.Type::Person;
Contact.Name := ‘Crediteuren administratie’;
// shouldn’t this be inherited from the Cutomer record?
Contact.VALIDATE(“Company No.”,
BussinesContactName.“Contact No.”);
// where does this “Contact No.” come from?
Contact.INSERT(TRUE);
END;

Notes:

  • INSERT(TRUE) will fire the OnInsert trigger on the Contact table before inserting the record in the database as the primary key “No.” field is empty and will assign a unique value to “No.” allowing the record to be inserted into the database without a primary key violation (i.e. trying to insert a record with a same primary key value that a record in the database already has)
  • Still do not exactly know the context of this code and what you want to achieve with it; for example why do you check IF Customer.“Digital shipment” = TRUE THEN BEGIN?
  • Instead of IF Customer.“Digital shipment” = TRUE THEN best practice is to write IF Customer.“Digital shipment” THEN
  • Might even call VALIDATE for the Name field to ensure the code in the OnValidate trigger of this field it being executed:
    Contact.VALIDATE(Name,‘Crediteuren administratie’);
  • This also brings makes me wonder why you assign a hard coded value to Name, but probably this is just an easy way to get data in that field for the sake of your example

As you can see, Niels, there is a lot to your code example to be said and, not knowing the context and exact goal, I took the risk of stepping in and to try to make something, more NAV like, out of it.

Rereading your first line (I … want to get the last record of a table) the most straight forward answer would have been (to get the last record):

Contact.FINDLAST;

But apparently, seeing a lot more code, you are wanting more. So for next time try to be somewhat more specific on what you want to achieve.

Hope it makes sense to you, still.

Hi Luc,

Thank you for your reply. Because I want to add an extra contact if Crediteuren administratie is not in the table. So I try to do: last contact + 1. Like this:

//Begin insert van Crediteuren administratie contact :

IF “”.“Digital shipment” = TRUE THEN BEGIN

KlantContact.INIT;

IF KlantContact.FINDLAST = TRUE THEN

KlantContact.Type := 1;

KlantContact.“No.” := INCSTR(KlantContact.“No.”);

//KlantContact.“No.” := ‘’;

KlantContact.Name := ‘Crediteuren administratie’;

KlantContact.“E-Mail” := EmailDigitalefactuur;

KlantContact.“Invoice recipient” := TRUE;

KlantContact.“Reminder Recipient” := TRUE;

KlantContact.VALIDATE(KlantContact.“Company No.”, BussinesContactName.“Contact No.”);

KlantContact.INSERT;

END;

//end contact

But it seems that this doesnt work

[Arg … just made some remarks on better coding and then you provide the same, sorry to say, ugly code.]

Let me first pose a simple question: How do you know “Crediteuren administratie” is not in the database? I see no code checking that.

Hi Luc

Ok, I have tried your suggestion. But the problem is that I will get the following warning: soort moet Persoon zijn in Contact Nr.=9912. So that’s why I have tried like this:

//Begin insert van Crediteuren administratie contact :

IF “”.“Digital shipment” = TRUE THEN BEGIN

KlantContact.INIT;

IF KlantContact.FINDLAST = TRUE THEN

KlantContact.Type := 1;

KlantContact.“No.” := INCSTR(KlantContact.“No.”);

//KlantContact.“No.” := ‘’;

KlantContact.Name := ‘Crediteuren administratie’;

KlantContact.“E-Mail” := EmailDigitalefactuur;

KlantContact.“Invoice recipient” := TRUE;

KlantContact.“Reminder Recipient” := TRUE;

KlantContact.VALIDATE(KlantContact.“Company No.”, BussinesContactName.“Contact No.”);

KlantContact.INSERT;

END;

//end contact

and an extra contact with the name: Crediteuren administratie is added. But the problem is now that the new contact with the name Crediteuren administratie has primary key: 9913. But the ‘normal’ contact has primary key: 46069. So it will be nice ofcourse to have the contact name Crediteuren administratie 46070. So that 's what I mean with Last contact + 1. But how to archive that? Thank you.

I hope I am more clear now.

Thank you

But what is the answer to my last question? One thing at a time.

{And yes, you get that error, but have a look at my second code and combine.]

Ok. I posted new comment. I hope you understand what I mean now. But ofcourse thank you for all your help

Still no answer to my last question, Niels. Sorry to insist, but this way we are heading nowhere. So let me repeat it: How do you know “Crediteuren administratie” is not in the database?

And BTW, I am Dutch and can read the Dutch error messages, but in general your fellows out here are not Dutch, so run your application in ENU so you get ENU messages which you can past in your posts here.

I can see bij Verkopers that a new record is made. So there I can see if the record is Crediteuren administratie" added or not. And I can also look in the table contact if the record is added. But so my question is how to make the new record with a increment number. So if my last record is for example: 4006, so Crediteuren administratie has to have primary key: 4007. Thank you.

And yes I have tried this:

KlantContact.“No.” :=’’;

But it then generated an empty record

Sure you as a human can check whether the record is there, but how does the code know (see my initial addition to my question: “I see no code checking that.”)?

This becomes to long and complex to discuss, Niels. Sorry to say, but you really need more background on how to program NAV.

Oke, I solved like this:

//For insert the contact Crediteuren administratie:

CreditContact.RESET;

CreditContact.INIT;

CreditContact.Type := 1;

CreditContact.Name := ‘Crediteuren administratie’;

CreditContact.“E-Mail” := EmailDigitalefactuur;

CreditContact.“Invoice recipient” := TRUE;

CreditContact.“Reminder Recipient” := TRUE;

CreditContact.VALIDATE(“Company No.”, BussinesContactName.“Contact No.”);

CreditContact.INSERT(TRUE);

but in the OnPostXMLport(). Thanks

Congrats and of course keep on trying. However, do you want to create every time a new contact with Name “Crediteuren administratie”. You still do not seem to check (at least not with this code) whether it already exists or not?