pyfastexcel 0.0.6__tar.gz → 0.0.7__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.
- pyfastexcel-0.0.7/PKG-INFO +183 -0
- pyfastexcel-0.0.7/README.md +159 -0
- pyfastexcel-0.0.7/pyfastexcel/__init__.py +13 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel/driver.py +98 -12
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel/pyfastexcel.dll +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel/pyfastexcel.so +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel/utils.py +16 -2
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel/writer.py +11 -11
- pyfastexcel-0.0.7/pyfastexcel.egg-info/PKG-INFO +183 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel.egg-info/SOURCES.txt +0 -1
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/setup.cfg +1 -1
- pyfastexcel-0.0.6/PKG-INFO +0 -346
- pyfastexcel-0.0.6/README.md +0 -322
- pyfastexcel-0.0.6/pyfastexcel/__init__.py +0 -7
- pyfastexcel-0.0.6/pyfastexcel/exceptions.py +0 -13
- pyfastexcel-0.0.6/pyfastexcel.egg-info/PKG-INFO +0 -346
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/LICENSE +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel.egg-info/dependency_links.txt +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel.egg-info/not-zip-safe +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel.egg-info/requires.txt +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/pyfastexcel.egg-info/top_level.txt +0 -0
- {pyfastexcel-0.0.6 → pyfastexcel-0.0.7}/setup.py +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pyfastexcel
|
|
3
|
+
Version: 0.0.7
|
|
4
|
+
Summary: High performace excel file generation library.
|
|
5
|
+
Home-page: https://github.com/Zncl2222/pyfastexcel
|
|
6
|
+
Author: Zncl2222
|
|
7
|
+
Author-email: 3002shinning@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Go
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Requires-Python: >=3.7
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: msgspec
|
|
23
|
+
Requires-Dist: openpyxl-style-writer>=1.1.3
|
|
24
|
+
|
|
25
|
+
# pyfastexcel
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
[](https://goreportcard.com/report/github.com/Zncl2222/pyfastexcel)
|
|
29
|
+

|
|
30
|
+

|
|
31
|
+
[](https://app.codacy.com/gh/Zncl2222/pyfastexcel/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
32
|
+
[](https://codecov.io/gh/Zncl2222/pyfastexcel)
|
|
33
|
+
[](https://pyfastexcel.readthedocs.io/en/stable/?badge=stable)
|
|
34
|
+
|
|
35
|
+
This package enables high-performance Excel writing by integrating with the
|
|
36
|
+
streaming API from the golang package
|
|
37
|
+
[excelize](https://github.com/qax-os/excelize). Users can leverage this
|
|
38
|
+
functionality without the need to write any Go code, as the entire process
|
|
39
|
+
can be accomplished through Python.
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- Python and Golang Integration: Seamlessly call Golang built shared
|
|
44
|
+
libraries from Python.
|
|
45
|
+
|
|
46
|
+
- No Golang Code Required: Users can solely rely on Python for Excel file
|
|
47
|
+
generation, eliminating the need for Golang expertise.
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
### Install via pip (Recommended)
|
|
52
|
+
|
|
53
|
+
You can easily install the package via pip
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install pyfastexcel
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Install manually
|
|
60
|
+
|
|
61
|
+
If you prefer to build the package manually, follow these steps:
|
|
62
|
+
|
|
63
|
+
1. Clone the repository:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone https://github.com/Zncl2222/pyfastexcel.git
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
2. Go to the project root directory:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd pyfastexcel
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
3. Install the required golang packages:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
go mod download
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
4. Build the Golang shared library using the Makefile:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
make
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
5. Install the required python packages:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pip install -r requirements.txt
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
or
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pipenv install
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
6. Import the project and start using it!
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
The index assignment is now avaliable in `Workbook` and the `FastWriter`.
|
|
104
|
+
Here is the example usage:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pyfastexcel import Workbook
|
|
108
|
+
from pyfastexcel.utils import set_custom_style
|
|
109
|
+
|
|
110
|
+
# CustomStyle will be integrate to the pyfatexcel in next version
|
|
111
|
+
# Beside, CustomStyle will be re-implement in future to make it no-longer
|
|
112
|
+
# depend on openpyxl_style writer and openpyxl
|
|
113
|
+
from openpyxl_style_writer import CustomStyle
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
if __name__ == '__main__':
|
|
117
|
+
# Workbook
|
|
118
|
+
wb = Workbook()
|
|
119
|
+
|
|
120
|
+
# Set and register CustomStyle
|
|
121
|
+
bold_style = CustomStyle(font_size=15, font_bold=True)
|
|
122
|
+
set_custom_style('bold_style', bold_style)
|
|
123
|
+
|
|
124
|
+
ws = wb['Sheet1']
|
|
125
|
+
# Write value with default style
|
|
126
|
+
ws['A1'] = 'A1 value'
|
|
127
|
+
# Write value with custom style
|
|
128
|
+
ws['B1'] = ('B1 value', 'bold_style')
|
|
129
|
+
|
|
130
|
+
# Write value in slice with default style
|
|
131
|
+
ws['A2': 'C2'] = [1, 2, 3]
|
|
132
|
+
# Write value in slice with custom style
|
|
133
|
+
ws['A3': 'C3'] = [(1, 'bold_style'), (2, 'bold_style'), (3, 'bold_style')]
|
|
134
|
+
|
|
135
|
+
# Write value by row with default style (python index 0 is the index 1 in excel)
|
|
136
|
+
ws[3] = [9, 8, 'go']
|
|
137
|
+
# Write value by row with custom style
|
|
138
|
+
ws[4] = [(9, 'bold_style'), (8, 'bold_style'), ('go', 'bold_style')]
|
|
139
|
+
|
|
140
|
+
# Send request to golang lib and create excel
|
|
141
|
+
wb.read_lib_and_create_excel()
|
|
142
|
+
|
|
143
|
+
# File path to save
|
|
144
|
+
file_path = 'pyexample_workbook.xlsx'
|
|
145
|
+
wb.save(file_path)
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
You can also using the `FastWriter` or `NormalWriter` which was the
|
|
150
|
+
subclass of `Workbook` to write excel row by row, see the more in documentations [quickstart](https://pyfastexcel.readthedocs.io/en/stable/quickstart/).
|
|
151
|
+
|
|
152
|
+
## Documentation
|
|
153
|
+
|
|
154
|
+
The documentation is hosted on Read the Docs.
|
|
155
|
+
|
|
156
|
+
- [Development Version](https://pyfastexcel.readthedocs.io/en/latest/)
|
|
157
|
+
|
|
158
|
+
- [Latest Stable Version](https://pyfastexcel.readthedocs.io/en/stable/)
|
|
159
|
+
|
|
160
|
+
## How it Works
|
|
161
|
+
|
|
162
|
+
The core functionality revolves around encoding Excel cell data and styles,
|
|
163
|
+
or any other Excel properties, into a JSON string within Python. This JSON
|
|
164
|
+
payload is then passed through ctypes to a Golang shared library. In Golang,
|
|
165
|
+
the JSON is parsed, and using the streaming writer of
|
|
166
|
+
[excelize](https://github.com/qax-os/excelize) to wrtie excel in
|
|
167
|
+
high performance.
|
|
168
|
+
|
|
169
|
+
## Current Limitations & Future Plans
|
|
170
|
+
|
|
171
|
+
### Problem 1: Dependence on Other Excel Package
|
|
172
|
+
|
|
173
|
+
Limitations:
|
|
174
|
+
|
|
175
|
+
This project currently depends on the `CustomStyle` object of
|
|
176
|
+
the [openpyxl_style_writer](https://github.com/Zncl2222/openpyxl_style_writer)
|
|
177
|
+
package, which is built for openpyxl to write styles in write-only
|
|
178
|
+
mode more efficiently without duplicating code.
|
|
179
|
+
|
|
180
|
+
Future Plans:
|
|
181
|
+
|
|
182
|
+
This project plans to create its own `Style` object, making it no longer
|
|
183
|
+
dependent on the mentioned package.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# pyfastexcel
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://goreportcard.com/report/github.com/Zncl2222/pyfastexcel)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://app.codacy.com/gh/Zncl2222/pyfastexcel/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
8
|
+
[](https://codecov.io/gh/Zncl2222/pyfastexcel)
|
|
9
|
+
[](https://pyfastexcel.readthedocs.io/en/stable/?badge=stable)
|
|
10
|
+
|
|
11
|
+
This package enables high-performance Excel writing by integrating with the
|
|
12
|
+
streaming API from the golang package
|
|
13
|
+
[excelize](https://github.com/qax-os/excelize). Users can leverage this
|
|
14
|
+
functionality without the need to write any Go code, as the entire process
|
|
15
|
+
can be accomplished through Python.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- Python and Golang Integration: Seamlessly call Golang built shared
|
|
20
|
+
libraries from Python.
|
|
21
|
+
|
|
22
|
+
- No Golang Code Required: Users can solely rely on Python for Excel file
|
|
23
|
+
generation, eliminating the need for Golang expertise.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
### Install via pip (Recommended)
|
|
28
|
+
|
|
29
|
+
You can easily install the package via pip
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install pyfastexcel
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Install manually
|
|
36
|
+
|
|
37
|
+
If you prefer to build the package manually, follow these steps:
|
|
38
|
+
|
|
39
|
+
1. Clone the repository:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/Zncl2222/pyfastexcel.git
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
2. Go to the project root directory:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd pyfastexcel
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
3. Install the required golang packages:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
go mod download
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
4. Build the Golang shared library using the Makefile:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
make
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
5. Install the required python packages:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install -r requirements.txt
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
or
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pipenv install
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
6. Import the project and start using it!
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
The index assignment is now avaliable in `Workbook` and the `FastWriter`.
|
|
80
|
+
Here is the example usage:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from pyfastexcel import Workbook
|
|
84
|
+
from pyfastexcel.utils import set_custom_style
|
|
85
|
+
|
|
86
|
+
# CustomStyle will be integrate to the pyfatexcel in next version
|
|
87
|
+
# Beside, CustomStyle will be re-implement in future to make it no-longer
|
|
88
|
+
# depend on openpyxl_style writer and openpyxl
|
|
89
|
+
from openpyxl_style_writer import CustomStyle
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
if __name__ == '__main__':
|
|
93
|
+
# Workbook
|
|
94
|
+
wb = Workbook()
|
|
95
|
+
|
|
96
|
+
# Set and register CustomStyle
|
|
97
|
+
bold_style = CustomStyle(font_size=15, font_bold=True)
|
|
98
|
+
set_custom_style('bold_style', bold_style)
|
|
99
|
+
|
|
100
|
+
ws = wb['Sheet1']
|
|
101
|
+
# Write value with default style
|
|
102
|
+
ws['A1'] = 'A1 value'
|
|
103
|
+
# Write value with custom style
|
|
104
|
+
ws['B1'] = ('B1 value', 'bold_style')
|
|
105
|
+
|
|
106
|
+
# Write value in slice with default style
|
|
107
|
+
ws['A2': 'C2'] = [1, 2, 3]
|
|
108
|
+
# Write value in slice with custom style
|
|
109
|
+
ws['A3': 'C3'] = [(1, 'bold_style'), (2, 'bold_style'), (3, 'bold_style')]
|
|
110
|
+
|
|
111
|
+
# Write value by row with default style (python index 0 is the index 1 in excel)
|
|
112
|
+
ws[3] = [9, 8, 'go']
|
|
113
|
+
# Write value by row with custom style
|
|
114
|
+
ws[4] = [(9, 'bold_style'), (8, 'bold_style'), ('go', 'bold_style')]
|
|
115
|
+
|
|
116
|
+
# Send request to golang lib and create excel
|
|
117
|
+
wb.read_lib_and_create_excel()
|
|
118
|
+
|
|
119
|
+
# File path to save
|
|
120
|
+
file_path = 'pyexample_workbook.xlsx'
|
|
121
|
+
wb.save(file_path)
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
You can also using the `FastWriter` or `NormalWriter` which was the
|
|
126
|
+
subclass of `Workbook` to write excel row by row, see the more in documentations [quickstart](https://pyfastexcel.readthedocs.io/en/stable/quickstart/).
|
|
127
|
+
|
|
128
|
+
## Documentation
|
|
129
|
+
|
|
130
|
+
The documentation is hosted on Read the Docs.
|
|
131
|
+
|
|
132
|
+
- [Development Version](https://pyfastexcel.readthedocs.io/en/latest/)
|
|
133
|
+
|
|
134
|
+
- [Latest Stable Version](https://pyfastexcel.readthedocs.io/en/stable/)
|
|
135
|
+
|
|
136
|
+
## How it Works
|
|
137
|
+
|
|
138
|
+
The core functionality revolves around encoding Excel cell data and styles,
|
|
139
|
+
or any other Excel properties, into a JSON string within Python. This JSON
|
|
140
|
+
payload is then passed through ctypes to a Golang shared library. In Golang,
|
|
141
|
+
the JSON is parsed, and using the streaming writer of
|
|
142
|
+
[excelize](https://github.com/qax-os/excelize) to wrtie excel in
|
|
143
|
+
high performance.
|
|
144
|
+
|
|
145
|
+
## Current Limitations & Future Plans
|
|
146
|
+
|
|
147
|
+
### Problem 1: Dependence on Other Excel Package
|
|
148
|
+
|
|
149
|
+
Limitations:
|
|
150
|
+
|
|
151
|
+
This project currently depends on the `CustomStyle` object of
|
|
152
|
+
the [openpyxl_style_writer](https://github.com/Zncl2222/openpyxl_style_writer)
|
|
153
|
+
package, which is built for openpyxl to write styles in write-only
|
|
154
|
+
mode more efficiently without duplicating code.
|
|
155
|
+
|
|
156
|
+
Future Plans:
|
|
157
|
+
|
|
158
|
+
This project plans to create its own `Style` object, making it no longer
|
|
159
|
+
dependent on the mentioned package.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from openpyxl_style_writer import CustomStyle, DefaultStyle
|
|
2
|
+
|
|
3
|
+
from pyfastexcel.writer import FastWriter, NormalWriter, Workbook
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
'Workbook',
|
|
7
|
+
'FastWriter',
|
|
8
|
+
'NormalWriter',
|
|
9
|
+
# Temporary link the CustomStyle from openpyxl_style_writer for
|
|
10
|
+
# convinent usage.
|
|
11
|
+
'CustomStyle',
|
|
12
|
+
'DefaultStyle',
|
|
13
|
+
]
|
|
@@ -11,12 +11,13 @@ from typing import Any
|
|
|
11
11
|
import msgspec
|
|
12
12
|
from openpyxl_style_writer import CustomStyle
|
|
13
13
|
|
|
14
|
-
from .exceptions import CreateFileNotCalledError
|
|
15
14
|
from .utils import (
|
|
16
15
|
column_to_index,
|
|
17
16
|
excel_index_to_list_index,
|
|
18
17
|
extract_numeric_part,
|
|
19
18
|
separate_alpha_numeric,
|
|
19
|
+
validate_and_format_value,
|
|
20
|
+
validate_and_register_style,
|
|
20
21
|
)
|
|
21
22
|
|
|
22
23
|
BASE_DIR = Path(__file__).resolve().parent
|
|
@@ -109,6 +110,7 @@ class ExcelDriver:
|
|
|
109
110
|
self.file_props = self._get_default_file_props()
|
|
110
111
|
self.sheet = 'Sheet1'
|
|
111
112
|
self._sheet_list = tuple(['Sheet1'])
|
|
113
|
+
self._dict_wb = {}
|
|
112
114
|
|
|
113
115
|
@property
|
|
114
116
|
def sheet_list(self):
|
|
@@ -119,11 +121,16 @@ class ExcelDriver:
|
|
|
119
121
|
cls.REGISTERED_STYLES[name] = custom_style
|
|
120
122
|
cls._STYLE_NAME_MAP[custom_style] = name
|
|
121
123
|
|
|
124
|
+
@classmethod
|
|
125
|
+
def reset_style_configs(cls):
|
|
126
|
+
cls.REGISTERED_STYLES = {'DEFAULT_STYLE': cls.DEFAULT_STYLE}
|
|
127
|
+
cls._STYLE_NAME_MAP = {}
|
|
128
|
+
cls._STYLE_ID = 0
|
|
129
|
+
cls._style_map = {}
|
|
130
|
+
|
|
122
131
|
def save(self, path: str = './pyfastexcel.xlsx') -> None:
|
|
123
132
|
if not hasattr(self, 'decoded_bytes'):
|
|
124
|
-
|
|
125
|
-
'Function read_lib_and_create_excel should be ' + 'called before saving the file.',
|
|
126
|
-
)
|
|
133
|
+
self.read_lib_and_create_excel()
|
|
127
134
|
|
|
128
135
|
with open(path, 'wb') as file:
|
|
129
136
|
file.write(self.decoded_bytes)
|
|
@@ -150,10 +157,10 @@ class ExcelDriver:
|
|
|
150
157
|
|
|
151
158
|
# Transfer all WorkSheet Object to the sheet dictionary in the workbook.
|
|
152
159
|
for sheet in self._sheet_list:
|
|
153
|
-
self.
|
|
160
|
+
self._dict_wb[sheet] = self.workbook[sheet]._transfer_to_dict()
|
|
154
161
|
|
|
155
162
|
results = {
|
|
156
|
-
'content': self.
|
|
163
|
+
'content': self._dict_wb,
|
|
157
164
|
'file_props': self.file_props,
|
|
158
165
|
'style': self._style_map,
|
|
159
166
|
}
|
|
@@ -166,6 +173,7 @@ class ExcelDriver:
|
|
|
166
173
|
byte_data = create_excel(json_data)
|
|
167
174
|
self.decoded_bytes = base64.b64decode(ctypes.cast(byte_data, ctypes.c_char_p).value)
|
|
168
175
|
free_pointer(byte_data)
|
|
176
|
+
ExcelDriver.reset_style_configs()
|
|
169
177
|
return self.decoded_bytes
|
|
170
178
|
|
|
171
179
|
def _read_lib(self, lib_path: str) -> ctypes.CDLL:
|
|
@@ -371,6 +379,9 @@ class WorkSheet:
|
|
|
371
379
|
Validates the input value and ensures it is a tuple with the correct
|
|
372
380
|
format.
|
|
373
381
|
|
|
382
|
+
set_style(target: str | slice | list[int, int], style: CustomStyle | str) -> None:
|
|
383
|
+
Applies a style to specified cells.
|
|
384
|
+
|
|
374
385
|
__getitem__(key: str | slice | int) -> tuple | list[tuple]:
|
|
375
386
|
If index_supported is True, retrieves the cell value at the
|
|
376
387
|
specified index. Raises TypeError if index_supported is False.
|
|
@@ -427,6 +438,71 @@ class WorkSheet:
|
|
|
427
438
|
self._expand_row_and_cols(row, column)
|
|
428
439
|
self.data[row][column] = value
|
|
429
440
|
|
|
441
|
+
def set_style(
|
|
442
|
+
self,
|
|
443
|
+
target: str | slice | list[int, int],
|
|
444
|
+
style: CustomStyle | str,
|
|
445
|
+
) -> None:
|
|
446
|
+
"""
|
|
447
|
+
Applies a specified style to a target range of cells.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
target (str | slice | list[int, int]): Target cells to apply style.
|
|
451
|
+
style (CustomStyle | str): Style to apply to the cells.
|
|
452
|
+
|
|
453
|
+
Raises:
|
|
454
|
+
TypeError: If target type is invalid.
|
|
455
|
+
ValueError: If style is not registered.
|
|
456
|
+
"""
|
|
457
|
+
if self.index_supported is False:
|
|
458
|
+
raise IndexError('Index is not supported in this Writer.')
|
|
459
|
+
|
|
460
|
+
if isinstance(style, str):
|
|
461
|
+
if ExcelDriver.REGISTERED_STYLES.get(style) is None:
|
|
462
|
+
raise ValueError(
|
|
463
|
+
f'Style not found: {style}. Style should be register by '
|
|
464
|
+
'set_custom_style function when you set a style with '
|
|
465
|
+
'string.',
|
|
466
|
+
)
|
|
467
|
+
elif isinstance(style, CustomStyle):
|
|
468
|
+
if ExcelDriver._STYLE_NAME_MAP.get(style) is None:
|
|
469
|
+
validate_and_register_style(style)
|
|
470
|
+
style = ExcelDriver._STYLE_NAME_MAP[style]
|
|
471
|
+
|
|
472
|
+
if isinstance(target, str):
|
|
473
|
+
self._apply_style_to_string_target(target, style)
|
|
474
|
+
elif isinstance(target, slice):
|
|
475
|
+
self._apply_style_to_slice_target(target, style)
|
|
476
|
+
elif isinstance(target, list) and len(target) == 2:
|
|
477
|
+
self._apply_style_to_list_target(target, style)
|
|
478
|
+
else:
|
|
479
|
+
raise TypeError('Target should be a string, slice, or list[row, index].')
|
|
480
|
+
|
|
481
|
+
def _apply_style_to_string_target(self, target: str, style: str):
|
|
482
|
+
if ':' not in target:
|
|
483
|
+
row, col = excel_index_to_list_index(target)
|
|
484
|
+
self.data[row][col] = (self.data[row][col][0], style)
|
|
485
|
+
else:
|
|
486
|
+
target_slice = target.split(':')
|
|
487
|
+
target = slice(target_slice[0], target_slice[1])
|
|
488
|
+
self._apply_style_to_slice_target(target, style)
|
|
489
|
+
|
|
490
|
+
def _apply_style_to_slice_target(self, target: slice, style: str):
|
|
491
|
+
start_row, start_col, col_stop = self._extract_slice_indices(target)
|
|
492
|
+
for col in range(start_col, col_stop + 1):
|
|
493
|
+
self.data[start_row][col] = (self.data[start_row][col][0], style)
|
|
494
|
+
|
|
495
|
+
def _apply_style_to_list_target(self, target: list[int, int], style: str):
|
|
496
|
+
row = target[0]
|
|
497
|
+
col = target[1]
|
|
498
|
+
if not isinstance(row, int) or not isinstance(col, int):
|
|
499
|
+
raise TypeError('Target should be a list of integers.')
|
|
500
|
+
if row < 0 or row > 1048576:
|
|
501
|
+
raise ValueError(f'Invalid row index: {row}')
|
|
502
|
+
if col < 0 or col > 16384:
|
|
503
|
+
raise ValueError(f'Invalid column index: {col}')
|
|
504
|
+
self.data[row][col] = (self.data[row][col][0], style)
|
|
505
|
+
|
|
430
506
|
def set_cell_width(self, col: str | int, value: int) -> None:
|
|
431
507
|
if isinstance(col, str):
|
|
432
508
|
col = column_to_index(col)
|
|
@@ -550,19 +626,25 @@ class WorkSheet:
|
|
|
550
626
|
or a CustomStyle object.
|
|
551
627
|
"""
|
|
552
628
|
if not isinstance(value, tuple):
|
|
553
|
-
|
|
554
|
-
if not isinstance(value, (int, float, str)):
|
|
555
|
-
value = f'{value}'
|
|
556
|
-
value = (value, 'DEFAULT_STYLE')
|
|
629
|
+
value = validate_and_format_value(value)
|
|
557
630
|
else:
|
|
558
631
|
if len(value) != 2:
|
|
559
632
|
raise ValueError(
|
|
560
|
-
'Cell value should be a tuple with two element
|
|
633
|
+
'Cell value should be a tuple with two element like (value, style).',
|
|
561
634
|
)
|
|
562
635
|
if not isinstance(value[1], (str, CustomStyle)):
|
|
563
636
|
raise TypeError(
|
|
564
637
|
'Style should be a string or CustomStyle object.',
|
|
565
638
|
)
|
|
639
|
+
# The case that user do not register the Custom Style by 'Class attributes'
|
|
640
|
+
# or set_cumston_style function.
|
|
641
|
+
if (
|
|
642
|
+
isinstance(value[1], CustomStyle)
|
|
643
|
+
and ExcelDriver._STYLE_NAME_MAP.get(value[1]) is None
|
|
644
|
+
):
|
|
645
|
+
validate_and_register_style(value[1])
|
|
646
|
+
style = ExcelDriver._STYLE_NAME_MAP[value[1]]
|
|
647
|
+
value = (value[0], style)
|
|
566
648
|
return value
|
|
567
649
|
|
|
568
650
|
def __getitem__(self, key: str | slice) -> tuple | list[tuple]:
|
|
@@ -600,7 +682,7 @@ class WorkSheet:
|
|
|
600
682
|
row, col = excel_index_to_list_index(key)
|
|
601
683
|
return self.data[row][col]
|
|
602
684
|
|
|
603
|
-
def
|
|
685
|
+
def _extract_slice_indices(self, cell_slice: slice) -> tuple[int, int, int]:
|
|
604
686
|
start_row = extract_numeric_part(cell_slice.start)
|
|
605
687
|
stop_row = extract_numeric_part(cell_slice.stop)
|
|
606
688
|
if start_row != stop_row:
|
|
@@ -608,6 +690,10 @@ class WorkSheet:
|
|
|
608
690
|
start_row, start_col = excel_index_to_list_index(cell_slice.start)
|
|
609
691
|
_, col_stop = excel_index_to_list_index(cell_slice.stop)
|
|
610
692
|
self._expand_row_and_cols(start_row, col_stop)
|
|
693
|
+
return start_row, start_col, col_stop
|
|
694
|
+
|
|
695
|
+
def _set_cell_by_slice(self, cell_slice: slice, value: Any) -> None:
|
|
696
|
+
start_row, start_col, col_stop = self._extract_slice_indices(cell_slice)
|
|
611
697
|
for idx, col in enumerate(range(start_col, col_stop + 1)):
|
|
612
698
|
val = self._validate_value_and_set_default(value[idx])
|
|
613
699
|
self.data[start_row][col] = val
|
|
Binary file
|
|
Binary file
|
|
@@ -2,17 +2,18 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
import string
|
|
5
|
+
from typing import Any, Literal
|
|
5
6
|
|
|
6
7
|
from openpyxl_style_writer import CustomStyle
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
def set_custom_style(style_name: str, style: CustomStyle):
|
|
10
|
+
def set_custom_style(style_name: str, style: CustomStyle) -> None:
|
|
10
11
|
from .driver import ExcelDriver
|
|
11
12
|
|
|
12
13
|
ExcelDriver.set_custom_style(style_name, style)
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def
|
|
16
|
+
def validate_and_register_style(style: CustomStyle) -> None:
|
|
16
17
|
from .driver import ExcelDriver
|
|
17
18
|
|
|
18
19
|
if not isinstance(style, CustomStyle):
|
|
@@ -23,6 +24,19 @@ def style_validation(style: CustomStyle):
|
|
|
23
24
|
ExcelDriver._STYLE_ID += 1
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
def validate_and_format_value(
|
|
28
|
+
value: Any,
|
|
29
|
+
set_default_style: bool = True,
|
|
30
|
+
) -> tuple[Any, Literal['DEFAULT_STYLE']] | Any:
|
|
31
|
+
# Convert non-numeric value to string
|
|
32
|
+
value = f'{value}' if not isinstance(value, (int, float, str)) else value
|
|
33
|
+
# msgpec does not support np.float64, so we should convert
|
|
34
|
+
# it to python float.
|
|
35
|
+
value = float(value) if isinstance(value, float) else value
|
|
36
|
+
|
|
37
|
+
return (value, 'DEFAULT_STYLE') if set_default_style else value
|
|
38
|
+
|
|
39
|
+
|
|
26
40
|
def separate_alpha_numeric(input_string: str):
|
|
27
41
|
alpha_part = re.findall(r'[a-zA-Z]+', input_string)
|
|
28
42
|
num_part = re.findall(r'[0-9]+', input_string)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
3
5
|
from openpyxl_style_writer import CustomStyle
|
|
4
6
|
|
|
5
7
|
from pyfastexcel.driver import ExcelDriver, WorkSheet
|
|
6
8
|
|
|
7
|
-
from .utils import
|
|
9
|
+
from .utils import validate_and_format_value, validate_and_register_style
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class Workbook(ExcelDriver):
|
|
@@ -149,18 +151,19 @@ class FastWriter(Workbook):
|
|
|
149
151
|
self.current_row = 0
|
|
150
152
|
self.current_col = 0
|
|
151
153
|
|
|
152
|
-
def row_append(self, value:
|
|
154
|
+
def row_append(self, value: Any, style: str | CustomStyle = 'DEFAULT_STYLE'):
|
|
153
155
|
"""
|
|
154
156
|
Appends a value to a specific row and column.
|
|
155
157
|
|
|
156
158
|
Args:
|
|
157
|
-
value (
|
|
159
|
+
value (Any): The value to be appended.
|
|
158
160
|
style (str): The style of the value.
|
|
159
161
|
"""
|
|
160
162
|
if isinstance(style, CustomStyle):
|
|
161
163
|
if self._STYLE_NAME_MAP.get(style) is None:
|
|
162
|
-
|
|
164
|
+
validate_and_register_style(style)
|
|
163
165
|
style = self._STYLE_NAME_MAP[style]
|
|
166
|
+
value = validate_and_format_value(value, set_default_style=False)
|
|
164
167
|
self._row_list[self.current_row][self.current_col] = (value, style)
|
|
165
168
|
self.current_col += 1
|
|
166
169
|
|
|
@@ -236,28 +239,25 @@ class NormalWriter(Workbook):
|
|
|
236
239
|
self._row_list = []
|
|
237
240
|
self.data = data
|
|
238
241
|
|
|
239
|
-
def row_append(self, value:
|
|
242
|
+
def row_append(self, value: Any, style: str | CustomStyle = 'DEFAULT_STYLE'):
|
|
240
243
|
"""
|
|
241
244
|
Appends a value to the row list.
|
|
242
245
|
|
|
243
246
|
Args:
|
|
244
|
-
value (
|
|
247
|
+
value (Any): The value to be appended.
|
|
245
248
|
style (str | CustomStyle): The style of the value, can be either
|
|
246
249
|
a style name or a CustomStyle object.
|
|
247
250
|
"""
|
|
248
251
|
if isinstance(style, CustomStyle):
|
|
249
252
|
if self._STYLE_NAME_MAP.get(style) is None:
|
|
250
|
-
|
|
253
|
+
validate_and_register_style(style)
|
|
251
254
|
style = self._STYLE_NAME_MAP[style]
|
|
255
|
+
value = validate_and_format_value(value, set_default_style=False)
|
|
252
256
|
self._row_list.append((value, style))
|
|
253
257
|
|
|
254
258
|
def create_row(self):
|
|
255
259
|
"""
|
|
256
260
|
Creates a row in the Excel data, and clean the current _row_list.
|
|
257
|
-
|
|
258
|
-
Args:
|
|
259
|
-
is_header (bool, optional): Indicates whether the row is a header
|
|
260
|
-
row. Defaults to False.
|
|
261
261
|
"""
|
|
262
262
|
self.workbook[self.sheet].data.append(self._row_list)
|
|
263
263
|
self._row_list = []
|