More Charts

More Charts

  • Comments 8

This is a follow up to this post:

Using Client Extensibility in NAV 2009 SP1 to create Charts

News in this post are:

2-series line charts. For example showing number of new Orders and Quotes for the last 10 days:

2SeriesChart

Item Sales Chart (basically identical to the Customer Sales Chart in the previous post):

ItemSales

Doughnut charts have been shined up a bit to make them look better:

Don

Double-click callback to NAV: When you double-click a chart, it will call the ControlAddin trigger. The example below will open up a list of Cust. Ledger Entries when double-clicking on a chart on the Customer Card page:

Sales (LCY) - OnControlAddIn(Index : Integer;Data : Text[1024])
CustLedgEntry.SETCURRENTKEY("Customer No.");
CustLedgEntry.SETRANGE("Customer No.","No.");
PAGE.RUN(0,CustLedgEntry);

All you need is attached at the end of this post. It contains .dlls, including their source code, and a NAV codeunit. To implement some examples:

Implement the charts add-on:

1)  If you want to modify the attached c# project you must install "Microsoft Chart Controls Add-on for Microsoft Visual Studio 2008".

2)  On any client machine where you want to run the charts, you must install "Microsoft Chart Controls for Microsoft .NET Framework 3.5".

3)  Detach and unzip the attached file.

4)  From the unzipped file, copy the files from \XTCharts\bin\Debug\ into the "Add-ins" sub folder of the RoleTailored Client (RTC).

5)  And import the codeunit from XTChart.fob in Object Designer.

6)  In a Classic Client, run table 2000000069 "Client Add-in" and enter one line (if it doesn't already exists from the previous post):

Control Add-in Name:    XTChart
Public Key Token:    d1a25808afd603da

(making sure to have exactly these values, in the right case)

Adding charts to pages:

On the page where you want a chart, insert a new line of type Field. In the property "ControlAddIn", select the XTChart (XTChart;PublicKeyToken=d1a25808afd603da). This adds the control itself. To send data to the control you must specify SourceExpression too. Declare a Global variable called XTChartUtil, Type = Codeunit, Sub Type = Codeunit 75550 "XT Chart Util" to use in SourceExpression. If the chart is on a Customer Card page, then specify this SourceExpression:

For a line-chart, showing "Sales (LCY)" for the last 6 months:  XTChartUtil.CustPointsChart(Rec)

For a Doughnut chart, showing "Balance (LCY)" percentage of "Credit Limit": XTChartUtil.CustDoughnutChart(Rec)

On an Item Card page, for a line chart showing Item "Sales (LCY)" for the last 6 months, have SourceExpressions XTChartUtil.ItemPointsChart(Rec)

On the main Role Centre, to have a 2-series chart showing number of Quotes and Orders created in the past 10 days, I added the chart in Page 9060 with this SourceExpression: ChartUtil.SalesCueChart

Then, for each example above, if you want to trigger any activity when the user double clicks the chart, just put some C/AL code on the corresponding OnControlAddIn-trigger.

You can add charts in many other places, except for pages of the following types which cannot handle Extensibility components:

  • Under a Repeater Control (i.e. a list page)
  • Action Pane
  • Command Bar
  • Filter Pane

Note:

In the example here, I added a chart to the main Role Centre. In a production environment this is maybe not such a good idea, for these two reasons:

1)  If a chart goes wrong and crashes, for example if a user has not installed the Chart Controls for .NET (link above), then it may crash the whole RTC. If this happens from some page which shows a chart, then at least the user knows that such and such page has a problem. If it happens on the Role Centre, then RTC will crash as soon as it is opened, and the user cannot use RTC at all, and it may not be obvious why RTC crashes.

2)  Performance is not great in the SalesCueChart-example here, counting Sales Header records filtering on "Document Date". If a company has 1.000s of orders, then this would have some impact on performance. So, at least only calculate the chart on request, and not on the main page whether the user actually needs it or not.

Development notes

If you want to extend this to create new charts, then this is how the attached example works:

Chart Data is generated in xml format in codeunit 75550 "XT Chart Util". It has a function for each type of chart. The xml data must have this format:

- <Chart>

<ChartType>1</ChartType> <-- Chart Type 1 = Lines, 2 = Doughnut and 3 = 3D lines

- <Data Title="Orders"> <-- Title is optional. If specified, it will show as legend on the chart

<REC1 Title="16/01/11">0</REC1> <-- Name the elements REC1, REC2, etc.

<REC2 Title="17/01/11">2</REC2>

<REC3 Title="18/01/11">0</REC3>

<REC4 Title="19/01/11">2</REC4>

</Data>

- <Data2 Title="Quotes"> <-- Data2 section is optional. Used for making 2-series charts. If there is a Data2 section, then it must have the same number of elements as Data, and with the same names.

<REC1 Title="16/01/11">0</REC1>

<REC2 Title="17/01/11">0</REC2>

<REC3 Title="18/01/11">0</REC3>

<REC4 Title="19/01/11">1</REC4>

</Data2>

</Chart>

In case of a Doughnut chart, just generate an xml document like this:

- <Chart>

<ChartType>2</ChartType>

- <Data>

<REC1 Title="Balance">9.20</REC1>

<REC2 Title="CreditLimit">90.80</REC2>

</Data>

</Chart>

with 2 REC-elements which total up to 100.

The c#-code is all inside of one big try{} catch{} - structure. If anything goes wrong, then it will just show the data that was received in a MessageBox, but not what actually went wrong. Only if you remark the try{} and catch{} - section, it will throw the actual error message to tell you what went wrong (it should log it in the Application log). But the downside of this is, that RTC is also likely to crash.

Lars Lohndorf-Larsen

CSS EMEA

This posting is provided "AS IS" with no warranties, and confers no rights

Attachment: XTCharts.zip
Leave a Comment
  • Please add 7 and 6 and type the answer here:
  • Post
  • Hello,

    how do you get the chart to extend across whole width of the page, and not show the Caption?

  • The RTC will do a lot of the rendering automatically, so it is not always we can control it 100%. But, try to add the Chart in a group in the page, where the group has GroupType = FixedLayout. Also if you do that, just see if it still works OK if you resize the page, and try to resize it back - I had some issues with this at one point.

    If it's the caption that comes from the Page, then I'm not sure we can remove this completely. But if you mean captions inside of the Chart, then I think we can probably move it somewhere in the c# code.

  • Great!

    Thanks.

    Do you have any idea how to get more than 1kb of data across?

  • The data is sent to the chart component via the SourceExpression property on the page. This can be either Text or BigText. So with BigText you can sent more or less any size of data across. But the code in this example would need to be updated to use BigText everywhere. Is it likely to have a chart definition larger than 1kb? Or did you have some other scenarios in mind?

  • I see now that chart definition can quite easily become longer than 1024 characters, in which case this sample wouldn't work. It would have to be redesigned to load xml into a BigText, or to pass just the xml filename to the client add-in, but some redesign of this example would be needed...

  • Yes, it's easy to have more than 1kb, say a month of two measures..

    I'll have to look into having it as a BigText, thanks.

  • I got the charts workin also with longer than 1024 character definitions. I did not have to change the .dll - it takes whichever text you send to it, whether it's Text or BigText. So only changes on the page showing the chart is needed. This is what I changed:

    To send the chart definition as BigText we can't do it directly from SourceExpression anymore, so instead of this in SourceExpression:

    XTChartUtil.CustPointsChart(Rec)

    Have a new BigText variable in SourceExpression, then use the OnAfterGetRecord trigger on the page to calculate it, like this:

    TempBlob.DELETEALL;

    TempBlob."Primay Key" := 1;

    TempBlob.INSERT;

    XTChartUtil.CustPointsWithBigText(Rec,TempBlob);

    TempBlob.Blob.CREATEINSTREAM(IStream);

    BigTxt.READ(IStream);

    (TempBlob is a TEMP record variable, table 99008535):

    Then in codeunit 75550 XT Chart Util I added a new function:

    CustPointsWithBigText(Cust : Record Customer;VAR TempBlob : TEMPORARY Record TempBlob)

    CustPointsChart(Cust);

    TempBlob.Blob.CREATEOUTSTREAM(OStr);

    XMLDoc.save(OStr);

    TempBlob.MODIFY;

    In this way it’s calling the original function, so you get exactly the same chart. And then finally: In the original function, here is where you would get the overflow:

    ReturnTxt := XMLDoc.xml;

    So, remove that line (it’s not needed anymore anyway)

  • Thanks for this post. I am using this for developing charts in RTC. I want 12 months on the X axis of the Chart, I am passing the 12 months of data, but the Chart truncates the alternative Months and displays Jan - Mar - May - Jul - Sep - Nov.

    Is there any way I can force the Chart to display all the 12 parameters. When I reduced the No. of months to 9, the chart dsiplays 9 months(Good). When I add one more to make it 10, the Chart truncates alternative months.

Page 1 of 1 (8 items)