Added all
This commit is contained in:
9
file-management/buscar_grandes.sh
Normal file
9
file-management/buscar_grandes.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Directorio base desde donde buscar (puedes cambiarlo o usar el argumento del script)
|
||||
DIRECTORIO=${1:-.}
|
||||
|
||||
# Encuentra archivos mayores a 1GB y muestra su tamaño ordenado
|
||||
echo "Archivos mayores a 1GB en el directorio: $DIRECTORIO"
|
||||
find "$DIRECTORIO" -type f -size +1G -exec du -h {} + | sort -hr
|
||||
echo "Búsqueda completada."
|
||||
57
file-management/filtrar_excel_per_csv.py
Normal file
57
file-management/filtrar_excel_per_csv.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import pandas as pd
|
||||
import os
|
||||
import sys
|
||||
|
||||
print("🔍 --- Filtrant Excel segons usuaris actius del CSV ---")
|
||||
|
||||
# Noms dels fitxers
|
||||
fitxer_csv = "Newsletter_Combinat_Final_Actius.csv"
|
||||
fitxer_excel = "Contactos_Unificats.xlsx"
|
||||
fitxer_resultat = "Contactos_Unificats_Filtrats.xlsx"
|
||||
|
||||
# Comprovem que existeixen
|
||||
if not os.path.exists(fitxer_csv) or not os.path.exists(fitxer_excel):
|
||||
print("❌ Error: Assegura't que els fitxers CSV i Excel són a la mateixa carpeta.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print("⏳ Llegint els usuaris actius del CSV...")
|
||||
# Llegim el CSV (sabem que està separat per punt i coma)
|
||||
df_csv = pd.read_csv(fitxer_csv, sep=';', encoding='utf-8')
|
||||
|
||||
# Extraiem els correus de la columna 'Email_ID', els passem a minúscules i traiem espais en blanc
|
||||
# per assegurar-nos que coincideixen perfectament
|
||||
correus_actius = set(df_csv['Email_ID'].dropna().astype(str).str.lower().str.strip())
|
||||
print(f"✅ S'han carregat {len(correus_actius)} correus únics del CSV.")
|
||||
|
||||
print("⏳ Processant l'Excel pestanya per pestanya...")
|
||||
# Obrim l'Excel original i preparem el nou per escriure
|
||||
excel_original = pd.ExcelFile(fitxer_excel)
|
||||
|
||||
with pd.ExcelWriter(fitxer_resultat, engine='openpyxl') as writer:
|
||||
for nom_pestanya in excel_original.sheet_names:
|
||||
# Llegim la pestanya actual
|
||||
df_pestanya = pd.read_excel(excel_original, sheet_name=nom_pestanya)
|
||||
total_inicial = len(df_pestanya)
|
||||
|
||||
# Normalitzem la columna 'email' de l'Excel per poder comparar-la
|
||||
if 'email' in df_pestanya.columns:
|
||||
correus_excel = df_pestanya['email'].astype(str).str.lower().str.strip()
|
||||
|
||||
# Filtrem: ens quedem només amb les files on el correu estigui a la nostra llista d'actius
|
||||
df_filtrat = df_pestanya[correus_excel.isin(correus_actius)]
|
||||
total_final = len(df_filtrat)
|
||||
|
||||
print(f" 👉 Pestanya '{nom_pestanya}': s'han mantingut {total_final} de {total_inicial} contactes.")
|
||||
else:
|
||||
print(f" ⚠️ Avís: La pestanya '{nom_pestanya}' no té cap columna anomenada 'email'. Es deixa intacta.")
|
||||
df_filtrat = df_pestanya
|
||||
|
||||
# Guardem el resultat a la mateixa pestanya del nou fitxer
|
||||
df_filtrat.to_excel(writer, sheet_name=nom_pestanya, index=False)
|
||||
|
||||
print(f"\n🎉 Procés completat amb èxit!")
|
||||
print(f"📄 S'ha creat el fitxer amb els contactes filtrats: {fitxer_resultat}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ S'ha produït un error: {e}")
|
||||
67
file-management/juntar_csv.py
Normal file
67
file-management/juntar_csv.py
Normal file
@@ -0,0 +1,67 @@
|
||||
import csv
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
# 1. Comprovem si s'ha passat la ruta com a argument
|
||||
if len(sys.argv) < 2:
|
||||
print("❌ Error: Has d'indicar la ruta de la carpeta.")
|
||||
print("💡 Ús correcte: python juntar_csv.py /ruta/de/la/carpeta")
|
||||
sys.exit(1)
|
||||
|
||||
# 2. Agafem la ruta (el primer argument després del nom de l'script)
|
||||
carpeta_origen = sys.argv[1]
|
||||
|
||||
# Netegem possibles cometes que la terminal hagi afegit
|
||||
carpeta_origen = carpeta_origen.strip("'").strip('"').strip()
|
||||
|
||||
# 3. Comprovem que la carpeta existeix
|
||||
if not os.path.isdir(carpeta_origen):
|
||||
print(f"❌ Error: La ruta '{carpeta_origen}' no és vàlida o no és una carpeta.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"📁 Cercant fitxers CSV a: {carpeta_origen}")
|
||||
|
||||
ruta_cerca = os.path.join(carpeta_origen, "*.csv")
|
||||
fitxers_csv = glob.glob(ruta_cerca)
|
||||
|
||||
# Definim el nom del fitxer final
|
||||
fitxer_resultat = os.path.join(carpeta_origen, "Newsletter_Combinat_Final.csv")
|
||||
|
||||
if not fitxers_csv:
|
||||
print("⚠️ No s'han trobat fitxers CSV a la carpeta indicada.")
|
||||
else:
|
||||
# Filtrem per no incloure el fitxer resultat si ja existeix d'una execució anterior
|
||||
fitxers_a_processar = [f for f in fitxers_csv if f != fitxer_resultat]
|
||||
|
||||
if not fitxers_a_processar:
|
||||
print("⚠️ Només s'ha trobat el fitxer combinat anterior. No hi ha res de nou per unir.")
|
||||
sys.exit(0)
|
||||
|
||||
print(f"🔄 S'han trobat {len(fitxers_a_processar)} fitxers. Processant...")
|
||||
|
||||
# 4. Unifiquem els fitxers
|
||||
with open(fitxer_resultat, 'w', newline='', encoding='utf-8') as sortida:
|
||||
escrivent = csv.writer(sortida, delimiter=';')
|
||||
|
||||
fitxers_processats = 0
|
||||
for nom_fitxer in fitxers_a_processar:
|
||||
with open(nom_fitxer, 'r', encoding='utf-8') as f:
|
||||
lector = csv.reader(f, delimiter=';')
|
||||
try:
|
||||
capcalera = next(lector)
|
||||
except StopIteration:
|
||||
continue # Saltem el fitxer si està completament buit
|
||||
|
||||
# Escrivim la capçalera només pel primer fitxer vàlid
|
||||
if fitxers_processats == 0:
|
||||
escrivent.writerow(capcalera)
|
||||
|
||||
# Escrivim la resta de dades
|
||||
for fila in lector:
|
||||
escrivent.writerow(fila)
|
||||
|
||||
fitxers_processats += 1
|
||||
|
||||
print(f"✅ Èxit! S'han combinat {fitxers_processats} fitxers.")
|
||||
print(f"📄 Fitxer creat a: {fitxer_resultat}")
|
||||
73
file-management/mautic.py
Normal file
73
file-management/mautic.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import pandas as pd
|
||||
import csv
|
||||
|
||||
def filtrar_i_consolidar_etiquetes(tags_str):
|
||||
"""Filtra i agrupa les etiquetes segons les regles de negoci."""
|
||||
if pd.isna(tags_str) or str(tags_str).strip().lower() == 'nan':
|
||||
return ''
|
||||
|
||||
# 1. Separem les etiquetes i les netegem
|
||||
llista_tags = [t.strip().lower() for t in str(tags_str).split(',')]
|
||||
|
||||
# Utilitzem un 'set' per evitar etiquetes duplicades al final
|
||||
tags_finals = set()
|
||||
|
||||
for t in llista_tags:
|
||||
# 2. Regla de conservació directa: test_, int_ i rrhh
|
||||
if t.startswith('test_') or t.startswith('int_') or t == 'rrhh':
|
||||
tags_finals.add(t)
|
||||
continue
|
||||
|
||||
# 3. Regles d'agrupació (l'ordre és important per als prefixos llargs)
|
||||
if t.startswith('skupspo2-') or t.startswith('pspo2-'):
|
||||
tags_finals.add('pspo2')
|
||||
elif t.startswith('pspo-'):
|
||||
tags_finals.add('pspo')
|
||||
elif t.startswith('psm2-'):
|
||||
tags_finals.add('psm2')
|
||||
elif t.startswith('psm-'):
|
||||
tags_finals.add('psm')
|
||||
elif t.startswith('psux-') or t.startswith('psu-'):
|
||||
tags_finals.add('psu')
|
||||
elif t.startswith('sps-'):
|
||||
tags_finals.add('sps')
|
||||
elif t.startswith('safe-'):
|
||||
tags_finals.add('safe-ls')
|
||||
elif t.startswith('pal_ebm-'):
|
||||
tags_finals.add('pal_ebm')
|
||||
elif t.startswith('pal-'):
|
||||
tags_finals.add('pal')
|
||||
|
||||
# 4. Si tenim etiquetes vàlides, les ordenem, les unim amb | i hi posem cometes
|
||||
if tags_finals:
|
||||
# Ordenar-les (sorted) fa que el resultat sigui més fàcil de llegir al CSV
|
||||
tags_units = '|'.join(sorted(list(tags_finals)))
|
||||
return f'"{tags_units}"'
|
||||
else:
|
||||
return ''
|
||||
|
||||
# --- INICI DEL PROCÉS ---
|
||||
|
||||
# 1. Carregar el fitxer original
|
||||
df = pd.read_excel('contactes_mautic/Contactos_2602026_7881pax.xlsx')
|
||||
|
||||
# 2. Seleccionar només les columnes que ens interessen
|
||||
columnes_mautic = ['email', 'nombre_x', 'apellidos_x', '*ciudad_x', '*pais_x', 'etiquetas_x']
|
||||
df_net = df[columnes_mautic].copy()
|
||||
|
||||
# 3. Reanomenar les columnes perquè Mautic les auto-detecti
|
||||
df_net.rename(columns={
|
||||
'nombre_x': 'firstname',
|
||||
'apellidos_x': 'lastname',
|
||||
'*ciudad_x': 'city',
|
||||
'*pais_x': 'country',
|
||||
'etiquetas_x': 'etiquetes'
|
||||
}, inplace=True)
|
||||
|
||||
# 4. APLICAR EL FILTRE I LA CONSOLIDACIÓ
|
||||
df_net['etiquetes'] = df_net['etiquetes'].apply(filtrar_i_consolidar_etiquetes)
|
||||
|
||||
# 5. Guardar com a CSV llest per importar
|
||||
df_net.to_csv('Contactes_Mautic_Consolidats.csv', index=False, encoding='utf-8', quoting=csv.QUOTE_NONE, escapechar='\\')
|
||||
|
||||
print("✅ Fitxer preparat! Les etiquetes s'han filtrat i agrupat correctament.")
|
||||
84
file-management/mautic_tags.py
Normal file
84
file-management/mautic_tags.py
Normal file
@@ -0,0 +1,84 @@
|
||||
import pandas as pd
|
||||
import os
|
||||
import csv
|
||||
|
||||
def simplificar_etiqueta(tag):
|
||||
"""Filtra i redueix les etiquetes a la seva essència."""
|
||||
tag = tag.strip().lower()
|
||||
|
||||
# 1. Traducció dels noms llargs oficials
|
||||
if 'professional-scrum-master' in tag: return 'psm'
|
||||
if 'professional-scrum-product-owner' in tag: return 'pspo'
|
||||
if 'professional-scrum-developer' in tag: return 'psd'
|
||||
if 'professional-agile-leadership' in tag: return 'pal'
|
||||
|
||||
# 2. Protecció de nivells avançats (Molt important posar-ho abans que els normals)
|
||||
if 'psm2' in tag or 'psm-2' in tag: return 'psm2'
|
||||
if 'pspo2' in tag or 'pspo-2' in tag: return 'pspo2'
|
||||
if 'pspo-a' in tag: return 'pspo-a'
|
||||
|
||||
# 3. Agrupació per paraula clau (Si conté la paraula, s'assigna a l'etiqueta base)
|
||||
if 'psm' in tag: return 'psm'
|
||||
if 'pspo' in tag: return 'pspo'
|
||||
if 'psu' in tag: return 'psu'
|
||||
if 'psd' in tag: return 'psd'
|
||||
if 'aps' in tag: return 'aps'
|
||||
if 'apk' in tag: return 'apk'
|
||||
if 'pal' in tag: return 'pal'
|
||||
if 'sps' in tag: return 'sps'
|
||||
|
||||
# 4. Altres agrupacions útils que he detectat a la teva llista
|
||||
if 'okr' in tag: return 'okr'
|
||||
if 'scrumday' in tag or 'sd20' in tag or 'sd21' in tag: return 'scrumday'
|
||||
|
||||
# 5. Si no és cap de les importants, la deixem tal qual (però neta de test_)
|
||||
if tag.startswith('test_'):
|
||||
return tag.replace('test_', 'int_', 1)
|
||||
|
||||
return tag
|
||||
|
||||
# --- INICI DEL PROCÉS ---
|
||||
|
||||
nom_fitxer = 'contactes_mautic/Contactos_2602026_7881pax.xlsx'
|
||||
print(f"Llegint el fitxer {nom_fitxer}...")
|
||||
df = pd.read_excel(nom_fitxer)
|
||||
|
||||
columnes = {
|
||||
'email': 'email',
|
||||
'nombre_x': 'firstname',
|
||||
'apellidos_x': 'lastname',
|
||||
'*ciudad_x': 'city',
|
||||
'*pais_x': 'country',
|
||||
'etiquetas_x': 'tags'
|
||||
}
|
||||
df_net = df[list(columnes.keys())].rename(columns=columnes)
|
||||
df_net = df_net.dropna(subset=['email', 'tags'])
|
||||
|
||||
carpeta_sortida = 'Mautic_CSVs_per_Tag'
|
||||
os.makedirs(carpeta_sortida, exist_ok=True)
|
||||
|
||||
# Apliquem la nostra súper funció de simplificació
|
||||
df_net['tag_individual'] = df_net['tags'].apply(
|
||||
lambda x: [simplificar_etiqueta(tag) for tag in str(x).split(',') if tag.strip()]
|
||||
)
|
||||
|
||||
# Expandim i eliminem duplicats
|
||||
df_exploded = df_net.explode('tag_individual')
|
||||
df_exploded = df_exploded.drop_duplicates(subset=['email', 'tag_individual'])
|
||||
|
||||
etiquetes_uniques = df_exploded['tag_individual'].unique()
|
||||
print(f"🎉 Màgia feta! Hem reduït centenars d'etiquetes a només {len(etiquetes_uniques)} úniques.")
|
||||
|
||||
for tag in etiquetes_uniques:
|
||||
df_tag = df_exploded[df_exploded['tag_individual'] == tag].copy()
|
||||
|
||||
df_tag['tags'] = tag
|
||||
df_tag = df_tag.rename(columns={'tags': tag})
|
||||
df_tag = df_tag.drop(columns=['tag_individual'])
|
||||
|
||||
nom_tag_net = str(tag).replace(' ', '_').replace('/', '_').replace(':', '')
|
||||
ruta_fitxer = os.path.join(carpeta_sortida, f"etiqueta_{nom_tag_net}.csv")
|
||||
|
||||
df_tag.to_csv(ruta_fitxer, index=False, encoding='utf-8', sep=',', quoting=csv.QUOTE_ALL)
|
||||
|
||||
print(f"✅ Tots els fitxers nets estan a la carpeta '{carpeta_sortida}'.")
|
||||
17
file-management/nan-mautic.py
Normal file
17
file-management/nan-mautic.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import pandas as pd
|
||||
|
||||
# 1. Carregar el fitxer original
|
||||
df = pd.read_excel('contactes_mautic/Contactos_2602026_7881pax.xlsx')
|
||||
|
||||
# 2. Quedar-nos només amb els emails vàlids
|
||||
df_net = df.dropna(subset=['email'])[['email']].copy()
|
||||
|
||||
# 3. Ordre d'esborrat múltiple
|
||||
# Afegim el signe '-' davant de l'etiqueta estranya i també del 'nan' normal
|
||||
# La 'r' al davant indica a Python que llegeixi les barres invertides literalment
|
||||
df_net['etiquetes'] = r'-\"-nan\"|-nan'
|
||||
|
||||
# 4. Guardem el CSV de manera natural (sense forçar paràmetres d'escapament)
|
||||
df_net.to_csv('Neteja_Definitiva_Tags.csv', index=False, encoding='utf-8')
|
||||
|
||||
print("✅ Fitxer preparat! Les etiquetes errònies s'han marcat per ser esborrades.")
|
||||
53
file-management/netejar_desuscrits.py
Normal file
53
file-management/netejar_desuscrits.py
Normal file
@@ -0,0 +1,53 @@
|
||||
import csv
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Comprovem que s'ha passat el fitxer com a argument
|
||||
if len(sys.argv) < 2:
|
||||
print("❌ Error: Has d'indicar la ruta del fitxer CSV.")
|
||||
print("💡 Ús correcte: python netejar_desuscrits.py /ruta/al/Newsletter_Combinat_Final.csv")
|
||||
sys.exit(1)
|
||||
|
||||
fitxer_origen = sys.argv[1].strip("'").strip('"').strip()
|
||||
|
||||
if not os.path.isfile(fitxer_origen):
|
||||
print(f"❌ Error: No s'ha trobat el fitxer '{fitxer_origen}'.")
|
||||
sys.exit(1)
|
||||
|
||||
fitxer_desti = fitxer_origen.replace(".csv", "_Actius.csv")
|
||||
|
||||
usuaris_eliminats = 0
|
||||
usuaris_actius = 0
|
||||
|
||||
print(f"🔍 Analitzant el fitxer: {fitxer_origen}")
|
||||
|
||||
with open(fitxer_origen, 'r', encoding='utf-8') as f_in, \
|
||||
open(fitxer_desti, 'w', newline='', encoding='utf-8') as f_out:
|
||||
|
||||
lector = csv.reader(f_in, delimiter=';')
|
||||
escrivent = csv.writer(f_out, delimiter=';')
|
||||
|
||||
# Llegim i escrivim la capçalera
|
||||
capcalera = next(lector)
|
||||
escrivent.writerow(capcalera)
|
||||
|
||||
# Busquem l'índex de la columna de desuscripció
|
||||
try:
|
||||
index_unsub = capcalera.index("Unsubscribe_Date")
|
||||
except ValueError:
|
||||
print("❌ Error: No s'ha trobat la columna 'Unsubscribe_Date' al fitxer.")
|
||||
sys.exit(1)
|
||||
|
||||
# Filtrem les files
|
||||
for fila in lector:
|
||||
# Si la columna està buida, l'usuari és actiu
|
||||
if len(fila) > index_unsub and not fila[index_unsub].strip():
|
||||
escrivent.writerow(fila)
|
||||
usuaris_actius += 1
|
||||
else:
|
||||
usuaris_eliminats += 1
|
||||
|
||||
print("✅ Neteja completada amb èxit!")
|
||||
print(f"📉 Usuaris desuscrits eliminats: {usuaris_eliminats}")
|
||||
print(f"📈 Usuaris actius conservats: {usuaris_actius}")
|
||||
print(f"📄 Nou fitxer creat a: {fitxer_desti}")
|
||||
32
file-management/netejar_excel.py
Normal file
32
file-management/netejar_excel.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import pandas as pd
|
||||
|
||||
# 1. Definir los nombres de los archivos
|
||||
archivo_entrada = 'Contactos_2602026_totales.xlsx'
|
||||
archivo_salida = 'Contactos_2602026_Limpios.xlsx'
|
||||
|
||||
print(f"Cargando el archivo: {archivo_entrada}...")
|
||||
|
||||
# 2. Leer el archivo Excel
|
||||
# Asumimos que los datos están en la primera hoja (Sheet1)
|
||||
df = pd.read_excel(archivo_entrada)
|
||||
|
||||
# Contar cuántos registros hay inicialmente
|
||||
total_inicial = len(df)
|
||||
print(f"Registros iniciales encontrados: {total_inicial}")
|
||||
|
||||
# 3. Eliminar duplicados basados en la columna 'email'
|
||||
# keep='first' conserva la primera aparición del correo y elimina las siguientes
|
||||
df_limpio = df.drop_duplicates(subset=['email'], keep='first')
|
||||
|
||||
# Contar cuántos registros quedaron y cuántos se eliminaron
|
||||
total_final = len(df_limpio)
|
||||
duplicados_eliminados = total_inicial - total_final
|
||||
|
||||
print(f"Se han eliminado {duplicados_eliminados} contactos duplicados.")
|
||||
print(f"Registros finales únicos: {total_final}")
|
||||
|
||||
# 4. Exportar el resultado a un nuevo archivo Excel
|
||||
print("Guardando el nuevo archivo limpio...")
|
||||
df_limpio.to_excel(archivo_salida, index=False)
|
||||
|
||||
print(f"¡Proceso completado! Archivo guardado como: {archivo_salida}")
|
||||
46
file-management/split_excel.py
Normal file
46
file-management/split_excel.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import math
|
||||
|
||||
# Load the Excel file
|
||||
file_name = 'Contactos_2602026_7881pax.xlsx'
|
||||
|
||||
print("Llegint el fitxer Excel...")
|
||||
|
||||
# --- CORRECCIÓ AQUÍ ---
|
||||
# Fem servir read_excel en lloc de read_csv
|
||||
df = pd.read_excel(file_name)
|
||||
# ----------------------
|
||||
|
||||
# Display head and info to understand the structure
|
||||
print(df.head())
|
||||
print(df.info())
|
||||
|
||||
# Total number of rows
|
||||
total_rows = len(df)
|
||||
print(f"Total rows: {total_rows}")
|
||||
|
||||
# Number of splits
|
||||
n = 6
|
||||
# Fem servir math.ceil o np.ceil per assegurar que no deixem files fora
|
||||
chunk_size = int(np.ceil(total_rows / n))
|
||||
|
||||
# Split and save
|
||||
output_files = []
|
||||
print(f"Dividint en {n} parts...")
|
||||
|
||||
for i in range(n):
|
||||
start_row = i * chunk_size
|
||||
end_row = min((i + 1) * chunk_size, total_rows)
|
||||
|
||||
# Si per algun motiu start_row supera el total, parem
|
||||
if start_row >= total_rows:
|
||||
break
|
||||
|
||||
chunk = df.iloc[start_row:end_row]
|
||||
|
||||
output_filename = f'Contactos_linkedin_part_{i+1}.xlsx'
|
||||
chunk.to_excel(output_filename, index=False)
|
||||
output_files.append(output_filename)
|
||||
|
||||
print(f"Files created: {output_files}")
|
||||
104
file-management/teams.py
Normal file
104
file-management/teams.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import pandas as pd
|
||||
import glob
|
||||
import re
|
||||
import os
|
||||
import csv
|
||||
|
||||
def extreure_minuts(temps_str):
|
||||
"""Converteix cadenes de text com '2h 15m', '45m' o '1h' a minuts totals."""
|
||||
if pd.isna(temps_str):
|
||||
return 0
|
||||
temps_str = str(temps_str).lower()
|
||||
hores = 0
|
||||
minuts = 0
|
||||
|
||||
match_h = re.search(r'(\d+)\s*h', temps_str)
|
||||
if match_h:
|
||||
hores = int(match_h.group(1))
|
||||
|
||||
match_m = re.search(r'(\d+)\s*m', temps_str)
|
||||
if match_m:
|
||||
minuts = int(match_m.group(1))
|
||||
|
||||
return (hores * 60) + minuts
|
||||
|
||||
fitxers = glob.glob("*.csv")
|
||||
dades_alumnes = {}
|
||||
|
||||
if not fitxers:
|
||||
print("⚠️ No s'han trobat fitxers CSV a la carpeta actual.")
|
||||
else:
|
||||
print(f"S'han trobat {len(fitxers)} fitxers. Processant dades...\n")
|
||||
|
||||
for fitxer in fitxers:
|
||||
try:
|
||||
# 1. Obrim el fitxer manualment per buscar a quina fila comencen les dades
|
||||
with open(fitxer, 'r', encoding='utf-16') as f:
|
||||
linies = f.readlines()
|
||||
|
||||
fila_capcalera = -1
|
||||
separador = '\t'
|
||||
|
||||
# Busquem la línia que conté "Nom" o "Nombre" o "Name"
|
||||
for i, linia in enumerate(linies):
|
||||
if 'Nom' in linia or 'Nombre' in linia or 'Name' in linia:
|
||||
fila_capcalera = i
|
||||
# Detectem si fa servir tabulacions o comes
|
||||
if ',' in linia and '\t' not in linia:
|
||||
separador = ','
|
||||
break
|
||||
|
||||
if fila_capcalera == -1:
|
||||
print(f"⚠️ Saltant '{fitxer}': No s'ha trobat cap fila amb la paraula 'Nom'.")
|
||||
continue
|
||||
|
||||
# 2. Llegim el CSV dient-li exactament on comença
|
||||
df = pd.read_csv(fitxer, sep=separador, encoding='utf-16', skiprows=fila_capcalera)
|
||||
|
||||
# 3. Busquem les columnes dinàmicament
|
||||
col_durada = next((col for col in df.columns if 'durada' in col.lower() or 'duración' in col.lower() or 'duration' in col.lower()), None)
|
||||
col_nom = next((col for col in df.columns if 'nom' in col.lower() or 'nombre' in col.lower() or 'name' in col.lower()), None)
|
||||
|
||||
if not col_nom or not col_durada:
|
||||
print(f"⚠️ Saltant '{fitxer}': Columnes invàlides. Trobades: {list(df.columns)}")
|
||||
continue
|
||||
|
||||
for index, row in df.iterrows():
|
||||
nom = row[col_nom]
|
||||
if pd.isna(nom):
|
||||
continue
|
||||
|
||||
minuts = extreure_minuts(row[col_durada])
|
||||
|
||||
# Apliquem la regla del 5 de febrer (límit de 205 minuts)
|
||||
if "2-05-26" in fitxer and minuts > 205:
|
||||
minuts = 205
|
||||
|
||||
if nom in dades_alumnes:
|
||||
dades_alumnes[nom] += minuts
|
||||
else:
|
||||
dades_alumnes[nom] = minuts
|
||||
|
||||
except UnicodeError:
|
||||
print(f"❌ Error de codificació al fitxer '{fitxer}'. Intenta obrir-lo i guardar-lo de nou.")
|
||||
except Exception as e:
|
||||
print(f"❌ Error processant el fitxer '{fitxer}': {e}")
|
||||
|
||||
# 4. Resultats
|
||||
if dades_alumnes:
|
||||
print("="*50)
|
||||
print("📊 RESULTATS D'ASSISTÈNCIA (Mínim requerit: 1581 min)")
|
||||
print("="*50)
|
||||
|
||||
for nom in sorted(dades_alumnes.keys()):
|
||||
minuts_totals = dades_alumnes[nom]
|
||||
|
||||
if minuts_totals >= 1581:
|
||||
estat = "✅ Supera el 80%"
|
||||
else:
|
||||
estat = "❌ No arriba"
|
||||
|
||||
h = minuts_totals // 60
|
||||
m = minuts_totals % 60
|
||||
|
||||
print(f"{nom}: {minuts_totals} minuts ({h}h {m}m) -> {estat}")
|
||||
40
file-management/treure_etiquetes_mautic.py
Normal file
40
file-management/treure_etiquetes_mautic.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import pandas as pd
|
||||
import csv
|
||||
|
||||
def preparar_etiquetes_per_esborrar(tags_str):
|
||||
"""Afegeix un '-' a cada etiqueta, les uneix amb | i les tanca entre cometes."""
|
||||
# 1. Si la cel·la està buida, la deixem en blanc
|
||||
if pd.isna(tags_str) or str(tags_str).strip().lower() == 'nan':
|
||||
return ''
|
||||
|
||||
# 2. Separem les etiquetes originals per coma i traiem espais
|
||||
llista_tags = [t.strip() for t in str(tags_str).split(',')]
|
||||
|
||||
# 3. Afegim el signe '-' davant de CADA etiqueta (excepte si està buida)
|
||||
tags_per_esborrar = [f"-{t}" for t in llista_tags if t]
|
||||
|
||||
# 4. Les unim amb | i hi afegim les cometes dobles manualment
|
||||
if tags_per_esborrar:
|
||||
tags_units = '|'.join(tags_per_esborrar)
|
||||
return f'"{tags_units}"'
|
||||
else:
|
||||
return ''
|
||||
|
||||
# --- INICI DEL PROCÉS ---
|
||||
|
||||
# 1. Carregar el fitxer original
|
||||
df = pd.read_excel('contactes_mautic/Contactos_2602026_7881pax.xlsx')
|
||||
|
||||
# 2. Seleccionar només l'email i les etiquetes
|
||||
df_esborrar = df[['email', 'etiquetas_x']].copy()
|
||||
|
||||
# 3. Reanomenar la columna
|
||||
df_esborrar.rename(columns={'etiquetas_x': 'etiquetes'}, inplace=True)
|
||||
|
||||
# 4. APLICAR LA TRANSFORMACIÓ
|
||||
df_esborrar['etiquetes'] = df_esborrar['etiquetes'].apply(preparar_etiquetes_per_esborrar)
|
||||
|
||||
# 5. Guardar el CSV respectant les nostres cometes literals
|
||||
df_esborrar.to_csv('Contactes_Mautic_Esborrar_Etiquetes.csv', index=False, encoding='utf-8', quoting=csv.QUOTE_NONE, escapechar='\\')
|
||||
|
||||
print("✅ Fitxer preparat! Les etiquetes tenen el '-' i estan entre cometes dobles.")
|
||||
19
file-management/unificar_excels.py
Normal file
19
file-management/unificar_excels.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import pandas as pd
|
||||
|
||||
# 1. Cargar el primer archivo (tiene encabezados)
|
||||
df1 = pd.read_excel('Contactos_linkedin_120126_agile_6589pax_filtrado.xlsx')
|
||||
|
||||
# 2. Cargar el segundo archivo (sin encabezados, asignamos los principales)
|
||||
# Asumimos que las primeras 3 columnas son email, apellidos y nombre
|
||||
df2 = pd.read_excel('lista_contactos_brevo_20251023_1394pax_AGILE611.xlsx', header=None)
|
||||
df2.rename(columns={0: 'email', 1: 'apellidos_x', 2: 'nombre_x'}, inplace=True)
|
||||
|
||||
# 3. Unir ambos archivos (apilarlos uno debajo del otro)
|
||||
df_final = pd.concat([df1, df2], ignore_index=True)
|
||||
|
||||
# 4. Eliminar contactos duplicados basados en la columna 'email'
|
||||
df_final.drop_duplicates(subset=['email'], keep='first', inplace=True)
|
||||
|
||||
# 5. Exportar el resultado a un nuevo archivo Excel
|
||||
df_final.to_excel('Contactos_Unificados_Agile611.xlsx', index=False)
|
||||
print("¡Archivo unificado creado con éxito!")
|
||||
40
file-management/unir_excels_pestanyes.py
Normal file
40
file-management/unir_excels_pestanyes.py
Normal file
@@ -0,0 +1,40 @@
|
||||
import pandas as pd
|
||||
import os
|
||||
import sys
|
||||
|
||||
print("📊 --- Unificador de fitxers Excel ---")
|
||||
|
||||
# Definim els noms dels fitxers d'entrada i el de sortida
|
||||
fitxer1 = "Contactos_rrhh_040226.xlsx"
|
||||
fitxer2 = "Contactos_2602026_7881pax.xlsx"
|
||||
fitxer_resultat = "Contactos_Unificats.xlsx"
|
||||
|
||||
# Comprovem que els fitxers existeixen a la carpeta actual
|
||||
if not os.path.exists(fitxer1):
|
||||
print(f"❌ Error: No s'ha trobat el fitxer '{fitxer1}'.")
|
||||
sys.exit(1)
|
||||
|
||||
if not os.path.exists(fitxer2):
|
||||
print(f"❌ Error: No s'ha trobat el fitxer '{fitxer2}'.")
|
||||
sys.exit(1)
|
||||
|
||||
print("⏳ Llegint els fitxers... (això pot trigar uns segons depenent de la mida)")
|
||||
|
||||
try:
|
||||
# Llegim els dos fitxers Excel
|
||||
df1 = pd.read_excel(fitxer1)
|
||||
df2 = pd.read_excel(fitxer2)
|
||||
|
||||
# Creem el nou fitxer Excel amb múltiples pestanyes
|
||||
with pd.ExcelWriter(fitxer_resultat, engine='openpyxl') as writer:
|
||||
# Escrivim cada DataFrame en una pestanya diferent
|
||||
df1.to_excel(writer, sheet_name='RRHH', index=False)
|
||||
df2.to_excel(writer, sheet_name='Contactos_7881', index=False)
|
||||
|
||||
print(f"✅ Procés completat amb èxit!")
|
||||
print(f"📄 S'ha creat el fitxer: {fitxer_resultat}")
|
||||
print(" - Pestanya 1: 'RRHH'")
|
||||
print(" - Pestanya 2: 'Contactos_7881'")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ S'ha produït un error durant el procés: {e}")
|
||||
Reference in New Issue
Block a user