@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,2820 @@
1
+ # OpenXML SDK 3.x Complete Reference Encyclopedia — Part 2
2
+
3
+ **Target:** DocumentFormat.OpenXml 3.x / .NET 8+ / C# 12
4
+ **Last Updated:** 2026-03-22
5
+
6
+ This document covers page setup, tables, headers/footers, section breaks, document properties, and printing/compatibility settings. Every code block is ready to copy-paste.
7
+
8
+ ---
9
+
10
+ ## Namespace Aliases Used Throughout
11
+
12
+ ```csharp
13
+ using DocumentFormat.OpenXml;
14
+ using DocumentFormat.OpenXml.Packaging;
15
+ using DocumentFormat.OpenXml.Wordprocessing;
16
+ using A = DocumentFormat.OpenXml.Drawing;
17
+ using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
18
+ using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Table of Contents
24
+
25
+ 1. [Page Setup](#1-page-setup)
26
+ 2. [Tables — Comprehensive](#2-tables--comprehensive)
27
+ 3. [Headers, Footers & Page Numbers](#3-headers-footers--page-numbers)
28
+ 4. [Section Breaks & Multi-Section](#4-section-breaks--multi-section)
29
+ 5. [Document Properties](#5-document-properties)
30
+ 6. [Printing & Compatibility Settings](#6-printing--compatibility-settings)
31
+
32
+ ---
33
+
34
+ ## 1. Page Setup
35
+
36
+ Page setup is controlled via `SectionProperties`, which is placed as the **last child element** of `Body` for the final (or only) section, or inside `ParagraphProperties` for mid-document section breaks.
37
+
38
+ ### 1.1 PageSize — Standard Paper Sizes
39
+
40
+ ```csharp
41
+ // =============================================================================
42
+ // PAGE SIZE — STANDARD PAPER SIZES
43
+ // =============================================================================
44
+ // PageSize Width and Height are specified in DXA (twentieths of a point).
45
+ // 1 inch = 1440 DXA. 1 cm ≈ 567 DXA. 1 mm ≈ 56.7 DXA.
46
+ //
47
+ // Common paper sizes (portrait orientation):
48
+ // Letter: 12240 × 15840 (8.5" × 11")
49
+ // A4: 11906 × 16838 (210mm × 297mm)
50
+ // Legal: 12240 × 20160 (8.5" × 14")
51
+ // A3: 16838 × 23811 (297mm × 420mm)
52
+ // B5: 10318 × 14570 (182mm × 257mm)
53
+ // 16K: 10318 × 14570 (approximate, varies by region)
54
+
55
+ var sectionProps = new SectionProperties();
56
+
57
+ // --- Letter (US default) ---
58
+ sectionProps.AppendChild(new PageSize
59
+ {
60
+ Width = 12240U, // 8.5 inches
61
+ Height = 15840U // 11 inches
62
+ });
63
+ // Produces XML: <w:pgSz w:w="12240" w:h="15840" />
64
+
65
+ // --- A4 (ISO default) ---
66
+ var a4Size = new PageSize
67
+ {
68
+ Width = 11906U, // 210mm
69
+ Height = 16838U // 297mm
70
+ };
71
+
72
+ // --- Legal ---
73
+ var legalSize = new PageSize
74
+ {
75
+ Width = 12240U, // 8.5 inches
76
+ Height = 20160U // 14 inches
77
+ };
78
+
79
+ // --- A3 ---
80
+ var a3Size = new PageSize
81
+ {
82
+ Width = 16838U, // 297mm
83
+ Height = 23811U // 420mm
84
+ };
85
+
86
+ body.AppendChild(sectionProps);
87
+ ```
88
+
89
+ ### 1.2 PageOrientation — CRITICAL Landscape Handling
90
+
91
+ ```csharp
92
+ // =============================================================================
93
+ // PAGE ORIENTATION — LANDSCAPE
94
+ // =============================================================================
95
+ // CRITICAL GOTCHA: Setting Orient = Landscape is NOT enough!
96
+ // You MUST ALSO swap Width and Height values. Word uses the numeric dimensions
97
+ // to determine actual page size; Orient only controls the print driver rotation.
98
+ //
99
+ // If you set Orient = Landscape but don't swap dimensions, Word will
100
+ // display portrait but print rotated — a confusing bug.
101
+
102
+ // --- Portrait (default, explicit) ---
103
+ var portraitSize = new PageSize
104
+ {
105
+ Width = 12240U,
106
+ Height = 15840U
107
+ // Orient is omitted for portrait (it's the default)
108
+ };
109
+ // Produces XML: <w:pgSz w:w="12240" w:h="15840" />
110
+
111
+ // --- Landscape — CORRECT way ---
112
+ var landscapeSize = new PageSize
113
+ {
114
+ Width = 15840U, // SWAPPED: was Height
115
+ Height = 12240U, // SWAPPED: was Width
116
+ Orient = PageOrientationValues.Landscape // AND set Orient
117
+ };
118
+ // Produces XML: <w:pgSz w:w="15840" w:h="12240" w:orient="landscape" />
119
+
120
+ // --- Helper method for safe orientation switching ---
121
+ static PageSize CreatePageSize(uint shortEdge, uint longEdge, bool landscape)
122
+ {
123
+ return landscape
124
+ ? new PageSize
125
+ {
126
+ Width = longEdge, // Long edge becomes width
127
+ Height = shortEdge, // Short edge becomes height
128
+ Orient = PageOrientationValues.Landscape
129
+ }
130
+ : new PageSize
131
+ {
132
+ Width = shortEdge,
133
+ Height = longEdge
134
+ };
135
+ }
136
+
137
+ // Usage:
138
+ var letterLandscape = CreatePageSize(12240, 15840, landscape: true);
139
+ var a4Portrait = CreatePageSize(11906, 16838, landscape: false);
140
+ ```
141
+
142
+ ### 1.3 PageMargin — Common Presets
143
+
144
+ ```csharp
145
+ // =============================================================================
146
+ // PAGE MARGIN — ALL PROPERTIES
147
+ // =============================================================================
148
+ // All margin values are in DXA (twentieths of a point). 1 inch = 1440 DXA.
149
+ //
150
+ // Properties:
151
+ // Top, Bottom — signed Int32 (can be negative for overlap)
152
+ // Left, Right — unsigned UInt32
153
+ // Header, Footer — unsigned UInt32 (distance from page edge to header/footer)
154
+ // Gutter — unsigned UInt32 (extra margin for binding; added to Left
155
+ // unless GutterAtTop is set in Settings)
156
+
157
+ // --- Normal / Standard (1" all around) ---
158
+ var normalMargins = new PageMargin
159
+ {
160
+ Top = 1440, // 1 inch
161
+ Bottom = 1440, // 1 inch
162
+ Left = 1440U, // 1 inch
163
+ Right = 1440U, // 1 inch
164
+ Header = 720U, // 0.5 inch (distance from page edge)
165
+ Footer = 720U, // 0.5 inch
166
+ Gutter = 0U // No binding gutter
167
+ };
168
+ // Produces XML:
169
+ // <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"
170
+ // w:header="720" w:footer="720" w:gutter="0" />
171
+
172
+ // --- Narrow (0.5" all around) ---
173
+ var narrowMargins = new PageMargin
174
+ {
175
+ Top = 720,
176
+ Bottom = 720,
177
+ Left = 720U,
178
+ Right = 720U,
179
+ Header = 720U,
180
+ Footer = 720U,
181
+ Gutter = 0U
182
+ };
183
+
184
+ // --- Moderate (1" top/bottom, 0.75" left/right) ---
185
+ var moderateMargins = new PageMargin
186
+ {
187
+ Top = 1440,
188
+ Bottom = 1440,
189
+ Left = 1080U, // 0.75 inch
190
+ Right = 1080U, // 0.75 inch
191
+ Header = 720U,
192
+ Footer = 720U,
193
+ Gutter = 0U
194
+ };
195
+
196
+ // --- Wide (1" top/bottom, 2" left/right) ---
197
+ var wideMargins = new PageMargin
198
+ {
199
+ Top = 1440,
200
+ Bottom = 1440,
201
+ Left = 2880U, // 2 inches
202
+ Right = 2880U, // 2 inches
203
+ Header = 720U,
204
+ Footer = 720U,
205
+ Gutter = 0U
206
+ };
207
+
208
+ // --- Chinese Government Document 公文 standard (GB/T 9704-2012) ---
209
+ // Top: 37mm (2098 DXA), Bottom: 35mm (1984 DXA)
210
+ // Left: 28mm (1588 DXA), Right: 26mm (1474 DXA)
211
+ var chineseGovMargins = new PageMargin
212
+ {
213
+ Top = 2098, // 37mm
214
+ Bottom = 1984, // 35mm
215
+ Left = 1588U, // 28mm
216
+ Right = 1474U, // 26mm
217
+ Header = 851U, // 15mm
218
+ Footer = 567U, // 10mm (approx)
219
+ Gutter = 0U
220
+ };
221
+
222
+ // --- With binding gutter (e.g., for book printing) ---
223
+ var gutterMargins = new PageMargin
224
+ {
225
+ Top = 1440,
226
+ Bottom = 1440,
227
+ Left = 1440U,
228
+ Right = 1440U,
229
+ Header = 720U,
230
+ Footer = 720U,
231
+ Gutter = 720U // 0.5 inch added to left margin for binding
232
+ };
233
+ ```
234
+
235
+ ### 1.4 PageBorders
236
+
237
+ ```csharp
238
+ // =============================================================================
239
+ // PAGE BORDERS
240
+ // =============================================================================
241
+ // PageBorders defines borders around the entire page.
242
+ // OffsetFrom controls whether border distance is from page edge or text margin.
243
+ // PageBorderOffsetValues.Page = from page edge
244
+ // PageBorderOffsetValues.Text = from text margin
245
+ //
246
+ // Each border: Val (style), Size (eighth-points: 4=0.5pt, 8=1pt, 12=1.5pt),
247
+ // Color (hex RGB), Space (distance in points from text/page edge)
248
+
249
+ var pageBorders = new PageBorders
250
+ {
251
+ OffsetFrom = PageBorderOffsetValues.Page
252
+ };
253
+
254
+ // Top border: single line, 1pt, black
255
+ pageBorders.AppendChild(new TopBorder
256
+ {
257
+ Val = BorderValues.Single,
258
+ Size = 8U, // 8 eighth-points = 1pt
259
+ Color = "000000",
260
+ Space = 24U // 24 points from page edge
261
+ });
262
+
263
+ // Bottom border
264
+ pageBorders.AppendChild(new BottomBorder
265
+ {
266
+ Val = BorderValues.Single,
267
+ Size = 8U,
268
+ Color = "000000",
269
+ Space = 24U
270
+ });
271
+
272
+ // Left border
273
+ pageBorders.AppendChild(new LeftBorder
274
+ {
275
+ Val = BorderValues.Single,
276
+ Size = 8U,
277
+ Color = "000000",
278
+ Space = 24U
279
+ });
280
+
281
+ // Right border
282
+ pageBorders.AppendChild(new RightBorder
283
+ {
284
+ Val = BorderValues.Single,
285
+ Size = 8U,
286
+ Color = "000000",
287
+ Space = 24U
288
+ });
289
+
290
+ // --- Double border example ---
291
+ var doubleBorder = new TopBorder
292
+ {
293
+ Val = BorderValues.Double, // Double line
294
+ Size = 4U, // 0.5pt per line
295
+ Color = "0000FF", // Blue
296
+ Space = 24U
297
+ };
298
+
299
+ // --- Common BorderValues ---
300
+ // Single, Double, Triple, DotDash, Dashed, Dotted, Thick, ThinThickSmallGap,
301
+ // ThickThinSmallGap, Wave, DoubleWave, BasicBlackDots, None
302
+
303
+ sectionProps.AppendChild(pageBorders);
304
+ ```
305
+
306
+ ### 1.5 Columns — Multi-Column Layout
307
+
308
+ ```csharp
309
+ // =============================================================================
310
+ // COLUMNS — MULTI-COLUMN LAYOUTS
311
+ // =============================================================================
312
+ // Columns element defines the column layout within a section.
313
+ // Space is measured in DXA. EqualWidth=true makes all columns equal.
314
+
315
+ // --- 2 equal columns ---
316
+ var twoCols = new Columns
317
+ {
318
+ EqualWidth = true,
319
+ ColumnCount = 2,
320
+ Space = "720" // 0.5 inch gap between columns
321
+ };
322
+ // Produces XML: <w:cols w:num="2" w:space="720" w:equalWidth="1" />
323
+
324
+ // --- 3 equal columns with separator ---
325
+ var threeColsSep = new Columns
326
+ {
327
+ EqualWidth = true,
328
+ ColumnCount = 3,
329
+ Space = "360", // 0.25 inch gap
330
+ Separator = true // Vertical line between columns
331
+ };
332
+ // Produces XML: <w:cols w:num="3" w:space="360" w:equalWidth="1" w:sep="1" />
333
+
334
+ // --- Custom unequal columns (e.g., 2/3 + 1/3 of content width) ---
335
+ // When using unequal widths, EqualWidth must be false and you define
336
+ // each column explicitly with Column elements.
337
+ // For Letter page with 1" margins: content width = 12240 - 1440 - 1440 = 9360 DXA
338
+ // Column 1: 6000 DXA wide, 360 DXA space after
339
+ // Column 2: 3000 DXA wide (6000 + 360 + 3000 = 9360)
340
+
341
+ var unequalCols = new Columns { EqualWidth = false };
342
+ unequalCols.AppendChild(new Column
343
+ {
344
+ Width = "6000",
345
+ Space = "360"
346
+ });
347
+ unequalCols.AppendChild(new Column
348
+ {
349
+ Width = "3000"
350
+ // No Space on last column
351
+ });
352
+ // Produces XML:
353
+ // <w:cols w:equalWidth="0">
354
+ // <w:col w:w="6000" w:space="360" />
355
+ // <w:col w:w="3000" />
356
+ // </w:cols>
357
+
358
+ sectionProps.AppendChild(unequalCols);
359
+ ```
360
+
361
+ ### 1.6 LineNumbering
362
+
363
+ ```csharp
364
+ // =============================================================================
365
+ // LINE NUMBERING
366
+ // =============================================================================
367
+ // LineNumbering adds line numbers in the margin. Useful for legal/academic docs.
368
+ // CountBy = show every Nth number (1 = every line, 5 = every 5th)
369
+ // Start = starting number
370
+ // Distance = distance from text in DXA
371
+ // Restart: NewPage, NewSection, Continuous
372
+
373
+ var lineNums = new LineNumbering
374
+ {
375
+ CountBy = 5, // Show every 5th line number
376
+ Start = 1, // Start at line 1
377
+ Distance = 360U, // 0.25 inch from text
378
+ Restart = LineNumberRestartValues.NewPage // Restart each page
379
+ };
380
+ // Produces XML:
381
+ // <w:lnNumType w:countBy="5" w:start="1" w:distance="360" w:restart="newPage" />
382
+
383
+ sectionProps.AppendChild(lineNums);
384
+ ```
385
+
386
+ ### 1.7 DocGrid — CJK Document Grid
387
+
388
+ ```csharp
389
+ // =============================================================================
390
+ // DOCUMENT GRID — CJK LAYOUT
391
+ // =============================================================================
392
+ // DocGrid specifies a document grid (character grid) primarily for CJK documents.
393
+ // Type: Default (no grid), Lines (line grid), LinesAndChars (line+char grid),
394
+ // SnapToChars (snap to character grid)
395
+ // LinePitch = distance between lines in DXA (e.g., 312 for standard Chinese docs)
396
+ // CharacterSpace = extra spacing between characters in DXA
397
+
398
+ // --- Chinese document grid: 28 lines × 28 chars per line (common for 公文) ---
399
+ var cjkGrid = new DocGrid
400
+ {
401
+ Type = DocGridValues.LinesAndChars,
402
+ LinePitch = 579, // DXA between lines (≈ 28 lines on A4 with std margins)
403
+ CharacterSpace = 0 // Default character spacing
404
+ };
405
+ // Produces XML:
406
+ // <w:docGrid w:type="linesAndChars" w:linePitch="579" w:charSpace="0" />
407
+
408
+ // --- Simple line-only grid ---
409
+ var lineGrid = new DocGrid
410
+ {
411
+ Type = DocGridValues.Lines,
412
+ LinePitch = 360 // Standard line pitch
413
+ };
414
+
415
+ sectionProps.AppendChild(cjkGrid);
416
+ ```
417
+
418
+ ### 1.8 VerticalTextAlignmentOnPage
419
+
420
+ ```csharp
421
+ // =============================================================================
422
+ // VERTICAL TEXT ALIGNMENT ON PAGE
423
+ // =============================================================================
424
+ // Controls vertical alignment of text within the page (above bottom margin).
425
+ // Values: Top (default), Center, Both (justified), Bottom
426
+
427
+ var vertAlign = new VerticalTextAlignmentOnPage
428
+ {
429
+ Val = VerticalJustificationValues.Center
430
+ };
431
+ // Produces XML: <w:vAlign w:val="center" />
432
+ // Use case: Title pages, certificate pages
433
+
434
+ sectionProps.AppendChild(vertAlign);
435
+ ```
436
+
437
+ ### 1.9 Complete Page Setup Example
438
+
439
+ ```csharp
440
+ // =============================================================================
441
+ // COMPLETE PAGE SETUP — PUTTING IT ALL TOGETHER
442
+ // =============================================================================
443
+ // A4 portrait, moderate margins, 2-column layout with separator
444
+
445
+ using var doc = WordprocessingDocument.Create(
446
+ "PageSetupDemo.docx", WordprocessingDocumentType.Document);
447
+
448
+ var mainPart = doc.MainDocumentPart!;
449
+ var body = mainPart.Document.Body!;
450
+
451
+ // Add content paragraphs ...
452
+ body.AppendChild(new Paragraph(
453
+ new Run(new Text("This is a two-column document on A4 paper."))));
454
+
455
+ // Section properties — MUST be last child of Body
456
+ var sectPr = new SectionProperties();
457
+
458
+ // Page size: A4 portrait
459
+ sectPr.AppendChild(new PageSize
460
+ {
461
+ Width = 11906U,
462
+ Height = 16838U
463
+ });
464
+
465
+ // Margins: moderate
466
+ sectPr.AppendChild(new PageMargin
467
+ {
468
+ Top = 1440, Bottom = 1440,
469
+ Left = 1080U, Right = 1080U,
470
+ Header = 720U, Footer = 720U, Gutter = 0U
471
+ });
472
+
473
+ // 2-column with separator
474
+ sectPr.AppendChild(new Columns
475
+ {
476
+ EqualWidth = true,
477
+ ColumnCount = 2,
478
+ Space = "720",
479
+ Separator = true
480
+ });
481
+
482
+ // Line grid for CJK
483
+ sectPr.AppendChild(new DocGrid
484
+ {
485
+ Type = DocGridValues.Lines,
486
+ LinePitch = 312
487
+ });
488
+
489
+ body.AppendChild(sectPr);
490
+ mainPart.Document.Save();
491
+ ```
492
+
493
+ ---
494
+
495
+ ## 2. Tables — Comprehensive
496
+
497
+ ### 2.1 TableProperties — Width, Layout, Alignment, Indent
498
+
499
+ ```csharp
500
+ // =============================================================================
501
+ // TABLE PROPERTIES — WIDTH, LAYOUT, ALIGNMENT
502
+ // =============================================================================
503
+ // Table width can be specified in three ways:
504
+ // Pct: percentage of page width. 5000 = 100%. (multiply % by 50)
505
+ // Dxa: absolute width in DXA (twentieths of a point). 1 inch = 1440 DXA.
506
+ // Auto: table auto-sizes to content.
507
+ //
508
+ // TableLayout:
509
+ // Fixed: columns maintain exact widths. Required for complex cell sizing.
510
+ // Autofit: columns adjust to content (default).
511
+ //
512
+ // TableJustification: Left (default), Center, Right
513
+
514
+ var table = new Table();
515
+
516
+ var tblProps = new TableProperties();
517
+
518
+ // --- Width: 100% of page ---
519
+ tblProps.AppendChild(new TableWidth
520
+ {
521
+ Width = "5000", // 5000 = 100%
522
+ Type = TableWidthUnitValues.Pct
523
+ });
524
+ // Produces XML: <w:tblW w:w="5000" w:type="pct" />
525
+
526
+ // --- Width: fixed DXA ---
527
+ // var tblWidth = new TableWidth { Width = "9360", Type = TableWidthUnitValues.Dxa };
528
+
529
+ // --- Width: auto ---
530
+ // var tblWidth = new TableWidth { Width = "0", Type = TableWidthUnitValues.Auto };
531
+
532
+ // Layout: fixed column widths
533
+ tblProps.AppendChild(new TableLayout
534
+ {
535
+ Type = TableLayoutValues.Fixed
536
+ });
537
+
538
+ // Center the table on the page
539
+ tblProps.AppendChild(new TableJustification
540
+ {
541
+ Val = TableRowAlignmentValues.Center
542
+ });
543
+
544
+ // Table indent (left offset when not centered) — in DXA
545
+ // tblProps.AppendChild(new TableIndentation
546
+ // {
547
+ // Width = 720, // 0.5 inch indent
548
+ // Type = TableWidthUnitValues.Dxa
549
+ // });
550
+
551
+ table.AppendChild(tblProps);
552
+ ```
553
+
554
+ ### 2.2 TableBorders — All Border Properties
555
+
556
+ ```csharp
557
+ // =============================================================================
558
+ // TABLE BORDERS
559
+ // =============================================================================
560
+ // TableBorders defines default borders for the entire table.
561
+ // Each border has:
562
+ // Val — BorderValues enum (Single, Double, Dotted, Dashed, None, etc.)
563
+ // Size — in eighth-points: 4 = 0.5pt, 8 = 1pt, 12 = 1.5pt, 16 = 2pt, 24 = 3pt
564
+ // Color — hex RGB string (e.g., "000000" for black, "FF0000" for red)
565
+ // Space — space between border and content in points
566
+ //
567
+ // Border types: TopBorder, BottomBorder, LeftBorder, RightBorder,
568
+ // InsideHorizontalBorder, InsideVerticalBorder
569
+
570
+ var tblBorders = new TableBorders();
571
+
572
+ // Top border: single, 1pt, black
573
+ tblBorders.AppendChild(new TopBorder
574
+ {
575
+ Val = BorderValues.Single,
576
+ Size = 8U, // 1pt (8 eighth-points)
577
+ Color = "000000",
578
+ Space = 0U
579
+ });
580
+
581
+ // Bottom border
582
+ tblBorders.AppendChild(new BottomBorder
583
+ {
584
+ Val = BorderValues.Single,
585
+ Size = 8U,
586
+ Color = "000000",
587
+ Space = 0U
588
+ });
589
+
590
+ // Left border
591
+ tblBorders.AppendChild(new LeftBorder
592
+ {
593
+ Val = BorderValues.Single,
594
+ Size = 8U,
595
+ Color = "000000",
596
+ Space = 0U
597
+ });
598
+
599
+ // Right border
600
+ tblBorders.AppendChild(new RightBorder
601
+ {
602
+ Val = BorderValues.Single,
603
+ Size = 8U,
604
+ Color = "000000",
605
+ Space = 0U
606
+ });
607
+
608
+ // Inside horizontal borders (between rows)
609
+ tblBorders.AppendChild(new InsideHorizontalBorder
610
+ {
611
+ Val = BorderValues.Single,
612
+ Size = 4U, // 0.5pt — thinner than outer borders
613
+ Color = "000000",
614
+ Space = 0U
615
+ });
616
+
617
+ // Inside vertical borders (between columns)
618
+ tblBorders.AppendChild(new InsideVerticalBorder
619
+ {
620
+ Val = BorderValues.Single,
621
+ Size = 4U,
622
+ Color = "000000",
623
+ Space = 0U
624
+ });
625
+
626
+ // Produces XML:
627
+ // <w:tblBorders>
628
+ // <w:top w:val="single" w:sz="8" w:color="000000" w:space="0" />
629
+ // <w:bottom w:val="single" w:sz="8" w:color="000000" w:space="0" />
630
+ // <w:left w:val="single" w:sz="8" w:color="000000" w:space="0" />
631
+ // <w:right w:val="single" w:sz="8" w:color="000000" w:space="0" />
632
+ // <w:insideH w:val="single" w:sz="4" w:color="000000" w:space="0" />
633
+ // <w:insideV w:val="single" w:sz="4" w:color="000000" w:space="0" />
634
+ // </w:tblBorders>
635
+
636
+ tblProps.AppendChild(tblBorders);
637
+ ```
638
+
639
+ ### 2.3 TableGrid — Column Definitions
640
+
641
+ ```csharp
642
+ // =============================================================================
643
+ // TABLE GRID — COLUMN WIDTH DEFINITIONS
644
+ // =============================================================================
645
+ // TableGrid defines the column structure of the table. Each GridColumn
646
+ // specifies the width in DXA. The number of GridColumn elements determines
647
+ // the number of columns.
648
+ //
649
+ // IMPORTANT: GridColumn widths should sum to the table width.
650
+ // For a 100% table on Letter with 1" margins: 12240 - 1440 - 1440 = 9360 DXA
651
+
652
+ var tableGrid = new TableGrid();
653
+
654
+ // 3 columns: 3000 + 3000 + 3360 = 9360 DXA
655
+ tableGrid.AppendChild(new GridColumn { Width = "3000" });
656
+ tableGrid.AppendChild(new GridColumn { Width = "3000" });
657
+ tableGrid.AppendChild(new GridColumn { Width = "3360" });
658
+
659
+ // Produces XML:
660
+ // <w:tblGrid>
661
+ // <w:gridCol w:w="3000" />
662
+ // <w:gridCol w:w="3000" />
663
+ // <w:gridCol w:w="3360" />
664
+ // </w:tblGrid>
665
+
666
+ table.AppendChild(tableGrid);
667
+ ```
668
+
669
+ ### 2.4 TableCellProperties — Width, Alignment, Direction, Shading
670
+
671
+ ```csharp
672
+ // =============================================================================
673
+ // TABLE CELL PROPERTIES
674
+ // =============================================================================
675
+ // TableCellProperties controls individual cell appearance.
676
+
677
+ var cellProps = new TableCellProperties();
678
+
679
+ // Cell width — should match the GridColumn width
680
+ cellProps.AppendChild(new TableCellWidth
681
+ {
682
+ Width = "3000",
683
+ Type = TableWidthUnitValues.Dxa
684
+ });
685
+
686
+ // Vertical alignment within cell: Top (default), Center, Bottom
687
+ cellProps.AppendChild(new TableCellVerticalAlignment
688
+ {
689
+ Val = TableVerticalAlignmentValues.Center
690
+ });
691
+
692
+ // Text direction (for vertical text in CJK, etc.)
693
+ // Values: LefToRight (default), TopToBottom (text rotated 90° CW),
694
+ // TopToBottomV (vertical CJK), BottomToTopV
695
+ cellProps.AppendChild(new TextDirection
696
+ {
697
+ Val = TextDirectionValues.TopToBottom
698
+ });
699
+
700
+ // NoWrap — prevents text from wrapping within the cell
701
+ cellProps.AppendChild(new NoWrap());
702
+
703
+ // Cell shading (background color)
704
+ cellProps.AppendChild(new Shading
705
+ {
706
+ Val = ShadingPatternValues.Clear,
707
+ Color = "auto",
708
+ Fill = "D9E2F3" // Light blue background
709
+ });
710
+ // Produces XML: <w:shd w:val="clear" w:color="auto" w:fill="D9E2F3" />
711
+ ```
712
+
713
+ ### 2.5 TableCellMargin — Table-Level Default vs Per-Cell Override
714
+
715
+ ```csharp
716
+ // =============================================================================
717
+ // TABLE CELL MARGINS
718
+ // =============================================================================
719
+ // There are TWO levels of cell margin control:
720
+ // 1. Table-level default: TableCellMarginDefault (inside TableProperties)
721
+ // 2. Per-cell override: TableCellMargin (inside TableCellProperties)
722
+ //
723
+ // All values are in DXA. Default Word cell margins are approximately:
724
+ // Top: 0, Bottom: 0, Left: 108 (0.075"), Right: 108
725
+
726
+ // --- Table-level default margins ---
727
+ var defaultMargins = new TableCellMarginDefault();
728
+ defaultMargins.AppendChild(new TopMargin
729
+ {
730
+ Width = "72", // ~0.05 inch
731
+ Type = TableWidthUnitValues.Dxa
732
+ });
733
+ defaultMargins.AppendChild(new BottomMargin
734
+ {
735
+ Width = "72",
736
+ Type = TableWidthUnitValues.Dxa
737
+ });
738
+ defaultMargins.AppendChild(new StartMargin
739
+ {
740
+ Width = "108", // ~0.075 inch (default)
741
+ Type = TableWidthUnitValues.Dxa
742
+ });
743
+ defaultMargins.AppendChild(new EndMargin
744
+ {
745
+ Width = "108",
746
+ Type = TableWidthUnitValues.Dxa
747
+ });
748
+
749
+ tblProps.AppendChild(defaultMargins);
750
+ // Produces XML:
751
+ // <w:tblCellMar>
752
+ // <w:top w:w="72" w:type="dxa" />
753
+ // <w:bottom w:w="72" w:type="dxa" />
754
+ // <w:start w:w="108" w:type="dxa" />
755
+ // <w:end w:w="108" w:type="dxa" />
756
+ // </w:tblCellMar>
757
+
758
+ // --- Per-cell override (larger padding for a specific cell) ---
759
+ var cellMarginOverride = new TableCellMargin();
760
+ cellMarginOverride.AppendChild(new TopMargin
761
+ {
762
+ Width = "144", // 0.1 inch
763
+ Type = TableWidthUnitValues.Dxa
764
+ });
765
+ cellMarginOverride.AppendChild(new BottomMargin
766
+ {
767
+ Width = "144",
768
+ Type = TableWidthUnitValues.Dxa
769
+ });
770
+ cellMarginOverride.AppendChild(new StartMargin
771
+ {
772
+ Width = "216", // 0.15 inch
773
+ Type = TableWidthUnitValues.Dxa
774
+ });
775
+ cellMarginOverride.AppendChild(new EndMargin
776
+ {
777
+ Width = "216",
778
+ Type = TableWidthUnitValues.Dxa
779
+ });
780
+
781
+ cellProps.AppendChild(cellMarginOverride);
782
+ ```
783
+
784
+ ### 2.6 Row Height
785
+
786
+ ```csharp
787
+ // =============================================================================
788
+ // TABLE ROW HEIGHT
789
+ // =============================================================================
790
+ // TableRowHeight is set inside TableRowProperties.
791
+ // Val = height in DXA
792
+ // HeightRuleType:
793
+ // Exact: row is exactly this height (content may be clipped)
794
+ // AtLeast: row is at least this height, grows for content (default behavior)
795
+ // Auto: height determined by content
796
+
797
+ var rowProps = new TableRowProperties();
798
+
799
+ // Row height: at least 0.5 inch
800
+ rowProps.AppendChild(new TableRowHeight
801
+ {
802
+ Val = 720U, // 0.5 inch in DXA
803
+ HeightRule = HeightRuleValues.AtLeast
804
+ });
805
+ // Produces XML: <w:trHeight w:val="720" w:hRule="atLeast" />
806
+
807
+ // Exact height (content may clip):
808
+ // rowProps.AppendChild(new TableRowHeight
809
+ // {
810
+ // Val = 720U,
811
+ // HeightRule = HeightRuleValues.Exact
812
+ // });
813
+
814
+ var row = new TableRow();
815
+ row.AppendChild(rowProps);
816
+ ```
817
+
818
+ ### 2.7 Header Row Repeat (Repeat on Every Page)
819
+
820
+ ```csharp
821
+ // =============================================================================
822
+ // HEADER ROW REPEAT
823
+ // =============================================================================
824
+ // TableHeader on TableRowProperties marks a row to repeat at the top
825
+ // of each page when the table spans multiple pages.
826
+ // IMPORTANT: Only works for rows at the TOP of the table (contiguous from first row).
827
+ // You cannot repeat a row in the middle of a table.
828
+
829
+ var headerRowProps = new TableRowProperties();
830
+ headerRowProps.AppendChild(new TableHeader()); // No value needed — presence = true
831
+
832
+ // Produces XML:
833
+ // <w:trPr>
834
+ // <w:tblHeader />
835
+ // </w:trPr>
836
+
837
+ var headerRow = new TableRow();
838
+ headerRow.AppendChild(headerRowProps);
839
+ // ... add cells to headerRow ...
840
+ ```
841
+
842
+ ### 2.8 Per-Cell Border Override
843
+
844
+ ```csharp
845
+ // =============================================================================
846
+ // PER-CELL BORDER OVERRIDE
847
+ // =============================================================================
848
+ // TableCellBorders inside TableCellProperties overrides table-level borders
849
+ // for a specific cell. Useful for special formatting, merging visual areas, etc.
850
+
851
+ var cellBorders = new TableCellBorders();
852
+
853
+ // Remove bottom border on this cell
854
+ cellBorders.AppendChild(new BottomBorder
855
+ {
856
+ Val = BorderValues.None,
857
+ Size = 0U,
858
+ Color = "auto",
859
+ Space = 0U
860
+ });
861
+
862
+ // Add thick right border
863
+ cellBorders.AppendChild(new RightBorder
864
+ {
865
+ Val = BorderValues.Single,
866
+ Size = 24U, // 3pt thick
867
+ Color = "FF0000", // Red
868
+ Space = 0U
869
+ });
870
+
871
+ // Produces XML:
872
+ // <w:tcBorders>
873
+ // <w:bottom w:val="none" w:sz="0" w:color="auto" w:space="0" />
874
+ // <w:right w:val="single" w:sz="24" w:color="FF0000" w:space="0" />
875
+ // </w:tcBorders>
876
+
877
+ cellProps.AppendChild(cellBorders);
878
+ ```
879
+
880
+ ### 2.9 Horizontal Merge (GridSpan)
881
+
882
+ ```csharp
883
+ // =============================================================================
884
+ // HORIZONTAL MERGE — GRIDSPAN
885
+ // =============================================================================
886
+ // To merge cells horizontally, use GridSpan on the first cell's properties.
887
+ // The cell spans across multiple grid columns. You do NOT add extra cells
888
+ // for the spanned columns — only one cell covers the span.
889
+ //
890
+ // Example: 3-column table, first row merges columns 1+2
891
+
892
+ var mergedRow = new TableRow();
893
+
894
+ // Cell spanning columns 1 and 2
895
+ var spanCell = new TableCell();
896
+ var spanCellProps = new TableCellProperties();
897
+ spanCellProps.AppendChild(new GridSpan { Val = 2 }); // Span 2 columns
898
+ spanCellProps.AppendChild(new TableCellWidth
899
+ {
900
+ Width = "6000", // Combined width: 3000 + 3000
901
+ Type = TableWidthUnitValues.Dxa
902
+ });
903
+ spanCell.AppendChild(spanCellProps);
904
+ spanCell.AppendChild(new Paragraph(new Run(new Text("Spans columns 1-2"))));
905
+ mergedRow.AppendChild(spanCell);
906
+
907
+ // Cell in column 3 (normal)
908
+ var normalCell = new TableCell();
909
+ normalCell.AppendChild(new TableCellProperties(
910
+ new TableCellWidth { Width = "3360", Type = TableWidthUnitValues.Dxa }));
911
+ normalCell.AppendChild(new Paragraph(new Run(new Text("Column 3"))));
912
+ mergedRow.AppendChild(normalCell);
913
+
914
+ // Produces XML for the merged cell:
915
+ // <w:tc>
916
+ // <w:tcPr>
917
+ // <w:gridSpan w:val="2" />
918
+ // <w:tcW w:w="6000" w:type="dxa" />
919
+ // </w:tcPr>
920
+ // <w:p><w:r><w:t>Spans columns 1-2</w:t></w:r></w:p>
921
+ // </w:tc>
922
+ ```
923
+
924
+ ### 2.10 Vertical Merge
925
+
926
+ ```csharp
927
+ // =============================================================================
928
+ // VERTICAL MERGE
929
+ // =============================================================================
930
+ // To merge cells vertically across rows, use VerticalMerge:
931
+ // First row: VerticalMerge with Val = Restart (starts the merge)
932
+ // Subsequent rows: VerticalMerge with Val = Continue (or omit Val — Continue is default)
933
+ //
934
+ // Each row still needs the cell placeholder, but continue cells should contain
935
+ // an empty paragraph only.
936
+
937
+ // Row 1: start of vertical merge
938
+ var vRow1 = new TableRow();
939
+ var vCell1 = new TableCell();
940
+ var vCellProps1 = new TableCellProperties();
941
+ vCellProps1.AppendChild(new VerticalMerge { Val = MergedCellValues.Restart });
942
+ vCellProps1.AppendChild(new TableCellWidth { Width = "3000", Type = TableWidthUnitValues.Dxa });
943
+ vCell1.AppendChild(vCellProps1);
944
+ vCell1.AppendChild(new Paragraph(new Run(new Text("Merged vertically"))));
945
+ vRow1.AppendChild(vCell1);
946
+ // ... add remaining cells in row 1
947
+
948
+ // Row 2: continue the vertical merge
949
+ var vRow2 = new TableRow();
950
+ var vCell2 = new TableCell();
951
+ var vCellProps2 = new TableCellProperties();
952
+ vCellProps2.AppendChild(new VerticalMerge()); // Val omitted = Continue
953
+ vCellProps2.AppendChild(new TableCellWidth { Width = "3000", Type = TableWidthUnitValues.Dxa });
954
+ vCell2.AppendChild(vCellProps2);
955
+ vCell2.AppendChild(new Paragraph()); // Empty paragraph required — cell must have content
956
+ vRow2.AppendChild(vCell2);
957
+ // ... add remaining cells in row 2
958
+
959
+ // Row 3: if no VerticalMerge, the merge stops and this cell is independent.
960
+
961
+ // Produces XML:
962
+ // Row 1 cell: <w:tcPr><w:vMerge w:val="restart" /></w:tcPr>
963
+ // Row 2 cell: <w:tcPr><w:vMerge /></w:tcPr> (continue is the default)
964
+ ```
965
+
966
+ ### 2.11 Nested Tables
967
+
968
+ ```csharp
969
+ // =============================================================================
970
+ // NESTED TABLES
971
+ // =============================================================================
972
+ // A table can be nested inside a table cell. Simply add a Table element
973
+ // as a child of a TableCell (alongside the required Paragraph).
974
+ // IMPORTANT: Every TableCell MUST contain at least one Paragraph, even if
975
+ // it also contains a nested table. The Paragraph should come AFTER the table.
976
+
977
+ var outerTable = new Table();
978
+ // ... outer table properties and grid ...
979
+
980
+ var containerCell = new TableCell();
981
+ containerCell.AppendChild(new TableCellProperties(
982
+ new TableCellWidth { Width = "6000", Type = TableWidthUnitValues.Dxa }));
983
+
984
+ // Build inner (nested) table
985
+ var innerTable = new Table();
986
+ var innerProps = new TableProperties();
987
+ innerProps.AppendChild(new TableWidth { Width = "5000", Type = TableWidthUnitValues.Pct });
988
+ innerProps.AppendChild(new TableBorders(
989
+ new TopBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" },
990
+ new BottomBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" },
991
+ new LeftBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" },
992
+ new RightBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" },
993
+ new InsideHorizontalBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" },
994
+ new InsideVerticalBorder { Val = BorderValues.Single, Size = 4U, Color = "999999" }
995
+ ));
996
+ innerTable.AppendChild(innerProps);
997
+
998
+ var innerGrid = new TableGrid(
999
+ new GridColumn { Width = "2500" },
1000
+ new GridColumn { Width = "2500" });
1001
+ innerTable.AppendChild(innerGrid);
1002
+
1003
+ var innerRow = new TableRow(
1004
+ new TableCell(
1005
+ new TableCellProperties(new TableCellWidth { Width = "2500", Type = TableWidthUnitValues.Dxa }),
1006
+ new Paragraph(new Run(new Text("Inner A")))),
1007
+ new TableCell(
1008
+ new TableCellProperties(new TableCellWidth { Width = "2500", Type = TableWidthUnitValues.Dxa }),
1009
+ new Paragraph(new Run(new Text("Inner B"))))
1010
+ );
1011
+ innerTable.AppendChild(innerRow);
1012
+
1013
+ // Add inner table to container cell
1014
+ containerCell.AppendChild(innerTable);
1015
+ // MUST have a paragraph after nested table
1016
+ containerCell.AppendChild(new Paragraph());
1017
+ ```
1018
+
1019
+ ### 2.12 Table Positioning (Floating Table)
1020
+
1021
+ ```csharp
1022
+ // =============================================================================
1023
+ // TABLE POSITIONING — FLOATING TABLE
1024
+ // =============================================================================
1025
+ // TablePositionProperties makes a table "float" at a specific position
1026
+ // on the page, allowing text to wrap around it.
1027
+ // All position values are in DXA.
1028
+
1029
+ var floatProps = new TablePositionProperties
1030
+ {
1031
+ VerticalAnchor = VerticalAnchorValues.Page,
1032
+ HorizontalAnchor = HorizontalAnchorValues.Page,
1033
+ TablePositionX = 2880, // 2 inches from left page edge
1034
+ TablePositionY = 4320, // 3 inches from top page edge
1035
+ LeftFromText = 180, // 0.125 inch gap from text on left
1036
+ RightFromText = 180,
1037
+ TopFromText = 0,
1038
+ BottomFromText = 0
1039
+ };
1040
+
1041
+ tblProps.AppendChild(floatProps);
1042
+ // Produces XML:
1043
+ // <w:tblpPr w:vertAnchor="page" w:horzAnchor="page"
1044
+ // w:tblpX="2880" w:tblpY="4320"
1045
+ // w:leftFromText="180" w:rightFromText="180"
1046
+ // w:topFromText="0" w:bottomFromText="0" />
1047
+ ```
1048
+
1049
+ ### 2.13 TableLook — Conditional Formatting Flags
1050
+
1051
+ ```csharp
1052
+ // =============================================================================
1053
+ // TABLE LOOK — CONDITIONAL FORMATTING FLAGS
1054
+ // =============================================================================
1055
+ // TableLook controls which conditional formatting bands are applied from
1056
+ // the table style. These flags tell Word which "special" formatting to use.
1057
+ //
1058
+ // Val is a hex bitmask. Common values:
1059
+ // 0x04A0 = FirstRow + LastRow + NoHBand (typical for styled tables)
1060
+ // 0x0000 = no conditional formatting
1061
+ //
1062
+ // Individual boolean flags can also be set:
1063
+
1064
+ var tableLook = new TableLook
1065
+ {
1066
+ Val = "04A0",
1067
+ FirstRow = true, // Apply first-row (header) formatting
1068
+ LastRow = true, // Apply last-row (totals) formatting
1069
+ FirstColumn = false,
1070
+ LastColumn = false,
1071
+ NoHorizontalBand = true, // Don't apply horizontal banding
1072
+ NoVerticalBand = true // Don't apply vertical banding
1073
+ };
1074
+
1075
+ tblProps.AppendChild(tableLook);
1076
+ // Produces XML:
1077
+ // <w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="1"
1078
+ // w:firstColumn="0" w:lastColumn="0"
1079
+ // w:noHBand="1" w:noVBand="1" />
1080
+ ```
1081
+
1082
+ ### 2.14 Complete Styled Table — Header + Data + Totals + Zebra Striping
1083
+
1084
+ ```csharp
1085
+ // =============================================================================
1086
+ // COMPLETE STYLED TABLE
1087
+ // =============================================================================
1088
+ // Builds a professional table with:
1089
+ // - Header row (dark background, white text, repeats on page break)
1090
+ // - Data rows with alternating zebra-stripe shading
1091
+ // - Totals row (bold, top border)
1092
+ // - Full 100% width on Letter page
1093
+
1094
+ static Table CreateStyledTable(string[][] data, bool hasHeaderRow = true, bool hasTotalsRow = true)
1095
+ {
1096
+ int cols = data[0].Length;
1097
+ // For Letter page with 1" margins: 12240 - 2 * 1440 = 9360
1098
+ int totalWidth = 9360;
1099
+ int colWidth = totalWidth / cols;
1100
+
1101
+ var table = new Table();
1102
+
1103
+ // --- Table Properties ---
1104
+ var tblPr = new TableProperties(
1105
+ new TableWidth { Width = "5000", Type = TableWidthUnitValues.Pct },
1106
+ new TableLayout { Type = TableLayoutValues.Fixed },
1107
+ new TableBorders(
1108
+ new TopBorder { Val = BorderValues.Single, Size = 8U, Color = "000000" },
1109
+ new BottomBorder { Val = BorderValues.Single, Size = 8U, Color = "000000" },
1110
+ new LeftBorder { Val = BorderValues.Single, Size = 4U, Color = "BFBFBF" },
1111
+ new RightBorder { Val = BorderValues.Single, Size = 4U, Color = "BFBFBF" },
1112
+ new InsideHorizontalBorder { Val = BorderValues.Single, Size = 4U, Color = "BFBFBF" },
1113
+ new InsideVerticalBorder { Val = BorderValues.Single, Size = 4U, Color = "BFBFBF" }
1114
+ ),
1115
+ new TableLook
1116
+ {
1117
+ Val = "04A0", FirstRow = true, LastRow = true,
1118
+ FirstColumn = false, LastColumn = false,
1119
+ NoHorizontalBand = true, NoVerticalBand = true
1120
+ }
1121
+ );
1122
+ table.AppendChild(tblPr);
1123
+
1124
+ // --- Table Grid ---
1125
+ var grid = new TableGrid();
1126
+ for (int c = 0; c < cols; c++)
1127
+ {
1128
+ int w = (c == cols - 1) ? totalWidth - colWidth * (cols - 1) : colWidth;
1129
+ grid.AppendChild(new GridColumn { Width = w.ToString() });
1130
+ }
1131
+ table.AppendChild(grid);
1132
+
1133
+ // --- Rows ---
1134
+ for (int r = 0; r < data.Length; r++)
1135
+ {
1136
+ bool isHeader = hasHeaderRow && r == 0;
1137
+ bool isTotals = hasTotalsRow && r == data.Length - 1;
1138
+ bool isOddDataRow = !isHeader && !isTotals && (r % 2 == 1);
1139
+
1140
+ var row = new TableRow();
1141
+
1142
+ // Row properties
1143
+ var trPr = new TableRowProperties();
1144
+ trPr.AppendChild(new TableRowHeight
1145
+ {
1146
+ Val = isHeader ? 480U : 360U,
1147
+ HeightRule = HeightRuleValues.AtLeast
1148
+ });
1149
+ if (isHeader)
1150
+ {
1151
+ trPr.AppendChild(new TableHeader()); // Repeat header on each page
1152
+ }
1153
+ row.AppendChild(trPr);
1154
+
1155
+ // Cells
1156
+ for (int c = 0; c < cols; c++)
1157
+ {
1158
+ int w = (c == cols - 1) ? totalWidth - colWidth * (cols - 1) : colWidth;
1159
+ var cell = new TableCell();
1160
+ var tcPr = new TableCellProperties();
1161
+ tcPr.AppendChild(new TableCellWidth
1162
+ {
1163
+ Width = w.ToString(),
1164
+ Type = TableWidthUnitValues.Dxa
1165
+ });
1166
+ tcPr.AppendChild(new TableCellVerticalAlignment
1167
+ {
1168
+ Val = TableVerticalAlignmentValues.Center
1169
+ });
1170
+
1171
+ // Header: dark blue background
1172
+ if (isHeader)
1173
+ {
1174
+ tcPr.AppendChild(new Shading
1175
+ {
1176
+ Val = ShadingPatternValues.Clear,
1177
+ Color = "auto",
1178
+ Fill = "2F5496" // Dark blue
1179
+ });
1180
+ }
1181
+ // Zebra stripe: light gray on odd data rows
1182
+ else if (isOddDataRow)
1183
+ {
1184
+ tcPr.AppendChild(new Shading
1185
+ {
1186
+ Val = ShadingPatternValues.Clear,
1187
+ Color = "auto",
1188
+ Fill = "F2F2F2" // Light gray
1189
+ });
1190
+ }
1191
+ // Totals row: top border emphasis
1192
+ if (isTotals)
1193
+ {
1194
+ tcPr.AppendChild(new TableCellBorders(
1195
+ new TopBorder
1196
+ {
1197
+ Val = BorderValues.Single,
1198
+ Size = 12U, // 1.5pt
1199
+ Color = "000000"
1200
+ }
1201
+ ));
1202
+ }
1203
+ cell.AppendChild(tcPr);
1204
+
1205
+ // Paragraph with text
1206
+ var runProps = new RunProperties();
1207
+ if (isHeader)
1208
+ {
1209
+ runProps.AppendChild(new Bold());
1210
+ runProps.AppendChild(new Color { Val = "FFFFFF" }); // White text
1211
+ runProps.AppendChild(new FontSize { Val = "22" }); // 11pt
1212
+ }
1213
+ else if (isTotals)
1214
+ {
1215
+ runProps.AppendChild(new Bold());
1216
+ }
1217
+
1218
+ var para = new Paragraph(
1219
+ new ParagraphProperties(
1220
+ new Justification
1221
+ {
1222
+ Val = (c > 0) ? JustificationValues.Right : JustificationValues.Left
1223
+ }
1224
+ ),
1225
+ new Run(runProps, new Text(data[r][c]))
1226
+ );
1227
+ cell.AppendChild(para);
1228
+ row.AppendChild(cell);
1229
+ }
1230
+ table.AppendChild(row);
1231
+ }
1232
+ return table;
1233
+ }
1234
+
1235
+ // --- Usage ---
1236
+ string[][] salesData =
1237
+ [
1238
+ ["Product", "Q1", "Q2", "Q3", "Q4" ],
1239
+ ["Widget A", "1,200", "1,350", "1,100", "1,500"],
1240
+ ["Widget B", "800", "920", "870", "1,010"],
1241
+ ["Widget C", "2,100", "2,300", "2,150", "2,400"],
1242
+ ["Total", "4,100", "4,570", "4,120", "4,910"]
1243
+ ];
1244
+
1245
+ var styledTable = CreateStyledTable(salesData, hasHeaderRow: true, hasTotalsRow: true);
1246
+ body.AppendChild(styledTable);
1247
+ body.AppendChild(new Paragraph()); // Empty paragraph after table
1248
+ ```
1249
+
1250
+ ### 2.15 Three-Line Table (学术三线表)
1251
+
1252
+ ```csharp
1253
+ // =============================================================================
1254
+ // THREE-LINE TABLE (学术三线表)
1255
+ // =============================================================================
1256
+ // Academic/scientific table style common in Chinese academic publishing:
1257
+ // - Top border: THICK (1.5pt)
1258
+ // - Border below header: THIN (0.75pt)
1259
+ // - Bottom border: THICK (1.5pt)
1260
+ // - NO vertical borders, NO other horizontal borders
1261
+ //
1262
+ // This is achieved by:
1263
+ // 1. Setting table borders to None (removes all defaults)
1264
+ // 2. Using per-cell borders on the header row (bottom) and first/last rows (top/bottom)
1265
+
1266
+ static Table CreateThreeLineTable(string[] headers, string[][] rows)
1267
+ {
1268
+ int cols = headers.Length;
1269
+ int totalWidth = 9360;
1270
+ int colWidth = totalWidth / cols;
1271
+
1272
+ var table = new Table();
1273
+
1274
+ // Table properties: NO borders by default
1275
+ var tblPr = new TableProperties(
1276
+ new TableWidth { Width = "5000", Type = TableWidthUnitValues.Pct },
1277
+ new TableJustification { Val = TableRowAlignmentValues.Center },
1278
+ new TableLayout { Type = TableLayoutValues.Fixed },
1279
+ new TableBorders(
1280
+ new TopBorder { Val = BorderValues.None, Size = 0U },
1281
+ new BottomBorder { Val = BorderValues.None, Size = 0U },
1282
+ new LeftBorder { Val = BorderValues.None, Size = 0U },
1283
+ new RightBorder { Val = BorderValues.None, Size = 0U },
1284
+ new InsideHorizontalBorder { Val = BorderValues.None, Size = 0U },
1285
+ new InsideVerticalBorder { Val = BorderValues.None, Size = 0U }
1286
+ )
1287
+ );
1288
+ table.AppendChild(tblPr);
1289
+
1290
+ // Table grid
1291
+ var grid = new TableGrid();
1292
+ for (int c = 0; c < cols; c++)
1293
+ {
1294
+ int w = (c == cols - 1) ? totalWidth - colWidth * (cols - 1) : colWidth;
1295
+ grid.AppendChild(new GridColumn { Width = w.ToString() });
1296
+ }
1297
+ table.AppendChild(grid);
1298
+
1299
+ // --- Header row ---
1300
+ var headerRow = new TableRow();
1301
+ headerRow.AppendChild(new TableRowProperties(new TableHeader()));
1302
+
1303
+ for (int c = 0; c < cols; c++)
1304
+ {
1305
+ int w = (c == cols - 1) ? totalWidth - colWidth * (cols - 1) : colWidth;
1306
+ var cell = new TableCell();
1307
+ var tcPr = new TableCellProperties(
1308
+ new TableCellWidth { Width = w.ToString(), Type = TableWidthUnitValues.Dxa },
1309
+ new TableCellBorders(
1310
+ // Top: THICK line (1.5pt = 12 eighth-points)
1311
+ new TopBorder { Val = BorderValues.Single, Size = 12U, Color = "000000", Space = 0U },
1312
+ // Bottom: THIN line (0.75pt = 6 eighth-points)
1313
+ new BottomBorder { Val = BorderValues.Single, Size = 6U, Color = "000000", Space = 0U }
1314
+ ),
1315
+ new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }
1316
+ );
1317
+ cell.AppendChild(tcPr);
1318
+ cell.AppendChild(new Paragraph(
1319
+ new ParagraphProperties(
1320
+ new Justification { Val = JustificationValues.Center }),
1321
+ new Run(
1322
+ new RunProperties(new Bold()),
1323
+ new Text(headers[c]))));
1324
+ cell.AppendChild(cell); // Fix: should be row.AppendChild
1325
+ headerRow.AppendChild(cell);
1326
+ }
1327
+ table.AppendChild(headerRow);
1328
+
1329
+ // --- Data rows ---
1330
+ for (int r = 0; r < rows.Length; r++)
1331
+ {
1332
+ var dataRow = new TableRow();
1333
+ bool isLastRow = (r == rows.Length - 1);
1334
+
1335
+ for (int c = 0; c < cols; c++)
1336
+ {
1337
+ int w = (c == cols - 1) ? totalWidth - colWidth * (cols - 1) : colWidth;
1338
+ var cell = new TableCell();
1339
+ var tcPr = new TableCellProperties(
1340
+ new TableCellWidth { Width = w.ToString(), Type = TableWidthUnitValues.Dxa }
1341
+ );
1342
+
1343
+ // Last data row: add THICK bottom border
1344
+ if (isLastRow)
1345
+ {
1346
+ tcPr.AppendChild(new TableCellBorders(
1347
+ new BottomBorder
1348
+ {
1349
+ Val = BorderValues.Single,
1350
+ Size = 12U, // 1.5pt thick
1351
+ Color = "000000",
1352
+ Space = 0U
1353
+ }
1354
+ ));
1355
+ }
1356
+
1357
+ tcPr.AppendChild(new TableCellVerticalAlignment
1358
+ {
1359
+ Val = TableVerticalAlignmentValues.Center
1360
+ });
1361
+ cell.AppendChild(tcPr);
1362
+ cell.AppendChild(new Paragraph(
1363
+ new ParagraphProperties(
1364
+ new Justification { Val = JustificationValues.Center }),
1365
+ new Run(new Text(rows[r][c]))));
1366
+ dataRow.AppendChild(cell);
1367
+ }
1368
+ table.AppendChild(dataRow);
1369
+ }
1370
+
1371
+ return table;
1372
+ }
1373
+
1374
+ // --- Usage ---
1375
+ string[] columnHeaders = ["Variable", "Mean", "SD", "p-value"];
1376
+ string[][] dataRows =
1377
+ [
1378
+ ["Age", "45.2", "12.3", "0.032"],
1379
+ ["BMI", "26.8", "4.1", "0.001"],
1380
+ ["SBP", "132", "18.5", "< 0.001"],
1381
+ ["HR", "72.1", "11.2", "0.145"]
1382
+ ];
1383
+
1384
+ var threeLineTable = CreateThreeLineTable(columnHeaders, dataRows);
1385
+ body.AppendChild(threeLineTable);
1386
+ ```
1387
+
1388
+ ---
1389
+
1390
+ ## 3. Headers, Footers & Page Numbers
1391
+
1392
+ Headers and footers are stored in separate XML parts (HeaderPart, FooterPart) linked to SectionProperties via HeaderReference and FooterReference.
1393
+
1394
+ ### 3.1 Creating HeaderPart and FooterPart
1395
+
1396
+ ```csharp
1397
+ // =============================================================================
1398
+ // CREATING HEADER AND FOOTER PARTS
1399
+ // =============================================================================
1400
+ // Headers and footers are separate parts within the package, each containing
1401
+ // their own XML document tree rooted at <w:hdr> or <w:ftr>.
1402
+ // They are linked to sections via HeaderReference/FooterReference.
1403
+ //
1404
+ // Steps:
1405
+ // 1. Add a HeaderPart/FooterPart to the MainDocumentPart
1406
+ // 2. Set the part's root element (Header/Footer)
1407
+ // 3. Add content (paragraphs, tables, images) to the root element
1408
+ // 4. Create a HeaderReference/FooterReference in SectionProperties
1409
+
1410
+ var mainPart = doc.MainDocumentPart!;
1411
+
1412
+ // --- Create a header part ---
1413
+ var headerPart = mainPart.AddNewPart<HeaderPart>();
1414
+ string headerPartId = mainPart.GetIdOfPart(headerPart);
1415
+
1416
+ // Build header content
1417
+ headerPart.Header = new Header(
1418
+ new Paragraph(
1419
+ new ParagraphProperties(
1420
+ new Justification { Val = JustificationValues.Center }),
1421
+ new Run(
1422
+ new RunProperties(
1423
+ new FontSize { Val = "18" }, // 9pt — typical header size
1424
+ new Color { Val = "808080" }), // Gray
1425
+ new Text("Company Confidential"))
1426
+ )
1427
+ );
1428
+ headerPart.Header.Save();
1429
+
1430
+ // --- Create a footer part ---
1431
+ var footerPart = mainPart.AddNewPart<FooterPart>();
1432
+ string footerPartId = mainPart.GetIdOfPart(footerPart);
1433
+
1434
+ footerPart.Footer = new Footer(
1435
+ new Paragraph(
1436
+ new ParagraphProperties(
1437
+ new Justification { Val = JustificationValues.Center }),
1438
+ new Run(
1439
+ new RunProperties(new FontSize { Val = "18" }),
1440
+ new Text("Footer text here"))
1441
+ )
1442
+ );
1443
+ footerPart.Footer.Save();
1444
+ ```
1445
+
1446
+ ### 3.2 HeaderReference and FooterReference — Types
1447
+
1448
+ ```csharp
1449
+ // =============================================================================
1450
+ // HEADER/FOOTER REFERENCE — LINKING TO SECTION
1451
+ // =============================================================================
1452
+ // HeaderReference/FooterReference types:
1453
+ // Default — used on all pages (unless First/Even overrides)
1454
+ // First — used on the first page of the section (requires TitlePage)
1455
+ // Even — used on even-numbered pages (requires EvenAndOddHeaders setting)
1456
+ //
1457
+ // A section can have up to 3 headers and 3 footers (Default + First + Even).
1458
+
1459
+ var sectPr = body.Elements<SectionProperties>().FirstOrDefault()
1460
+ ?? body.AppendChild(new SectionProperties());
1461
+
1462
+ // Default header (all pages)
1463
+ sectPr.AppendChild(new HeaderReference
1464
+ {
1465
+ Type = HeaderFooterValues.Default,
1466
+ Id = headerPartId
1467
+ });
1468
+
1469
+ // Default footer (all pages)
1470
+ sectPr.AppendChild(new FooterReference
1471
+ {
1472
+ Type = HeaderFooterValues.Default,
1473
+ Id = footerPartId
1474
+ });
1475
+
1476
+ // Produces XML:
1477
+ // <w:sectPr>
1478
+ // <w:headerReference w:type="default" r:id="rId4" />
1479
+ // <w:footerReference w:type="default" r:id="rId5" />
1480
+ // </w:sectPr>
1481
+ ```
1482
+
1483
+ ### 3.3 Different First Page (TitlePage)
1484
+
1485
+ ```csharp
1486
+ // =============================================================================
1487
+ // DIFFERENT FIRST PAGE — TITLEPAGE
1488
+ // =============================================================================
1489
+ // To have a different header/footer on the first page, you must:
1490
+ // 1. Add a TitlePage element to SectionProperties
1491
+ // 2. Create separate HeaderPart/FooterPart for the first page
1492
+ // 3. Add HeaderReference/FooterReference with Type = First
1493
+
1494
+ // Enable different first page
1495
+ sectPr.AppendChild(new TitlePage());
1496
+ // Produces XML: <w:titlePg />
1497
+
1498
+ // Create first-page header (e.g., empty / no header on cover page)
1499
+ var firstHeaderPart = mainPart.AddNewPart<HeaderPart>();
1500
+ string firstHeaderId = mainPart.GetIdOfPart(firstHeaderPart);
1501
+ firstHeaderPart.Header = new Header(new Paragraph()); // Empty header
1502
+ firstHeaderPart.Header.Save();
1503
+
1504
+ // Create first-page footer
1505
+ var firstFooterPart = mainPart.AddNewPart<FooterPart>();
1506
+ string firstFooterId = mainPart.GetIdOfPart(firstFooterPart);
1507
+ firstFooterPart.Footer = new Footer(new Paragraph()); // Empty footer
1508
+ firstFooterPart.Footer.Save();
1509
+
1510
+ // Link to section
1511
+ sectPr.AppendChild(new HeaderReference
1512
+ {
1513
+ Type = HeaderFooterValues.First,
1514
+ Id = firstHeaderId
1515
+ });
1516
+ sectPr.AppendChild(new FooterReference
1517
+ {
1518
+ Type = HeaderFooterValues.First,
1519
+ Id = firstFooterId
1520
+ });
1521
+ ```
1522
+
1523
+ ### 3.4 Even and Odd Page Headers
1524
+
1525
+ ```csharp
1526
+ // =============================================================================
1527
+ // EVEN AND ODD PAGE HEADERS/FOOTERS
1528
+ // =============================================================================
1529
+ // For different headers on even vs. odd pages (e.g., book-style layout):
1530
+ // 1. Set EvenAndOddHeaders in DocumentSettingsPart
1531
+ // 2. Create separate parts for Even pages
1532
+ // 3. "Default" type becomes the ODD page header/footer
1533
+
1534
+ // Enable even/odd in Settings
1535
+ var settingsPart = mainPart.DocumentSettingsPart
1536
+ ?? mainPart.AddNewPart<DocumentSettingsPart>();
1537
+ if (settingsPart.Settings == null)
1538
+ settingsPart.Settings = new Settings();
1539
+
1540
+ settingsPart.Settings.AppendChild(new EvenAndOddHeaders());
1541
+ settingsPart.Settings.Save();
1542
+ // Produces XML in settings.xml: <w:evenAndOddHeaders />
1543
+
1544
+ // Create even-page header
1545
+ var evenHeaderPart = mainPart.AddNewPart<HeaderPart>();
1546
+ string evenHeaderId = mainPart.GetIdOfPart(evenHeaderPart);
1547
+ evenHeaderPart.Header = new Header(
1548
+ new Paragraph(
1549
+ new ParagraphProperties(
1550
+ new Justification { Val = JustificationValues.Left }),
1551
+ new Run(new Text("Chapter Title")) // Left-aligned on even pages
1552
+ )
1553
+ );
1554
+ evenHeaderPart.Header.Save();
1555
+
1556
+ // Link: "Default" = odd pages, "Even" = even pages
1557
+ sectPr.AppendChild(new HeaderReference
1558
+ {
1559
+ Type = HeaderFooterValues.Even,
1560
+ Id = evenHeaderId
1561
+ });
1562
+ // The existing Default header is now used only on odd pages.
1563
+ ```
1564
+
1565
+ ### 3.5 SimpleField — PAGE, NUMPAGES, SECTIONPAGES
1566
+
1567
+ ```csharp
1568
+ // =============================================================================
1569
+ // SIMPLE FIELDS — PAGE NUMBERS AND TOTALS
1570
+ // =============================================================================
1571
+ // SimpleField inserts a field code that Word evaluates at render time.
1572
+ // Common field codes:
1573
+ // PAGE — current page number
1574
+ // NUMPAGES — total pages in document
1575
+ // SECTIONPAGES — total pages in current section
1576
+ // DATE — current date
1577
+ // TIME — current time
1578
+ //
1579
+ // The Instruction property contains the field code string.
1580
+ // A child Run with text is used for the "cached" display value (optional but
1581
+ // recommended for non-Word renderers).
1582
+
1583
+ // --- Simple page number field ---
1584
+ var pageField = new SimpleField { Instruction = " PAGE " };
1585
+ pageField.AppendChild(new Run(new Text("1"))); // Cached display value
1586
+ // Produces XML: <w:fldSimple w:instr=" PAGE "><w:r><w:t>1</w:t></w:r></w:fldSimple>
1587
+
1588
+ // --- Total page count ---
1589
+ var totalField = new SimpleField { Instruction = " NUMPAGES " };
1590
+ totalField.AppendChild(new Run(new Text("1")));
1591
+
1592
+ // --- Section page count ---
1593
+ var sectionPagesField = new SimpleField { Instruction = " SECTIONPAGES " };
1594
+ sectionPagesField.AppendChild(new Run(new Text("1")));
1595
+ ```
1596
+
1597
+ ### 3.6 "Page X of Y" Footer
1598
+
1599
+ ```csharp
1600
+ // =============================================================================
1601
+ // "PAGE X OF Y" FOOTER
1602
+ // =============================================================================
1603
+ // Combines text runs with SimpleField elements in a single paragraph.
1604
+
1605
+ var pageXofYFooter = mainPart.AddNewPart<FooterPart>();
1606
+ string pageXofYId = mainPart.GetIdOfPart(pageXofYFooter);
1607
+
1608
+ var footerPara = new Paragraph(
1609
+ new ParagraphProperties(
1610
+ new Justification { Val = JustificationValues.Center })
1611
+ );
1612
+
1613
+ // "Page "
1614
+ footerPara.AppendChild(new Run(
1615
+ new RunProperties(new FontSize { Val = "18" }), // 9pt
1616
+ new Text("Page ") { Space = SpaceProcessingModeValues.Preserve }
1617
+ ));
1618
+
1619
+ // PAGE field
1620
+ var pgField = new SimpleField { Instruction = " PAGE " };
1621
+ pgField.AppendChild(new Run(
1622
+ new RunProperties(new FontSize { Val = "18" }),
1623
+ new Text("1")));
1624
+ footerPara.AppendChild(pgField);
1625
+
1626
+ // " of "
1627
+ footerPara.AppendChild(new Run(
1628
+ new RunProperties(new FontSize { Val = "18" }),
1629
+ new Text(" of ") { Space = SpaceProcessingModeValues.Preserve }
1630
+ ));
1631
+
1632
+ // NUMPAGES field
1633
+ var npField = new SimpleField { Instruction = " NUMPAGES " };
1634
+ npField.AppendChild(new Run(
1635
+ new RunProperties(new FontSize { Val = "18" }),
1636
+ new Text("1")));
1637
+ footerPara.AppendChild(npField);
1638
+
1639
+ pageXofYFooter.Footer = new Footer(footerPara);
1640
+ pageXofYFooter.Footer.Save();
1641
+
1642
+ // Link to section
1643
+ sectPr.AppendChild(new FooterReference
1644
+ {
1645
+ Type = HeaderFooterValues.Default,
1646
+ Id = pageXofYId
1647
+ });
1648
+ ```
1649
+
1650
+ ### 3.7 Header with Logo Image
1651
+
1652
+ ```csharp
1653
+ // =============================================================================
1654
+ // HEADER WITH LOGO IMAGE
1655
+ // =============================================================================
1656
+ // To add an image to a header:
1657
+ // 1. Add an ImagePart to the HeaderPart (not MainDocumentPart)
1658
+ // 2. Build the Drawing/Inline/Graphic elements in the header paragraph
1659
+ // 3. Image sizing uses EMUs (English Metric Units): 1 inch = 914400 EMU
1660
+
1661
+ var logoHeaderPart = mainPart.AddNewPart<HeaderPart>();
1662
+ string logoHeaderId = mainPart.GetIdOfPart(logoHeaderPart);
1663
+
1664
+ // Add image to header part
1665
+ var imagePart = logoHeaderPart.AddImagePart(ImagePartType.Png);
1666
+ using (var stream = File.OpenRead("logo.png"))
1667
+ {
1668
+ imagePart.FeedData(stream);
1669
+ }
1670
+ string imageRelId = logoHeaderPart.GetIdOfPart(imagePart);
1671
+
1672
+ // Image dimensions in EMU (e.g., 1.5 inch wide × 0.5 inch tall)
1673
+ long widthEmu = 1371600; // 1.5 * 914400
1674
+ long heightEmu = 457200; // 0.5 * 914400
1675
+
1676
+ // Build the inline drawing element
1677
+ var drawing = new Drawing(
1678
+ new DW.Inline(
1679
+ new DW.Extent { Cx = widthEmu, Cy = heightEmu },
1680
+ new DW.EffectExtent { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L },
1681
+ new DW.DocProperties { Id = 1U, Name = "Logo" },
1682
+ new DW.NonVisualGraphicFrameDrawingProperties(
1683
+ new A.GraphicFrameLocks { NoChangeAspect = true }),
1684
+ new A.Graphic(
1685
+ new A.GraphicData(
1686
+ new PIC.Picture(
1687
+ new PIC.NonVisualPictureProperties(
1688
+ new PIC.NonVisualDrawingProperties { Id = 1U, Name = "logo.png" },
1689
+ new PIC.NonVisualPictureDrawingProperties()),
1690
+ new PIC.BlipFill(
1691
+ new A.Blip { Embed = imageRelId },
1692
+ new A.Stretch(new A.FillRectangle())),
1693
+ new PIC.ShapeProperties(
1694
+ new A.Transform2D(
1695
+ new A.Offset { X = 0L, Y = 0L },
1696
+ new A.Extents { Cx = widthEmu, Cy = heightEmu }),
1697
+ new A.PresetGeometry(new A.AdjustValueList())
1698
+ { Preset = A.ShapeTypeValues.Rectangle })
1699
+ )
1700
+ ) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }
1701
+ )
1702
+ )
1703
+ {
1704
+ DistanceFromTop = 0U,
1705
+ DistanceFromBottom = 0U,
1706
+ DistanceFromLeft = 0U,
1707
+ DistanceFromRight = 0U
1708
+ }
1709
+ );
1710
+
1711
+ logoHeaderPart.Header = new Header(
1712
+ new Paragraph(new Run(drawing))
1713
+ );
1714
+ logoHeaderPart.Header.Save();
1715
+ ```
1716
+
1717
+ ### 3.8 Table-Layout Header (Logo Left, Text Center, Page Right)
1718
+
1719
+ ```csharp
1720
+ // =============================================================================
1721
+ // TABLE-LAYOUT HEADER
1722
+ // =============================================================================
1723
+ // A common professional header pattern: 3-column invisible table
1724
+ // Left cell: Company logo
1725
+ // Center cell: Document title
1726
+ // Right cell: Page number
1727
+ // The table has no borders, giving a clean three-zone layout.
1728
+
1729
+ var tblHeaderPart = mainPart.AddNewPart<HeaderPart>();
1730
+ string tblHeaderId = mainPart.GetIdOfPart(tblHeaderPart);
1731
+
1732
+ // Content width for Letter with 1" margins = 9360 DXA
1733
+ var headerTable = new Table(
1734
+ new TableProperties(
1735
+ new TableWidth { Width = "5000", Type = TableWidthUnitValues.Pct },
1736
+ new TableLayout { Type = TableLayoutValues.Fixed },
1737
+ new TableBorders(
1738
+ new TopBorder { Val = BorderValues.None },
1739
+ new BottomBorder { Val = BorderValues.Single, Size = 4U, Color = "000000" },
1740
+ new LeftBorder { Val = BorderValues.None },
1741
+ new RightBorder { Val = BorderValues.None },
1742
+ new InsideHorizontalBorder { Val = BorderValues.None },
1743
+ new InsideVerticalBorder { Val = BorderValues.None }
1744
+ )
1745
+ ),
1746
+ new TableGrid(
1747
+ new GridColumn { Width = "3120" }, // ~1/3
1748
+ new GridColumn { Width = "3120" }, // ~1/3
1749
+ new GridColumn { Width = "3120" } // ~1/3
1750
+ )
1751
+ );
1752
+
1753
+ // Left cell: logo placeholder (or image Drawing)
1754
+ var leftCell = new TableCell(
1755
+ new TableCellProperties(
1756
+ new TableCellWidth { Width = "3120", Type = TableWidthUnitValues.Dxa },
1757
+ new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }),
1758
+ new Paragraph(
1759
+ new ParagraphProperties(
1760
+ new Justification { Val = JustificationValues.Left }),
1761
+ new Run(
1762
+ new RunProperties(new Bold(), new FontSize { Val = "18" }),
1763
+ new Text("ACME Corp")))
1764
+ );
1765
+
1766
+ // Center cell: document title
1767
+ var centerCell = new TableCell(
1768
+ new TableCellProperties(
1769
+ new TableCellWidth { Width = "3120", Type = TableWidthUnitValues.Dxa },
1770
+ new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }),
1771
+ new Paragraph(
1772
+ new ParagraphProperties(
1773
+ new Justification { Val = JustificationValues.Center }),
1774
+ new Run(
1775
+ new RunProperties(new FontSize { Val = "18" }),
1776
+ new Text("Technical Specification v2.0")))
1777
+ );
1778
+
1779
+ // Right cell: page number
1780
+ var pageFieldRight = new SimpleField { Instruction = " PAGE " };
1781
+ pageFieldRight.AppendChild(new Run(
1782
+ new RunProperties(new FontSize { Val = "18" }),
1783
+ new Text("1")));
1784
+
1785
+ var rightCell = new TableCell(
1786
+ new TableCellProperties(
1787
+ new TableCellWidth { Width = "3120", Type = TableWidthUnitValues.Dxa },
1788
+ new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center }),
1789
+ new Paragraph(
1790
+ new ParagraphProperties(
1791
+ new Justification { Val = JustificationValues.Right }),
1792
+ new Run(
1793
+ new RunProperties(new FontSize { Val = "18" }),
1794
+ new Text("Page ") { Space = SpaceProcessingModeValues.Preserve }),
1795
+ pageFieldRight)
1796
+ );
1797
+
1798
+ headerTable.AppendChild(new TableRow(leftCell, centerCell, rightCell));
1799
+
1800
+ tblHeaderPart.Header = new Header(headerTable, new Paragraph());
1801
+ tblHeaderPart.Header.Save();
1802
+ ```
1803
+
1804
+ ### 3.9 Chinese Government Document Page Numbers (公文页码)
1805
+
1806
+ ```csharp
1807
+ // =============================================================================
1808
+ // CHINESE GOVERNMENT DOCUMENT PAGE NUMBERS (公文页码)
1809
+ // =============================================================================
1810
+ // Standard: bottom center, format "-X-" (em-dash surrounding page number)
1811
+ // Font: 宋体 (SimSun) 四号 (14pt = "28" half-points)
1812
+ // Per GB/T 9704-2012
1813
+
1814
+ var govFooterPart = mainPart.AddNewPart<FooterPart>();
1815
+ string govFooterId = mainPart.GetIdOfPart(govFooterPart);
1816
+
1817
+ var govFooterPara = new Paragraph(
1818
+ new ParagraphProperties(
1819
+ new Justification { Val = JustificationValues.Center })
1820
+ );
1821
+
1822
+ // Run properties for 宋体四号
1823
+ RunProperties GovPageRunProps() => new RunProperties(
1824
+ new RunFonts
1825
+ {
1826
+ Ascii = "SimSun",
1827
+ HighAnsi = "SimSun",
1828
+ EastAsia = "SimSun"
1829
+ },
1830
+ new FontSize { Val = "28" }, // 14pt = 四号
1831
+ new FontSizeComplexScript { Val = "28" }
1832
+ );
1833
+
1834
+ // "—" (em-dash before page number)
1835
+ govFooterPara.AppendChild(new Run(
1836
+ GovPageRunProps(),
1837
+ new Text("\u2014") { Space = SpaceProcessingModeValues.Preserve }
1838
+ ));
1839
+
1840
+ // PAGE field
1841
+ var govPageField = new SimpleField { Instruction = " PAGE " };
1842
+ govPageField.AppendChild(new Run(GovPageRunProps(), new Text("1")));
1843
+ govFooterPara.AppendChild(govPageField);
1844
+
1845
+ // "—" (em-dash after page number)
1846
+ govFooterPara.AppendChild(new Run(
1847
+ GovPageRunProps(),
1848
+ new Text("\u2014") { Space = SpaceProcessingModeValues.Preserve }
1849
+ ));
1850
+
1851
+ govFooterPart.Footer = new Footer(govFooterPara);
1852
+ govFooterPart.Footer.Save();
1853
+
1854
+ // Link to section
1855
+ sectPr.AppendChild(new FooterReference
1856
+ {
1857
+ Type = HeaderFooterValues.Default,
1858
+ Id = govFooterId
1859
+ });
1860
+ ```
1861
+
1862
+ ### 3.10 Multi-Section with Different Headers
1863
+
1864
+ ```csharp
1865
+ // =============================================================================
1866
+ // MULTI-SECTION WITH DIFFERENT HEADERS
1867
+ // =============================================================================
1868
+ // Each section can have its own set of header/footer parts.
1869
+ // To change headers mid-document, create a section break and attach
1870
+ // different HeaderReference/FooterReference to each SectionProperties.
1871
+ // See Section 4 for full section break mechanics.
1872
+
1873
+ // Section 1 header
1874
+ var sec1Header = mainPart.AddNewPart<HeaderPart>();
1875
+ string sec1HeaderId = mainPart.GetIdOfPart(sec1Header);
1876
+ sec1Header.Header = new Header(
1877
+ new Paragraph(new Run(new Text("Chapter 1: Introduction"))));
1878
+ sec1Header.Header.Save();
1879
+
1880
+ // Section 2 header
1881
+ var sec2Header = mainPart.AddNewPart<HeaderPart>();
1882
+ string sec2HeaderId = mainPart.GetIdOfPart(sec2Header);
1883
+ sec2Header.Header = new Header(
1884
+ new Paragraph(new Run(new Text("Chapter 2: Methods"))));
1885
+ sec2Header.Header.Save();
1886
+
1887
+ // Section 1 content + section break
1888
+ body.AppendChild(new Paragraph(new Run(new Text("Section 1 content..."))));
1889
+
1890
+ // Mid-document section properties (in last paragraph of section 1)
1891
+ var sec1Break = new Paragraph(
1892
+ new ParagraphProperties(
1893
+ new SectionProperties(
1894
+ new PageSize { Width = 12240U, Height = 15840U },
1895
+ new PageMargin
1896
+ {
1897
+ Top = 1440, Bottom = 1440,
1898
+ Left = 1440U, Right = 1440U,
1899
+ Header = 720U, Footer = 720U, Gutter = 0U
1900
+ },
1901
+ new SectionType { Val = SectionMarkValues.NextPage },
1902
+ new HeaderReference { Type = HeaderFooterValues.Default, Id = sec1HeaderId }
1903
+ )
1904
+ )
1905
+ );
1906
+ body.AppendChild(sec1Break);
1907
+
1908
+ // Section 2 content
1909
+ body.AppendChild(new Paragraph(new Run(new Text("Section 2 content..."))));
1910
+
1911
+ // Final section properties (last child of Body)
1912
+ var sec2Props = new SectionProperties(
1913
+ new PageSize { Width = 12240U, Height = 15840U },
1914
+ new PageMargin
1915
+ {
1916
+ Top = 1440, Bottom = 1440,
1917
+ Left = 1440U, Right = 1440U,
1918
+ Header = 720U, Footer = 720U, Gutter = 0U
1919
+ },
1920
+ new HeaderReference { Type = HeaderFooterValues.Default, Id = sec2HeaderId }
1921
+ );
1922
+ body.AppendChild(sec2Props);
1923
+ ```
1924
+
1925
+ ---
1926
+
1927
+ ## 4. Section Breaks & Multi-Section
1928
+
1929
+ ### 4.1 Section Properties Placement Rules
1930
+
1931
+ ```csharp
1932
+ // =============================================================================
1933
+ // SECTION PROPERTIES PLACEMENT
1934
+ // =============================================================================
1935
+ // There are exactly TWO places SectionProperties can appear:
1936
+ //
1937
+ // 1. FINAL SECTION: As the last child element of <w:body>.
1938
+ // This controls the last (or only) section of the document.
1939
+ // body.AppendChild(new SectionProperties(...));
1940
+ //
1941
+ // 2. MID-DOCUMENT SECTION BREAK: Inside ParagraphProperties of the
1942
+ // LAST paragraph of a section. This paragraph acts as the section divider.
1943
+ // The paragraph's text content belongs to the PREVIOUS section.
1944
+ //
1945
+ // IMPORTANT: Mid-document SectionProperties goes inside pPr, NOT as a child
1946
+ // of Body. This is the #1 mistake when creating multi-section documents.
1947
+
1948
+ // --- Final section (last child of Body) ---
1949
+ var finalSectPr = new SectionProperties(
1950
+ new PageSize { Width = 12240U, Height = 15840U },
1951
+ new PageMargin
1952
+ {
1953
+ Top = 1440, Bottom = 1440,
1954
+ Left = 1440U, Right = 1440U,
1955
+ Header = 720U, Footer = 720U, Gutter = 0U
1956
+ }
1957
+ );
1958
+ body.AppendChild(finalSectPr); // MUST be last child
1959
+
1960
+ // --- Mid-document section break ---
1961
+ // This paragraph ends section 1 and starts section 2
1962
+ var sectionBreakPara = new Paragraph(
1963
+ new ParagraphProperties(
1964
+ new SectionProperties(
1965
+ new PageSize { Width = 12240U, Height = 15840U },
1966
+ new PageMargin
1967
+ {
1968
+ Top = 1440, Bottom = 1440,
1969
+ Left = 1440U, Right = 1440U,
1970
+ Header = 720U, Footer = 720U, Gutter = 0U
1971
+ },
1972
+ new SectionType { Val = SectionMarkValues.NextPage }
1973
+ )
1974
+ )
1975
+ );
1976
+ // Produces XML:
1977
+ // <w:p>
1978
+ // <w:pPr>
1979
+ // <w:sectPr>
1980
+ // <w:pgSz w:w="12240" w:h="15840" />
1981
+ // <w:pgMar ... />
1982
+ // <w:type w:val="nextPage" />
1983
+ // </w:sectPr>
1984
+ // </w:pPr>
1985
+ // </w:p>
1986
+ ```
1987
+
1988
+ ### 4.2 SectionType Values
1989
+
1990
+ ```csharp
1991
+ // =============================================================================
1992
+ // SECTION TYPE VALUES
1993
+ // =============================================================================
1994
+ // SectionType controls how the section break behaves:
1995
+ //
1996
+ // NextPage — new section starts on next page (most common)
1997
+ // Continuous — new section starts on same page (used for column changes)
1998
+ // EvenPage — new section starts on next even page (inserts blank if needed)
1999
+ // OddPage — new section starts on next odd page (inserts blank if needed)
2000
+ //
2001
+ // If SectionType is omitted, the default is NextPage.
2002
+
2003
+ // Next page break (explicit)
2004
+ var nextPageBreak = new SectionType { Val = SectionMarkValues.NextPage };
2005
+
2006
+ // Continuous — same page (e.g., switch from 1-column to 2-column)
2007
+ var continuousBreak = new SectionType { Val = SectionMarkValues.Continuous };
2008
+
2009
+ // Even page — for chapters that must start on left page (in book layout)
2010
+ var evenPageBreak = new SectionType { Val = SectionMarkValues.EvenPage };
2011
+
2012
+ // Odd page — for chapters that must start on right page
2013
+ var oddPageBreak = new SectionType { Val = SectionMarkValues.OddPage };
2014
+ ```
2015
+
2016
+ ### 4.3 Per-Section Page Setup
2017
+
2018
+ ```csharp
2019
+ // =============================================================================
2020
+ // PER-SECTION PAGE SETUP
2021
+ // =============================================================================
2022
+ // Each section independently controls its own:
2023
+ // - PageSize (portrait vs landscape, paper size)
2024
+ // - PageMargin
2025
+ // - Columns
2026
+ // - Headers/Footers
2027
+ // - PageNumberType (restart numbering)
2028
+ // - LineNumbering
2029
+ // - DocGrid
2030
+
2031
+ // Example: Section with landscape A4 and narrow margins
2032
+ var landscapeSection = new SectionProperties(
2033
+ new PageSize
2034
+ {
2035
+ Width = 16838U, // A4 long edge (landscape: swap W/H)
2036
+ Height = 11906U, // A4 short edge
2037
+ Orient = PageOrientationValues.Landscape
2038
+ },
2039
+ new PageMargin
2040
+ {
2041
+ Top = 720, Bottom = 720,
2042
+ Left = 720U, Right = 720U,
2043
+ Header = 720U, Footer = 720U, Gutter = 0U
2044
+ },
2045
+ new SectionType { Val = SectionMarkValues.NextPage }
2046
+ );
2047
+ ```
2048
+
2049
+ ### 4.4 PageNumberType — Restart Numbering
2050
+
2051
+ ```csharp
2052
+ // =============================================================================
2053
+ // PAGE NUMBER TYPE — RESTART AND FORMAT
2054
+ // =============================================================================
2055
+ // PageNumberType controls page numbering within a section.
2056
+ // Start — starting page number (restarts counting)
2057
+ // Format — numbering format (Decimal, UpperRoman, LowerRoman,
2058
+ // UpperLetter, LowerLetter)
2059
+ //
2060
+ // Common pattern: front matter uses i, ii, iii; body restarts at 1.
2061
+
2062
+ // Restart at page 1 (e.g., after front matter)
2063
+ var restartNumbering = new PageNumberType
2064
+ {
2065
+ Start = 1,
2066
+ Format = NumberFormatValues.Decimal
2067
+ };
2068
+ // Produces XML: <w:pgNumType w:start="1" w:fmt="decimal" />
2069
+
2070
+ // Roman numeral numbering for front matter
2071
+ var romanNumbering = new PageNumberType
2072
+ {
2073
+ Start = 1,
2074
+ Format = NumberFormatValues.LowerRoman
2075
+ };
2076
+ // Produces XML: <w:pgNumType w:start="1" w:fmt="lowerRoman" />
2077
+
2078
+ // Add to section properties
2079
+ landscapeSection.AppendChild(restartNumbering);
2080
+ ```
2081
+
2082
+ ### 4.5 Complete Example: Portrait, Landscape, Portrait
2083
+
2084
+ ```csharp
2085
+ // =============================================================================
2086
+ // COMPLETE MULTI-SECTION EXAMPLE
2087
+ // =============================================================================
2088
+ // Document with three sections:
2089
+ // Section 1: Letter portrait (cover + intro)
2090
+ // Section 2: Letter landscape (wide table)
2091
+ // Section 3: Letter portrait (conclusion), page numbers restart at 1
2092
+ //
2093
+ // Each section has its own header.
2094
+
2095
+ using var doc = WordprocessingDocument.Create(
2096
+ "MultiSection.docx", WordprocessingDocumentType.Document);
2097
+
2098
+ var mainPart = doc.MainDocumentPart!;
2099
+ var body = mainPart.Document.Body!;
2100
+
2101
+ // --- Create headers for each section ---
2102
+ HeaderPart CreateSimpleHeader(string text)
2103
+ {
2104
+ var hp = mainPart.AddNewPart<HeaderPart>();
2105
+ hp.Header = new Header(
2106
+ new Paragraph(
2107
+ new ParagraphProperties(
2108
+ new ParagraphBorders(
2109
+ new BottomBorder
2110
+ {
2111
+ Val = BorderValues.Single, Size = 4U,
2112
+ Color = "999999", Space = 1U
2113
+ }),
2114
+ new Justification { Val = JustificationValues.Right }),
2115
+ new Run(
2116
+ new RunProperties(
2117
+ new FontSize { Val = "18" },
2118
+ new Color { Val = "999999" }),
2119
+ new Text(text)))
2120
+ );
2121
+ hp.Header.Save();
2122
+ return hp;
2123
+ }
2124
+
2125
+ var header1 = CreateSimpleHeader("Introduction");
2126
+ var header2 = CreateSimpleHeader("Data Tables");
2127
+ var header3 = CreateSimpleHeader("Conclusion");
2128
+
2129
+ // --- Create "Page X of Y" footer (shared) ---
2130
+ var sharedFooter = mainPart.AddNewPart<FooterPart>();
2131
+ var fPara = new Paragraph(
2132
+ new ParagraphProperties(new Justification { Val = JustificationValues.Center }));
2133
+ fPara.AppendChild(new Run(
2134
+ new RunProperties(new FontSize { Val = "18" }),
2135
+ new Text("Page ") { Space = SpaceProcessingModeValues.Preserve }));
2136
+ var pf = new SimpleField { Instruction = " PAGE " };
2137
+ pf.AppendChild(new Run(new RunProperties(new FontSize { Val = "18" }), new Text("1")));
2138
+ fPara.AppendChild(pf);
2139
+ fPara.AppendChild(new Run(
2140
+ new RunProperties(new FontSize { Val = "18" }),
2141
+ new Text(" of ") { Space = SpaceProcessingModeValues.Preserve }));
2142
+ var npf = new SimpleField { Instruction = " NUMPAGES " };
2143
+ npf.AppendChild(new Run(new RunProperties(new FontSize { Val = "18" }), new Text("1")));
2144
+ fPara.AppendChild(npf);
2145
+ sharedFooter.Footer = new Footer(fPara);
2146
+ sharedFooter.Footer.Save();
2147
+ string sharedFooterId = mainPart.GetIdOfPart(sharedFooter);
2148
+
2149
+ // =================== SECTION 1: Portrait ===================
2150
+ body.AppendChild(new Paragraph(
2151
+ new ParagraphProperties(
2152
+ new Justification { Val = JustificationValues.Center }),
2153
+ new Run(
2154
+ new RunProperties(new Bold(), new FontSize { Val = "48" }),
2155
+ new Text("Annual Report 2025"))));
2156
+
2157
+ body.AppendChild(new Paragraph(new Run(new Text("Introduction content goes here..."))));
2158
+
2159
+ // Section 1 break (inside pPr of last paragraph)
2160
+ body.AppendChild(new Paragraph(
2161
+ new ParagraphProperties(
2162
+ new SectionProperties(
2163
+ new PageSize { Width = 12240U, Height = 15840U },
2164
+ new PageMargin
2165
+ {
2166
+ Top = 1440, Bottom = 1440,
2167
+ Left = 1440U, Right = 1440U,
2168
+ Header = 720U, Footer = 720U, Gutter = 0U
2169
+ },
2170
+ new SectionType { Val = SectionMarkValues.NextPage },
2171
+ new HeaderReference
2172
+ {
2173
+ Type = HeaderFooterValues.Default,
2174
+ Id = mainPart.GetIdOfPart(header1)
2175
+ },
2176
+ new FooterReference
2177
+ {
2178
+ Type = HeaderFooterValues.Default,
2179
+ Id = sharedFooterId
2180
+ }
2181
+ )
2182
+ )
2183
+ ));
2184
+
2185
+ // =================== SECTION 2: Landscape ===================
2186
+ body.AppendChild(new Paragraph(new Run(
2187
+ new RunProperties(new Bold(), new FontSize { Val = "28" }),
2188
+ new Text("Wide Data Table"))));
2189
+
2190
+ body.AppendChild(new Paragraph(new Run(
2191
+ new Text("This section uses landscape orientation for a wide table."))));
2192
+
2193
+ // Section 2 break
2194
+ body.AppendChild(new Paragraph(
2195
+ new ParagraphProperties(
2196
+ new SectionProperties(
2197
+ new PageSize
2198
+ {
2199
+ Width = 15840U, // SWAPPED for landscape
2200
+ Height = 12240U, // SWAPPED for landscape
2201
+ Orient = PageOrientationValues.Landscape
2202
+ },
2203
+ new PageMargin
2204
+ {
2205
+ Top = 1440, Bottom = 1440,
2206
+ Left = 1440U, Right = 1440U,
2207
+ Header = 720U, Footer = 720U, Gutter = 0U
2208
+ },
2209
+ new SectionType { Val = SectionMarkValues.NextPage },
2210
+ new HeaderReference
2211
+ {
2212
+ Type = HeaderFooterValues.Default,
2213
+ Id = mainPart.GetIdOfPart(header2)
2214
+ },
2215
+ new FooterReference
2216
+ {
2217
+ Type = HeaderFooterValues.Default,
2218
+ Id = sharedFooterId
2219
+ }
2220
+ )
2221
+ )
2222
+ ));
2223
+
2224
+ // =================== SECTION 3: Portrait (restart page numbers) ===================
2225
+ body.AppendChild(new Paragraph(new Run(
2226
+ new RunProperties(new Bold(), new FontSize { Val = "28" }),
2227
+ new Text("Conclusion"))));
2228
+
2229
+ body.AppendChild(new Paragraph(new Run(
2230
+ new Text("Final section content with restarted page numbering."))));
2231
+
2232
+ // Final section properties — last child of Body
2233
+ body.AppendChild(new SectionProperties(
2234
+ new PageSize { Width = 12240U, Height = 15840U },
2235
+ new PageMargin
2236
+ {
2237
+ Top = 1440, Bottom = 1440,
2238
+ Left = 1440U, Right = 1440U,
2239
+ Header = 720U, Footer = 720U, Gutter = 0U
2240
+ },
2241
+ new PageNumberType
2242
+ {
2243
+ Start = 1, // Restart at page 1
2244
+ Format = NumberFormatValues.Decimal
2245
+ },
2246
+ new HeaderReference
2247
+ {
2248
+ Type = HeaderFooterValues.Default,
2249
+ Id = mainPart.GetIdOfPart(header3)
2250
+ },
2251
+ new FooterReference
2252
+ {
2253
+ Type = HeaderFooterValues.Default,
2254
+ Id = sharedFooterId
2255
+ }
2256
+ ));
2257
+
2258
+ mainPart.Document.Save();
2259
+ ```
2260
+
2261
+ ---
2262
+
2263
+ ## 5. Document Properties
2264
+
2265
+ ### 5.1 CoreFilePropertiesPart (Dublin Core Metadata)
2266
+
2267
+ ```csharp
2268
+ // =============================================================================
2269
+ // CORE FILE PROPERTIES (DUBLIN CORE)
2270
+ // =============================================================================
2271
+ // Core properties map to the Dublin Core metadata standard.
2272
+ // They appear in File > Properties > Summary in Word.
2273
+ // The underlying XML is stored in docProps/core.xml.
2274
+ //
2275
+ // Available properties: Title, Subject, Creator (Author), Keywords,
2276
+ // Description, LastModifiedBy, Revision, Created, Modified, Category,
2277
+ // ContentStatus, ContentType, Identifier, Language, Version
2278
+
2279
+ using var doc = WordprocessingDocument.Create(
2280
+ "PropertiesDemo.docx", WordprocessingDocumentType.Document);
2281
+
2282
+ // Core properties are accessed via the package-level properties
2283
+ // Use the OpenXml Packaging API:
2284
+ var corePart = doc.CoreFilePropertiesPart
2285
+ ?? doc.AddCoreFilePropertiesPart();
2286
+
2287
+ // The core properties use the OpenXmlPart's XML directly.
2288
+ // You can set properties via the PackageProperties interface:
2289
+ doc.PackageProperties.Title = "Quarterly Financial Report";
2290
+ doc.PackageProperties.Subject = "Q4 2025 Financial Summary";
2291
+ doc.PackageProperties.Creator = "Jane Smith";
2292
+ doc.PackageProperties.Keywords = "finance, quarterly, report, 2025";
2293
+ doc.PackageProperties.Description = "Comprehensive financial report for Q4 2025";
2294
+ doc.PackageProperties.LastModifiedBy = "John Doe";
2295
+ doc.PackageProperties.Revision = "3";
2296
+ doc.PackageProperties.Created = DateTime.UtcNow;
2297
+ doc.PackageProperties.Modified = DateTime.UtcNow;
2298
+ doc.PackageProperties.Category = "Financial Reports";
2299
+ doc.PackageProperties.ContentStatus = "Final";
2300
+ doc.PackageProperties.Language = "en-US";
2301
+ doc.PackageProperties.Version = "2.0";
2302
+
2303
+ // Produces docProps/core.xml:
2304
+ // <cp:coreProperties>
2305
+ // <dc:title>Quarterly Financial Report</dc:title>
2306
+ // <dc:subject>Q4 2025 Financial Summary</dc:subject>
2307
+ // <dc:creator>Jane Smith</dc:creator>
2308
+ // <cp:keywords>finance, quarterly, report, 2025</cp:keywords>
2309
+ // <dc:description>Comprehensive financial report...</dc:description>
2310
+ // <cp:lastModifiedBy>John Doe</cp:lastModifiedBy>
2311
+ // <cp:revision>3</cp:revision>
2312
+ // <dcterms:created>2025-12-01T00:00:00Z</dcterms:created>
2313
+ // <dcterms:modified>2025-12-01T00:00:00Z</dcterms:modified>
2314
+ // <cp:category>Financial Reports</cp:category>
2315
+ // <cp:contentStatus>Final</cp:contentStatus>
2316
+ // </cp:coreProperties>
2317
+ ```
2318
+
2319
+ ### 5.2 ExtendedFilePropertiesPart (Application Properties)
2320
+
2321
+ ```csharp
2322
+ // =============================================================================
2323
+ // EXTENDED FILE PROPERTIES (APPLICATION PROPERTIES)
2324
+ // =============================================================================
2325
+ // Extended properties are stored in docProps/app.xml.
2326
+ // They include application-specific metadata like Company, Manager, etc.
2327
+
2328
+ using DocumentFormat.OpenXml.ExtendedProperties;
2329
+
2330
+ var extPart = doc.ExtendedFilePropertiesPart
2331
+ ?? doc.AddExtendedFilePropertiesPart();
2332
+
2333
+ extPart.Properties = new DocumentFormat.OpenXml.ExtendedProperties.Properties();
2334
+
2335
+ // Company name
2336
+ extPart.Properties.AppendChild(
2337
+ new DocumentFormat.OpenXml.ExtendedProperties.Company("ACME Corporation"));
2338
+
2339
+ // Manager
2340
+ extPart.Properties.AppendChild(
2341
+ new DocumentFormat.OpenXml.ExtendedProperties.Manager("Alice Johnson"));
2342
+
2343
+ // Application name
2344
+ extPart.Properties.AppendChild(
2345
+ new DocumentFormat.OpenXml.ExtendedProperties.Application("Custom Document Generator"));
2346
+
2347
+ // Application version
2348
+ extPart.Properties.AppendChild(
2349
+ new DocumentFormat.OpenXml.ExtendedProperties.ApplicationVersion("1.0.0"));
2350
+
2351
+ // Total editing time in minutes
2352
+ extPart.Properties.AppendChild(
2353
+ new DocumentFormat.OpenXml.ExtendedProperties.TotalTime("0"));
2354
+
2355
+ // Pages, Words, Characters (these are hints; Word recalculates them)
2356
+ extPart.Properties.AppendChild(
2357
+ new DocumentFormat.OpenXml.ExtendedProperties.Pages("1"));
2358
+ extPart.Properties.AppendChild(
2359
+ new DocumentFormat.OpenXml.ExtendedProperties.Words("0"));
2360
+ extPart.Properties.AppendChild(
2361
+ new DocumentFormat.OpenXml.ExtendedProperties.Characters("0"));
2362
+
2363
+ extPart.Properties.Save();
2364
+
2365
+ // Produces docProps/app.xml:
2366
+ // <Properties>
2367
+ // <Company>ACME Corporation</Company>
2368
+ // <Manager>Alice Johnson</Manager>
2369
+ // <Application>Custom Document Generator</Application>
2370
+ // <AppVersion>1.0.0</AppVersion>
2371
+ // <TotalTime>0</TotalTime>
2372
+ // <Pages>1</Pages>
2373
+ // </Properties>
2374
+ ```
2375
+
2376
+ ### 5.3 CustomFilePropertiesPart (Custom Key-Value Properties)
2377
+
2378
+ ```csharp
2379
+ // =============================================================================
2380
+ // CUSTOM FILE PROPERTIES (KEY-VALUE PAIRS)
2381
+ // =============================================================================
2382
+ // Custom properties allow arbitrary key-value metadata.
2383
+ // Stored in docProps/custom.xml. Useful for document management systems,
2384
+ // workflow tracking, template variables, etc.
2385
+ //
2386
+ // Supported value types: Text (string), Number (int), Date (DateTime),
2387
+ // Boolean (bool), Filetime
2388
+
2389
+ using DocumentFormat.OpenXml.CustomProperties;
2390
+ using DocumentFormat.OpenXml.VariantTypes;
2391
+
2392
+ var customPart = doc.CustomFilePropertiesPart
2393
+ ?? doc.AddCustomFilePropertiesPart();
2394
+
2395
+ customPart.Properties = new DocumentFormat.OpenXml.CustomProperties.Properties();
2396
+
2397
+ // Property IDs must start at 2 and increment
2398
+ int propertyId = 2;
2399
+
2400
+ // --- String property ---
2401
+ customPart.Properties.AppendChild(new CustomDocumentProperty
2402
+ {
2403
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
2404
+ PropertyId = propertyId++,
2405
+ Name = "Department",
2406
+ VTLPWSTR = new VTLPWSTR("Engineering")
2407
+ });
2408
+
2409
+ // --- Integer property ---
2410
+ customPart.Properties.AppendChild(new CustomDocumentProperty
2411
+ {
2412
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
2413
+ PropertyId = propertyId++,
2414
+ Name = "DocumentVersion",
2415
+ VTInt32 = new VTInt32("5")
2416
+ });
2417
+
2418
+ // --- Boolean property ---
2419
+ customPart.Properties.AppendChild(new CustomDocumentProperty
2420
+ {
2421
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
2422
+ PropertyId = propertyId++,
2423
+ Name = "Approved",
2424
+ VTBool = new VTBool("true")
2425
+ });
2426
+
2427
+ // --- DateTime property ---
2428
+ customPart.Properties.AppendChild(new CustomDocumentProperty
2429
+ {
2430
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
2431
+ PropertyId = propertyId++,
2432
+ Name = "ApprovalDate",
2433
+ VTFileTime = new VTFileTime(DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"))
2434
+ });
2435
+
2436
+ // --- Double/Float property ---
2437
+ customPart.Properties.AppendChild(new CustomDocumentProperty
2438
+ {
2439
+ FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
2440
+ PropertyId = propertyId++,
2441
+ Name = "ConfidenceScore",
2442
+ VTDouble = new VTDouble("0.95")
2443
+ });
2444
+
2445
+ customPart.Properties.Save();
2446
+
2447
+ // Produces docProps/custom.xml:
2448
+ // <Properties>
2449
+ // <property fmtid="{D5CDD505-...}" pid="2" name="Department">
2450
+ // <vt:lpwstr>Engineering</vt:lpwstr>
2451
+ // </property>
2452
+ // <property fmtid="{D5CDD505-...}" pid="3" name="DocumentVersion">
2453
+ // <vt:i4>5</vt:i4>
2454
+ // </property>
2455
+ // <property fmtid="{D5CDD505-...}" pid="4" name="Approved">
2456
+ // <vt:bool>true</vt:bool>
2457
+ // </property>
2458
+ // ...
2459
+ // </Properties>
2460
+ ```
2461
+
2462
+ ### 5.4 Reading and Modifying Existing Properties
2463
+
2464
+ ```csharp
2465
+ // =============================================================================
2466
+ // READING AND MODIFYING EXISTING PROPERTIES
2467
+ // =============================================================================
2468
+
2469
+ using var existingDoc = WordprocessingDocument.Open("existing.docx", isEditable: true);
2470
+
2471
+ // --- Read core properties ---
2472
+ string? title = existingDoc.PackageProperties.Title;
2473
+ string? author = existingDoc.PackageProperties.Creator;
2474
+ DateTime? modified = existingDoc.PackageProperties.Modified;
2475
+
2476
+ // --- Modify core properties ---
2477
+ existingDoc.PackageProperties.Title = "Updated Title";
2478
+ existingDoc.PackageProperties.Modified = DateTime.UtcNow;
2479
+
2480
+ // --- Read custom properties ---
2481
+ var customProps = existingDoc.CustomFilePropertiesPart?.Properties;
2482
+ if (customProps != null)
2483
+ {
2484
+ foreach (var prop in customProps.Elements<CustomDocumentProperty>())
2485
+ {
2486
+ string name = prop.Name!;
2487
+ // Value is in one of the VT* child elements
2488
+ string? textValue = prop.VTLPWSTR?.Text;
2489
+ string? intValue = prop.VTInt32?.Text;
2490
+ string? boolValue = prop.VTBool?.Text;
2491
+ // Use whichever is non-null
2492
+ }
2493
+ }
2494
+
2495
+ // --- Update a specific custom property ---
2496
+ var deptProp = customProps?.Elements<CustomDocumentProperty>()
2497
+ .FirstOrDefault(p => p.Name == "Department");
2498
+ if (deptProp != null)
2499
+ {
2500
+ deptProp.VTLPWSTR = new VTLPWSTR("Marketing");
2501
+ customProps!.Save();
2502
+ }
2503
+ ```
2504
+
2505
+ ---
2506
+
2507
+ ## 6. Printing & Compatibility Settings
2508
+
2509
+ ### 6.1 DocumentSettingsPart — Zoom, TabStop, ProofState
2510
+
2511
+ ```csharp
2512
+ // =============================================================================
2513
+ // DOCUMENT SETTINGS — ZOOM, TAB STOPS, PROOF STATE
2514
+ // =============================================================================
2515
+ // DocumentSettingsPart (settings.xml) contains document-wide settings.
2516
+ // These control behavior in Word's UI and rendering.
2517
+
2518
+ var mainPart2 = doc.MainDocumentPart!;
2519
+ var settingsPart2 = mainPart2.DocumentSettingsPart
2520
+ ?? mainPart2.AddNewPart<DocumentSettingsPart>();
2521
+ settingsPart2.Settings ??= new Settings();
2522
+ var settings = settingsPart2.Settings;
2523
+
2524
+ // --- Zoom level ---
2525
+ // Val = percentage (100 = 100%). Percent is a string.
2526
+ settings.AppendChild(new Zoom
2527
+ {
2528
+ Percent = "120", // 120% zoom
2529
+ Val = PresetZoomValues.BestFit // Or: None, FullPage, BestFit, TextFit
2530
+ });
2531
+ // Produces XML: <w:zoom w:percent="120" w:val="bestFit" />
2532
+
2533
+ // --- Default Tab Stop ---
2534
+ // Distance in DXA for default tab stops. Standard is 720 (0.5 inch).
2535
+ settings.AppendChild(new DefaultTabStop
2536
+ {
2537
+ Val = 720 // 0.5 inch
2538
+ });
2539
+ // Produces XML: <w:defaultTabStop w:val="720" />
2540
+
2541
+ // For Chinese documents, common default tab stop is 420 (about 2 characters wide)
2542
+ // settings.AppendChild(new DefaultTabStop { Val = 420 });
2543
+
2544
+ // --- Proof State ---
2545
+ // Tells Word the spell/grammar check status. Setting both to "clean"
2546
+ // prevents Word from showing the "Proofing" notification on open.
2547
+ settings.AppendChild(new ProofState
2548
+ {
2549
+ Spelling = ProofingStateValues.Clean,
2550
+ Grammar = ProofingStateValues.Clean
2551
+ });
2552
+ // Produces XML: <w:proofState w:spelling="clean" w:grammar="clean" />
2553
+
2554
+ // --- Character Spacing Control ---
2555
+ // CompressWhitespace: whether to compress whitespace at line edges (CJK)
2556
+ settings.AppendChild(new CharacterSpacingControl
2557
+ {
2558
+ Val = CharacterSpacingValues.DoNotCompress
2559
+ });
2560
+
2561
+ // --- Remove personal information on save ---
2562
+ settings.AppendChild(new RemovePersonalInformation());
2563
+ // Produces XML: <w:removePersonalInformation />
2564
+
2565
+ settings.Save();
2566
+ ```
2567
+
2568
+ ### 6.2 Compatibility Settings
2569
+
2570
+ ```csharp
2571
+ // =============================================================================
2572
+ // COMPATIBILITY SETTINGS
2573
+ // =============================================================================
2574
+ // Compatibility settings control how Word renders the document,
2575
+ // providing backward compatibility with older Word versions.
2576
+ // CompatibilityMode is the most important setting.
2577
+
2578
+ var compat = new Compatibility();
2579
+
2580
+ // --- Compatibility Mode ---
2581
+ // 15 = Word 2013+ mode (current standard)
2582
+ // 14 = Word 2010 mode
2583
+ // 12 = Word 2007 mode
2584
+ // Omitted or 0 = oldest compatibility
2585
+ compat.AppendChild(new CompatibilitySetting
2586
+ {
2587
+ Name = CompatSettingNameValues.CompatibilityMode,
2588
+ Uri = "http://schemas.microsoft.com/office/word",
2589
+ Val = "15" // Word 2013+ mode
2590
+ });
2591
+
2592
+ // --- Override page break rules ---
2593
+ // Useful compatibility flags for consistent rendering:
2594
+
2595
+ // UseWord2002TableStyleRules: use newer table style rules
2596
+ compat.AppendChild(new CompatibilitySetting
2597
+ {
2598
+ Name = CompatSettingNameValues.OverrideTableStyleFontSizeAndJustification,
2599
+ Uri = "http://schemas.microsoft.com/office/word",
2600
+ Val = "1"
2601
+ });
2602
+
2603
+ // EnableOpenTypeFeatures: enable advanced typography
2604
+ compat.AppendChild(new CompatibilitySetting
2605
+ {
2606
+ Name = CompatSettingNameValues.EnableOpenTypeFeatures,
2607
+ Uri = "http://schemas.microsoft.com/office/word",
2608
+ Val = "1"
2609
+ });
2610
+
2611
+ // DifferentiateMultirowTableHeaders
2612
+ compat.AppendChild(new CompatibilitySetting
2613
+ {
2614
+ Name = CompatSettingNameValues.DifferentiateMultirowTableHeaders,
2615
+ Uri = "http://schemas.microsoft.com/office/word",
2616
+ Val = "1"
2617
+ });
2618
+
2619
+ // UseWord2013TrackBottomHyphenation
2620
+ compat.AppendChild(new CompatibilitySetting
2621
+ {
2622
+ Name = CompatSettingNameValues.UseWord2013TrackBottomHyphenation,
2623
+ Uri = "http://schemas.microsoft.com/office/word",
2624
+ Val = "0"
2625
+ });
2626
+
2627
+ settings.AppendChild(compat);
2628
+ settings.Save();
2629
+
2630
+ // Produces XML:
2631
+ // <w:compat>
2632
+ // <w:compatSetting w:name="compatibilityMode"
2633
+ // w:uri="http://schemas.microsoft.com/office/word" w:val="15" />
2634
+ // <w:compatSetting w:name="overrideTableStyleFontSizeAndJustification"
2635
+ // w:uri="http://schemas.microsoft.com/office/word" w:val="1" />
2636
+ // ...
2637
+ // </w:compat>
2638
+ ```
2639
+
2640
+ ### 6.3 MirrorMargins, GutterAtTop, BookFoldPrinting
2641
+
2642
+ ```csharp
2643
+ // =============================================================================
2644
+ // MIRROR MARGINS, GUTTER, BOOK FOLD
2645
+ // =============================================================================
2646
+ // These settings are for documents intended for double-sided printing or
2647
+ // book binding.
2648
+
2649
+ // --- Mirror Margins ---
2650
+ // When enabled, Left/Right margins become Inside/Outside.
2651
+ // On even pages, margins are swapped so the binding edge stays consistent.
2652
+ settings.AppendChild(new MirrorMargins());
2653
+ // Produces XML: <w:mirrorMargins />
2654
+ // After this, PageMargin.Left = inside margin, PageMargin.Right = outside margin.
2655
+ // Even pages automatically flip them.
2656
+
2657
+ // --- Gutter at Top ---
2658
+ // By default, gutter is added to the left (or inside with MirrorMargins).
2659
+ // GutterAtTop moves the gutter to the top margin instead.
2660
+ // Used for calendar-style or top-bound documents.
2661
+ settings.AppendChild(new GutterAtTop());
2662
+ // Produces XML: <w:gutterAtTop />
2663
+
2664
+ // --- Book Fold Printing ---
2665
+ // Enables booklet printing (2 pages per sheet, folded in half).
2666
+ // Word reorders pages for saddle-stitch binding.
2667
+ settings.AppendChild(new BookFoldPrinting());
2668
+ // Produces XML: <w:bookFoldPrinting />
2669
+
2670
+ // Optional: sheets per booklet (for thick documents split into signatures)
2671
+ // Default 0 = all pages in one booklet
2672
+ settings.AppendChild(new BookFoldPrintingSheets { Val = 16 });
2673
+ // Produces XML: <w:bookFoldPrintingSheets w:val="16" />
2674
+ // 16 sheets = 64 pages per booklet signature
2675
+
2676
+ // --- Book Fold Reversed ---
2677
+ // For right-to-left booklets (Hebrew, Arabic, Japanese right-bound)
2678
+ // settings.AppendChild(new BookFoldRevPrinting());
2679
+
2680
+ settings.Save();
2681
+ ```
2682
+
2683
+ ### 6.4 Additional Document Settings
2684
+
2685
+ ```csharp
2686
+ // =============================================================================
2687
+ // ADDITIONAL DOCUMENT SETTINGS
2688
+ // =============================================================================
2689
+
2690
+ // --- Update Fields on Open ---
2691
+ // Forces Word to recalculate all fields (TOC, page numbers, etc.) on open.
2692
+ settings.AppendChild(new UpdateFieldsOnOpen { Val = true });
2693
+ // Produces XML: <w:updateFields w:val="true" />
2694
+ // WARNING: This causes a dialog popup in some Word versions.
2695
+
2696
+ // --- Do Not Track Moves ---
2697
+ // Prevents move tracking in track changes (shows as delete + insert instead).
2698
+ // settings.AppendChild(new DoNotTrackMoves());
2699
+
2700
+ // --- Do Not Track Formatting ---
2701
+ // Prevents formatting changes from being tracked.
2702
+ // settings.AppendChild(new DoNotTrackFormatting());
2703
+
2704
+ // --- Default Zoom for Print Preview ---
2705
+ // PrintTwoOnOne: print 2 pages per sheet
2706
+ // settings.AppendChild(new PrintTwoOnOne());
2707
+
2708
+ // --- Document protection (read-only, forms-only, etc.) ---
2709
+ // DocumentProtection can enforce read-only, allow only comments,
2710
+ // restrict to form fields, etc.
2711
+ // settings.AppendChild(new DocumentProtection
2712
+ // {
2713
+ // Edit = DocumentProtectionValues.ReadOnly,
2714
+ // Enforcement = true
2715
+ // });
2716
+
2717
+ // --- Even and Odd Headers (setting-level flag) ---
2718
+ // Must be set here for the EvenPage header/footer references to work.
2719
+ // settings.AppendChild(new EvenAndOddHeaders());
2720
+
2721
+ settings.Save();
2722
+ ```
2723
+
2724
+ ### 6.5 Complete Settings Setup
2725
+
2726
+ ```csharp
2727
+ // =============================================================================
2728
+ // COMPLETE SETTINGS SETUP — PRODUCTION-READY
2729
+ // =============================================================================
2730
+ // A comprehensive settings configuration suitable for most documents.
2731
+
2732
+ static void ConfigureDocumentSettings(WordprocessingDocument doc)
2733
+ {
2734
+ var mainPart = doc.MainDocumentPart!;
2735
+ var settingsPart = mainPart.DocumentSettingsPart
2736
+ ?? mainPart.AddNewPart<DocumentSettingsPart>();
2737
+ settingsPart.Settings = new Settings();
2738
+ var s = settingsPart.Settings;
2739
+
2740
+ // Zoom to 100%
2741
+ s.AppendChild(new Zoom
2742
+ {
2743
+ Percent = "100",
2744
+ Val = PresetZoomValues.None
2745
+ });
2746
+
2747
+ // Default tab stop: 0.5 inch
2748
+ s.AppendChild(new DefaultTabStop { Val = 720 });
2749
+
2750
+ // Mark spell/grammar as clean
2751
+ s.AppendChild(new ProofState
2752
+ {
2753
+ Spelling = ProofingStateValues.Clean,
2754
+ Grammar = ProofingStateValues.Clean
2755
+ });
2756
+
2757
+ // Character spacing control
2758
+ s.AppendChild(new CharacterSpacingControl
2759
+ {
2760
+ Val = CharacterSpacingValues.DoNotCompress
2761
+ });
2762
+
2763
+ // Compatibility: Word 2013+ mode with useful features
2764
+ var compat = new Compatibility();
2765
+ foreach (var (name, val) in new[]
2766
+ {
2767
+ (CompatSettingNameValues.CompatibilityMode, "15"),
2768
+ (CompatSettingNameValues.OverrideTableStyleFontSizeAndJustification, "1"),
2769
+ (CompatSettingNameValues.EnableOpenTypeFeatures, "1"),
2770
+ (CompatSettingNameValues.DifferentiateMultirowTableHeaders, "1"),
2771
+ (CompatSettingNameValues.UseWord2013TrackBottomHyphenation, "0"),
2772
+ })
2773
+ {
2774
+ compat.AppendChild(new CompatibilitySetting
2775
+ {
2776
+ Name = name,
2777
+ Uri = "http://schemas.microsoft.com/office/word",
2778
+ Val = val
2779
+ });
2780
+ }
2781
+ s.AppendChild(compat);
2782
+
2783
+ s.Save();
2784
+ }
2785
+
2786
+ // Usage:
2787
+ ConfigureDocumentSettings(doc);
2788
+ ```
2789
+
2790
+ ---
2791
+
2792
+ ## Quick Reference: Unit Conversions
2793
+
2794
+ | Unit | Full Name | Relation |
2795
+ |------|-----------|----------|
2796
+ | DXA | Twentieths of a point | 1 inch = 1440 DXA; 1 cm = 567 DXA; 1 pt = 20 DXA |
2797
+ | Half-point | Half a typographic point | Font size: 24 = 12pt. 1 pt = 2 half-points |
2798
+ | Eighth-point | Eighth of a point | Border size: 8 = 1pt. 1 pt = 8 eighth-points |
2799
+ | EMU | English Metric Unit | 1 inch = 914400 EMU; 1 cm = 360000 EMU; 1 pt = 12700 EMU |
2800
+ | Pct (table width) | Fiftieths of a percent | 5000 = 100%. Multiply percentage by 50 |
2801
+
2802
+ ## Quick Reference: Common PageSize Values
2803
+
2804
+ | Paper | Width (DXA) | Height (DXA) | Inches | mm |
2805
+ |-------|-------------|--------------|--------|-----|
2806
+ | Letter | 12240 | 15840 | 8.5 x 11 | 216 x 279 |
2807
+ | A4 | 11906 | 16838 | -- | 210 x 297 |
2808
+ | Legal | 12240 | 20160 | 8.5 x 14 | 216 x 356 |
2809
+ | A3 | 16838 | 23811 | -- | 297 x 420 |
2810
+ | B5 | 10318 | 14570 | -- | 182 x 257 |
2811
+
2812
+ ## Quick Reference: Common Margin Presets (DXA)
2813
+
2814
+ | Preset | Top | Bottom | Left | Right |
2815
+ |--------|-----|--------|------|-------|
2816
+ | Normal | 1440 | 1440 | 1440 | 1440 |
2817
+ | Narrow | 720 | 720 | 720 | 720 |
2818
+ | Moderate | 1440 | 1440 | 1080 | 1080 |
2819
+ | Wide | 1440 | 1440 | 2880 | 2880 |
2820
+ | Chinese 公文 | 2098 | 1984 | 1588 | 1474 |