aspose-slides/SKILL.md
Comprehensive skill for manipulating Microsoft PowerPoint presentations using Aspose.Slides.NET library with modern C# patterns
npx skillsauth add alanben/claudeskills aspose-slidesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill enables Claude Code to effectively manipulate Microsoft PowerPoint presentations using the Aspose.Slides.NET library. It provides comprehensive guidance for working with presentations programmatically without requiring Microsoft PowerPoint installation.
Presentation (IPresentation)
├── Slides (ISlideCollection)
│ ├── Slide (ISlide)
│ │ ├── Shapes (IShapeCollection)
│ │ │ ├── AutoShape (IAutoShape)
│ │ │ ├── Table (ITable)
│ │ │ ├── Chart (IChart)
│ │ │ ├── PictureFrame (IPictureFrame)
│ │ │ └── GroupShape (IGroupShape)
│ │ ├── Background (IBackground)
│ │ └── SlideShowTransition
│ └── NotesSlide (INotesSlide)
├── Masters (IMasterSlideCollection)
│ └── MasterSlide (IMasterSlide)
├── Layouts (ILayoutSlideCollection)
│ └── LayoutSlide (ILayoutSlide)
└── DocumentProperties (IDocumentProperties)
TextFrame (ITextFrame)
├── Paragraphs (IParagraphCollection)
│ └── Paragraph (IParagraph)
│ ├── Portions (IPortionCollection)
│ │ └── Portion (IPortion)
│ │ └── PortionFormat (IPortionFormat)
│ └── ParagraphFormat (IParagraphFormat)
└── TextFrameFormat (ITextFrameFormat)
Always use using statements for proper disposal:
using Aspose.Slides;
// Single presentation
using var presentation = new Presentation("input.pptx");
// Work with presentation
presentation.Save("output.pptx", SaveFormat.Pptx);
// Multiple resources
using var sourcePresentation = new Presentation("source.pptx");
using var targetPresentation = new Presentation();
// Combine presentations
Leverage LINQ and functional patterns:
// Find shapes by type
var textShapes = slide.Shapes
.OfType<IAutoShape>()
.Where(s => s.TextFrame != null)
.ToList();
// Process all text portions
var allText = slide.Shapes
.OfType<IAutoShape>()
.Where(s => s.TextFrame != null)
.SelectMany(s => s.TextFrame.Paragraphs)
.SelectMany(p => p.Portions)
.Select(p => p.Text);
// Update text declaratively
slide.Shapes
.OfType<IAutoShape>()
.Where(s => s.Name == "Title")
.Select(s => s.TextFrame)
.Where(tf => tf != null)
.ToList()
.ForEach(tf => tf.Text = "New Title");
Use modern C# features for shape handling:
foreach (var shape in slide.Shapes)
{
var result = shape switch
{
IAutoShape autoShape when autoShape.TextFrame != null
=> ProcessTextShape(autoShape),
ITable table
=> ProcessTable(table),
IChart chart
=> ProcessChart(chart),
IPictureFrame picture
=> ProcessImage(picture),
_ => null
};
}
Create helper methods for declarative configuration:
IAutoShape AddConfiguredShape(
ISlide slide,
ShapeType shapeType,
float x, float y, float width, float height,
Action<IAutoShape> configure)
{
var shape = slide.Shapes.AddAutoShape(shapeType, x, y, width, height);
configure(shape);
return shape;
}
// Usage
var titleShape = AddConfiguredShape(
slide,
ShapeType.Rectangle,
50, 50, 600, 100,
shape =>
{
shape.TextFrame.Text = "Title";
shape.FillFormat.FillType = FillType.Solid;
shape.FillFormat.SolidFillColor.Color = Color.Blue;
});
using var presentation = new Presentation("template.pptx");
// Populate placeholder text
foreach (var slide in presentation.Slides)
{
foreach (var shape in slide.Shapes.OfType<IAutoShape>())
{
if (shape.Placeholder != null)
{
var placeholderType = shape.Placeholder.Type;
shape.TextFrame.Text = placeholderType switch
{
PlaceholderType.Title => "Dynamic Title",
PlaceholderType.Body => "Dynamic Content",
_ => shape.TextFrame.Text
};
}
}
}
presentation.Save("output.pptx", SaveFormat.Pptx);
// Define table dimensions
var columnWidths = new[] { 100.0, 150.0, 200.0 };
var rowHeights = new[] { 50.0, 40.0, 40.0, 40.0 };
var table = slide.Shapes.AddTable(
x: 50,
y: 50,
columnWidths,
rowHeights);
// Populate headers
var headers = new[] { "Name", "Value", "Description" };
for (int col = 0; col < headers.Length; col++)
{
table[col, 0].TextFrame.Text = headers[col];
table[col, 0].CellFormat.FillFormat.FillType = FillType.Solid;
table[col, 0].CellFormat.FillFormat.SolidFillColor.Color =
Color.FromArgb(68, 114, 196);
table[col, 0].TextFrame.Paragraphs[0].Portions[0].PortionFormat
.FillFormat.SolidFillColor.Color = Color.White;
}
// Populate data rows
var data = new[]
{
new[] { "Item 1", "100", "First item" },
new[] { "Item 2", "200", "Second item" },
new[] { "Item 3", "300", "Third item" }
};
for (int row = 0; row < data.Length; row++)
{
for (int col = 0; col < data[row].Length; col++)
{
table[col, row + 1].TextFrame.Text = data[row][col];
}
}
// Add chart to slide
var chart = slide.Shapes.AddChart(
ChartType.ClusteredColumn,
x: 50,
y: 50,
width: 500,
height: 400);
// Clear default data
chart.ChartData.Series.Clear();
chart.ChartData.Categories.Clear();
// Set categories
var categories = new[] { "Q1", "Q2", "Q3", "Q4" };
foreach (var category in categories)
{
chart.ChartData.Categories.Add(
chart.ChartData.ChartDataWorkbook.GetCell(0, 0, 0, category));
}
// Add data series
var series1 = chart.ChartData.Series.Add(
chart.ChartData.ChartDataWorkbook.GetCell(0, 0, 1, "Sales"),
chart.Type);
var salesData = new[] { 120, 150, 180, 160 };
for (int i = 0; i < salesData.Length; i++)
{
series1.DataPoints.AddDataPointForBarSeries(
chart.ChartData.ChartDataWorkbook.GetCell(0, i + 1, 1, salesData[i]));
}
// Style the chart
series1.Format.Fill.FillType = FillType.Solid;
series1.Format.Fill.SolidFillColor.Color = Color.FromArgb(68, 114, 196);
chart.HasTitle = true;
chart.ChartTitle.AddTextFrameForOverriding("Quarterly Sales");
void ReplaceTextPreservingFormat(
IPresentation presentation,
string searchText,
string replacementText)
{
foreach (var slide in presentation.Slides)
{
foreach (var shape in slide.Shapes.OfType<IAutoShape>())
{
if (shape.TextFrame == null) continue;
foreach (var paragraph in shape.TextFrame.Paragraphs)
{
foreach (var portion in paragraph.Portions)
{
if (portion.Text.Contains(searchText))
{
portion.Text = portion.Text.Replace(
searchText,
replacementText);
}
}
}
}
}
}
// Add image from file
using var image = Image.FromFile("logo.png");
var ppImage = presentation.Images.AddImage(image);
var pictureFrame = slide.Shapes.AddPictureFrame(
ShapeType.Rectangle,
x: 100,
y: 100,
width: 200,
height: 150,
ppImage);
// Extract all images from presentation
var imageIndex = 0;
foreach (var slide in presentation.Slides)
{
foreach (var shape in slide.Shapes.OfType<IPictureFrame>())
{
var image = shape.PictureFormat.Picture.Image.SystemImage;
image.Save($"extracted_image_{imageIndex++}.png");
}
}
For data-driven presentations, use a declarative approach:
public class SlideDataModel
{
public string Title { get; set; }
public List<BulletPoint> BulletPoints { get; set; }
public TableData TableData { get; set; }
public ChartData ChartData { get; set; }
}
void PopulateSlideFromJson(ISlide slide, SlideDataModel data)
{
// Update title
var titleShape = slide.Shapes
.OfType<IAutoShape>()
.FirstOrDefault(s => s.Placeholder?.Type == PlaceholderType.Title);
if (titleShape != null && data.Title != null)
{
titleShape.TextFrame.Text = data.Title;
}
// Update bullet points
var bodyShape = slide.Shapes
.OfType<IAutoShape>()
.FirstOrDefault(s => s.Placeholder?.Type == PlaceholderType.Body);
if (bodyShape != null && data.BulletPoints != null)
{
bodyShape.TextFrame.Paragraphs.Clear();
foreach (var bullet in data.BulletPoints)
{
var paragraph = new Paragraph();
paragraph.Text = bullet.Text;
paragraph.ParagraphFormat.Bullet.Type = BulletType.Symbol;
bodyShape.TextFrame.Paragraphs.Add(paragraph);
}
}
// Populate table if present
if (data.TableData != null)
{
PopulateTable(slide, data.TableData);
}
// Populate chart if present
if (data.ChartData != null)
{
PopulateChart(slide, data.ChartData);
}
}
// Use BlobManagementOptions for large presentations
var blobOptions = new BlobManagementOptions
{
PresentationLockingBehavior = PresentationLockingBehavior.KeepLocked,
IsTemporaryFilesAllowed = true,
TempFilesRootPath = Path.GetTempPath()
};
var loadOptions = new LoadOptions { BlobManagementOptions = blobOptions };
using var presentation = new Presentation("large.pptx", loadOptions);
async Task ProcessPresentationsAsync(IEnumerable<string> files)
{
var processingTasks = files.Select(async file =>
{
using var presentation = new Presentation(file);
// Process presentation
await Task.Run(() => ProcessSlides(presentation));
var outputPath = Path.ChangeExtension(file, ".processed.pptx");
presentation.Save(outputPath, SaveFormat.Pptx);
});
await Task.WhenAll(processingTasks);
}
Result<Presentation> LoadPresentationSafely(string path)
{
try
{
var presentation = new Presentation(path);
return Result<Presentation>.Success(presentation);
}
catch (Exception ex) when (ex is InvalidOperationException or IOException)
{
return Result<Presentation>.Failure($"Failed to load presentation: {ex.Message}");
}
}
// Usage with pattern matching
var result = LoadPresentationSafely("presentation.pptx");
result switch
{
{ IsSuccess: true } => ProcessPresentation(result.Value),
{ IsSuccess: false } => LogError(result.Error)
};
var pdfOptions = new PdfOptions
{
Compliance = PdfCompliance.Pdf15,
JpegQuality = 90,
TextCompression = PdfTextCompression.Flate,
EmbedFullFonts = true,
DrawSlidesFrame = false
};
// Include notes in PDF
pdfOptions.NotesCommentsLayouting.NotesPosition = NotesPositions.BottomFull;
presentation.Save("output.pdf", SaveFormat.Pdf, pdfOptions);
var htmlOptions = new HtmlOptions
{
EmbedImages = true,
HtmlFormatter = HtmlFormatter.CreateDocumentFormatter(string.Empty, false)
};
presentation.Save("output.html", SaveFormat.Html, htmlOptions);
foreach (var slide in presentation.Slides)
{
using var bitmap = slide.GetThumbnail(2.0f, 2.0f); // 2x scale
bitmap.Save(
$"slide_{slide.SlideNumber}.png",
System.Drawing.Imaging.ImageFormat.Png);
}
Solution: Use slide dimensions as reference
var slideWidth = presentation.SlideSize.Size.Width;
var slideHeight = presentation.SlideSize.Size.Height;
// Center shape
var shape = slide.Shapes.AddAutoShape(
ShapeType.Rectangle,
x: (slideWidth - shapeWidth) / 2,
y: (slideHeight - shapeHeight) / 2,
width: shapeWidth,
height: shapeHeight);
Solution: Enable auto-fit or adjust shape size
var textFrame = shape.TextFrame;
textFrame.TextFrameFormat.AutofitType = TextAutofitType.Shape;
// or
textFrame.TextFrameFormat.AutofitType = TextAutofitType.Normal;
Solution: Embed fonts explicitly
var fontData = File.ReadAllBytes("customfont.ttf");
presentation.FontsManager.AddEmbeddedFont(fontData, EmbedFontCharacters.All);
Solution: Refresh chart data workbook
chart.ChartData.ChartDataWorkbook.Clear(0);
// Re-populate data
When implementing Aspose.Slides functionality:
Start with the desired outcome and work backward:
// Goal: Create a data-driven presentation from JSON
// 1. Define the data structure
var slideData = JsonSerializer.Deserialize<PresentationData>(jsonContent);
// 2. Load or create presentation
using var presentation = LoadTemplate("template.pptx")
?? CreateNewPresentation();
// 3. Apply data to slides
foreach (var (slide, data) in presentation.Slides.Zip(slideData.Slides))
{
ApplyDataToSlide(slide, data);
}
// 4. Save with appropriate options
SavePresentation(presentation, "output.pptx", slideData.ExportOptions);
This skill enables Claude Code to manipulate PowerPoint presentations using modern C# patterns with Aspose.Slides. Focus on:
using statementsWhen tackling a new task, understand the object hierarchy, leverage LINQ for collection operations, and prefer composition over complex imperative code.
development
Update and maintain core repository documentation files (README.md, CHANGELOG.md, LICENSE, CONTRIBUTING.md) before commits or releases. Use when users need to update documentation to reflect code changes, prepare for releases, or ensure documentation consistency.
development
Re-index all PDF and HTML documents, update index.html, and commit/push changes to the repository
tools
Generate .NET Core data API code from model definitions using the Maker XML specification and CLI. Use when users need to: (1) Create Maker XML models from JSON objects, SQL scripts, or database schemas, (2) Generate .NET Core CRUD API endpoints from Maker XML, (3) Understand or validate Maker XML model definitions, or (4) Work with the Maker CLI tool for code generation.
development
Guide for building .NET APIs using CQRS pattern with MediatR, FluentValidation, and Carter modules