web-dev-qa-db-fra.com

Est-il possible d'obtenir le nombre de lignes d'un document Excel sans charger l'intégralité du document en mémoire?

Je travaille sur une application qui traite d'énormes fichiers Excel 2007, et j'utilise OpenPyXL pour le faire. OpenPyXL utilise deux méthodes différentes pour lire un fichier Excel: une méthode "normale" dans laquelle le document entier est chargé en mémoire en une fois et une méthode dans laquelle les itérateurs sont utilisés pour lire ligne par ligne.

Le problème est que lorsque j'utilise la méthode itérateur, je ne reçois aucune métadonnée de document telle que la largeur des colonnes et le nombre de lignes/colonnes, et i vraiment a besoin de ces données. Je suppose que ces données sont stockées dans le document Excel situé au sommet, il ne devrait donc pas être nécessaire de charger le fichier entier de 10 Mo en mémoire pour pouvoir y accéder.

Alors, y a-t-il un moyen de connaître le nombre de lignes/colonnes et la largeur des colonnes sans charger d’abord le document entier en mémoire?

37
Hubro

Ajoutons à ce que Hubro a dit, apparemment get_highest_row() est obsolète. L'utilisation des propriétés max_row et max_column renvoie le nombre de lignes et de colonnes. Par exemple:

    wb = load_workbook(path, use_iterators=True)
    sheet = wb.worksheets[0]

    row_count = sheet.max_row
    column_count = sheet.max_column
78
dransom90

La solution suggérée dans cette réponse est obsolète et risque de ne plus fonctionner.


En regardant le code source de OpenPyXL ( IterableWorksheet ), j'ai compris comment obtenir le nombre de colonnes et de lignes à partir d'une feuille de calcul d'itérateur:

wb = load_workbook(path, use_iterators=True)
sheet = wb.worksheets[0]

row_count = sheet.get_highest_row() - 1
column_count = letter_to_index(sheet.get_highest_column()) + 1

IterableWorksheet.get_highest_column renvoie une chaîne avec la lettre de colonne que vous pouvez voir dans Excel, par exemple. "A", "B", "C" etc. Par conséquent, j'ai également écrit une fonction pour traduire la lettre de colonne en un index de base zéro:

def letter_to_index(letter):
    """Converts a column letter, e.g. "A", "B", "AA", "BC" etc. to a zero based
    column index.

    A becomes 0, B becomes 1, Z becomes 25, AA becomes 26 etc.

    Args:
        letter (str): The column index letter.
    Returns:
        The column index as an integer.
    """
    letter = letter.upper()
    result = 0

    for index, char in enumerate(reversed(letter)):
        # Get the ASCII number of the letter and subtract 64 so that A
        # corresponds to 1.
        num = ord(char) - 64

        # Multiply the number with 26 to the power of `index` to get the correct
        # value of the letter based on it's index in the string.
        final_num = (26 ** index) * num

        result += final_num

    # Subtract 1 from the result to make it zero-based before returning.
    return result - 1

Je n'ai toujours pas trouvé comment obtenir la taille des colonnes, j'ai donc décidé d'utiliser une police à largeur fixe et des colonnes mises à l'échelle automatiquement dans mon application.

14
Hubro

Cela peut être extrêmement compliqué et il est possible que je manque l’évidence, mais sans OpenPyXL dans les colonnes_dimensions de Iterable Worksheets (voir mon commentaire ci-dessus), le seul moyen de retrouver la taille de la colonne sans tout charger est d’analyser le xml directement :

from xml.etree.ElementTree import iterparse
from openpyxl import load_workbook
wb=load_workbook("/path/to/workbook.xlsx", use_iterators=True)
ws=wb.worksheets[0]
xml = ws._xml_source
xml.seek(0)

for _,x in iterparse(xml):

    name= x.tag.split("}")[-1]
    if name=="col":
        print "Column %(max)s: Width: %(width)s"%x.attrib # width = x.attrib["width"]

    if name=="cols":
        print "break before reading the rest of the file"
        break
2
Markus

https://pythonhosted.org/pyexcel/iapi/pyexcel.sheets.Sheet.html voir: row_range () Fonction utilitaire pour obtenir la plage de lignes

si vous utilisez pyexcel, vous pouvez appeler row_range obtenir le nombre maximal de lignes.

python 3.4 test réussi.

0
delphisharp