## ¿Qué es CSV y por qué convertirlo?
**CSV** (Comma-Separated Values) es texto plano con datos tabulares separados por coma (o punto y coma). Sus limitaciones: sin tipos de datos, sin formato, sin múltiples hojas, sin fórmulas.
## CSV a Excel (pandas)
```python
import pandas as pd
# Básico
df = pd.read_csv("datos.csv", encoding="utf-8")
df.to_excel("datos.xlsx", index=False)
# Múltiples hojas
with pd.ExcelWriter("reporte.xlsx", engine="openpyxl") as writer:
df_ventas.to_excel(writer, sheet_name="Ventas", index=False)
df_clientes.to_excel(writer, sheet_name="Clientes", index=False)
# CSV con punto y coma (español)
df = pd.read_csv("datos.csv", sep=";", encoding="latin-1")
```
## CSV a Excel con formato (openpyxl)
```python
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
import csv
wb = Workbook()
ws = wb.active
header_font = Font(bold=True, color="FFFFFF")
header_fill = PatternFill(start_color="1F4E79", end_color="1F4E79", fill_type="solid")
with open("datos.csv", "r", encoding="utf-8") as f:
for row_idx, row in enumerate(csv.reader(f), 1):
for col_idx, value in enumerate(row, 1):
cell = ws.cell(row=row_idx, column=col_idx, value=value)
if row_idx == 1:
cell.font = header_font
cell.fill = header_fill
for col in ws.columns:
max_len = max(len(str(cell.value or "")) for cell in col)
ws.column_dimensions[col[0].column_letter].width = min(max_len + 2, 50)
wb.save("datos_formateados.xlsx")
```
## CSV a JSON
```python
import csv, json
def csv_to_json(csv_path, json_path, delimiter=","):
with open(csv_path, "r", encoding="utf-8") as f:
data = []
for row in csv.DictReader(f, delimiter=delimiter):
clean = {}
for key, value in row.items():
try:
clean[key] = int(value)
except ValueError:
try:
clean[key] = float(value)
except ValueError:
clean[key] = value
data.append(clean)
with open(json_path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"Convertidos {len(data)} registros")
csv_to_json("ventas.csv", "ventas.json")
```
## CSV a XML
```python
import csv, xml.etree.ElementTree as ET
from xml.dom import minidom
def csv_to_xml(csv_path, xml_path, root_tag="datos", row_tag="registro"):
root = ET.Element(root_tag)
with open(csv_path, "r", encoding="utf-8") as f:
for row in csv.DictReader(f):
item = ET.SubElement(root, row_tag)
for key, value in row.items():
if key:
ET.SubElement(item, key.replace(" ", "_")).text = str(value)
xml_str = minidom.parseString(ET.tostring(root)).toprettyxml(indent=" ")
with open(xml_path, "w", encoding="utf-8") as f:
f.write(xml_str)
```
## Limpieza de datos
```python
import pandas as pd
df = pd.read_csv("datos_sucios.csv")
df = df.dropna(how="all")
df["precio"] = df["precio"].fillna(0)
df["nombre"] = df["nombre"].str.strip()
df["fecha"] = pd.to_datetime(df["fecha"], dayfirst=True)
df = df.drop_duplicates(subset=["id"])
df.to_excel("datos_limpios.xlsx", index=False)
df.to_json("datos_limpios.json", orient="records", force_ascii=False, indent=2)
```
## Conversión masiva (batch)
```python
import pathlib, pandas as pd
output_dir = pathlib.Path("excels/")
output_dir.mkdir(exist_ok=True)
for csv_file in pathlib.Path("csvs/").glob("*.csv"):
try:
df = pd.read_csv(csv_file)
output = output_dir / csv_file.with_suffix(".xlsx").name
df.to_excel(output, index=False)
print(f"OK: {csv_file.name} ({len(df)} filas)")
except Exception as e:
print(f"ERROR: {csv_file.name} - {e}")
```
## Conclusión
**Python con pandas** es la solución más completa para convertir CSV a Excel, JSON o XML. Para conversiones simples: dos líneas. Para necesidades avanzadas (formato, múltiples hojas, limpieza): openpyxl y manipulación directa del DataFrame.
Guía