Skip to main content

High performace excel file generation library.

Project description

pyfastexcel

GitHub Actions Workflow Status Go Report Card GitHub Actions Workflow Status GitHub Actions Workflow Status Codacy Badge codecov

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.

Installation

Install via pip (Recommended)

You can easily install the package via pip

pip install pyfastexcel

Install manually

If you prefer to build the package manually, follow these steps:

  1. Clone the repository:

    git clone https://github.com/Zncl2222/pyfastexcel.git
    
  2. Go to the project root directory:

    cd pyfastexcel
    
  3. Install the required golang packages:

    go mod download
    
  4. Build the Golang shared library using the Makefile:

    make
    
  5. Install the required python packages:

    pip install -r requirements.txt
    

    or

    pipenv install
    
  6. Import the project and start using it!

Features

  • 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.

How it Works

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.

Usage

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:

  1. Create a class for your style registed like StyleCollections in the example.

  2. Create a class for your excel creation implementation and inherit NormalWriter or FastWriter and StyleCollections.

  3. Implement your data writing logic in def _create_body() and def _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)

Current Limitations & Future Plans

Problem 1: Dependence on Other Excel Package

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.

Problem 2: Inflexible Usage

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:

  1. 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 custom-writer-class. All the styles registered through that function will be sent to Golang and registered.

  2. 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'
    

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyfastexcel-0.0.4.tar.gz (6.5 MB view hashes)

Uploaded Source

Built Distribution

pyfastexcel-0.0.4-py3-none-any.whl (6.5 MB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page