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! ![]()