Overview
When creating Word documents using the OpenXML SDK, you can programmatically control the alignment of each paragraph (Left, Center, Right, Justified/Both). This is achieved by adding the Justification information inside the ParagraphProperties of a paragraph to adjust the text position.
Specifications (Input/Output)
- Input: File path, text string, and alignment type (
JustificationValues). - Output: A
.docxfile with the specified alignment settings applied. - Library: DocumentFormat.OpenXml (NuGet package).
Implemented Methods
| Method Name | Description |
| AppendParagraph | Receives text and an alignment position (Left, Center, Right, etc.) and adds a paragraph with that setting. Defaults to Left. |
Basic Usage
using DocumentFormat.OpenXml.Wordprocessing;
using var generator = new SimpleWordGenerator("AlignmentTest.docx");
// Left alignment (default)
generator.AppendParagraph("This text is left-aligned.");
// Center alignment
generator.AppendParagraph("Centered Title", JustificationValues.Center);
// Right alignment
generator.AppendParagraph("January 1, 2025 Right-aligned", JustificationValues.Right);
Full Code Example
using System;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
class Program
{
static void Main()
{
string filePath = "AlignmentExample.docx";
try
{
Console.WriteLine($"Generating {filePath} ...");
using (var doc = new SimpleWordGenerator(filePath))
{
// 1. Left alignment (Left)
doc.AppendParagraph("This is a left-aligned paragraph.", JustificationValues.Left);
// 2. Center alignment (Center)
doc.AppendParagraph("This is a centered paragraph.", JustificationValues.Center);
// 3. Right alignment (Right)
doc.AppendParagraph("This is a right-aligned paragraph.", JustificationValues.Right);
// 4. Justified (Both) - effective for long blocks of text
string longText = "Justified alignment (Both) automatically adjusts character spacing " +
"so that both the left and right edges of the lines are clean. " +
"It is frequently used in formal documents and reports to improve visual presentation.";
doc.AppendParagraph(longText, JustificationValues.Both);
}
Console.WriteLine("Done.");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
/// <summary>
/// Word document generation class supporting paragraph alignment.
/// </summary>
public sealed class SimpleWordGenerator : IDisposable
{
private WordprocessingDocument _document;
private Body _body;
public SimpleWordGenerator(string filePath)
{
// Initialize document and Body
_document = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document);
MainDocumentPart mainPart = _document.AddMainDocumentPart();
mainPart.Document = new Document();
_body = mainPart.Document.AppendChild(new Body());
}
public void Dispose()
{
_document?.Dispose();
}
/// <summary>
/// Adds a paragraph with the specified alignment.
/// </summary>
/// <param name="text">Text to write</param>
/// <param name="align">Alignment (Left, Center, Right, Both, etc.)</param>
public void AppendParagraph(string text, JustificationValues align = JustificationValues.Left)
{
// 1. Generate Paragraph
var paragraph = new Paragraph();
// 2. Generate ParagraphProperties (pPr)
var pPr = new ParagraphProperties();
// 3. Generate Justification and add to properties
// Set the JustificationValues enum to the Val property
var justification = new Justification() { Val = align };
pPr.Append(justification);
// 4. Apply properties to the paragraph
paragraph.Append(pPr);
// 5. Generate and add text portion (Run > Text)
var run = new Run();
run.Append(new Text(text));
paragraph.Append(run);
// 6. Add to Body
_body.Append(paragraph);
}
}
Customization Points
- Changing Default Values: In some document standards, “Justified (JustificationValues.Both)” is preferred. It is convenient to change the method’s default argument to
Both. - Adding Indentation: You can also set indentation by adding an
Indentationobject toParagraphProperties.Example: Adding a left indentpPr.Append(new Indentation() { Left = “720” }); // Approx. 1.27cm (1440 = 1 inch)
Important Notes
- Property Order: While the order of elements within a
Paragraphis somewhat flexible in OpenXML, generallyParagraphProperties(pPr) must be added to theParagraphbefore theRun. - Effect of “Both”:
JustificationValues.Both(Justified) will look the same asLeftif the text is short enough to fit on one line. The effect only becomes visible when the text is long enough to wrap across multiple lines. - Distribute: Using
JustificationValues.Distributewill space characters to fill the entire width of the line regardless of character count. Use this carefully for headings, as it can result in extremely wide character spacing.
Advanced Usage
Centering Styled Headings
This example demonstrates how to apply a heading style while simultaneously centering it.
public void AddCenteredHeading(string text)
{
var p = new Paragraph();
var pPr = new ParagraphProperties();
// Specify Style ID "Heading1"
pPr.Append(new ParagraphStyleId() { Val = "Heading1" });
// Specify Center alignment
pPr.Append(new Justification() { Val = JustificationValues.Center });
p.Append(pPr);
p.Append(new Run(new Text(text)));
_body.Append(p);
}
Summary
To control the appearance of paragraphs in OpenXML, it is essential to understand the structure: placing ParagraphProperties directly under Paragraph, and then adding specific setting elements like Justification inside it. Once you master this pattern, you can set line spacing, background colors, and borders using similar procedures.
