ablechart 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ablechart-0.1.0/CHANGELOG.md +23 -0
- ablechart-0.1.0/LICENSE +21 -0
- ablechart-0.1.0/MANIFEST.in +5 -0
- ablechart-0.1.0/PKG-INFO +279 -0
- ablechart-0.1.0/README.md +245 -0
- ablechart-0.1.0/pyproject.toml +54 -0
- ablechart-0.1.0/setup.cfg +4 -0
- ablechart-0.1.0/src/ablechart/__init__.py +351 -0
- ablechart-0.1.0/src/ablechart/_log.py +34 -0
- ablechart-0.1.0/src/ablechart/annotations.py +614 -0
- ablechart-0.1.0/src/ablechart/api.py +518 -0
- ablechart-0.1.0/src/ablechart/builder.py +370 -0
- ablechart-0.1.0/src/ablechart/cleaner.py +144 -0
- ablechart-0.1.0/src/ablechart/date_axis.py +673 -0
- ablechart-0.1.0/src/ablechart/examples.py +113 -0
- ablechart-0.1.0/src/ablechart/inspect.py +230 -0
- ablechart-0.1.0/src/ablechart/layout.py +535 -0
- ablechart-0.1.0/src/ablechart/metadata.py +198 -0
- ablechart-0.1.0/src/ablechart/oxml/__init__.py +22 -0
- ablechart-0.1.0/src/ablechart/oxml/axes.py +219 -0
- ablechart-0.1.0/src/ablechart/oxml/plots.py +267 -0
- ablechart-0.1.0/src/ablechart/oxml/series.py +509 -0
- ablechart-0.1.0/src/ablechart/oxml_ns.py +8 -0
- ablechart-0.1.0/src/ablechart/parser.py +1007 -0
- ablechart-0.1.0/src/ablechart/plot_area.py +119 -0
- ablechart-0.1.0/src/ablechart/polish.py +560 -0
- ablechart-0.1.0/src/ablechart/presets.py +519 -0
- ablechart-0.1.0/src/ablechart/range_chart.py +180 -0
- ablechart-0.1.0/src/ablechart/range_snapshot.py +1174 -0
- ablechart-0.1.0/src/ablechart/replace.py +321 -0
- ablechart-0.1.0/src/ablechart/scatter.py +301 -0
- ablechart-0.1.0/src/ablechart/schema.py +205 -0
- ablechart-0.1.0/src/ablechart/semantic_anchor.py +125 -0
- ablechart-0.1.0/src/ablechart/semantic_family.py +2239 -0
- ablechart-0.1.0/src/ablechart/spec.py +1375 -0
- ablechart-0.1.0/src/ablechart/styles.py +298 -0
- ablechart-0.1.0/src/ablechart/tokens.py +163 -0
- ablechart-0.1.0/src/ablechart/waterfall.py +750 -0
- ablechart-0.1.0/src/ablechart.egg-info/PKG-INFO +279 -0
- ablechart-0.1.0/src/ablechart.egg-info/SOURCES.txt +55 -0
- ablechart-0.1.0/src/ablechart.egg-info/dependency_links.txt +1 -0
- ablechart-0.1.0/src/ablechart.egg-info/requires.txt +11 -0
- ablechart-0.1.0/src/ablechart.egg-info/top_level.txt +1 -0
- ablechart-0.1.0/tests/fixtures/_generate_external_sample.py +98 -0
- ablechart-0.1.0/tests/fixtures/external_sample.pptx +0 -0
- ablechart-0.1.0/tests/test_external_chart.py +166 -0
- ablechart-0.1.0/tests/test_external_fixture_file.py +189 -0
- ablechart-0.1.0/tests/test_gtm_patterns.py +278 -0
- ablechart-0.1.0/tests/test_inspect.py +172 -0
- ablechart-0.1.0/tests/test_package_contract.py +933 -0
- ablechart-0.1.0/tests/test_parser_internals.py +54 -0
- ablechart-0.1.0/tests/test_polish.py +60 -0
- ablechart-0.1.0/tests/test_release_readiness.py +113 -0
- ablechart-0.1.0/tests/test_replace.py +473 -0
- ablechart-0.1.0/tests/test_round_trip_matrix.py +362 -0
- ablechart-0.1.0/tests/test_semantic_dispatcher_contract.py +95 -0
- ablechart-0.1.0/tests/test_spec_layer.py +291 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `ablechart` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 - 2026-06-21
|
|
6
|
+
|
|
7
|
+
Initial public package candidate.
|
|
8
|
+
|
|
9
|
+
Supported scope:
|
|
10
|
+
|
|
11
|
+
- editable native PowerPoint combo charts
|
|
12
|
+
- waterfall, scatter, bubble, and range snapshot chart families
|
|
13
|
+
- semantic metadata round-trip for generated charts
|
|
14
|
+
- chart inventory and template-safe data replacement for the first-batch native chart types
|
|
15
|
+
- experimental semantic component families for single-slide financial report panels
|
|
16
|
+
|
|
17
|
+
Packaging:
|
|
18
|
+
|
|
19
|
+
- MIT license
|
|
20
|
+
- Python `>=3.10`
|
|
21
|
+
- PyPI metadata and source distribution manifest prepared
|
|
22
|
+
- Release-readiness tests for license, package metadata, README positioning, and sdist manifest
|
|
23
|
+
- GitHub Actions CI plus TestPyPI / PyPI Trusted Publishing workflow prepared
|
ablechart-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ablechart contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ablechart-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ablechart
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Editable PowerPoint chart engine for dual-axis financial charts
|
|
5
|
+
Author: ablechart contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hanlinlibham/ablechart
|
|
8
|
+
Project-URL: Repository, https://github.com/hanlinlibham/ablechart
|
|
9
|
+
Project-URL: Issues, https://github.com/hanlinlibham/ablechart/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/hanlinlibham/ablechart/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: powerpoint,pptx,charts,finance,openxml
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Office/Business :: Office Suites
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: python-pptx<1.1,>=1.0.2
|
|
26
|
+
Requires-Dist: pandas<3,>=2.2
|
|
27
|
+
Requires-Dist: numpy<2,>=1.26
|
|
28
|
+
Requires-Dist: lxml<6,>=5
|
|
29
|
+
Requires-Dist: openpyxl<4,>=3.1
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: pytest; extra == "test"
|
|
32
|
+
Requires-Dist: tomli; python_version < "3.11" and extra == "test"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# ablechart
|
|
36
|
+
|
|
37
|
+
`ablechart` is a focused Python SDK for creating, inspecting, parsing,
|
|
38
|
+
and updating editable PowerPoint chart assets.
|
|
39
|
+
|
|
40
|
+
It is built for workflows where a chart must stay a real PowerPoint chart,
|
|
41
|
+
not a screenshot:
|
|
42
|
+
|
|
43
|
+
- editable in Microsoft PowerPoint after generation
|
|
44
|
+
- backed by an embedded workbook
|
|
45
|
+
- able to carry semantic metadata for round-trip parsing
|
|
46
|
+
- replaceable in an existing `.pptx` without rebuilding the whole slide
|
|
47
|
+
- shaped around financial reporting chart families rather than a generic chart zoo
|
|
48
|
+
|
|
49
|
+
The project is intentionally narrow. It is a chart asset kernel, not a full
|
|
50
|
+
presentation generation framework, report builder, template library, or AI
|
|
51
|
+
slide generator.
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
*A real, editable PowerPoint chart rendered from a `.pptx` produced by `ablechart` — stacked columns and two lines on a second value axis, with per-axis number formats. Data: CATL (300750.SZ) FY2019–2024 annual filings (source: Tushare).*
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install ablechart
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Python `>=3.10` is required.
|
|
64
|
+
|
|
65
|
+
Core dependencies:
|
|
66
|
+
|
|
67
|
+
- `python-pptx>=1.0.2,<1.1`
|
|
68
|
+
- `pandas>=2.2,<3`
|
|
69
|
+
- `numpy>=1.26,<2`
|
|
70
|
+
- `lxml>=5,<6`
|
|
71
|
+
- `openpyxl>=3.1,<4`
|
|
72
|
+
|
|
73
|
+
For local development:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git clone https://github.com/hanlinlibham/ablechart.git
|
|
77
|
+
cd ablechart
|
|
78
|
+
pip install -e .
|
|
79
|
+
python -m pytest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Quickstart
|
|
83
|
+
|
|
84
|
+
### Create an editable combo chart
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
import pandas as pd
|
|
88
|
+
from pptx import Presentation
|
|
89
|
+
from ablechart import create_combo_chart
|
|
90
|
+
|
|
91
|
+
df = pd.DataFrame(
|
|
92
|
+
{
|
|
93
|
+
"Year": [2021, 2022, 2023, 2024],
|
|
94
|
+
"Revenue": [100, 110, 120, 140],
|
|
95
|
+
"Profit": [10, 12, 15, 18],
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
prs = Presentation()
|
|
100
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
101
|
+
|
|
102
|
+
create_combo_chart(
|
|
103
|
+
slide=slide,
|
|
104
|
+
df=df,
|
|
105
|
+
categories_col="Year",
|
|
106
|
+
series_config=[
|
|
107
|
+
{"key": "Revenue", "name": "Revenue", "type": "bar", "axis": "primary"},
|
|
108
|
+
{"key": "Profit", "name": "Profit", "type": "line", "axis": "secondary"},
|
|
109
|
+
],
|
|
110
|
+
title="Revenue and profit",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
prs.save("combo-demo.pptx")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Parse a chart back into data and metadata
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from ablechart import parse_chart_from_pptx
|
|
120
|
+
|
|
121
|
+
df, series_config, chart_type, layout_info = parse_chart_from_pptx("combo-demo.pptx")
|
|
122
|
+
|
|
123
|
+
print(chart_type)
|
|
124
|
+
print(df.head())
|
|
125
|
+
print(series_config)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Inspect and update charts in an existing deck
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from ablechart import SeriesData, inspect_pptx_charts, replace_pptx_chart_data
|
|
132
|
+
|
|
133
|
+
inventory = inspect_pptx_charts("template.pptx")
|
|
134
|
+
target = next(item for item in inventory if item.replaceable)
|
|
135
|
+
|
|
136
|
+
result = replace_pptx_chart_data(
|
|
137
|
+
input_pptx="template.pptx",
|
|
138
|
+
output_pptx="updated.pptx",
|
|
139
|
+
selector=target.selector,
|
|
140
|
+
categories=["2026Q1", "2026Q2", "2026Q3"],
|
|
141
|
+
series=[
|
|
142
|
+
SeriesData(name="Revenue", values=[120.0, 132.0, 141.0]),
|
|
143
|
+
SeriesData(name="Cost", values=[82.0, 88.0, 91.0]),
|
|
144
|
+
],
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
assert result.status == "ok", result.error_detail
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## What It Supports
|
|
151
|
+
|
|
152
|
+
### Chart families
|
|
153
|
+
|
|
154
|
+
| Family | Entry point | Notes |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| Combo | `create_combo_chart()` | Bar, line, area, stacked, percent-stacked, dual-axis, date-axis presets |
|
|
157
|
+
| Waterfall | `create_waterfall_chart()` | Editable bridge chart with total and relative measures |
|
|
158
|
+
| Scatter | `create_scatter_chart()` | Native scatter chart with parse helpers |
|
|
159
|
+
| Bubble | `create_bubble_chart()` | Native bubble chart with parse helpers |
|
|
160
|
+
| Range snapshot | `create_range_snapshot_chart()` | Valuation range snapshot with min/max/average/current markers |
|
|
161
|
+
|
|
162
|
+

|
|
163
|
+
|
|
164
|
+
*Each panel is a real, editable PowerPoint chart produced by `ablechart`, then rendered to an image. Every one can be parsed back into a DataFrame and updated in place. All four use the same real dataset (CATL 300750.SZ, source: Tushare); regenerate with `python scripts/make_gallery.py`.*
|
|
165
|
+
|
|
166
|
+
### Semantic financial families
|
|
167
|
+
|
|
168
|
+
`create_semantic_chart()` and the family-specific helpers provide a higher
|
|
169
|
+
level mapping from financial-report concepts to native chart or shape
|
|
170
|
+
composition primitives.
|
|
171
|
+
|
|
172
|
+
Currently exposed families include:
|
|
173
|
+
|
|
174
|
+
- `performance_compare`
|
|
175
|
+
- `distribution_plus_history`
|
|
176
|
+
- `style_box`
|
|
177
|
+
- `style_allocation`
|
|
178
|
+
- `factor_exposure`
|
|
179
|
+
- `score_overlay`
|
|
180
|
+
- `concentration`
|
|
181
|
+
- `event_timeline`
|
|
182
|
+
- `attribution_decomposition`
|
|
183
|
+
- `ranked_tile_matrix`
|
|
184
|
+
- `heatmap_matrix`
|
|
185
|
+
- `table_plus_chart_composite`
|
|
186
|
+
- `factor_attribution_panel`
|
|
187
|
+
- `regime_table_panel`
|
|
188
|
+
- `manager_timeline_profile`
|
|
189
|
+
- `award_timeline_panel`
|
|
190
|
+
- `selection_timing_grid`
|
|
191
|
+
- `dual_chart_panel`
|
|
192
|
+
- `holding_detail`
|
|
193
|
+
|
|
194
|
+
This layer is useful for single-slide financial report components. It is not
|
|
195
|
+
a report orchestration engine.
|
|
196
|
+
|
|
197
|
+
## Public API Shape
|
|
198
|
+
|
|
199
|
+
The public API is organized around the chart asset lifecycle:
|
|
200
|
+
|
|
201
|
+
| Lifecycle | Representative APIs |
|
|
202
|
+
| --- | --- |
|
|
203
|
+
| Create | `create_combo_chart()`, `create_waterfall_chart()`, `create_semantic_chart()` |
|
|
204
|
+
| Parse | `parse_chart_from_pptx()`, `parse_all_charts_from_pptx()`, `get_semantic_chart_spec()` |
|
|
205
|
+
| Metadata | `ChartMetadataV1`, `write_chart_metadata`, `METADATA_SCHEMA_VERSION` |
|
|
206
|
+
| Inspect | `inspect_pptx_charts()`, `ChartInventoryItem`, `ChartSelector` |
|
|
207
|
+
| Replace | `replace_pptx_chart_data()`, `SeriesData`, `ReplaceResult` |
|
|
208
|
+
|
|
209
|
+
The design goal is that a generated chart can become a durable asset:
|
|
210
|
+
created once, opened and edited in PowerPoint, parsed again later, and updated
|
|
211
|
+
without losing its position, size, identity, or basic editability.
|
|
212
|
+
|
|
213
|
+
## How This Differs From Similar Packages
|
|
214
|
+
|
|
215
|
+
`ablechart` is not trying to replace broad PowerPoint SDKs. It is a
|
|
216
|
+
small layer for high-quality chart assets and template-safe chart updates.
|
|
217
|
+
|
|
218
|
+
| Project | Main strength | How `ablechart` differs |
|
|
219
|
+
| --- | --- | --- |
|
|
220
|
+
| [`python-pptx`](https://python-pptx.readthedocs.io/en/latest/user/charts.html) | General Python library for creating and updating `.pptx` files, including adding charts and replacing chart data. | `ablechart` builds on the PowerPoint-native path but adds financial chart families, semantic metadata, chart round-trip parsing, inventory, and template-safe replacement contracts. |
|
|
221
|
+
| [`PptxGenJS`](https://gitbrent.github.io/PptxGenJS/) | Broad JavaScript presentation generation for Node.js, browser, React, Electron, charts, tables, images, and HTML-to-PPTX workflows. | `ablechart` is Python-only and intentionally narrower: it does not generate full decks from layouts, but focuses on editable chart assets and parse/update lifecycles. |
|
|
222
|
+
| [`mschart`](https://ardata-fr.github.io/mschart/) | R package for native editable Microsoft Office charts, commonly used with `officer`. | `ablechart` targets Python financial-report workflows and adds inspect/replace and metadata round-trip APIs for existing `.pptx` chart assets. |
|
|
223
|
+
| [`Aspose.Slides for Python via .NET`](https://docs.aspose.com/slides/python-net/) | Commercial, full-featured presentation processing SDK with broad PowerPoint manipulation, chart modules, export, animation, SmartArt, VBA, and conversion features. | `ablechart` is MIT-licensed and much smaller. It does not aim to cover the whole PowerPoint object model or rendering/export conversion. |
|
|
224
|
+
| [`Spire.Presentation for Python`](https://www.e-iceblue.com/Introduce/presentation-for-python.html) | Commercial presentation API covering creation, editing, conversion, and chart operations. | `ablechart` avoids broad document processing scope and concentrates on deterministic chart creation, chart metadata, and safe data replacement. |
|
|
225
|
+
|
|
226
|
+
In short:
|
|
227
|
+
|
|
228
|
+
- Use `python-pptx` when you need a general Python PowerPoint building block.
|
|
229
|
+
- Use `PptxGenJS` when your stack is JavaScript or browser-side PPTX generation.
|
|
230
|
+
- Use Aspose or Spire when you need broad commercial document processing,
|
|
231
|
+
conversion, or complete PowerPoint object-model coverage.
|
|
232
|
+
- Use `ablechart` when your hard problem is editable, updateable,
|
|
233
|
+
inspectable PowerPoint charts for data-heavy reports.
|
|
234
|
+
|
|
235
|
+
## Current Limits
|
|
236
|
+
|
|
237
|
+
`ablechart` does not currently provide:
|
|
238
|
+
|
|
239
|
+
- full report assembly
|
|
240
|
+
- slide template management
|
|
241
|
+
- data connectors
|
|
242
|
+
- CLI job orchestration
|
|
243
|
+
- PDF or image export
|
|
244
|
+
- AI prompt-to-deck generation
|
|
245
|
+
- complete coverage of every PowerPoint chart type
|
|
246
|
+
- HTML or interactive web output
|
|
247
|
+
|
|
248
|
+
Unsupported chart replacement cases fail explicitly rather than silently
|
|
249
|
+
rebuilding the chart. The first-batch replacement path is focused on common
|
|
250
|
+
embedded-workbook chart types such as bar, line, combo, area, pie, scatter,
|
|
251
|
+
and bubble charts.
|
|
252
|
+
|
|
253
|
+
## Development
|
|
254
|
+
|
|
255
|
+
Run the test suite:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
python -m pytest
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Build the distribution artifacts:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m build --sdist --wheel
|
|
265
|
+
python -m twine check dist/*
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
The repository keeps contract tests for:
|
|
269
|
+
|
|
270
|
+
- public exports
|
|
271
|
+
- generated chart round-trips
|
|
272
|
+
- semantic metadata recovery
|
|
273
|
+
- existing-deck chart inspection
|
|
274
|
+
- in-place chart data replacement
|
|
275
|
+
- checked-in `.pptx` fixture behavior
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
MIT License. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# ablechart
|
|
2
|
+
|
|
3
|
+
`ablechart` is a focused Python SDK for creating, inspecting, parsing,
|
|
4
|
+
and updating editable PowerPoint chart assets.
|
|
5
|
+
|
|
6
|
+
It is built for workflows where a chart must stay a real PowerPoint chart,
|
|
7
|
+
not a screenshot:
|
|
8
|
+
|
|
9
|
+
- editable in Microsoft PowerPoint after generation
|
|
10
|
+
- backed by an embedded workbook
|
|
11
|
+
- able to carry semantic metadata for round-trip parsing
|
|
12
|
+
- replaceable in an existing `.pptx` without rebuilding the whole slide
|
|
13
|
+
- shaped around financial reporting chart families rather than a generic chart zoo
|
|
14
|
+
|
|
15
|
+
The project is intentionally narrow. It is a chart asset kernel, not a full
|
|
16
|
+
presentation generation framework, report builder, template library, or AI
|
|
17
|
+
slide generator.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
*A real, editable PowerPoint chart rendered from a `.pptx` produced by `ablechart` — stacked columns and two lines on a second value axis, with per-axis number formats. Data: CATL (300750.SZ) FY2019–2024 annual filings (source: Tushare).*
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install ablechart
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Python `>=3.10` is required.
|
|
30
|
+
|
|
31
|
+
Core dependencies:
|
|
32
|
+
|
|
33
|
+
- `python-pptx>=1.0.2,<1.1`
|
|
34
|
+
- `pandas>=2.2,<3`
|
|
35
|
+
- `numpy>=1.26,<2`
|
|
36
|
+
- `lxml>=5,<6`
|
|
37
|
+
- `openpyxl>=3.1,<4`
|
|
38
|
+
|
|
39
|
+
For local development:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/hanlinlibham/ablechart.git
|
|
43
|
+
cd ablechart
|
|
44
|
+
pip install -e .
|
|
45
|
+
python -m pytest
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quickstart
|
|
49
|
+
|
|
50
|
+
### Create an editable combo chart
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import pandas as pd
|
|
54
|
+
from pptx import Presentation
|
|
55
|
+
from ablechart import create_combo_chart
|
|
56
|
+
|
|
57
|
+
df = pd.DataFrame(
|
|
58
|
+
{
|
|
59
|
+
"Year": [2021, 2022, 2023, 2024],
|
|
60
|
+
"Revenue": [100, 110, 120, 140],
|
|
61
|
+
"Profit": [10, 12, 15, 18],
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
prs = Presentation()
|
|
66
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
67
|
+
|
|
68
|
+
create_combo_chart(
|
|
69
|
+
slide=slide,
|
|
70
|
+
df=df,
|
|
71
|
+
categories_col="Year",
|
|
72
|
+
series_config=[
|
|
73
|
+
{"key": "Revenue", "name": "Revenue", "type": "bar", "axis": "primary"},
|
|
74
|
+
{"key": "Profit", "name": "Profit", "type": "line", "axis": "secondary"},
|
|
75
|
+
],
|
|
76
|
+
title="Revenue and profit",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
prs.save("combo-demo.pptx")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Parse a chart back into data and metadata
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from ablechart import parse_chart_from_pptx
|
|
86
|
+
|
|
87
|
+
df, series_config, chart_type, layout_info = parse_chart_from_pptx("combo-demo.pptx")
|
|
88
|
+
|
|
89
|
+
print(chart_type)
|
|
90
|
+
print(df.head())
|
|
91
|
+
print(series_config)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Inspect and update charts in an existing deck
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from ablechart import SeriesData, inspect_pptx_charts, replace_pptx_chart_data
|
|
98
|
+
|
|
99
|
+
inventory = inspect_pptx_charts("template.pptx")
|
|
100
|
+
target = next(item for item in inventory if item.replaceable)
|
|
101
|
+
|
|
102
|
+
result = replace_pptx_chart_data(
|
|
103
|
+
input_pptx="template.pptx",
|
|
104
|
+
output_pptx="updated.pptx",
|
|
105
|
+
selector=target.selector,
|
|
106
|
+
categories=["2026Q1", "2026Q2", "2026Q3"],
|
|
107
|
+
series=[
|
|
108
|
+
SeriesData(name="Revenue", values=[120.0, 132.0, 141.0]),
|
|
109
|
+
SeriesData(name="Cost", values=[82.0, 88.0, 91.0]),
|
|
110
|
+
],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
assert result.status == "ok", result.error_detail
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## What It Supports
|
|
117
|
+
|
|
118
|
+
### Chart families
|
|
119
|
+
|
|
120
|
+
| Family | Entry point | Notes |
|
|
121
|
+
| --- | --- | --- |
|
|
122
|
+
| Combo | `create_combo_chart()` | Bar, line, area, stacked, percent-stacked, dual-axis, date-axis presets |
|
|
123
|
+
| Waterfall | `create_waterfall_chart()` | Editable bridge chart with total and relative measures |
|
|
124
|
+
| Scatter | `create_scatter_chart()` | Native scatter chart with parse helpers |
|
|
125
|
+
| Bubble | `create_bubble_chart()` | Native bubble chart with parse helpers |
|
|
126
|
+
| Range snapshot | `create_range_snapshot_chart()` | Valuation range snapshot with min/max/average/current markers |
|
|
127
|
+
|
|
128
|
+

|
|
129
|
+
|
|
130
|
+
*Each panel is a real, editable PowerPoint chart produced by `ablechart`, then rendered to an image. Every one can be parsed back into a DataFrame and updated in place. All four use the same real dataset (CATL 300750.SZ, source: Tushare); regenerate with `python scripts/make_gallery.py`.*
|
|
131
|
+
|
|
132
|
+
### Semantic financial families
|
|
133
|
+
|
|
134
|
+
`create_semantic_chart()` and the family-specific helpers provide a higher
|
|
135
|
+
level mapping from financial-report concepts to native chart or shape
|
|
136
|
+
composition primitives.
|
|
137
|
+
|
|
138
|
+
Currently exposed families include:
|
|
139
|
+
|
|
140
|
+
- `performance_compare`
|
|
141
|
+
- `distribution_plus_history`
|
|
142
|
+
- `style_box`
|
|
143
|
+
- `style_allocation`
|
|
144
|
+
- `factor_exposure`
|
|
145
|
+
- `score_overlay`
|
|
146
|
+
- `concentration`
|
|
147
|
+
- `event_timeline`
|
|
148
|
+
- `attribution_decomposition`
|
|
149
|
+
- `ranked_tile_matrix`
|
|
150
|
+
- `heatmap_matrix`
|
|
151
|
+
- `table_plus_chart_composite`
|
|
152
|
+
- `factor_attribution_panel`
|
|
153
|
+
- `regime_table_panel`
|
|
154
|
+
- `manager_timeline_profile`
|
|
155
|
+
- `award_timeline_panel`
|
|
156
|
+
- `selection_timing_grid`
|
|
157
|
+
- `dual_chart_panel`
|
|
158
|
+
- `holding_detail`
|
|
159
|
+
|
|
160
|
+
This layer is useful for single-slide financial report components. It is not
|
|
161
|
+
a report orchestration engine.
|
|
162
|
+
|
|
163
|
+
## Public API Shape
|
|
164
|
+
|
|
165
|
+
The public API is organized around the chart asset lifecycle:
|
|
166
|
+
|
|
167
|
+
| Lifecycle | Representative APIs |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| Create | `create_combo_chart()`, `create_waterfall_chart()`, `create_semantic_chart()` |
|
|
170
|
+
| Parse | `parse_chart_from_pptx()`, `parse_all_charts_from_pptx()`, `get_semantic_chart_spec()` |
|
|
171
|
+
| Metadata | `ChartMetadataV1`, `write_chart_metadata`, `METADATA_SCHEMA_VERSION` |
|
|
172
|
+
| Inspect | `inspect_pptx_charts()`, `ChartInventoryItem`, `ChartSelector` |
|
|
173
|
+
| Replace | `replace_pptx_chart_data()`, `SeriesData`, `ReplaceResult` |
|
|
174
|
+
|
|
175
|
+
The design goal is that a generated chart can become a durable asset:
|
|
176
|
+
created once, opened and edited in PowerPoint, parsed again later, and updated
|
|
177
|
+
without losing its position, size, identity, or basic editability.
|
|
178
|
+
|
|
179
|
+
## How This Differs From Similar Packages
|
|
180
|
+
|
|
181
|
+
`ablechart` is not trying to replace broad PowerPoint SDKs. It is a
|
|
182
|
+
small layer for high-quality chart assets and template-safe chart updates.
|
|
183
|
+
|
|
184
|
+
| Project | Main strength | How `ablechart` differs |
|
|
185
|
+
| --- | --- | --- |
|
|
186
|
+
| [`python-pptx`](https://python-pptx.readthedocs.io/en/latest/user/charts.html) | General Python library for creating and updating `.pptx` files, including adding charts and replacing chart data. | `ablechart` builds on the PowerPoint-native path but adds financial chart families, semantic metadata, chart round-trip parsing, inventory, and template-safe replacement contracts. |
|
|
187
|
+
| [`PptxGenJS`](https://gitbrent.github.io/PptxGenJS/) | Broad JavaScript presentation generation for Node.js, browser, React, Electron, charts, tables, images, and HTML-to-PPTX workflows. | `ablechart` is Python-only and intentionally narrower: it does not generate full decks from layouts, but focuses on editable chart assets and parse/update lifecycles. |
|
|
188
|
+
| [`mschart`](https://ardata-fr.github.io/mschart/) | R package for native editable Microsoft Office charts, commonly used with `officer`. | `ablechart` targets Python financial-report workflows and adds inspect/replace and metadata round-trip APIs for existing `.pptx` chart assets. |
|
|
189
|
+
| [`Aspose.Slides for Python via .NET`](https://docs.aspose.com/slides/python-net/) | Commercial, full-featured presentation processing SDK with broad PowerPoint manipulation, chart modules, export, animation, SmartArt, VBA, and conversion features. | `ablechart` is MIT-licensed and much smaller. It does not aim to cover the whole PowerPoint object model or rendering/export conversion. |
|
|
190
|
+
| [`Spire.Presentation for Python`](https://www.e-iceblue.com/Introduce/presentation-for-python.html) | Commercial presentation API covering creation, editing, conversion, and chart operations. | `ablechart` avoids broad document processing scope and concentrates on deterministic chart creation, chart metadata, and safe data replacement. |
|
|
191
|
+
|
|
192
|
+
In short:
|
|
193
|
+
|
|
194
|
+
- Use `python-pptx` when you need a general Python PowerPoint building block.
|
|
195
|
+
- Use `PptxGenJS` when your stack is JavaScript or browser-side PPTX generation.
|
|
196
|
+
- Use Aspose or Spire when you need broad commercial document processing,
|
|
197
|
+
conversion, or complete PowerPoint object-model coverage.
|
|
198
|
+
- Use `ablechart` when your hard problem is editable, updateable,
|
|
199
|
+
inspectable PowerPoint charts for data-heavy reports.
|
|
200
|
+
|
|
201
|
+
## Current Limits
|
|
202
|
+
|
|
203
|
+
`ablechart` does not currently provide:
|
|
204
|
+
|
|
205
|
+
- full report assembly
|
|
206
|
+
- slide template management
|
|
207
|
+
- data connectors
|
|
208
|
+
- CLI job orchestration
|
|
209
|
+
- PDF or image export
|
|
210
|
+
- AI prompt-to-deck generation
|
|
211
|
+
- complete coverage of every PowerPoint chart type
|
|
212
|
+
- HTML or interactive web output
|
|
213
|
+
|
|
214
|
+
Unsupported chart replacement cases fail explicitly rather than silently
|
|
215
|
+
rebuilding the chart. The first-batch replacement path is focused on common
|
|
216
|
+
embedded-workbook chart types such as bar, line, combo, area, pie, scatter,
|
|
217
|
+
and bubble charts.
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
Run the test suite:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
python -m pytest
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Build the distribution artifacts:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
python -m build --sdist --wheel
|
|
231
|
+
python -m twine check dist/*
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The repository keeps contract tests for:
|
|
235
|
+
|
|
236
|
+
- public exports
|
|
237
|
+
- generated chart round-trips
|
|
238
|
+
- semantic metadata recovery
|
|
239
|
+
- existing-deck chart inspection
|
|
240
|
+
- in-place chart data replacement
|
|
241
|
+
- checked-in `.pptx` fixture behavior
|
|
242
|
+
|
|
243
|
+
## License
|
|
244
|
+
|
|
245
|
+
MIT License. See [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ablechart"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Editable PowerPoint chart engine for dual-axis financial charts"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [{ name = "ablechart contributors" }]
|
|
12
|
+
license = "MIT"
|
|
13
|
+
license-files = ["LICENSE"]
|
|
14
|
+
keywords = ["powerpoint", "pptx", "charts", "finance", "openxml"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 3 - Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Office/Business :: Office Suites",
|
|
24
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
# Upper bounds pinned 2026-05-24: pandas 3.0 broke chart metadata round-trip
|
|
29
|
+
# (categories_col read back as NaN). Treat this as a conservative published
|
|
30
|
+
# baseline; when relaxing, re-run full `pytest tests/` and install-from-wheel
|
|
31
|
+
# smoke tests under the target dependency set.
|
|
32
|
+
"python-pptx>=1.0.2,<1.1",
|
|
33
|
+
"pandas>=2.2,<3",
|
|
34
|
+
"numpy>=1.26,<2",
|
|
35
|
+
"lxml>=5,<6",
|
|
36
|
+
"openpyxl>=3.1,<4",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
test = ["pytest", "tomli; python_version < '3.11'"]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/hanlinlibham/ablechart"
|
|
44
|
+
Repository = "https://github.com/hanlinlibham/ablechart"
|
|
45
|
+
Issues = "https://github.com/hanlinlibham/ablechart/issues"
|
|
46
|
+
Changelog = "https://github.com/hanlinlibham/ablechart/blob/main/CHANGELOG.md"
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
include = ["ablechart*"]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
addopts = ["-p", "no:asyncio"]
|
|
54
|
+
pythonpath = ["src"]
|