//using Ghostscript.NET; //using Ghostscript.NET.Processor; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Drawing.Printing; using System.IO; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Controls; using FastReport; using FastReport.Data; using FastReport.Export.Pdf; using FastReport.Utils; using InABox.Clients; using InABox.Core; using InABox.Core.Reports; using InABox.Scripting; using InABox.Wpf.Reports.CustomObjects; using Syncfusion.Pdf; using Syncfusion.Pdf.Parsing; using XmlDocument = System.Xml.XmlDocument; namespace InABox.Wpf.Reports { public enum ReportExportType { PDF, HTML, RTF, Excel, Text, Image } public delegate void ReportExportDefinitionClicked(); public class ReportExportDefinition { public ReportExportDefinition(string caption, Bitmap image, ReportExportType type, Action action) { Caption = caption; Image = image; Type = type; Action = action; } public ReportExportDefinition(string caption, ContentControl control, ReportExportType type, Action action) { Caption = caption; Type = type; Action = action; Control = control; } public event ReportExportDefinitionClicked OnReportDefinitionClicked; public string Caption { get; } public Bitmap Image { get; } public ContentControl Control { get; } public ReportExportType Type { get; } public Action Action { get; } } [LibraryInitializer] public static class ReportUtils { public static List ExportDefinitions { get; } = new(); public static void RegisterClasses() { foreach (string printer in PrinterSettings.InstalledPrinters) ReportPrinters.Register(printer); Application.Current.Dispatcher.BeginInvoke(() => { RegisteredObjects.Add(typeof(MultiImageObject), "ReportPage", Wpf.Resources.multi_image, "Multi-Image"); RegisteredObjects.Add(typeof(MultiSignatureObject), "ReportPage",Wpf.Resources.signature, "Multi-Signature"); RegisteredObjects.Add(typeof(HTMLView), "ReportPage",Wpf.Resources.view, "HTML"); }); } public static void PreviewReport(ReportTemplate template, DataModel data, bool printandclose = false, bool allowdesigner = false) { if (template.IsRDL) { MessageBox.Show("RDL Reports are no longer supported!"); } else { PreviewWindow window = new(template, data) { AllowDesign = allowdesigner, Title = string.Format("Report Preview - {0}", template.Name), Height = 800, Width = 1200, WindowState = WindowState.Maximized, }; window.Show(); } } public static Report SetupReport(ReportTemplate? template, DataModel data, bool repopulate) { var templaterdl = template != null ? string.IsNullOrWhiteSpace(template.RDL) ? "" : template.RDL : ""; var tables = new List(); if (!string.IsNullOrWhiteSpace(templaterdl)) { var xml = new XmlDocument(); xml.LoadString(templaterdl); var datasources = xml.GetElementsByTagName("TableDataSource"); for (var i = 0; i < datasources.Count; i++) { var datasource = datasources[i]; tables.Add(datasource.Attributes.GetNamedItem("Name").Value); } } else { foreach(var table in data.DefaultTables) { tables.Add(table.TableName); } } var report = new Report(); report.Log += (sender, args) => Logger.Send(args.IsError ? LogType.Error : LogType.Information, "", args.Message); Config.ReportSettings.ShowProgress = false; report.LoadFromString(templaterdl); report.FileName = template?.Name ?? ""; foreach(var tableName in data.TableNames) { var modelTable = data.GetDataModelTable(tableName); var dataSource = report.GetDataSource(tableName); if (dataSource != null && modelTable.Type is not null) { var columnNames = CoreUtils.GetColumnNames(modelTable.Type, x => true); foreach (var column in dataSource.Columns) { if(column is FastReport.Data.Column col && !col.Enabled) { //columns.Add(col.Name.Replace('_','.')); columnNames.Remove(col.Name.Replace('_', '.')); } /*if (column is FastReport.Data.Column col && col.DataType != null && col.DataType.IsAssignableTo(typeof(IEnumerable))) { col.BindableControl = ColumnBindableControl.Custom; col.CustomBindableControl = "MultiImageObject"; }*/ } modelTable.Columns = Columns.None(modelTable.Type).Add(columnNames); } } ScriptDocument? script = null; bool ScriptOK = false; if (!string.IsNullOrWhiteSpace(template?.Script)) { script = new ScriptDocument(template.Script); if (script.Compile()) { script.SetValue("Model", data); ScriptOK = script.Execute("Report", "Init"); } } if (repopulate) data.LoadModel(tables); if (ScriptOK && script is not null) { script.SetValue("RequireTables", tables); script.Execute("Report", "Populate"); } var ds = data.AsDataSet(); report.RegisterData(ds); foreach (var tableName in data.TableNames) { var columnNames = data.GetColumns(tableName)?.ColumnNames().ToHashSet(); var dataSource = report.GetDataSource(tableName); if(dataSource != null) { foreach (var column in dataSource.Columns) { if (column is FastReport.Data.Column col) { if (col.DataType != null && col.DataType.IsAssignableTo(typeof(IEnumerable))) { col.BindableControl = ColumnBindableControl.Custom; col.CustomBindableControl = "MultiImageObject"; } col.Enabled = columnNames is null || columnNames.Contains(col.Name.Replace('_', '.')); } } } } if (string.IsNullOrWhiteSpace(templaterdl)) { foreach (var table in data.DefaultTables) { var dataSource = report.GetDataSource(table.TableName); dataSource.Enabled = true; } foreach (Relation relation in report.Dictionary.Relations) if (data.DefaultTables.Any(x => x.TableName.Equals(relation.ParentDataSource.Alias)) && data.DefaultTables.Any(x => x.TableName.Equals(relation.ChildDataSource.Alias))) relation.Enabled = true; } return report; } public static void DesignReport(ReportTemplate template, DataModel data, bool populate = false, Action? saveTemplate = null) { var isrdl = template != null && template.IsRDL; var templaterdl = template != null ? string.IsNullOrWhiteSpace(template.RDL) ? "" : template.RDL : ""; if (isrdl) MessageBox.Show("RDL Reports are not supported!"); else { PreviewWindow window = new(template, data) { AllowDesign = true, Title = string.Format("Report Designer - {0}", template.Name), Height = 800, Width = 1200, WindowState = WindowState.Maximized, IsPreview = false, ShouldPopulate = populate, SaveTemplate = saveTemplate }; window.Show(); } } public static byte[] CompressPDF(byte[] original) { //Load the existing PDF document PdfLoadedDocument loadedDocument = new PdfLoadedDocument(original); //Create a new compression option. PdfCompressionOptions options = new PdfCompressionOptions(); //Enable the compress image. options.CompressImages = true; //Set the image quality. options.ImageQuality = 50; //Assign the compression option to the document. loadedDocument.CompressionOptions = options; //Creating the stream object. using (MemoryStream stream = new MemoryStream()) { //Save the document into stream. loadedDocument.Save(stream); return stream.GetBuffer(); } } public static byte[] ReportToPDF(ReportTemplate template, DataModel data, bool repopulate = true) { byte[] result = null; if (template.IsRDL) MessageBox.Show("RDL Reports are not supported!"); else using (var report = SetupReport(template, data, repopulate)) { report.Prepare(); var ms = new MemoryStream(); report.Export(new PDFExport() { JpegCompression = true, JpegQuality = 65, Compressed = true }, ms); result = ms.GetBuffer(); } return result; } public static Filter GetReportFilter(string sectionName, DataModel model) { return new Filter(x => x.DataModel).IsEqualTo(model.Name) .And(x => x.Section).IsEqualTo(sectionName) .And(x => x.Visible).IsEqualTo(true); } public static IEnumerable LoadReports(string sectionName, DataModel model, Columns? columns = null) { return new Client().Query( GetReportFilter(sectionName, model), columns, new SortOrder(x => x.Name)) .ToObjects(); } private static void PopulateMenu(ItemsControl menu, string sectionName, DataModel model, bool allowdesign, bool populate = false) { var reports = LoadReports(sectionName, model); foreach (var report in reports) { var print = new MenuItem { Header = report.Name, Tag = report }; print.Click += (sender, args) => { PreviewReport(report, model, false, allowdesign); }; menu.Items.Add(print); } if (allowdesign) { if (menu.Items.Count > 0 && menu.Items[^1] is not Separator) { menu.Items.Add(new Separator()); } var manage = new MenuItem { Header = "Manage Reports" }; manage.Click += (sender, args) => { var manager = new ReportManager() { DataModel = model, Section = sectionName, Populate = populate }; manager.ShowDialog(); }; menu.Items.Add(manage); } } /// /// Populate the with a list of reports attached to this data model, loaded through . /// /// /// This is used for the various places we have context menus for printing reports. /// /// Allow designing reports; if , then also adds a "Manage Reports" button. /// Determines whether the datamodel should be reloaded when printing a report.
Set to if all the data has already been loaded. public static void PopulateMenu(MenuItem menu, string sectionName, DataModel model, bool allowdesign, bool populate = false) => PopulateMenu(menu as ItemsControl, sectionName, model, allowdesign, populate); /// /// Populate the with a list of reports attached to this data model, loaded through . /// /// /// This is used for the various places we have context menus for printing reports. /// /// Allow designing reports; if , then also adds a "Manage Reports" button. /// Determines whether the datamodel should be reloaded when printing a report.
Set to if all the data has already been loaded. public static void PopulateMenu(ContextMenu menu, string sectionName, DataModel model, bool allowdesign, bool populate = false) => PopulateMenu(menu as ItemsControl, sectionName, model, allowdesign, populate); public static void PrintMenu(FrameworkElement? element, string sectionName, DataModel model, bool allowdesign, bool populate = false) { var menu = new ContextMenu(); PopulateMenu(menu, sectionName, model, allowdesign, populate); if (menu.Items.Count > 0) { menu.PlacementTarget = element; menu.IsOpen = true; } } public static void PrintMenu(FrameworkElement? element, string sectionName, DataModel model, bool allowdesign, bool populate = false) where TType : Entity, IRemotable, IPersistent, new() { PrintMenu(element, sectionName, model, allowdesign, populate); } } }