{"id":90,"date":"2010-01-14T11:02:00","date_gmt":"2010-01-14T11:02:00","guid":{"rendered":"\/lisa\/post\/2010\/01\/14\/Walkthrough-Part-I-Dynamic-interactive-paging-and-another-fierce-look-at-parameters.aspx"},"modified":"2010-01-14T11:02:00","modified_gmt":"2010-01-14T11:02:00","slug":"walkthrough-part-i-dynamic-interactive-paging-and-another-fierce-look-at-parameters","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2010\/01\/14\/walkthrough-part-i-dynamic-interactive-paging-and-another-fierce-look-at-parameters\/","title":{"rendered":"Walkthrough, Part I: Dynamic interactive paging and another fierce look at parameters"},"content":{"rendered":"<p>\nIt&#39;s hard to believe how many questions come my way involving dynamic page breaks and parameters.\n<\/p>\n<p class=\"NB\">\n(Including yours, Philippe.&nbsp; You&#39;re next.&nbsp; And yours was &#39;way easy compared to this one&#8230; &lt;g&gt;)\n<\/p>\n<p>\nKaren Grube came up with an interesting scenario and some specific constraints, requiring some special handling.&nbsp;I&#39;m going to paraphrase a bit, to try to bring out the generically &quot;interesting&quot; bits, and walk through the whole problem, and I hope you find that some parts of it are useful to you.\n<\/p>\n<p>\nHere&#39;s the deal:\n<\/p>\n<ul>\n<li>\n<div>\n\tShe&#39;s using RS 2008 and an ASPX page with a ReportViewer&nbsp;control on it to display&nbsp;reports to users&nbsp;\n\t<\/div>\n<\/li>\n<li>\n<div>\n\tShe has hundreds of reports, with a common setup, as follows:\n\t<\/div>\n<ul>\n<li>\n<div>\n\t\ta standard landscape-orientation page size for rendered output (such as printing, Excel, PDF)\n\t\t<\/div>\n<\/li>\n<li>\n<div>\n\t\ta standard expectation on users&#39; parts to see the HTML content, hosted in the ReportViewer control, un-paginated, <strong>but<\/strong>\n\t\t<\/div>\n<\/li>\n<li>\n<div>\n\t\ta rule that the unpaginated content must be forced to paginated output if the dataset has &gt; a certain number of rows, <strong>and<\/strong>\n\t\t<\/div>\n<\/li>\n<li>\n<div>\n\t\tan inability to extrapolate a probable number of output rows from the user-chosen parameter values.&nbsp;\n\t\t<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\nThe last condition is really the killer.&nbsp; Presumably, she has a large number of&nbsp;parameters, and they may be quite different for each report.&nbsp; She is not allowed to do a preprocess call to the db-backend from her web tier in order to decide whether the html-rendered content should paginate or not.&nbsp; She won&#39;t know until she&#39;s actually in the report.\n<\/p>\n<p>\nSo, previous to talking with me, she had settled on a methodology something like this:\n<\/p>\n<ul>\n<li>\n<div>\n\tUse a parameter called ShowAll&nbsp;for the user to indicate their preference for&nbsp;browser-hosted display&nbsp;\n\t<\/div>\n<\/li>\n<li>\n<div>\n\tSet the Interactive Page dimensions the same way as the export\/standard page dimensions&nbsp;\n\t<\/div>\n<\/li>\n<li>\n<div>\n\tCreate two overlaid tablix layout controls, one with &quot;Keep Together&quot; set true and one with the same property set False\n\t<\/div>\n<\/li>\n<li>\n<div>\n\tBring the data into the report, and, at that point,&nbsp;evaluate ShowAll and also whether there are too many rows to allow un-paginated display in the browser,\n\t<\/div>\n<\/li>\n<li>Hide\/show the two tablix controls based on this evaluation.<\/li>\n<\/ul>\n<p>\nThis technique works, but causes a couple of problems:\n<\/p>\n<ul>\n<li>\n<div>\n\tTwo tablix controls to maintain, for each report, is kind of a PITA.\n\t<\/div>\n<\/li>\n<li>\n<div>\n\tThere are two textbox controls following the table-format content, and these get forced to the next &quot;page&quot;, which is not optimal.\n\t<\/div>\n<\/li>\n<\/ul>\n<p>\nWhat Karen would really like to do is set either &quot;Keep Together&quot; or Interactive Page Height dynamically.&nbsp; She knows that the right way to get un-paginated content in the HTML display is to set Interactive Page Height to 0 &#8212; and I hope you do too.\n<\/p>\n<p>\nUnfortunately, neither&nbsp;KeepTogether nor InteractivePageHeight&nbsp;can take an expression.&nbsp; And, remember: she can&#39;t adjust the RDL dynamically in this case, because she doesn&#39;t know how many rows will end up in the report before actually gathering the data <em>into<\/em> the report.\n<\/p>\n<p>\nSo&#8230; what to do?\n<\/p>\n<h2>Stand the problem on its head.<\/h2>\n<p>\nSince the right way to get &quot;flowing&quot;, un-paginated content in the HTML display is to set Interactive Page Height to 0&#8230; let&#39;s do that.\n<\/p>\n<p>\nBut wait.&nbsp; What happens when the user doesn&#39;t want ShowAll to be on (the user prefers pagination)?&nbsp; And, more significantly, what happens if the number of rows is greater than the allowed maximum?\n<\/p>\n<p>\nWe can use dynamic page breaks for that.\n<\/p>\n<p>\nBut, wait.&nbsp; Won&#39;t dynamic page breaks interfere with the correct pagination for standard &nbsp;export content?&nbsp; (Karen&#39;s rows aren&#39;t all the same height, so we shouldn&#39;t try to figure out a particular number of rows per PDF or printed page.)&nbsp; Well&#8230; they might.&nbsp; But we can control the export content ourselves and make sure that the export content always behaves as if ShowAll is False, so our explicit page breaks don&#39;t interfere with the &quot;natural&quot; ones in each renderer.&nbsp;\n<\/p>\n<p>\nAnd how are we going to do that?&nbsp; Aye, there&#39;s the rub.&nbsp; Karen thinks it&#39;s easy to mess around with parameters at exactly the right moment.&nbsp; It turns out, it&#39;s not easy at all.&nbsp;&nbsp; That&#39;s why this walkthrough has two parts.\n<\/p>\n<p>\nAt least the textbox problem completely goes away without any work at all.&nbsp; Small comfort.\n<\/p>\n<p>\nSo, bear with me, and we&#39;ll start our walkthrough now.\n<\/p>\n<h2>Mise en place<\/h2>\n<p>\nKaren&#39;s a C# programmer, so I&#39;ll use C#.&nbsp; I&#39;m not great at it, don&#39;t laugh. I&#39;m sure you&#39;ll do better.&nbsp; But I&#39;m going to fully work through this problem, no matter how silly the code I use, because I think you will miss some niceties if I don&#39;t.\n<\/p>\n<p>\nI&#39;ll also use the RS SOAP API here, for no good reason except that I rarely do, but I figure Karen will probably be happier with it than REST.\n<\/p>\n<p>\nMy simple report of course has only one tablix in it, not two, followed by a couple of text boxes with aggregated values to match Karen&#39;s scenario.&nbsp; It has&nbsp;four parameters, as follows:\n<\/p>\n<table border=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\"><strong>ShowAll<\/strong><\/td>\n<td>&nbsp; &nbsp;<\/td>\n<td valign=\"top\">\n<p>\n\t\t\tThis one is Karen&#39;s. You know what it does.\n\t\t\t<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\"><strong>RowLimit<\/strong><\/td>\n<td>&nbsp;&nbsp; <\/td>\n<td valign=\"top\">\n<p>\n\t\t\tThis one represents all Karen&#39;s other parameters. It governs how many rows are returned in my test report.\n\t\t\t<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\"><strong>PerPageLimit<\/strong><\/td>\n<td>&nbsp;&nbsp; <\/td>\n<td valign=\"top\">\n<p>\n\t\t\tThis one is the largest number of rows that should be displayed on an interactive page, no matter what the value of ShowAll. Karen probably would not display this one.\n\t\t\t<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\"><strong>Test<\/strong><\/td>\n<td>&nbsp;&nbsp; <\/td>\n<td valign=\"top\">\n<p>\n\t\t\tThis is a multi-valued parameter, which does nothing in the report except make sure my parameter-handling code handles all situations, including error trapping for a missing or nullvalue, and the special object-handling that a parameter list requires.\n\t\t\t<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p style=\"text-align: center\">\n<img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2010\/1\/DIP1.PNG\" alt=\"\" \/>\n<\/p>\n<p>\nI&#39;ll use my usual simple SQLWorld database borrowed from the mySQL community, because the data really isn&#39;t the point in this walkthrough. Here&#39;s the query I used; you can see how RowLimit stands in for Karen&#39;s query requirements when I test:\n<\/p>\n<p class=\"code\">\n<span style=\"color: #0000ff\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT TOP <\/span><span style=\"color: #808080\">(<\/span>@RowLimit<span style=\"color: #808080\">) *<\/span> <span style=\"color: #0000ff\">FROM <\/span>SQLWorld<span style=\"color: #808080\">.<\/span>dbo<span style=\"color: #808080\">.<\/span>City\n<\/p>\n<h2>&Ccedil;a marche&#8230;&nbsp;<\/h2>\n<p>\nNow the fun begins.&nbsp; The sample report with the parameters above is simplicity itself.&nbsp; This screen shot is from ReportBuilder 2.0; there is really nothing in&nbsp;this that would be easier to do in Report Designer than the Builder.\n<\/p>\n<p align=\"center\">\n<img decoding=\"async\" src=\"\/lisa\/wp-non\/migrated\/2010\/1\/DIP2.PNG\" alt=\"\" \/>\n<\/p>\n<p>\nThe only weird thing you&#39;ll see in the report &#8212; and it isn&#39;t really pertinent to Karen&#39;s scenario in particular &#8212;&nbsp;is that I have replicated the tablix header row in the page header.&nbsp;These two extra textbox controls&nbsp;each have the hidden\/Visibility expression <strong>=Globals!PageNumber=1<\/strong>, so they stand in for the tablix header on subsequent pages.&nbsp;\n<\/p>\n<p>\nWhat are they for? Frankly, sometimes I get tired of trying to figure out how various renderers will &quot;react&quot; to the various layouts and attributes that tell a header whether it should re-appear on additional pages, and when I&#39;m in a hurry I just use this dodge instead of testing all the possibilities.\n<\/p>\n<p class=\"NB\">\nAlso frankly, I tend not to use KeepTogether; I generally don&#39;t understand some of the logic behind some of these options. I&#39;m impressed to see that Karen was comfortable with its behavior and is using it successfully. I&#39;m not sure how each renderer will treat it, what small variations in page size will do, and rarely rely on it if I don&#39;t have time to test exhaustively. As you&#39;ll see, it&#39;s not relevant to my version of the solution.\n<\/p>\n<p>\nThe &quot;regular&quot; page layout size for my solution matches Karen&#39;s. We plan not to mess with exported renditions, which follow those dimensions as appropriate to each format, remember? My Interactive Page Width is the same as Karen&#39;s too. (Don&#39;t be fooled because the layout you see in the layout window is much narrower than a landscape report; as long as your laid out width is <em>narrower<\/em> than your intended result, with a comfortable buffer for margins, you should always be fine. But the Interactive Page Height is 0.\n<\/p>\n<h2>A soup&ccedil;on of saffron&#8230;&nbsp;<\/h2>\n<p>\nYou also see &#8212; and the &quot;tip&quot; textbox in the page header calls your attention to it &#8212; that I&#39;ve added a group to this report. Here&#39;s where we control the pagination.\n<\/p>\n<p>\nI&#39;ve deleted visible columns from this group, and set it to page break &quot;between each instance of the group&quot;.&nbsp; I&#39;ve used the following group break expressinon:\n<\/p>\n<p class=\"code\">\n=IIF(<span style=\"color: red\">Parameters!PerPageLimit.Value =-1&nbsp;OrElse Parameters!ShowAll.Value, <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Nothing<\/span>,<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style=\"color: green\"><strong>Code.BreakGroup<\/strong>(RowNumber(&quot;Tablix1&quot;) Mod Parameters!PerPageLimit.Value =0)<\/span>)\n<\/p>\n<p>\nOkay, let&#39;s parse this instruction: if our current number-of-rows per page has not been explicitly limited&nbsp;or the user has indicated a preference for un-paginated content, <span style=\"color: red\">never break<\/span>.&nbsp; Otherwise, decide when to break based on <span style=\"color: green\">a simple code function<\/span>, which I&#39;ve embedded in the report.&nbsp;(It&#39;s completely generic, so there&#39;s no reason you couldn&#39;t put it into an external DLL for use by all your reports if you prefer.)&nbsp;Here&#39;s all the code:\n<\/p>\n<p class=\"code\">\n<span style=\"color: #0000ff\">Dim<\/span> MyGroup <span style=\"color: #0000ff\">As Integer<\/span> = 0 &nbsp; <br \/>\n<font color=\"#0000ff\"><br \/>\nFunction<\/font> BreakGroup(ByVal TimeToBreak As Boolean) <font color=\"#0000ff\">As Integer <\/font><br \/>\n<span style=\"color: #0000ff\">&nbsp;&nbsp; If<\/span> TimeToBreak<span style=\"color: #0000ff\">Then<\/span> <br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyGroup = MyGroup + 1&nbsp;<br \/>\n<span style=\"color: #0000ff\">&nbsp;&nbsp;&nbsp;End<\/span> <span style=\"color: #0000ff\">If<\/span> <br \/>\n<span style=\"color: #0000ff\">&nbsp;&nbsp; Return<\/span> MyGroup <\/p>\n<p><font color=\"#0000ff\">EndFunction &nbsp; <\/font>\n<\/p>\n<p>\nThe simple logic above isn&#39;t 100% perfect.&nbsp; For one thing, it&#39;s based on a number of rows per page, and we already know that Karen&#39;s rows-per-page could vary based on stretching row heights.&nbsp; For another thing, I haven&#39;t bothered accounting for the fact that the Mod break expression will probably have one less rows-per-page on the first page than others; you could add Globals!PageNumber.Value into the mix here, and correct as needed, if you want.&nbsp; But it really doesn&#39;t matter.\n<\/p>\n<p>\nThis logic is only there for <strong>interactive<\/strong>&nbsp;page breaks in the browsed&nbsp;HTML version and, as such, the exact height of the page isn&#39;t important.&nbsp; We just want to limit it.&nbsp; If the limit is, say, 250, but the first page only has 249, or if the height of 250 rows is a couple of pixels more or less on different pages, we don&#39;t really care.\n<\/p>\n<p>\nFor rendered pages in other formats, we&#39;re simply going <strong>to make sure that the value of PerPageLimit is always -1<\/strong>, so the renderer&#39;s natural behavior for the page size will &quot;take over&quot; and control the page breaks.\n<\/p>\n<p>\nHow are we going to do that?&nbsp; Aha.&nbsp; This is where life gets really interesting.\n<\/p>\n<h2>Define interesting.<\/h2>\n<p>\n<a href=\"\/lisa\/2010\/01\/16\/Walkthrough-Part-II-Dynamic-Interactive-Paging-and-another-fierce-look-at-parameters\/\" title=\"blog post with the second part of this walkthrough.\">OK, I will<\/a>.&nbsp; But it&#39;s going to take a whole &#39;nuther walkthrough (I write long posts, but this would be ridiculous) and a lot more code.&nbsp;\n<\/p>\n<p>\nIt&#39;s still the right way, and the code is in the right place for Karen to use her own tier (and her type of skills) to take care of business, for all reports at once.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#39;s hard to believe how many questions come my way involving dynamic page breaks and parameters. (Including yours, Philippe.&nbsp; You&#39;re next.&nbsp; And yours was &#39;way easy compared to this one&#8230; &lt;g&gt;) Karen Grube came up with an interesting scenario and some specific constraints, requiring some special handling.&nbsp;I&#39;m going to paraphrase a bit, to try to<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2010\/01\/14\/walkthrough-part-i-dynamic-interactive-paging-and-another-fierce-look-at-parameters\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,5],"tags":[],"class_list":["post-90","post","type-post","status-publish","format-standard","hentry","category-asp-net","category-reporting"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/90","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/comments?post=90"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/90\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=90"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=90"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=90"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}