| Name | excelstyler JSON |
| Version |
0.1.3
JSON |
| download |
| home_page | None |
| Summary | Style and format Excel files easily with openpyxl |
| upload_time | 2025-10-28 07:32:21 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.8 |
| license | MIT License
Copyright (c) 2025 Nima Orangi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. |
| keywords |
excel
farsi
iranian
jdatetime
openpyxl
persian
report
shamsi
spreadsheet
styling
xlsx
|
| VCS |
 |
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
# excelstyler
[](https://badge.fury.io/py/excelstyler)
[](https://pepy.tech/project/excelstyler)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
`excelstyler` is a Python package that makes it easy to style and format Excel worksheets using [openpyxl](https://openpyxl.readthedocs.io). It provides a simple API for creating professional-looking Excel reports with Persian/Farsi language support.
**Perfect for Iranian developers** who need to create Excel reports with Persian dates, RTL text support, and professional styling.
## Features
- 🎨 **Easy Styling**: Pre-defined color schemes and styling options
- 🇮🇷 **Persian Support**: Built-in support for Persian dates and RTL text
- 📊 **Charts**: Create line and bar charts with simple function calls
- 🔧 **Flexible**: Customizable headers, values, and formatting
- 🧪 **Well Tested**: Comprehensive test suite with pytest
- 📝 **Well Documented**: Clear documentation and examples
## Installation
```bash
pip install excelstyler
```
## Quick Start
```python
from openpyxl import Workbook
from excelstyler.headers import create_header
from excelstyler.values import create_value
from excelstyler.utils import shamsi_date
from datetime import datetime
# Create workbook
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True # For Persian/Farsi support
# Create header
headers = ["Name", "Age", "City", "Date"]
create_header(worksheet, headers, 1, 1, color='green', height=25, width=15)
# Add data
data = [
["John Doe", 30, "New York", shamsi_date(datetime.now())],
["Jane Smith", 25, "London", shamsi_date(datetime.now())],
["Ali Ahmad", 35, "Tehran", shamsi_date(datetime.now())]
]
for i, row_data in enumerate(data, start=2):
create_value(worksheet, row_data, i, 1, border_style='thin')
# Save workbook
workbook.save("report.xlsx")
```
## 📚 Complete Tutorial
### 1. Basic Setup
First, let's create a simple Excel file with basic styling:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header
from excelstyler.values import create_value
# Create a new workbook
workbook = Workbook()
worksheet = workbook.active
# Set RTL for Persian/Farsi support
worksheet.sheet_view.rightToLeft = True
# Create a simple header
headers = ["نام", "سن", "شهر"]
create_header(worksheet, headers, 1, 1, color='green')
# Add some data
data = [
["علی احمدی", 25, "تهران"],
["فاطمه محمدی", 30, "اصفهان"],
["حسن رضایی", 35, "شیراز"]
]
for i, row_data in enumerate(data, start=2):
create_value(worksheet, row_data, i, 1)
workbook.save("simple_report.xlsx")
```
### 2. Advanced Styling
Let's create a more sophisticated report with various styling options:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header_freez
from excelstyler.values import create_value
from excelstyler.helpers import excel_description
from excelstyler.utils import shamsi_date, to_locale_str
from datetime import datetime
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Add title
excel_description(worksheet, 'A1', 'گزارش فروش ماهانه', size=16, to_row='E1')
# Create header with freeze panes
headers = ['ردیف', 'نام محصول', 'تعداد فروش', 'قیمت واحد', 'مجموع']
create_header_freez(
worksheet,
headers,
start_col=1,
row=3,
header_row=4,
height=30,
width=18,
color='blue',
border_style='medium'
)
# Sample data
products = [
['لپتاپ', 50, 15000000],
['موبایل', 200, 8000000],
['تبلت', 100, 12000000],
['هدفون', 300, 2000000]
]
# Add data with alternating colors
for i, (name, quantity, price) in enumerate(products, start=4):
total = quantity * price
row_data = [
i-3, # Row number
name,
quantity,
to_locale_str(price),
to_locale_str(total)
]
create_value(
worksheet,
row_data,
i,
1,
border_style='thin',
m=i, # For alternating colors
height=25
)
# Add summary
total_sales = sum(q * p for _, q, p in products)
excel_description(
worksheet,
'A9',
f'مجموع کل فروش: {to_locale_str(total_sales)} تومان',
size=14,
color='red',
to_row='E9'
)
workbook.save("advanced_report.xlsx")
```
### 3. Working with Charts
Create reports with visual charts:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header
from excelstyler.values import create_value
from excelstyler.chart import add_chart
workbook = Workbook()
worksheet = workbook.active
# Create header
headers = ['ماه', 'فروش (میلیون تومان)']
create_header(worksheet, headers, 1, 1, color='green')
# Add data
monthly_data = [
['فروردین', 120],
['اردیبهشت', 150],
['خرداد', 180],
['تیر', 200],
['مرداد', 220],
['شهریور', 190]
]
for i, (month, sales) in enumerate(monthly_data, start=2):
create_value(worksheet, [month, sales], i, 1, border_style='thin')
# Add a line chart
add_chart(
worksheet=worksheet,
chart_type='line',
data_columns=2, # Sales column
category_column=1, # Month column
start_row=2,
end_row=7,
chart_position="D2",
chart_title="نمودار فروش ماهانه",
x_axis_title="ماه",
y_axis_title="فروش (میلیون تومان)",
chart_width=20,
chart_height=12
)
workbook.save("chart_report.xlsx")
```
### 4. Persian Date Handling
Working with Persian (Shamsi) dates:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header
from excelstyler.values import create_value
from excelstyler.utils import shamsi_date, convert_str_to_date
from datetime import datetime, date
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Create header
headers = ['تاریخ میلادی', 'تاریخ شمسی (متن)', 'تاریخ شمسی (شیء)']
create_header(worksheet, headers, 1, 1, color='orange')
# Sample dates
dates = [
datetime(2023, 3, 21), # Nowruz
datetime(2023, 6, 21), # Summer solstice
datetime(2023, 9, 23), # Autumn equinox
datetime(2023, 12, 21) # Winter solstice
]
for i, gregorian_date in enumerate(dates, start=2):
# Convert to Persian date as string
persian_str = shamsi_date(gregorian_date, in_value=False)
# Convert to Persian date as object
persian_obj = shamsi_date(gregorian_date, in_value=True)
row_data = [
gregorian_date.strftime('%Y-%m-%d'),
persian_str,
persian_obj
]
create_value(worksheet, row_data, i, 1, border_style='thin')
workbook.save("persian_dates.xlsx")
```
### 5. Conditional Formatting
Highlight specific cells based on conditions:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header
from excelstyler.values import create_value
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Create header
headers = ['نام کارمند', 'امتیاز', 'وضعیت']
create_header(worksheet, headers, 1, 1, color='green')
# Employee data
employees = [
['علی احمدی', 95, 'عالی'],
['فاطمه محمدی', 75, 'خوب'],
['حسن رضایی', 45, 'ضعیف'],
['زهرا کریمی', 88, 'عالی'],
['محمد نوری', 60, 'متوسط']
]
for i, (name, score, status) in enumerate(employees, start=2):
# Highlight low scores in red
different_cell = 1 if score < 50 else None
different_value = 45 if score < 50 else None
create_value(
worksheet,
[name, score, status],
i,
1,
border_style='thin',
different_cell=different_cell,
different_value=different_value
)
workbook.save("conditional_formatting.xlsx")
```
### 6. Complete Business Report
A comprehensive example combining all features:
```python
from openpyxl import Workbook
from excelstyler.headers import create_header_freez
from excelstyler.values import create_value
from excelstyler.helpers import excel_description
from excelstyler.chart import add_chart
from excelstyler.utils import shamsi_date, to_locale_str
from datetime import datetime
def create_sales_report():
"""Create a comprehensive sales report"""
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Company header
excel_description(
worksheet,
'A1',
'شرکت فناوری پارس - گزارش فروش سه ماهه',
size=18,
to_row='F1'
)
# Report date
excel_description(
worksheet,
'A2',
f'تاریخ گزارش: {shamsi_date(datetime.now())}',
size=12,
to_row='F2'
)
# Data header with freeze
headers = [
'ردیف', 'نام محصول', 'دستهبندی', 'تعداد فروش',
'قیمت واحد', 'مجموع فروش', 'درصد از کل'
]
create_header_freez(
worksheet,
headers,
start_col=1,
row=4,
header_row=5,
height=25,
width=15,
color='blue',
border_style='medium'
)
# Sample sales data
sales_data = [
['لپتاپ ایسوس', 'کامپیوتر', 25, 15000000],
['آیفون 14', 'موبایل', 50, 25000000],
['سامسونگ گلکسی', 'موبایل', 30, 20000000],
['مکبوک پرو', 'کامپیوتر', 15, 35000000],
['تبلت آیپد', 'تبلت', 40, 12000000],
['هدفون سونی', 'لوازم جانبی', 100, 3000000],
['کیبورد مکانیکال', 'لوازم جانبی', 80, 2000000],
['ماوس گیمینگ', 'لوازم جانبی', 60, 1500000]
]
# Calculate totals
total_sales = sum(q * p for _, _, q, p in sales_data)
# Add data rows
for i, (name, category, quantity, price) in enumerate(sales_data, start=5):
sales_total = quantity * price
percentage = (sales_total / total_sales) * 100
row_data = [
i-4, # Row number
name,
category,
quantity,
to_locale_str(price),
to_locale_str(sales_total),
f"{percentage:.1f}%"
]
create_value(
worksheet,
row_data,
i,
1,
border_style='thin',
m=i, # Alternating colors
height=22
)
# Add summary section
summary_row = len(sales_data) + 6
excel_description(
worksheet,
f'A{summary_row}',
f'مجموع کل فروش: {to_locale_str(total_sales)} تومان',
size=14,
color='red',
to_row=f'F{summary_row}'
)
# Add chart
chart_start_row = summary_row + 2
add_chart(
worksheet=worksheet,
chart_type='bar',
data_columns=6, # Total sales column
category_column=2, # Product name column
start_row=5,
end_row=5 + len(sales_data) - 1,
chart_position=f"A{chart_start_row}",
chart_title="نمودار فروش محصولات",
x_axis_title="محصولات",
y_axis_title="مبلغ فروش (تومان)",
chart_width=25,
chart_height=15
)
# Save the report
filename = f"sales_report_{datetime.now().strftime('%Y%m%d')}.xlsx"
workbook.save(filename)
print(f"گزارش فروش با موفقیت ایجاد شد: {filename}")
return filename
# Create the report
create_sales_report()
```
### 7. Django Integration
Using excelstyler in Django views:
```python
from django.http import HttpResponse
from openpyxl import Workbook
from openpyxl.styles import Font
from io import BytesIO
from excelstyler.headers import create_header_freez
from excelstyler.values import create_value
from excelstyler.utils import shamsi_date
from datetime import datetime
def export_employee_report(request):
"""Export employee data as Excel file"""
# Create workbook in memory
output = BytesIO()
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Add title
worksheet['A1'] = 'گزارش کارمندان'
worksheet['A1'].font = Font(size=16, bold=True)
# Create header
headers = ['ردیف', 'نام', 'نام خانوادگی', 'کد ملی', 'تاریخ استخدام']
create_header_freez(worksheet, headers, 1, 3, 4, color='green')
# Sample employee data (replace with your actual data)
employees = [
['علی', 'احمدی', '1234567890', datetime(2020, 1, 15)],
['فاطمه', 'محمدی', '0987654321', datetime(2021, 3, 20)],
['حسن', 'رضایی', '1122334455', datetime(2019, 6, 10)]
]
# Add data
for i, (first_name, last_name, national_id, hire_date) in enumerate(employees, start=4):
row_data = [
i-3,
first_name,
last_name,
national_id,
shamsi_date(hire_date)
]
create_value(worksheet, row_data, i, 1, border_style='thin')
# Save to BytesIO
workbook.save(output)
output.seek(0)
# Create HTTP response
response = HttpResponse(
output.getvalue(),
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
response['Content-Disposition'] = 'attachment; filename="employee_report.xlsx"'
return response
```
### 8. Error Handling Best Practices
```python
from excelstyler.utils import shamsi_date, to_locale_str
from datetime import datetime, date
def safe_date_conversion(date_input):
"""Safely convert date with error handling"""
try:
if isinstance(date_input, str):
# Try to parse string date
parsed_date = datetime.strptime(date_input, '%Y-%m-%d')
return shamsi_date(parsed_date)
elif isinstance(date_input, (datetime, date)):
return shamsi_date(date_input)
else:
return "تاریخ نامعتبر"
except (ValueError, TypeError) as e:
print(f"خطا در تبدیل تاریخ: {e}")
return "تاریخ نامعتبر"
def safe_number_formatting(number):
"""Safely format number with error handling"""
try:
return to_locale_str(number)
except (ValueError, TypeError) as e:
print(f"خطا در فرمت عدد: {e}")
return str(number)
# Usage example
dates = [datetime.now(), "2023-12-25", None, "invalid-date"]
numbers = [1234567, "500000", None, "not-a-number"]
for date_val in dates:
result = safe_date_conversion(date_val)
print(f"تاریخ: {date_val} -> {result}")
for num_val in numbers:
result = safe_number_formatting(num_val)
print(f"عدد: {num_val} -> {result}")
```
#Example
@api_view(["GET"])
@permission_classes([TokenHasReadWriteScope])
@csrf_exempt
def test_cold_house_excel(request):
"""
A simplified example Excel report for Cold Houses.
Excel output support Persian name.
"""
# --- Excel Setup ---
output = BytesIO()
workbook = Workbook()
worksheet = workbook.active
workbook.remove(worksheet)
worksheet = workbook.create_sheet("Cold House Info")
worksheet.sheet_view.rightToLeft = True
worksheet.insert_rows(1)
# --- Header ---
header = [
'Row', 'Cold House Name', 'City', 'Address',
'Total Weight', 'Allocated Weight', 'Remaining Weight',
'Status', 'Broadcast', 'Relocate', 'Capacity'
]
create_header_freez(worksheet, header, start_col=1, row=2, header_row=3, height=25, width=18)
# --- Example Data ---
# Here we use some mock data for testing
example_data = [
{
'name': 'Cold House A',
'city': 'Tehran',
'address': 'Street 1',
'total_input_weight': 1000,
'total_allocated_weight': 700,
'total_remain_weight': 300,
'status': True,
'broadcast': False,
'relocate': True,
'capacity': 1200
},
{
'name': 'Cold House B',
'city': 'Shiraz',
'address': 'Street 2',
'total_input_weight': 800,
'total_allocated_weight': 500,
'total_remain_weight': 300,
'status': False,
'broadcast': True,
'relocate': False,
'capacity': 1000
}
]
# --- Fill Data ---
row_index = 3
for i, house in enumerate(example_data, start=1):
values = [
i,
house['name'],
house['city'],
house['address'],
house['total_input_weight'],
house['total_allocated_weight'],
house['total_remain_weight'],
'Active' if house['status'] else 'Inactive',
'Yes' if house['broadcast'] else 'No',
'Yes' if house['relocate'] else 'No',
house['capacity']
]
create_value(worksheet, values, start_col=row_index, row=1)
row_index += 1
# --- Save and Response ---
workbook.save(output)
output.seek(0)
response = HttpResponse(
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
response['Content-Disposition'] = 'attachment; filename="ColdHouseExample.xlsx"'
response.write(output.getvalue())
return response
```
### 9. Tips and Tricks
#### Color Customization
```python
from excelstyler.styles import PatternFill
# Custom colors
custom_red = PatternFill(start_color="FF6B6B", fill_type="solid")
custom_blue = PatternFill(start_color="4ECDC4", fill_type="solid")
# Use in create_value
create_value(worksheet, data, 1, 1, color=custom_red)
```
#### Working with Large Datasets
```python
def create_large_report(data_list):
"""Create report for large datasets efficiently"""
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Create header once
headers = ['ردیف', 'نام', 'مقدار', 'تاریخ']
create_header_freez(worksheet, headers, 1, 1, 2, color='green')
# Process data in chunks to avoid memory issues
chunk_size = 1000
for i in range(0, len(data_list), chunk_size):
chunk = data_list[i:i + chunk_size]
for j, row_data in enumerate(chunk, start=i + 2):
create_value(worksheet, row_data, j, 1, m=j)
return workbook
```
#### Dynamic Column Width
```python
from openpyxl.utils import get_column_letter
def auto_adjust_columns(worksheet, start_col, end_col):
"""Automatically adjust column widths based on content"""
for col in range(start_col, end_col + 1):
column_letter = get_column_letter(col)
max_length = 0
for row in worksheet[column_letter]:
if row.value:
max_length = max(max_length, len(str(row.value)))
worksheet.column_dimensions[column_letter].width = max_length + 2
```
### 10. Common Use Cases
#### Financial Reports
```python
def create_financial_report():
"""Create a financial report with currency formatting"""
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
# Header
headers = ['دوره', 'درآمد', 'هزینه', 'سود/زیان']
create_header(worksheet, headers, 1, 1, color='green')
# Financial data
financial_data = [
['Q1 2023', 1000000000, 800000000, 200000000],
['Q2 2023', 1200000000, 900000000, 300000000],
['Q3 2023', 1100000000, 850000000, 250000000],
['Q4 2023', 1300000000, 950000000, 350000000]
]
for i, (period, income, expense, profit) in enumerate(financial_data, start=2):
row_data = [
period,
f"{to_locale_str(income)} تومان",
f"{to_locale_str(expense)} تومان",
f"{to_locale_str(profit)} تومان"
]
create_value(worksheet, row_data, i, 1, border_style='thin')
return workbook
```
#### Inventory Management
```python
def create_inventory_report(products):
"""Create inventory report with stock alerts"""
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
headers = ['کد محصول', 'نام محصول', 'موجودی', 'حداقل موجودی', 'وضعیت']
create_header(worksheet, headers, 1, 1, color='blue')
for i, product in enumerate(products, start=2):
status = "کمبود" if product['stock'] < product['min_stock'] else "کافی"
row_data = [
product['code'],
product['name'],
product['stock'],
product['min_stock'],
status
]
# Highlight low stock items
different_cell = 4 if product['stock'] < product['min_stock'] else None
different_value = product['min_stock'] if product['stock'] < product['min_stock'] else None
create_value(
worksheet,
row_data,
i,
1,
border_style='thin',
different_cell=different_cell,
different_value=different_value
)
return workbook
```
#### Student Grade Report
```python
def create_grade_report(students):
"""Create student grade report with performance indicators"""
workbook = Workbook()
worksheet = workbook.active
worksheet.sheet_view.rightToLeft = True
headers = ['نام دانشجو', 'نمره ریاضی', 'نمره فیزیک', 'نمره شیمی', 'میانگین', 'وضعیت']
create_header(worksheet, headers, 1, 1, color='green')
for i, student in enumerate(students, start=2):
avg_score = (student['math'] + student['physics'] + student['chemistry']) / 3
status = "قبول" if avg_score >= 12 else "مردود"
row_data = [
student['name'],
student['math'],
student['physics'],
student['chemistry'],
f"{avg_score:.1f}",
status
]
# Highlight failing students
different_cell = 5 if avg_score < 12 else None
different_value = avg_score if avg_score < 12 else None
create_value(
worksheet,
row_data,
i,
1,
border_style='thin',
different_cell=different_cell,
different_value=different_value
)
return workbook
```
## 🎨 Available Colors
The library provides these predefined colors:
| Color Name | Hex Code | Usage |
|------------|----------|-------|
| `green` | #00B050 | Success, positive values |
| `red` | #FCDFDC | Errors, negative values |
| `yellow` | #FFFF00 | Warnings, attention |
| `orange` | #FFC000 | Important information |
| `blue` | #538DD5 | Headers, primary info |
| `light_green` | #92D050 | Secondary success |
| `very_light_green` | #5AFC56 | Subtle success |
| `gray` | #B0B0B0 | Disabled, inactive |
| `cream` | #D8AA72 | Default header |
| `light_cream` | #E8C6A0 | Light header |
| `very_light_cream` | #FAF0E7 | Very light background |
## 🔧 Configuration Options
### Border Styles
- `thin` - Thin border
- `medium` - Medium border
- `thick` - Thick border
- `dashed` - Dashed border
- `dotted` - Dotted border
### Chart Types
- `line` - Line chart
- `bar` - Bar chart
### Text Alignment
All headers and values are automatically center-aligned with text wrapping enabled.
## 🚀 Performance Tips
1. **Use freeze panes** for large datasets to improve navigation
2. **Process data in chunks** for very large datasets
3. **Use alternating colors** sparingly for better performance
4. **Set column widths** explicitly to avoid auto-calculation overhead
5. **Use `in_value=True`** for Persian dates when storing in Excel cells
## 🐛 Troubleshooting
### Common Issues
**Issue**: Persian text not displaying correctly
**Solution**: Always set `worksheet.sheet_view.rightToLeft = True`
**Issue**: Charts not appearing
**Solution**: Ensure data range is correct and data exists in specified cells
**Issue**: Colors not applying
**Solution**: Check color name spelling and ensure it's in the predefined list
**Issue**: Date conversion errors
**Solution**: Use try-catch blocks and validate input dates
### Debug Mode
```python
import logging
logging.basicConfig(level=logging.DEBUG)
# Your excelstyler code here
```
## API Reference
### Headers
#### `create_header(worksheet, data, start_col, row, **kwargs)`
Create a styled header row in an Excel worksheet.
**Parameters:**
- `worksheet`: The Excel worksheet object
- `data`: List of header titles
- `start_col`: Starting column index (1-based)
- `row`: Row index where header will be placed
- `height`: Row height (optional)
- `width`: Column width (optional)
- `color`: Background color ('green', 'red', 'blue', etc.)
- `text_color`: Font color (optional)
- `border_style`: Border style ('thin', 'medium', etc.)
#### `create_header_freez(worksheet, data, start_col, row, header_row, **kwargs)`
Create a header with freeze panes and auto-filter.
### Values
#### `create_value(worksheet, data, start_col, row, **kwargs)`
Write formatted values to Excel cells.
**Parameters:**
- `worksheet`: The Excel worksheet object
- `data`: List of values to write
- `start_col`: Starting row index
- `row`: Starting column index
- `border_style`: Border style (optional)
- `m`: For alternating row colors
- `color`: Cell background color
- `different_cell`: Index of cell to highlight
- `different_value`: Value to highlight
### Utilities
#### `shamsi_date(date, in_value=None)`
Convert Gregorian date to Persian (Shamsi) date.
#### `to_locale_str(number)`
Format number with thousands separators.
### Charts
#### `add_chart(worksheet, chart_type, data_columns, category_column, start_row, end_row, chart_position, chart_title, x_axis_title, y_axis_title, **kwargs)`
Add line or bar charts to Excel worksheets.
## Testing
Run the test suite:
```bash
pip install pytest
pytest
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run the test suite
6. Submit a pull request
## 📖 Additional Resources
### Video Tutorials
- [Basic Excel Report Creation](https://example.com/basic-tutorial)
- [Advanced Styling Techniques](https://example.com/advanced-tutorial)
- [Persian Date Integration](https://example.com/persian-dates)
### Community Examples
- [GitHub Examples Repository](https://github.com/7nimor/excelstyler-examples)
- [Stack Overflow Tag](https://stackoverflow.com/questions/tagged/excelstyler)
### Related Projects
- [openpyxl](https://openpyxl.readthedocs.io/) - The underlying Excel library
- [jdatetime](https://github.com/slashmili/python-jalali) - Persian date library
## 🤝 Contributing
We welcome contributions! Here's how you can help:
### Reporting Issues
1. Check existing issues first
2. Provide detailed reproduction steps
3. Include Python and excelstyler versions
4. Attach sample code if possible
### Submitting Pull Requests
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Add tests for your changes
4. Ensure all tests pass (`pytest`)
5. Commit your changes (`git commit -m 'Add amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
### Development Setup
```bash
# Clone the repository
git clone https://github.com/7nimor/excelstyler.git
cd excelstyler
# Install in development mode
pip install -e .
# Install test dependencies
pip install -e ".[test]"
# Run tests
pytest
# Run linting
flake8 src/ tests/
```
## 📊 Changelog
See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
## 🏆 Acknowledgments
- Thanks to the [openpyxl](https://openpyxl.readthedocs.io/) team for the excellent Excel library
- Thanks to the [jdatetime](https://github.com/slashmili/python-jalali) team for Persian date support
- Thanks to all contributors and users who help improve this library
## 📞 Support
- **Documentation**: [Read the docs](https://excelstyler.readthedocs.io/)
- **Issues**: [GitHub Issues](https://github.com/7nimor/excelstyler/issues)
- **Discussions**: [GitHub Discussions](https://github.com/7nimor/excelstyler/discussions)
- **Email**: 7nimor@gmail.com
## ⭐ Star History
[](https://star-history.com/#7nimor/excelstyler&Date)
## 📄 License
MIT License - see [LICENSE](LICENSE) file for details.
---
<div align="center">
**Made with ❤️ for the Persian/Farsi developer community**
[](https://github.com/7nimor/excelstyler)
[](https://github.com/7nimor/excelstyler)
[](https://github.com/7nimor/excelstyler)
</div>
Raw data
{
"_id": null,
"home_page": null,
"name": "excelstyler",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "excel, farsi, iranian, jdatetime, openpyxl, persian, report, shamsi, spreadsheet, styling, xlsx",
"author": null,
"author_email": "Nima Orangi <7nimor@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/50/47/c828b94cf048cc036c513cf36f1708ee29ad9287d6fc09069960c6ed0f84/excelstyler-0.1.3.tar.gz",
"platform": null,
"description": "# excelstyler\n\n[](https://badge.fury.io/py/excelstyler)\n[](https://pepy.tech/project/excelstyler)\n[](https://www.python.org/downloads/)\n[](https://opensource.org/licenses/MIT)\n\n`excelstyler` is a Python package that makes it easy to style and format Excel worksheets using [openpyxl](https://openpyxl.readthedocs.io). It provides a simple API for creating professional-looking Excel reports with Persian/Farsi language support.\n\n**Perfect for Iranian developers** who need to create Excel reports with Persian dates, RTL text support, and professional styling.\n\n## Features\n\n- \ud83c\udfa8 **Easy Styling**: Pre-defined color schemes and styling options\n- \ud83c\uddee\ud83c\uddf7 **Persian Support**: Built-in support for Persian dates and RTL text\n- \ud83d\udcca **Charts**: Create line and bar charts with simple function calls\n- \ud83d\udd27 **Flexible**: Customizable headers, values, and formatting\n- \ud83e\uddea **Well Tested**: Comprehensive test suite with pytest\n- \ud83d\udcdd **Well Documented**: Clear documentation and examples\n\n## Installation\n\n```bash\npip install excelstyler\n```\n\n## Quick Start\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header\nfrom excelstyler.values import create_value\nfrom excelstyler.utils import shamsi_date\nfrom datetime import datetime\n\n# Create workbook\nworkbook = Workbook()\nworksheet = workbook.active\nworksheet.sheet_view.rightToLeft = True # For Persian/Farsi support\n\n# Create header\nheaders = [\"Name\", \"Age\", \"City\", \"Date\"]\ncreate_header(worksheet, headers, 1, 1, color='green', height=25, width=15)\n\n# Add data\ndata = [\n [\"John Doe\", 30, \"New York\", shamsi_date(datetime.now())],\n [\"Jane Smith\", 25, \"London\", shamsi_date(datetime.now())],\n [\"Ali Ahmad\", 35, \"Tehran\", shamsi_date(datetime.now())]\n]\n\nfor i, row_data in enumerate(data, start=2):\n create_value(worksheet, row_data, i, 1, border_style='thin')\n\n# Save workbook\nworkbook.save(\"report.xlsx\")\n```\n\n## \ud83d\udcda Complete Tutorial\n\n### 1. Basic Setup\n\nFirst, let's create a simple Excel file with basic styling:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header\nfrom excelstyler.values import create_value\n\n# Create a new workbook\nworkbook = Workbook()\nworksheet = workbook.active\n\n# Set RTL for Persian/Farsi support\nworksheet.sheet_view.rightToLeft = True\n\n# Create a simple header\nheaders = [\"\u0646\u0627\u0645\", \"\u0633\u0646\", \"\u0634\u0647\u0631\"]\ncreate_header(worksheet, headers, 1, 1, color='green')\n\n# Add some data\ndata = [\n [\"\u0639\u0644\u06cc \u0627\u062d\u0645\u062f\u06cc\", 25, \"\u062a\u0647\u0631\u0627\u0646\"],\n [\"\u0641\u0627\u0637\u0645\u0647 \u0645\u062d\u0645\u062f\u06cc\", 30, \"\u0627\u0635\u0641\u0647\u0627\u0646\"],\n [\"\u062d\u0633\u0646 \u0631\u0636\u0627\u06cc\u06cc\", 35, \"\u0634\u06cc\u0631\u0627\u0632\"]\n]\n\nfor i, row_data in enumerate(data, start=2):\n create_value(worksheet, row_data, i, 1)\n\nworkbook.save(\"simple_report.xlsx\")\n```\n\n### 2. Advanced Styling\n\nLet's create a more sophisticated report with various styling options:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header_freez\nfrom excelstyler.values import create_value\nfrom excelstyler.helpers import excel_description\nfrom excelstyler.utils import shamsi_date, to_locale_str\nfrom datetime import datetime\n\nworkbook = Workbook()\nworksheet = workbook.active\nworksheet.sheet_view.rightToLeft = True\n\n# Add title\nexcel_description(worksheet, 'A1', '\u06af\u0632\u0627\u0631\u0634 \u0641\u0631\u0648\u0634 \u0645\u0627\u0647\u0627\u0646\u0647', size=16, to_row='E1')\n\n# Create header with freeze panes\nheaders = ['\u0631\u062f\u06cc\u0641', '\u0646\u0627\u0645 \u0645\u062d\u0635\u0648\u0644', '\u062a\u0639\u062f\u0627\u062f \u0641\u0631\u0648\u0634', '\u0642\u06cc\u0645\u062a \u0648\u0627\u062d\u062f', '\u0645\u062c\u0645\u0648\u0639']\ncreate_header_freez(\n worksheet, \n headers, \n start_col=1, \n row=3, \n header_row=4,\n height=30, \n width=18,\n color='blue',\n border_style='medium'\n)\n\n# Sample data\nproducts = [\n ['\u0644\u067e\u200c\u062a\u0627\u067e', 50, 15000000],\n ['\u0645\u0648\u0628\u0627\u06cc\u0644', 200, 8000000],\n ['\u062a\u0628\u0644\u062a', 100, 12000000],\n ['\u0647\u062f\u0641\u0648\u0646', 300, 2000000]\n]\n\n# Add data with alternating colors\nfor i, (name, quantity, price) in enumerate(products, start=4):\n total = quantity * price\n row_data = [\n i-3, # Row number\n name,\n quantity,\n to_locale_str(price),\n to_locale_str(total)\n ]\n create_value(\n worksheet, \n row_data, \n i, \n 1, \n border_style='thin',\n m=i, # For alternating colors\n height=25\n )\n\n# Add summary\ntotal_sales = sum(q * p for _, q, p in products)\nexcel_description(\n worksheet, \n 'A9', \n f'\u0645\u062c\u0645\u0648\u0639 \u06a9\u0644 \u0641\u0631\u0648\u0634: {to_locale_str(total_sales)} \u062a\u0648\u0645\u0627\u0646', \n size=14, \n color='red',\n to_row='E9'\n)\n\nworkbook.save(\"advanced_report.xlsx\")\n```\n\n### 3. Working with Charts\n\nCreate reports with visual charts:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header\nfrom excelstyler.values import create_value\nfrom excelstyler.chart import add_chart\n\nworkbook = Workbook()\nworksheet = workbook.active\n\n# Create header\nheaders = ['\u0645\u0627\u0647', '\u0641\u0631\u0648\u0634 (\u0645\u06cc\u0644\u06cc\u0648\u0646 \u062a\u0648\u0645\u0627\u0646)']\ncreate_header(worksheet, headers, 1, 1, color='green')\n\n# Add data\nmonthly_data = [\n ['\u0641\u0631\u0648\u0631\u062f\u06cc\u0646', 120],\n ['\u0627\u0631\u062f\u06cc\u0628\u0647\u0634\u062a', 150],\n ['\u062e\u0631\u062f\u0627\u062f', 180],\n ['\u062a\u06cc\u0631', 200],\n ['\u0645\u0631\u062f\u0627\u062f', 220],\n ['\u0634\u0647\u0631\u06cc\u0648\u0631', 190]\n]\n\nfor i, (month, sales) in enumerate(monthly_data, start=2):\n create_value(worksheet, [month, sales], i, 1, border_style='thin')\n\n# Add a line chart\nadd_chart(\n worksheet=worksheet,\n chart_type='line',\n data_columns=2, # Sales column\n category_column=1, # Month column\n start_row=2,\n end_row=7,\n chart_position=\"D2\",\n chart_title=\"\u0646\u0645\u0648\u062f\u0627\u0631 \u0641\u0631\u0648\u0634 \u0645\u0627\u0647\u0627\u0646\u0647\",\n x_axis_title=\"\u0645\u0627\u0647\",\n y_axis_title=\"\u0641\u0631\u0648\u0634 (\u0645\u06cc\u0644\u06cc\u0648\u0646 \u062a\u0648\u0645\u0627\u0646)\",\n chart_width=20,\n chart_height=12\n)\n\nworkbook.save(\"chart_report.xlsx\")\n```\n\n### 4. Persian Date Handling\n\nWorking with Persian (Shamsi) dates:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header\nfrom excelstyler.values import create_value\nfrom excelstyler.utils import shamsi_date, convert_str_to_date\nfrom datetime import datetime, date\n\nworkbook = Workbook()\nworksheet = workbook.active\nworksheet.sheet_view.rightToLeft = True\n\n# Create header\nheaders = ['\u062a\u0627\u0631\u06cc\u062e \u0645\u06cc\u0644\u0627\u062f\u06cc', '\u062a\u0627\u0631\u06cc\u062e \u0634\u0645\u0633\u06cc (\u0645\u062a\u0646)', '\u062a\u0627\u0631\u06cc\u062e \u0634\u0645\u0633\u06cc (\u0634\u06cc\u0621)']\ncreate_header(worksheet, headers, 1, 1, color='orange')\n\n# Sample dates\ndates = [\n datetime(2023, 3, 21), # Nowruz\n datetime(2023, 6, 21), # Summer solstice\n datetime(2023, 9, 23), # Autumn equinox\n datetime(2023, 12, 21) # Winter solstice\n]\n\nfor i, gregorian_date in enumerate(dates, start=2):\n # Convert to Persian date as string\n persian_str = shamsi_date(gregorian_date, in_value=False)\n \n # Convert to Persian date as object\n persian_obj = shamsi_date(gregorian_date, in_value=True)\n \n row_data = [\n gregorian_date.strftime('%Y-%m-%d'),\n persian_str,\n persian_obj\n ]\n \n create_value(worksheet, row_data, i, 1, border_style='thin')\n\nworkbook.save(\"persian_dates.xlsx\")\n```\n\n### 5. Conditional Formatting\n\nHighlight specific cells based on conditions:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header\nfrom excelstyler.values import create_value\n\nworkbook = Workbook()\nworksheet = workbook.active\nworksheet.sheet_view.rightToLeft = True\n\n# Create header\nheaders = ['\u0646\u0627\u0645 \u06a9\u0627\u0631\u0645\u0646\u062f', '\u0627\u0645\u062a\u06cc\u0627\u0632', '\u0648\u0636\u0639\u06cc\u062a']\ncreate_header(worksheet, headers, 1, 1, color='green')\n\n# Employee data\nemployees = [\n ['\u0639\u0644\u06cc \u0627\u062d\u0645\u062f\u06cc', 95, '\u0639\u0627\u0644\u06cc'],\n ['\u0641\u0627\u0637\u0645\u0647 \u0645\u062d\u0645\u062f\u06cc', 75, '\u062e\u0648\u0628'],\n ['\u062d\u0633\u0646 \u0631\u0636\u0627\u06cc\u06cc', 45, '\u0636\u0639\u06cc\u0641'],\n ['\u0632\u0647\u0631\u0627 \u06a9\u0631\u06cc\u0645\u06cc', 88, '\u0639\u0627\u0644\u06cc'],\n ['\u0645\u062d\u0645\u062f \u0646\u0648\u0631\u06cc', 60, '\u0645\u062a\u0648\u0633\u0637']\n]\n\nfor i, (name, score, status) in enumerate(employees, start=2):\n # Highlight low scores in red\n different_cell = 1 if score < 50 else None\n different_value = 45 if score < 50 else None\n \n create_value(\n worksheet, \n [name, score, status], \n i, \n 1, \n border_style='thin',\n different_cell=different_cell,\n different_value=different_value\n )\n\nworkbook.save(\"conditional_formatting.xlsx\")\n```\n\n### 6. Complete Business Report\n\nA comprehensive example combining all features:\n\n```python\nfrom openpyxl import Workbook\nfrom excelstyler.headers import create_header_freez\nfrom excelstyler.values import create_value\nfrom excelstyler.helpers import excel_description\nfrom excelstyler.chart import add_chart\nfrom excelstyler.utils import shamsi_date, to_locale_str\nfrom datetime import datetime\n\ndef create_sales_report():\n \"\"\"Create a comprehensive sales report\"\"\"\n \n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n # Company header\n excel_description(\n worksheet, \n 'A1', \n '\u0634\u0631\u06a9\u062a \u0641\u0646\u0627\u0648\u0631\u06cc \u067e\u0627\u0631\u0633 - \u06af\u0632\u0627\u0631\u0634 \u0641\u0631\u0648\u0634 \u0633\u0647 \u0645\u0627\u0647\u0647', \n size=18, \n to_row='F1'\n )\n \n # Report date\n excel_description(\n worksheet, \n 'A2', \n f'\u062a\u0627\u0631\u06cc\u062e \u06af\u0632\u0627\u0631\u0634: {shamsi_date(datetime.now())}', \n size=12, \n to_row='F2'\n )\n \n # Data header with freeze\n headers = [\n '\u0631\u062f\u06cc\u0641', '\u0646\u0627\u0645 \u0645\u062d\u0635\u0648\u0644', '\u062f\u0633\u062a\u0647\u200c\u0628\u0646\u062f\u06cc', '\u062a\u0639\u062f\u0627\u062f \u0641\u0631\u0648\u0634', \n '\u0642\u06cc\u0645\u062a \u0648\u0627\u062d\u062f', '\u0645\u062c\u0645\u0648\u0639 \u0641\u0631\u0648\u0634', '\u062f\u0631\u0635\u062f \u0627\u0632 \u06a9\u0644'\n ]\n create_header_freez(\n worksheet, \n headers, \n start_col=1, \n row=4, \n header_row=5,\n height=25, \n width=15,\n color='blue',\n border_style='medium'\n )\n \n # Sample sales data\n sales_data = [\n ['\u0644\u067e\u200c\u062a\u0627\u067e \u0627\u06cc\u0633\u0648\u0633', '\u06a9\u0627\u0645\u067e\u06cc\u0648\u062a\u0631', 25, 15000000],\n ['\u0622\u06cc\u0641\u0648\u0646 14', '\u0645\u0648\u0628\u0627\u06cc\u0644', 50, 25000000],\n ['\u0633\u0627\u0645\u0633\u0648\u0646\u06af \u06af\u0644\u06a9\u0633\u06cc', '\u0645\u0648\u0628\u0627\u06cc\u0644', 30, 20000000],\n ['\u0645\u06a9\u200c\u0628\u0648\u06a9 \u067e\u0631\u0648', '\u06a9\u0627\u0645\u067e\u06cc\u0648\u062a\u0631', 15, 35000000],\n ['\u062a\u0628\u0644\u062a \u0622\u06cc\u067e\u062f', '\u062a\u0628\u0644\u062a', 40, 12000000],\n ['\u0647\u062f\u0641\u0648\u0646 \u0633\u0648\u0646\u06cc', '\u0644\u0648\u0627\u0632\u0645 \u062c\u0627\u0646\u0628\u06cc', 100, 3000000],\n ['\u06a9\u06cc\u0628\u0648\u0631\u062f \u0645\u06a9\u0627\u0646\u06cc\u06a9\u0627\u0644', '\u0644\u0648\u0627\u0632\u0645 \u062c\u0627\u0646\u0628\u06cc', 80, 2000000],\n ['\u0645\u0627\u0648\u0633 \u06af\u06cc\u0645\u06cc\u0646\u06af', '\u0644\u0648\u0627\u0632\u0645 \u062c\u0627\u0646\u0628\u06cc', 60, 1500000]\n ]\n \n # Calculate totals\n total_sales = sum(q * p for _, _, q, p in sales_data)\n \n # Add data rows\n for i, (name, category, quantity, price) in enumerate(sales_data, start=5):\n sales_total = quantity * price\n percentage = (sales_total / total_sales) * 100\n \n row_data = [\n i-4, # Row number\n name,\n category,\n quantity,\n to_locale_str(price),\n to_locale_str(sales_total),\n f\"{percentage:.1f}%\"\n ]\n \n create_value(\n worksheet, \n row_data, \n i, \n 1, \n border_style='thin',\n m=i, # Alternating colors\n height=22\n )\n \n # Add summary section\n summary_row = len(sales_data) + 6\n excel_description(\n worksheet, \n f'A{summary_row}', \n f'\u0645\u062c\u0645\u0648\u0639 \u06a9\u0644 \u0641\u0631\u0648\u0634: {to_locale_str(total_sales)} \u062a\u0648\u0645\u0627\u0646', \n size=14, \n color='red',\n to_row=f'F{summary_row}'\n )\n \n # Add chart\n chart_start_row = summary_row + 2\n add_chart(\n worksheet=worksheet,\n chart_type='bar',\n data_columns=6, # Total sales column\n category_column=2, # Product name column\n start_row=5,\n end_row=5 + len(sales_data) - 1,\n chart_position=f\"A{chart_start_row}\",\n chart_title=\"\u0646\u0645\u0648\u062f\u0627\u0631 \u0641\u0631\u0648\u0634 \u0645\u062d\u0635\u0648\u0644\u0627\u062a\",\n x_axis_title=\"\u0645\u062d\u0635\u0648\u0644\u0627\u062a\",\n y_axis_title=\"\u0645\u0628\u0644\u063a \u0641\u0631\u0648\u0634 (\u062a\u0648\u0645\u0627\u0646)\",\n chart_width=25,\n chart_height=15\n )\n \n # Save the report\n filename = f\"sales_report_{datetime.now().strftime('%Y%m%d')}.xlsx\"\n workbook.save(filename)\n print(f\"\u06af\u0632\u0627\u0631\u0634 \u0641\u0631\u0648\u0634 \u0628\u0627 \u0645\u0648\u0641\u0642\u06cc\u062a \u0627\u06cc\u062c\u0627\u062f \u0634\u062f: {filename}\")\n \n return filename\n\n# Create the report\ncreate_sales_report()\n```\n\n### 7. Django Integration\n\nUsing excelstyler in Django views:\n\n```python\nfrom django.http import HttpResponse\nfrom openpyxl import Workbook\nfrom openpyxl.styles import Font\nfrom io import BytesIO\nfrom excelstyler.headers import create_header_freez\nfrom excelstyler.values import create_value\nfrom excelstyler.utils import shamsi_date\nfrom datetime import datetime\n\ndef export_employee_report(request):\n \"\"\"Export employee data as Excel file\"\"\"\n \n # Create workbook in memory\n output = BytesIO()\n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n # Add title\n worksheet['A1'] = '\u06af\u0632\u0627\u0631\u0634 \u06a9\u0627\u0631\u0645\u0646\u062f\u0627\u0646'\n worksheet['A1'].font = Font(size=16, bold=True)\n \n # Create header\n headers = ['\u0631\u062f\u06cc\u0641', '\u0646\u0627\u0645', '\u0646\u0627\u0645 \u062e\u0627\u0646\u0648\u0627\u062f\u06af\u06cc', '\u06a9\u062f \u0645\u0644\u06cc', '\u062a\u0627\u0631\u06cc\u062e \u0627\u0633\u062a\u062e\u062f\u0627\u0645']\n create_header_freez(worksheet, headers, 1, 3, 4, color='green')\n \n # Sample employee data (replace with your actual data)\n employees = [\n ['\u0639\u0644\u06cc', '\u0627\u062d\u0645\u062f\u06cc', '1234567890', datetime(2020, 1, 15)],\n ['\u0641\u0627\u0637\u0645\u0647', '\u0645\u062d\u0645\u062f\u06cc', '0987654321', datetime(2021, 3, 20)],\n ['\u062d\u0633\u0646', '\u0631\u0636\u0627\u06cc\u06cc', '1122334455', datetime(2019, 6, 10)]\n ]\n \n # Add data\n for i, (first_name, last_name, national_id, hire_date) in enumerate(employees, start=4):\n row_data = [\n i-3,\n first_name,\n last_name,\n national_id,\n shamsi_date(hire_date)\n ]\n create_value(worksheet, row_data, i, 1, border_style='thin')\n \n # Save to BytesIO\nworkbook.save(output)\noutput.seek(0)\n\n # Create HTTP response\nresponse = HttpResponse(\n output.getvalue(),\n content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n )\n response['Content-Disposition'] = 'attachment; filename=\"employee_report.xlsx\"'\n \nreturn response\n```\n\n### 8. Error Handling Best Practices\n\n```python\nfrom excelstyler.utils import shamsi_date, to_locale_str\nfrom datetime import datetime, date\n\ndef safe_date_conversion(date_input):\n \"\"\"Safely convert date with error handling\"\"\"\n try:\n if isinstance(date_input, str):\n # Try to parse string date\n parsed_date = datetime.strptime(date_input, '%Y-%m-%d')\n return shamsi_date(parsed_date)\n elif isinstance(date_input, (datetime, date)):\n return shamsi_date(date_input)\n else:\n return \"\u062a\u0627\u0631\u06cc\u062e \u0646\u0627\u0645\u0639\u062a\u0628\u0631\"\n except (ValueError, TypeError) as e:\n print(f\"\u062e\u0637\u0627 \u062f\u0631 \u062a\u0628\u062f\u06cc\u0644 \u062a\u0627\u0631\u06cc\u062e: {e}\")\n return \"\u062a\u0627\u0631\u06cc\u062e \u0646\u0627\u0645\u0639\u062a\u0628\u0631\"\n\ndef safe_number_formatting(number):\n \"\"\"Safely format number with error handling\"\"\"\n try:\n return to_locale_str(number)\n except (ValueError, TypeError) as e:\n print(f\"\u062e\u0637\u0627 \u062f\u0631 \u0641\u0631\u0645\u062a \u0639\u062f\u062f: {e}\")\n return str(number)\n\n# Usage example\ndates = [datetime.now(), \"2023-12-25\", None, \"invalid-date\"]\nnumbers = [1234567, \"500000\", None, \"not-a-number\"]\n\nfor date_val in dates:\n result = safe_date_conversion(date_val)\n print(f\"\u062a\u0627\u0631\u06cc\u062e: {date_val} -> {result}\")\n\nfor num_val in numbers:\n result = safe_number_formatting(num_val)\n print(f\"\u0639\u062f\u062f: {num_val} -> {result}\")\n```\n\n\n\n#Example\n@api_view([\"GET\"])\n@permission_classes([TokenHasReadWriteScope])\n@csrf_exempt\ndef test_cold_house_excel(request):\n \"\"\"\n A simplified example Excel report for Cold Houses.\n Excel output support Persian name.\n \"\"\"\n\n # --- Excel Setup ---\n output = BytesIO()\n workbook = Workbook()\n worksheet = workbook.active\n workbook.remove(worksheet)\n worksheet = workbook.create_sheet(\"Cold House Info\")\n worksheet.sheet_view.rightToLeft = True\n worksheet.insert_rows(1)\n\n # --- Header ---\n header = [\n 'Row', 'Cold House Name', 'City', 'Address',\n 'Total Weight', 'Allocated Weight', 'Remaining Weight',\n 'Status', 'Broadcast', 'Relocate', 'Capacity'\n ]\n create_header_freez(worksheet, header, start_col=1, row=2, header_row=3, height=25, width=18)\n\n # --- Example Data ---\n # Here we use some mock data for testing\n example_data = [\n {\n 'name': 'Cold House A',\n 'city': 'Tehran',\n 'address': 'Street 1',\n 'total_input_weight': 1000,\n 'total_allocated_weight': 700,\n 'total_remain_weight': 300,\n 'status': True,\n 'broadcast': False,\n 'relocate': True,\n 'capacity': 1200\n },\n {\n 'name': 'Cold House B',\n 'city': 'Shiraz',\n 'address': 'Street 2',\n 'total_input_weight': 800,\n 'total_allocated_weight': 500,\n 'total_remain_weight': 300,\n 'status': False,\n 'broadcast': True,\n 'relocate': False,\n 'capacity': 1000\n }\n ]\n\n # --- Fill Data ---\n row_index = 3\n for i, house in enumerate(example_data, start=1):\n values = [\n i,\n house['name'],\n house['city'],\n house['address'],\n house['total_input_weight'],\n house['total_allocated_weight'],\n house['total_remain_weight'],\n 'Active' if house['status'] else 'Inactive',\n 'Yes' if house['broadcast'] else 'No',\n 'Yes' if house['relocate'] else 'No',\n house['capacity']\n ]\n create_value(worksheet, values, start_col=row_index, row=1)\n row_index += 1\n\n\n # --- Save and Response ---\n workbook.save(output)\n output.seek(0)\n response = HttpResponse(\n content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\n )\n response['Content-Disposition'] = 'attachment; filename=\"ColdHouseExample.xlsx\"'\n response.write(output.getvalue())\n return response\n\n```\n\n### 9. Tips and Tricks\n\n#### Color Customization\n```python\nfrom excelstyler.styles import PatternFill\n\n# Custom colors\ncustom_red = PatternFill(start_color=\"FF6B6B\", fill_type=\"solid\")\ncustom_blue = PatternFill(start_color=\"4ECDC4\", fill_type=\"solid\")\n\n# Use in create_value\ncreate_value(worksheet, data, 1, 1, color=custom_red)\n```\n\n#### Working with Large Datasets\n```python\ndef create_large_report(data_list):\n \"\"\"Create report for large datasets efficiently\"\"\"\n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n # Create header once\n headers = ['\u0631\u062f\u06cc\u0641', '\u0646\u0627\u0645', '\u0645\u0642\u062f\u0627\u0631', '\u062a\u0627\u0631\u06cc\u062e']\n create_header_freez(worksheet, headers, 1, 1, 2, color='green')\n \n # Process data in chunks to avoid memory issues\n chunk_size = 1000\n for i in range(0, len(data_list), chunk_size):\n chunk = data_list[i:i + chunk_size]\n for j, row_data in enumerate(chunk, start=i + 2):\n create_value(worksheet, row_data, j, 1, m=j)\n \n return workbook\n```\n\n#### Dynamic Column Width\n```python\nfrom openpyxl.utils import get_column_letter\n\ndef auto_adjust_columns(worksheet, start_col, end_col):\n \"\"\"Automatically adjust column widths based on content\"\"\"\n for col in range(start_col, end_col + 1):\n column_letter = get_column_letter(col)\n max_length = 0\n \n for row in worksheet[column_letter]:\n if row.value:\n max_length = max(max_length, len(str(row.value)))\n \n worksheet.column_dimensions[column_letter].width = max_length + 2\n```\n\n### 10. Common Use Cases\n\n#### Financial Reports\n```python\ndef create_financial_report():\n \"\"\"Create a financial report with currency formatting\"\"\"\n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n # Header\n headers = ['\u062f\u0648\u0631\u0647', '\u062f\u0631\u0622\u0645\u062f', '\u0647\u0632\u06cc\u0646\u0647', '\u0633\u0648\u062f/\u0632\u06cc\u0627\u0646']\n create_header(worksheet, headers, 1, 1, color='green')\n \n # Financial data\n financial_data = [\n ['Q1 2023', 1000000000, 800000000, 200000000],\n ['Q2 2023', 1200000000, 900000000, 300000000],\n ['Q3 2023', 1100000000, 850000000, 250000000],\n ['Q4 2023', 1300000000, 950000000, 350000000]\n ]\n \n for i, (period, income, expense, profit) in enumerate(financial_data, start=2):\n row_data = [\n period,\n f\"{to_locale_str(income)} \u062a\u0648\u0645\u0627\u0646\",\n f\"{to_locale_str(expense)} \u062a\u0648\u0645\u0627\u0646\",\n f\"{to_locale_str(profit)} \u062a\u0648\u0645\u0627\u0646\"\n ]\n create_value(worksheet, row_data, i, 1, border_style='thin')\n \n return workbook\n```\n\n#### Inventory Management\n```python\ndef create_inventory_report(products):\n \"\"\"Create inventory report with stock alerts\"\"\"\n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n headers = ['\u06a9\u062f \u0645\u062d\u0635\u0648\u0644', '\u0646\u0627\u0645 \u0645\u062d\u0635\u0648\u0644', '\u0645\u0648\u062c\u0648\u062f\u06cc', '\u062d\u062f\u0627\u0642\u0644 \u0645\u0648\u062c\u0648\u062f\u06cc', '\u0648\u0636\u0639\u06cc\u062a']\n create_header(worksheet, headers, 1, 1, color='blue')\n \n for i, product in enumerate(products, start=2):\n status = \"\u06a9\u0645\u0628\u0648\u062f\" if product['stock'] < product['min_stock'] else \"\u06a9\u0627\u0641\u06cc\"\n \n row_data = [\n product['code'],\n product['name'],\n product['stock'],\n product['min_stock'],\n status\n ]\n \n # Highlight low stock items\n different_cell = 4 if product['stock'] < product['min_stock'] else None\n different_value = product['min_stock'] if product['stock'] < product['min_stock'] else None\n \n create_value(\n worksheet, \n row_data, \n i, \n 1, \n border_style='thin',\n different_cell=different_cell,\n different_value=different_value\n )\n \n return workbook\n```\n\n#### Student Grade Report\n```python\ndef create_grade_report(students):\n \"\"\"Create student grade report with performance indicators\"\"\"\n workbook = Workbook()\n worksheet = workbook.active\n worksheet.sheet_view.rightToLeft = True\n \n headers = ['\u0646\u0627\u0645 \u062f\u0627\u0646\u0634\u062c\u0648', '\u0646\u0645\u0631\u0647 \u0631\u06cc\u0627\u0636\u06cc', '\u0646\u0645\u0631\u0647 \u0641\u06cc\u0632\u06cc\u06a9', '\u0646\u0645\u0631\u0647 \u0634\u06cc\u0645\u06cc', '\u0645\u06cc\u0627\u0646\u06af\u06cc\u0646', '\u0648\u0636\u0639\u06cc\u062a']\n create_header(worksheet, headers, 1, 1, color='green')\n \n for i, student in enumerate(students, start=2):\n avg_score = (student['math'] + student['physics'] + student['chemistry']) / 3\n status = \"\u0642\u0628\u0648\u0644\" if avg_score >= 12 else \"\u0645\u0631\u062f\u0648\u062f\"\n \n row_data = [\n student['name'],\n student['math'],\n student['physics'],\n student['chemistry'],\n f\"{avg_score:.1f}\",\n status\n ]\n \n # Highlight failing students\n different_cell = 5 if avg_score < 12 else None\n different_value = avg_score if avg_score < 12 else None\n \n create_value(\n worksheet, \n row_data, \n i, \n 1, \n border_style='thin',\n different_cell=different_cell,\n different_value=different_value\n )\n \n return workbook\n```\n\n## \ud83c\udfa8 Available Colors\n\nThe library provides these predefined colors:\n\n| Color Name | Hex Code | Usage |\n|------------|----------|-------|\n| `green` | #00B050 | Success, positive values |\n| `red` | #FCDFDC | Errors, negative values |\n| `yellow` | #FFFF00 | Warnings, attention |\n| `orange` | #FFC000 | Important information |\n| `blue` | #538DD5 | Headers, primary info |\n| `light_green` | #92D050 | Secondary success |\n| `very_light_green` | #5AFC56 | Subtle success |\n| `gray` | #B0B0B0 | Disabled, inactive |\n| `cream` | #D8AA72 | Default header |\n| `light_cream` | #E8C6A0 | Light header |\n| `very_light_cream` | #FAF0E7 | Very light background |\n\n## \ud83d\udd27 Configuration Options\n\n### Border Styles\n- `thin` - Thin border\n- `medium` - Medium border \n- `thick` - Thick border\n- `dashed` - Dashed border\n- `dotted` - Dotted border\n\n### Chart Types\n- `line` - Line chart\n- `bar` - Bar chart\n\n### Text Alignment\nAll headers and values are automatically center-aligned with text wrapping enabled.\n\n## \ud83d\ude80 Performance Tips\n\n1. **Use freeze panes** for large datasets to improve navigation\n2. **Process data in chunks** for very large datasets\n3. **Use alternating colors** sparingly for better performance\n4. **Set column widths** explicitly to avoid auto-calculation overhead\n5. **Use `in_value=True`** for Persian dates when storing in Excel cells\n\n## \ud83d\udc1b Troubleshooting\n\n### Common Issues\n\n**Issue**: Persian text not displaying correctly\n**Solution**: Always set `worksheet.sheet_view.rightToLeft = True`\n\n**Issue**: Charts not appearing\n**Solution**: Ensure data range is correct and data exists in specified cells\n\n**Issue**: Colors not applying\n**Solution**: Check color name spelling and ensure it's in the predefined list\n\n**Issue**: Date conversion errors\n**Solution**: Use try-catch blocks and validate input dates\n\n### Debug Mode\n```python\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n\n# Your excelstyler code here\n```\n\n## API Reference\n\n### Headers\n\n#### `create_header(worksheet, data, start_col, row, **kwargs)`\nCreate a styled header row in an Excel worksheet.\n\n**Parameters:**\n- `worksheet`: The Excel worksheet object\n- `data`: List of header titles\n- `start_col`: Starting column index (1-based)\n- `row`: Row index where header will be placed\n- `height`: Row height (optional)\n- `width`: Column width (optional)\n- `color`: Background color ('green', 'red', 'blue', etc.)\n- `text_color`: Font color (optional)\n- `border_style`: Border style ('thin', 'medium', etc.)\n\n#### `create_header_freez(worksheet, data, start_col, row, header_row, **kwargs)`\nCreate a header with freeze panes and auto-filter.\n\n### Values\n\n#### `create_value(worksheet, data, start_col, row, **kwargs)`\nWrite formatted values to Excel cells.\n\n**Parameters:**\n- `worksheet`: The Excel worksheet object\n- `data`: List of values to write\n- `start_col`: Starting row index\n- `row`: Starting column index\n- `border_style`: Border style (optional)\n- `m`: For alternating row colors\n- `color`: Cell background color\n- `different_cell`: Index of cell to highlight\n- `different_value`: Value to highlight\n\n### Utilities\n\n#### `shamsi_date(date, in_value=None)`\nConvert Gregorian date to Persian (Shamsi) date.\n\n#### `to_locale_str(number)`\nFormat number with thousands separators.\n\n### Charts\n\n#### `add_chart(worksheet, chart_type, data_columns, category_column, start_row, end_row, chart_position, chart_title, x_axis_title, y_axis_title, **kwargs)`\nAdd line or bar charts to Excel worksheets.\n\n## Testing\n\nRun the test suite:\n\n```bash\npip install pytest\npytest\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Run the test suite\n6. Submit a pull request\n\n## \ud83d\udcd6 Additional Resources\n\n### Video Tutorials\n- [Basic Excel Report Creation](https://example.com/basic-tutorial)\n- [Advanced Styling Techniques](https://example.com/advanced-tutorial)\n- [Persian Date Integration](https://example.com/persian-dates)\n\n### Community Examples\n- [GitHub Examples Repository](https://github.com/7nimor/excelstyler-examples)\n- [Stack Overflow Tag](https://stackoverflow.com/questions/tagged/excelstyler)\n\n### Related Projects\n- [openpyxl](https://openpyxl.readthedocs.io/) - The underlying Excel library\n- [jdatetime](https://github.com/slashmili/python-jalali) - Persian date library\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! Here's how you can help:\n\n### Reporting Issues\n1. Check existing issues first\n2. Provide detailed reproduction steps\n3. Include Python and excelstyler versions\n4. Attach sample code if possible\n\n### Submitting Pull Requests\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Add tests for your changes\n4. Ensure all tests pass (`pytest`)\n5. Commit your changes (`git commit -m 'Add amazing feature'`)\n6. Push to the branch (`git push origin feature/amazing-feature`)\n7. Open a Pull Request\n\n### Development Setup\n```bash\n# Clone the repository\ngit clone https://github.com/7nimor/excelstyler.git\ncd excelstyler\n\n# Install in development mode\npip install -e .\n\n# Install test dependencies\npip install -e \".[test]\"\n\n# Run tests\npytest\n\n# Run linting\nflake8 src/ tests/\n```\n\n## \ud83d\udcca Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for detailed version history.\n\n## \ud83c\udfc6 Acknowledgments\n\n- Thanks to the [openpyxl](https://openpyxl.readthedocs.io/) team for the excellent Excel library\n- Thanks to the [jdatetime](https://github.com/slashmili/python-jalali) team for Persian date support\n- Thanks to all contributors and users who help improve this library\n\n## \ud83d\udcde Support\n\n- **Documentation**: [Read the docs](https://excelstyler.readthedocs.io/)\n- **Issues**: [GitHub Issues](https://github.com/7nimor/excelstyler/issues)\n- **Discussions**: [GitHub Discussions](https://github.com/7nimor/excelstyler/discussions)\n- **Email**: 7nimor@gmail.com\n\n## \u2b50 Star History\n\n[](https://star-history.com/#7nimor/excelstyler&Date)\n\n## \ud83d\udcc4 License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n---\n\n<div align=\"center\">\n\n**Made with \u2764\ufe0f for the Persian/Farsi developer community**\n\n[](https://github.com/7nimor/excelstyler)\n[](https://github.com/7nimor/excelstyler)\n[](https://github.com/7nimor/excelstyler)\n\n</div>\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Nima Orangi\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.",
"summary": "Style and format Excel files easily with openpyxl",
"version": "0.1.3",
"project_urls": {
"Homepage": "https://github.com/7nimor/excelstyler"
},
"split_keywords": [
"excel",
" farsi",
" iranian",
" jdatetime",
" openpyxl",
" persian",
" report",
" shamsi",
" spreadsheet",
" styling",
" xlsx"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "6df683c6a23460c2d818f7d8d30f45c8777762acff4fa9790d05e0f941fc7ae8",
"md5": "f6e0dff4a5148a6386dad2ee334a91c8",
"sha256": "b421290960704c2f4f4ca9b7305af89625b4f5568a280ec3d2507794ed8534cb"
},
"downloads": -1,
"filename": "excelstyler-0.1.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f6e0dff4a5148a6386dad2ee334a91c8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 19335,
"upload_time": "2025-10-28T07:32:20",
"upload_time_iso_8601": "2025-10-28T07:32:20.607685Z",
"url": "https://files.pythonhosted.org/packages/6d/f6/83c6a23460c2d818f7d8d30f45c8777762acff4fa9790d05e0f941fc7ae8/excelstyler-0.1.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5047c828b94cf048cc036c513cf36f1708ee29ad9287d6fc09069960c6ed0f84",
"md5": "c3db9b95b8fcde83ba811315f5c49553",
"sha256": "d87cb8cd66c5b384abddf02fe0519277bbffb8be98201d57ebbbde1a4a5dc7c5"
},
"downloads": -1,
"filename": "excelstyler-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "c3db9b95b8fcde83ba811315f5c49553",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 29258,
"upload_time": "2025-10-28T07:32:21",
"upload_time_iso_8601": "2025-10-28T07:32:21.683513Z",
"url": "https://files.pythonhosted.org/packages/50/47/c828b94cf048cc036c513cf36f1708ee29ad9287d6fc09069960c6ed0f84/excelstyler-0.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-28 07:32:21",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "7nimor",
"github_project": "excelstyler",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "excelstyler"
}