If you ever worked on multiple Business Central extensions, you may know the struggle with dependencies.
The Issue
When we need to access a table, page or anything else that come from another extension, then you need to set your own app depending on it, and this happen quite often. This drive to two major struggles :
- Business central do not provide “conditional” dependencies, so your app can’t be both independant and comptabible with other app if they’re installed.
Eg: An ISV have 2 independent app, but the 2 can also be used together and interact with each other.
In this horrible case you’ll need to maintain an additional app combining them two, or a third app for doing only the connection betwen them. - When updating or reinstalling an app, other extensions whom depend on it may be uninstalled and forgotten (depending BC Version)
Solution
Let me share a solution who can help working without dependencies and still interact with other Business Central extensions.
I called it Reference Helper, as it’s basically just a codeunit that could access other app records without the need of dependencies. It use a nice mixture of references and metadatas.
Bonus : it also allow to read and write table from other extensions who are not accessible (Access = Internal).
Exemple
Following sample code will manipulate Customer record.
It will search for a specific customer, insert it if it dosn’t exist.
Then search for a customer with existing balance and return the name
Then search for a customer with existing balance and return the name
All this can be done without dependence on Microsoft Base Application.
Try it yourself, AL project : RecordReferenceHelper.zip
var RefHelper: Codeunit "Reference Helper"; RecRef: RecordRef; // Open table RefHelper.OpenRecRef(RecRef, 'Customer', false, CompanyName); // Insert dupont if not RefHelper.Get('DUPONT') then begin // you have to know the Primary Key of the table RecRef.Init(); RefHelper.SetFieldValue('No.', 'DUPONT', false); RefHelper.SetFieldValue('Name', 'Mr. Dupont', false); RefHelper.SetFieldValue('Credit Limit (LCY)', 10000, false); RecRef.Insert(true); Message('Dupont Inserted'); end else Message('Dupont already exists'); // Search Customer with balance RefHelper.SetFilter('Balance', '>0'); if RecRef.FindFirst() then Message('Customer found sucessfully using Reference : ' + format(RefHelper.GetFieldValue('Name')) + '\ Balance : ' + format(RefHelper.GetFieldValue('Balance'))) else Message('Unable to found Customer with balance > 0');
How to use it
– IsExtensionInstalled(ExtensionName: Text; ShowError: Boolean): Boolean
Tell you if an extension matching the provided name is currently installed.
Tell you if an extension matching the provided name is currently installed.
– LookupCustomTable(TableName: text; FieldNameToReturn: Text[50]): Text
Open a lookup list page for the provided table. Return the selected user value of specific field name.
Can be used as alternative lookup feature on table from external app without need of dependencies.
Can be used as alternative lookup feature on table from external app without need of dependencies.
– OpenRecRef(var RecRef: RecordRef; TableName: Text; IsTemp: Boolean; Company: Text)
Open a RecordRef on a specified table. Work fine even if the table it from another App without having to specify the dependencies.
Open a RecordRef on a specified table. Work fine even if the table it from another App without having to specify the dependencies.
– SetFilter(FieldName: Text; FieldFilter: Text)
Same as standard SetFitler, applied on previously open record reference.
The field name have to be provided in text.
Same as standard SetFitler, applied on previously open record reference.
The field name have to be provided in text.
– SetRange(FieldName: Text; FieldFilter: Variant)
Same as standard SetRange, applied on previously open record reference.
The field name have to be provided in text.
Same as standard SetRange, applied on previously open record reference.
The field name have to be provided in text.
– Get(PKValue1: Variant; [PKValue2: Variant …]): Boolean
Same as standard Get function, applied on previously open record reference.
– GetFieldValue(FieldName: Text): Variant
Return a field value of the previously open record reference.
The field name have to be provided in text.
Return a field value of the previously open record reference.
The field name have to be provided in text.
– SetFieldValue(FieldName: Text; FieldValue: Variant; ValidateField: Boolean)
Affect a value to previosuly open record on a field provided in text.
This function will control the value type passed match the destination field.
Affect a value to previosuly open record on a field provided in text.
This function will control the value type passed match the destination field.
– ValidateField(FieldName: Text)
Same as standard Validate function, applied on previously open record reference.
The field name have to be provided in text.
– FieldError(FieldName: Text; ErrDescription: text)
Same as standard FieldError function, applied on previously open record reference.
Same as standard FieldError function, applied on previously open record reference.
The field name have to be provided in text.