//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() { CoreUtils.RegisterClasses(typeof(ReportTemplate).Assembly, typeof(ReportUtils).Assembly); 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); } } public static void PopulateMenu(MenuItem menu, string sectionName, DataModel model, bool allowdesign, bool populate = false) => PopulateMenu(menu as ItemsControl, sectionName, model, allowdesign, populate); 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); } #region Old RDL Stuff (Deprecated) // private static ReportDefinition SetupReportDefinition(String rdl, Dictionary dataenvironment = null) // { // ReportDefinition report = null; // if (String.IsNullOrWhiteSpace(rdl)) // report = CreateReport(); // else // report = DeserialiseReport(rdl); // // if (dataenvironment != null) // SetupReportData(report, dataenvironment); // return report; // } // public static String SetupReport(String rdl, Dictionary dataenvironment = null) // { // var defn = SetupReportDefinition(rdl, dataenvironment); // return SerialiseReport(defn); // } // // public static MemoryStream SetupReportToStream(String rdl, Dictionary dataenvironment = null) // { // var defn = SetupReportDefinition(rdl, dataenvironment); // return SerialiseReportToStream(defn); // } // public static String CleanupReport(String rdl) // { // ReportDefinition report = null; // if (String.IsNullOrWhiteSpace(rdl)) // report = CreateReport(); // else // report = DeserialiseReport(rdl); // // CleanupReportData(report); // // return SerialiseReport(report); // // } // private static ReportDefinition CreateReport() // { // ReportDefinition rd = new ReportDefinition(); // rd.DataSources = new DataSources(); // rd.DataSets = new DataSets(); // // rd.ReportSections = new ReportSections(); // rd.ReportSections.Add( // new ReportSection() // { // Width = new Syncfusion.RDL.DOM.Size("7.5in"), // Body = new Body() // { // Style = new Syncfusion.RDL.DOM.Style() { BackgroundColor = "White", Border = new Syncfusion.RDL.DOM.Border() }, // Height = new Syncfusion.RDL.DOM.Size("10in"), // // }, // Page = new Syncfusion.RDL.DOM.Page() // { // PageHeight = new Syncfusion.RDL.DOM.Size("11in"), // PageWidth = new Syncfusion.RDL.DOM.Size("8.5in"), // Style = new Syncfusion.RDL.DOM.Style() { BackgroundColor = "White", Border = new Syncfusion.RDL.DOM.Border() }, // } // } // ); // rd.EmbeddedImages = new EmbeddedImages(); // // rd.RDLType = RDLType.RDL2010; // rd.CodeModules = new CodeModules(); // rd.CodeModules.Add(new CodeModule() { Value = "System.Drawing, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a" }); // rd.CodeModules.Add(new CodeModule() { Value = "Syncfusion.Pdf.Base, Version = 13.3350.0.7, Culture = neutral, PublicKeyToken = 3d67ed1f87d44c89" }); // rd.CodeModules.Add(new CodeModule() { Value = "Syncfusion.Linq.Base, Version = 13.3350.0.7, Culture = neutral, PublicKeyToken = 3d67ed1f87d44c89" }); // // rd.Classes = new Classes(); // rd.Classes.Add(new Class() { ClassName = "Syncfusion.Pdf.Barcode.PDFCode39Barcode", InstanceName = "Code39" }); // rd.Classes.Add(new Class() { ClassName = "Syncfusion.Pdf.Barcode.PdfQRBarcode", InstanceName = "QRCode" }); // // rd.Code = @" // Public Function Code39BarCode(Text As String) As String // Dim _msg as String // try // Code39.BarHeight = 100 // Code39.Text = Text // Code39.EnableCheckDigit = True // Code39.EncodeStartStopSymbols = True // Code39.ShowCheckDigit = False // Code39.TextDisplayLocation = 0 // Dim _img As System.Drawing.Image = Code39.ToImage() // Dim ms As New System.IO.MemoryStream() // _img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp) // Dim _bytes = ms.ToArray() // Return System.Convert.ToBase64String(_bytes, 0, _bytes.Length) // Catch ex As Exception // _msg = ex.toString() // End Try // return Nothing // End Function // // Public Function QRBarCode(Text As String) As String // Dim _msg as String // try // QRCode.Text = Text // QRCode.XDimension = 4 // Dim _img As System.Drawing.Image = QRCode.ToImage() // Dim ms As New System.IO.MemoryStream() // _img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp) // Dim _bytes = ms.ToArray() // Return System.Convert.ToBase64String(_bytes, 0, _bytes.Length) // Catch ex As Exception // _msg = ex.toString() // End Try // return Nothing // End Function // // "; // return rd; // // //MemoryStream memoryStream = new MemoryStream(); // //TextWriter ws2 = new StreamWriter(memoryStream); // //xs2.Serialize(ws2, rd, serialize); // //memoryStream.Position = 0; // ////To save to a file. // //StringWriter ws3 = new StringWriter // //TextWriter ws3 = new StreamWriter(_tempfile); // //xs2.Serialize(ws3, rd, serialize); // //ws2.Close(); // //ws3.Close(); // //memoryStream.Close(); // // } private static string DataTableToXML(Type type, CoreTable table) { var doc = new XmlDocument(); var root = doc.CreateElement("", type.Name.ToLower() + "s", ""); doc.AppendChild(root); //var properties = CoreUtils.PropertyList(type, x => true, true); if (table != null) { if (table.Rows.Any()) { foreach (var datarow in table.Rows) { var row = doc.CreateElement("", type.Name.ToLower(), ""); foreach (var column in table.Columns) { var field = doc.CreateElement("", column.ColumnName.Replace('.', '_'), ""); var oVal = datarow[column.ColumnName]; var value = doc.CreateTextNode(oVal != null ? oVal.ToString() : ""); field.AppendChild(value); row.AppendChild(field); } root.AppendChild(row); } } else { var row = doc.CreateElement("", type.Name.ToLower(), ""); foreach (var column in table.Columns) { var field = doc.CreateElement("", column.ColumnName.Replace('.', '_'), ""); var value = doc.CreateTextNode(""); field.AppendChild(value); row.AppendChild(field); } root.AppendChild(row); } } var xmlString = ""; using (var wr = new StringWriter()) { doc.Save(wr); xmlString = wr.ToString(); } return xmlString.Replace("\r\n", ""); } public static DataSet CreateReportDataSource(Dictionary dataenvironment) { var ds = new DataSet(); foreach (var key in dataenvironment.Keys) { var table = dataenvironment[key]; var dt = new DataTable(key.EntityName().Split('.').Last()); foreach (var column in table.Columns) dt.Columns.Add(column.ColumnName); foreach (var row in table.Rows) dt.Rows.Add(row.Values.ToArray()); ds.Tables.Add(dt); } return ds; } // private static void SetupReportData(ReportDefinition report, Dictionary dataenvironment) // { // // report.DataSets.Clear(); // report.DataSources.Clear(); // foreach (System.Type type in dataenvironment.Keys) // { // String _tempfile = Path.GetTempFileName(); // String xml = DataTableToXML(type, dataenvironment[type]); // File.WriteAllText(_tempfile, xml); // // Create DataSource(s) // DataSource datasource = new DataSource() // { // Name = type.Name, // ConnectionProperties = new ConnectionProperties() // { // DataProvider = "XML", // IntegratedSecurity = true, // ConnectString = _tempfile // }, // SecurityType = SecurityType.None, // }; // report.DataSources.Add(datasource); // // Syncfusion.RDL.DOM.DataSet dataset = new Syncfusion.RDL.DOM.DataSet() { Name = type.Name }; // dataset.Fields = new Fields(); // // CoreTable table = dataenvironment[type]; // foreach (var column in table.Columns) // { // dataset.Fields.Add( // new Field() // { // Name = column.ColumnName.Replace('.', '_'), // DataField = column.ColumnName.Replace('.', '_'), // TypeName = column.DataType.Name // } // ); // } // // //var properties = CoreUtils.PropertyList(type, x => true, true); // // //// Create DataSet(s) // //foreach (String key in properties.Keys) // //{ // // dataset.Fields.Add( // // new Field() // // { // // Name = key.Replace('.', '_'), // // DataField = key.Replace('.', '_'), // // TypeName = properties[key].Name // // } // // ); // //} // dataset.Query = new Query() // { // DataSourceName = type.Name, // CommandType = Syncfusion.RDL.DOM.CommandType.Text, // CommandText = String.Format("{0}s/{0}", type.Name.ToLower()) // }; // report.DataSets.Add(dataset); // } // } // // private static void CleanupReportData(ReportDefinition report) // { // foreach (var ds in report.DataSources) // { // String _tempfile = ds.ConnectionProperties.ConnectString; // if (File.Exists(_tempfile)) // File.Delete(_tempfile); // ds.ConnectionProperties.ConnectString = ""; // } // report.DataSources[0].ConnectionProperties.ConnectString = ""; // } // // private static ReportDefinition DeserialiseReport(String rdl) // { // String data = rdl; // try // { // byte[] debase64 = Convert.FromBase64String(rdl); // data = Encoding.UTF8.GetString(debase64); // } // catch (Exception e) // { // Logger.Send(LogType.Error, "", String.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); // } // ReportDefinition report = null; // XmlSerializer xs = new XmlSerializer(typeof(ReportDefinition), "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"); // using (StringReader stringreader = new StringReader(data)) // root.ToString())) // { // report = (ReportDefinition)xs.Deserialize(stringreader); // } // return report; // } // // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] // private static String SerialiseReport(ReportDefinition report) // { // var stream = SerialiseReportToStream(report); // return Encoding.UTF8.GetString(stream.ToArray()); // // } // // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] // private static MemoryStream SerialiseReportToStream(ReportDefinition report) // { // // string nameSpace = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"; // // if (report.RDLType == RDLType.RDL2010) // nameSpace = "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"; // // XmlSerializerNamespaces serialize = new XmlSerializerNamespaces(); // serialize.Add("rd", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"); // XmlSerializer xs2 = new XmlSerializer(typeof(Syncfusion.RDL.DOM.ReportDefinition), nameSpace); // MemoryStream memoryStream = new MemoryStream(); // TextWriter ws2 = new StreamWriter(memoryStream); // xs2.Serialize(ws2, report, serialize); // memoryStream.Position = 0; // return memoryStream; // //return Encoding.UTF8.GetString(memoryStream.ToArray()); // // } // private static byte[] GhostScriptIt(byte[] pdf) // { // String input = Path.GetTempFileName(); // File.WriteAllBytes(input, pdf); // byte[] result = new byte[] { }; // GhostscriptVersionInfo gv = new GhostscriptVersionInfo( // new Version(0, 0, 0), // "gsdll32.dll", // "", // GhostscriptLicense.GPL // ); // GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput(); // // pipe handle format: %handle%hexvalue // string outputPipeHandle = "%handle%" + int.Parse(gsPipedOutput.ClientHandle).ToString("X2"); // using (GhostscriptProcessor processor = new GhostscriptProcessor(gv, true)) // { // List switches = new List(); // switches.Add("-empty"); // switches.Add("-dQUIET"); // switches.Add("-dSAFER"); // switches.Add("-dBATCH"); // switches.Add("-dNOPAUSE"); // switches.Add("-dNOPROMPT"); // switches.Add("-dCompatibilityLevel=1.4"); // switches.Add("-sDEVICE=pdfwrite"); // switches.Add("-o" + outputPipeHandle); // switches.Add("-q"); // switches.Add("-f"); // switches.Add(input); // try // { // processor.StartProcessing(switches.ToArray(), null); // result = gsPipedOutput.Data; // } // catch (Exception ex) // { // Console.WriteLine(ex.Message); // } // finally // { // gsPipedOutput.Dispose(); // gsPipedOutput = null; // } // } // File.Delete(input); // return result; // } #endregion } }