We use a ReportViewer control for report hosting and generation in a Windows Application.
The report is a .rdlc (several in fact with sub reports), and runs local.
I need to gain additional control over the contents in the footer which is now required to show minimal chart data, which is sensitive to the section of the report.
I understand that I cannot put a chart in the footer, that is no issue though, as I can generate the images needed for the footer up front, however I still need a way of linking the correct images into the footer.
There are some global pages, which all would contain the same footer image along with the global PageNumber. These compose the first few pages and the last couple of pages. So basically these are fine.
There are also some dynamic report sections in the middle of the report, these are a series of sub reports in a Tablix, and each of these sections, which could span multiple pages, would have a specific report footer set by the datasets row key for the current section. The Tablix passes this id Through to the SubReports as a parameter, so I had an idea that I could use a function instead of setting the parameter directly.
The idea here was to update a global variable in code which could be accessed within the footer to provide a dynamic element to any image path.
public shared dim HeaderIndex as Int32 = 0
Public Function HeaderPassThrough(ByVal index As Int32) As Int32
HeaderIndex = index
Return index
End Function
As you may already know it does not work, whenever the footer queries the value of Code.HeaderIndex it is the value of the very last section to process. So, the footer generates after the body of the report it would seem.
There is no way I can reasonably know the page numbers in advance, 1 section might flow to a single page, another 20, so any custom content I generate to go in the footer, will be generated based on that HeaderIndex, not a page number.
I then thought is there a way to get the page number into the page, as in this case an array of page number / HeaderIndex could be stored, and then referenced by the footer. But of course the global PageNumber is not available in the report body.
I would love to hear any ideas, as to how it might be possible to control footer contents dynamically based on report data.
The solution turned out to be less than obvious.
I added a TextBox to the Tablix containing the sub reports, and set the value of that TextBox to the Data key that I needed, I named it HeaderIndex
This value can then be referenced in the footer via ReportItems!HeaderIndex.Value
This was however only part of the solution as the value would only be populated on the first page of the subreport.
So I added the following function to the Report code section :
public shared dim LastHeaderIndex as Int32 = 0
Public Function HeaderPassThrough(ByVal index As String) As String
If Index = "" Then
Return LastHeaderIndex.ToString()
Else
LastHeaderIndex = Integer.Parse(index)
End IF
Return index
End Function
So now I can generate footer images in advance of rendering the report and save them on the filesystem keyed via the HeaderIndex.
The path for each image in the footer can then be an expression that includes the following (which provides the section identifier that the footer is under):
=Code.HeaderPassThrough(ReportItems!HeaderIndex.Value)
Related
I need a solution that will do the following.
When a report is run, it follows up with a disclaimer page.
However, if the report data runs over two pages, I need the disclaimer after each page. So, if the report is one page, page 1 is the report data and page 2 is the disclaimer. If the report spans over two pages, page 1 is the first portion of the report, page 2 is disclaimer, page 3 is second portion of the report, page 4 is disclaimer.
I cant think of a general method in ssrs to achieve that,
(depending on the structure of your report, there might be some tricks for example with groupings by lines of text, and a footer of the size of a page, that repeats every group, but that is assuming a text line is also a row in your dataset, which in turn is assuming you can manipulate your dataset with stored procedure. tl;dr; it depends and gets complicated quickly)
however, assuming you use c# to render your reports, using pdfsharp you could
prepare the disclaimer as pdf and simply add it after everey page in "post processing"
(something like that)
var document PdfReader.Open(StreamForPDf, PdfDocumentOpenMode.Import)
var disclaimer PdfReader.Open(pathorStream, PdfDocumentOpenMode.Import)
var result = new PdfDocument();
foreach (var page in document.pages)
{
result.add(page);
result.add(diclaimer.pages[0]);
}
result.save(streamorpath);
I'm facing an odd issue: I'm going to create lots of reports using reporting services (SSRS) and one request was to create a subreport that will be shown as a header in main report. I've come across two main problems:
It is not possible to insert subreports into report headers. I thought of a possible workaround and just create a subreport without header and then insert subreport on top of body in main report. But then I faced another problem:
My header contains a logo, title and page number. However, function for page numbering cannot be used in report body, only in header.
Is there any alternative? Or should i just add a header to each report instead of trying to create a subreport for the header?
You can start by using a report with the header as a template. You would start with this whenever you make a new report. That at least eliminates the need to recreate it each time.
If you do want to be able to manage the headers dynamically, you can use a data-driven approach. Almost all of the properties for images and text boxes can be defined with expressions. And the expressions can refer to a dataset. In other words, you can store all of your preferences in a table. Your header template would include a dataset that brings in all the settings. Then you can use expressions to define how the header will look.
By doing this, you would be able to adjust the image, font size, etc. in all the headers at once just by changing a value in your table. Obviously there is some overhead with setting up the template this way, but it has a negligible performance impact and gives you more power to manage the header dynamically.
I have a requirement to insert a blank page after every page when an SSRS report is printed/exported to PDF, however this needs to be controlled via a parameter.
The reason for this requirement is that when the report is printed each page of data needs to be printed onto a separate piece of paper, however the majority of printers are set to double sided by default. Users aren't able to change the default setting except on each occasion they print. Unfortunately this double sided print setting isn't applied everywhere so there needs to be an ability to control the addition/removal of blank pages.
I am able to force a blank page to be created after every page by simply setting the size of the report bigger than the page size, though it isn't possible to control page width size via an expression.
My only thought is that this may be possible via custom code but don't really know where to start with that.
If you go to the table properties, you can set an expression for the Page Break Disabled property. This will allow you to disable / enable a page break based on a parameter. In this example I created a boolean parameter called Break. If its set the parameter to True, you will get an additional page after your table. Hope this can get you started!
I've been fighting with SSRS for too long now on what should be a simple matter. I'm hoping someone can help me see a solution.
I have a report which has a number of profiles, and each profile has a large number of data sections. The data sections (various tables and charts) are not related to each other in any way other than that they "key" back to the parent profile id.
The goal (which seems simple) is to have a header on each page with the profile information, and then have the data sections (each formatted completely differently) laid out.
The first problem we encountered was that for some reason SSRS2008 does not allow a tablix cell to contain another tablix with a different dataset (why it can't just require a filter based on the parent grouping is beyond me). The recommended workaround for this shortcoming is to either combine all data into a giant dataset (not possible here, data sections are too numerous and varied) or to embed subreports and pass in the parameters. While option number two increases the "work" needed to print a large number of profiles, we proceeded to implement this and it does work.
The problem comes in on the main tablix (the one containing the subreports) that has a static row header group set with "RepeatOnNewPage = true". This setting allows the header to show on every page as desired... except for subreports the span multiple pages, where the header is incorrectly ommitted.
For some reason, when the subreport spans multiple pages, the header of the parent tablix is not repeated! This is driving me insane as it would seem that a couple bad design decisions in SSRS has put me in a situation where I can't create the report I want... headers works without subreports, but I need subreports in order to "join" the data sections to the profile.
This would seem to be a simple and common requirement... after all, it's a report that is being migrated from a decades old reporting system. I've scoured StackOverflow and Google without success... I've seem a number of questions/answers about page breaks, but nothing that suggests a solution to this problem with subreports.
I'm posting this in case I'm missing something. If anyone has any suggestions at all, it would be much appreciated.
A very clean and simple way to repeat the column header on each page
http://www.a2zmenu.com/Blogs/BI/Tablix-headers-not-repeating-in-SSRS-2008.aspx
We've solved our problem... although not in the most ideal way.
The Page Header (of the "master" report, not the subreports) seems to be the only way to consistently have a header section.
We implemented a solution based in large part on this blog posting:
Maintaining State in Reporting Services 2008
We modified slightly from the blog post, removing "id" from the methods and including a GUID to ensure the report values are not mixed up even if the user runs several copies of the report at the same time. (When using shared variables, remember that they are global to the report running across execution instances and across users on the report server, so a lot of care needs to be taken when they are used!)
In the report body we have a hidden text block that calls:
=Code.SetValue("xxx",Fields!Field1.Value) & Code.SetValue("yyy",Fields!Field2.Value)
and in the report page header we reference these as (for example):
=Code.GetValue("xxx")
This works because the body is calculated before the page header, even for Page 1.
Still, in the end it is a hack for something that should be in Microsoft's product, given that they have poured years of development into this product! Why we cannot have nested tablix's and easier to use headers is beyond me... again this is upgrading a report from a program from the early 90's which did all this without problem. At the very least, give us report variables that can be retrieved and set as the report is processed!
Regardless, things are as they are... we've tested the solution with shared variables and it seems to be working very well. We're going to run stress tests to make sure it's implemented correctly, I'll post something here if we find any further problems.
(And if anyone knows of some other way to get consistent header rows on pages, even when there are detail rows with large heights, please share...)
We have faced exactly the same problem during implementation of customer demands on SSRS Reports,
And did try a lot of things which all of them resulted with failure.
In our case,
Main Report has 4 subreport. Each SubReport should be started in new page. And also when new subreport begins, page header should be changed dynamically based on Subreport in body in current page.
Also one of SubReports which was SubReport3 has another case. Basically Main Report was running based on Dealer level. But Customer wants SubReport3 to run for each SubDealer related with #Dealer parameter. Also Customer wants to see each SubDealer data started in New page inside SubReport3.
As a result, we found different workaround as follows.
We created Page Header to Main Report. (Report Menu -> Add Page Header)(As #codinginthevoid said it is most consistent way)
We putted 4 subreports inside separate tablix. We added new column to each tablix. That column in each tablix visiblity = false, width of that column can be as small as possible, then created placeholder inside of that column, wroted down expression as follows:
If expression is in Tablix1, expression was ="Tablix1", if in Tablix2 then "Tablix2" and etc.
Then started design page header for Tablix1, each report item in pageheader that was putted for Tablix1 has visibility expression as follows:
=ReportItems!Tablix1_HiddenTextbox1.Value IS NOTHING
then applied same thing for Tablix2 and etc.
In the end, there were lots of textbox in PageHeader of report and some of them position was completely same, overlapped, But when reports is being rendered, each of those textboxes is being shown it is related page with related subreport.
I have encountered the same problem as well. What I found was that the way to solve the issue was to de-normalise the data, adding a 'Record Type' field to identify whether the row was a parent or a child.
There were two sub-tables in my tablix, both displaying detail data linked to the outer grouping. If I set the headers of the sub-tables to repeat on every page (using the Advanced arrow > Static Properties > KeepTogether = True, KeepWithGroup = After, RepeatOnNewPage = True) then one of the sub-tables would display correctly, however the parent table's repeating header would just disappear.
To keep a long story short, this was a massively annoying problem to solve. The solution is simple, it worked for me, but may not work for everyone.
Linked below is a SSRS2008 example RDL that connects to localhost and has an example of the problem I had and also the solution I implemented. Please feel free to use it if you find it useful!
(I would've posted it on here but Stack Overflow fails for code blocks it seems)
http://www.sqlservercentral.com/Forums/Topic1111567-1633-1.aspx?Update=1
I've been tasked with creating a report in MS-Access that looks exactly like a spreadsheet that a vendor supplies to us for my company to fill in.
The number of records per page is about 40 and there are usually 3-6 pages that need to be prepared. Each month there is a new report sent out and I just got finished writing it all in manually while looking at a report I generated. The purpose of this is to avoid manually transcribing the data.
They are adamant about using their format and will not accept a different report, so I'm trying to be sneaky about it.
Problems
I can duplicate the header of the spreadsheet and the rows just fine, I've just run into a few snags.
Blank rows need to be displayed on the last page of the report instead of nothing being printed (whitespace) and then the page footer.
Whitespace that exists between the Details and the Page Footer is present. The page footer should instead appear to be another row of cells, except that it has the text Page Total and the page total on that row.
The second item happens because the Page Footer always appears at the bottom of the page in a set location as opposed to where the records ended (even if they took up the entire page).
Ideas
If there is someway I could create a
group based on page, then I could
stick that right after the details
section so that it would line up
nicely as opposed to the page total
and still be able to display the page
total.
Inserting blank rows into the rows to
match the number of records, is this
possible? I could calculate how many
extra rows I would need to complete
the page, but how would I insert
those rows into the data source?
Creating a new excel spreadsheet from a template and just writing to there the rows.
I'm using MS-Access 2007 here with a MS-Access 2003 MDB.
Any help is greatly appreciated.
If you need gridlines to print at the end of an Access report, one option is to create a background bitmap that you insert into the report's picture property.
This would be rather fussy, as you could use it only if your headers and footers are identical on all pages, and you'd have to be sure that controls entirely cover the whole detail area so that the background graphic will not show through except on pages where there is blank space. Also, if you altered the width of your detail fields, you'd need to edit the graphic to harmonize with those changes.
Let me just say that I consider the insistance on replicating the look of the spreadsheet to be incredibly boneheaded stupid. What purpose is served by these gridlines except to replicate the visual appearance of a spreadsheet? Are they going to use the grid to write things in? If not, then it's just a really idiotic requirement.
Start by turning a copy of their Excel report into a template file. Remove the data, but keep headers, formating, and formulas as needed (Some data manipulation will be easier in Access.).
This way you can enter and store data in Access. Instead of having users fill-in the spreadsheet in Excel with VBA based on the template file.
You'll run into different issues of how to place the results of a query to a worksheet and filling in formulas in specific fields, etc., but those can be later questions to post.