Class PresentationEditor
- Namespace
- DocToolkit
- Assembly
- DocToolkit.Pptx.dll
Opens and edits PowerPoint (.pptx) presentations.
public static class PresentationEditor
- Inheritance
-
PresentationEditor
- Inherited Members
Methods
AddChart(byte[], int, ChartType, ChartData, string, double, double, double, double)
Adds a chart to slide slideIndex and returns the updated presentation.
public static byte[] AddChart(byte[] pptx, int slideIndex, ChartType type, ChartData data, string title = "", double leftPoints = 0, double topPoints = 0, double widthPoints = 432, double heightPoints = 252)
Parameters
pptxbyte[]The presentation to add the chart to. It is not modified.
slideIndexint1-based, because that is how a reader numbers slides.
typeChartTypeThe chart's shape.
dataChartDataThe chart's categories and value series.
titlestringThe chart's title. Empty for no title.
leftPointsdoubleThe chart's left edge, in points from the slide's left edge.
topPointsdoubleThe chart's top edge, in points from the slide's top edge.
widthPointsdoubleThe chart's width, in points.
heightPointsdoubleThe chart's height, in points.
Returns
- byte[]
Exceptions
- ArgumentNullException
pptxordatais null.- ArgumentException
pptxis empty.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- DocumentConversionException
The package could not be opened or edited.
AddChartAsync(Stream, int, ChartType, ChartData, string, double, double, double, double, CancellationToken)
Reads a .pptx from source and returns a new presentation with a chart
added to slide slideIndex — see AddChart(byte[], int, ChartType, ChartData, string, double, double, double, double) for the
parameters. source is read to its end and is neither disposed,
closed nor sought.
public static Task<byte[]> AddChartAsync(Stream source, int slideIndex, ChartType type, ChartData data, string title = "", double leftPoints = 0, double topPoints = 0, double widthPoints = 432, double heightPoints = 252, CancellationToken ct = default)
Parameters
sourceStreamslideIndexinttypeChartTypedataChartDatatitlestringleftPointsdoubletopPointsdoublewidthPointsdoubleheightPointsdoublectCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceordatais null.- ArgumentException
sourceis not readable or held no bytes.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
AddChartAsync(string, int, ChartType, ChartData, string, double, double, double, double, CancellationToken)
Reads a .pptx from path and returns a new presentation with a chart
added to slide slideIndex — see AddChart(byte[], int, ChartType, ChartData, string, double, double, double, double) for the
parameters.
public static Task<byte[]> AddChartAsync(string path, int slideIndex, ChartType type, ChartData data, string title = "", double leftPoints = 0, double topPoints = 0, double widthPoints = 432, double heightPoints = 252, CancellationToken ct = default)
Parameters
pathstringThe .pptx to read.
slideIndexint1-based, because that is how a reader numbers slides.
typeChartTypeThe chart's shape.
dataChartDataThe chart's categories and value series.
titlestringThe chart's title. Empty for no title.
leftPointsdoubleThe chart's left edge, in points from the slide's left edge.
topPointsdoubleThe chart's top edge, in points from the slide's top edge.
widthPointsdoubleThe chart's width, in points.
heightPointsdoubleThe chart's height, in points.
ctCancellationTokenCancels the read.
Returns
Exceptions
- ArgumentNullException
pathordatais null.- ArgumentException
pathis blank, or the file it names is empty.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- FileNotFoundException
pathdoes not exist.- DirectoryNotFoundException
path's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
Create(IEnumerable<PptxSlide>)
Creates a deck from slides, one slide each.
This exists for content that comes from data rather than from an existing file: there is no template to edit, so ReplaceText(byte[], IReadOnlyDictionary<string, string>) cannot help, and the same slides produce the same CONTENT on every machine — nothing here consults the current culture. Not the same BYTES: the OpenXml SDK mints fresh relationship ids per package, so two calls with identical slides in the same process differ. Do not build a cache key, a content hash or a golden-file test on the bytes.
An empty sequence is valid and produces a valid deck with no slides.
public static byte[] Create(IEnumerable<PptxSlide> slides)
Parameters
slidesIEnumerable<PptxSlide>The slides, in deck order.
Returns
- byte[]
Examples
byte[] pptx = PresentationEditor.Create(new[]
{
PptxSlide.Titled("Quarterly Report", "Revenue up 12%"),
PptxSlide.Titled("Outlook", "Hiring 3 engineers"),
});
Exceptions
- ArgumentNullException
slidesis null.- ArgumentException
An element of
slidesis null.- DocumentConversionException
The deck could not be built.
CreateAsync(IEnumerable<PptxSlide>, Stream, CancellationToken)
Builds a deck from slides and writes it to
destination. See Create(IEnumerable<PptxSlide>) for the slide semantics.
destination is written, from its current position, and is
not disposed, closed or sought — it belongs to the caller, and may be write-only and
forward-only, such as an HTTP response body.
public static Task CreateAsync(IEnumerable<PptxSlide> slides, Stream destination, CancellationToken ct = default)
Parameters
slidesIEnumerable<PptxSlide>The slides, in deck order.
destinationStreamThe stream the deck is written to.
ctCancellationTokenCancels the build and the write to
destination.
Returns
Exceptions
- ArgumentNullException
slidesordestinationis null.- ArgumentException
An element of
slidesis null, ordestinationis not writable.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The deck could not be built or written.
CreateToFileAsync(IEnumerable<PptxSlide>, string, CancellationToken)
Builds a deck from slides and writes it to outputPath.
See Create(IEnumerable<PptxSlide>) for the slide semantics.
Named CreateToFileAsync rather than a third CreateAsync overload, matching
WorkbookEditor.CreateToFileAsync:
the distinct name keeps which kind of destination a call writes to visible at the call site,
rather than resting on the argument type alone.
The deck is built completely before the output is opened. That ordering is what stops a
failed build truncating a file that was already there, and it is pinned by
FilePathOverloadTests rather than left as a comment — it survives only as long as
nobody rewrites this into a streaming write.
public static Task CreateToFileAsync(IEnumerable<PptxSlide> slides, string outputPath, CancellationToken ct = default)
Parameters
slidesIEnumerable<PptxSlide>The slides, in deck order.
outputPathstringWhere to write the deck. Overwritten if it exists.
ctCancellationTokenCancels the write to
outputPath.
Returns
Exceptions
- ArgumentNullException
slidesoroutputPathis null.- ArgumentException
outputPathis blank, or an element ofslidesis null.- DirectoryNotFoundException
outputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The deck could not be built.
ExtractText(byte[])
All text found on every slide, one entry per text-bearing body, in the order the deck is presented rather than the order the slide parts happen to be related.
A "text-bearing body" is any element holding <a:p> paragraphs: an ordinary shape's <p:txBody>, a shape nested in a group, and a table cell's <a:txBody> alike. Paragraphs within one body are joined with newlines. This is deliberately the same walk ReplaceText(byte[], IReadOnlyDictionary<string, string>) performs, so anything this reports is something that can be replaced and vice versa. Speaker notes and slide masters/layouts are not included.
Each slide's SmartArt diagrams follow that slide's own text-bearing bodies, one entry per diagram — see ReadSmartArt(byte[], int). A SmartArt diagram's text lives in a diagram data part, not a <p:txBody>, so it is not itself a text-bearing body and was invisible here before this was added; it is not something ReplaceText(byte[], IReadOnlyDictionary<string, string>) can reach.
public static IReadOnlyList<string> ExtractText(byte[] pptx)
Parameters
pptxbyte[]
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- DocumentConversionException
The package could not be opened or read.
ExtractTextAsync(Stream, CancellationToken)
Reads a .pptx from source and returns all text found on every slide, one
entry per text-bearing body, in deck order — see ExtractText(byte[]) for
exactly what counts as a text-bearing body. source is read to its
end and is neither disposed, closed nor sought.
public static Task<IReadOnlyList<string>> ExtractTextAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
ExtractTextAsync(string, CancellationToken)
Reads a .pptx from path and returns all text found on every slide, one
entry per text-bearing body, in deck order — see ExtractText(byte[]) for
exactly what counts as a text-bearing body.
public static Task<IReadOnlyList<string>> ExtractTextAsync(string path, CancellationToken ct = default)
Parameters
pathstringThe .pptx to read.
ctCancellationTokenCancels the read.
Returns
- Task<IReadOnlyList<string>>
One entry per text-bearing body, in deck order.
Exceptions
- ArgumentNullException
pathis null.- ArgumentException
pathis blank, or the file it names is empty.- FileNotFoundException
pathdoes not exist.- DirectoryNotFoundException
path's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
InsertSlides(byte[], int, IEnumerable<PptxSlide>)
A copy of pptx with slides inserted so that the
first of them becomes slide atIndex. See Create(IEnumerable<PptxSlide>) for what
a PptxSlide becomes.
Each inserted slide attaches to the layout of the slide immediately before the insertion point — or, when inserting at position 1 of a non-empty deck, the layout of what is currently the first slide — so it renders consistently with its neighbours rather than requiring a caller to name one. A deck with no slides at all falls back to its first slide master's first layout.
The inserted slide's title and body boxes inherit the target layout's own placeholder
position only when that layout positions that placeholder itself — it has a
placeholder of the matching role (same type, and for the body, the same index),
and that placeholder carries its own position and size, and it is one of the
layout's own TOP-LEVEL shapes: a placeholder nested inside a group (p:grpSp) on the
layout does not count, matching role and complete geometry notwithstanding. A hand-designed
deck's own title/body geometry is then honoured rather than overridden.
Otherwise the shape keeps this library's own fixed coordinates, rescaled to fit the target
deck's canvas size. That covers four distinct cases, and the first two are common: a layout
with no placeholder of that role at all (an ordinary "Title Slide" layout uses
ctrTitle/subTitle), a layout that names the role but leaves its geometry to
the slide master (a stock "Title and Content" layout usually does), a layout whose
placeholder carries only part of a box (a position with no size, or a size with no
position), and a layout that positions the role's placeholder only inside a group.
Inheriting in any of these would leave content schema-valid but with no box this library's
render pipeline (which resolves a slide's inherited geometry from the layout's TOP-LEVEL
shape tree only — never from inside a group, and never by resolving layout → master) could
actually draw in — invisible in a render. That is why the fallback exists: it keeps content
visible, positioned by this library's own choice, at the cost of not matching a
hand-designed layout's own intended position in these cases.
public static byte[] InsertSlides(byte[] pptx, int atIndex, IEnumerable<PptxSlide> slides)
Parameters
pptxbyte[]The presentation to insert into. It is not modified.
atIndexint1-based position the first inserted slide will occupy.
1puts them in front of everything;SlideCount + 1appends, which is deliberately allowed — it is the obvious way to say "after everything".slidesIEnumerable<PptxSlide>The slides to insert, in order.
Returns
- byte[]
Exceptions
- ArgumentNullException
pptxorslidesis null.- ArgumentException
pptxis empty, or an element ofslidesis null.- ArgumentOutOfRangeException
atIndexis below 1 or more than one past the last slide.- DocumentConversionException
The package could not be opened or edited, or the slide the new content would attach to has no layout of its own.
InsertSlidesAsync(Stream, int, IEnumerable<PptxSlide>, Stream, CancellationToken)
Reads a .pptx from source, inserts slides at
atIndex, and writes the result to destination — see
InsertSlides(byte[], int, IEnumerable<PptxSlide>) for the insertion and layout rules.
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
public static Task InsertSlidesAsync(Stream source, int atIndex, IEnumerable<PptxSlide> slides, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the .pptx package is read from.
atIndexint1-based insertion position;
SlideCount + 1appends.slidesIEnumerable<PptxSlide>The slides to insert, in order.
destinationStreamThe stream the edited .pptx package is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
sourceis not readable or held no bytes,destinationis not writable, or an element ofslidesis null.- ArgumentOutOfRangeException
atIndexis below 1 or more than one past the last slide.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited, or the slide the new content would attach to has no layout of its own.
InsertSlidesAsync(string, string, int, IEnumerable<PptxSlide>, CancellationToken)
Reads a .pptx from inputPath, inserts slides at
atIndex, and writes the result to outputPath — see
InsertSlides(byte[], int, IEnumerable<PptxSlide>) for the insertion and layout rules. The two paths may be the
same file: the updated bytes are computed in full before outputPath is
opened.
public static Task InsertSlidesAsync(string inputPath, string outputPath, int atIndex, IEnumerable<PptxSlide> slides, CancellationToken ct = default)
Parameters
inputPathstringThe .pptx to read.
outputPathstringWhere to write the result. Overwritten if it exists.
atIndexint1-based insertion position;
SlideCount + 1appends.slidesIEnumerable<PptxSlide>The slides to insert, in order.
ctCancellationTokenCancels the read and the write.
Returns
Exceptions
- ArgumentNullException
A path or
slidesis null.- ArgumentException
A path is blank, the file at
inputPathis empty, or an element ofslidesis null.- ArgumentOutOfRangeException
atIndexis below 1 or more than one past the last slide.- FileNotFoundException
inputPathdoes not exist.- DirectoryNotFoundException
inputPath's oroutputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited, or the slide the new content would attach to has no layout of its own.
InspectSignatures(byte[])
Inspects pptx for digital signatures — whether it carries one, how
many, and who claims to have signed it. Does not validate anything cryptographically; see
ValidateSignatures(byte[], DocumentSignatureValidationOptions?).
public static DocumentSignatureInfo InspectSignatures(byte[] pptx)
Parameters
pptxbyte[]
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- DocumentConversionException
The presentation could not be inspected.
InspectSignaturesAsync(Stream, CancellationToken)
Reads a .pptx from source and inspects it for digital signatures — see
InspectSignatures(byte[]). source is read to its end and is
neither disposed, closed nor sought.
public static Task<DocumentSignatureInfo> InspectSignaturesAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The presentation could not be inspected.
IsProtected(byte[])
Whether pptx is an ENCRYPTED Office document.
public static bool IsProtected(byte[] pptx)
Parameters
pptxbyte[]The bytes to inspect.
Returns
Remarks
This is not a validity check, and a false is not a promise that
anything else will succeed. It distinguishes an encrypted document from a plain one;
input that is neither — an image, a PDF, a text file, random bytes — is not encrypted, so
this answers false for it, while every other method on this class refuses
it. Measured over real files: a JPEG and a PDF both return false here and
both throw from ExtractText.
The summary used to say "that is, whether the other methods on this class will refuse it". That reads as a guard — test it, and if false, proceed — and takes the wrong branch for every input that is not a document at all. The behaviour was always right and only the sentence was wrong, which is why the fix is here and not in the code.
Reads the file signature; it does not try the password and does not need one. A plain PPTX is a ZIP package, an encrypted one is a compound file, and the two are distinguishable from their first eight bytes.
Exceptions
- ArgumentNullException
pptxis null.
IsProtectedAsync(Stream, CancellationToken)
Whether pptx is an ENCRYPTED Office document.
public static Task<bool> IsProtectedAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
ctCancellationTokenCancels the read.
Returns
Remarks
source is read to its end and is neither disposed, closed nor
sought. Unlike IsProtected(byte[]), which answers false for
an empty array, an empty source is rejected — every Stream overload
in this package treats a source that held no bytes as a caller error rather than as content.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.
Protect(byte[], string)
A copy of pptx encrypted with password, so it cannot
be opened without one.
public static byte[] Protect(byte[] pptx, string password)
Parameters
pptxbyte[]The presentation to encrypt.
passwordstringThe password required to open the result. May not be empty.
Returns
- byte[]
Remarks
This is file encryption, not presentation protection. Office offers both under the same menu and they are not the same thing: this scrambles the whole file, so nothing can be read without the password. The other kind - a flag asking a reader not to edit - is a request rather than a lock, and is deliberately not exposed here.
The result is not a PPTX package any more. An encrypted Office document is a compound file with the package sealed inside it, so every other method on this class refuses it - call Unprotect(byte[], string) first. That refusal is the honest behaviour: those methods could not read the content even if they tried.
Exceptions
- ArgumentNullException
pptxorpasswordis null.- ArgumentException
pptxis empty, orpasswordis empty.- DocumentConversionException
The presentation could not be read or encrypted.
ProtectAsync(Stream, Stream, string, CancellationToken)
Reads a presentation from source and writes the encrypted copy to
destination.
Neither stream is disposed, closed or sought.
public static Task ProtectAsync(Stream source, Stream destination, string password, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
destinationStreamThe stream the encrypted presentation is written to.
passwordstringThe password required to open the result. May not be empty.
ctCancellationTokenCancels the read and the write.
Returns
Remarks
This is file encryption, not presentation protection. Office offers both under the same menu and they are not the same thing: this scrambles the whole file, so nothing can be read without the password. The other kind - a flag asking a reader not to edit - is a request rather than a lock, and is deliberately not exposed here.
The result is not a PPTX package any more. An encrypted Office document is a compound file with the package sealed inside it, so every other method on this class refuses it - call Unprotect(byte[], string) first. That refusal is the honest behaviour: those methods could not read the content even if they tried.
ReadMetadata(byte[])
The document properties pptx carries.
public static DocumentMetadata ReadMetadata(byte[] pptx)
Parameters
pptxbyte[]
Returns
Remarks
On a freshly created deck every property is null, exactly like DOCX and XLSX — measured directly rather than assumed. That is not true of WithMetadata(byte[], DocumentMetadata); see its own remarks for why writing and reading disagree here.
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- DocumentConversionException
The presentation could not be read.
ReadMetadataAsync(Stream, CancellationToken)
The document properties pptx carries.
public static Task<DocumentMetadata> ReadMetadataAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
ctCancellationTokenCancels the read.
Returns
Remarks
source is read to its end and is neither disposed, closed nor sought.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The presentation could not be read.
ReadNotes(byte[], int)
The speaker notes on slide slideIndex, or an empty string when it has
none. slideIndex is 1-based, like ReadSlide(byte[], int).
public static string ReadNotes(byte[] pptx, int slideIndex)
Parameters
Returns
Remarks
A slide with no notes returns Empty, never null. Measured rather than assumed: every slide carries a notes object whose text is empty until something writes to it, so there is no "has notes" state to distinguish from "notes are blank" and the API does not invent one.
Notes are not returned by ExtractText(byte[]), which reads the slide bodies. They are a separate surface a reader has to ask for.
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- DocumentConversionException
The package could not be opened or read.
ReadNotesAsync(Stream, int, CancellationToken)
The speaker notes on slide slideIndex, or an empty string when it has
none. slideIndex is 1-based, like ReadSlide(byte[], int).
public static Task<string> ReadNotesAsync(Stream source, int slideIndex, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
slideIndexintThe 1-based slide number.
ctCancellationTokenCancels the read.
Returns
Remarks
source is read to its end and is neither disposed, closed nor sought.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
ReadSlide(byte[], int)
All text found on slide index — see ExtractText(byte[])
for exactly what counts as a text-bearing body. Same per-body granularity as that method,
scoped to one slide.
public static IReadOnlyList<string> ReadSlide(byte[] pptx, int index)
Parameters
pptxbyte[]The presentation to read.
indexint1-based, because that is how a reader numbers slides.
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- DocumentConversionException
The package could not be opened or read.
ReadSlideAsync(Stream, int, CancellationToken)
Reads a .pptx from source and returns all text found on slide
index — see ReadSlide(byte[], int) for exactly what counts
as a text-bearing body. source is read to its end and is neither
disposed, closed nor sought.
public static Task<IReadOnlyList<string>> ReadSlideAsync(Stream source, int index, CancellationToken ct = default)
Parameters
sourceStreamindexintctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
ReadSlideAsync(string, int, CancellationToken)
Reads a .pptx from path and returns all text found on slide
index — see ReadSlide(byte[], int) for exactly what counts
as a text-bearing body.
public static Task<IReadOnlyList<string>> ReadSlideAsync(string path, int index, CancellationToken ct = default)
Parameters
pathstringThe .pptx to read.
indexint1-based, because that is how a reader numbers slides.
ctCancellationTokenCancels the read.
Returns
Exceptions
- ArgumentNullException
pathis null.- ArgumentException
pathis blank, or the file it names is empty.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- FileNotFoundException
pathdoes not exist.- DirectoryNotFoundException
path's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
ReadSmartArt(byte[], int)
The text of every SmartArt diagram on slide index, one entry per
diagram, each diagram's nodes joined with newlines in the order OfficeIMO reports them.
A SmartArt diagram's text lives in a diagram data part, not a text-bearing shape body, so it is invisible to ReadSlide(byte[], int) — ExtractText(byte[]) reports it too, alongside every ordinary text-bearing body, for exactly that reason.
An empty list means the slide has no SmartArt, which is not an error — the same convention ReadSlide(byte[], int) uses for a slide with no text-bearing shapes.
public static IReadOnlyList<string> ReadSmartArt(byte[] pptx, int index)
Parameters
pptxbyte[]The presentation to read.
indexint1-based, because that is how a reader numbers slides.
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- DocumentConversionException
The package could not be opened or read.
ReadSmartArtAsync(Stream, int, CancellationToken)
Reads a .pptx from source and returns the text of every SmartArt
diagram on slide index — see ReadSmartArt(byte[], int).
source is read to its end and is neither disposed, closed nor
sought.
public static Task<IReadOnlyList<string>> ReadSmartArtAsync(Stream source, int index, CancellationToken ct = default)
Parameters
sourceStreamindexintctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
ReadSmartArtAsync(string, int, CancellationToken)
Reads a .pptx from path and returns the text of every SmartArt diagram
on slide index — see ReadSmartArt(byte[], int).
public static Task<IReadOnlyList<string>> ReadSmartArtAsync(string path, int index, CancellationToken ct = default)
Parameters
pathstringThe .pptx to read.
indexint1-based, because that is how a reader numbers slides.
ctCancellationTokenCancels the read.
Returns
Exceptions
- ArgumentNullException
pathis null.- ArgumentException
pathis blank, or the file it names is empty.- ArgumentOutOfRangeException
indexis below 1, or above the deck's slide count.- FileNotFoundException
pathdoes not exist.- DirectoryNotFoundException
path's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
RemoveSlides(byte[], IEnumerable<int>)
A copy of pptx with the slides at indices removed.
public static byte[] RemoveSlides(byte[] pptx, IEnumerable<int> indices)
Parameters
pptxbyte[]The presentation to remove slides from. It is not modified.
indicesIEnumerable<int>1-based slide numbers to remove, each exactly once and in any order — not a contiguous range, so
[2, 7]removes exactly those two slides in one call.
Returns
- byte[]
Exceptions
- ArgumentNullException
pptxorindicesis null.- ArgumentException
pptxis empty, orindicescontains a duplicate.- ArgumentOutOfRangeException
An index in
indicesis outside the deck's slide range, or removing every listed index would leave a zero-slide deck.- DocumentConversionException
The package could not be opened or edited.
RemoveSlidesAsync(Stream, IEnumerable<int>, Stream, CancellationToken)
Reads a .pptx from source, removes the slides at
indices, and writes the result to destination — see
RemoveSlides(byte[], IEnumerable<int>) for exactly what indices accepts.
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
public static Task RemoveSlidesAsync(Stream source, IEnumerable<int> indices, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the .pptx package is read from.
indicesIEnumerable<int>1-based slide numbers to remove, each exactly once, any order.
destinationStreamThe stream the edited .pptx package is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
sourceis not readable or held no bytes,destinationis not writable, orindicescontains a duplicate.- ArgumentOutOfRangeException
An index in
indicesis outside the deck's slide range, or removing every listed index would leave a zero-slide deck.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
RemoveSlidesAsync(string, string, IEnumerable<int>, CancellationToken)
Reads a .pptx from inputPath, removes the slides at
indices, and writes the result to outputPath — see
RemoveSlides(byte[], IEnumerable<int>) for exactly what indices accepts. The two
paths may be the same file: the updated bytes are computed in full before
outputPath is opened.
public static Task RemoveSlidesAsync(string inputPath, string outputPath, IEnumerable<int> indices, CancellationToken ct = default)
Parameters
inputPathstringThe .pptx to read.
outputPathstringWhere to write the result. Overwritten if it exists.
indicesIEnumerable<int>1-based slide numbers to remove, each exactly once, any order.
ctCancellationTokenCancels the read and the write.
Returns
Exceptions
- ArgumentNullException
A path or
indicesis null.- ArgumentException
A path is blank, the file at
inputPathis empty, orindicescontains a duplicate.- ArgumentOutOfRangeException
An index in
indicesis outside the deck's slide range, or removing every listed index would leave a zero-slide deck.- FileNotFoundException
inputPathdoes not exist.- DirectoryNotFoundException
inputPath's oroutputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
ReorderSlides(byte[], IEnumerable<int>)
A copy of pptx with its slides in the order given by
order, which holds 1-based slide numbers.
public static byte[] ReorderSlides(byte[] pptx, IEnumerable<int> order)
Parameters
pptxbyte[]The presentation to reorder. It is not modified.
orderIEnumerable<int>A permutation of every slide — the same slides, in a different order. Not a subset, and no repeats.
Returns
- byte[]
Exceptions
- ArgumentNullException
pptxororderis null.- ArgumentException
pptxis empty, ororderis not a permutation of 1..SlideCount.- DocumentConversionException
The package could not be opened or edited.
ReorderSlidesAsync(Stream, IEnumerable<int>, Stream, CancellationToken)
Reads a .pptx from source, reorders its slides per
order, and writes the result to destination — see
ReorderSlides(byte[], IEnumerable<int>) for exactly what order must contain.
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
public static Task ReorderSlidesAsync(Stream source, IEnumerable<int> order, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the .pptx package is read from.
orderIEnumerable<int>A permutation of every slide's 1-based number.
destinationStreamThe stream the edited .pptx package is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
sourceis not readable or held no bytes,destinationis not writable, ororderis not a permutation of every slide.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
ReorderSlidesAsync(string, string, IEnumerable<int>, CancellationToken)
Reads a .pptx from inputPath, reorders its slides per
order, and writes the result to outputPath — see
ReorderSlides(byte[], IEnumerable<int>) for exactly what order must contain. The two
paths may be the same file: the updated bytes are computed in full before
outputPath is opened.
public static Task ReorderSlidesAsync(string inputPath, string outputPath, IEnumerable<int> order, CancellationToken ct = default)
Parameters
inputPathstringThe .pptx to read.
outputPathstringWhere to write the result. Overwritten if it exists.
orderIEnumerable<int>A permutation of every slide's 1-based number.
ctCancellationTokenCancels the read and the write.
Returns
Exceptions
- ArgumentNullException
A path or
orderis null.- ArgumentException
A path is blank, the file at
inputPathis empty, ororderis not a permutation of every slide.- FileNotFoundException
inputPathdoes not exist.- DirectoryNotFoundException
inputPath's oroutputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
ReplaceImage(byte[], string, byte[])
Replaces every shape whose text is exactly placeholder with
image, which is scaled to fit inside that shape's box and centred there.
Position and size come from the template, so there is nothing to pass: a designer draws a
box in PowerPoint where the image belongs and the image lands there. This deliberately does
not mirror DocxEditor.ReplaceImage's size arguments — a DOCX image is inline
in the text flow and needs a size, a PPTX picture is a positioned shape and already has one.
The shape's text must be nothing but the placeholder. The unit replaced is the whole shape,
so a shape reading Chart: {{chart}} (Q3) would lose the words around the placeholder
— silently, and with a schema-valid result. That is refused instead.
PNG and JPEG only, detected from magic bytes rather than any filename.
public static byte[] ReplaceImage(byte[] pptx, string placeholder, byte[] image)
Parameters
Returns
- byte[]
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
pptxorimageis empty, orplaceholderis blank.- DocumentConversionException
The placeholder appears nowhere, appears only inside a grouped shape, a matched shape holds other text, a matched shape has no explicit position, the image is neither PNG nor JPEG, or the package could not be edited.
ReplaceImageAsync(Stream, string, byte[], Stream, CancellationToken)
Reads a .pptx from source, replaces every shape whose text is exactly
placeholder with image, and writes the result to
destination — see ReplaceImage(byte[], string, byte[]) for exactly what counts as a
match and how the image is fit into the matched shape's box.
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
public static Task ReplaceImageAsync(Stream source, string placeholder, byte[] image, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the .pptx package is read from.
placeholderstringThe placeholder text a shape must hold, and hold only.
imagebyte[]PNG or JPEG bytes. The format is decided by the bytes, never a filename.
destinationStreamThe stream the edited .pptx package is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
placeholderis blank,imageis empty,sourceis not readable or held no bytes, ordestinationis not writable.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The placeholder appears nowhere, appears only inside a grouped shape, a matched shape holds other text, a matched shape has no explicit position, the image is neither PNG nor JPEG, or the package could not be edited.
ReplaceImageAsync(string, string, string, byte[], CancellationToken)
Reads a .pptx from inputPath, replaces every shape whose text is exactly
placeholder with image, and writes the result to
outputPath — see ReplaceImage(byte[], string, byte[]) for exactly what counts as a
match and how the image is fit into the matched shape's box. The two paths may be the same
file: the updated bytes are computed in full before outputPath is opened,
so a document that fails to process — cannot be read, or cannot be edited — leaves
outputPath untouched. That guarantee does not extend to a failure during
the write itself: a full disk, a cancellation, or the process dying mid-write can still leave
a partial file, so in-place editing of an irreplaceable document is not crash-safe.
public static Task ReplaceImageAsync(string inputPath, string outputPath, string placeholder, byte[] image, CancellationToken ct = default)
Parameters
inputPathstringThe .pptx to read.
outputPathstringWhere to write the result. Overwritten if it exists.
placeholderstringThe placeholder text a shape must hold, and hold only.
imagebyte[]PNG or JPEG bytes. The format is decided by the bytes, never a filename.
ctCancellationTokenCancels the read and the write.
Returns
Exceptions
- ArgumentNullException
A path,
placeholderorimageis null.- ArgumentException
A path is blank, the file at
inputPathis empty,placeholderis blank, orimageis empty.- FileNotFoundException
inputPathdoes not exist.- DirectoryNotFoundException
inputPath's oroutputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The placeholder appears nowhere, appears only inside a grouped shape, a matched shape holds other text, a matched shape has no explicit position, the image is neither PNG nor JPEG, or the package could not be edited.
ReplaceText(byte[], IReadOnlyDictionary<string, string>)
Replaces every key with its value across all slide text, returning updated bytes.
PowerPoint routinely splits a single visible word across several <a:t> runs (spell-check state, formatting changes), so a naive per-run replace misses any placeholder that straddles a run boundary. Substitution therefore happens against the concatenated text of each paragraph, but the result is spliced back into only the runs the match actually overlaps: runs outside a match keep their text and their formatting untouched. When a placeholder does straddle runs, the replacement value is written into the run holding its first character and so inherits that run's formatting.
Keys are matched in a single left-to-right pass and the longest key wins at any given offset, so a substituted value is never rescanned for further placeholders. Slides are visited in deck order; speaker notes and slide masters/layouts are not touched.
public static byte[] ReplaceText(byte[] pptx, IReadOnlyDictionary<string, string> replacements)
Parameters
pptxbyte[]replacementsIReadOnlyDictionary<string, string>
Returns
- byte[]
Exceptions
- ArgumentNullException
Either argument is null.
- ArgumentException
pptxis empty.- DocumentConversionException
The package could not be opened or edited.
ReplaceTextAsync(Stream, IReadOnlyDictionary<string, string>, Stream, CancellationToken)
Reads a .pptx from source, replaces every key with its value across all
slide text, and writes the result to destination — see
ReplaceText(byte[], IReadOnlyDictionary<string, string>) for exactly what counts as a match and how formatting survives it.
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
public static Task ReplaceTextAsync(Stream source, IReadOnlyDictionary<string, string> replacements, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the .pptx package is read from.
replacementsIReadOnlyDictionary<string, string>Each key is replaced by its value, longest key wins per match.
destinationStreamThe stream the edited .pptx package is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Exceptions
- ArgumentNullException
Any argument is null.
- ArgumentException
sourceis not readable or held no bytes, ordestinationis not writable.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
ReplaceTextAsync(string, string, IReadOnlyDictionary<string, string>, CancellationToken)
Reads a .pptx from inputPath, replaces every key with its value across
all slide text, and writes the result to outputPath — see
ReplaceText(byte[], IReadOnlyDictionary<string, string>) for exactly what counts as a match and how formatting survives
it. The two paths may be the same file: the updated bytes are computed in full before
outputPath is opened, so a document that fails to process — cannot be
read, or cannot be edited — leaves outputPath untouched. That guarantee
does not extend to a failure during the write itself: a full disk, a cancellation, or the
process dying mid-write can still leave a partial file, so in-place editing of an
irreplaceable document is not crash-safe.
public static Task ReplaceTextAsync(string inputPath, string outputPath, IReadOnlyDictionary<string, string> replacements, CancellationToken ct = default)
Parameters
inputPathstringThe .pptx to read.
outputPathstringWhere to write the result. Overwritten if it exists.
replacementsIReadOnlyDictionary<string, string>Each key is replaced by its value, longest key wins per match.
ctCancellationTokenCancels the read and the write.
Returns
Exceptions
- ArgumentNullException
A path or
replacementsis null.- ArgumentException
A path is blank, or the file at
inputPathis empty.- FileNotFoundException
inputPathdoes not exist.- DirectoryNotFoundException
inputPath's oroutputPath's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or edited.
SetNotes(byte[], int, string)
Sets the speaker notes on slide slideIndex and returns the updated deck.
slideIndex is 1-based, like ReadSlide(byte[], int).
public static byte[] SetNotes(byte[] pptx, int slideIndex, string notes)
Parameters
pptxbyte[]The presentation to edit. It is not modified.
slideIndexintThe 1-based slide number.
notesstringThe notes text. Empty clears them.
Returns
- byte[]
Remarks
Replaces whatever the slide's notes said; pass an empty string to clear them. Every other slide is left exactly as it was — measured, because editing one slide's notes and silently disturbing another's is the kind of loss no text-reading test would notice.
Exceptions
- ArgumentNullException
pptxornotesis null.- ArgumentException
pptxis empty.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- DocumentConversionException
The package could not be opened or written.
SetNotesAsync(Stream, int, string, Stream, CancellationToken)
Sets the speaker notes on slide slideIndex and returns the updated deck.
slideIndex is 1-based, like ReadSlide(byte[], int).
public static Task SetNotesAsync(Stream source, int slideIndex, string notes, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
slideIndexintThe 1-based slide number.
notesstringThe notes text. Empty clears them.
destinationStreamThe stream the updated deck is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Remarks
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
Exceptions
- ArgumentNullException
An argument is null.
- ArgumentException
sourceis not readable or held no bytes, ordestinationis not writable.- ArgumentOutOfRangeException
slideIndexis below 1, or above the deck's slide count.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or written.
SlideCount(byte[])
Number of slides in the deck, as counted from the deck's slide list.
public static int SlideCount(byte[] pptx)
Parameters
pptxbyte[]
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- DocumentConversionException
The package could not be opened or read.
SlideCountAsync(Stream, CancellationToken)
Reads a .pptx from source and returns its slide count, counted from the
deck's slide list. source is read to its end and is neither
disposed, closed nor sought.
public static Task<int> SlideCountAsync(Stream source, CancellationToken ct = default)
Parameters
sourceStreamctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
SlideCountAsync(string, CancellationToken)
Reads a .pptx from path and returns its slide count, as counted from
the deck's slide list — see SlideCount(byte[]) for details.
public static Task<int> SlideCountAsync(string path, CancellationToken ct = default)
Parameters
pathstringThe .pptx to read.
ctCancellationTokenCancels the read.
Returns
Exceptions
- ArgumentNullException
pathis null.- ArgumentException
pathis blank, or the file it names is empty.- FileNotFoundException
pathdoes not exist.- DirectoryNotFoundException
path's directory does not exist.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The package could not be opened or read.
Unprotect(byte[], string)
A copy of pptx with its encryption removed, so the rest of this class
can work on it.
public static byte[] Unprotect(byte[] pptx, string password)
Parameters
pptxbyte[]The encrypted presentation.
passwordstringThe password the presentation was encrypted with.
Returns
- byte[]
Remarks
The output is not protected in any way. That is what was asked for, but the bytes this returns are readable by anyone who obtains them.
A presentation that was never encrypted is reported as such rather than passed through, because silently returning the input would make a broken pipeline look like a working one.
Exceptions
- ArgumentNullException
pptxorpasswordis null.- ArgumentException
pptxis empty, orpasswordis empty.- DocumentConversionException
The password was wrong, the presentation was not encrypted, or it could not be read.
UnprotectAsync(Stream, Stream, string, CancellationToken)
Reads an encrypted presentation from source and writes the unprotected copy to
destination.
Neither stream is disposed, closed or sought.
public static Task UnprotectAsync(Stream source, Stream destination, string password, CancellationToken ct = default)
Parameters
sourceStreamThe stream the encrypted presentation is read from.
destinationStreamThe stream the unprotected presentation is written to.
passwordstringThe password the presentation was encrypted with.
ctCancellationTokenCancels the read and the write.
Returns
Remarks
The output is not protected in any way. That is what was asked for, but the bytes this returns are readable by anyone who obtains them.
A presentation that was never encrypted is reported as such rather than passed through, because silently returning the input would make a broken pipeline look like a working one.
ValidateSignatures(byte[], DocumentSignatureValidationOptions?)
Validates every digital signature pptx carries, returning the
report-level tamper-detection verdict alongside each signature's own certificate chain
trust and revocation status. Read
DocumentSignatureValidationResult's own remarks before treating its
CryptographicStatus as tamper detection — it is not; the report-level
IsCryptographicallyValid is. Never
performs revocation checking or certificate downloads over the network, regardless of
options — see DocumentSignatureValidationOptions's own
remarks.
public static DocumentSignatureValidationReport ValidateSignatures(byte[] pptx, DocumentSignatureValidationOptions? options = null)
Parameters
pptxbyte[]optionsDocumentSignatureValidationOptions
Returns
Exceptions
- ArgumentNullException
pptxis null.- ArgumentException
pptxis empty.- DocumentConversionException
The presentation could not be validated.
ValidateSignaturesAsync(Stream, DocumentSignatureValidationOptions?, CancellationToken)
Reads a .pptx from source and validates its digital signatures — see
ValidateSignatures(byte[], DocumentSignatureValidationOptions?). source is read to its end and is
neither disposed, closed nor sought.
public static Task<DocumentSignatureValidationReport> ValidateSignaturesAsync(Stream source, DocumentSignatureValidationOptions? options = null, CancellationToken ct = default)
Parameters
sourceStreamoptionsDocumentSignatureValidationOptionsctCancellationToken
Returns
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourceis not readable or held no bytes.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The presentation could not be validated.
WithMetadata(byte[], DocumentMetadata)
A copy of pptx carrying metadata.
public static byte[] WithMetadata(byte[] pptx, DocumentMetadata metadata)
Parameters
pptxbyte[]metadataDocumentMetadata
Returns
- byte[]
Remarks
A null property leaves what the presentation already had in place, so stamping a title does not silently erase an author. Pass an empty string to clear one.
One exception, forced by OfficeIMO itself: Creator never
survives as null through this method. Measured directly: OfficeIMO.PowerPoint's own
Save() unconditionally stamps Creator to "OfficeIMO" whenever it is
empty at save time — even on a call that never touches Creator at all, and even on a
bare save that changes nothing else. ReadMetadata(byte[]) alone, with no save
involved, correctly reports null on an untouched deck; it is specifically
going through this method — which always saves — that loses the distinction. DOCX and
XLSX do not have this behaviour; it is PowerPoint-side only, and there is no supported way
around it short of never calling this method.
A second, narrower OfficeIMO defect is also worked around here rather than merely
avoided. A deck built by Create(IEnumerable<PptxSlide>)
carries zero core-properties relationships — verified directly, and identical to what
DocxDocumentWriter produces for DOCX, which does not hit this. Touching
BuiltinDocumentProperties on such a deck before Save() makes OfficeIMO create
two relationships instead of one, and the save then fails with
FileFormatException ("more than one Core Properties relationship") — a defect
in OfficeIMO.PowerPoint's own save path, not in the input. The retry below seeds exactly one
relationship via the plain, non-experimental Package API before OfficeIMO ever
sees the bytes, then tries again. The seed value is drawn from metadata
itself — this branch is only ever reached after a real setter has already fired, so at
least one of the four properties is guaranteed non-null — so the throwaway seed write and
the real value applied moments later are identical, and nothing leaks through as a
placeholder the way a made-up seed string would.
Exceptions
- ArgumentNullException
pptxormetadatais null.- ArgumentException
pptxis empty.- DocumentConversionException
The presentation could not be read or written.
WithMetadataAsync(Stream, DocumentMetadata, Stream, CancellationToken)
A copy of pptx carrying metadata.
public static Task WithMetadataAsync(Stream source, DocumentMetadata metadata, Stream destination, CancellationToken ct = default)
Parameters
sourceStreamThe stream the presentation is read from.
metadataDocumentMetadataThe properties to stamp.
destinationStreamThe stream the updated presentation is written to.
ctCancellationTokenCancels the read, the edit and the write.
Returns
Remarks
source is read to its end and destination is
written; neither is disposed, closed or sought, and neither has to be seekable.
Exceptions
- ArgumentNullException
source,metadataordestinationis null.- ArgumentException
sourceis not readable or held no bytes, ordestinationis not writable.- OperationCanceledException
ctwas cancelled.- DocumentConversionException
The presentation could not be read or written.