-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcsv2excel.py
More file actions
160 lines (129 loc) · 5.15 KB
/
Copy pathcsv2excel.py
File metadata and controls
160 lines (129 loc) · 5.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import os
import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
class ConverterApp:
def __init__(self, root):
self.root = root
self.root.title("CSV to Excel Converter")
self.root.geometry("440x280")
self.root.resizable(False, False)
self.file_path = None
self.df = None
# Upload button
tk.Button(
root,
text="Upload CSV",
width=30,
command=self.upload_file
).pack(pady=15)
# Selected file label
self.file_label = tk.Label(
root,
text="No file selected",
fg="gray"
)
self.file_label.pack()
# Convert button
self.convert_btn = tk.Button(
root,
text="Convert to Excel",
width=30,
state=tk.DISABLED,
command=self.convert_file
)
self.convert_btn.pack(pady=25)
def upload_file(self):
self.file_path = filedialog.askopenfilename(
title="Select CSV file",
filetypes=[
("CSV files", "*.csv"),
]
)
if not self.file_path:
return
self.file_label.config(
text=os.path.basename(self.file_path),
fg="black"
)
try:
self.df = pd.read_csv(self.file_path, dtype=str)
# ---- AUTO ADD No COLUMN IF MISSING ----
if "No" not in self.df.columns and "No." not in self.df.columns:
self.df.insert(0, "No", range(1, len(self.df) + 1))
# ---- amount: FORCE 2 DECIMAL PLACES + THOUSANDS ----
if "amount" in self.df.columns:
self.df["amount"] = (
self.df["amount"]
.astype(str)
.str.replace(",", "", regex=False)
.apply(lambda x: f"{float(x):,.2f}" if x not in ("nan", "", "None") else "0.00")
)
self.convert_btn.config(state=tk.NORMAL)
except Exception as e:
messagebox.showerror("Error", str(e))
def convert_file(self):
save_path = filedialog.asksaveasfilename(
title="Save Excel file",
defaultextension=".xlsx",
filetypes=[("Excel files", "*.xlsx")]
)
if not save_path:
return
try:
wb = Workbook()
ws = wb.active
ws.title = "Data"
# ---- STYLES ----
header_font = Font(name="Calibri", bold=True, color="FFFFFF", size=11)
header_fill = PatternFill(fill_type="solid", fgColor="2F75B6")
header_align = Alignment(horizontal="center", vertical="center", wrap_text=True)
data_font = Font(name="Calibri", size=11)
data_align_center = Alignment(horizontal="center", vertical="center")
data_align_right = Alignment(horizontal="right", vertical="center")
alt_fill = PatternFill(fill_type="solid", fgColor="DDEBF7")
thin = Side(style="thin", color="BFBFBF")
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# ---- HEADER ROW ----
headers = list(self.df.columns)
for col_idx, col_name in enumerate(headers, start=1):
cell = ws.cell(row=1, column=col_idx, value=col_name)
cell.font = header_font
cell.fill = header_fill
cell.alignment = header_align
cell.border = border
# ---- DATA ROWS ----
amount_col = headers.index("amount") + 1 if "amount" in headers else None
for row_idx, row in enumerate(self.df.itertuples(index=False), start=2):
fill = alt_fill if row_idx % 2 == 0 else None
for col_idx, value in enumerate(row, start=1):
cell = ws.cell(row=row_idx, column=col_idx, value=value)
cell.font = data_font
cell.border = border
if col_idx == amount_col:
cell.alignment = data_align_right
else:
cell.alignment = data_align_center
if fill:
cell.fill = fill
# ---- COLUMN WIDTHS ----
for col_idx, col_name in enumerate(headers, start=1):
values = [len(str(v)) for v in self.df.iloc[:, col_idx - 1]]
max_len = max([len(str(col_name))] + values) if values else len(str(col_name))
ws.column_dimensions[get_column_letter(col_idx)].width = min(max_len + 4, 40)
# ---- FREEZE HEADER ----
ws.freeze_panes = "A2"
wb.save(save_path)
messagebox.showinfo(
"Success",
"File converted successfully!"
)
except Exception as e:
messagebox.showerror("Error", str(e))
if __name__ == "__main__":
root = tk.Tk()
app = ConverterApp(root)
root.mainloop()