Howto add item images to the Sales quote report

Not often, but it can be, that a client wants product pics in the lines of a report, e.g. the sales quote is a candidate for that. So the client can present his products in a more convincing way. 😉

I researched for a solution in Business Central, but did not find any solution, especially when using a word report. But i found my own way, as always.

For that follow these steps:

1) Copy the standard sales quote report, also the layout to a new custom report, set new object id (e.g. 50100) and name (e.g. “Custom Sales Quote”), so that you can make the needed changes. save, compile, publish the extension. for that steps follow my last post.

2) add variable TenantMedia: record “Tenant Media” to the global report variables

3) add new dataitem(Item;Item) after the last column of dataitem “Line” (Sales Line)

4) add the typical properties to connect the dataitems Line and Item via field “No.”

5) add column(Picture;TenantMedia.Content) to the new dataitem for viewing the item picture in the line

6) in trigger OnAfterGetrecord of dataitem “Line” add new local variable “Item: record item”.
at the end of the trigger’s code add:
if item.picture.count > 0 then begin

remark: to load the picture data within the OnAfterGetrecord trigger in new dataitem “Item” won’t work, the data is loaded to late to be shown in the line.

7) edit the word layout in vs-code using ms word, activate the developer tools menu in word, activate the xml structure to view the fields structure

8) add new column in the lines matrix. set the column heading to “Picture”, set the cursor into the new data cell in the new column, add new field Header/Line/Item/Picture as Picture (type) into the new data cell. save the word report, close word, compile and publish the extension. replace the sales quote no. in “report selection” to the new report.


Great, isn’t it?

Change standard reports in BC?

First of all, you cannot make changes in standart reports. You cannot change the dataitem, the code behind. But it’s possible to change the layout by creating a custom layout with BC using MS Word or the RDLC Report Designer. There you can use the available fields from the standard report. It’s not possible to add new fields.

To add new fields, additional code, following has to be done: Copy the existing Standard report, create a new report extension and add the dataitem and the code to the extension by using the “AL Object Designer” in Visual Studio Code.

(AL Object Designer)

For version 15 or newer:

  • Start with a new extension in BC
  • Install or use installed “AL Object Designer”
  • Download symbols from a sandbox
  • Open the “AL Object Designer”: type “AL Object Designer” in the search box.
  • Search for the report, click on the report name. A new tab will be opened, the code incl. dataitem of the report is then shown.
  • Copy the code to the new .al file, change ID and name. Make then the needed changes, add fields and code, what ever, save.
  • Upload and publish the extension to the sandbox.
  • Goto “Report layouts/Custom layouts”, download the original layout and upload it to the new report, press update layout.
  • Download the report layout from the new report, change the layout according to your needs, add e.g. the new fields.
  • Upload the changed report layout, select the new report in report selections and use it, where needed.  

For older Releases do the following: Install a local version of BC on your laptop or use a docker container for that. Export the report object using finsql as .txt file. Then convert it to AL code using the Txt2Al conversion tool.

Convert String to Char array in AL code

Was needed in a forum question.

 procedure ConvertStringToCharArray(var arr: array[10] of char; srcStr: Text)
   i: Integer;
   for i := 1 to strlen(srcStr) do
     arr[i] := srcStr[i];
or simply convert a String Element into a char value. 😉
srcStr: Text;
chVal: char

// get 1. element of the string and convert it to a char
chVal := srcStr[1]; .


HexToInt in AL code

That was needed in a forum question.

  hexStr := 'A2F'; // int value = 2607
  intVal := HexToInt(hexStr);
  Message(hexStr + ' = ' + format(intVal));

procedure HexToInt(hexStr: Text): Integer
  len, base, decVal, i, j : Integer;
  base := 1;
  decVal := 0;
  len := strlen(hexStr);

  for i := 0 to len - 1 do begin
    j := len - i;
    if (hexStr[j] >= '0') and (hexStr[j] <= '9') then begin
      decVal += (hexStr[j] - 48) * base;
      base := base * 16;
    end else if (hexStr[j] >= 'A') and (hexStr[j] <= 'F') then begin
      decVal += (hexStr[j] - 55) * base;
      base := base * 16;


Create recurring sales invoices automatically

A common issue is to generate invoices per month for items and services automatically, which are being sold periodically.

You can use report “Create recurring Sales Invoice” to generate sales invoices with the needed lines manually. The parameters “Order Date” and “Posting Date” in the request page are mandatory. So, the report cannot be used to generate invoices automatically without setting the mandatory parameters.

But one step after the other.
First goto “Recurring sales lines” and create a new record, set code and description and add a line with the item, which should be added in the sales invoice, when a new sales invoice will be created.


Next open the customer, for which the sales invoices with recurring lines should be created for. There goto Navigate/Sales/”Recurring sales lines” and add a new record with code “LIC”. Set additional values if needed.
Now, if a new sales invoice with that customer is created, the recurring lines are added automatically. That’s fine.

Next run report 172 “Create recurring sales invoices” to create sales invoices with recurring lines, semi-automatically. In the Request page set “customer no.” with the customer’s no. from above, also set the Code from the “Recurring sales lines”.


Fields “Order Date” and “Posting Date” are mandatory to run the report. Therefore it cannot run automatically without setting both date fields.

What to do now?
To run the report automatically e.g. monthly, the best choice is using a job queue entry. There the request page default values can be set. Set the filter fields like above, additional you could set a default value for the date fields. Doing that, the job queue entry can be run with no problem, but all invoices get then the default date value, what we do not want. It would be nice, if the current date is used.
To solve that  it could be an option to extend table “Standard Customer Sales Code”, if there would be a kind of “OnBeforeCreateSalesInvoice” event to replace the dates, but there isn’t.

So i decided to create a copy of report 172 and make one change.

trigger OnPreReport()
  if (CurrentClientType = ClientType::Background) or (CurrentClientType = ClientType::NAS) then begin
    OrderDate := Today;
    PostingDate := Today;

   if (OrderDate = 0D) or (PostingDate = 0D) then
Ok, preparation ready.
Now create a new “job queue entry” as above described and leave the date fields empty.
The job queue entry:
To run the report monthly on every 1st of the month set a dateformula in “Next Run Date Formula”, here use “CM+D1”.


EventSubscribers are a nice feature to add code to triggers in standard objects. It’s the replacement for changing the code directly in standard objects.

A sample:
add code at the end of trigger “Address 2”-OnValidate from page “Customer Card”. It’s a so called OnAfterValidate event. There are many events available in each standard object, which one can subscribe to.


the syntax for the EventSubscriber Attribute, that connects the custom procedure with the standard trigger:

for details goto here.

the code:
create a new codeunit or use an existing to add following code.
it’s needed that property EventSubscriberInstance is set in the codeunit.
for details goto here.


the result:

Business Central Cloud in non supported countries.

Data Center Clipart



Today i watched a live web session about BC Cloud Update strategies. The participants had the option to ask questions, which were answered immediatly.

One of the most asked questions was: How can companies get access to BC Cloud in non supported countries? The answers were in my opinion not really satisfying, because the answer was simply “Not now, maybe in the future….”. UK is supported, but not Ireland, the neighbor country, means North Ireland is, Republic Ireland is not. The Microsoft Headquarter Europe is settled in Dublin, Republic Ireland. 😉 Bit strange. Microsoft adds new countries over the time. Support for India is planned, but with no details about the release date. Till then indian companies can use ITAX.

So what can companies and CSPs/ASPs do now, to provide BC Cloud or kind of … ?

Current Availability for BC Cloud:

Country/Region Localized by Availability
Australia Microsoft Available
Austria Microsoft Available
Belgium Microsoft Available
Canada Microsoft Available
Colombia Partner Available
Croatia Partner Available
Czechia Microsoft Available
Denmark Microsoft Available
Estonia Partner Available
Finland Microsoft Available
France Microsoft Available
Germany Microsoft Available
Hong Kong SAR Partner Available
Hungary Partner Available
Iceland Microsoft Available
Indonesia Partner Available
Italy Microsoft Available
Japan Partner Available
Latvia Partner Available
Malaysia Partner Available
Mexico Microsoft Available
Netherlands Microsoft Available
New Zealand Microsoft Available
Norway Microsoft Available
Peru Partner Available
Philippines Partner Available
Poland Partner Available
Portugal Partner Available
Russia (on-premises only) Microsoft Available
Serbia Partner Available
Singapore Partner Available
Slovenia Partner Available
South Africa Partner Available
South Korea Partner Available
Spain Microsoft Available
Sweden Microsoft Available
Switzerland Microsoft Available
Taiwan Partner Available
Thailand Partner Available
United Arab Emirates Partner Available
United Kingdom Microsoft Available
United States Microsoft Available
Vietnam Partner Available

Development of custom localisations


Record Race Condition – 2 users block each other

A forum user needed help for a typical situation in dynamics nav. 2 users are working on the same sales order at the same time. both make changes. as a result one gets the error: the current record has an old load status, record was changed by an other user.

this is a so called race condition, means two persons want to change the same record or the value of the same field. at the time were the second person, who edited the record, wants to save his changes, the system realizes, that the status of the loaded record is old, because the first person has already saved his changes.

the question was: how to lock the sales order, when one user edits the record, so that a 2. user cannot edit the record.

how to solve the problem:

  • the process answer: i most cases that should not be an issue, because only one user should work with one record at a time, e.g. one sales order. it makes no sense that 2 persons work at the same time with the same order. if that occurs, the work process in the company needs some optimization. So some consultancy is needed.
    • situation 1: 2 persons do different things with the same order. In that case a workflow has to be defined, so that person 1 does his work first, then in step 2 person 2 his work step. result: never work 2 persons at the same time with the same order.
    • situation 2: both do the same. then it’s needed to set the field assigned user, so that each person can filter the sales order list by that field and get so the assigned work load. as a result there is never a situation, where 2 persons work with the same order.
  •  tech answer: the issue is also solvable technically, but i recommend the process change.
    • table sales header: add 2 fields InUse – boolean, UsedBy – code.20
    • page 42 sales order, add following code to
      trigger OnQueryClosePage


      UsedBy := ”;
      InUse := FALSE;


      trigger OnAfterGetCurrRecord()

      InUse := TRUE;
      UsedBy := USERID;

      END ELSE

      IF UsedBy <> USERID THEN
      ERROR(‘in use by %1’, UsedBy);


Workflows in Dynamics Nav/BC


ich beschäftige mich aktuell mit Workflows in Dynamics Nav.
Ich bin seit vielen Jahren Senior Consultant für Dynamics Nav und hatte keinen einzigen Kunden, der das Workflow Modul im Einsatz hat, was schade ist, weil das Modul durchaus was kann. Gestern ist mir jedoch klar geworden, dass man keine Genehmigungsrollen in einem Workflow benutzen, nur mit spezifischen Benutzern arbeiten kann. Tasks von einer Rolle zu einer anderen Rolle weiterzuleiten ist aber ein typisches Thema in Workflowszenarien, etwa beim Eingangsrechnungsworkflow.

Dazu ein paar Fragen:
* Lässt sich das Thema Genehmigungsrolle mit dem Standard Nav Workflow umsetzen bzw. gibt es dafür entsprechende Erweiterungen von Drittherstellern?
* Welche konkreten, typischen Anforderungen haben die Kunden, die das Workflow Modul benutzen? Mussten hier Anpassungen vorgenommen werden oder reichten die Features des Standard Nav Workflow Moduls?

Würde mich über Feedback freuen.

beste Grüße
Dipl.Ing. Franz Kalchmair

Do you know Uniconta?

Because working with D365 BC is not that fun and the features are for small customers too much (they pay for many, what they don’t need), i started with Uniconta. First of all, it is far away from big ERP Systems like NAV and BC. The marketing propaganda says it’s easy to use … So what is the reality?

Uniconta is a new cloud based ERP System. At first view some nice features, quite cheap, very fast, but lacks in some kind in the areas configuration, usability and business logic. It’s quite hard to customize it in that way we know it from NAV. It’s easy to add fields in tables, but not easy to add a button with it’s on functionality. It’s not possible too change existing code, e.g. the posting routines like in Nav often done.


  • Often needed information is not available on the current point, e.g. item ledger entries (i.e. inventory posting entries in uniconta) are not available in the shipment list.
  • Shipment can be created from an order multiple times without changing anything in the system except that there is a new shipment in the list. That’s really disturbing.
  • Creating a shipment does not reduce the item stock. That’s also really disturbing.
  • To post an order only for delivering, but without invoicing was really hard to find out, how this simple basic erp process works in uniconta. that after some needed configuration (sales preferences, activating of some inventory module features) the item quantity of the sales line is removed from stock immediatly when you set up the quantity in the sales line and not after posting, is quite strange. seems that this is a kind of reservation. is this a well considered erp process? not sure …

I tested a lot, found a huge number of programming/logic/translation failures and irritating and/or not translated error messages (some of them are like “error has occured”), wrote a lot, lot mails to the austrian support. It’s tedious … Nevertheless, maybe i will continue, will see, if i have the time …

In the end, who knows, maybe it will be developed into the right direction. Hopefully the bugs will be fixed and the usability & the business logic will be better.

For more details see: