A question I receive a lot from customers and partners is if there’s a way to implement the PlaceInBottom effect on a report in RDLC.
As you might already know, in the Classic Client, which I should now call the Development Environment, in the report object, there’s a property called PlaceInBottom. It determines whether a footer section should be printed at the bottom of the (physical) page.
In NAV 2009 and beyond, the property isn’t supported in RDLC and there’s no counterpart in the properties of the layout in Visual Studio. So basically, if you want to implement the Place In Bottom effect, you either have to keep using the Classic Layout or find a workaround in the RDLC layout.
Finding a solution in the RDLC layout is not that easy. I have been scratching my head for a long time and still haven’t found a good one. So what I will present here is a workaround, until a better solution is available.
The problem is determining in the RDLC layout what is the physical end of a page.
First, let’ s have a look at what we want.
At design time:
At run time:
Now le’ts see what we get in RDLC.
At design time:
At run time:
As you can see, in the RDLC the text is not at the bottom of the page and there’s no property on the textbox, or rectangle for this either.
Hey, what if I would use the Page Footer in RDLC and put the rectangle/textbox in there?
Well, that would fix the problem, BUT, in most cases, the text that needs to be at the bottom of the page is in a data region, like a table, matrix or chart, and a data region can not be moved to a Page Footer.
So the real question is, how do we simulate a Place In Bottom Of Body?
Well, the magic trick in my case, is to generate linefeeds, and for that I’m going to use an expression and a function:
Public Function GenerateVbCrLf(ByVal Count as integer) dim Value as String dim i as integer For i = 1 To Count Step 1 Value = Value & " " & VbCrLf Next i Return Value End Function
And in the table, I will add a table footer row in which I will call this function:
=Code.GenerateVbCrLf(42 - cint(CountRows("Table1")))
This will generate a number of line feeds (“CarriageReturn LineFeed” to be exact) depending on the number of rows in the table: Table1.
Why 42 you might think, well because 42 is the answerto the Ultimate Question of Life, the Universe, and Everything… (see The Hitchhiker’s Guide to the Galaxy) 🙂 🙂
No, 42 is found via trial and error and will depend in the size of your table, the other ‘stuff’ in your report, the margins, … You can find it by running the report and changing the number untill your PlaceInBottom text falls of the page. The number before that is your answer to the ultimate question 😉 And in this case, for report 111, the magical number happens to be 42.
This is, as I said, just a workaround. It’s imho not a solution.
It requires trial and error for every report you implement it on and if you ever update the report layout, you will have to do the trial & error all over again. And remember to test it in Print Layout, not Print Preview. And also, export to pdf and/or print it on paper to see if that”s also ok.
Anyway, it’s better then nothing, no?
The solution can also be automated. For example by creating a Report Layout Setup table, in which you store, for every report you need it on, the magical number. Then, via C/AL code you can fetch this number and pass it on to the RDLC layout.
Using a Report Layout Setup table can also be a good idea to store colors. For example if you want to standardize the company look & feel and have the same colors in table headers, table details, table footers, … But I will come back to this in a later blog post…
To download the demo report:
Pingback: PlaceInBottom in RDLC layout | Pardaan.com
Looks very nice, one problem although…
I’m having troubles to achieve the same functionality when more than one table have to be taken in account for the CountRows.
For example on sales document: Sales Lines & Extended Text Lines.
I’ve tried it with an report parameter who holds the sum of both CountRows… but this doesn’t seem to work either.
But my reporting knowledge is rather limited, so I could be doing something awfully wrong.
Indeed, when there are multiple tables to keep into account it gets a little more difficult. You can try to guess (the trial & error method) depending on ‘the average number of dimensions’ (in this case) and take it into account in the expression.
Or you can use another expression (and variable) to stock the TotalRows and use that.
Shared TotalRows as Integer
Public Function SetCountRow(RowsToAdd as integer)
TotalRows = TotalRows + RowsToAdd
Public Function GetCountRow() as Integer
and use an expression like:
=Code.GenerateVbCrLf(42 - Code.GetCountRow)
Have a look at this example:
And remember, it’s not a solution, just a workaround 🙂
sorry for delay but…
an easier solution is to put a textbox in each table you use in the body, name it and in expression just put cint(countrows(“table name”).
into the textbox that generates blank lines just include into the calculation the no. of rows taken from the textbox that count rows for each table…
It should be something like..
=Code.GenerateVbCrLf(38 – (ReportItems!TB3Rows.Value + ReportItems!TB4Rows.Value +ReportItems!TB8Rows.Value + cint(CountRows(“Tablix6”))))
I can confirm that it doesn’t work on multiple pages. You have to count lines from Nav Classic Client.
Thank you very much. I have made a couple of my own functions in RDLS report on the basis of this article. It is easier then do the same in NAV and then send to RDLS. But for me it is more useful to increment quantity of rows instead of using function countrows…
I am using 7 tables in my .rdlc report and I want table 6 and table 7 to place in bottom.
Can u help me in this?
Sure, just send me an email and I’m glad to help out.
I tried to use this and in general it works okay, but when the report stretches over multiple pages the row count does not make much sense in determining the number of linefeeds to generate.
Have you figured a way to only count the number of rows on the current page?
I implemented this functionality , but the problem is that the textbox which i have to place at bottom deviates on next page i.e from page no 1 onwards. Is their a solution?
I recognize that this is getting old, but I still found it most useful in my implementation.
(The guy who played Clash of clans during your lecture. Sorry about that 🙂 )
Do you have a sample of this in NAV 2016? Thank you.