PowerShell-first document automation for Word, Excel, PowerPoint, Markdown, and CSV, built on top of OfficeIMO.*.
π¦ PowerShell Gallery
π οΈ Project
PSWriteOffice is the PowerShell layer for OfficeIMO.*.
OfficeIMOowns the document engine and low-level file-format behavior.PSWriteOfficeowns the PowerShell cmdlets, DSL aliases, packaging, examples, and scripting ergonomics.- The goal is simple: make Office document automation feel native in PowerShell without requiring Microsoft Office on the machine.
| Area | Status | What it covers now |
|---|---|---|
| Word | Mature | Document creation, readers, bookmarks, content controls, fields, HTML conversion, Markdown conversion |
| Excel | Advanced | Sheets, tables, named ranges, formulas, validation, charts, pivots, comments, TOC/navigation, explicit range readers, chart formatting, smarter links, URL images, summary-sheet linking |
| PowerPoint | Experimental but useful | Slides, titles, text boxes, bullets, notes, layouts, placeholders, sections, text replacement, slide import, slide copy, transitions, sizing |
| Markdown | Solid | Read Markdown, inspect full object trees/headings/front matter/tables, build Markdown with a DSL, render HTML, convert HTML |
| CSV | Solid | Read CSV, emit CSV, object-focused data workflows |
New-OfficeWord -Path .\Report.docx {
WordSection {
WordHeader { WordParagraph -Text 'Quarterly Report' -Style Heading2 }
WordFooter { WordPageNumber }
WordParagraph -Text 'Hello from PSWriteOffice.'
WordList -Style Bulleted {
WordListItem -Text 'Alpha'
WordListItem -Text 'Beta'
}
}
}$chartData = @(
[PSCustomObject]@{ Region = 'NA'; Revenue = 100 }
[PSCustomObject]@{ Region = 'EMEA'; Revenue = 200 }
)
New-OfficeWord -Path .\Charts.docx {
Add-OfficeWordChart -Type Pie -Data $chartData -CategoryProperty Region -SeriesProperty Revenue -Title 'Revenue Mix'
}$data = @(
[PSCustomObject]@{ Region = 'NA'; Revenue = 100 }
[PSCustomObject]@{ Region = 'EMEA'; Revenue = 200 }
)
New-OfficeExcel -Path .\Report.xlsx {
ExcelSheet 'Data' {
ExcelTable -Data $data -TableName 'Sales' -AutoFit
ExcelNamedRange -Name 'SalesData' -Range 'A1:B3'
}
ExcelSheet 'Notes' {
ExcelRow -Row 1 -Values 'Label', 'Value'
ExcelRow -Row 2 -Values 'Generated', (Get-Date -Format 'yyyy-MM-dd')
}
ExcelTableOfContents -IncludeNamedRanges
}New-OfficePowerPoint -Path .\Deck.pptx {
PptSlide {
PptTitle -Title 'Status Update'
PptTextBox -Text 'Generated with PSWriteOffice' -X 80 -Y 150 -Width 360 -Height 60
PptBullets -Bullets 'Wins','Risks','Next Steps' -X 430 -Y 150 -Width 260 -Height 200
PptNotes -Text 'Keep this under five minutes.'
}
}$ppt = Get-OfficePowerPoint -FilePath .\Deck.pptx
Add-OfficePowerPointSection -Presentation $ppt -Name 'Intro' -StartSlideIndex 0
Rename-OfficePowerPointSection -Presentation $ppt -Name 'Intro' -NewName 'Opening'
Update-OfficePowerPointText -Presentation $ppt -OldValue 'FY24' -NewValue 'FY25' -IncludeNotes
Copy-OfficePowerPointSlide -Presentation $ppt -Index 0
Get-OfficePowerPointSlide -Presentation $ppt -Index 0 | Set-OfficePowerPointSlideTransition -Transition Fade
Set-OfficePowerPointSlideSize -Presentation $ppt -Preset Screen16x9
Import-OfficePowerPointSlide -Presentation $ppt -SourcePath .\SourceDeck.pptx -SourceIndex 0$ppt = Get-OfficePowerPoint -FilePath .\Deck.pptx
Set-OfficePowerPointThemeColor -Presentation $ppt -Colors @{ Accent1 = '#C00000'; Accent2 = '#00B0F0' } -AllMasters
Set-OfficePowerPointThemeFonts -Presentation $ppt -MajorLatin 'Aptos' -MinorLatin 'Calibri' -AllMasters
Set-OfficePowerPointThemeName -Presentation $ppt -Name 'Contoso Theme' -AllMasters
Get-OfficePowerPointSlide -Presentation $ppt -Index 0 | Set-OfficePowerPointSlideLayout -LayoutName 'Title and Content'
Get-OfficePowerPointTheme -Presentation $ppt$chart = Add-OfficeExcelChart -TableName 'Sales' -Row 6 -Column 1 -Type Pie -Title 'Revenue Mix' -PassThru
$chart |
Set-OfficeExcelChartLegend -Position Right |
Set-OfficeExcelChartDataLabels -ShowValue $true -ShowPercent $true -Position OutsideEnd -NumberFormat '0.0%' -SourceLinked:$false |
Set-OfficeExcelChartStyle -StyleId 251 -ColorStyleId 10ExcelSheet 'Data' {
Set-OfficeExcelSmartHyperlink -Address 'A2' -Url 'https://datatracker.ietf.org/doc/html/rfc7208'
Set-OfficeExcelHostHyperlink -Address 'B2' -Url 'https://learn.microsoft.com/office/open-xml/'
Add-OfficeExcelImageFromUrl -Address 'D2' -Url 'https://example.org/logo.png' -WidthPixels 48 -HeightPixels 48
}ExcelSheet 'Summary' {
Set-OfficeExcelInternalLinks -Range 'D2:D10'
Set-OfficeExcelInternalLinksByHeader -Header 'Sheet' -TableName 'SummaryTable' -DisplayScript { param($text) "Open $text" }
}ExcelSheet 'Summary' {
Set-OfficeExcelUrlLinksByHeader -Header 'RFC' -TableName 'LinksTable' -UrlScript { param($text) "https://datatracker.ietf.org/doc/html/$text" } -TitleScript { param($text) "Open $text" }
Set-OfficeExcelUrlLinks -Range 'D2:D10' -UrlScript { param($text) "https://datatracker.ietf.org/doc/html/$text" }
}New-OfficeMarkdown -Path .\README.md {
MarkdownHeading -Level 1 -Text 'Report'
MarkdownParagraph -Text 'Generated by PSWriteOffice.'
}
$data | ConvertTo-OfficeCsv -OutputPath .\export.csvPSWriteOffice is not only about writing files. The module now has stronger read-back and bridge workflows too.
$data | Export-OfficeExcel -Path .\Report.xlsx -WorksheetName 'Data' -TableName 'Data' -AutoFit -FreezeTopRow
Import-OfficeExcel -Path .\Report.xlsx -WorksheetName 'Data'Get-OfficeExcelData -Path .\Report.xlsx -Sheet 'Data'
Get-OfficeExcelRange -Path .\Report.xlsx -Sheet 'Data' -Range 'A1:B10'
Get-OfficeExcelUsedRange -Path .\Report.xlsx -Sheet 'Data' -AsDataTable
Get-OfficeExcelNamedRange -Path .\Report.xlsx
Get-OfficeExcelPivotTable -Path .\Report.xlsx$markdown = ConvertTo-OfficeWordMarkdown -Path .\Report.docx
ConvertFrom-OfficeWordMarkdown -Markdown $markdown -OutputPath .\Report-Roundtrip.docx
$doc = Get-OfficeWord -Path .\Report.docx
Update-OfficeWordText -Document $doc -OldValue 'FY24' -NewValue 'FY25'
Close-OfficeWord -Document $doc -Save$doc = New-OfficeWord -Path .\Report.docx
$chart = $doc.AddChart('Revenue Mix')
$chart.AddPie('North America', 125000).
AddPie('EMEA', 98000).
AddPie('APAC', 143000) | Out-Null
Close-OfficeWord -Document $doc -Save$tableData = $data | Select-Object Region, Revenue,
@{ Name = 'RevenueBand'; Expression = { if ($_.Revenue -gt 100000) { 'High' } else { 'Standard' } } }
New-OfficeWord -Path .\Report.docx {
Add-OfficeWordTable -InputObject $tableData -Style 'GridTable1LightAccent1'
}$ppt = Get-OfficePowerPoint -FilePath .\Deck.pptx
Get-OfficePowerPointSlide -Presentation $ppt
Get-OfficePowerPointSlideSummary -Presentation $ppt
Get-OfficePowerPointNotes -Presentation $ppt
Get-OfficePowerPointShape -Presentation $ppt -Index 0- Word to Markdown and Markdown to Word are now surfaced directly through
OfficeIMO.Word.Markdown. - Excel now has
Add-OfficeExcelTableOfContents,Get-OfficeExcelRange, andGet-OfficeExcelUsedRange. - PowerPoint now has section cmdlets, deck-wide text replacement, slide import helpers, slide copy, transitions, slide sizing, theme inspection, theme updates, and layout switching.
- Excel charts can now be finished with
Set-OfficeExcelChartLegend,Set-OfficeExcelChartDataLabels, andSet-OfficeExcelChartStyle. - Excel now has discoverable URL-image insertion plus smarter external hyperlink helpers.
- Excel summary sheets can now auto-link ranges and header-based columns to workbook tabs or external URLs.
- Backlink placement in Excel TOC flows is safer by default, avoiding overwriting active worksheet data.
Use the examples in this README for the first pass, then move to the generated command reference when you need exact parameters and pipeline behavior.
- OVERVIEW.md explains the project scope and design direction.
- Docs/Readme.md is the generated cmdlet index.
- Docs contains one generated page per command.
- Examples contains runnable scripts grouped by Word, Excel, PowerPoint, Markdown, CSV, and shared samples.
dotnet build .\Sources\PSWriteOffice.sln -c Debug
pwsh -NoLogo -NoProfile -File .\PSWriteOffice.Tests.ps1
pwsh -NoLogo -NoProfile -File .\Build\Validate-PackagedArtefact.ps1Development loading is handled through PSWriteOffice.psm1, which prefers the local debug build in Sources\PSWriteOffice\bin\Debug\.
MIT