Skip to content

About

Open-source C#/.NET library for creating, reading and editing PowerPoint (.pptx) presentations — slides, shapes, text, tables, fills, effects, notes and comments. MIT licensed.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Repository files navigation

Aspose.Slides FOSS for .NET

CI NuGet License: MIT .NET

An MIT-licensed .NET library that creates, reads and edits PowerPoint .pptx presentations by building the Office Open XML package itself — no PowerPoint installation, no COM interop, no native dependency and no NuGet dependencies at all.

It is for developers who need to generate or modify decks on a server or in a build, and who are working inside the PowerPoint file format. It is not a renderer or a converter: it does not produce PDF, HTML or images, and the things it cannot do are listed in full under What it cannot do.


At a glance

flowchart TD
  subgraph StartingPoints["Starting Points"]
    direction TB
    i1["An existing PPTX presentation"]
  end
  PRODUCT["Aspose.Slides FOSS for .NET"]
  subgraph Capabilities["Core Capabilities"]
    direction LR
    subgraph capl[" "]
      direction TB
      c1["Presentation, slide, and section creation and editing"]
      c2["Shape creation (AutoShape, Table, Connector, PictureFrame)"]
      c3["Text formatting (TextFrame, Paragraph, Portion)"]
      c4["Fill, line, and 3D shape styling"]
    end
    subgraph capr[" "]
      direction TB
      c5["Visual effects (shadow, glow, blur, reflection)"]
      c6["Document properties (core, app, custom)"]
      c7["Speaker notes and classic comments"]
      c8["Image embedding"]
    end
  end
  subgraph Outputs["Outputs"]
    direction TB
    o1["PPTX, PPSX or POTX package"]
  end
  StartingPoints --> PRODUCT --> Capabilities --> Outputs
Loading

The diagram is an overview, not a contract. Each box is expanded, with the XML it produces, under What it can do; the boundaries are under What it cannot do.


Requirements

Target frameworks net8.0 and net10.0
Package dependencies none — the library declares no PackageReference
Native dependencies none — no DllImport, no LibraryImport, no unsafe code
Platforms the CI workflow builds and runs every test on ubuntu-latest, windows-latest and macos-latest

Both are built, tested and shipped in the package; CI runs the whole suite on each. .NET 8 and .NET 10 are the two long-term releases still in support.

Installation

dotnet add package Aspose.Slides.FOSS

The package targets net8.0 and net10.0 and has no dependencies. Note the casing: the package id is Aspose.Slides.FOSS, while the assembly and the namespaces are Aspose.Slides.Foss.

Two other routes work as well — building from source, and the package every CI run produces.

Build from source

git clone https://github.com/aspose-slides-foss/Aspose.Slides-FOSS-for-.NET.git
cd Aspose.Slides-FOSS-for-.NET
dotnet build src/Aspose.Slides.Foss/Aspose.Slides.Foss.csproj --configuration Release

Then reference the project from your own:

<ItemGroup>
  <ProjectReference Include="../Aspose.Slides-FOSS-for-.NET/src/Aspose.Slides.Foss/Aspose.Slides.Foss.csproj" />
</ItemGroup>

Install the package CI built

Every push, on any branch, whose tests pass produces a .nupkg and a symbol .snupkg as workflow artefacts. Download them from the Actions tab — GitHub hands you a .zip, so extract it first; NuGet reads a folder of .nupkg files, not a zip of them — put the extracted files in a folder, and point NuGet at that folder:

<!-- nuget.config next to your solution -->
<configuration>
  <packageSources>
    <add key="local" value="./local-packages" />
  </packageSources>
</configuration>
dotnet add package Aspose.Slides.FOSS --version 26.9.0

Use whatever version the artefact you downloaded is called; a CI build carries the version in Directory.Build.props at that commit, which may be ahead of the last release.


Quick start

using Aspose.Slides.Foss;
using Aspose.Slides.Foss.Export;

using (var presentation = new Presentation())
{
    ISlide slide = presentation.Slides[0];
    IAutoShape shape = slide.Shapes!.AddAutoShape(ShapeType.Rectangle, 50, 50, 400, 100);
    shape.AddTextFrame("Hello from Aspose.Slides FOSS");

    presentation.Save("hello.pptx", SaveFormat.Pptx);
}

using var reopened = new Presentation("hello.pptx");
var reread = (IAutoShape)reopened.Slides[0].Shapes![0];

Console.WriteLine($"slides: {reopened.Slides.Count}");
Console.WriteLine($"shapes: {reopened.Slides[0].Shapes!.Count}");
Console.WriteLine($"text:   {reread.TextFrame?.Text}");

Output:

slides: 1
shapes: 1
text:   Hello from Aspose.Slides FOSS

A new Presentation is a 13-part package with one slide, one master, one layout and a slide size of 9144000 × 6858000 EMU — 4:3, type="screen4x3". There is no API to change the slide size.

Why the !

IBaseSlide.Shapes is declared IShapeCollection? and returns null for a slide that is not backed by a package part; a few other members are annotated the same way. The samples here use the null-forgiving operator so that they compile without warnings in a project with <Nullable>enable</Nullable>, which is the default for new .NET projects. Every sample on this page was compiled with nullable enabled and produced zero warnings.


Examples

Every example below was compiled and executed against this revision, and the values quoted after each one were read out of the .pptx it wrote by an independent ZIP/XML reader — not by asking the library to read its own file back.

Three namespaces cover every sample on this page, and each sample below assumes all three:

using Aspose.Slides.Foss;           // Presentation, the I* interfaces, ShapeType, FontData
using Aspose.Slides.Foss.Drawing;   // Color, PointF
using Aspose.Slides.Foss.Export;    // SaveFormat

Color and PointF are this library's own types in Aspose.Slides.Foss.Drawing; they are not the System.Drawing types of the same name, and neither namespace is in scope by default.

Those three are this library's own namespaces. The samples also use Console, DateTime, File, FileStream and MemoryStream, which come from System and System.IO: <ImplicitUsings> brings both into scope and is on by default in a project from dotnet new console — the same default this page relies on for Nullable above. Turn implicit usings off and you add those two using lines yourself.

Text and formatting

using var presentation = new Presentation();
IAutoShape shape = presentation.Slides[0].Shapes!.AddAutoShape(
    ShapeType.Rectangle, 50, 50, 400, 150);
ITextFrame textFrame = shape.AddTextFrame("Formatted text")!;

IParagraph paragraph = textFrame.Paragraphs[0];
paragraph.ParagraphFormat.Alignment = TextAlignment.Center;

IBasePortionFormat format = paragraph.Portions[0].PortionFormat!;
format.FontHeight = 24;
format.FontBold = NullableBool.True;
format.LatinFont = new FontData("Verdana");
format.FillFormat!.FillType = FillType.Solid;
format.FillFormat.SolidFillColor.Color = Color.FromArgb(255, 0, 70, 127);

presentation.Save("text.pptx", SaveFormat.Pptx);

In ppt/slides/slide1.xml: <a:rPr b="1" sz="2400">, <a:latin typeface="Verdana"/>, <a:pPr algn="ctr">.

Tables

using var presentation = new Presentation();
ITable table = presentation.Slides[0].Shapes!.AddTable(
    50, 50, [150.0, 150.0], [40.0, 40.0]);

table.Rows[0][0].TextFrame!.Text = "Region";
table.Rows[0][1].TextFrame!.Text = "Revenue";
table.Rows[1][0].TextFrame!.Text = "EMEA";
table.Rows[1][1].TextFrame!.Text = "1,240";

table.MergeCells(table.Rows[0][0], table.Rows[0][1], allowSplitting: false);

presentation.Save("table.pptx", SaveFormat.Pptx);

Four <a:tc> cells, two of them carrying a merge attribute.

Pictures

using var presentation = new Presentation();

// from a byte array
IPPImage image = presentation.Images.AddImage(File.ReadAllBytes("photo.png"));
presentation.Slides[0].Shapes!.AddPictureFrame(
    ShapeType.Rectangle, 50, 50, 200, 200, image);

// or from a stream
using FileStream stream = File.OpenRead("photo.png");
IPPImage streamed = presentation.Images.AddImage(stream);

presentation.Save("picture.pptx", SaveFormat.Pptx);

One <a:blip r:embed="…"> in the slide and one part under ppt/media/. There is no overload that takes a file path — read the bytes yourself, as above.

Effects

using var presentation = new Presentation();
IAutoShape shape = presentation.Slides[0].Shapes!.AddAutoShape(
    ShapeType.Rectangle, 50, 50, 300, 120);

shape.FillFormat.FillType = FillType.Solid;
shape.FillFormat.SolidFillColor.Color = Color.FromArgb(255, 30, 120, 200);

IEffectFormat effects = shape.EffectFormat;
effects.EnableOuterShadowEffect();
effects.OuterShadowEffect!.BlurRadius = 10;
effects.OuterShadowEffect.Distance = 5;

presentation.Save("effects.pptx", SaveFormat.Pptx);

All eight effects were enabled one at a time, each into its own file, and each produced its element inside <a:effectLst>: a:outerShdw, a:innerShdw, a:glow, a:softEdge, a:reflection, a:blur, a:prstShdw, a:fillOverlay.

Notes and comments

using var presentation = new Presentation();
ISlide slide = presentation.Slides[0];

INotesSlide notes = slide.NotesSlideManager.AddNotesSlide();
notes.NotesTextFrame.Text = "Open with the revenue figures.";

ICommentAuthor author = presentation.CommentAuthors.AddAuthor("Jane Smith", "JS");
author.Comments.AddComment("Check these numbers.", slide, new PointF(2.0f, 2.0f), DateTime.UtcNow);

presentation.Save("notes-comments.pptx", SaveFormat.Pptx);

Writes ppt/notesSlides/notesSlide1.xml with its ppt/notesMasters/notesMaster1.xml, and the classic comment pair ppt/commentAuthors.xml + ppt/comments/comment1.xml. It does not write the modern ppt/threadedComments/ part — see What it cannot do.

Sections

using var presentation = new Presentation();
presentation.Slides.AddEmptySlide(presentation.LayoutSlides[0]);
presentation.Slides.AddEmptySlide(presentation.LayoutSlides[0]);

presentation.Sections.AddSection("Introduction", presentation.Slides[0]);
presentation.Sections.AddSection("Detail", presentation.Slides[1]);

presentation.Save("sections.pptx", SaveFormat.Pptx);

Two <p14:section> elements in ppt/presentation.xml. A Section has no public constructor: it is created through Sections.AddSection or Sections.AppendEmptySection, which bind it to the presentation whose slides it divides.

Streams

using var presentation = new Presentation();
presentation.Slides[0].Shapes!.AddAutoShape(ShapeType.Rectangle, 10, 10, 100, 50);

using var buffer = new MemoryStream();
presentation.Save(buffer, SaveFormat.Pptx);

buffer.Position = 0;
using var reopened = new Presentation(buffer);

Presentation opens from a path or a Stream, with or without ILoadOptions, and Save has the matching overloads including a slide-subset one.


What it can do

Everything in this list was exercised through the public API and then confirmed by reading the XML inside the file that came out.

  • Presentations — create, open a path or a stream, save to a path or a stream, save a subset of slides, IDisposable throughout.
  • Slides — add empty, insert, remove (the slide part is removed from the package, not just from the list), clone, hide (<p:sld show="0">), enumerate; masters and layouts are enumerable and a master can be cloned.
  • Sections — add, append, remove, remove with slides, reorder with slides.
  • Shapes — AutoShapes for 187 of the 189 ShapeType values: each of the 187 was written into its own file and each produced its own distinct <a:prstGeom prst="…">. The two exceptions are ShapeType.NotDefined and ShapeType.Custom, which have no preset to write; AddAutoShape accepts them without complaint and the shape comes out as prst="rect". Also picture frames, tables, connectors bound to shapes by connection site, Reorder for z-order, and adjust values on geometry shapes.
  • Text — text frames, paragraphs, portions; character formatting (bold, italic, underline, strikethrough, size, spacing, caps, latin/east-asian/complex-script/symbol fonts), paragraph formatting (alignment, indent, margins, spacing, symbol and numbered bullets), text-frame formatting (margins, wrap, anchor, autofit, columns, rotation, vertical text).
  • Fill — solid, gradient (stops, direction, shape, angle, tile flip), pattern, picture (with crop, stretch, tile and fill mode), no-fill; the same fill model applies to shapes, lines, text portions and table cells.
  • Lines — width, dash style and custom dash pattern, cap, join, miter limit, compound style, alignment, and arrowheads at both ends with style, width and length.
  • Effects — outer shadow, inner shadow, glow, soft edge, reflection, blur, preset shadow, fill overlay.
  • 3-D — bevel top and bottom, extrusion height and colour, contour width and colour, material preset, a camera with a preset, field of view, zoom and rotation, and a light rig with a preset, direction and rotation.
  • Tables — rows, columns, cells, cell merge (splitting optional), cell fill, the six cell borders, cell margins and anchoring, and a table style preset written as <a:tableStyleId>.
  • Pictures — embed from a byte array or a stream, deduplicated by content.
  • Notes — a notes slide per slide, written with the notes master it requires, plus footer text, footer visibility and slide-number visibility on the notes slide.
  • Comments — authors, comments with position and timestamp, on the classic comment list.
  • Document properties — core, extended and custom; docProps/core.xml, docProps/app.xml and docProps/custom.xml are all written.
  • Unknown parts — parts the library does not model are carried through a load and a save unchanged.

What it cannot do

This section is the point of this file. Nothing below is a "coming soon"; it is what the API does not contain today.

Not in the public API

Charts IShapeCollection.AddChart does not exist
SmartArt, OLE objects, video, audio no AddSmartArt / AddOleObjectFrame / AddVideoFrame / AddAudioFrame
Mathematical text not modelled — no a:m / oMath element is read or written
Group shapes no AddGroupShape. IGroupShape is declared but nothing implements it, and the public GroupShape class adds nothing to Shape — so no shape can hold child shapes
Animations and slide transitions no ISlide.Timeline, no ISlide.SlideShowTransition
Hyperlinks no HyperlinkClick on a shape or on a text portion. IHyperlinkContainer is declared and many shape types implement it, but it has no members at all — implementing it gives you nothing
Slide backgrounds no ISlide.Background
Themes no IPresentation.MasterTheme
Slide size no IPresentation.SlideSize — a new deck is 4:3 and cannot be changed
Adding or cloning a layout ILayoutSlideCollection declares an indexer, GetByType and two collection views — nothing that adds or clones. A new deck has exactly one layout and its LayoutType is Custom, so GetByType answers only for Custom and returns null for every other value. A Title or Title-and-Content layout can only come from a deck you opened
Threaded comments replies are held in memory; no ppt/threadedComments/ part is written
Encryption and protection no IPresentation.Protect
Rendering and conversion no PDF, HTML, SVG, image or text export of any kind
VBA macros, digital signatures not modelled
Reordering slides IShapeCollection.Reorder exists for shapes; ISlideCollection has no equivalent

Save formats

SaveFormat declares 21 values. Save writes three of them and raises NotSupportedException for the other eighteen — it never writes a package under a name that claims to be a format it did not produce.

Written Refused
Pptx, Ppsx, Potx Ppt, Pdf, Xps, Tiff, Odp, Pptm, Ppsm, Potm, Html, Swf, Otp, Pps, Pot, Fodp, Gif, Html5, Md, Xml

The three that are written are three genuinely different packages, each with its own main-part content type:

Pptx  -> application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml
Ppsx  -> application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml
Potx  -> application/vnd.openxmlformats-officedocument.presentationml.template.main+xml

The refusal says what to do instead:

Save format 'Pdf' is not supported: it is not an Office Open XML presentation package and this
library does not render or convert. Supported formats: Pptx, Ppsx, Potx.

Save format 'Pptm' is not supported: a macro-enabled package requires a VBA project part, which
this library does not write. Supported formats: Pptx, Ppsx, Potx.

Give the file the extension that matches the format you asked for — .pptx, .ppsx, .potx. Office keys off the name as well as the content type, and a file whose two disagree may be refused.

What "round-trip" does and does not mean

Opening a deck and saving it again preserves every part, and preserves the great majority of them byte for byte. It does not rewrite nothing at all. Measured on this repository's own 46-part PowerPoint-authored fixture (tests/test_data/PowerPointDeck.pptx, <Application>Microsoft Office PowerPoint</Application>):

Parts in / out 46 / 46
Parts dropped 0
Parts added 0
Parts byte-identical afterwards 42 of 46
Parts rewritten [Content_Types].xml, docProps/app.xml, docProps/core.xml, ppt/presentation.xml
Slide text runs identical, in order

docProps/core.xml is rewritten because saving stamps a modification time; docProps/app.xml is regenerated from the presentation; the other two are rebuilt from the package model. Parts this library has no model for — presProps, viewProps, tableStyles, thumbnails, extra themes, unused layouts — are among the 42 that come back unchanged. That is a specific, measured claim about one real deck, and it is deliberately narrower than "full fidelity".

Text language

A deck written by this library contains no lang= attribute anywhere and no <a:rPr> on a portion that was never formatted. PowerPoint will apply the authoring machine's default language rather than a language the file states.


Choosing an edition

There are four editions of this library and they are not interchangeable. Three of them — .NET, Java and C++ — are the same design in three languages; Python is a larger and different one. The table below was measured on 2026-08-16 by running each edition and reading the XML in the file it produced.

.NET Java C++ Python
Create, open, round-trip, save yes yes yes yes
Text, tables, connectors, fills, all 8 effects, 3-D yes yes yes yes
Notes and classic comments yes yes yes yes
Threaded comment part no yes no yes
Save to a stream yes yes no yes
Add a picture from a stream yes yes no yes
Sections yes no no no
Charts no no no yes
Animations no no no yes
Slide transitions no no no yes
Themes no no no yes
Slide backgrounds no no no yes
Group shapes no no no yes
Hyperlinks no no no yes
Markdown export no no no yes
Formats Save writes 3 3 6 7
Default slide size of a new deck 4:3 4:3 4:3 16:9
Layouts in a new deck 1 1 1 11

The short version: if you need charts, animations, transitions, themes, backgrounds, group shapes or hyperlinks, none of them exist in this edition — use the Python one. If you need sections, this is the only edition that has them. Code written against the Python examples does not port to the other three, and a new deck is not even the same shape.


Documentation and support

This library mirrors the naming of the commercial Aspose.Slides for .NET product, so that product's documentation is usually the fastest way to understand what a shared type name means. It describes a much larger API: check the tables above before relying on anything you read there.

When you want the commercial product instead of this one: if you need to render or convert — PDF, images, HTML, thumbnails — or need charts, SmartArt, animations, OLE objects or macro-enabled files, or need a supported product with a licence, none of that is here and none of it is planned in this repository. This library is the right choice when you are reading and writing .pptx and want an MIT-licensed dependency with no other dependencies at all.

Bugs and feature requests for this library belong in this repository's issue tracker, not in the commercial product's forum.


Contributing

Pull requests are welcome. Read CONTRIBUTING.md first — it explains the build, the three test suites, and the one rule that is specific to this project: a writer fix ships with a test that asserts on the produced .pptx package, not on what the library reads back.

By participating you agree to the Code of Conduct. Changes are recorded in CHANGELOG.md.

Security

Do not report a vulnerability in a public issue. See SECURITY.md for the reporting route.

License

MIT — see LICENSE. Copyright (c) 2026 Aspose Pty Ltd.

About

Open-source C#/.NET library for creating, reading and editing PowerPoint (.pptx) presentations — slides, shapes, text, tables, fills, effects, notes and comments. MIT licensed.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages