using System; #if __MACOS__ using Syncfusion.Drawing; #else using System.Drawing; #endif using System.Linq; using Syncfusion.DocIO.DLS; using Vinno.IUS.Common.Log; using Vinno.vCloud.Report.Interfaces; using Vinno.vCloud.Report.Models; using PageNumberStyle = Syncfusion.DocIO.DLS.PageNumberStyle; namespace Vinno.vCloud.ReportGenerator { public class ReportWordDocument : WordDocument, IReportWordDocument { } public class ReportWordDocumentManager { private static bool _showImageIndex; private static float _widthZoomRatio; /// /// gets word document from report info /// /// /// public static IReportWordDocument GetGenerateWordDocument(ReportInfo reportInfo) { _widthZoomRatio = 1; var wordDocument = new ReportWordDocument(); try { if (reportInfo == null) { return null; } _showImageIndex = reportInfo.ElementValues != null && reportInfo.ElementValues.ContainsKey(ElementTag.AIIndexFlag); reportInfo = reportInfo.Clone();//bcs may del table row or change HeaderDistance/HeaderHeight var reportTemplate = reportInfo.Template; var headerVisible = reportTemplate.Header.Any(x => x.IsVisibleIn(reportInfo)); if (!headerVisible) reportInfo.Template.HeaderDistance = 0; var footerVisible = reportTemplate.Footer.Any(x => x.IsVisibleIn(reportInfo)); if (!footerVisible) reportInfo.Template.FooterDistance = 0; if (reportTemplate.InvertColor) { wordDocument.Background.Type = BackgroundType.Color; wordDocument.Background.Color = Color.Black; } wordDocument.FontSettings.SubstituteFont += OnSubstituteFont; var section = wordDocument.AddSection(); SetPageSetting(reportTemplate.PageSize, reportTemplate.PagePadding, section); if (reportTemplate.Header.Count > 0) { if (reportTemplate.HeaderHeight == null) { foreach (var blockElement in reportTemplate.Header) { AddBlock(reportInfo, blockElement, section.HeadersFooters.Header, wordDocument); } } else { var table = section.HeadersFooters.Header.AddTable(); InitTable(table); var cell = table.Rows[0].Cells[0]; foreach (var blockElement in reportTemplate.Header) { AddBlock(reportInfo, blockElement, cell, wordDocument); } //bcs may del table row in AddBlock table.Rows[0].Height = (float)reportTemplate.HeaderHeight - 5; } } foreach (var blockElement in reportTemplate.Blocks) { AddBlock(reportInfo, blockElement, section.Body, wordDocument); } if (reportTemplate.Footer.Count > 0) { if (reportTemplate.FooterHeight == null) { foreach (var blockElement in reportTemplate.Footer) { AddBlock(reportInfo, blockElement, section.HeadersFooters.Footer, wordDocument); } } else { var table = section.HeadersFooters.Footer.AddTable(); InitTable(table); table.Rows[0].Height = (float)reportTemplate.FooterHeight - 5; var cell = table.Rows[0].Cells[0]; foreach (var blockElement in reportTemplate.Footer) { AddBlock(reportInfo, blockElement, cell, wordDocument); } } } var pageNumberElement = reportTemplate.Footer.SelectMany(f => f.Elements) .FirstOrDefault(e => e is PageNumberElement) as PageNumberElement; if (pageNumberElement != null) { section.PageSetup.RestartPageNumbering = true; section.PageSetup.PageStartingNumber = 1; section.PageSetup.PageNumberStyle = PageNumberStyle.Arabic; } foreach (WSection wSection in wordDocument.Sections) { wSection.PageSetup.HeaderDistance = (float)reportInfo.Template.HeaderDistance; if (!headerVisible) { wSection.HeadersFooters.Header.ChildEntities.Clear(); } wSection.PageSetup.FooterDistance = (float)reportInfo.Template.FooterDistance; if (!footerVisible) { wSection.HeadersFooters.Footer.ChildEntities.Clear(); } var endParagraph = wSection.AddParagraph();//hide blank page/paragraph after last table endParagraph.BreakCharacterFormat.FontSize = 0; } } catch (Exception e) { Logger.WriteLineError($"Generate word document error {e}"); } return wordDocument; } public static IReportWordDocument GetGenerateWordDocumentAdaptPageSetting(ReportInfo reportInfo, RTPageSize pageSize, RTThickness pagePadding) { var wordDocument = new ReportWordDocument(); try { if (reportInfo == null) { return null; } _showImageIndex = reportInfo.ElementValues != null && reportInfo.ElementValues.ContainsKey(ElementTag.AIIndexFlag); reportInfo = reportInfo.Clone();//bcs may del table row or change HeaderDistance/HeaderHeight var reportTemplate = reportInfo.Template; _widthZoomRatio = (float)Math.Round((pageSize.Width-pagePadding.Left-pagePadding.Right) / (reportTemplate.PageSize.Width-reportTemplate.PagePadding.Left-reportTemplate.PagePadding.Right), 3); var headerVisible = reportTemplate.Header.Any(x => x.IsVisibleIn(reportInfo)); if (!headerVisible) reportInfo.Template.HeaderDistance = 0; var footerVisible = reportTemplate.Footer.Any(x => x.IsVisibleIn(reportInfo)); if (!footerVisible) reportInfo.Template.FooterDistance = 0; if (reportTemplate.InvertColor) { wordDocument.Background.Type = BackgroundType.Color; wordDocument.Background.Color = Color.Black; } wordDocument.FontSettings.SubstituteFont += OnSubstituteFont; var section = wordDocument.AddSection(); SetPageSetting(pageSize, pagePadding, section); if (reportTemplate.Header.Count > 0) { if (reportTemplate.HeaderHeight == null) { foreach (var blockElement in reportTemplate.Header) { AddBlock(reportInfo, blockElement, section.HeadersFooters.Header, wordDocument); } } else { var table = section.HeadersFooters.Header.AddTable(); InitTable(table); var cell = table.Rows[0].Cells[0]; foreach (var blockElement in reportTemplate.Header) { AddBlock(reportInfo, blockElement, cell, wordDocument); } //bcs may del table row in AddBlock table.Rows[0].Height = (float)reportTemplate.HeaderHeight - 5; } } foreach (var blockElement in reportTemplate.Blocks) { AddBlock(reportInfo, blockElement, section.Body, wordDocument); } if (reportTemplate.Footer.Count > 0) { if (reportTemplate.FooterHeight == null) { foreach (var blockElement in reportTemplate.Footer) { AddBlock(reportInfo, blockElement, section.HeadersFooters.Footer, wordDocument); } } else { var table = section.HeadersFooters.Footer.AddTable(); InitTable(table); table.Rows[0].Height = (float)reportTemplate.FooterHeight - 5; var cell = table.Rows[0].Cells[0]; foreach (var blockElement in reportTemplate.Footer) { AddBlock(reportInfo, blockElement, cell, wordDocument); } } } var pageNumberElement = reportTemplate.Footer.SelectMany(f => f.Elements) .FirstOrDefault(e => e is PageNumberElement) as PageNumberElement; if (pageNumberElement != null) { section.PageSetup.RestartPageNumbering = true; section.PageSetup.PageStartingNumber = 1; section.PageSetup.PageNumberStyle = PageNumberStyle.Arabic; } foreach (WSection wSection in wordDocument.Sections) { wSection.PageSetup.HeaderDistance = (float)reportInfo.Template.HeaderDistance; if (!headerVisible) { wSection.HeadersFooters.Header.ChildEntities.Clear(); } wSection.PageSetup.FooterDistance = (float)reportInfo.Template.FooterDistance; if (!footerVisible) { wSection.HeadersFooters.Footer.ChildEntities.Clear(); } var endParagraph = wSection.AddParagraph();//hide blank page/paragraph after last table endParagraph.BreakCharacterFormat.FontSize = 0; } } catch (Exception e) { Logger.WriteLineError($"Generate word document error {e}"); } return wordDocument; } private static void OnSubstituteFont(object sender, SubstituteFontEventArgs args) { args.AlternateFontName = "Microsoft YaHei"; } private static void InitTable(IWTable table) { table.ResetCells(1, 1); table.Rows[0].HeightType = TableRowHeightType.Exactly; table.TableFormat.Borders.BorderType = BorderStyle.None; table.TableFormat.Paddings.All = 0;// workaround for syncfusion bug } /// /// Add Block /// public static void AddBlock(ReportInfo reportInfo, IBlockElement blockElement, WTextBody textBody, ReportWordDocument wordDocument) { if (blockElement is Paragraph paragraph) { ParagraphGenerater.Generate(reportInfo, paragraph, textBody); return; } if (blockElement is RTTable rtTable) { if (rtTable.IsVisibleIn(reportInfo)) { TableGenerater.Generate(reportInfo, rtTable, textBody, _widthZoomRatio, true); return; } if (reportInfo.Template.HeaderHeight != null && textBody.IsInHeader()) reportInfo.Template.HeaderHeight -= rtTable.RowDefinitions.Sum(x => x.Height); } if (blockElement is InputImageList inputImageList) { TableGenerater.GenerateInputImageList(reportInfo, inputImageList, textBody, _showImageIndex); } if (blockElement is AtlasElement atlasElement) { TableGenerater.GenerateAtlasElement(reportInfo, atlasElement, textBody, wordDocument); } } /// /// Set pagesetting /// private static void SetPageSetting(RTPageSize pageSize, RTThickness pagePadding, IWSection section) { // workaround fix for too large page size crash var width = (float)pageSize.Width; if (width > 3000) width = 3000; var height = (float)pageSize.Height; if (height > 3000) height = 3000; section.PageSetup.PageSize = new SizeF(width, height); section.PageSetup.Margins = new MarginsF((float)pagePadding.Left, (float)pagePadding.Top, (float)pagePadding.Right, (float)pagePadding.Bottom); } } }