DEV Community

Mate Technologies
Mate Technologies

Posted on

πŸš€ Build a CSV to Excel Desktop App (PySide6 + SQLite)

πŸ”— GitHub Repo: https://github.com/rogers-cyber/CSVtoExcel

In this tutorial, you’ll learn how to build a modern desktop app that:

Converts CSV β†’ Excel (.xlsx)

Shows a preview of data

Saves history using SQLite

Supports batch processing

🧱 Step 1 β€” Install Dependencies

First, install required packages:

pip install PySide6 xlsxwriter
Enter fullscreen mode Exit fullscreen mode

🧠 Step 2 β€” Project Structure

Create a simple structure:

csv_to_excel_app/
β”‚
β”œβ”€β”€ main.py
└── logo.ico (optional)
βš™οΈ Step 3 β€” Basic App Setup

Let’s create a minimal PySide6 app window.

import sys
from PySide6 import QtWidgets

app = QtWidgets.QApplication(sys.argv)

window = QtWidgets.QMainWindow()
window.setWindowTitle("CSVtoExcel")
window.resize(800, 500)

window.show()
sys.exit(app.exec())
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ This gives you a blank desktop window.

πŸ—‚ Step 4 β€” Create App Data Folder

We store history (SQLite DB) in a system-safe location.

from pathlib import Path
import os
import sys

def get_app_dir() -> Path:
    if sys.platform.startswith("win"):
        base = Path(os.getenv('LOCALAPPDATA') or Path.home())
    elif sys.platform.startswith("darwin"):
        base = Path.home() / 'Library/Application Support'
    else:
        base = Path.home() / '.local/share'

    app_dir = base / "csv_to_excel_app"
    app_dir.mkdir(parents=True, exist_ok=True)
    return app_dir
Enter fullscreen mode Exit fullscreen mode

πŸ—„ Step 5 β€” Setup SQLite Database

We store conversion history.

import sqlite3

DB_PATH = get_app_dir() / "history.db"

def init_db():
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()

    c.execute("""
        CREATE TABLE IF NOT EXISTS history(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            src_path TEXT,
            dest_path TEXT,
            timestamp TEXT,
            rows INTEGER,
            cols INTEGER
        )
    """)

    conn.commit()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Call this once when the app starts.

πŸ“₯ Step 6 β€” Load CSV File

Let users pick a CSV file.

from PySide6.QtWidgets import QFileDialog

def open_csv():
    file, _ = QFileDialog.getOpenFileName(
        None,
        "Open CSV",
        "",
        "CSV Files (*.csv)"
    )
    return file
Enter fullscreen mode Exit fullscreen mode

πŸ‘ Step 7 β€” Preview CSV Data

We read first 100 rows.

import csv

def preview_csv(path, limit=100):
    rows = []

    with open(path, encoding="utf-8", errors="replace") as f:
        reader = csv.reader(f)
        for i, row in enumerate(reader):
            if i >= limit:
                break
            rows.append(row)

    return rows
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ This keeps the app fast even with large files.

πŸ“Š Step 8 β€” Convert CSV β†’ Excel

Now the core feature πŸ”₯

import xlsxwriter

def convert_to_excel(csv_path, output_path):
    with open(csv_path, encoding="utf-8", errors="replace") as f:
        reader = csv.reader(f)
        rows = list(reader)

    workbook = xlsxwriter.Workbook(output_path, {'strings_to_urls': False})
    sheet = workbook.add_worksheet()

    for r, row in enumerate(rows):
        for c, value in enumerate(row):
            sheet.write(r, c, value)

    workbook.close()
Enter fullscreen mode Exit fullscreen mode

🧾 Step 9 β€” Save History

Every conversion is stored.

from datetime import datetime

def save_history(src, dest, rows, cols):
    conn = sqlite3.connect(DB_PATH)
    c = conn.cursor()

    c.execute(
        "INSERT INTO history (src_path, dest_path, timestamp, rows, cols) VALUES (?, ?, ?, ?, ?)",
        (src, dest, datetime.utcnow().isoformat(), rows, cols)
    )

    conn.commit()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

🧡 Step 10 β€” Run Conversion in Background

We avoid freezing the UI using threads.

from PySide6.QtCore import QRunnable, QThreadPool

class Worker(QRunnable):
    def __init__(self, csv_path, output):
        super().__init__()
        self.csv_path = csv_path
        self.output = output

    def run(self):
        convert_to_excel(self.csv_path, self.output)
Enter fullscreen mode Exit fullscreen mode

Run it:

pool = QThreadPool()
pool.start(Worker("input.csv", "output.xlsx"))
Enter fullscreen mode Exit fullscreen mode

πŸ–₯ Step 11 β€” Build UI Layout

Add buttons + table preview.

layout = QtWidgets.QVBoxLayout()

btn_open = QtWidgets.QPushButton("Open CSV")
btn_convert = QtWidgets.QPushButton("Convert")

table = QtWidgets.QTableWidget()

layout.addWidget(btn_open)
layout.addWidget(btn_convert)
layout.addWidget(table)
Enter fullscreen mode Exit fullscreen mode

🎨 Step 12 β€” Add Styling (QSS)

app.setStyleSheet("""
QPushButton {
    background: #1976d2;
    color: white;
    padding: 6px;
    border-radius: 6px;
}
QPushButton:hover {
    background: #125aa0;
}
""")
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ Step 13 β€” Build EXE (Optional)

Use PyInstaller:

pip install pyinstaller
pyinstaller --onefile --windowed main.py
Enter fullscreen mode Exit fullscreen mode

πŸŽ‰ Final Result

You now have a desktop app that:

βœ… Converts CSV to Excel
βœ… Handles large files
βœ… Saves history
βœ… Has a modern UI

πŸ’‘ Pro Tips

Add drag & drop support

Add batch folder conversion

Add encoding selector

Add preview table model (QTableView)

πŸ”— Full Source Code

πŸ‘‰ https://github.com/rogers-cyber/CSVtoExcel

Top comments (0)