Introduction
Excel remains one of the most powerful tools for organizing and analyzing data, but repetitive tasks like formatting, data entry, and report generation can consume hours of your time. This is where automation steps in.
OpenPyXL is a Python library that empowers developers to automate Excel workflows with ease. Its versatility allows you to create, edit, and format Excel files programmatically while supporting advanced features like formulas, charts, and styling.
This blog combines two perspectives:
The practical steps for automating Excel reports.
A deep dive into the design principles—modularity, extensibility, and function encapsulation—that make this project reusable and future-proof.
Let’s explore how OpenPyXL and Python’s object-oriented programming (OOP) principles are used to create dynamic Excel reports.
What You’ll Learn
How to automate Excel workflows with Python.
Techniques for writing reusable and extensible code using OOP.
Step-by-step walkthrough of creating formatted Excel reports with dynamic formulas and sheet handling.
Project Overview
This project is divided into three modular files and an output folder.
generate_reports.py
: The main script that orchestrates report generation.utils/openpyxl_format_handler.py
: Handles styling, formulas, and formatting utilities.utils/openpyxl_generic.py
: Provides reusable functions for workbook and sheet management.output/detailed_report.xlsx
: Contains the output file generated by the script.
Each of these modular files plays a vital role in generating Excel reports efficiently. Let’s delve into the key features of this project and see how these components work together.
Key Features of the Project
1. Dynamic Workbook and Sheet Creation
The process begins with creating a new workbook and a custom-named worksheet. The ExcelWorkbook
class simplifies these tasks, allowing you to focus on the data.
file_path = workbook_utils.create_file("detailed_report.xlsx")
workbook_utils.create_workbook()
sheet = workbook_utils.create_worksheet("Comprehensive_Report")
workbook_utils.remove_default_sheet() # Clean up default sheets
2. Writing Data Dynamically
The write_worksheet
method writes structured data, including headers and formulas, into the worksheet. For example:
data = [
["Sales and Purchase Details"],
["Category", "Item", "Quantity", "Price", "Total"],
["Sales", "Item A", 5, 20, "=C3*D3"],
["Sales", "Item B", 10, 15, "=C4*D4"],
["Purchases", "Item C", 7, 30, "=C5*D5"],
["Purchases", "Item D", 4, 25, "=C6*D6"],
["", "Grand Total", "", "", ""]
]
workbook_utils.write_worksheet(data)
How the Code is Designed
This project makes extensive use of inheritance and encapsulation to create a reusable, extensible toolkit.
Encapsulation in openpyxl_generic.py
The core functionalities—creating workbooks, sheets, and managing data—are encapsulated in the ExcelWorkbook
class. Specialized classes like CellFormatting
, CellBorder
, and CellColor
extend this base functionality.
class ExcelWorkbook:
def create_workbook(self):
self.workbook = Workbook()
return self.workbook
def create_worksheet(self, sheetname):
self.sheet = self.workbook.create_sheet(sheetname)
return self.sheet
Inheritance for Specialized Tasks
By using inheritance, specialized classes focus on their respective tasks without duplicating code. For instance, the WorkbookProperties
class inherits formatting and formula-handling functionality:
class WorkbookProperties(CellFormatting, CellFormula):
def add_filter(self):
self.sheet.auto_filter.ref = get_column_letter(self.min_col) + \
str(self.header_row) + ":" + \
get_column_letter(self.max_col) + str(self.last_row)
This design makes the code easily modifiable and extensible.
Practical Steps in Action
3. Applying Custom Formatting
Headers and titles are formatted with borders, colors, and alignment to enhance readability and visual appeal.
workbook_utils.merge_cells(start_row=1, start_column=1, end_row=1, end_column=5)
title_color = workbook_utils.set_custom_color('lightBlue')
workbook_utils.add_title_color(title_color)
Custom alignment and borders are applied to header rows dynamically:
header_style_request = generic_formatter.form_style_req(2, 1, 6, is_row=True)
workbook_utils.set_named_styles()
workbook_utils.make_style_format(header_style_request, "bold_center")
header_border_request = generic_formatter.form_style_req(2, 1, 5, is_row=True)
workbook_utils.make_border_format(header_border_request, "top_bottom_medium")
These custom alignments, borders, and colors are fully customizable and can be tailored to suit specific requirements.
4. Handling Formulas Dynamically
Formulas are added programmatically for calculating fields such as totals or averages.
formula_request = generic_formatter.form_formula_req(
input_row=7, input_col=5, start_row=3, start_col=5, end_row=6, end_col=5
)
workbook_utils.apply_formula(formula_request, "sum")
We currently have functionality for summing and copying formulas, but the framework can be extended to handle other types like averages or counts as needed.
5. Copying Entire Sheets
Need to duplicate a sheet while preserving its styles and formulas? The CopyWholeSheet
class simplifies this task.
new_sheet = workbook_utils.create_worksheet("Copied_Report")
sheet_copier = CopyWholeSheet(sheet, new_sheet)
sheet_copier.copy_sheet()
Why This Design Matters
Ease of Maintenance:
Each class handles specific responsibilities, reducing complexity.
Adding new features is straightforward, as functionality is modularized.
Code Reusability:
- The utility functions in
openpyxl_generic.py
andopenpyxl_format_handler.py
can be reused across multiple projects.
- The utility functions in
Extensibility:
- Want to add conditional formatting? Simply create a new subclass and extend the functionality without touching existing code.
Modular Testing:
- Each class can be tested independently, ensuring reliability.
Output Example
The generated Excel file includes:
A merged title row with a custom background color.
Headers with bold text, centered, borders, and auto-filters.
Data rows dynamically calculated with formulas.
A copied sheet preserving all styles and formulas.
Extending the Project
Here are some ideas to expand the project:
Conditional Formatting: Highlight rows or cells based on values using
openpyxl.styles
.Chart Integration: Add bar or pie charts using OpenPyXL's charting tools.
Real-Time Data: Populate reports with data fetched from APIs or databases.
Conclusion
This project highlights the power of OpenPyXL for automating Excel workflows while emphasizing modularity and extensibility. By leveraging reusable classes and clear design principles, you can save time, ensure consistency, and create professional-grade reports effortlessly.
Explore the provided GitHub repository to try out the code yourself. Experiment with customizing the utilities and extending the project to meet your unique needs. Whether it’s adding charts, integrating APIs, or enhancing formatting, the possibilities are endless.