⚡ Extract PowerPoint Text in Java: PPTX Tables
Extract PowerPoint text in Java with Spire.Presentation: read PPTX tables, slides, and selected pages, handle edge cases, and save clean UTF-8. Try it!

Extract Text from PowerPoint in Java: Slides, Shapes, and Tables
PowerPoint content usually ends up somewhere else: a report, a searchable archive, a documentation system, or a data pipeline. Copying slides by hand is fine once. Doing it across dozens of decks gets messy fast - slow, error-prone, and hard to maintain.
Java can automate extraction, but a presentation isn't one big text document. Text boxes and titles are stored differently from tables, and text inside screenshots isn't "text data" at all. So a loop that reads ordinary shapes may look correct... until it quietly misses what you actually need.
This guide uses Spire.Presentation for Java to extract text from every slide, a selected slide, and tables. It also covers slide numbering, UTF-8 output, and the limits you'll hit when exporting to plain text. The main idea is simple: match your extraction method to how the content is stored, or you'll end up with a script that behaves like a pipeline - until it doesn't.
Set up PowerPoint text extraction in Java
The examples use Spire.Presentation, a Java library for working with PowerPoint files. Add its repository and dependency to your Maven pom.xml:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.presentation</artifactId>
<version>11.9.10</version>
</dependency>
</dependencies>
The version above matches the source example. If you're starting a new project, still check the vendor's current release and licensing terms. A version that works for a demo isn't automatically the right fit for a commercial app, a long-running service, or environments with specific support requirements.
The examples assume a file named report.pptx in the application's working directory. They write extracted content to UTF-8 text files using Java's Files.write and StandardCharsets.UTF_8. UTF-8 matters if slides contain names, punctuation, or non-Latin text. If you rely on the system default encoding, you can end up with different output between a developer laptop and a production server. See the Java Files API for the methods used here.
Each program disposes of the Presentation object in a finally block. That's worth doing even for small utilities. File-processing code often gets reused later inside a service, and cleanup tends to matter more than it does in a quick local run.
Extract text from all slides or selected slides
For ordinary slide text, the flow stays pretty consistent: load the presentation, iterate through slides, inspect shapes, and read paragraphs from shapes that implement IAutoShape. Add slide labels to the output so the extracted text is still useful after it's separated from the original deck.
Extract text from every slide
This example collects text from IAutoShape objects and writes it to ppt-all-text.txt:
import com.spire.presentation.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExtractAllPPTText {
public static void main(String[] args) throws Exception {
Presentation presentation = new Presentation();
try {
presentation.loadFromFile("report.pptx");
StringBuilder result = new StringBuilder();
for (int i = 0; i < presentation.getSlides().getCount(); i++) {
ISlide slide = presentation.getSlides().get(i);
result.append("Slide ").append(i + 1)
.append(System.lineSeparator());
for (Object shape : slide.getShapes()) {
if (shape instanceof IAutoShape) {
IAutoShape autoShape = (IAutoShape) shape;
for (Object item : autoShape.getTextFrame().getParagraphs()) {
ParagraphEx paragraph = (ParagraphEx) item;
String text = paragraph.getText();
if (text != null && !text.trim().isEmpty()) {
result.append(text)
.append(System.lineSeparator());
}
}
}
}
result.append(System.lineSeparator());
}
Files.write(Paths.get("ppt-all-text.txt"),
result.toString().getBytes(StandardCharsets.UTF_8));
System.out.println("Text extraction completed.");
} finally {
presentation.dispose();
}
}
}
The loop uses getSlides() to access the slides and getShapes() to walk through the shapes on each slide. For a text-bearing auto shape, getTextFrame().getParagraphs() returns its paragraphs, and ParagraphEx.getText() gives you the paragraph text. Empty paragraphs are skipped, so you don't end up with a file full of blank lines.
The slide number written to the output is i + 1 because readers expect slide numbers to start at 1. The collection index is zero-based. Keeping those two numbering schemes separate helps you avoid the classic off-by-one mistake later when you target a specific slide.
Extract text from one slide
If you only need a particular slide, validate the human-readable slide number, then subtract one when accessing the slides collection. This example extracts slide 3 into slide-3-text.txt:
int slideNumber = 3;
int slideCount = presentation.getSlides().getCount();
if (slideNumber < 1 || slideNumber > slideCount) {
throw new IllegalArgumentException("The specified slide does not exist.");
}
ISlide slide = presentation.getSlides().get(slideNumber - 1);
StringBuilder result = new StringBuilder();
for (Object shape : slide.getShapes()) {
if (shape instanceof IAutoShape) {
IAutoShape autoShape = (IAutoShape) shape;
for (Object item : autoShape.getTextFrame().getParagraphs()) {
ParagraphEx paragraph = (ParagraphEx) item;
String text = paragraph.getText();
if (text != null && !text.trim().isEmpty()) {
result.append(text).append(System.lineSeparator());
}
}
}
}
Files.write(Paths.get("slide-3-text.txt"),
result.toString().getBytes(StandardCharsets.UTF_8));
Use this inside the same Presentation loading and cleanup pattern shown above, with the required imports. The range check gives you a clear error before an invalid collection access. Without it, a user-provided slide number like 0 (or anything above the slide count) fails later with a less helpful exception.
If you're extracting several selected slides, store the requested slide numbers in a list and run the same validated extraction logic for each one. That's often easier than extracting the whole deck and filtering afterward, especially when the presentation archive is large and your selection is small. If you're processing lots of files, move the repeated shape-reading logic into a method so you can test it independently.
Extract text from PowerPoint tables
Tables aren't the same as normal text boxes. Their contents live in cells, so checking only IAutoShape isn't going to get table text. Look for objects implementing ITable, then walk through rows and columns.
The following program searches each slide for tables and writes tab-separated rows to ppt-table-text.txt:
import com.spire.presentation.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ExtractPPTTableText {
public static void main(String[] args) throws Exception {
Presentation presentation = new Presentation();
try {
presentation.loadFromFile("report.pptx");
StringBuilder result = new StringBuilder();
for (int i = 0; i < presentation.getSlides().getCount(); i++) {
ISlide slide = presentation.getSlides().get(i);
for (Object shape : slide.getShapes()) {
if (shape instanceof ITable) {
ITable table = (ITable) shape;
result.append("Table on Slide ").append(i + 1)
.append(System.lineSeparator());
int rowCount = table.getTableRows().getCount();
int columnCount = table.getColumnsList().getCount();
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
String text = table.get(col, row)
.getTextFrame().getText();
if (text != null) {
text = text.replace("\r", " ")
.replace("\n", " ")
.replace("\t", " ");
result.append(text);
}
if (col < columnCount - 1) {
result.append("\t");
}
}
result.append(System.lineSeparator());
}
result.append(System.lineSeparator());
}
}
}
Files.write(Paths.get("ppt-table-text.txt"),
result.toString().getBytes(StandardCharsets.UTF_8));
System.out.println("Table text extraction completed.");
} finally {
presentation.dispose();
}
}
}
One easy-to-miss detail: in table.get(col, row), the column index comes first, then the row index. Both start at zero. The row and column counts come from getTableRows().getCount() and getColumnsList().getCount().
Tabs separate columns and line breaks separate rows. That usually gives you a readable text file, and it can often be imported into spreadsheet tools. For example, a table with task, owner, and status columns turns into tab-separated records. The code replaces tabs and line breaks inside a cell so each source row becomes one output line. It's a practical formatting choice, not a perfect copy of the original cell content. If those characters are meaningful, use escaping or output a structured format instead.
Merged cells can also trip you up. A simple row-and-column iteration can produce empty or repeated-looking positions depending on how the table is laid out. Test against a few real decks before treating the output as definitive data. If you need the exact table structure later, plain text may be the wrong export format - consider preserving cell coordinates and merge info in a structured representation.
Handle extraction limits and production concerns
A successful extraction run doesn't mean you got every visible word. It only means the objects your code covers were read successfully. In production, the real questions are different: Which kinds of content did it actually extract, and what did it skip?
Visible text is not always extractable text
The examples handle ordinary text in IAutoShape objects and table content in ITable objects. PowerPoint can also store text in speaker notes, chart labels, grouped objects, and other content types. Those may need additional handling depending on what the library exposes and how the deck is built.
Text embedded in an image is another case entirely. A screenshot, scanned page, or chart image contains pixels, not PowerPoint text frames. Shape-based extraction can't read it. If that matters, add an OCR step and treat OCR output as its own data source with review and confidence considerations.
If you want something dependable, inspect the object types in your actual presentations. A deck created from a standard template may behave consistently; decks assembled from different tools (or by different teams) often won't. Your test set should include the content types you expect: text boxes, tables, charts, grouped objects, notes, and images when relevant.
Text order and formatting can change
The shape collection order isn't guaranteed to match what a person sees as "reading order." For example, a title might appear after a side label in the collection. If reading order matters, you may need to use shape positions and apply your own ordering rules. There's no universal visual-order algorithm that works across every layout, so test this against real slides.
A .txt file also drops presentation formatting - font size, color, emphasis, and even the slide layout. If your next step depends on heading hierarchy or table structure, you'll need to capture that explicitly rather than assuming plain text will preserve it. For search, quick review, or basic reporting, text output is often enough. For reliable interchange between systems, define a structured schema before scaling up.
Make the job predictable
A one-off script can dump output to a hard-coded path and stop on the first error. A repeatable process needs a bit more discipline:
- Validate the input file exists and the requested slide number is in range.
- Keep slide numbers in the output so extracted paragraphs retain context.
- Use UTF-8 explicitly instead of relying on the host machine's default encoding.
- Dispose of the
presentationobject even when load or extraction fails. - Test with presentations that reflect your real mix of templates and object types.
- Log which slides and content types were processed, especially if missing text has business impact.
- Choose TXT only when losing layout and formatting is acceptable.
These checks aren't "extra"; they're what make failures diagnosable. If a report is missing a table, you want to know whether the deck didn't have one, the object type wasn't covered, or the file couldn't be read - rather than only noticing after delivery when the output "looks incomplete."