Multicolumn Reports in RDLC…eeeasy, maaaaan!

December 17th, 2011 by mirko

Hi guys,

I’ve been (and I still am) very busy in these days, due to a BIG go-live on 1st January…and I admit that writing about NAV is not so enjoying after you work with it for 6 days a week and about 9-10 hours a day. I just need to rest a bit on sundays and to keep in touch with friends and other people, you know? It’s called social life ;)

anyway, i’ve 3 topics i want to blog about and i am trying find some time here and there to write them.

this one is the shorter, but it’s very useful!

I’m talking about muli column reports, which are a bit painful and boring to design in classic client, because you have to evaluate 2-3 records in a single section (doing some “risky” NEXT in onaftergetrecord, create some array variables and evaluate them)…ok, I don’t want to blog about CLASSIC multicolumn reports, you can find how to design them anywhere in mibuso.

with rdlc, the whole story is actually faaaar-mooore-eaaasy. I don’t even need screenshots to explain it:

1. create a new report in classic (through wizard is fine) on customer table, and add the number and the name in the body section.

2. convert it with the create layout suggestion

2a. (optional) save and run it: you’ll see a plain list of customer numbers and names…nothing more :(

2b. if you did 2a, go back to the rdlc designer

3. click on the white space of the rdlc designer, find the “columns” property and select “2″ (or three, or four…whatever you like)

4. resize the white page and you’ll see a new column appear

5. adjust column spacing and size properties as you prefer

6. print the report. Nice huh?

I think this is a well known trick for the rdlc developers, but as a nav developer, i’ve never seen this anywhere on the communities/blogs i usually read. Enjoy!

Compare 2 records

October 10th, 2011 by mirko

Hi everyone,

i’ll present here a pair of tips to compare two record variables to check if they are the same, and i’m not talking about that they’ve the same key, but that they are totally equal, every field.

Actually, such a function does not exist in NAV (it’s not built-in, at least). Instead, I found a pair of methods to check if the records are equal. Both methods have their pros and cons, so I’ll post them both.

Then, I’ll explain my observations and it will be up to you to choose the best one for your specific case.

Code Snippet

IsDifferent function: (the second function)

Inspired (ok, almost copied :) ) from function logmodification of codeunit 423 - Change Log Management.

This function compares all the NORMAL fields one by one, and if the value is different, it returns false.

IsDifferentWithFormat function: (the first function)

This one is all mine. :P It uses the format function on the recordref variables and compares the results.

It uses an array of 5 text1024 and compares the results 1024 by 1024 characters. If both the format of rec and xrec are blank, it means we have reached the end of record, so the function exits false (records are equal).

I did some tests on performance of both these functions, and it turned out that usually the fastest is the one with FORMAT instruction, due to the minor number of loops. The other function is faster only if it’s one of the first fields that is different (or if the table has just a few fields).

The implementation is the same for both functions, (just pass 2 evaluated recordrefs to compare) so it’s up to you to choose the best function for you! THIS DOESN’T WORK, UNFORTUNATELY (SEE COMMENTS), STICK TO ISDIFFERENT FUNCTION FOR LONG TABLES (BUT IT WILL PROBABLY TAKE A LOT OF TIME), AND USE FORMAT(REC) ON A NORMAL TABLE VARIABLE FOR SMALL TABLES.

I’m going to upload the objects ASAP, now I’ve to go back to work.

See you next time!

NAV TechDays Incoming!

September 3rd, 2011 by mirko

Hi everyone,

Long time no see, I’m sorry.

The problem is that I am (and I willbe) very busy until…….February 2012 ( O.o ) for a BIG BIG go-live…i know i should be more active as an “MVP” but i can’t work during spare time, because i’m already overwhelmed during the day…I have to have my brain “breathe” :)

That said, we should be happy to have so much work!

Now, that i told you that i’m very busy, I’ll tell you that I’ll be having 2-3 days out of office to go to Belgium at the NAV Tech Days !!! Yes, I have to admit it’s a bit contradictory :-P

I’m so excited to meet so much experts personally, and honestly…take a look at the title of topics and the name of relators…how can a NAV developer even miss it?!?!!?

I hope to meet a lot mibuso members (but not only them) there, to have a chat!

See you soon! (I’m slowly preparing “nav hotfixer” winform, it will be my next article, i hope)

Silent or Unattended Installation of NAV 2009

April 28th, 2011 by mirko

Hi everyone,

I’ve recently followed a nice 1hour-livemeeting about silent installation of microsoft dynamics nav 2009 R2 (or, as MS relator says: “microsoft dynamics EN-EI-VI two thousands and nine, AR two”).

First of all: about half of the meeting have been wasted in saying the product name :)

But let’s get into the good part.

WHAT IS SILENT OR UNATTENEDED INSTALLATION

Maybe a lot of you already know it, but for completeness, i’ll explain it here in two words: basically a silent installation is exactly what you can imagine. A software (in our case nav2009) is installed on a client pc without user interface and user interaction (that is: no “next->next->…->finish” procedure).

This is quite useful if you want to spare time during client installations, especially if there are a lot of client PCs being involved.

INTRODUCTION

Microsoft recommends to only run “setup.exe” file when you install a new NAV client (and/or server), because the installer have been tested by them using this procedure only. This means that you shouldn’t run the various .msi files individually (althought possible ;) ).

Anyway, the setup.exe file runs all the .msi files that are necessary for a correct installation. It also installs the prerequisites, for example .NET framework3.5, and other stuff.

This means that our goal is to run this exe silently.

RUN THE EXE SILENTLY

Nothing simpler! there are some parameters that you can append to the command line in order to achieve fancy things:

/quiet <– you can guess that we need this to run the exe in background

/log  [filename] <– create a log textfile in the specified position

/config [filename]<– another key feature we need to configure our installation automatically

/uninstall <– i’m still wondering what this will do ;)

/repair <– repairs a bad installation

LET’S INSTALL!

First of all, let’s start our exe file by doubleclicking it, as always.

Then let’s go through all the steps of the installation, select the pieces of software we want to install (classic, roletailored, server, etc) and then STOP(!) at the very last screen of our installation wizard: DON’T PUSH FINISH!! Click instead on one of the links of the configurable parts, for example “Role tailored client” and go ahead with some further configuration.

(in the screenshot, you can find my configuration. The blacked values are all my computer name. Because i’m going to install my standalone dev environment).

 My install screen

You can guess what we’re going to do now: click on “Save Configuration Settings” and create an xml file. You can open this xml file and check what it contains: a list of all the product components and how to behave with them (there are actions like local, absent, repair, bla bla bla…). Why do we need this file? In order to avoid user intervention during installation, obviously! The xml will be the [filename] argument of our “/config” parameter.

Now, you can run the silent install by simply doing start -> run -> [exepath] /quiet /config [configfilepath.xml], but there’s a much more smart way to do it: create a bat file that tells you that the installer is working, and alerts you when it has finished with a message. In this way, you can deploy the file on various PCs, and start it. In order to achieve this simple task, just copy the following text in a notpad and save it as .bat instead of .txt. 

[exepath] -> where setup.exe is placed: simply write setup.exe if the but is in the same folder of the setup.exe ;)

[configpath] -> where you have saved the configuration xml file .

[logpath] -> where do you want (if you want it) the log file path saved. I always recommend to create this log.

Remember to write file extensions, too, and also place the paths between the double quotemarks if the one of they contain spaces or special characters! ;)

@echo off
Echo start INSTALLING NAV2009R2: IT WILL TAKE SOME TIME, PLEASE WAIT...
Time /t
[exepath(.exe)] /quiet /config [configpath(.xml)] /log [logpath(.txt)]
Echo end: INSTALLATION COMPLETE! YOU CAN NOW UNLEASH THE PWR OF NAV2009R2!!!
Time /t
pause

The installer will take much more time if it’s the first installation, because the prerequisites are huge. The nav installation alone will take only a few minutes, instead.

And that’s it! you can create as many configuration files as you want. Be sure to take a look to the log file, too and keep in mind that the root folder of the installer shouldn’t be too “deep” in your file system. I received some errors during my tests which disappeared after moving the root folder of the installer under “C:\” …weird, huh? (unless i’ve messed up something with the installer) O.o

Happy Install!

Action Image Library.PDF(!!!!!)

April 4th, 2011 by mirko

Finally…phew…I finally finished this TEDIOUS work: i finally made a pdf with the list of all the pictures allowed in NAV, and, more importantly, the file is text-searchable!!! (instead of this, which is a big, unsearchable image)

Inspired by the many compliants in that link, i thought that this file can by time saving for me and anyone else, at the small cost of 2 hours of my life (No junior programmers have been harmed in creating this file :) , I swear it)

I hope it doesn’t already exist somewhere else ;(

Like every tedious and repetitive work, there can be some typo errors or missing words/images: I didn’t have the necessary patience to double check it, but this ugly formatted pdf file should do the work quite well for me and you. I have not attached the source file that i created to generate the pdf, because i’d like you to post here (or with a pm in mibuso) if you find some error in the file. In this way we can have a common and updated pdf file. When all the typos will be corrected I will be able to release the word file, if you want it ;)

I’m counting on you, guys!

Thanks in advance!

P.S.: it appears that the pdf crashes FF4 browser. I’ll upload a zipped version whenever i can, sorry

Action Library Images

MVP!!

April 2nd, 2011 by mirko

http://belead.wordpress.com/2011/04/01/microsoft-mvp-award-april-2011-awards/

Hi guys,yesterday evening I was going out of home with some friends, and i though  to check my email before going out (yeah, yeah…i shouldn’t do that on friday night): i’ve been stunned after seeing the object “Congratulations” from [MVP Award Program]…

i thought it was an “April Fish”, that is a recurrence happening on first april, when people do jokes to other people (at least, here in italy :) )

After some further analysis to the mail, i realized it was really true! I’ve been awarded of MVP status!honestly, i feel a bit embarassed about it: I’ve gained the same award of people like Kamil Sacek, Alain Krikilion, Jorg Stryk, Daniel Rimmelzwaan, Rashed Amini, Mark Brummel, Luc Van Dyck, Harry Ruiz, Eric Wauters, Alex Chow, Sandeep Singla, Dhan Raj Bansal, Adam Roue……I don’t think that i deserve this award more than the 10% of how much they deserve it, and i don’t pretend that my opinions can be compared to theirs, but i got the award for the first year, and be sure, I’LL DO MY BEST (and possibly more) to renew this title and try to reach those giants (in the long-term future, i mean ;) )

I have to say “thank you” to all these masters, to other mibuso members (they’re countless, i can’t really list them all) and, last but not least, to all of my colleagues, who helped me to make my way in the NAV world!THANK YOU!

Manage System Indicator

January 10th, 2011 by mirko

Just a little tip that you probably are already aware of:

you can manage the system indicator text and style of dynamics nav 2009 R2 like this (code in Codeunit 1)

Function GetSystemIndicator

IF CompanyInformation.GET THEN
  CompanyInformation.GetSystemIndicator(Text,Style);
//-@MM 10.01.11
Text := 'Kratos Rocks!';
EVALUATE(TimeAsInteger,FORMAT(TIME));
IF TimeAsInteger MOD 2 = 0 THEN
  Style := Style::Accent1
ELSE
  Style := Style::Standard;
//+@MM 10.01.11

HyperList - How to run filtered list pages from report hyperlinks!

January 10th, 2011 by mirko

Hi readers,

It’s passed some time since i found this workaround, but hey, better late than never! ;) : as you can read from the topic title, we’re going to do something that’s actually impossible in nav, because the “&filter=” parameter is not accepted for hyperlinks that refers to pages. Here’s a sample:

if you try to run this

dynamicsnav:////runpage?page=9&filter=Languages.Code:101011

you’ll get back a big and smiley error: “The query parameter is not supported.”

I was very disappointed when i noticed it: what if i wanted to click the “Balance (LCY)” field in the customer  - top 10 list?

I started to dig the help online and i noticed that report DOES accept the “&filter=” parameter instead, and that night i’ve had the idea: filter the table i want to show, pass its filters to a report, copy the filters in the report and then run the filtered page. YEAH!

Now, I’m going to explain what i’ve done, but first of all, you have to know how to run generic hyperlinks from a report to another report. Here you can find all the necessary:

http://msdn.microsoft.com/en-us/library/dd338628.aspx

IMPORTANT: I have to credit mibuso member “einstein.NET” for some important hints about the function that parses the “GETVIEW”. Thanks a lot!

I’ll take the good old Inventory - Top 10 List as a sample: it has an Inventory field and i want that field to behave just like the drilldown on the item card. Let’s start.

First of all, let’s create this simple report (50500 in the fob file): HyperList Report. This report has the only use to run a page based on the filters of the dataitem. let’s set the Item ledger entry table (the table on wich the inventory flowfield is based on) as a dataitem of indentation zero. You will notice that in my 50500 report there’s also a cust. ledger entry dataitem: this is because you can add as many dataitems of indentation zero as you want (up to the max number of dataitems that a nav report allow) in order to reuse this utility report for as many drilldowns as possible.

The report Must be processingonly, and userequestform must be set to no (for obvious reasons :) )

then write the following lines of code in the report

hyperlist report code

the
IF GETFILTERS <> '' THEN BEGIN
line of code is used to “select” the dataitem to run: obviously, if you didn’t set any filter the report doesn’t work, but if you’ve not set filters, you also don’t need to use this report ;) .

Now that our report is ready, we have to run it with the correct filters in order to let it run the correct page with correct filters for us; to achieve our goal we have to do some easy steps.

At first we have to modify our report Inventory - Top 10 List, adding a rec variable for item ledger entry table. Then, we are going to set all the filters we want. In our case, i put them in the integer dataitem (onaftergetrecord) after the item.get is done: this is the correct place because (as you can see in the section designer) the integer table is the one being printed.

filters.JPG

Also add this line of code in the onprereport, that initializes some parameters in the “jump to url” codeunit
CUJumpToUrl.FNTFirstRun;

firstrun.JPG

and don’t forget to set “enablehyperlinks” property to yes in the report

now, we will have to call the “Jump to url” codeunit i added in the .fob: we are going to call it directly in the sourceexpression of a textbox in the sections, like this:

sections.JPG

CUJumpToUrl.FNTCreateUrl(1,REPORT::"HyperList Report",CUJumpToUrl.FNTAppendFilter(DATABASE::"Item Ledger Entry",TBItemLedgEntry.GETVIEW(FALSE)))

Now, i’m going to explain this call. Here’s the code of the codeunit:
jumptourl.JPG

1: indicates that you want to run a report; if you pass zero, you’ll run a page instead.

REPORT::”HyperList Report”: this is the report we created before for the purpose of running pages.
CUJumpToUrl.FNTAppendFilter: this is a function that returns a string with the needed filters
DATABASE::”Item Ledger Entry”: this is the base table for the drilldown
TBItemLedgEntry.GETVIEW(FALSE):the getview returns a string with all the applied filters. this string is parsed by the FNTAppendFilter function to make it suitable for the link.

now that we have created our link, we can open the rdlc designer, and place the value in the “jump to url property” of the inventory field. add some fancy formatting to the textbox and we’re done!

preview.JPG

UPDATE: you can also use dummy filters to pass values to the hyperlist report and eventually run functions within the pages. this is useful to run fancy pages that needs a sort of “getparameter” function before being run. Here’s a sample:

Sales Shipment Header - OnPreDataItem()
IF GETFILTERS <> '' THEN BEGIN
  EVALUATE(PostingDate,GETFILTER("Posting Date"));
  mypage.GetParameters(
  GETFILTER("Patient Code"),GETFILTER("Responsibility Center"),GETFILTER("Sell-to Customer No."),PostingDate);
  mypage.RUN;
  CurrReport.QUIT;
END ELSE
  CurrReport.BREAK;

Sample Objects

Run RTC Reports From Classic

November 3rd, 2010 by mirko

hi everyone, i’m back after some time with a new and easy trick for the laziest programmers…

when developing reports for the 3 tier client, we are going to make a lot of tests because of their complexity and because they are error prone.

This approach lead us to make something like 50-100 runs per report in order to check the layout after every change. Unfortunately we would need an action to run our report. I found an easy and simple way to make the whole thing faster:

create a new page with only a container, and put this code in the onopen trigger
REPORT.RUNMODAL(REPORT::"myreportname");
COMMIT;
ERROR('');

Now, the only thing you have to do is to run the page: the commit makes sure that if your report is modifying something, it will be saved. this is necessary because we have the ERROR(”) that closes the page (the currpage.close does not work) that would lead to an unwanted rollback.

It’s a quit stupid trick, but saves some time in day to day work.

Enjoy

Is it really temporary?

September 16th, 2010 by mirko

Temporary tables are a very useful tool we have in nav, and their usage is constantly increasing in my projects. For this reason, during upgrades (or when someone else have to modify my code), there’s the chance that some BAD guy removes the temporary property, just for mistake or because he doesn’t know what it is O.o

The real problem is when i do

MyTempTable.RESET;
MyTempTable.DELETEALL;

In order to clean it before some further processing. What does it happen if the table variable is not temporary?!
You (or him) get simply nuked by the customer, because you (him) nuked his table!

How to avoid this bad situation (i mean, getting nuked)?
RecRef.GETTABLE(MyTempTable);
IF NOT RecRef.ISTEMPORARY THEN
  ERROR('MyTempTable must be temporary!What are you doing?You wanna die?');

I thought to adapt this code to any table, because i wanted to have a function where i pass a record variable and then execute the code without rewriting it everytime, but up to now, it’s not possible in nav :(
Anyway, it’s not so much effort to put these lines of code in your application, unless you’re even lazier than me :)
just declare a recref variable, copy/paste the code and modify the error text!
See you next time!