import openpyxl
from openpyxl.styles import Alignment
from openpyxl.styles import Font
def unmerge_cells_from_file(my_file):
"""
For a given file, opens each sheet and unmerges the cells.
Aligns to left and highlights in red the unmerged cells.
Saves a new excel file with the _UNMERGED suffix.
"""
= Alignment(horizontal='left')
LEFT_ALIGN = Font(color="FF0000")
RED_FONT # data_only is required to evaluate the cells and store the correct value
= openpyxl.load_workbook(my_file, data_only=True)
wb for sheet in wb.sheetnames:
= wb[sheet]
ws # It's weird, but the for loop do not capture all the groups
# So we iterate with a while loop to reduce all merged cells
while len(ws.merged_cells.ranges) > 0:
= ws.merged_cells.ranges[0]
group = group.bounds
min_col, min_row, max_col, max_row = ws.cell(row=min_row, column=min_col).value
top_left_cell_value # unmerge before asigning a the value
str(group))
ws.unmerge_cells(for irow in range(min_row, max_row+1):
for jcol in range(min_col, max_col+1):
= ws.cell(row=irow, column=jcol)
cell = top_left_cell_value
cell.value = LEFT_ALIGN
cell.alignment = RED_FONT
cell.font
= my_file.replace("input", "tmp").replace(".xlsx", " UNMERGED.xlsx")
output_file
wb.save(output_file)return
Unmerging celdas de excel
Hace poco necesitaba procesar una gran cantidad de archivos excel que tenía muchas celdas fusionadas (merged cells). Algo así como muestro en la imagen:
Pensé que vieja confiable librería de pandas sería suficiente, pero no. Al abrir el archivo con pandas, el valor de la celda se asigna sólo a la primera:
Ingenuamente intenté llenar con fillna y reemplazar los NaNs, pero el resultado no era el desado:
Ninguno de los métodos para llenar las celdas contiguas (fillna
con opciones ‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None
) sirve, porque hay celdas no fusionadas que deberían mantenerse sin datos.
¿Qué hacer entonces? Después de mucho googlear, encontré la solución correcta en stackoverflow. La librería openpyxl
es increíblemente flexible y permite la manipulación celda a celda.
La siguiente función que es una versión mejorada de la propuesta en stackoverflow removerá las celdas fusionadas copiando los valores correspondientes. Lo realizará para todas las pestañas del archivo, y marcará en rojo las celdas que fueron intervenidas:
El excel resultante es el siguiente:
Desde ese punto, ya es posible trabajar con pandas sin problemas.
Observación: Hay que usar una versión reciente de pyopenxl, ya que en la versión anterior arroja un error.