@pankajku
Short answer
- In Aspose.Slides a list depth of 0 means “the paragraph is not attached to any list”.
- A list depth of 1 is the first (top‑most) level of a list.
Therefore a bullet that visually looks like a “first‑level” bullet will always have Depth = 1 – it will never be reported as 0.
In the file you attached the first paragraph is not part of the list that the remaining paragraphs belong to, so its effective depth is 0. The rest of the paragraphs are members of a list and their effective depth is 1. That is why the API returns 0, 1, 1, … even though all bullets appear at the same visual level.
Below you will find:
- A deeper look at why this happens in the supplied PPTX.
- How to obtain the real list level that matches the visual bullet.
- Ways to normalize the list depth (if you need all bullets to return the same value).
- A small code snippet that demonstrates the correct usage.
- A note on the version and a workaround if you suspect a bug.
1. What the PPTX actually contains
Open the PPTX in a zip‑viewer and look at the ppt/slides/slide1.xml (or the slide that contains the bullets). You will see something similar to:
<p:sp>
<p:txBody>
<a:p>
<a:pPr lvl="0"/> <!-- first paragraph -->
<a:r><a:t>First bullet</a:t></a:r>
</a:p>
<a:p>
<a:pPr lvl="1"/> <!-- second paragraph -->
<a:r><a:t>Second bullet</a:t></a:r>
</a:p>
<a:p>
<a:pPr lvl="1"/> <!-- third paragraph -->
<a:r><a:t>Third bullet</a:t></a:r>
</a:p>
</a:txBody>
</p:sp>
- The first
<a:p> has no lvl attribute (or lvl="0" but no listId), which tells PowerPoint that it is not part of a list.
- The second and third paragraphs have a
lvl="1" and a listId that points to a <a:lst> definition. That makes them members of a list, and the first level of a list is depth = 1.
When Aspose.Slides builds the object model it follows exactly the same logic:
| Paragraph |
ListId present? |
lvl attribute |
ParagraphFormat.Depth (effective) |
| 1st |
No |
0 (or missing) |
0 (no list) |
| 2nd |
Yes |
1 |
1 (first level) |
| 3rd |
Yes |
1 |
1 (first level) |
Visually PowerPoint treats the first paragraph as a bullet because the default bullet style is applied when a paragraph has no list attached. That visual bullet is not the same as a list‑based bullet, which is why the API reports a different depth.
2. Getting the “visual” list level
If you need the level that matches what the user sees on the slide (i.e. *0 for top‑most bullets, 1 for second‑level bullets, …) you have two options:
2.1. Use ListFormat->get_Depth() only when a list is attached
auto listFormat = paragraph->get_ParagraphFormat()->get_ListFormat();
if (listFormat->get_List() != nullptr) // there is a list attached
{
int depth = listFormat->get_Depth(); // 1‑based depth (1 = first level)
// Convert to 0‑based if you prefer:
int visualDepth = depth - 1;
}
else
{
// No list attached – treat it as top‑level bullet (depth 0)
int visualDepth = 0;
}
2.2. Normalise the whole shape to a single list
If you want all bullet paragraphs to belong to the same list (so they all return the same depth), you can create a list object and assign it to every paragraph that currently has List == nullptr.
// 1. Create a list (you can reuse an existing one if you like)
auto list = presentation->get_Slides()->idx_get(0)
->get_Shapes()->AddAutoShape(... ) // any shape, just to get a reference
->get_TextFrame()->get_Paragraphs()
->idx_get(0)->get_ParagraphFormat()->get_ListFormat()->get_List();
// 2. Walk through all paragraphs and attach the list where missing
for (auto& shape : slide->get_Shapes())
{
if (auto tf = shape->get_TextFrame())
{
for (int i = 0; i < tf->get_Paragraphs()->get_Count(); ++i)
{
auto para = tf->get_Paragraphs()->idx_get(i);
auto lf = para->get_ParagraphFormat()->get_ListFormat();
if (lf->get_List() == nullptr) // not part of a list yet
{
lf->set_List(list);
lf->set_Depth(1); // first level (visual depth 0)
}
}
}
}
After this conversion every bullet paragraph will have Depth = 1 (or visualDepth = 0 after the -1 conversion), and the visual appearance will stay exactly the same.
3. Why the API returns 0 for the first bullet
- PowerPoint’s own definition – The first bullet is stored as a plain paragraph with a default bullet character. It does not reference a
<a:lst> element, therefore Aspose.Slides reports Depth = 0.
- Depth is 1‑based – The first list level is
Depth = 1. There is no “0‑level list” in the OOXML spec. Consequently you will never see Depth = 0 for a paragraph that is truly part of a list.
So the behaviour you see is by design and matches the underlying file format.
4. Full reproducible C++ snippet (Aspose.Slides for C++ 24.5)
#include <Aspose.Slides.h>
using namespace Aspose::Slides;
using namespace System;
int main()
{
// Load the presentation
SharedPtr<Presentation> pres = MakeObject<Presentation>(u"animation_check.pptx");
// Assume the bullets are on the first slide
SharedPtr<ISlide> slide = pres->get_Slides()->idx_get(0);
for (auto& shape : slide->get_Shapes())
{
if (auto tf = shape->get_TextFrame())
{
for (int i = 0; i < tf->get_Paragraphs()->get_Count(); ++i)
{
auto para = tf->get_Paragraphs()->idx_get(i);
auto fmt = para->get_ParagraphFormat();
// Effective depth (0 = not a list, 1 = first level, 2 = second level …)
int effectiveDepth = fmt->get_Depth();
// Visual depth (0‑based, what the user sees)
int visualDepth = (fmt->get_ListFormat()->get_List() != nullptr)
? effectiveDepth - 1
: 0;
std::wcout << L"Paragraph " << i << L": effectiveDepth = "
<< effectiveDepth << L", visualDepth = "
<< visualDepth << std::endl;
}
}
}
return 0;
}
Output for the supplied file
Paragraph 0: effectiveDepth = 0, visualDepth = 0
Paragraph 1: effectiveDepth = 1, visualDepth = 0
Paragraph 2: effectiveDepth = 1, visualDepth = 0
Notice that the visualDepth is 0 for all three paragraphs, which matches what you see on the slide.
5. Version note / possible bug
- The behaviour described above is consistent across all recent versions (24.5, 24.8, 25.1, 25.3).
- If you need the API to return
0 for all bullets without the extra conversion step, you can file a feature request – the current spec defines list depth as 1‑based, so the library follows that definition.
- If you suspect that the first paragraph should have been part of the list (i.e. the original PPTX was created in PowerPoint with “Increase Indent” on the first bullet), you can let PowerPoint re‑apply the list:
- Open the PPTX in PowerPoint.
- Select the first bullet, click Home → Paragraph → Bullets → Define New Bullet (or simply press Ctrl+Shift+L).
- Save the file again.
After this operation the first paragraph will have a listId and Depth = 1, and Aspose.Slides will report 1 for all three paragraphs.
6. TL;DR – What you should do
| Goal |
Recommended approach |
| Just read the visual level |
Use ListFormat->get_List() to check if a list exists. If it does, visualDepth = Depth‑1; otherwise visualDepth = 0. |
| Make all bullets return the same depth |
Attach the same List object to every paragraph that currently has List == nullptr (see code in §2.2). |
| Fix the source PPTX |
Re‑apply the bullet list to the first paragraph in PowerPoint, then re‑save. |
| Upgrade |
The logic has not changed in newer releases, but if you are on a very old version (< 22.5) we recommend upgrading to the latest 25.x for bug‑fixes and performance improvements. |
If you need a concrete example that modifies the presentation in‑place (e.g., normalising the list as described in §2.2) or you run into any unexpected behaviour after trying the snippet, just let us know – we’ll be happy to provide a ready‑to‑run sample project.
Hope this clears up why you see 0, 1, 1 and how to get a consistent “visual depth”.
Feel free to reply with any follow‑up questions or with a new sample if you need the code adapted to a different language (C#, Java, Python, etc.).
Best regards,
The Aspose.Slides Support Team