AUTHOR NOTE: 2021-02-10 – There is a Dynamics 365 Business Central Repo showing how to handle this in Business Central.
I’ll try to update the blog with a new post walking through it, but it’s very functionally the same as below:
Generally speaking, enabling huge text fields in NAV is bad design because it encourages dumping unstructured data into the system. Reason Codes is an example of adding useful, structured data to the system.
But, every once in a while, there’s a legitimate need to write up a large chunk of text. The Notes functionality isn’t bad for that, but try adding that to a Report or a FastTab.
When that need comes along, you can do it natively now using the built-in RTC tools. I’m using a case scenario for a company that performed contractual maintenance tasks for their customers and they needed a free-text place to enter information about the work done each site visit that would then print on a report.
Their interface for it looks like so:
Work Description is their internal notes. Work Performed is their potentially customer facing information. We’ll talk about that. Just to show it off, here’s how it looks as you enter chunks of data:
Table and Functions
First, you need a place for the data to live.
We’ll create it as a BLOB, but there’s a handy SubType we’ll want to set called Memo.
For universal access to the functions we’ll need, two public Functions are just the thing.
SetWorkPerformed sets the value of the blob from a Text (size unlimited) variable using TempBlob’s handy “WriteAsText” function.
GetWorkPerformed does the reverse, returning the raw BLOB text as Text using the TempBlob’s ReadAsText function. That’s it, though you’ll notice we have a couple things in there dealing with Line Feeds and Text Encoding, so you may have to adjust those based on your regional/platform needs.
For easy splicing into your own text objects, here the two functions are in C/AL Text Object format:
PROCEDURE SetWorkPerformed@1220060013(NewWorkPerformed@1000 : Text); VAR TempBlob@1001 : TEMPORARY Record 99008535; BEGIN CLEAR("Work Performed"); IF NewWorkPerformed = '' THEN EXIT; TempBlob.Blob := "Work Performed"; TempBlob.WriteAsText(NewWorkPerformed,TEXTENCODING::Windows); "Work Performed" := TempBlob.Blob; MODIFY; END; PROCEDURE GetWorkPerformed@1220060012() : Text; VAR TempBlob@1000 : TEMPORARY Record 99008535; CR@1004 : Text; BEGIN CALCFIELDS("Work Performed"); IF NOT "Work Performed".HASVALUE THEN EXIT(''); CR := 10; TempBlob.Blob := "Work Performed"; EXIT(TempBlob.ReadAsText(CR,TEXTENCODING::Windows)); END;
Now, the page is pretty simple.
We need Global Text Variables:
We also need to add the controls to the Page:
To get the layout I showed above, I use nested Groups to add the Captions above the Field, rather then to the left, widening the control to a more TextArea style appearance. Then, the Variable fields get a couple key Properties:
- MultiLine: Yes
- ShowCaption: No
We also need our equivalent of Setters and Getters. You can refactor this to Eventing if you want – this customer was on a version that had limited support for it.
First, we have to fetch the values to the Variable. When the page loads a record, we populate the Text variables with our Record’s function.
Then on the Field itself, during OnValidate(), we need to write the info back:
Same as the Page. Use your Getter to load a Text variable, then add that to the Report’s Data model. That simple.
Bear in mind there will still be limits to this field – it’s a BLOB, so you have to jump through hoops to work with the contents. If someone asks if you can filter on it, the answer is “No*”. You could provide a really, really slow MARKED(TRUE); search function that could scan through them, but start with no. If it’s something that needs to be filtered or searched on, it should be structured data.
Hopefully this helps some of you.