He intentado xlrd, pandas, openpyxl y otras bibliotecas similares, y todas parecen llevar un tiempo exponencial a medida que aumenta el tamaño del archivo a medida que lee todo el archivo. Las otras soluciones mencionadas anteriormente donde usaban 'on_demand' no funcionaron para mí. Si solo desea obtener los nombres de las hojas inicialmente, la siguiente función funciona para los archivos xlsx.
def get_sheet_details(file_path):
sheets = []
file_name = os.path.splitext(os.path.split(file_path)[-1])[0]
# Make a temporary directory with the file name
directory_to_extract_to = os.path.join(settings.MEDIA_ROOT, file_name)
os.mkdir(directory_to_extract_to)
# Extract the xlsx file as it is just a zip file
zip_ref = zipfile.ZipFile(file_path, 'r')
zip_ref.extractall(directory_to_extract_to)
zip_ref.close()
# Open the workbook.xml which is very light and only has meta data, get sheets from it
path_to_workbook = os.path.join(directory_to_extract_to, 'xl', 'workbook.xml')
with open(path_to_workbook, 'r') as f:
xml = f.read()
dictionary = xmltodict.parse(xml)
for sheet in dictionary['workbook']['sheets']['sheet']:
sheet_details = {
'id': sheet['@sheetId'],
'name': sheet['@name']
}
sheets.append(sheet_details)
# Delete the extracted files directory
shutil.rmtree(directory_to_extract_to)
return sheets
Dado que todos los xlsx son básicamente archivos comprimidos, extraemos los datos xml subyacentes y leemos los nombres de las hojas del libro directamente, lo que lleva una fracción de segundo en comparación con las funciones de la biblioteca.
Evaluación comparativa: (en un archivo xlsx de 6mb con 4 hojas)
Pandas, xlrd: 12 segundos
openpyxl: 24 segundos
Método propuesto: 0.4 segundos
Como mi requisito era solo leer los nombres de las hojas, la sobrecarga innecesaria de leer todo el tiempo me estaba molestando, así que tomé esta ruta en su lugar.
ExcelFile
? Además, supongamos que busco la lista de hojas y decido cargar N de ellas, ¿en ese momento debería llamarread_excel
(a la nueva interfaz) para cada hoja o apegarmex1.parse
?