Master Report solution we discussed in the previous post works great but it lacks automation: someone has to go and manually select the master and child templates in order to get the combined result.
But what if we needed to email a few dozens of such reports every day and didn’t want to hire a monkey?
Then we’d probably need a scheduled task which would run daily and generate those reports based on some input parameters and email them over. Seems like a hard one for SharpShooter? Not at all – read on for the solution!
High level solution.
So we create a new console app with Main like this:
/// /// Usage: [app.exe] /master:"path" /child:"path" /saveAs:"path" /// static void Main(string[] args) { var masterPath = args[0].Replace("/master:", ""); var childPath = args[1].Replace("/child:", ""); var saveAsPath = args[2].Replace("/saveAs:", ""); var generator = new ReportGenerator(masterPath, childPath, saveAsPath); generator.Run(); }
Yes it lacks quite a bit of error checking but I’d leave it as an exercise to the reader
Internally, the above ReportGenerator might seem a bit complicated as we’d have to solve one big problem there: how to generate a report without showing a windows form. Interested? Let’s look inside!
Implementation details.
We need a WinForm due to the asynchronous nature of SharpShooter: without a form it cannot properly operate its threads. However, it’s possible to create a hidden form just for the generation timespan, and close it immediately afterwards. That’s exactly the trick we’ll employ.
Below is the constructor of our generator:
public ReportGenerator(string masterPath, string childPath, string resultPdfPath) { ApplyReport(_masterSlot, masterPath); ApplyReport(_childSlot, childPath); _resultPdfPath = resultPdfPath; var hiddenForm = new Form { FormBorderStyle = FormBorderStyle.FixedToolWindow, ShowInTaskbar = false, StartPosition = FormStartPosition.Manual, Location = new Point(-2000, -2000), Size = new Size(1, 1), Text = "Hidden form to generate reports from a console app" }; _reportManager.OwnerForm = hiddenForm; _reportManager.Reports.AddRange(new[] { _masterSlot, _childSlot }); _reportManager.ResolveSubReport += (sender, args) => { if (args.TemplateName.EndsWith("Master")) { args.Template = _masterSlot.LoadReport(); } }; }
Above, we do a bunch of interesting things:
- setup master and child report slots via ApplyReport method which is not important enough to show here
- create a hidden Windows Form which becomes “owner form” for our report manager
- setup ResolveSubReport so that it would correctly setup master template in case the child template requires it
So far so good, and now let’s look at the Run method:
public void Run() { try { var filter = new PdfExportFilter(); filter.Export(_childSlot.RenderDocument(), _resultPdfPath, false); } finally { if (_reportManager.OwnerForm != null) { _reportManager.OwnerForm.Close(); } } //to test email sending, uncomment and update: //var message = new MailMessage("[email protected]", "[email protected]") { // Subject = "Report", // Body = "Please find the report pdf attached" //}; //message.Attachments.Add(new Attachment(_resultPdfPath)); //var emailClient = new SmtpClient("smtp.bar.com"); //emailClient.Send(message); }
As you see, we export the generated report as a .pdf file and dispose the hidden form – voilà, job done! (If you want to test email sending, the feel free to uncomment and update appropriately the corresponding snippet above.)
Here’s how we use the whole thing:
And here’s the .pdf generated with the master/child templates from the previous post (the “Happy New Year” header comes from the master template, while the zipcode comes from the child one):
Summary.
Console applications can work with SharpShooter, too – you’re not constrained to WinForms interfaces.
Coding is slightly odd though, but using SharpShooter from a console app opens up a way to a throng of new usages, autonomous scripts which would generate reports, email them, send them over SFTP and do all sorts of things, all of which – potentially – completely automatically.
Feel free to browse source code of the solution, or download .zip archive – and, indeed, Happy New Year 2012!