This package enables high-performance Excel writing by integrating with the streaming API from the golang package excelize. Users can leverage this functionality without the need to write any Go code, as the entire process can be accomplished through Python.
You can easily install the package via pip
pip install pyfastexcel
If you prefer to build the package manually, follow these steps:
-
Clone the repository:
git clone https://github.com/Zncl2222/pyfastexcel.git
-
Go to the project root directory:
cd pyfastexcel
-
Install the required golang packages:
go mod download
-
Build the Golang shared library using the Makefile:
make
-
Install the required python packages:
pip install -r requirements.txt
or
pipenv install
-
Import the project and start using it!
-
Python and Golang Integration: Seamlessly call Golang built shared libraries from Python.
-
No Golang Code Required: Users can solely rely on Python for Excel file generation, eliminating the need for Golang expertise.
The core functionality revolves around encoding Excel cell data and styles, or any other Excel properties, into a JSON string within Python. This JSON payload is then passed through ctypes to a Golang shared library. In Golang, the JSON is parsed, and using the streaming writer of excelize to wrtie excel in high performance.
The current version can only be used with this library through example snippets or the example.py file in the root directory of this repository. See limitations for more details.
The steps are:
-
Create a class for your
style
registed likeStyleCollections
in the example. -
Create a class for your excel creation implementation and inherit
NormalWriter
orFastWriter
andStyleCollections
. -
Implement your data writing logic in
def _create_body()
anddef _create_single_header()
(The latter is not necessary)
from openpyxl_style_writer import CustomStyle
from openpyxl.styles import Side
from pyfastexcel.driver import FastWriter, NormalWriter
def prepare_example_data(rows: int = 1000, cols: int = 10) -> list[dict[str, str]]:
import random
random.seed(42)
headers = [f'Column_{i}' for i in range(cols)]
data = [[random.random() for _ in range(cols)] for _ in range(rows)]
records = []
for row in data:
record = {}
for header, value in zip(headers, row):
record[header] = str(round(value * 100, 2))
records.append(record)
return records
class StyleCollections:
black_fill_style = CustomStyle(
font_size='11',
font_bold=True,
font_color='F62B00',
fill_color='000000',
)
green_fill_style = CustomStyle(
font_size='29',
font_bold=False,
font_color='000000',
fill_color='375623',
)
test_fill_style = CustomStyle(
font_params={
'size': 20,
'bold': True,
'italic': True,
'color': '5e03fc',
},
fill_params={
'patternType': 'solid',
'fgColor': '375623',
},
border_params={
'left': Side(style='thin', color='e12aeb'),
'right': Side(style='thick', color='e12aeb'),
'top': Side(style=None, color='e12aeb'),
'bottom': Side(style='dashDot', color='e12aeb'),
},
ali_params={
'wrapText': True,
'shrinkToFit': True,
},
number_format='0.00%',
)
class PyExcelizeNormalExample(NormalWriter, StyleCollections):
def create_excel(self) -> bytes:
self._set_header()
self._create_style()
self.set_file_props('Creator', 'Hello')
self._create_single_header()
self._create_body()
return self._read_lib_and_create_excel()
def _set_header(self):
self.headers = list(self.data[0].keys())
def _create_single_header(self):
for h in self.headers:
self.row_append(h, style='green_fill_style')
self.create_row()
def _create_body(self) -> None:
for row in self.data:
for h in self.headers:
if h[-1] in ('1', '3', '5', '7', '9'):
self.row_append(row[h], style='black_fill_style')
else:
self.row_append(row[h], style='test_fill_style')
self.create_row()
self.switch_sheet('Sheet2')
for row in self.data:
for h in self.headers:
if h[-1] in ('1', '3', '5', '7', '9'):
self.row_append(row[h], style=self.green_fill_style)
else:
self.row_append(row[h], style='black_fill_style')
self.create_row()
if __name__ == '__main__':
data = prepare_example_data(653, 90)
excel_normal = PyExcelizeNormalExample(data).create_excel()
file_path = 'pyexample_normal.xlsx'
with open(file_path2, 'wb') as file:
file.write(excel_normal)
Limitations:
This project currently depends on the CustomStyle
object of
the openpyxl_style_writer
package, which is built for openpyxl to write styles in write-only
mode more efficiently without duplicating code.
Future Plans:
This project plans to create its own Style
object, making it no longer
dependent on the mentioned package.
Limitations:
The current version only has the function to write a cell with a style using
the class-based inheritance streaming writer method, similar to the
Advanced Usage
in
openpyxl_style_writer.
This means users must inherit the NormalWriter
or FastWriter
classes and
also your StyleCollections
to correctly register and use the Style. In short,
if you want to use this library, you have to create StyleCollections
and
Your-Writer-Class
and implement the excel creation in Your-Writer-Class
as
shown in the code snippet provided.
from openpyxl_style_writer import CustomStyle
class StyleCollections:
black_fill_style = CustomStyle(
font_size='11',
font_bold=True,
font_color='F62B00',
fill_color='000000',
)
test_fill_style = CustomStyle(
font_size='19'
)
class PyExcelizeNormalExample(NormalWriter, StyleCollections):
headers = ['col1', 'col2', 'col3']
def create_excel(self) -> None:
for row in self.data:
for h in self.headers:
if h[-1] in ('1', '3', '5', '7', '9'):
self.row_append(row[h], style='black_fill_style')
else:
self.row_append(row[h], style='test_fill_style')
self.create_row()
if __name__ == '__main__':
data = [{'col1': 1, 'col2': 2, 'col3': 3}, {'col1': 4, 'col2': 5, 'col3', 6}]
excel = PyExcelizeNormalExample(data).create_excel()
with open('example.xlsx', 'wb') as file:
file.write(excel)
Future Plans:
-
Make the style register in the shared class object on the Python side. Also, create a function to register the style. By doing so, the style won't need to depend on the(This has been finished in current version)custom-writer-class
. All the styles registered through that function will be sent to Golang and registered. -
Add the ability to create a cell and style with the index, similar to what openpyxl does. (The code snippet provided is only an example, not the real implementation method planned)
ws['A1'].value = 'test' ws['A1'].style = 'black_fill_style'