Freedom Sale
Independence Day Special — Unlock the AI Path 70% off our most popular AI course · Limited time offer
--Days
--Hrs
--Min
--Sec
Claim Your Discount
✦ Beginner ⏱ 25 min

📊 Build a CSV to Excel Converter with Python

🎯 What You'll Build

A Python tool that converts any CSV file into a formatted Excel spreadsheet — with styled headers, auto-column widths, number formatting, and conditional highlighting.

📋 What You'll Need

1

Basic CSV to Excel conversion

Read a CSV with pandas and write it to Excel in two lines.

import pandas as pd

df = pd.read_csv('sales_data.csv')
df.to_excel('sales_data.xlsx', index=False)
print("Converted! Open sales_data.xlsx")
2

Style the Excel file with openpyxl

Add coloured headers, bold fonts, auto-column widths, and number formatting.

import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter

def csv_to_excel_styled(csv_path, xlsx_path):
    df = pd.read_csv(csv_path)
    df.to_excel(xlsx_path, index=False)

    wb = load_workbook(xlsx_path)
    ws = wb.active

    # Style header row
    header_fill = PatternFill('solid', fgColor='162447')
    header_font = Font(bold=True, color='FFFFFF', size=11)
    thin = Side(style='thin', color='DDDDDD')
    border = Border(left=thin, right=thin, top=thin, bottom=thin)

    for cell in ws[1]:
        cell.fill      = header_fill
        cell.font      = header_font
        cell.alignment = Alignment(horizontal='center', vertical='center')
        cell.border    = border

    ws.row_dimensions[1].height = 28

    # Auto-fit column widths
    for col_idx, col in enumerate(ws.columns, 1):
        max_len = 0
        for cell in col:
            try:
                max_len = max(max_len, len(str(cell.value or '')))
            except:
                pass
        ws.column_dimensions[get_column_letter(col_idx)].width = min(max_len + 4, 40)

    # Zebra-stripe data rows
    light = PatternFill('solid', fgColor='F8FAFC')
    for row in ws.iter_rows(min_row=2):
        if row[0].row % 2 == 0:
            for cell in row:
                cell.fill = light

    # Freeze header row
    ws.freeze_panes = 'A2'

    wb.save(xlsx_path)
    print(f"Styled Excel saved: {xlsx_path}  ({df.shape[0]} rows, {df.shape[1]} columns)")

csv_to_excel_styled('sales_data.csv', 'sales_report.xlsx')
Styled Excel saved: sales_report.xlsx  (500 rows, 6 columns)
3

Highlight cells based on values

Colour cells green/red based on whether a value meets a threshold.

from openpyxl.styles import PatternFill

GREEN = PatternFill('solid', fgColor='DCFCE7')
RED   = PatternFill('solid', fgColor='FEE2E2')

# After loading the workbook, find the 'growth' column
headers = [cell.value for cell in ws[1]]
if 'growth' in headers:
    col_idx = headers.index('growth') + 1
    for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx):
        for cell in row:
            try:
                val = float(str(cell.value).replace('%',''))
                cell.fill = GREEN if val > 0 else RED
            except:
                pass

wb.save(xlsx_path)
print("Conditional formatting applied!")
💡 Tip: openpyxl can also read Excel files — use load_workbook("file.xlsx") to extract data from existing spreadsheets. This makes it great for automating monthly reports that need to be updated in place.

🎉 You Did It!

You automated a task that most people do manually in Excel every week. Combine this with the uptime monitor or sales dashboard to auto-generate and email a formatted report every morning.

Found something wrong?

Spotted a bug, broken code, or something that doesn't look right? Tell us what's off and we'll fix it.