JsonToWordHelper.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using Aspose.Words;
  2. using Aspose.Words.Tables;
  3. using System.Text.Json;
  4. using System.Text.Json.Serialization;
  5. public static class JsonToWordHelper
  6. {
  7. public static byte[] ConvertJsonToWord(string json)
  8. {
  9. if (string.IsNullOrWhiteSpace(json))
  10. throw new ArgumentException("JSON不能为空", nameof(json));
  11. var model = System.Text.Json.JsonSerializer.Deserialize<TripDocumentModel>(json, new JsonSerializerOptions
  12. {
  13. PropertyNameCaseInsensitive = true
  14. });
  15. if (model == null)
  16. throw new InvalidOperationException("JSON反序列化失败");
  17. model.Sections ??= new List<TripSection>();
  18. model.Closing ??= new List<string>();
  19. var doc = new Document();
  20. var builder = new DocumentBuilder(doc);
  21. SetDefaultFont(builder);
  22. // 标题
  23. builder.ParagraphFormat.ClearFormatting();
  24. builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  25. builder.Font.Bold = true;
  26. builder.Font.Size = 16;
  27. builder.Writeln(model.Title ?? string.Empty);
  28. builder.InsertParagraph();
  29. // 收文单位
  30. builder.ParagraphFormat.ClearFormatting();
  31. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  32. builder.Font.Bold = false;
  33. builder.Font.Size = 12;
  34. builder.Writeln($"{model.Receiver}:");
  35. // 引言
  36. WriteNormalParagraph(builder, model.Intro);
  37. // 正文 sections
  38. foreach (var section in model.Sections)
  39. {
  40. if (!string.IsNullOrWhiteSpace(section.Title))
  41. {
  42. builder.ParagraphFormat.ClearFormatting();
  43. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  44. builder.Font.Bold = true;
  45. builder.Font.Size = 12;
  46. builder.Writeln(section.Title);
  47. }
  48. if (string.Equals(section.Type, "table", StringComparison.OrdinalIgnoreCase))
  49. {
  50. WriteTable(builder, section.Table);
  51. builder.InsertParagraph();
  52. continue;
  53. }
  54. if (section.Items != null && section.Items.Count > 0)
  55. {
  56. for (int i = 0; i < section.Items.Count; i++)
  57. {
  58. var item = section.Items[i];
  59. WriteNormalParagraph(builder, $"{i + 1}. {item.Title}");
  60. if (item.Content != null)
  61. {
  62. foreach (var line in item.Content)
  63. {
  64. WriteNormalParagraph(builder, line);
  65. }
  66. }
  67. }
  68. }
  69. else if (section.Content != null && section.Content.Count > 0)
  70. {
  71. foreach (var line in section.Content)
  72. {
  73. WriteNormalParagraph(builder, line);
  74. }
  75. }
  76. builder.InsertParagraph();
  77. }
  78. // 结尾
  79. foreach (var line in model.Closing)
  80. {
  81. WriteNormalParagraph(builder, line);
  82. }
  83. builder.InsertParagraph();
  84. // 落款
  85. builder.ParagraphFormat.ClearFormatting();
  86. builder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
  87. builder.Font.Bold = false;
  88. builder.Font.Size = 12;
  89. builder.Writeln(model.Signature ?? string.Empty);
  90. builder.Writeln(model.Date ?? string.Empty);
  91. using var ms = new MemoryStream();
  92. doc.Save(ms, SaveFormat.Docx);
  93. return ms.ToArray();
  94. }
  95. private static void WriteNormalParagraph(DocumentBuilder builder, string? text)
  96. {
  97. if (string.IsNullOrWhiteSpace(text))
  98. return;
  99. builder.ParagraphFormat.ClearFormatting();
  100. builder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
  101. builder.ParagraphFormat.FirstLineIndent = 24; // 首行缩进,约2字符
  102. builder.ParagraphFormat.SpaceAfter = 6;
  103. builder.Font.Bold = false;
  104. builder.Font.Size = 12;
  105. builder.Writeln(text.Trim());
  106. }
  107. private static void WriteTable(DocumentBuilder builder, TripTable? table)
  108. {
  109. if (table?.Headers == null || table.Headers.Count == 0)
  110. return;
  111. var colCount = table.Headers.Count;
  112. builder.StartTable();
  113. // 表头
  114. foreach (var header in table.Headers)
  115. {
  116. builder.InsertCell();
  117. builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
  118. builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  119. builder.Font.Bold = true;
  120. builder.Write(header ?? string.Empty);
  121. }
  122. builder.EndRow();
  123. // 数据
  124. if (table.Rows != null)
  125. {
  126. foreach (var row in table.Rows)
  127. {
  128. var safeRow = row ?? new List<string>();
  129. for (int i = 0; i < colCount; i++)
  130. {
  131. builder.InsertCell();
  132. builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;
  133. builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;
  134. builder.Font.Bold = false;
  135. var cellText = i < safeRow.Count ? safeRow[i] ?? string.Empty : string.Empty;
  136. builder.Write(cellText);
  137. }
  138. builder.EndRow();
  139. }
  140. }
  141. var wordTable = builder.EndTable();
  142. // 表格样式
  143. wordTable.AutoFit(AutoFitBehavior.AutoFitToWindow);
  144. foreach (Row row in wordTable.Rows)
  145. {
  146. foreach (Cell cell in row.Cells)
  147. {
  148. cell.CellFormat.LeftPadding = 5;
  149. cell.CellFormat.RightPadding = 5;
  150. cell.CellFormat.TopPadding = 3;
  151. cell.CellFormat.BottomPadding = 3;
  152. }
  153. }
  154. }
  155. private static void SetDefaultFont(DocumentBuilder builder)
  156. {
  157. builder.Font.Name = "宋体";
  158. builder.Font.Size = 12;
  159. }
  160. }
  161. public class TripDocumentModel
  162. {
  163. [JsonPropertyName("title")]
  164. public string? Title { get; set; }
  165. [JsonPropertyName("receiver")]
  166. public string? Receiver { get; set; }
  167. [JsonPropertyName("intro")]
  168. public string? Intro { get; set; }
  169. [JsonPropertyName("sections")]
  170. public List<TripSection>? Sections { get; set; }
  171. [JsonPropertyName("closing")]
  172. public List<string>? Closing { get; set; }
  173. [JsonPropertyName("signature")]
  174. public string? Signature { get; set; }
  175. [JsonPropertyName("date")]
  176. public string? Date { get; set; }
  177. }
  178. public class TripSection
  179. {
  180. [JsonPropertyName("type")]
  181. public string? Type { get; set; }
  182. [JsonPropertyName("title")]
  183. public string? Title { get; set; }
  184. [JsonPropertyName("items")]
  185. public List<TripItem>? Items { get; set; }
  186. [JsonPropertyName("content")]
  187. public List<string>? Content { get; set; }
  188. [JsonPropertyName("table")]
  189. public TripTable? Table { get; set; }
  190. }
  191. public class TripItem
  192. {
  193. [JsonPropertyName("title")]
  194. public string? Title { get; set; }
  195. [JsonPropertyName("content")]
  196. public List<string>? Content { get; set; }
  197. }
  198. public class TripTable
  199. {
  200. [JsonPropertyName("headers")]
  201. public List<string>? Headers { get; set; }
  202. [JsonPropertyName("rows")]
  203. public List<List<string>>? Rows { get; set; }
  204. }