@nguyenphp/antigravity-marketing 1.0.18 → 1.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +130 -78
  2. package/package.json +4 -3
  3. package/templates/.agent/skills/marketing-report-expert/SKILL.md +70 -0
  4. package/templates/.agent/skills/minimax-docx/LICENSE +21 -0
  5. package/templates/.agent/skills/minimax-docx/SKILL.md +274 -0
  6. package/templates/.agent/skills/minimax-docx/assets/styles/academic_styles.xml +250 -0
  7. package/templates/.agent/skills/minimax-docx/assets/styles/corporate_styles.xml +284 -0
  8. package/templates/.agent/skills/minimax-docx/assets/styles/default_styles.xml +449 -0
  9. package/templates/.agent/skills/minimax-docx/assets/xsd/aesthetic-rules.xsd +470 -0
  10. package/templates/.agent/skills/minimax-docx/assets/xsd/business-rules.xsd +130 -0
  11. package/templates/.agent/skills/minimax-docx/assets/xsd/common-types.xsd +159 -0
  12. package/templates/.agent/skills/minimax-docx/assets/xsd/wml-subset.xsd +589 -0
  13. package/templates/.agent/skills/minimax-docx/references/cjk_typography.md +357 -0
  14. package/templates/.agent/skills/minimax-docx/references/cjk_university_template_guide.md +184 -0
  15. package/templates/.agent/skills/minimax-docx/references/comments_guide.md +191 -0
  16. package/templates/.agent/skills/minimax-docx/references/design_good_bad_examples.md +829 -0
  17. package/templates/.agent/skills/minimax-docx/references/design_principles.md +819 -0
  18. package/templates/.agent/skills/minimax-docx/references/openxml_element_order.md +308 -0
  19. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part1.md +4061 -0
  20. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part2.md +2820 -0
  21. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part3.md +3381 -0
  22. package/templates/.agent/skills/minimax-docx/references/openxml_namespaces.md +82 -0
  23. package/templates/.agent/skills/minimax-docx/references/openxml_units.md +72 -0
  24. package/templates/.agent/skills/minimax-docx/references/scenario_a_create.md +284 -0
  25. package/templates/.agent/skills/minimax-docx/references/scenario_b_edit_content.md +295 -0
  26. package/templates/.agent/skills/minimax-docx/references/scenario_c_apply_template.md +456 -0
  27. package/templates/.agent/skills/minimax-docx/references/track_changes_guide.md +200 -0
  28. package/templates/.agent/skills/minimax-docx/references/troubleshooting.md +506 -0
  29. package/templates/.agent/skills/minimax-docx/references/typography_guide.md +294 -0
  30. package/templates/.agent/skills/minimax-docx/references/xsd_validation_guide.md +158 -0
  31. package/templates/.agent/skills/minimax-docx/scripts/doc_to_docx.sh +40 -0
  32. package/templates/.agent/skills/minimax-docx/scripts/docx_preview.sh +37 -0
  33. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj +19 -0
  34. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/Program.cs +18 -0
  35. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/AnalyzeCommand.cs +147 -0
  36. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ApplyTemplateCommand.cs +322 -0
  37. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/CreateCommand.cs +324 -0
  38. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/DiffCommand.cs +155 -0
  39. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/EditContentCommand.cs +487 -0
  40. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/FixOrderCommand.cs +108 -0
  41. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/MergeRunsCommand.cs +122 -0
  42. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ValidateCommand.cs +107 -0
  43. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/MiniMaxAIDocx.Core.csproj +15 -0
  44. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs +169 -0
  45. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/ElementOrder.cs +80 -0
  46. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/NamespaceConstants.cs +42 -0
  47. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/RunMerger.cs +81 -0
  48. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/StyleAnalyzer.cs +81 -0
  49. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/TrackChangesHelper.cs +99 -0
  50. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/UnitConverter.cs +23 -0
  51. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples.cs +1832 -0
  52. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch1.cs +910 -0
  53. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch2.cs +999 -0
  54. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch3.cs +1048 -0
  55. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch4.cs +1038 -0
  56. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/CharacterFormattingSamples.cs +1020 -0
  57. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/DocumentCreationSamples.cs +1121 -0
  58. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FieldAndTocSamples.cs +624 -0
  59. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FootnoteAndCommentSamples.cs +675 -0
  60. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/HeaderFooterSamples.cs +838 -0
  61. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ImageSamples.cs +917 -0
  62. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ListAndNumberingSamples.cs +826 -0
  63. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ParagraphFormattingSamples.cs +1199 -0
  64. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/StyleSystemSamples.cs +1487 -0
  65. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TableSamples.cs +1163 -0
  66. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TrackChangesSamples.cs +595 -0
  67. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/CjkHelper.cs +39 -0
  68. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/FontDefaults.cs +24 -0
  69. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/PageSizes.cs +20 -0
  70. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/BusinessRuleValidator.cs +224 -0
  71. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/GateCheckValidator.cs +148 -0
  72. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/ValidationResult.cs +23 -0
  73. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/XsdValidator.cs +69 -0
  74. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.slnx +4 -0
  75. package/templates/.agent/skills/minimax-docx/scripts/env_check.sh +196 -0
  76. package/templates/.agent/skills/minimax-docx/scripts/setup.ps1 +274 -0
  77. package/templates/.agent/skills/minimax-docx/scripts/setup.sh +504 -0
  78. package/templates/.agent/skills/minimax-multimodal-toolkit/SKILL.md +359 -0
  79. package/templates/.agent/skills/minimax-pdf/README.md +222 -0
  80. package/templates/.agent/skills/minimax-pdf/SKILL.md +201 -0
  81. package/templates/.agent/skills/minimax-pdf/design/design.md +381 -0
  82. package/templates/.agent/skills/minimax-pdf/scripts/cover.py +1579 -0
  83. package/templates/.agent/skills/minimax-pdf/scripts/fill_inspect.py +200 -0
  84. package/templates/.agent/skills/minimax-pdf/scripts/fill_write.py +242 -0
  85. package/templates/.agent/skills/minimax-pdf/scripts/make.sh +491 -0
  86. package/templates/.agent/skills/minimax-pdf/scripts/merge.py +112 -0
  87. package/templates/.agent/skills/minimax-pdf/scripts/palette.py +559 -0
  88. package/templates/.agent/skills/minimax-pdf/scripts/reformat_parse.py +374 -0
  89. package/templates/.agent/skills/minimax-pdf/scripts/render_body.py +1055 -0
  90. package/templates/.agent/skills/minimax-pdf/scripts/render_cover.cjs +111 -0
  91. package/templates/.agent/skills/minimax-xlsx/SKILL.md +138 -0
  92. package/templates/.agent/skills/minimax-xlsx/references/create.md +691 -0
  93. package/templates/.agent/skills/minimax-xlsx/references/edit.md +684 -0
  94. package/templates/.agent/skills/minimax-xlsx/references/fix.md +37 -0
  95. package/templates/.agent/skills/minimax-xlsx/references/format.md +768 -0
  96. package/templates/.agent/skills/minimax-xlsx/references/ooxml-cheatsheet.md +231 -0
  97. package/templates/.agent/skills/minimax-xlsx/references/read-analyze.md +97 -0
  98. package/templates/.agent/skills/minimax-xlsx/references/validate.md +772 -0
  99. package/templates/.agent/skills/minimax-xlsx/scripts/formula_check.py +422 -0
  100. package/templates/.agent/skills/minimax-xlsx/scripts/libreoffice_recalc.py +248 -0
  101. package/templates/.agent/skills/minimax-xlsx/scripts/shared_strings_builder.py +163 -0
  102. package/templates/.agent/skills/minimax-xlsx/scripts/style_audit.py +575 -0
  103. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_add_column.py +395 -0
  104. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_insert_row.py +274 -0
  105. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_pack.py +87 -0
  106. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_reader.py +362 -0
  107. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_shift_rows.py +396 -0
  108. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_unpack.py +130 -0
  109. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/[Content_Types].xml +9 -0
  110. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/_rels/.rels +6 -0
  111. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +19 -0
  112. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +33 -0
  113. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/styles.xml +160 -0
  114. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/workbook.xml +30 -0
  115. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +70 -0
  116. package/templates/.agent/skills/pptx-generator/SKILL.md +249 -0
  117. package/templates/.agent/skills/pptx-generator/references/design-system.md +392 -0
  118. package/templates/.agent/skills/pptx-generator/references/editing.md +162 -0
  119. package/templates/.agent/skills/pptx-generator/references/pitfalls.md +112 -0
  120. package/templates/.agent/skills/pptx-generator/references/pptxgenjs.md +420 -0
  121. package/templates/.agent/skills/pptx-generator/references/slide-types.md +413 -0
  122. package/templates/.agent/skills/tutorial-video-expert/SKILL.md +88 -0
  123. package/templates/.agent/skills/ui-ux-pro-max/SKILL.md +170 -585
  124. package/templates/.agent/skills/vision-analysis/SKILL.md +174 -0
  125. package/templates/.agent/workflows/analyze.md +3 -0
  126. package/templates/.agent/workflows/brand-report.md +44 -0
  127. package/templates/.agent/workflows/report.md +49 -0
  128. package/templates/.agent/agents/backend-specialist.md +0 -263
  129. package/templates/.agent/agents/database-architect.md +0 -226
  130. package/templates/.agent/agents/debugger.md +0 -225
  131. package/templates/.agent/agents/devops-engineer.md +0 -242
  132. package/templates/.agent/agents/frontend-specialist.md +0 -527
  133. package/templates/.agent/agents/game-developer.md +0 -162
  134. package/templates/.agent/agents/mobile-developer.md +0 -377
  135. package/templates/.agent/agents/penetration-tester.md +0 -188
  136. package/templates/.agent/agents/security-auditor.md +0 -170
  137. package/templates/.agent/agents/test-engineer.md +0 -158
  138. package/templates/.agent/skills/api-patterns/SKILL.md +0 -81
  139. package/templates/.agent/skills/api-patterns/api-style.md +0 -42
  140. package/templates/.agent/skills/api-patterns/auth.md +0 -24
  141. package/templates/.agent/skills/api-patterns/documentation.md +0 -26
  142. package/templates/.agent/skills/api-patterns/graphql.md +0 -41
  143. package/templates/.agent/skills/api-patterns/rate-limiting.md +0 -31
  144. package/templates/.agent/skills/api-patterns/response.md +0 -37
  145. package/templates/.agent/skills/api-patterns/rest.md +0 -40
  146. package/templates/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
  147. package/templates/.agent/skills/api-patterns/security-testing.md +0 -122
  148. package/templates/.agent/skills/api-patterns/trpc.md +0 -41
  149. package/templates/.agent/skills/api-patterns/versioning.md +0 -22
  150. package/templates/.agent/skills/app-builder/SKILL.md +0 -75
  151. package/templates/.agent/skills/app-builder/agent-coordination.md +0 -71
  152. package/templates/.agent/skills/app-builder/feature-building.md +0 -53
  153. package/templates/.agent/skills/app-builder/project-detection.md +0 -34
  154. package/templates/.agent/skills/app-builder/scaffolding.md +0 -118
  155. package/templates/.agent/skills/app-builder/tech-stack.md +0 -40
  156. package/templates/.agent/skills/app-builder/templates/SKILL.md +0 -39
  157. package/templates/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
  158. package/templates/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
  159. package/templates/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
  160. package/templates/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
  161. package/templates/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
  162. package/templates/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
  163. package/templates/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
  164. package/templates/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -82
  165. package/templates/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -100
  166. package/templates/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -106
  167. package/templates/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -101
  168. package/templates/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
  169. package/templates/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -93
  170. package/templates/.agent/skills/architecture/SKILL.md +0 -55
  171. package/templates/.agent/skills/architecture/context-discovery.md +0 -43
  172. package/templates/.agent/skills/architecture/examples.md +0 -94
  173. package/templates/.agent/skills/architecture/pattern-selection.md +0 -68
  174. package/templates/.agent/skills/architecture/patterns-reference.md +0 -50
  175. package/templates/.agent/skills/architecture/trade-off-analysis.md +0 -77
  176. package/templates/.agent/skills/bash-linux/SKILL.md +0 -199
  177. package/templates/.agent/skills/behavioral-modes/SKILL.md +0 -242
  178. package/templates/.agent/skills/clean-code/SKILL.md +0 -201
  179. package/templates/.agent/skills/code-review-checklist/SKILL.md +0 -109
  180. package/templates/.agent/skills/database-design/SKILL.md +0 -52
  181. package/templates/.agent/skills/database-design/database-selection.md +0 -43
  182. package/templates/.agent/skills/database-design/indexing.md +0 -39
  183. package/templates/.agent/skills/database-design/migrations.md +0 -48
  184. package/templates/.agent/skills/database-design/optimization.md +0 -36
  185. package/templates/.agent/skills/database-design/orm-selection.md +0 -30
  186. package/templates/.agent/skills/database-design/schema-design.md +0 -56
  187. package/templates/.agent/skills/database-design/scripts/schema_validator.py +0 -172
  188. package/templates/.agent/skills/deployment-procedures/SKILL.md +0 -241
  189. package/templates/.agent/skills/docker-expert/SKILL.md +0 -409
  190. package/templates/.agent/skills/game-development/2d-games/SKILL.md +0 -119
  191. package/templates/.agent/skills/game-development/3d-games/SKILL.md +0 -135
  192. package/templates/.agent/skills/game-development/SKILL.md +0 -167
  193. package/templates/.agent/skills/game-development/game-art/SKILL.md +0 -185
  194. package/templates/.agent/skills/game-development/game-audio/SKILL.md +0 -190
  195. package/templates/.agent/skills/game-development/game-design/SKILL.md +0 -129
  196. package/templates/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
  197. package/templates/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
  198. package/templates/.agent/skills/game-development/pc-games/SKILL.md +0 -144
  199. package/templates/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
  200. package/templates/.agent/skills/game-development/web-games/SKILL.md +0 -150
  201. package/templates/.agent/skills/lint-and-validate/SKILL.md +0 -45
  202. package/templates/.agent/skills/lint-and-validate/scripts/lint_runner.py +0 -172
  203. package/templates/.agent/skills/lint-and-validate/scripts/type_coverage.py +0 -173
  204. package/templates/.agent/skills/mcp-builder/SKILL.md +0 -176
  205. package/templates/.agent/skills/nestjs-expert/SKILL.md +0 -552
  206. package/templates/.agent/skills/nextjs-best-practices/SKILL.md +0 -203
  207. package/templates/.agent/skills/nodejs-best-practices/SKILL.md +0 -333
  208. package/templates/.agent/skills/parallel-agents/SKILL.md +0 -175
  209. package/templates/.agent/skills/performance-profiling/SKILL.md +0 -143
  210. package/templates/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +0 -76
  211. package/templates/.agent/skills/powershell-windows/SKILL.md +0 -167
  212. package/templates/.agent/skills/prisma-expert/SKILL.md +0 -355
  213. package/templates/.agent/skills/python-patterns/SKILL.md +0 -441
  214. package/templates/.agent/skills/react-patterns/SKILL.md +0 -198
  215. package/templates/.agent/skills/red-team-tactics/SKILL.md +0 -199
  216. package/templates/.agent/skills/server-management/SKILL.md +0 -161
  217. package/templates/.agent/skills/systematic-debugging/SKILL.md +0 -109
  218. package/templates/.agent/skills/tdd-workflow/SKILL.md +0 -149
  219. package/templates/.agent/skills/testing-patterns/SKILL.md +0 -178
  220. package/templates/.agent/skills/testing-patterns/scripts/test_runner.py +0 -219
  221. package/templates/.agent/skills/typescript-expert/SKILL.md +0 -429
  222. package/templates/.agent/skills/vue-expert/SKILL.md +0 -374
  223. package/templates/.agent/skills/vulnerability-scanner/SKILL.md +0 -276
  224. package/templates/.agent/skills/vulnerability-scanner/checklists.md +0 -121
  225. package/templates/.agent/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
  226. package/templates/.agent/skills/webapp-testing/SKILL.md +0 -187
  227. package/templates/.agent/skills/webapp-testing/scripts/playwright_runner.py +0 -173
  228. package/templates/.agent/workflows/debug.md +0 -103
  229. package/templates/.agent/workflows/deploy.md +0 -176
  230. package/templates/.agent/workflows/enhance.md +0 -63
  231. package/templates/.agent/workflows/test.md +0 -144
@@ -0,0 +1,1121 @@
1
+ using DocumentFormat.OpenXml;
2
+ using DocumentFormat.OpenXml.CustomProperties;
3
+ using DocumentFormat.OpenXml.ExtendedProperties;
4
+ using DocumentFormat.OpenXml.Packaging;
5
+ using DocumentFormat.OpenXml.VariantTypes;
6
+ using DocumentFormat.OpenXml.Wordprocessing;
7
+ using MiniMaxAIDocx.Core.OpenXml;
8
+ using MiniMaxAIDocx.Core.Typography;
9
+ using WpPageSize = DocumentFormat.OpenXml.Wordprocessing.PageSize;
10
+
11
+ namespace MiniMaxAIDocx.Core.Samples;
12
+
13
+ /// <summary>
14
+ /// Compilable reference examples for DOCX document creation and setup.
15
+ /// Every method is self-contained and demonstrates a specific aspect of
16
+ /// document creation using the OpenXML SDK 3.x strongly-typed API.
17
+ /// </summary>
18
+ public static class DocumentCreationSamples
19
+ {
20
+ // ────────────────────────────────────────────────────────────────────
21
+ // 1. MINIMAL DOCUMENT
22
+ // ────────────────────────────────────────────────────────────────────
23
+
24
+ /// <summary>
25
+ /// Creates the absolute minimum valid DOCX file: a single empty paragraph
26
+ /// inside a body, with a final section properties element.
27
+ /// This is the smallest file Word/LibreOffice will open without error.
28
+ /// </summary>
29
+ /// <remarks>
30
+ /// Produces this XML in word/document.xml:
31
+ /// <code>
32
+ /// &lt;w:document&gt;
33
+ /// &lt;w:body&gt;
34
+ /// &lt;w:p/&gt;
35
+ /// &lt;w:sectPr&gt;
36
+ /// &lt;w:pgSz w:w="12240" w:h="15840"/&gt;
37
+ /// &lt;w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"
38
+ /// w:header="720" w:footer="720" w:gutter="0"/&gt;
39
+ /// &lt;/w:sectPr&gt;
40
+ /// &lt;/w:body&gt;
41
+ /// &lt;/w:document&gt;
42
+ /// </code>
43
+ /// </remarks>
44
+ public static void CreateMinimalDocument(string path)
45
+ {
46
+ // IMPORTANT: OpenXML SDK 3.x uses IDisposable — always wrap in using.
47
+ // Never call .Close() — it was removed in SDK 3.x.
48
+ using var doc = WordprocessingDocument.Create(path, WordprocessingDocumentType.Document);
49
+
50
+ // Every DOCX needs exactly one MainDocumentPart
51
+ var mainPart = doc.AddMainDocumentPart();
52
+
53
+ // The Document element is the root of word/document.xml
54
+ mainPart.Document = new Document(
55
+ new Body(
56
+ // At least one paragraph is required for a valid document
57
+ new Paragraph(),
58
+ // SectionProperties must be the LAST child of Body
59
+ // WARNING: If sectPr is not last, Word may silently move it or corrupt the file
60
+ new SectionProperties(
61
+ // PageSize: Letter = 8.5" x 11" = 12240 x 15840 DXA (1 inch = 1440 DXA)
62
+ new WpPageSize
63
+ {
64
+ Width = (UInt32Value)12240U,
65
+ Height = (UInt32Value)15840U
66
+ },
67
+ // PageMargin: 1 inch all sides = 1440 DXA each
68
+ // Header/footer distance: 0.5 inch = 720 DXA
69
+ new PageMargin
70
+ {
71
+ Top = 1440,
72
+ Right = (UInt32Value)1440U,
73
+ Bottom = 1440,
74
+ Left = (UInt32Value)1440U,
75
+ Header = (UInt32Value)720U,
76
+ Footer = (UInt32Value)720U,
77
+ Gutter = (UInt32Value)0U
78
+ }
79
+ )
80
+ )
81
+ );
82
+
83
+ // Save is called automatically by Dispose, but explicit save ensures
84
+ // all parts are flushed before the stream closes
85
+ mainPart.Document.Save();
86
+ }
87
+
88
+ // ────────────────────────────────────────────────────────────────────
89
+ // 2. FULL DOCUMENT (all parts)
90
+ // ────────────────────────────────────────────────────────────────────
91
+
92
+ /// <summary>
93
+ /// Creates a production-ready DOCX with all standard parts:
94
+ /// styles, settings, numbering definitions, font table, and theme.
95
+ /// This mirrors the structure Word generates for a "New Blank Document".
96
+ /// </summary>
97
+ public static void CreateFullDocument(string path)
98
+ {
99
+ using var doc = WordprocessingDocument.Create(path, WordprocessingDocumentType.Document);
100
+ var mainPart = doc.AddMainDocumentPart();
101
+
102
+ // ── StyleDefinitionsPart ──
103
+ // Contains all named styles (Normal, Heading1, etc.)
104
+ var stylesPart = mainPart.AddNewPart<StyleDefinitionsPart>();
105
+ stylesPart.Styles = new Styles();
106
+ // Populate styles using the StyleSystemSamples helper
107
+ StyleSystemSamples.SetupDocDefaults(stylesPart);
108
+ StyleSystemSamples.CreateBasicStyles(stylesPart);
109
+ stylesPart.Styles.Save();
110
+
111
+ // ── DocumentSettingsPart ──
112
+ // Contains zoom, compatibility, proofing state, etc.
113
+ var settingsPart = mainPart.AddNewPart<DocumentSettingsPart>();
114
+ settingsPart.Settings = new Settings();
115
+ AddDocumentSettings(mainPart);
116
+ settingsPart.Settings.Save();
117
+
118
+ // ── NumberingDefinitionsPart ──
119
+ // Required if any paragraph uses numbered/bulleted lists
120
+ var numberingPart = mainPart.AddNewPart<NumberingDefinitionsPart>();
121
+ numberingPart.Numbering = new Numbering();
122
+ // Add a basic bullet list abstract numbering definition
123
+ var abstractNum = new AbstractNum(
124
+ new Level(
125
+ new NumberingFormat { Val = NumberFormatValues.Bullet },
126
+ new LevelText { Val = "\u2022" }, // bullet character
127
+ new LevelJustification { Val = LevelJustificationValues.Left },
128
+ new ParagraphProperties(
129
+ new Indentation
130
+ {
131
+ Left = "720", // 0.5 inch = 720 DXA
132
+ Hanging = "360" // 0.25 inch hanging indent
133
+ }
134
+ )
135
+ )
136
+ { LevelIndex = 0 }
137
+ )
138
+ { AbstractNumberId = 1 };
139
+
140
+ // IMPORTANT: AbstractNum elements must come BEFORE NumberingInstance elements
141
+ // in the Numbering part, or Word will report corruption
142
+ numberingPart.Numbering.Append(abstractNum);
143
+ numberingPart.Numbering.Append(
144
+ new NumberingInstance(
145
+ new AbstractNumId { Val = 1 }
146
+ )
147
+ { NumberID = 1 }
148
+ );
149
+ numberingPart.Numbering.Save();
150
+
151
+ // ── FontTablePart ──
152
+ // Declares fonts used in the document; Word auto-populates on save,
153
+ // but pre-creating it avoids a repair prompt
154
+ var fontTablePart = mainPart.AddNewPart<FontTablePart>();
155
+ fontTablePart.Fonts = new Fonts(
156
+ new Font(
157
+ new Panose1Number { Val = "020B0604020202020204" },
158
+ new FontCharSet { Val = "00" },
159
+ new FontFamily { Val = FontFamilyValues.Swiss }
160
+ )
161
+ { Name = "Calibri" },
162
+ new Font(
163
+ new Panose1Number { Val = "020B0604020202020204" },
164
+ new FontCharSet { Val = "00" },
165
+ new FontFamily { Val = FontFamilyValues.Swiss }
166
+ )
167
+ { Name = "Calibri Light" }
168
+ );
169
+ fontTablePart.Fonts.Save();
170
+
171
+ // ── ThemePart ──
172
+ // Defines the document's theme colors and fonts.
173
+ // IMPORTANT: We use a minimal theme; for full Office themes, copy from a .docx template
174
+ var themePart = mainPart.AddNewPart<ThemePart>();
175
+ // Write minimal theme XML directly since the strongly-typed API for themes
176
+ // lives in DocumentFormat.OpenXml.Drawing and is very verbose
177
+ using (var writer = new System.IO.StreamWriter(themePart.GetStream()))
178
+ {
179
+ writer.Write("""
180
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
181
+ <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">
182
+ <a:themeElements>
183
+ <a:clrScheme name="Office">
184
+ <a:dk1><a:sysClr val="windowText" lastClr="000000"/></a:dk1>
185
+ <a:lt1><a:sysClr val="window" lastClr="FFFFFF"/></a:lt1>
186
+ <a:dk2><a:srgbClr val="44546A"/></a:dk2>
187
+ <a:lt2><a:srgbClr val="E7E6E6"/></a:lt2>
188
+ <a:accent1><a:srgbClr val="4472C4"/></a:accent1>
189
+ <a:accent2><a:srgbClr val="ED7D31"/></a:accent2>
190
+ <a:accent3><a:srgbClr val="A5A5A5"/></a:accent3>
191
+ <a:accent4><a:srgbClr val="FFC000"/></a:accent4>
192
+ <a:accent5><a:srgbClr val="5B9BD5"/></a:accent5>
193
+ <a:accent6><a:srgbClr val="70AD47"/></a:accent6>
194
+ <a:hlink><a:srgbClr val="0563C1"/></a:hlink>
195
+ <a:folHlink><a:srgbClr val="954F72"/></a:folHlink>
196
+ </a:clrScheme>
197
+ <a:fontScheme name="Office">
198
+ <a:majorFont><a:latin typeface="Calibri Light"/><a:ea typeface=""/><a:cs typeface=""/></a:majorFont>
199
+ <a:minorFont><a:latin typeface="Calibri"/><a:ea typeface=""/><a:cs typeface=""/></a:minorFont>
200
+ </a:fontScheme>
201
+ <a:fmtScheme name="Office">
202
+ <a:fillStyleLst>
203
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
204
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
205
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
206
+ </a:fillStyleLst>
207
+ <a:lnStyleLst>
208
+ <a:ln w="6350"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
209
+ <a:ln w="6350"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
210
+ <a:ln w="6350"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill></a:ln>
211
+ </a:lnStyleLst>
212
+ <a:effectStyleLst>
213
+ <a:effectStyle><a:effectLst/></a:effectStyle>
214
+ <a:effectStyle><a:effectLst/></a:effectStyle>
215
+ <a:effectStyle><a:effectLst/></a:effectStyle>
216
+ </a:effectStyleLst>
217
+ <a:bgFillStyleLst>
218
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
219
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
220
+ <a:solidFill><a:schemeClr val="phClr"/></a:solidFill>
221
+ </a:bgFillStyleLst>
222
+ </a:fmtScheme>
223
+ </a:themeElements>
224
+ </a:theme>
225
+ """);
226
+ }
227
+
228
+ // ── Document body ──
229
+ mainPart.Document = new Document(
230
+ new Body(
231
+ new Paragraph(
232
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
233
+ new Run(new Text("Sample Document"))
234
+ ),
235
+ new Paragraph(
236
+ new Run(new Text("This document includes all standard parts."))
237
+ ),
238
+ // Final section properties
239
+ new SectionProperties(
240
+ new WpPageSize
241
+ {
242
+ Width = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
243
+ Height = (UInt32Value)(uint)PageSizes.A4.HeightDxa
244
+ },
245
+ new PageMargin
246
+ {
247
+ Top = PageSizes.StandardMargins.TopDxa,
248
+ Right = (UInt32Value)(uint)PageSizes.StandardMargins.RightDxa,
249
+ Bottom = PageSizes.StandardMargins.BottomDxa,
250
+ Left = (UInt32Value)(uint)PageSizes.StandardMargins.LeftDxa,
251
+ Header = (UInt32Value)720U,
252
+ Footer = (UInt32Value)720U,
253
+ Gutter = (UInt32Value)0U
254
+ }
255
+ )
256
+ )
257
+ );
258
+
259
+ // Set document-level metadata
260
+ SetDocumentProperties(doc);
261
+
262
+ mainPart.Document.Save();
263
+ }
264
+
265
+ // ────────────────────────────────────────────────────────────────────
266
+ // 3. CREATE FROM STREAM (for web/API)
267
+ // ────────────────────────────────────────────────────────────────────
268
+
269
+ /// <summary>
270
+ /// Creates a DOCX entirely in memory, returning a MemoryStream.
271
+ /// Ideal for ASP.NET / Web API scenarios where you return FileStreamResult.
272
+ /// </summary>
273
+ /// <remarks>
274
+ /// Usage in ASP.NET:
275
+ /// <code>
276
+ /// var stream = DocumentCreationSamples.CreateFromStream();
277
+ /// return File(stream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "report.docx");
278
+ /// </code>
279
+ /// </remarks>
280
+ public static MemoryStream CreateFromStream()
281
+ {
282
+ // IMPORTANT: The MemoryStream must remain open after WordprocessingDocument is disposed.
283
+ // Do NOT wrap the stream in a using statement here — the caller owns its lifetime.
284
+ var stream = new MemoryStream();
285
+
286
+ // WARNING: You MUST pass 'true' for the 'leaveOpen' parameter (via the overload that
287
+ // accepts a stream) so that disposing the WordprocessingDocument does NOT close the stream.
288
+ // The Create overload with Stream does this correctly in SDK 3.x.
289
+ using (var doc = WordprocessingDocument.Create(stream, WordprocessingDocumentType.Document))
290
+ {
291
+ var mainPart = doc.AddMainDocumentPart();
292
+ mainPart.Document = new Document(
293
+ new Body(
294
+ new Paragraph(
295
+ new Run(new Text("Generated in memory"))
296
+ ),
297
+ new SectionProperties(
298
+ new WpPageSize
299
+ {
300
+ Width = (UInt32Value)(uint)PageSizes.Letter.WidthDxa,
301
+ Height = (UInt32Value)(uint)PageSizes.Letter.HeightDxa
302
+ },
303
+ new PageMargin
304
+ {
305
+ Top = 1440,
306
+ Right = (UInt32Value)1440U,
307
+ Bottom = 1440,
308
+ Left = (UInt32Value)1440U,
309
+ Header = (UInt32Value)720U,
310
+ Footer = (UInt32Value)720U,
311
+ Gutter = (UInt32Value)0U
312
+ }
313
+ )
314
+ )
315
+ );
316
+ mainPart.Document.Save();
317
+ }
318
+ // Disposing the WordprocessingDocument flushes all data to the stream.
319
+
320
+ // IMPORTANT: Reset position so the caller can read from the beginning.
321
+ stream.Position = 0;
322
+ return stream;
323
+ }
324
+
325
+ // ────────────────────────────────────────────────────────────────────
326
+ // 4. OPEN AND EDIT EXISTING DOCUMENT
327
+ // ────────────────────────────────────────────────────────────────────
328
+
329
+ /// <summary>
330
+ /// Opens an existing DOCX, modifies its content, and saves.
331
+ /// Demonstrates the read-modify-write pattern.
332
+ /// </summary>
333
+ public static void OpenAndEdit(string path)
334
+ {
335
+ // Open for editing (isEditable = true)
336
+ // WARNING: If the file is read-only on disk, this will throw IOException.
337
+ // For read-only access, pass false and use a copy-to-stream pattern instead.
338
+ using var doc = WordprocessingDocument.Open(path, isEditable: true);
339
+
340
+ var body = doc.MainDocumentPart?.Document.Body;
341
+ if (body is null)
342
+ return;
343
+
344
+ // Add a new paragraph at the end, BEFORE the final SectionProperties
345
+ // WARNING: Always insert before sectPr — it must remain the last child of Body
346
+ var sectPr = body.Elements<SectionProperties>().FirstOrDefault();
347
+
348
+ var newParagraph = new Paragraph(
349
+ new ParagraphProperties(
350
+ // Apply Normal style explicitly (usually inherited, but being explicit is safer)
351
+ new ParagraphStyleId { Val = "Normal" },
352
+ new Justification { Val = JustificationValues.Left }
353
+ ),
354
+ new Run(
355
+ new RunProperties(
356
+ new Bold(),
357
+ new Color { Val = "FF0000" } // red, RGB hex without #
358
+ ),
359
+ // IMPORTANT: When text has leading/trailing whitespace, you must set
360
+ // SpaceProcessingModeValues.Preserve or Word will strip it
361
+ new Text("This paragraph was added programmatically.") { Space = SpaceProcessingModeValues.Preserve }
362
+ )
363
+ );
364
+
365
+ if (sectPr is not null)
366
+ {
367
+ // Insert before the final section properties
368
+ body.InsertBefore(newParagraph, sectPr);
369
+ }
370
+ else
371
+ {
372
+ // No sectPr found (unusual but possible); just append
373
+ body.Append(newParagraph);
374
+ }
375
+
376
+ // Modify an existing paragraph — change the text of the first paragraph
377
+ var firstPara = body.Elements<Paragraph>().FirstOrDefault();
378
+ if (firstPara is not null)
379
+ {
380
+ var firstRun = firstPara.Elements<Run>().FirstOrDefault();
381
+ if (firstRun is not null)
382
+ {
383
+ var textElement = firstRun.Elements<Text>().FirstOrDefault();
384
+ if (textElement is not null)
385
+ {
386
+ textElement.Text = "Modified: " + textElement.Text;
387
+ }
388
+ }
389
+ }
390
+
391
+ // Save is called automatically on Dispose, but calling explicitly
392
+ // ensures errors surface at a known point
393
+ doc.MainDocumentPart!.Document.Save();
394
+ }
395
+
396
+ // ────────────────────────────────────────────────────────────────────
397
+ // 5. DOCUMENT DEFAULTS (DocDefaults)
398
+ // ────────────────────────────────────────────────────────────────────
399
+
400
+ /// <summary>
401
+ /// Sets RunPropertiesDefault and ParagraphPropertiesDefault in the styles part.
402
+ /// These defaults apply to ALL paragraphs and runs unless overridden by a style or direct formatting.
403
+ /// </summary>
404
+ /// <remarks>
405
+ /// Produces in styles.xml:
406
+ /// <code>
407
+ /// &lt;w:docDefaults&gt;
408
+ /// &lt;w:rPrDefault&gt;
409
+ /// &lt;w:rPr&gt;
410
+ /// &lt;w:rFonts w:ascii="Calibri" w:hAnsi="Calibri" w:eastAsia="SimSun" w:cs="Arial"/&gt;
411
+ /// &lt;w:sz w:val="22"/&gt;
412
+ /// &lt;w:szCs w:val="22"/&gt;
413
+ /// &lt;w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA"/&gt;
414
+ /// &lt;/w:rPr&gt;
415
+ /// &lt;/w:rPrDefault&gt;
416
+ /// &lt;w:pPrDefault&gt;
417
+ /// &lt;w:pPr&gt;
418
+ /// &lt;w:spacing w:after="160" w:line="259" w:lineRule="auto"/&gt;
419
+ /// &lt;/w:pPr&gt;
420
+ /// &lt;/w:pPrDefault&gt;
421
+ /// &lt;/w:docDefaults&gt;
422
+ /// </code>
423
+ /// </remarks>
424
+ public static void SetDocDefaults(MainDocumentPart mainPart)
425
+ {
426
+ // Ensure StyleDefinitionsPart exists
427
+ var stylesPart = mainPart.StyleDefinitionsPart
428
+ ?? mainPart.AddNewPart<StyleDefinitionsPart>();
429
+ stylesPart.Styles ??= new Styles();
430
+
431
+ var docDefaults = new DocDefaults();
432
+
433
+ // ── Run Properties Default ──
434
+ // These become the "base" formatting for all text in the document
435
+ var runPropsDefault = new RunPropertiesDefault(
436
+ new RunPropertiesBaseStyle(
437
+ // RunFonts has 4 slots for different Unicode ranges:
438
+ // Ascii — Latin characters (U+0000–U+007F)
439
+ // HighAnsi — extended Latin (U+0080–U+FFFF, non-EastAsian)
440
+ // EastAsia — CJK characters
441
+ // ComplexScript — RTL scripts (Arabic, Hebrew, etc.)
442
+ new RunFonts
443
+ {
444
+ Ascii = "Calibri",
445
+ HighAnsi = "Calibri",
446
+ EastAsia = "SimSun", // 宋体 — standard CJK body font
447
+ ComplexScript = "Arial"
448
+ },
449
+ // Font size is in HALF-POINTS: 22 half-pt = 11pt
450
+ new FontSize { Val = "22" },
451
+ // Complex script size (for Arabic/Hebrew text)
452
+ new FontSizeComplexScript { Val = "22" },
453
+ // Language tags control spell-check and hyphenation
454
+ new Languages
455
+ {
456
+ Val = "en-US",
457
+ EastAsia = "zh-CN",
458
+ Bidi = "ar-SA"
459
+ }
460
+ )
461
+ );
462
+
463
+ // ── Paragraph Properties Default ──
464
+ // Spacing that applies to all paragraphs unless overridden
465
+ var paraPropsDefault = new ParagraphPropertiesDefault(
466
+ new ParagraphPropertiesBaseStyle(
467
+ new SpacingBetweenLines
468
+ {
469
+ // After = space after paragraph in DXA twentieths-of-a-point
470
+ // 160 DXA = 8pt after each paragraph (Word 2016+ default)
471
+ After = "160",
472
+ // Line = line spacing:
473
+ // For "auto" rule: value is in 240ths of a line
474
+ // 259 = 1.0791... ≈ 1.08 line spacing (Word's "single" with body text font)
475
+ // For "exact"/"atLeast": value is in DXA twentieths-of-a-point
476
+ Line = "259",
477
+ LineRule = LineSpacingRuleValues.Auto
478
+ }
479
+ )
480
+ );
481
+
482
+ docDefaults.Append(runPropsDefault);
483
+ docDefaults.Append(paraPropsDefault);
484
+
485
+ // IMPORTANT: DocDefaults must be the FIRST child of w:styles.
486
+ // If there are existing children, prepend it.
487
+ var existingDocDefaults = stylesPart.Styles.DocDefaults;
488
+ if (existingDocDefaults is not null)
489
+ {
490
+ existingDocDefaults.Remove();
491
+ }
492
+ stylesPart.Styles.PrependChild(docDefaults);
493
+ stylesPart.Styles.Save();
494
+ }
495
+
496
+ // ────────────────────────────────────────────────────────────────────
497
+ // 6. DOCUMENT SETTINGS
498
+ // ────────────────────────────────────────────────────────────────────
499
+
500
+ /// <summary>
501
+ /// Adds document-level settings: zoom, default tab stop, proofing,
502
+ /// compatibility options, field update behavior, and character spacing control.
503
+ /// </summary>
504
+ /// <remarks>
505
+ /// Produces in word/settings.xml:
506
+ /// <code>
507
+ /// &lt;w:settings&gt;
508
+ /// &lt;w:zoom w:percent="100"/&gt;
509
+ /// &lt;w:defaultTabStop w:val="720"/&gt;
510
+ /// &lt;w:characterSpacingControl w:val="doNotCompress"/&gt;
511
+ /// &lt;w:proofState w:spelling="clean" w:grammar="clean"/&gt;
512
+ /// &lt;w:updateFields w:val="true"/&gt;
513
+ /// &lt;w:compat&gt;
514
+ /// &lt;w:compatSetting w:name="compatibilityMode" w:uri="..." w:val="15"/&gt;
515
+ /// &lt;/w:compat&gt;
516
+ /// &lt;/w:settings&gt;
517
+ /// </code>
518
+ /// </remarks>
519
+ public static void AddDocumentSettings(MainDocumentPart mainPart)
520
+ {
521
+ var settingsPart = mainPart.DocumentSettingsPart
522
+ ?? mainPart.AddNewPart<DocumentSettingsPart>();
523
+ settingsPart.Settings ??= new Settings();
524
+ var settings = settingsPart.Settings;
525
+
526
+ // ── Zoom level ──
527
+ // 100 = 100%. Word remembers this for the next open.
528
+ settings.Append(new Zoom { Percent = "100" });
529
+
530
+ // ── Default tab stop ──
531
+ // 720 DXA = 0.5 inch. This is the interval for default tab stops
532
+ // across the entire document. Common values:
533
+ // 720 = 0.5 inch (US default)
534
+ // 420 = ~0.74cm (common in Chinese docs)
535
+ settings.Append(new DefaultTabStop { Val = 720 });
536
+
537
+ // ── Character spacing control ──
538
+ // Controls how CJK character spacing is handled
539
+ // DoNotCompress — no compression of punctuation
540
+ // CompressPunctuation — compress CJK punctuation at line start/end
541
+ // CompressPunctuationAndJapaneseKanaWhitespace — full CJK compression
542
+ settings.Append(new CharacterSpacingControl
543
+ {
544
+ Val = CharacterSpacingValues.DoNotCompress
545
+ });
546
+
547
+ // ── Proofing state ──
548
+ // Tells Word that spell/grammar check is clean; avoids the squiggly-line
549
+ // check running immediately on open
550
+ settings.Append(new ProofState
551
+ {
552
+ Spelling = ProofingStateValues.Clean,
553
+ Grammar = ProofingStateValues.Clean
554
+ });
555
+
556
+ // ── Update fields on open ──
557
+ // WARNING: Setting this to true causes Word to prompt "This document contains
558
+ // fields that may refer to other files. Do you want to update the fields?"
559
+ // Useful for TOC/TOF fields that need refreshing
560
+ settings.Append(new UpdateFieldsOnOpen { Val = true });
561
+
562
+ // ── Compatibility settings ──
563
+ // compatibilityMode = 15 means "Word 2013+ mode" — the highest stable mode.
564
+ // This controls layout behavior: line breaking, table widths, spacing, etc.
565
+ // WARNING: Using a lower value (e.g., 11 for Word 2003) changes layout
566
+ // significantly and is almost never what you want.
567
+ var compat = new Compatibility();
568
+ compat.Append(new CompatibilitySetting
569
+ {
570
+ Name = CompatSettingNameValues.CompatibilityMode,
571
+ Uri = "http://schemas.microsoft.com/office/word",
572
+ Val = "15"
573
+ });
574
+ // Additional CJK compatibility settings
575
+ compat.Append(new CompatibilitySetting
576
+ {
577
+ Name = CompatSettingNameValues.OverrideTableStyleFontSizeAndJustification,
578
+ Uri = "http://schemas.microsoft.com/office/word",
579
+ Val = "1"
580
+ });
581
+ compat.Append(new CompatibilitySetting
582
+ {
583
+ Name = CompatSettingNameValues.EnableOpenTypeFeatures,
584
+ Uri = "http://schemas.microsoft.com/office/word",
585
+ Val = "1"
586
+ });
587
+ settings.Append(compat);
588
+
589
+ settings.Save();
590
+ }
591
+
592
+ // ────────────────────────────────────────────────────────────────────
593
+ // 7. DOCUMENT PROPERTIES (metadata)
594
+ // ────────────────────────────────────────────────────────────────────
595
+
596
+ /// <summary>
597
+ /// Sets core properties (Dublin Core: title, author, dates),
598
+ /// extended properties (company, application name),
599
+ /// and custom properties (arbitrary key-value pairs).
600
+ /// </summary>
601
+ /// <remarks>
602
+ /// Core properties go into docProps/core.xml (Dublin Core + CP namespaces).
603
+ /// Extended properties go into docProps/app.xml.
604
+ /// Custom properties go into docProps/custom.xml.
605
+ /// </remarks>
606
+ public static void SetDocumentProperties(WordprocessingDocument doc)
607
+ {
608
+ // ── Core Properties ──
609
+ // These map to Dublin Core metadata elements in docProps/core.xml
610
+ doc.PackageProperties.Title = "Quarterly Report";
611
+ doc.PackageProperties.Subject = "Financial Summary";
612
+ doc.PackageProperties.Creator = "MiniMax AI"; // Author
613
+ doc.PackageProperties.Keywords = "report, finance, Q4";
614
+ doc.PackageProperties.Description = "Auto-generated financial report";
615
+ doc.PackageProperties.Category = "Reports";
616
+ doc.PackageProperties.ContentStatus = "Draft";
617
+
618
+ // Dates — PackageProperties uses DateTimeOffset?
619
+ doc.PackageProperties.Created = DateTimeOffset.UtcNow.DateTime;
620
+ doc.PackageProperties.Modified = DateTimeOffset.UtcNow.DateTime;
621
+ doc.PackageProperties.LastModifiedBy = "DocBuilder Agent";
622
+
623
+ // ── Extended Properties ──
624
+ // These go into docProps/app.xml
625
+ var extendedProps = doc.AddExtendedFilePropertiesPart();
626
+ extendedProps.Properties = new DocumentFormat.OpenXml.ExtendedProperties.Properties
627
+ {
628
+ Company = new Company("MiniMax Inc."),
629
+ Application = new Application("MiniMaxAIDocx"),
630
+ ApplicationVersion = new ApplicationVersion("1.0.0")
631
+ };
632
+ extendedProps.Properties.Save();
633
+
634
+ // ── Custom Properties ──
635
+ // Arbitrary key-value pairs; visible in File > Properties > Custom in Word
636
+ var customProps = doc.AddCustomFilePropertiesPart();
637
+ customProps.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties();
638
+
639
+ // Each custom property needs a unique PID starting at 2
640
+ // (PID 0 and 1 are reserved by the system)
641
+ int pid = 2;
642
+
643
+ // String property
644
+ customProps.Properties.Append(new CustomDocumentProperty
645
+ {
646
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
647
+ PropertyId = pid++,
648
+ Name = "Department",
649
+ VTLPWSTR = new VTLPWSTR("Engineering")
650
+ });
651
+
652
+ // Integer property
653
+ customProps.Properties.Append(new CustomDocumentProperty
654
+ {
655
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
656
+ PropertyId = pid++,
657
+ Name = "ReviewCount",
658
+ VTInt32 = new VTInt32("3")
659
+ });
660
+
661
+ // Boolean property
662
+ customProps.Properties.Append(new CustomDocumentProperty
663
+ {
664
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
665
+ PropertyId = pid++,
666
+ Name = "IsApproved",
667
+ VTBool = new VTBool("true")
668
+ });
669
+
670
+ // Date property
671
+ customProps.Properties.Append(new CustomDocumentProperty
672
+ {
673
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
674
+ PropertyId = pid++,
675
+ Name = "ReviewDate",
676
+ VTFileTime = new VTFileTime(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"))
677
+ });
678
+
679
+ customProps.Properties.Save();
680
+ }
681
+
682
+ // ────────────────────────────────────────────────────────────────────
683
+ // 8. PAGE SETUP (sizes, margins, orientation)
684
+ // ────────────────────────────────────────────────────────────────────
685
+
686
+ /// <summary>
687
+ /// Creates a document demonstrating various page setups:
688
+ /// A4/Letter sizes, standard/narrow/wide/公文 margins,
689
+ /// and both portrait and landscape orientations (as separate sections).
690
+ /// </summary>
691
+ public static void CreateDocumentWithPageSetup(string path)
692
+ {
693
+ using var doc = WordprocessingDocument.Create(path, WordprocessingDocumentType.Document);
694
+ var mainPart = doc.AddMainDocumentPart();
695
+
696
+ var body = new Body();
697
+
698
+ // ════════════════════════════════════════════════════════════
699
+ // SECTION 1: A4 Portrait with Standard Margins (1 inch all)
700
+ // ════════════════════════════════════════════════════════════
701
+ body.Append(
702
+ new Paragraph(
703
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
704
+ new Run(new Text("Section 1: A4 Portrait, Standard Margins"))
705
+ )
706
+ );
707
+ body.Append(
708
+ new Paragraph(new Run(new Text("Standard 1-inch margins all around.")))
709
+ );
710
+
711
+ // IMPORTANT: This is a "continuous" section break that ends section 1.
712
+ // The sectPr inside a pPr defines the properties FOR THE PRECEDING section.
713
+ // The FINAL section's properties are in the body-level sectPr.
714
+ body.Append(
715
+ new Paragraph(
716
+ new ParagraphProperties(
717
+ new SectionProperties(
718
+ new WpPageSize
719
+ {
720
+ // A4: 210mm x 297mm = 11906 x 16838 DXA
721
+ Width = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
722
+ Height = (UInt32Value)(uint)PageSizes.A4.HeightDxa
723
+ // IMPORTANT: No Orient attribute = portrait (default)
724
+ },
725
+ new PageMargin
726
+ {
727
+ Top = PageSizes.StandardMargins.TopDxa, // 1440 = 1 inch
728
+ Right = (UInt32Value)(uint)PageSizes.StandardMargins.RightDxa,
729
+ Bottom = PageSizes.StandardMargins.BottomDxa,
730
+ Left = (UInt32Value)(uint)PageSizes.StandardMargins.LeftDxa,
731
+ Header = (UInt32Value)720U,
732
+ Footer = (UInt32Value)720U,
733
+ Gutter = (UInt32Value)0U
734
+ }
735
+ )
736
+ )
737
+ )
738
+ );
739
+
740
+ // ════════════════════════════════════════════════════════════
741
+ // SECTION 2: Letter Portrait with Narrow Margins
742
+ // ════════════════════════════════════════════════════════════
743
+ body.Append(
744
+ new Paragraph(
745
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
746
+ new Run(new Text("Section 2: Letter Portrait, Narrow Margins"))
747
+ )
748
+ );
749
+ body.Append(
750
+ new Paragraph(new Run(new Text("Narrow 0.5-inch margins for maximum content area.")))
751
+ );
752
+
753
+ body.Append(
754
+ new Paragraph(
755
+ new ParagraphProperties(
756
+ new SectionProperties(
757
+ new WpPageSize
758
+ {
759
+ // US Letter: 8.5" x 11" = 12240 x 15840 DXA
760
+ Width = (UInt32Value)(uint)PageSizes.Letter.WidthDxa,
761
+ Height = (UInt32Value)(uint)PageSizes.Letter.HeightDxa
762
+ },
763
+ new PageMargin
764
+ {
765
+ Top = PageSizes.NarrowMargins.TopDxa, // 720 = 0.5 inch
766
+ Right = (UInt32Value)(uint)PageSizes.NarrowMargins.RightDxa,
767
+ Bottom = PageSizes.NarrowMargins.BottomDxa,
768
+ Left = (UInt32Value)(uint)PageSizes.NarrowMargins.LeftDxa,
769
+ Header = (UInt32Value)720U,
770
+ Footer = (UInt32Value)720U,
771
+ Gutter = (UInt32Value)0U
772
+ }
773
+ )
774
+ )
775
+ )
776
+ );
777
+
778
+ // ════════════════════════════════════════════════════════════
779
+ // SECTION 3: A4 Landscape with Wide Margins
780
+ // ════════════════════════════════════════════════════════════
781
+ body.Append(
782
+ new Paragraph(
783
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
784
+ new Run(new Text("Section 3: A4 Landscape, Wide Margins"))
785
+ )
786
+ );
787
+ body.Append(
788
+ new Paragraph(new Run(new Text("Landscape orientation — width and height are SWAPPED.")))
789
+ );
790
+
791
+ body.Append(
792
+ new Paragraph(
793
+ new ParagraphProperties(
794
+ new SectionProperties(
795
+ new WpPageSize
796
+ {
797
+ // IMPORTANT: For landscape, SWAP width and height values
798
+ // AND set Orient = Landscape
799
+ Width = (UInt32Value)(uint)PageSizes.A4.HeightDxa, // 16838 (was height)
800
+ Height = (UInt32Value)(uint)PageSizes.A4.WidthDxa, // 11906 (was width)
801
+ Orient = PageOrientationValues.Landscape
802
+ },
803
+ new PageMargin
804
+ {
805
+ // Wide margins: 1" top/bottom, 1.5" left/right
806
+ Top = PageSizes.WideMargins.TopDxa, // 1440
807
+ Right = (UInt32Value)(uint)PageSizes.WideMargins.RightDxa, // 2160
808
+ Bottom = PageSizes.WideMargins.BottomDxa, // 1440
809
+ Left = (UInt32Value)(uint)PageSizes.WideMargins.LeftDxa, // 2160
810
+ Header = (UInt32Value)720U,
811
+ Footer = (UInt32Value)720U,
812
+ Gutter = (UInt32Value)0U
813
+ }
814
+ )
815
+ )
816
+ )
817
+ );
818
+
819
+ // ════════════════════════════════════════════════════════════
820
+ // SECTION 4 (FINAL): A4 Portrait with Chinese 公文 Margins
821
+ // ════════════════════════════════════════════════════════════
822
+ // Chinese government document standard (GB/T 9704-2012):
823
+ // Page: A4 (210mm x 297mm)
824
+ // Top: 37mm ≈ 2098 DXA Bottom: 35mm ≈ 1984 DXA
825
+ // Left: 28mm ≈ 1587 DXA Right: 26mm ≈ 1474 DXA
826
+ body.Append(
827
+ new Paragraph(
828
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
829
+ new Run(new Text("Section 4: A4 Portrait, 公文 Margins (GB/T 9704)"))
830
+ )
831
+ );
832
+ body.Append(
833
+ new Paragraph(new Run(new Text("Chinese government document standard margins.")))
834
+ );
835
+
836
+ // The FINAL section's SectionProperties goes as a direct child of Body (not in pPr)
837
+ body.Append(
838
+ new SectionProperties(
839
+ new WpPageSize
840
+ {
841
+ Width = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
842
+ Height = (UInt32Value)(uint)PageSizes.A4.HeightDxa
843
+ },
844
+ new PageMargin
845
+ {
846
+ // 公文 margins per GB/T 9704-2012
847
+ Top = UnitConverter.CmToDxa(3.7), // 37mm top
848
+ Right = (UInt32Value)(uint)UnitConverter.CmToDxa(2.6), // 26mm right
849
+ Bottom = UnitConverter.CmToDxa(3.5), // 35mm bottom
850
+ Left = (UInt32Value)(uint)UnitConverter.CmToDxa(2.8), // 28mm left
851
+ Header = (UInt32Value)(uint)UnitConverter.CmToDxa(1.5), // 15mm header
852
+ Footer = (UInt32Value)(uint)UnitConverter.CmToDxa(1.75),// 17.5mm footer
853
+ Gutter = (UInt32Value)0U
854
+ },
855
+ // Document grid for Chinese text layout:
856
+ // 28 lines per page, 28 characters per line (公文 standard)
857
+ new DocGrid
858
+ {
859
+ Type = DocGridValues.LinesAndChars,
860
+ LinePitch = 579, // vertical pitch in DXA: ~28 lines on A4
861
+ CharacterSpace = 210 // character spacing adjustment
862
+ }
863
+ )
864
+ );
865
+
866
+ mainPart.Document = new Document(body);
867
+ mainPart.Document.Save();
868
+ }
869
+
870
+ // ────────────────────────────────────────────────────────────────────
871
+ // 9. MULTI-SECTION DOCUMENT
872
+ // ────────────────────────────────────────────────────────────────────
873
+
874
+ /// <summary>
875
+ /// Creates a document with three sections demonstrating:
876
+ /// - Portrait intro with "first page" header
877
+ /// - Landscape table section with different header
878
+ /// - Portrait conclusion with page number restart
879
+ /// Each section has its own headers and page numbering.
880
+ /// </summary>
881
+ public static void CreateMultiSectionDocument(string path)
882
+ {
883
+ using var doc = WordprocessingDocument.Create(path, WordprocessingDocumentType.Document);
884
+ var mainPart = doc.AddMainDocumentPart();
885
+
886
+ // ── Create headers for each section ──
887
+ // Each section can reference its own header/footer parts.
888
+
889
+ // --- Section 1 headers: "first page" + "default" ---
890
+ var header1Default = CreateHeaderPart(mainPart, "Introduction — Page ");
891
+ var header1FirstPage = CreateHeaderPart(mainPart, "CONFIDENTIAL DRAFT");
892
+
893
+ // --- Section 2 header: landscape section ---
894
+ var header2Default = CreateHeaderPart(mainPart, "Data Tables — Landscape View");
895
+
896
+ // --- Section 3 header: conclusion ---
897
+ var header3Default = CreateHeaderPart(mainPart, "Conclusion — Page ");
898
+
899
+ var body = new Body();
900
+
901
+ // ════════════════════════════════════════════════════════════
902
+ // SECTION 1: Portrait Introduction
903
+ // ════════════════════════════════════════════════════════════
904
+ body.Append(
905
+ new Paragraph(
906
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
907
+ new Run(new Text("Introduction"))
908
+ )
909
+ );
910
+ body.Append(
911
+ new Paragraph(new Run(new Text(
912
+ "This section uses portrait orientation with a special first-page header.")))
913
+ );
914
+ body.Append(
915
+ new Paragraph(new Run(new Text(
916
+ "The first page shows 'CONFIDENTIAL DRAFT', subsequent pages show the section name.")))
917
+ );
918
+
919
+ // Section 1 properties (embedded in paragraph = section break)
920
+ var sect1Props = new SectionProperties(
921
+ // Header references link to header parts via relationship IDs
922
+ // HeaderFooterType: Default = all pages, First = first page only, Even = even pages
923
+ new HeaderReference
924
+ {
925
+ Type = HeaderFooterValues.Default,
926
+ Id = mainPart.GetIdOfPart(header1Default)
927
+ },
928
+ new HeaderReference
929
+ {
930
+ Type = HeaderFooterValues.First,
931
+ Id = mainPart.GetIdOfPart(header1FirstPage)
932
+ },
933
+ // IMPORTANT: SectionType controls how the section break renders:
934
+ // NextPage — starts on a new page (default if omitted)
935
+ // Continuous — no page break, flows on same page
936
+ // EvenPage / OddPage — starts on next even/odd page
937
+ new SectionType { Val = SectionMarkValues.NextPage },
938
+ new WpPageSize
939
+ {
940
+ Width = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
941
+ Height = (UInt32Value)(uint)PageSizes.A4.HeightDxa
942
+ },
943
+ new PageMargin
944
+ {
945
+ Top = 1440, Right = (UInt32Value)1440U, Bottom = 1440,
946
+ Left = (UInt32Value)1440U, Header = (UInt32Value)720U,
947
+ Footer = (UInt32Value)720U, Gutter = (UInt32Value)0U
948
+ },
949
+ // PageNumberType: start numbering from 1
950
+ new PageNumberType { Start = 1 },
951
+ // TitlePage: enables the "Different First Page" header/footer
952
+ // Without this, the First header reference is ignored!
953
+ new TitlePage()
954
+ );
955
+
956
+ body.Append(new Paragraph(new ParagraphProperties(sect1Props)));
957
+
958
+ // ════════════════════════════════════════════════════════════
959
+ // SECTION 2: Landscape Data Tables
960
+ // ════════════════════════════════════════════════════════════
961
+ body.Append(
962
+ new Paragraph(
963
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
964
+ new Run(new Text("Data Tables"))
965
+ )
966
+ );
967
+
968
+ // Add a simple table to justify landscape orientation
969
+ var table = new Table(
970
+ new TableProperties(
971
+ new TableWidth { Width = "5000", Type = TableWidthUnitValues.Pct },
972
+ new TableBorders(
973
+ new TopBorder { Val = BorderValues.Single, Size = 4 },
974
+ new BottomBorder { Val = BorderValues.Single, Size = 4 },
975
+ new LeftBorder { Val = BorderValues.Single, Size = 4 },
976
+ new RightBorder { Val = BorderValues.Single, Size = 4 },
977
+ new InsideHorizontalBorder { Val = BorderValues.Single, Size = 4 },
978
+ new InsideVerticalBorder { Val = BorderValues.Single, Size = 4 }
979
+ )
980
+ ),
981
+ new TableGrid(
982
+ new GridColumn { Width = "3000" },
983
+ new GridColumn { Width = "3000" },
984
+ new GridColumn { Width = "3000" }
985
+ ),
986
+ // Header row
987
+ new TableRow(
988
+ new TableCell(new Paragraph(new Run(new Text("Column A")))),
989
+ new TableCell(new Paragraph(new Run(new Text("Column B")))),
990
+ new TableCell(new Paragraph(new Run(new Text("Column C"))))
991
+ ),
992
+ // Data row
993
+ new TableRow(
994
+ new TableCell(new Paragraph(new Run(new Text("Data 1")))),
995
+ new TableCell(new Paragraph(new Run(new Text("Data 2")))),
996
+ new TableCell(new Paragraph(new Run(new Text("Data 3"))))
997
+ )
998
+ );
999
+ body.Append(table);
1000
+
1001
+ // Section 2 properties (landscape)
1002
+ var sect2Props = new SectionProperties(
1003
+ new HeaderReference
1004
+ {
1005
+ Type = HeaderFooterValues.Default,
1006
+ Id = mainPart.GetIdOfPart(header2Default)
1007
+ },
1008
+ new SectionType { Val = SectionMarkValues.NextPage },
1009
+ new WpPageSize
1010
+ {
1011
+ // IMPORTANT: Landscape = swap width/height AND set Orient
1012
+ Width = (UInt32Value)(uint)PageSizes.A4.HeightDxa,
1013
+ Height = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
1014
+ Orient = PageOrientationValues.Landscape
1015
+ },
1016
+ new PageMargin
1017
+ {
1018
+ Top = 1440, Right = (UInt32Value)1440U, Bottom = 1440,
1019
+ Left = (UInt32Value)1440U, Header = (UInt32Value)720U,
1020
+ Footer = (UInt32Value)720U, Gutter = (UInt32Value)0U
1021
+ },
1022
+ // Continue page numbering from previous section (no Start attribute)
1023
+ new PageNumberType()
1024
+ );
1025
+
1026
+ body.Append(new Paragraph(new ParagraphProperties(sect2Props)));
1027
+
1028
+ // ════════════════════════════════════════════════════════════
1029
+ // SECTION 3 (FINAL): Portrait Conclusion with Restart Numbering
1030
+ // ════════════════════════════════════════════════════════════
1031
+ body.Append(
1032
+ new Paragraph(
1033
+ new ParagraphProperties(new ParagraphStyleId { Val = "Heading1" }),
1034
+ new Run(new Text("Conclusion"))
1035
+ )
1036
+ );
1037
+ body.Append(
1038
+ new Paragraph(new Run(new Text(
1039
+ "This section restarts page numbering from 1.")))
1040
+ );
1041
+
1042
+ // Final section: SectionProperties as direct child of Body
1043
+ body.Append(
1044
+ new SectionProperties(
1045
+ new HeaderReference
1046
+ {
1047
+ Type = HeaderFooterValues.Default,
1048
+ Id = mainPart.GetIdOfPart(header3Default)
1049
+ },
1050
+ new WpPageSize
1051
+ {
1052
+ Width = (UInt32Value)(uint)PageSizes.A4.WidthDxa,
1053
+ Height = (UInt32Value)(uint)PageSizes.A4.HeightDxa
1054
+ },
1055
+ new PageMargin
1056
+ {
1057
+ Top = 1440, Right = (UInt32Value)1440U, Bottom = 1440,
1058
+ Left = (UInt32Value)1440U, Header = (UInt32Value)720U,
1059
+ Footer = (UInt32Value)720U, Gutter = (UInt32Value)0U
1060
+ },
1061
+ // Restart page numbering from 1 for this section
1062
+ new PageNumberType { Start = 1 }
1063
+ )
1064
+ );
1065
+
1066
+ mainPart.Document = new Document(body);
1067
+ mainPart.Document.Save();
1068
+ }
1069
+
1070
+ // ────────────────────────────────────────────────────────────────────
1071
+ // HELPER: Create a header part with text and optional page number field
1072
+ // ────────────────────────────────────────────────────────────────────
1073
+
1074
+ /// <summary>
1075
+ /// Creates a HeaderPart with the given text. If the text ends with a space,
1076
+ /// a PAGE field is appended to show the page number.
1077
+ /// </summary>
1078
+ private static HeaderPart CreateHeaderPart(MainDocumentPart mainPart, string text)
1079
+ {
1080
+ var headerPart = mainPart.AddNewPart<HeaderPart>();
1081
+ var header = new Header();
1082
+
1083
+ var para = new Paragraph(
1084
+ new ParagraphProperties(
1085
+ new Justification { Val = JustificationValues.Center }
1086
+ )
1087
+ );
1088
+
1089
+ // Add the text run
1090
+ para.Append(new Run(
1091
+ new RunProperties(
1092
+ new FontSize { Val = "18" } // 9pt for header text
1093
+ ),
1094
+ new Text(text) { Space = SpaceProcessingModeValues.Preserve }
1095
+ ));
1096
+
1097
+ // If text ends with space, add a PAGE field (auto page number)
1098
+ if (text.EndsWith(' '))
1099
+ {
1100
+ // PAGE field uses three runs: begin, instruction, end
1101
+ // This is the "complex field" pattern used by Word
1102
+ para.Append(new Run(
1103
+ new RunProperties(new FontSize { Val = "18" }),
1104
+ new FieldChar { FieldCharType = FieldCharValues.Begin }
1105
+ ));
1106
+ para.Append(new Run(
1107
+ new RunProperties(new FontSize { Val = "18" }),
1108
+ new FieldCode(" PAGE ") { Space = SpaceProcessingModeValues.Preserve }
1109
+ ));
1110
+ para.Append(new Run(
1111
+ new RunProperties(new FontSize { Val = "18" }),
1112
+ new FieldChar { FieldCharType = FieldCharValues.End }
1113
+ ));
1114
+ }
1115
+
1116
+ header.Append(para);
1117
+ headerPart.Header = header;
1118
+ headerPart.Header.Save();
1119
+ return headerPart;
1120
+ }
1121
+ }