xlsxturbo 0.4.1__tar.gz → 0.7.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.
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/CHANGELOG.md +46 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/Cargo.lock +21 -21
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/Cargo.toml +1 -1
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/PKG-INFO +118 -2
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/README.md +117 -1
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/ROADMAP.md +13 -8
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/pyproject.toml +1 -1
- xlsxturbo-0.7.0/python/xlsxturbo/__init__.pyi +118 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/src/lib.rs +982 -66
- xlsxturbo-0.7.0/tests/test_v060_features.py +449 -0
- xlsxturbo-0.4.1/python/xlsxturbo/__init__.pyi +0 -144
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/.github/workflows/ci.yml +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/.github/workflows/release.yml +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/.gitignore +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/LICENSE +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/benchmark.py +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/benchmark_parallel.py +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/python/xlsxturbo/__init__.py +0 -0
- {xlsxturbo-0.4.1 → xlsxturbo-0.7.0}/src/main.rs +0 -0
|
@@ -5,6 +5,49 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.0] - 2025-12-28
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Column formatting with wildcards** - `column_formats` parameter for styling columns by pattern
|
|
12
|
+
- Wildcard patterns: `prefix*`, `*suffix`, `*contains*`, or exact match
|
|
13
|
+
- Format options: `bg_color`, `font_color`, `num_format`, `bold`, `italic`, `underline`, `border`
|
|
14
|
+
- Example: `column_formats={'mcpt_*': {'bg_color': '#D6EAF8', 'num_format': '0.00000', 'border': True}}`
|
|
15
|
+
- Available in both `df_to_xlsx()` and `dfs_to_xlsx()`
|
|
16
|
+
- Per-sheet column formats via options dict in `dfs_to_xlsx()`
|
|
17
|
+
|
|
18
|
+
## [0.6.0] - 2025-12-08
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Global column width cap** - `column_widths={'_all': 50}` to cap all columns at a maximum width
|
|
22
|
+
- Can be combined with specific column widths: `{0: 20, '_all': 50}` (specific overrides '_all')
|
|
23
|
+
- Works with autofit as a cap: `autofit=True, column_widths={'_all': 30}` fits then caps
|
|
24
|
+
- **Table name parameter** - `table_name="MyTable"` to set custom Excel table names
|
|
25
|
+
- Invalid characters are automatically sanitized (spaces/special chars become underscores)
|
|
26
|
+
- Names starting with digits get underscore prefix (Excel requirement)
|
|
27
|
+
- Per-sheet table names in `dfs_to_xlsx()` via options dict
|
|
28
|
+
- **Header styling** - `header_format={'bold': True, 'bg_color': '#4F81BD', 'font_color': 'white'}`
|
|
29
|
+
- Supported options: `bold`, `italic`, `font_color`, `bg_color`, `font_size`, `underline`
|
|
30
|
+
- Colors accept hex (`#RRGGBB`) or named colors (white, black, red, blue, etc.)
|
|
31
|
+
- Per-sheet header formats in `dfs_to_xlsx()` via options dict
|
|
32
|
+
- Per-sheet options now support: `table_name`, `header_format`, `column_widths` with '_all'
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- `column_widths` parameter now accepts both integer keys (`{0: 20}`) and string keys (`{"_all": 50}`)
|
|
36
|
+
|
|
37
|
+
## [0.5.0] - 2025-12-08
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
- **Per-sheet options for `dfs_to_xlsx()`** - override global settings per sheet
|
|
41
|
+
- Each sheet can now be a 3-tuple: `(df, sheet_name, options_dict)`
|
|
42
|
+
- Options dict supports: `header`, `autofit`, `table_style`, `freeze_panes`, `column_widths`, `row_heights`
|
|
43
|
+
- Old 2-tuple API `(df, sheet_name)` still works (backward compatible)
|
|
44
|
+
- Example: `[(df1, "Data", {"table_style": "Medium2"}), (df2, "Instructions", {"header": False})]`
|
|
45
|
+
- `SheetOptions` TypedDict for type hints
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
- `dfs_to_xlsx()` signature now accepts mixed tuple formats internally
|
|
49
|
+
- Updated type stubs with new `SheetOptions` class and updated `dfs_to_xlsx` signature
|
|
50
|
+
|
|
8
51
|
## [0.4.1] - 2025-12-07
|
|
9
52
|
|
|
10
53
|
### Fixed
|
|
@@ -78,6 +121,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
78
121
|
- Support for custom sheet names
|
|
79
122
|
- Verbose mode for progress reporting
|
|
80
123
|
|
|
124
|
+
[0.7.0]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.7.0
|
|
125
|
+
[0.6.0]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.6.0
|
|
126
|
+
[0.5.0]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.5.0
|
|
81
127
|
[0.4.1]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.4.1
|
|
82
128
|
[0.4.0]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.4.0
|
|
83
129
|
[0.3.0]: https://github.com/tstone-1/xlsxturbo/releases/tag/v0.3.0
|
|
@@ -90,15 +90,15 @@ checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
|
|
90
90
|
|
|
91
91
|
[[package]]
|
|
92
92
|
name = "bumpalo"
|
|
93
|
-
version = "3.19.
|
|
93
|
+
version = "3.19.1"
|
|
94
94
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
95
|
-
checksum = "
|
|
95
|
+
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
|
96
96
|
|
|
97
97
|
[[package]]
|
|
98
98
|
name = "cc"
|
|
99
|
-
version = "1.2.
|
|
99
|
+
version = "1.2.51"
|
|
100
100
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
101
|
-
checksum = "
|
|
101
|
+
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
|
102
102
|
dependencies = [
|
|
103
103
|
"find-msvc-tools",
|
|
104
104
|
"shlex",
|
|
@@ -282,9 +282,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
|
|
282
282
|
|
|
283
283
|
[[package]]
|
|
284
284
|
name = "find-msvc-tools"
|
|
285
|
-
version = "0.1.
|
|
285
|
+
version = "0.1.6"
|
|
286
286
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
287
|
-
checksum = "
|
|
287
|
+
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
|
288
288
|
|
|
289
289
|
[[package]]
|
|
290
290
|
name = "flate2"
|
|
@@ -371,9 +371,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
|
|
371
371
|
|
|
372
372
|
[[package]]
|
|
373
373
|
name = "itoa"
|
|
374
|
-
version = "1.0.
|
|
374
|
+
version = "1.0.17"
|
|
375
375
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
376
|
-
checksum = "
|
|
376
|
+
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
|
377
377
|
|
|
378
378
|
[[package]]
|
|
379
379
|
name = "js-sys"
|
|
@@ -451,15 +451,15 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
|
451
451
|
|
|
452
452
|
[[package]]
|
|
453
453
|
name = "portable-atomic"
|
|
454
|
-
version = "1.
|
|
454
|
+
version = "1.13.0"
|
|
455
455
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
456
|
-
checksum = "
|
|
456
|
+
checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
|
|
457
457
|
|
|
458
458
|
[[package]]
|
|
459
459
|
name = "proc-macro2"
|
|
460
|
-
version = "1.0.
|
|
460
|
+
version = "1.0.104"
|
|
461
461
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
462
|
-
checksum = "
|
|
462
|
+
checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0"
|
|
463
463
|
dependencies = [
|
|
464
464
|
"unicode-ident",
|
|
465
465
|
]
|
|
@@ -574,9 +574,9 @@ dependencies = [
|
|
|
574
574
|
|
|
575
575
|
[[package]]
|
|
576
576
|
name = "rustix"
|
|
577
|
-
version = "1.1.
|
|
577
|
+
version = "1.1.3"
|
|
578
578
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
579
|
-
checksum = "
|
|
579
|
+
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
|
580
580
|
dependencies = [
|
|
581
581
|
"bitflags",
|
|
582
582
|
"errno",
|
|
@@ -593,9 +593,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
|
593
593
|
|
|
594
594
|
[[package]]
|
|
595
595
|
name = "ryu"
|
|
596
|
-
version = "1.0.
|
|
596
|
+
version = "1.0.22"
|
|
597
597
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
598
|
-
checksum = "
|
|
598
|
+
checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
|
|
599
599
|
|
|
600
600
|
[[package]]
|
|
601
601
|
name = "serde_core"
|
|
@@ -625,9 +625,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
|
625
625
|
|
|
626
626
|
[[package]]
|
|
627
627
|
name = "simd-adler32"
|
|
628
|
-
version = "0.3.
|
|
628
|
+
version = "0.3.8"
|
|
629
629
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
630
|
-
checksum = "
|
|
630
|
+
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
|
631
631
|
|
|
632
632
|
[[package]]
|
|
633
633
|
name = "strsim"
|
|
@@ -654,9 +654,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
|
654
654
|
|
|
655
655
|
[[package]]
|
|
656
656
|
name = "tempfile"
|
|
657
|
-
version = "3.
|
|
657
|
+
version = "3.24.0"
|
|
658
658
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
659
|
-
checksum = "
|
|
659
|
+
checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c"
|
|
660
660
|
dependencies = [
|
|
661
661
|
"fastrand",
|
|
662
662
|
"getrandom",
|
|
@@ -833,7 +833,7 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
|
|
833
833
|
|
|
834
834
|
[[package]]
|
|
835
835
|
name = "xlsxturbo"
|
|
836
|
-
version = "0.
|
|
836
|
+
version = "0.7.0"
|
|
837
837
|
dependencies = [
|
|
838
838
|
"chrono",
|
|
839
839
|
"clap",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xlsxturbo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -40,10 +40,13 @@ High-performance Excel writer with automatic type detection. Written in Rust, us
|
|
|
40
40
|
- **Direct DataFrame support** for pandas and polars
|
|
41
41
|
- **Excel tables** - filterable tables with 61 built-in styles (banded rows, autofilter)
|
|
42
42
|
- **Auto-fit columns** - automatically adjust column widths to fit content
|
|
43
|
-
- **Custom column widths** - set specific widths per column
|
|
43
|
+
- **Custom column widths** - set specific widths per column or cap all with _all
|
|
44
|
+
- **Header styling** - bold, colors, font size for header row
|
|
45
|
+
- **Named tables** - set custom table names
|
|
44
46
|
- **Custom row heights** - set specific heights per row
|
|
45
47
|
- **Freeze panes** - freeze header row for easier scrolling
|
|
46
48
|
- **Multi-sheet workbooks** - write multiple DataFrames to one file
|
|
49
|
+
- **Per-sheet options** - override settings per sheet in multi-sheet workbooks
|
|
47
50
|
- **Constant memory mode** - minimize RAM usage for very large files
|
|
48
51
|
- **Parallel CSV processing** - optional multi-core parsing for large files
|
|
49
52
|
- **Automatic type detection** from CSV strings and Python objects:
|
|
@@ -150,6 +153,83 @@ xlsxturbo.df_to_xlsx(df, "styled.xlsx",
|
|
|
150
153
|
)
|
|
151
154
|
```
|
|
152
155
|
|
|
156
|
+
### Global Column Width Cap
|
|
157
|
+
|
|
158
|
+
Use `column_widths={'_all': value}` to cap all columns at a maximum width:
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
import xlsxturbo
|
|
162
|
+
import pandas as pd
|
|
163
|
+
|
|
164
|
+
df = pd.DataFrame({
|
|
165
|
+
'Name': ['Alice', 'Bob'],
|
|
166
|
+
'VeryLongDescription': ['A' * 100, 'B' * 100],
|
|
167
|
+
'Score': [95, 87]
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
# Cap all columns at 30 characters
|
|
171
|
+
xlsxturbo.df_to_xlsx(df, "capped.xlsx", column_widths={'_all': 30})
|
|
172
|
+
|
|
173
|
+
# Mix specific widths with global cap (specific overrides '_all')
|
|
174
|
+
xlsxturbo.df_to_xlsx(df, "mixed.xlsx", column_widths={0: 15, '_all': 30})
|
|
175
|
+
|
|
176
|
+
# Autofit with cap: fit content, but never exceed 25 characters
|
|
177
|
+
xlsxturbo.df_to_xlsx(df, "fitted.xlsx", autofit=True, column_widths={'_all': 25})
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Named Excel Tables
|
|
181
|
+
|
|
182
|
+
Set custom names for Excel tables:
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
import xlsxturbo
|
|
186
|
+
import pandas as pd
|
|
187
|
+
|
|
188
|
+
df = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})
|
|
189
|
+
|
|
190
|
+
# Name the Excel table
|
|
191
|
+
xlsxturbo.df_to_xlsx(df, "report.xlsx",
|
|
192
|
+
table_style="Medium2",
|
|
193
|
+
table_name="ProductPrices"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Invalid characters are auto-sanitized, digits get underscore prefix
|
|
197
|
+
xlsxturbo.df_to_xlsx(df, "report.xlsx",
|
|
198
|
+
table_style="Medium2",
|
|
199
|
+
table_name="2024 Sales Data!" # Becomes "_2024_Sales_Data_"
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Header Styling
|
|
204
|
+
|
|
205
|
+
Apply custom formatting to header cells:
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
import xlsxturbo
|
|
209
|
+
import pandas as pd
|
|
210
|
+
|
|
211
|
+
df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Score': [95, 87]})
|
|
212
|
+
|
|
213
|
+
# Bold headers
|
|
214
|
+
xlsxturbo.df_to_xlsx(df, "bold.xlsx", header_format={'bold': True})
|
|
215
|
+
|
|
216
|
+
# Full styling with colors
|
|
217
|
+
xlsxturbo.df_to_xlsx(df, "styled.xlsx", header_format={
|
|
218
|
+
'bold': True,
|
|
219
|
+
'bg_color': '#4F81BD', # Blue background
|
|
220
|
+
'font_color': 'white' # White text
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
# Available options:
|
|
224
|
+
# - bold (bool): Bold text
|
|
225
|
+
# - italic (bool): Italic text
|
|
226
|
+
# - font_color (str): '#RRGGBB' or named color (white, black, red, blue, etc.)
|
|
227
|
+
# - bg_color (str): Background color
|
|
228
|
+
# - font_size (float): Font size in points
|
|
229
|
+
# - underline (bool): Underlined text
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
|
|
153
233
|
### Multi-Sheet Workbooks
|
|
154
234
|
|
|
155
235
|
```python
|
|
@@ -178,6 +258,42 @@ xlsxturbo.dfs_to_xlsx([
|
|
|
178
258
|
], "report.xlsx", column_widths={0: 20, 1: 15})
|
|
179
259
|
```
|
|
180
260
|
|
|
261
|
+
### Per-Sheet Options
|
|
262
|
+
|
|
263
|
+
Override global settings for individual sheets using a 3-tuple with options dict:
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import xlsxturbo
|
|
267
|
+
import pandas as pd
|
|
268
|
+
|
|
269
|
+
df_data = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})
|
|
270
|
+
df_instructions = pd.DataFrame({'Step': [1, 2], 'Action': ['Open file', 'Review data']})
|
|
271
|
+
|
|
272
|
+
# Different settings per sheet:
|
|
273
|
+
# - "Data" sheet: has header, table style, autofit
|
|
274
|
+
# - "Instructions" sheet: no header (raw data), no table style
|
|
275
|
+
xlsxturbo.dfs_to_xlsx([
|
|
276
|
+
(df_data, "Data", {"header": True, "table_style": "Medium2"}),
|
|
277
|
+
(df_instructions, "Instructions", {"header": False, "table_style": None})
|
|
278
|
+
], "report.xlsx", autofit=True)
|
|
279
|
+
|
|
280
|
+
# Old 2-tuple API still works - uses global defaults
|
|
281
|
+
xlsxturbo.dfs_to_xlsx([
|
|
282
|
+
(df_data, "Sheet1"), # Uses global header=True, table_style=None
|
|
283
|
+
(df_instructions, "Sheet2", {"header": False}) # Override just header
|
|
284
|
+
], "mixed.xlsx", header=True, autofit=True)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Available per-sheet options:
|
|
288
|
+
- `header` (bool): Include column names as header row
|
|
289
|
+
- `autofit` (bool): Automatically adjust column widths
|
|
290
|
+
- `table_style` (str|None): Excel table style or None to disable
|
|
291
|
+
- `freeze_panes` (bool): Freeze header row
|
|
292
|
+
- `column_widths` (dict): Custom column widths
|
|
293
|
+
- `row_heights` (dict): Custom row heights
|
|
294
|
+
- `table_name` (str): Custom Excel table name
|
|
295
|
+
- `header_format` (dict): Header cell styling
|
|
296
|
+
|
|
181
297
|
### Constant Memory Mode (Large Files)
|
|
182
298
|
|
|
183
299
|
For very large files (millions of rows), use `constant_memory=True` to minimize RAM usage:
|
|
@@ -7,10 +7,13 @@ High-performance Excel writer with automatic type detection. Written in Rust, us
|
|
|
7
7
|
- **Direct DataFrame support** for pandas and polars
|
|
8
8
|
- **Excel tables** - filterable tables with 61 built-in styles (banded rows, autofilter)
|
|
9
9
|
- **Auto-fit columns** - automatically adjust column widths to fit content
|
|
10
|
-
- **Custom column widths** - set specific widths per column
|
|
10
|
+
- **Custom column widths** - set specific widths per column or cap all with _all
|
|
11
|
+
- **Header styling** - bold, colors, font size for header row
|
|
12
|
+
- **Named tables** - set custom table names
|
|
11
13
|
- **Custom row heights** - set specific heights per row
|
|
12
14
|
- **Freeze panes** - freeze header row for easier scrolling
|
|
13
15
|
- **Multi-sheet workbooks** - write multiple DataFrames to one file
|
|
16
|
+
- **Per-sheet options** - override settings per sheet in multi-sheet workbooks
|
|
14
17
|
- **Constant memory mode** - minimize RAM usage for very large files
|
|
15
18
|
- **Parallel CSV processing** - optional multi-core parsing for large files
|
|
16
19
|
- **Automatic type detection** from CSV strings and Python objects:
|
|
@@ -117,6 +120,83 @@ xlsxturbo.df_to_xlsx(df, "styled.xlsx",
|
|
|
117
120
|
)
|
|
118
121
|
```
|
|
119
122
|
|
|
123
|
+
### Global Column Width Cap
|
|
124
|
+
|
|
125
|
+
Use `column_widths={'_all': value}` to cap all columns at a maximum width:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
import xlsxturbo
|
|
129
|
+
import pandas as pd
|
|
130
|
+
|
|
131
|
+
df = pd.DataFrame({
|
|
132
|
+
'Name': ['Alice', 'Bob'],
|
|
133
|
+
'VeryLongDescription': ['A' * 100, 'B' * 100],
|
|
134
|
+
'Score': [95, 87]
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
# Cap all columns at 30 characters
|
|
138
|
+
xlsxturbo.df_to_xlsx(df, "capped.xlsx", column_widths={'_all': 30})
|
|
139
|
+
|
|
140
|
+
# Mix specific widths with global cap (specific overrides '_all')
|
|
141
|
+
xlsxturbo.df_to_xlsx(df, "mixed.xlsx", column_widths={0: 15, '_all': 30})
|
|
142
|
+
|
|
143
|
+
# Autofit with cap: fit content, but never exceed 25 characters
|
|
144
|
+
xlsxturbo.df_to_xlsx(df, "fitted.xlsx", autofit=True, column_widths={'_all': 25})
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Named Excel Tables
|
|
148
|
+
|
|
149
|
+
Set custom names for Excel tables:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
import xlsxturbo
|
|
153
|
+
import pandas as pd
|
|
154
|
+
|
|
155
|
+
df = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})
|
|
156
|
+
|
|
157
|
+
# Name the Excel table
|
|
158
|
+
xlsxturbo.df_to_xlsx(df, "report.xlsx",
|
|
159
|
+
table_style="Medium2",
|
|
160
|
+
table_name="ProductPrices"
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Invalid characters are auto-sanitized, digits get underscore prefix
|
|
164
|
+
xlsxturbo.df_to_xlsx(df, "report.xlsx",
|
|
165
|
+
table_style="Medium2",
|
|
166
|
+
table_name="2024 Sales Data!" # Becomes "_2024_Sales_Data_"
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Header Styling
|
|
171
|
+
|
|
172
|
+
Apply custom formatting to header cells:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
import xlsxturbo
|
|
176
|
+
import pandas as pd
|
|
177
|
+
|
|
178
|
+
df = pd.DataFrame({'Name': ['Alice', 'Bob'], 'Score': [95, 87]})
|
|
179
|
+
|
|
180
|
+
# Bold headers
|
|
181
|
+
xlsxturbo.df_to_xlsx(df, "bold.xlsx", header_format={'bold': True})
|
|
182
|
+
|
|
183
|
+
# Full styling with colors
|
|
184
|
+
xlsxturbo.df_to_xlsx(df, "styled.xlsx", header_format={
|
|
185
|
+
'bold': True,
|
|
186
|
+
'bg_color': '#4F81BD', # Blue background
|
|
187
|
+
'font_color': 'white' # White text
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
# Available options:
|
|
191
|
+
# - bold (bool): Bold text
|
|
192
|
+
# - italic (bool): Italic text
|
|
193
|
+
# - font_color (str): '#RRGGBB' or named color (white, black, red, blue, etc.)
|
|
194
|
+
# - bg_color (str): Background color
|
|
195
|
+
# - font_size (float): Font size in points
|
|
196
|
+
# - underline (bool): Underlined text
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
|
|
120
200
|
### Multi-Sheet Workbooks
|
|
121
201
|
|
|
122
202
|
```python
|
|
@@ -145,6 +225,42 @@ xlsxturbo.dfs_to_xlsx([
|
|
|
145
225
|
], "report.xlsx", column_widths={0: 20, 1: 15})
|
|
146
226
|
```
|
|
147
227
|
|
|
228
|
+
### Per-Sheet Options
|
|
229
|
+
|
|
230
|
+
Override global settings for individual sheets using a 3-tuple with options dict:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
import xlsxturbo
|
|
234
|
+
import pandas as pd
|
|
235
|
+
|
|
236
|
+
df_data = pd.DataFrame({'Product': ['A', 'B'], 'Price': [10, 20]})
|
|
237
|
+
df_instructions = pd.DataFrame({'Step': [1, 2], 'Action': ['Open file', 'Review data']})
|
|
238
|
+
|
|
239
|
+
# Different settings per sheet:
|
|
240
|
+
# - "Data" sheet: has header, table style, autofit
|
|
241
|
+
# - "Instructions" sheet: no header (raw data), no table style
|
|
242
|
+
xlsxturbo.dfs_to_xlsx([
|
|
243
|
+
(df_data, "Data", {"header": True, "table_style": "Medium2"}),
|
|
244
|
+
(df_instructions, "Instructions", {"header": False, "table_style": None})
|
|
245
|
+
], "report.xlsx", autofit=True)
|
|
246
|
+
|
|
247
|
+
# Old 2-tuple API still works - uses global defaults
|
|
248
|
+
xlsxturbo.dfs_to_xlsx([
|
|
249
|
+
(df_data, "Sheet1"), # Uses global header=True, table_style=None
|
|
250
|
+
(df_instructions, "Sheet2", {"header": False}) # Override just header
|
|
251
|
+
], "mixed.xlsx", header=True, autofit=True)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Available per-sheet options:
|
|
255
|
+
- `header` (bool): Include column names as header row
|
|
256
|
+
- `autofit` (bool): Automatically adjust column widths
|
|
257
|
+
- `table_style` (str|None): Excel table style or None to disable
|
|
258
|
+
- `freeze_panes` (bool): Freeze header row
|
|
259
|
+
- `column_widths` (dict): Custom column widths
|
|
260
|
+
- `row_heights` (dict): Custom row heights
|
|
261
|
+
- `table_name` (str): Custom Excel table name
|
|
262
|
+
- `header_format` (dict): Header cell styling
|
|
263
|
+
|
|
148
264
|
### Constant Memory Mode (Large Files)
|
|
149
265
|
|
|
150
266
|
For very large files (millions of rows), use `constant_memory=True` to minimize RAM usage:
|
|
@@ -9,21 +9,21 @@ Features that would enable more migrations from pandas/polars write_excel.
|
|
|
9
9
|
- [x] **Column auto-width** - Automatically fit column widths to content (v0.3.0)
|
|
10
10
|
- [x] **Custom column widths** - Set specific widths per column (v0.4.0)
|
|
11
11
|
- [x] **Custom row heights** - Set specific heights per row (v0.4.0)
|
|
12
|
-
- [
|
|
13
|
-
|
|
14
|
-
- API idea: `sheets=[(df1, "Sheet1", {"header": True}), (df2, "Sheet2", {"header": False})]`
|
|
15
|
-
- [ ] **Header styling** - Option for bold/colored headers (`header_format` parameter)
|
|
12
|
+
- [x] **Per-sheet options in dfs_to_xlsx** - Allow different settings per sheet (v0.5.0)
|
|
13
|
+
- [x] **Header styling** - Option for bold/colored headers (`header_format` parameter) (v0.6.0)
|
|
16
14
|
- [x] **Freeze panes** - Freeze header row for easier scrolling (v0.3.0)
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
15
|
+
- [x] **Global column width cap** - `column_widths={'_all': value}` to limit all column widths (v0.6.0)
|
|
16
|
+
- [x] **Table name** - `table_name` parameter for named Excel tables (v0.6.0)
|
|
19
17
|
|
|
20
18
|
## Medium Priority
|
|
21
19
|
|
|
22
20
|
Power user features for more control over output.
|
|
23
21
|
|
|
24
22
|
- [x] **Multi-core support** - Parallel CSV parsing with rayon (~7% speedup for large files)
|
|
25
|
-
- [
|
|
26
|
-
-
|
|
23
|
+
- [x] **Column formatting with wildcards** - `column_formats` with pattern matching (v0.7.0)
|
|
24
|
+
- Supports: `prefix*`, `*suffix`, `*contains*`, exact match
|
|
25
|
+
- Format options: bg_color, font_color, num_format, bold, italic, underline, border
|
|
26
|
+
- [ ] **Row-level cell formatting** - Conditional styling based on cell values
|
|
27
27
|
- [ ] **Merged cells** - Merge cell ranges for headers/documentation sheets
|
|
28
28
|
- [ ] **Conditional formatting** - Color scales, data bars, icon sets
|
|
29
29
|
- [x] **Table styles** - Create Excel tables with auto-filters and 61 built-in styles (v0.3.0)
|
|
@@ -40,6 +40,10 @@ Niche features for specific use cases.
|
|
|
40
40
|
|
|
41
41
|
## Completed
|
|
42
42
|
|
|
43
|
+
- [x] Column formatting with wildcards via `column_formats` parameter (v0.7.0)
|
|
44
|
+
- [x] Global column width cap with `column_widths={'_all': value}` (v0.6.0)
|
|
45
|
+
- [x] Table name parameter with `table_name` (v0.6.0)
|
|
46
|
+
- [x] Header styling with `header_format` (v0.6.0)
|
|
43
47
|
- [x] CSV to XLSX conversion with type detection (v0.1.0)
|
|
44
48
|
- [x] pandas DataFrame support (v0.2.0)
|
|
45
49
|
- [x] polars DataFrame support (v0.2.0)
|
|
@@ -50,3 +54,4 @@ Niche features for specific use cases.
|
|
|
50
54
|
- [x] Custom column widths with `column_widths` parameter (v0.4.0)
|
|
51
55
|
- [x] Custom row heights with `row_heights` parameter (v0.4.0)
|
|
52
56
|
- [x] Constant memory mode with `constant_memory` parameter (v0.4.0)
|
|
57
|
+
- [x] Per-sheet options in `dfs_to_xlsx()` (v0.5.0)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Type stubs for xlsxturbo"""
|
|
2
|
+
|
|
3
|
+
from typing import TypedDict
|
|
4
|
+
|
|
5
|
+
class HeaderFormat(TypedDict, total=False):
|
|
6
|
+
"""Header cell formatting options. All fields are optional."""
|
|
7
|
+
bold: bool
|
|
8
|
+
italic: bool
|
|
9
|
+
font_color: str # '#RRGGBB' or named color (white, black, red, blue, etc.)
|
|
10
|
+
bg_color: str # '#RRGGBB' or named color
|
|
11
|
+
font_size: float
|
|
12
|
+
underline: bool
|
|
13
|
+
|
|
14
|
+
class SheetOptions(TypedDict, total=False):
|
|
15
|
+
"""Per-sheet options for dfs_to_xlsx. All fields are optional."""
|
|
16
|
+
header: bool
|
|
17
|
+
autofit: bool
|
|
18
|
+
table_style: str | None
|
|
19
|
+
freeze_panes: bool
|
|
20
|
+
column_widths: dict[int | str, float] | None # Keys: int index or '_all'
|
|
21
|
+
row_heights: dict[int, float] | None
|
|
22
|
+
table_name: str | None
|
|
23
|
+
header_format: HeaderFormat | None
|
|
24
|
+
|
|
25
|
+
def csv_to_xlsx(
|
|
26
|
+
input_path: str,
|
|
27
|
+
output_path: str,
|
|
28
|
+
sheet_name: str = "Sheet1",
|
|
29
|
+
parallel: bool = False,
|
|
30
|
+
) -> tuple[int, int]:
|
|
31
|
+
"""
|
|
32
|
+
Convert a CSV file to XLSX format with automatic type detection.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
input_path: Path to the input CSV file
|
|
36
|
+
output_path: Path for the output XLSX file
|
|
37
|
+
sheet_name: Name of the worksheet (default: "Sheet1")
|
|
38
|
+
parallel: Use multi-core parallel processing (default: False).
|
|
39
|
+
Faster for large files (100K+ rows) but uses more memory.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Tuple of (rows, columns) written to the Excel file
|
|
43
|
+
|
|
44
|
+
Raises:
|
|
45
|
+
ValueError: If the conversion fails
|
|
46
|
+
"""
|
|
47
|
+
...
|
|
48
|
+
|
|
49
|
+
def df_to_xlsx(
|
|
50
|
+
df: object,
|
|
51
|
+
output_path: str,
|
|
52
|
+
sheet_name: str = "Sheet1",
|
|
53
|
+
header: bool = True,
|
|
54
|
+
autofit: bool = False,
|
|
55
|
+
table_style: str | None = None,
|
|
56
|
+
freeze_panes: bool = False,
|
|
57
|
+
column_widths: dict[int | str, float] | None = None,
|
|
58
|
+
row_heights: dict[int, float] | None = None,
|
|
59
|
+
constant_memory: bool = False,
|
|
60
|
+
table_name: str | None = None,
|
|
61
|
+
header_format: HeaderFormat | None = None,
|
|
62
|
+
) -> tuple[int, int]:
|
|
63
|
+
"""
|
|
64
|
+
Convert a pandas or polars DataFrame to XLSX format.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
df: pandas DataFrame or polars DataFrame to export
|
|
68
|
+
output_path: Path for the output XLSX file
|
|
69
|
+
sheet_name: Name of the worksheet (default: "Sheet1")
|
|
70
|
+
header: Include column names as header row (default: True)
|
|
71
|
+
autofit: Automatically adjust column widths to fit content (default: False)
|
|
72
|
+
table_style: Apply Excel table formatting (default: None).
|
|
73
|
+
Styles: "Light1"-"Light21", "Medium1"-"Medium28", "Dark1"-"Dark11", "None".
|
|
74
|
+
freeze_panes: Freeze the header row for easier scrolling (default: False)
|
|
75
|
+
column_widths: Dict mapping column index to width. Use '_all' to cap all columns.
|
|
76
|
+
row_heights: Dict mapping row index to height in points.
|
|
77
|
+
constant_memory: Use streaming mode for minimal RAM usage (default: False).
|
|
78
|
+
table_name: Custom name for the Excel table (requires table_style).
|
|
79
|
+
header_format: Dict of header cell formatting options.
|
|
80
|
+
"""
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
def dfs_to_xlsx(
|
|
84
|
+
sheets: list[tuple[object, str] | tuple[object, str, SheetOptions]],
|
|
85
|
+
output_path: str,
|
|
86
|
+
header: bool = True,
|
|
87
|
+
autofit: bool = False,
|
|
88
|
+
table_style: str | None = None,
|
|
89
|
+
freeze_panes: bool = False,
|
|
90
|
+
column_widths: dict[int | str, float] | None = None,
|
|
91
|
+
row_heights: dict[int, float] | None = None,
|
|
92
|
+
constant_memory: bool = False,
|
|
93
|
+
table_name: str | None = None,
|
|
94
|
+
header_format: HeaderFormat | None = None,
|
|
95
|
+
) -> list[tuple[int, int]]:
|
|
96
|
+
"""
|
|
97
|
+
Write multiple DataFrames to separate sheets in a single workbook.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
sheets: List of (DataFrame, sheet_name) or (DataFrame, sheet_name, options) tuples.
|
|
101
|
+
output_path: Path for the output XLSX file
|
|
102
|
+
header: Include column names as header row (default: True)
|
|
103
|
+
autofit: Automatically adjust column widths (default: False)
|
|
104
|
+
table_style: Apply Excel table formatting (default: None).
|
|
105
|
+
freeze_panes: Freeze the header row (default: False)
|
|
106
|
+
column_widths: Dict mapping column index to width. Use '_all' to cap all columns.
|
|
107
|
+
row_heights: Dict mapping row index to height in points.
|
|
108
|
+
constant_memory: Use streaming mode (default: False).
|
|
109
|
+
table_name: Custom name for Excel tables (requires table_style).
|
|
110
|
+
header_format: Dict of header cell formatting options.
|
|
111
|
+
"""
|
|
112
|
+
...
|
|
113
|
+
|
|
114
|
+
def version() -> str:
|
|
115
|
+
"""Get the version of the xlsxturbo library."""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
__version__: str
|