pptxfill 0.2.5__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.
- pptxfill-0.2.5/.gitignore +16 -0
- pptxfill-0.2.5/.gitlab-ci.yml +38 -0
- pptxfill-0.2.5/.pre-commit-config.yaml +12 -0
- pptxfill-0.2.5/.python-version +1 -0
- pptxfill-0.2.5/PKG-INFO +34 -0
- pptxfill-0.2.5/README.md +22 -0
- pptxfill-0.2.5/docs/Makefile +20 -0
- pptxfill-0.2.5/docs/conf.py +44 -0
- pptxfill-0.2.5/docs/examples.rst +159 -0
- pptxfill-0.2.5/docs/img/example_multi_table_1.png +0 -0
- pptxfill-0.2.5/docs/img/example_multi_table_2.png +0 -0
- pptxfill-0.2.5/docs/img/example_multi_table_3.png +0 -0
- pptxfill-0.2.5/docs/img/example_table_1.png +0 -0
- pptxfill-0.2.5/docs/img/example_table_2.png +0 -0
- pptxfill-0.2.5/docs/img/example_text_1.png +0 -0
- pptxfill-0.2.5/docs/img/example_text_2.png +0 -0
- pptxfill-0.2.5/docs/img/selection-pane.png +0 -0
- pptxfill-0.2.5/docs/index.rst +35 -0
- pptxfill-0.2.5/docs/make.bat +35 -0
- pptxfill-0.2.5/docs/reference.rst +46 -0
- pptxfill-0.2.5/example/data.csv +51 -0
- pptxfill-0.2.5/example/examply.py +46 -0
- pptxfill-0.2.5/example/logo.png +0 -0
- pptxfill-0.2.5/example/result.pptx +0 -0
- pptxfill-0.2.5/example/template.pptx +0 -0
- pptxfill-0.2.5/pptxfill/__init__.py +21 -0
- pptxfill-0.2.5/pptxfill/eq.py +66 -0
- pptxfill-0.2.5/pptxfill/loader.py +57 -0
- pptxfill-0.2.5/pptxfill/picture.py +73 -0
- pptxfill-0.2.5/pptxfill/slides.py +93 -0
- pptxfill-0.2.5/pptxfill/table.py +105 -0
- pptxfill-0.2.5/pptxfill/text.py +23 -0
- pptxfill-0.2.5/pptxfill/walker.py +48 -0
- pptxfill-0.2.5/pyproject.toml +31 -0
- pptxfill-0.2.5/uv.lock +2038 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
variables:
|
|
2
|
+
# GitLab CI creates a separate mountpoint for the build directory,
|
|
3
|
+
# so we need to copy instead of using hard links.
|
|
4
|
+
UV_VERSION: "0.9.22"
|
|
5
|
+
PYTHON_VERSION: "3.12"
|
|
6
|
+
BASE_LAYER: bookworm-slim
|
|
7
|
+
UV_LINK_MODE: copy
|
|
8
|
+
UV_CACHE_DIR: .uv-cache
|
|
9
|
+
|
|
10
|
+
publish:
|
|
11
|
+
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
|
|
12
|
+
rules:
|
|
13
|
+
- if: $CI_COMMIT_TAG =~ /^v/
|
|
14
|
+
cache:
|
|
15
|
+
- key:
|
|
16
|
+
files:
|
|
17
|
+
- uv.lock
|
|
18
|
+
paths:
|
|
19
|
+
- $UV_CACHE_DIR
|
|
20
|
+
script:
|
|
21
|
+
- uv build
|
|
22
|
+
- uv publish --token "$UV_PUBLISH_TOKEN"
|
|
23
|
+
- uv cache prune --ci
|
|
24
|
+
|
|
25
|
+
docs:
|
|
26
|
+
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
|
|
27
|
+
rules:
|
|
28
|
+
- if: $CI_COMMIT_TAG =~ /^v/
|
|
29
|
+
cache:
|
|
30
|
+
- key:
|
|
31
|
+
files:
|
|
32
|
+
- uv.lock
|
|
33
|
+
paths:
|
|
34
|
+
- $UV_CACHE_DIR
|
|
35
|
+
script:
|
|
36
|
+
- uv run --group dev sphinx-build docs public
|
|
37
|
+
- uv cache prune --ci
|
|
38
|
+
pages: true
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
3
|
+
rev: 0.5.28
|
|
4
|
+
hooks:
|
|
5
|
+
- id: uv-lock
|
|
6
|
+
# Apply version tag whenever version changes in pyproject.toml
|
|
7
|
+
- repo: https://gitlab.com/snorkysnark/pyproject-auto-tag
|
|
8
|
+
rev: v0.3.0
|
|
9
|
+
hooks:
|
|
10
|
+
- id: pyproject-auto-tag
|
|
11
|
+
|
|
12
|
+
default_install_hook_types: [pre-commit, post-commit]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
pptxfill-0.2.5/PKG-INFO
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pptxfill
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Project-URL: Repository, https://gitlab.com/csml-tools/pptxfill/
|
|
6
|
+
Project-URL: Documentation, https://csml-tools.gitlab.io/pptxfill/
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
|
+
Requires-Dist: pandas>=2.3.3
|
|
9
|
+
Requires-Dist: python-pptx>=1.0.2
|
|
10
|
+
Requires-Dist: types-lxml>=2026.1.1
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# pptxfill
|
|
14
|
+
|
|
15
|
+
**pptxfill** is a templating library for PowerPoint presentations.
|
|
16
|
+
|
|
17
|
+
Unlike other similar template engines, this one does not rely on Slide Layouts,
|
|
18
|
+
instead using a more flexible system similar to ones used for Word documents,
|
|
19
|
+
where you can substitute variables in text blocks using string formatting,
|
|
20
|
+
replace arbitrary images and fill tables with data.
|
|
21
|
+
|
|
22
|
+
[Documentation](https://csml-tools.gitlab.io/pptxfill/)
|
|
23
|
+
|
|
24
|
+
## Installation:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
uv add pptxfill
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
or
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
pip install pptxfill
|
|
34
|
+
```
|
pptxfill-0.2.5/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# pptxfill
|
|
2
|
+
|
|
3
|
+
**pptxfill** is a templating library for PowerPoint presentations.
|
|
4
|
+
|
|
5
|
+
Unlike other similar template engines, this one does not rely on Slide Layouts,
|
|
6
|
+
instead using a more flexible system similar to ones used for Word documents,
|
|
7
|
+
where you can substitute variables in text blocks using string formatting,
|
|
8
|
+
replace arbitrary images and fill tables with data.
|
|
9
|
+
|
|
10
|
+
[Documentation](https://csml-tools.gitlab.io/pptxfill/)
|
|
11
|
+
|
|
12
|
+
## Installation:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
uv add pptxfill
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
or
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
pip install pptxfill
|
|
22
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = .
|
|
9
|
+
BUILDDIR = _build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
18
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
19
|
+
%: Makefile
|
|
20
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# For the full list of built-in configuration values, see the documentation:
|
|
4
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
5
|
+
|
|
6
|
+
# -- Project information -----------------------------------------------------
|
|
7
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
sys.path.append(".")
|
|
12
|
+
|
|
13
|
+
project = "pptxfill"
|
|
14
|
+
copyright = "2026, snorkysnark"
|
|
15
|
+
author = "snorkysnark"
|
|
16
|
+
release = "0.2.5"
|
|
17
|
+
|
|
18
|
+
# -- General configuration ---------------------------------------------------
|
|
19
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
|
20
|
+
|
|
21
|
+
extensions = [
|
|
22
|
+
"sphinx.ext.autodoc",
|
|
23
|
+
"sphinx.ext.napoleon",
|
|
24
|
+
"sphinx.ext.intersphinx",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
templates_path = ["_templates"]
|
|
28
|
+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# -- Options for HTML output -------------------------------------------------
|
|
32
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
|
33
|
+
|
|
34
|
+
html_theme = "alabaster"
|
|
35
|
+
html_static_path = ["_static"]
|
|
36
|
+
|
|
37
|
+
napoleon_google_docstring = True
|
|
38
|
+
|
|
39
|
+
intersphinx_mapping = {
|
|
40
|
+
"python": ("https://docs.python.org/3", None),
|
|
41
|
+
"pptx": ("https://python-pptx.readthedocs.io/en/latest/", None),
|
|
42
|
+
"pandas": ("https://pandas.pydata.org/docs/", None),
|
|
43
|
+
}
|
|
44
|
+
autodoc_typehints = "both"
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Examples
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
.. |br| raw:: html
|
|
5
|
+
|
|
6
|
+
<br />
|
|
7
|
+
|
|
8
|
+
Loading your template
|
|
9
|
+
---------------------
|
|
10
|
+
|
|
11
|
+
Since this library doesn't use Slide Layouts, your template is just a regular presentation. |br|
|
|
12
|
+
The template used in these examples: `template.pptx <https://gitlab.com/csml-tools/pptxfill/-/blob/main/example/template.pptx?ref_type=heads>`_
|
|
13
|
+
|
|
14
|
+
Ref: :func:`pptxfill.load_template`
|
|
15
|
+
|
|
16
|
+
.. code-block:: python
|
|
17
|
+
|
|
18
|
+
from pptxfill import load_template
|
|
19
|
+
|
|
20
|
+
template = load_template("template.pptx")
|
|
21
|
+
|
|
22
|
+
Text formatting
|
|
23
|
+
---------------
|
|
24
|
+
|
|
25
|
+
Apply string formatting to all text blocks on Slide 0. |br|
|
|
26
|
+
Python's `string formatting rules <https://www.w3schools.com/python/python_string_formatting.asp>`_ apply, including format specifiers for numbers.
|
|
27
|
+
|
|
28
|
+
Ref: :func:`pptxfill.format_text_on_slide`
|
|
29
|
+
|
|
30
|
+
.. code-block:: python
|
|
31
|
+
|
|
32
|
+
from pptxfill import format_text_on_slide
|
|
33
|
+
|
|
34
|
+
format_text_on_slide(
|
|
35
|
+
template.slides[0],
|
|
36
|
+
name="Example University",
|
|
37
|
+
publications=2932,
|
|
38
|
+
fwci=7.3658,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
.. image:: img/example_text_1.png
|
|
42
|
+
|
|
43
|
+
.. image:: img/example_text_2.png
|
|
44
|
+
|
|
45
|
+
Images
|
|
46
|
+
------
|
|
47
|
+
|
|
48
|
+
First, open the `Selection Pane <https://support.microsoft.com/en-us/powerpoint/use-the-selection-pane-to-manage-objects-in-documents>`_
|
|
49
|
+
in PowerPoint (``Alt + F10``) and give your placeholder a unique name.
|
|
50
|
+
|
|
51
|
+
.. image:: img/selection-pane.png
|
|
52
|
+
|
|
53
|
+
Then it can be replaced by the target image.
|
|
54
|
+
|
|
55
|
+
Set ``full_width=True`` or ``full_height=True`` to stretch the image to the placeholder's width and height
|
|
56
|
+
|
|
57
|
+
Ref: :func:`pptxfill.replace_image_by_name`
|
|
58
|
+
|
|
59
|
+
.. code-block:: python
|
|
60
|
+
|
|
61
|
+
from pptxfill import replace_image_by_name
|
|
62
|
+
|
|
63
|
+
replace_image_by_name(template.slides[0], "logo", "logo.png")
|
|
64
|
+
|
|
65
|
+
Tables
|
|
66
|
+
------
|
|
67
|
+
|
|
68
|
+
Fill a PowerPoint table with the contents of a pandas DataFrame. |br|
|
|
69
|
+
Example data: `data.csv <https://gitlab.com/csml-tools/pptxfill/-/blob/main/example/data.csv?ref_type=heads>`_
|
|
70
|
+
|
|
71
|
+
Ref: :func:`pptxfill.fill_table_by_name`
|
|
72
|
+
|
|
73
|
+
.. code-block:: python
|
|
74
|
+
|
|
75
|
+
import pandas as pd
|
|
76
|
+
from pptxfill import fill_table_by_name
|
|
77
|
+
|
|
78
|
+
data = pd.read_csv("data.csv")
|
|
79
|
+
fill_table_by_name(template.slides[0], "table", data)
|
|
80
|
+
|
|
81
|
+
Since by default ``skip_header=True``, the first row would not be filled.
|
|
82
|
+
|
|
83
|
+
The folliwing row must contain string templates, where data would be inserted
|
|
84
|
+
using :meth:`str.format` with a single argument: ``string.format(value)``)
|
|
85
|
+
|
|
86
|
+
.. image:: img/example_table_1.png
|
|
87
|
+
|
|
88
|
+
.. image:: img/example_table_2.png
|
|
89
|
+
|
|
90
|
+
This function *does not* automatically expand the table,
|
|
91
|
+
so the data will be cut off where the table ends
|
|
92
|
+
|
|
93
|
+
Repeating slides
|
|
94
|
+
----------------
|
|
95
|
+
|
|
96
|
+
Sometimes you may wish to duplicate the slide of the original presentation.
|
|
97
|
+
|
|
98
|
+
Since this would modify :attr:`template.slides <pptx.presentation.Presentation.slides>`,
|
|
99
|
+
you can make a copy of it to still be able to refere to slides by their original indices:
|
|
100
|
+
|
|
101
|
+
.. code-block:: python
|
|
102
|
+
|
|
103
|
+
template_slides = list(template.slides)
|
|
104
|
+
|
|
105
|
+
Let's make Slide #2 repeat 5 times:
|
|
106
|
+
|
|
107
|
+
Ref: :func:`pptxfill.multiply_slide`
|
|
108
|
+
|
|
109
|
+
.. code-block:: python
|
|
110
|
+
|
|
111
|
+
from pptxfill import multiply_slide
|
|
112
|
+
|
|
113
|
+
repeating_slides = multiply_slide(template.slides, template_slides[1], 5)
|
|
114
|
+
for i, slide in enumerate(repeating_slides):
|
|
115
|
+
format_text_on_slide(slide, slide_num=i + 1)
|
|
116
|
+
|
|
117
|
+
Split table into multiple slides
|
|
118
|
+
--------------------------------
|
|
119
|
+
|
|
120
|
+
If you wish to show the entire DataFrame's content, you can split it into multiple slides:
|
|
121
|
+
|
|
122
|
+
.. code-block:: python
|
|
123
|
+
|
|
124
|
+
from pptxfill import find_shape_by_name
|
|
125
|
+
from pptx.shapes.graphfrm import GraphicFrame
|
|
126
|
+
|
|
127
|
+
table = find_shape_by_name(template_slides[1], "table", GraphicFrame).table
|
|
128
|
+
|
|
129
|
+
# Since by default skip_header=True, the first row is not filled with data
|
|
130
|
+
table_size = len(table.rows) - 1
|
|
131
|
+
table_slides = multiply_slide(
|
|
132
|
+
template.slides,
|
|
133
|
+
template_slides[1],
|
|
134
|
+
math.ceil(len(data) / table_size)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
for i, slide in enumerate(table_slides):
|
|
138
|
+
format_text_on_slide(slide, slide_num=i + 1)
|
|
139
|
+
fill_table_by_name(
|
|
140
|
+
slide,
|
|
141
|
+
"table",
|
|
142
|
+
data.iloc[i * table_size : (i + 1) * table_size],
|
|
143
|
+
rownum=True,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
Here, we are using ``rownum=True`` to display the row index in the first column.
|
|
147
|
+
|
|
148
|
+
.. image:: img/example_multi_table_1.png
|
|
149
|
+
|
|
150
|
+
.. image:: img/example_multi_table_2.png
|
|
151
|
+
|
|
152
|
+
.. image:: img/example_multi_table_3.png
|
|
153
|
+
|
|
154
|
+
Exporting
|
|
155
|
+
---------
|
|
156
|
+
|
|
157
|
+
.. code-block:: python
|
|
158
|
+
|
|
159
|
+
template.save("result.pptx")
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.. pptxfill documentation master file, created by
|
|
2
|
+
sphinx-quickstart on Mon Aug 24 14:38:25 2026.
|
|
3
|
+
You can adapt this file completely to your liking, but it should at least
|
|
4
|
+
contain the root `toctree` directive.
|
|
5
|
+
|
|
6
|
+
pptxfill documentation
|
|
7
|
+
========================
|
|
8
|
+
|
|
9
|
+
**pptxfill** is a templating library for PowerPoint presentations.
|
|
10
|
+
|
|
11
|
+
Unlike other similar template engines, this one does not rely on Slide Layouts,
|
|
12
|
+
instead using a more flexible system similar to ones used for Word documents,
|
|
13
|
+
where you can substitute variables in text blocks using string formatting,
|
|
14
|
+
replace arbitrary images and fill tables with data.
|
|
15
|
+
|
|
16
|
+
Installation
|
|
17
|
+
------------
|
|
18
|
+
|
|
19
|
+
.. code-block::
|
|
20
|
+
|
|
21
|
+
uv add pptxfill --index https://gitlab.com/api/v4/groups/101754947/-/packages/pypi/simple
|
|
22
|
+
|
|
23
|
+
or
|
|
24
|
+
|
|
25
|
+
.. code-block::
|
|
26
|
+
|
|
27
|
+
pip install --index-url https://gitlab.com/api/v4/groups/101754947/-/packages/pypi/simple pptxfill
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
.. toctree::
|
|
31
|
+
:maxdepth: 2
|
|
32
|
+
:caption: Contents:
|
|
33
|
+
|
|
34
|
+
examples
|
|
35
|
+
reference
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@ECHO OFF
|
|
2
|
+
|
|
3
|
+
pushd %~dp0
|
|
4
|
+
|
|
5
|
+
REM Command file for Sphinx documentation
|
|
6
|
+
|
|
7
|
+
if "%SPHINXBUILD%" == "" (
|
|
8
|
+
set SPHINXBUILD=sphinx-build
|
|
9
|
+
)
|
|
10
|
+
set SOURCEDIR=.
|
|
11
|
+
set BUILDDIR=_build
|
|
12
|
+
|
|
13
|
+
%SPHINXBUILD% >NUL 2>NUL
|
|
14
|
+
if errorlevel 9009 (
|
|
15
|
+
echo.
|
|
16
|
+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
17
|
+
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
18
|
+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
19
|
+
echo.may add the Sphinx directory to PATH.
|
|
20
|
+
echo.
|
|
21
|
+
echo.If you don't have Sphinx installed, grab it from
|
|
22
|
+
echo.https://www.sphinx-doc.org/
|
|
23
|
+
exit /b 1
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if "%1" == "" goto help
|
|
27
|
+
|
|
28
|
+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
29
|
+
goto end
|
|
30
|
+
|
|
31
|
+
:help
|
|
32
|
+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
33
|
+
|
|
34
|
+
:end
|
|
35
|
+
popd
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
API Reference
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
Template
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
.. autofunction:: pptxfill.load_template
|
|
8
|
+
|
|
9
|
+
Shape Tree
|
|
10
|
+
----------
|
|
11
|
+
|
|
12
|
+
.. autofunction:: pptxfill.walk_shapes
|
|
13
|
+
|
|
14
|
+
.. autofunction:: pptxfill.find_shape_by_name
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Slide Manipulation
|
|
18
|
+
------------------
|
|
19
|
+
|
|
20
|
+
.. autofunction:: pptxfill.copy_slide_content
|
|
21
|
+
|
|
22
|
+
.. autofunction:: pptxfill.insert_slide
|
|
23
|
+
|
|
24
|
+
.. autofunction:: pptxfill.delete_slide
|
|
25
|
+
|
|
26
|
+
.. autofunction:: pptxfill.multiply_slide
|
|
27
|
+
|
|
28
|
+
Text
|
|
29
|
+
----
|
|
30
|
+
|
|
31
|
+
.. autofunction:: pptxfill.format_text_on_slide
|
|
32
|
+
|
|
33
|
+
Images
|
|
34
|
+
------
|
|
35
|
+
|
|
36
|
+
.. autofunction:: pptxfill.replace_image
|
|
37
|
+
|
|
38
|
+
.. autofunction:: pptxfill.replace_image_by_name
|
|
39
|
+
|
|
40
|
+
Tables
|
|
41
|
+
------
|
|
42
|
+
|
|
43
|
+
.. autofunction:: pptxfill.fill_table
|
|
44
|
+
|
|
45
|
+
.. autofunction:: pptxfill.fill_table_by_name
|
|
46
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name,cost,percentage
|
|
2
|
+
logistics,1783,27.418243245046312
|
|
3
|
+
league,3737,3.3290774158836633
|
|
4
|
+
spectrograph,2635,50.07984744768956
|
|
5
|
+
noodle,3245,30.434240332249495
|
|
6
|
+
budget,2841,61.96213623361662
|
|
7
|
+
chili,2201,37.97385252086871
|
|
8
|
+
wonderful,4939,74.8964289076211
|
|
9
|
+
tempo,4828,45.28791637745536
|
|
10
|
+
knowledge,4512,68.6937978433078
|
|
11
|
+
legend,2315,90.10919179049583
|
|
12
|
+
needy,1588,73.43247827182032
|
|
13
|
+
divide,4765,63.63810285920232
|
|
14
|
+
reliability,3871,32.03240986723951
|
|
15
|
+
interlay,3475,33.249377311697096
|
|
16
|
+
bowling,2585,22.03289180796749
|
|
17
|
+
animated,4967,93.45380236016199
|
|
18
|
+
fur,2768,37.45503608654145
|
|
19
|
+
spread,1234,83.06500436711761
|
|
20
|
+
horst,1755,9.120487683357359
|
|
21
|
+
meeting,3808,52.405902077128474
|
|
22
|
+
spree,1309,66.72493850677978
|
|
23
|
+
cloudy,4214,97.41879061022084
|
|
24
|
+
frenzy,4007,63.620655039985586
|
|
25
|
+
fog,4919,21.67586948741935
|
|
26
|
+
macro,3208,23.05521140069565
|
|
27
|
+
hearing,3821,1.306688325996963
|
|
28
|
+
settler,2208,15.73287084523165
|
|
29
|
+
underpants,1044,39.204788529376664
|
|
30
|
+
starboard,2712,84.98825725278499
|
|
31
|
+
former,4858,26.053151850542566
|
|
32
|
+
monopoly,3870,48.57777263757497
|
|
33
|
+
rag,1255,23.219516416486996
|
|
34
|
+
wake,3207,18.642743704938557
|
|
35
|
+
elevation,1990,89.36114451631306
|
|
36
|
+
colonization,1320,84.41680453820814
|
|
37
|
+
nice,4346,10.194224035576793
|
|
38
|
+
king,3682,99.506334861964
|
|
39
|
+
pulley,1309,11.529774855044206
|
|
40
|
+
edge,4319,59.955557737761865
|
|
41
|
+
cinema,3713,88.72685001257503
|
|
42
|
+
motorboat,1525,96.67543307972387
|
|
43
|
+
steward,4690,67.82904861043019
|
|
44
|
+
helmet,3917,54.24036679578976
|
|
45
|
+
gambling,2594,2.016212327948097
|
|
46
|
+
rainstorm,3893,1.1354635256942913
|
|
47
|
+
algorithm,4883,70.74882506429151
|
|
48
|
+
restructuring,4050,60.716841589077
|
|
49
|
+
washtub,3875,2.8019898207405136
|
|
50
|
+
chivalrous,1580,75.18100874664756
|
|
51
|
+
flashy,3755,16.009085621452137
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from pptx.shapes.graphfrm import GraphicFrame
|
|
5
|
+
|
|
6
|
+
from pptxfill import (
|
|
7
|
+
fill_table_by_name,
|
|
8
|
+
find_shape_by_name,
|
|
9
|
+
format_text_on_slide,
|
|
10
|
+
load_template,
|
|
11
|
+
multiply_slide,
|
|
12
|
+
replace_image_by_name,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
template = load_template("template.pptx")
|
|
16
|
+
template_slides = list(template.slides)
|
|
17
|
+
|
|
18
|
+
format_text_on_slide(
|
|
19
|
+
template_slides[0],
|
|
20
|
+
name="Example University",
|
|
21
|
+
publications=2932,
|
|
22
|
+
fwci=7.3658,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
replace_image_by_name(template_slides[0], "logo", "logo.png")
|
|
26
|
+
|
|
27
|
+
data = pd.read_csv("data.csv")
|
|
28
|
+
fill_table_by_name(template_slides[0], "table", data)
|
|
29
|
+
|
|
30
|
+
table = find_shape_by_name(template_slides[1], "table", GraphicFrame).table
|
|
31
|
+
# Since by default skip_header=True, the first row is not filled with data
|
|
32
|
+
table_size = len(table.rows) - 1
|
|
33
|
+
table_slides = multiply_slide(
|
|
34
|
+
template.slides, template_slides[1], math.ceil(len(data) / table_size)
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
for i, slide in enumerate(table_slides):
|
|
38
|
+
format_text_on_slide(slide, slide_num=i + 1)
|
|
39
|
+
fill_table_by_name(
|
|
40
|
+
slide,
|
|
41
|
+
"table",
|
|
42
|
+
data.iloc[i * table_size : (i + 1) * table_size],
|
|
43
|
+
rownum=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
template.save("result.pptx")
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .loader import load_template
|
|
2
|
+
from .picture import replace_image, replace_image_by_name
|
|
3
|
+
from .slides import copy_slide_content, delete_slide, insert_slide, multiply_slide
|
|
4
|
+
from .table import fill_table, fill_table_by_name
|
|
5
|
+
from .text import format_text_on_slide
|
|
6
|
+
from .walker import find_shape_by_name, walk_shapes
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"load_template",
|
|
10
|
+
"replace_image",
|
|
11
|
+
"replace_image_by_name",
|
|
12
|
+
"copy_slide_content",
|
|
13
|
+
"delete_slide",
|
|
14
|
+
"insert_slide",
|
|
15
|
+
"multiply_slide",
|
|
16
|
+
"fill_table",
|
|
17
|
+
"fill_table_by_name",
|
|
18
|
+
"format_text_on_slide",
|
|
19
|
+
"walk_shapes",
|
|
20
|
+
"find_shape_by_name",
|
|
21
|
+
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Callable, Optional, cast
|
|
2
|
+
|
|
3
|
+
from lxml.etree import Element, QName
|
|
4
|
+
from lxml.etree import tostring as lxml_tostring
|
|
5
|
+
from pptx.oxml.action import CT_Hyperlink
|
|
6
|
+
from pptx.oxml.text import CT_TextCharacterProperties, CT_TextFont
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def optional_eq[T](v1: Optional[T], v2: Optional[T], eq: Callable[[T, T], bool]):
|
|
10
|
+
if v1 is None or v2 is None:
|
|
11
|
+
return (v1 is None) == (v2 is None)
|
|
12
|
+
|
|
13
|
+
return eq(v1, v2)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_fill_properties(rpr: CT_TextCharacterProperties):
|
|
17
|
+
"""rPr.eg_fillProperties doesn't cover all fill-related tags, so using a custom method"""
|
|
18
|
+
return next(
|
|
19
|
+
filter(
|
|
20
|
+
lambda el: not isinstance(el.tag, bytearray)
|
|
21
|
+
and QName(el.tag).localname
|
|
22
|
+
in {
|
|
23
|
+
"noFill",
|
|
24
|
+
"solidFill",
|
|
25
|
+
"gradFill",
|
|
26
|
+
"blipFill",
|
|
27
|
+
"pattFill",
|
|
28
|
+
"grpFill",
|
|
29
|
+
"effectLst",
|
|
30
|
+
"effectDag",
|
|
31
|
+
"highlight",
|
|
32
|
+
"uLnTx",
|
|
33
|
+
"uLn",
|
|
34
|
+
"uFillTx",
|
|
35
|
+
"uFill",
|
|
36
|
+
},
|
|
37
|
+
cast(Element, rpr),
|
|
38
|
+
),
|
|
39
|
+
None,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def elements_eq(el1: Element, el2: Element):
|
|
44
|
+
return lxml_tostring(el1) == lxml_tostring(el2)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def text_font_eq(t1: CT_TextFont, t2: CT_TextFont):
|
|
48
|
+
return t1.typeface == t2.typeface
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def hyperlink_eq(h1: CT_Hyperlink, h2: CT_Hyperlink):
|
|
52
|
+
return h1.rId == h2.rId and h1.action == h2.action
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def text_character_properties_eq(
|
|
56
|
+
rpr1: CT_TextCharacterProperties, rpr2: CT_TextCharacterProperties
|
|
57
|
+
):
|
|
58
|
+
return (
|
|
59
|
+
optional_eq(get_fill_properties(rpr1), get_fill_properties(rpr2), elements_eq)
|
|
60
|
+
and optional_eq(rpr1.latin, rpr2.latin, text_font_eq)
|
|
61
|
+
and optional_eq(rpr1.hlinkClick, rpr2.hlinkClick, hyperlink_eq)
|
|
62
|
+
and rpr1.sz == rpr2.sz
|
|
63
|
+
and rpr1.b == rpr2.b
|
|
64
|
+
and rpr1.i == rpr2.i
|
|
65
|
+
and rpr1.u == rpr2.u
|
|
66
|
+
)
|