|
@@ -0,0 +1,297 @@
|
|
|
+using Hotline.Share.Dtos.ExportWord;
|
|
|
+using Hotline.Share.Enums.ExportWord;
|
|
|
+using Novacode;
|
|
|
+using System.Drawing;
|
|
|
+using XF.Domain.Exceptions;
|
|
|
+
|
|
|
+namespace Hotline.Application.ExportWord
|
|
|
+{
|
|
|
+ public class WordExportProvider : IWordExportProvider
|
|
|
+ {
|
|
|
+ public ExportByteWord ExportFromTemplate<T>(string templatePath, T data) where T : IWordExportTemplate
|
|
|
+ {
|
|
|
+ DocX docX = GetDocX(templatePath);
|
|
|
+ ReplacePlaceholders(docX, data);
|
|
|
+ using MemoryStream memoryStream = new();
|
|
|
+ docX.SaveAs(memoryStream);
|
|
|
+ return new ExportByteWord
|
|
|
+ {
|
|
|
+ WordBytes = memoryStream.ToArray()
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<ExportByteWord> ExportFromTemplateAsync<T>(string templatePath, T data) where T : IWordExportTemplate
|
|
|
+ {
|
|
|
+ return await Task.Run(() => ExportFromTemplate(templatePath, data));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholders<T>(DocX word, T wordData) where T : IWordExportTemplate
|
|
|
+ {
|
|
|
+ if (word == null)
|
|
|
+ {
|
|
|
+ throw new ArgumentNullException("word");
|
|
|
+ }
|
|
|
+
|
|
|
+ IEnumerable<PlaceholderEntity> replacements = wordData.GetReplacements();
|
|
|
+ if (replacements.Count() == 0)
|
|
|
+ {
|
|
|
+ throw UserFriendlyException.SameMessage("实体中没有可替换的属性");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ReplacePlaceholdersInWord(word, replacements);
|
|
|
+ if (word == null)
|
|
|
+ throw new ArgumentNullException("word");
|
|
|
+
|
|
|
+ if (replacements == null)
|
|
|
+ throw new ArgumentNullException("placeholderEntities");
|
|
|
+
|
|
|
+ foreach (PlaceholderEntity placeholderEntity in replacements)
|
|
|
+ {
|
|
|
+ switch (placeholderEntity.PlaceholderType)
|
|
|
+ {
|
|
|
+ case EPlaceholderType.Table:
|
|
|
+ ReplacePlaceholdersInTable(word, placeholderEntity.Placeholder, (ExportTable)placeholderEntity.Data);
|
|
|
+ break;
|
|
|
+ case EPlaceholderType.Text:
|
|
|
+ ReplacePlaceholdersInText(word, placeholderEntity.Placeholder, (ExportText)placeholderEntity.Data);
|
|
|
+ break;
|
|
|
+ case EPlaceholderType.Picture:
|
|
|
+ ReplacePlaceholdersInImage(word, placeholderEntity.Placeholder, placeholderEntity.Pictures);
|
|
|
+ break;
|
|
|
+ case EPlaceholderType.Paragraph:
|
|
|
+ ReplacePlaceholdersInParagraph(word, placeholderEntity.Placeholder, (ExportParagraph)placeholderEntity.Data);
|
|
|
+ break;
|
|
|
+ case EPlaceholderType.Complex:
|
|
|
+ ReplacePlaceholdersInComplex(word, placeholderEntity.Placeholder, (ExportComplex)placeholderEntity.Data);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private DocX GetDocX(string fileUrl)
|
|
|
+ {
|
|
|
+ if (!System.IO.File.Exists(fileUrl))
|
|
|
+ throw UserFriendlyException.SameMessage("找不到模板文件");
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ using FileStream stream = System.IO.File.OpenRead(fileUrl);
|
|
|
+ return DocX.Load(stream);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ throw UserFriendlyException.SameMessage("打开模板文件失败,异常原因:" + ex.Message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholdersInComplex(DocX word, string oldText, ExportComplex newComplex)
|
|
|
+ {
|
|
|
+ foreach (Paragraph paragraph2 in word.Paragraphs)
|
|
|
+ {
|
|
|
+ if (!paragraph2.Text.Contains(oldText))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (newComplex != null)
|
|
|
+ {
|
|
|
+ newComplex.Elements.Reverse();
|
|
|
+ foreach (IWordElement element in newComplex.Elements)
|
|
|
+ {
|
|
|
+ if (element.GetType() == typeof(ExportParagraph))
|
|
|
+ {
|
|
|
+ ExportParagraph fWParagraph = (ExportParagraph)element;
|
|
|
+ Paragraph paragraph = word.InsertParagraph();
|
|
|
+ paragraph.Append(fWParagraph.Run.Text);
|
|
|
+ if (fWParagraph.Run.IsBold)
|
|
|
+ {
|
|
|
+ paragraph.Bold();
|
|
|
+ }
|
|
|
+
|
|
|
+ paragraph.FontSize(fWParagraph.Run.FontSize);
|
|
|
+ paragraph.Font(fWParagraph.Run.FontFamily);
|
|
|
+ paragraph.Color(fWParagraph.Run.Color);
|
|
|
+ paragraph.Alignment = fWParagraph.Alignment;
|
|
|
+ paragraph2.InsertParagraphAfterSelf(paragraph);
|
|
|
+ paragraph.Remove(trackChanges: false);
|
|
|
+ }
|
|
|
+ else if (element.GetType() == typeof(ExportTable))
|
|
|
+ {
|
|
|
+ ExportTable fWTable = (ExportTable)element;
|
|
|
+ Table t = FWTableToTable(word, fWTable);
|
|
|
+ paragraph2.InsertTableAfterSelf(t);
|
|
|
+ }
|
|
|
+ else if (element.GetType() == typeof(ExportPicture))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ ExportPicture fWPicture = (ExportPicture)element;
|
|
|
+ Stream stream = ((fWPicture.PictureData != null) ? fWPicture.PictureData : System.IO.File.OpenRead(fWPicture.PictureUrl));
|
|
|
+ Novacode.Image image = word.AddImage(stream);
|
|
|
+ paragraph2.AppendPicture(image.CreatePicture(fWPicture.Height, fWPicture.Width));
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ paragraph2.ReplaceText(oldText, "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholdersInParagraph(DocX word, string oldText, ExportParagraph newParagraph)
|
|
|
+ {
|
|
|
+ foreach (Paragraph paragraph2 in word.Paragraphs)
|
|
|
+ {
|
|
|
+ if (paragraph2.Text.Contains(oldText))
|
|
|
+ {
|
|
|
+ Paragraph paragraph = word.InsertParagraph();
|
|
|
+ paragraph.Append(newParagraph.Run.Text);
|
|
|
+ if (newParagraph.Run.IsBold)
|
|
|
+ paragraph.Bold();
|
|
|
+
|
|
|
+ paragraph.FontSize(newParagraph.Run.FontSize);
|
|
|
+ paragraph.Font(newParagraph.Run.FontFamily);
|
|
|
+ paragraph.Color(newParagraph.Run.Color);
|
|
|
+ paragraph.Alignment = newParagraph.Alignment;
|
|
|
+ paragraph2.InsertParagraphAfterSelf(paragraph);
|
|
|
+ paragraph2.Remove(trackChanges: false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholdersInText(DocX word, string oldText, ExportText newText)
|
|
|
+ {
|
|
|
+ foreach (Paragraph paragraph in word.Paragraphs)
|
|
|
+ {
|
|
|
+ if (paragraph.Text.Contains(oldText))
|
|
|
+ paragraph.ReplaceText(oldText, newText.Data);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholdersInTable(DocX word, string oldText, ExportTable newTable)
|
|
|
+ {
|
|
|
+ foreach (Paragraph paragraph in word.Paragraphs)
|
|
|
+ {
|
|
|
+ if (paragraph.Text.Contains(oldText))
|
|
|
+ {
|
|
|
+ if (newTable != null)
|
|
|
+ {
|
|
|
+ Table t = FWTableToTable(word, newTable);
|
|
|
+ paragraph.InsertTableAfterSelf(t);
|
|
|
+ paragraph.Remove(trackChanges: false);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ paragraph.ReplaceText(oldText, "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ReplacePlaceholdersInImage(DocX word, string oldText, IEnumerable<ExportPicture> newPic)
|
|
|
+ {
|
|
|
+ IEnumerable<ExportPicture> enumerable;
|
|
|
+ if (newPic != null)
|
|
|
+ enumerable = newPic;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ IEnumerable<ExportPicture> enumerable2 = new List<ExportPicture>();
|
|
|
+ enumerable = enumerable2;
|
|
|
+ }
|
|
|
+
|
|
|
+ newPic = enumerable;
|
|
|
+ foreach (Paragraph paragraph2 in word.Paragraphs)
|
|
|
+ {
|
|
|
+ Paragraph paragraph = paragraph2;
|
|
|
+ if (!paragraph.Text.Contains(oldText))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (newPic.Count() > 0)
|
|
|
+ {
|
|
|
+ newPic.ToList().ForEach(delegate (ExportPicture pic)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ paragraph.AppendPicture(word.AddImage(pic.PictureData ?? System.IO.File.OpenRead(pic.PictureUrl)).CreatePicture(pic.Height, pic.Width));
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ paragraph.ReplaceText(oldText, "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Table FWTableToTable(DocX word, ExportTable FWTable)
|
|
|
+ {
|
|
|
+ Table table = word.AddTable(FWTable.RowCount, FWTable.ColumnCount);
|
|
|
+ table.Alignment = Alignment.center;
|
|
|
+ table.SetBorder(TableBorderType.InsideH, new Border());
|
|
|
+ table.SetBorder(TableBorderType.Top, new Border());
|
|
|
+ table.SetBorder(TableBorderType.Bottom, new Border());
|
|
|
+ table.SetBorder(TableBorderType.Left, new Border());
|
|
|
+ table.SetBorder(TableBorderType.Right, new Border());
|
|
|
+ table.SetBorder(TableBorderType.InsideV, new Border());
|
|
|
+ for (int i = 0; i < FWTable.Rows.Count; i++)
|
|
|
+ {
|
|
|
+ if (FWTable.Rows[i].Height > 0.0)
|
|
|
+ table.Rows[i].Height = FWTable.Rows[i].Height;
|
|
|
+
|
|
|
+ for (int j = 0; j < FWTable.Rows[i].Cells.Count; j++)
|
|
|
+ {
|
|
|
+ ExportTableCell fWTableCell = FWTable.Rows[i].Cells[j];
|
|
|
+ if (table.Rows[i].Cells[j].Width > 0.0)
|
|
|
+ table.Rows[i].Cells[j].Width = fWTableCell.Width;
|
|
|
+
|
|
|
+ if (fWTableCell.FillColor != Color.Empty)
|
|
|
+ table.Rows[i].Cells[j].FillColor = fWTableCell.FillColor;
|
|
|
+
|
|
|
+ table.Rows[i].Cells[j].VerticalAlignment = fWTableCell.VerticalAlignment;
|
|
|
+ table.Rows[i].Cells[j].RemoveParagraphAt(0);
|
|
|
+ foreach (ExportParagraph paragraph in fWTableCell.Paragraphs)
|
|
|
+ {
|
|
|
+ Paragraph p = table.Rows[i].Cells[j].InsertParagraph();
|
|
|
+ if (!string.IsNullOrEmpty(paragraph.Run.Text))
|
|
|
+ p.Append(paragraph.Run.Text);
|
|
|
+
|
|
|
+ if (paragraph.Run.IsBold)
|
|
|
+ p.Bold();
|
|
|
+
|
|
|
+ p.FontSize(paragraph.Run.FontSize);
|
|
|
+ p.Font(paragraph.Run.FontFamily);
|
|
|
+ p.Color(paragraph.Run.Color);
|
|
|
+ p.Alignment = paragraph.Alignment;
|
|
|
+ if (paragraph.Run.Pictures.Count > 0)
|
|
|
+ {
|
|
|
+ paragraph.Run.Pictures.ForEach(delegate (ExportPicture t)
|
|
|
+ {
|
|
|
+ p.AppendPicture(word.AddImage(t.PictureData ?? System.IO.File.OpenRead(t.PictureUrl)).CreatePicture(t.Height, t.Width));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var mergeCellsInColumn in FWTable.MergeCellsInColumns)
|
|
|
+ {
|
|
|
+ table.MergeCellsInColumn(mergeCellsInColumn.Item1, mergeCellsInColumn.Item2, mergeCellsInColumn.Item3);
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var mergeCellsInRow in FWTable.MergeCellsInRows)
|
|
|
+ {
|
|
|
+ table.Rows[mergeCellsInRow.Item1].MergeCells(mergeCellsInRow.Item2, mergeCellsInRow.Item3);
|
|
|
+ if (!(table.Rows[mergeCellsInRow.Item1].Cells[mergeCellsInRow.Item2].Paragraphs[0].Text == "备注"))
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ while (table.Rows[mergeCellsInRow.Item1].Cells[mergeCellsInRow.Item2].Paragraphs.Count > 1)
|
|
|
+ {
|
|
|
+ table.Rows[mergeCellsInRow.Item1].Cells[mergeCellsInRow.Item2].RemoveParagraphAt(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return table;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|