WedX - журнал о программировании и компьютерных науках

Можно ли получить количество строк документа Excel, не загружая весь документ в память?

Я работаю над приложением, которое обрабатывает огромные файлы Excel 2007, и использую для этого OpenPyXL. Это. OpenPyXL имеет два разных метода чтения файла Excel: один «обычный» метод, при котором весь документ загружается в память сразу, и один метод, при котором итераторы используются для чтения построчно.

Проблема в том, что когда я использую метод итератора, я не получаю никаких метаданных документа, таких как ширина столбцов и количество строк/столбцов, и мне действительно нужны эти данные. Я предполагаю, что эти данные хранятся в документе Excel ближе к началу, поэтому нет необходимости загружать весь 10-мегабайтный файл в память, чтобы получить к нему доступ.

Итак, есть ли способ получить количество строк/столбцов и ширину столбцов без предварительной загрузки всего документа в память?

14.11.2012

  • У меня такое ощущение, что если у вас огромные файлы Excel, вы, вероятно, используете Excel для задачи, для которой он не подходит. 14.11.2012
  • @Markus: Это не очень важно. Мой босс использует Excel, я просто пишу для него этот скрипт. 14.11.2012
  • В любом случае, я просматривал openpyxl, и, похоже, он не загружал размеры столбцов для IterableWorksheet. Если вы загрузите все это сразу, вы можете получить такие размеры, как worksheet.column_dimensions[A].width, однако словарь column_dimensions полностью не заполнен для итерируемого рабочего листа. :-/ Похоже, что новые документы Excel представляют собой просто XML, поэтому теоретически вы можете использовать его для поиска элементов столбца и прямого извлечения информации, но это хлопотно. 15.11.2012
  • С каких это пор 10 МБ стали огромными? 21.09.2017
  • @MadPhysicist 10 МБ на самом деле умеренно много для файлов xlsx. Помните, что они представляют собой сжатый XML. Таким образом, 10-мегабайтный xlsx потенциально может быть распакован до 100 МБ при загрузке (особенно если он содержит не примитивные объекты). Хотя я работал с XLSX в диапазоне 90 МБ... 07.12.2018
  • @ковберт. Я согласен с умеренно большими файлами XLS. Однако для практических целей мы имеем дело с несколькими ГБ оперативной памяти. 07.12.2018

Ответы:


1

В дополнение к тому, что сказал Хубро, по-видимому, get_highest_row() устарел. Использование свойств max_row и max_column возвращает количество строк и столбцов. Например:

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

    row_count = sheet.max_row
    column_count = sheet.max_column
10.09.2015
  • max_row и max_column не работали на sheet = wb.active. Я использую openpyxl==2.4.8 09.04.2018
  • @Hussain: Какую ценность вы получили и чего ожидали? А как же sheet = wb.worksheets[0]? 30.08.2018
  • @Hussain sheet = wb.active отлично работал у меня, используя эту версию 13.12.2018
  • но в этом случае вы также считаете ячейки с нулевым значением, вместо этого я попытался перебирать столбцы, я знаю, что это не лучший способ. а мне полезно. 06.12.2019

  • 2

    Решение, предложенное в этом ответе, устарело и может больше не работать.


    Взглянем на исходный код OpenPyXL (IterableWorksheet) Я понял, как получить количество столбцов и строк из рабочего листа итератора:

    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 возвращает строку с буквой столбца, которую вы видите в Excel, например. A, B, C и т. д. Поэтому я также написал функцию для перевода буквы столбца в нулевой индекс:

    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
    

    Однако я до сих пор не понял, как получить размеры столбцов, поэтому решил использовать в своем приложении шрифт фиксированной ширины и автоматически масштабируемые столбцы.

    14.11.2012
  • Оглядываясь назад, вычитание 1 из sheet.get_highest_row() для получения количества строк, вероятно, было неправильным. Поскольку номера строк отсчитывались от 1, а не от 0, наивысший индекс строки также будет числом строк. Хотя, возможно, была веская причина для вычитания 1, я не могу вспомнить. 12.08.2015
  • Стоит отметить, что метаданные о размере рабочего листа не всегда доступны. В этом случае вам нужно пройти весь рабочий лист. 11.09.2015
  • @CharlieClark Когда это будет недоступно? 11.09.2015
  • Ну, ровно по той же причине, по которой желательно иметь эту информацию в начале файла при чтении, нецелесообразно помещать ее туда при потоковой передаче в файл. Вот почему это считается необязательной функцией в спецификации. Таким образом, вы не найдете его в экспорте из Google или в собственном режиме только для записи openpyxl. Лучшим решением было бы включить метаданные в другое место в пакете, но мы застряли со спецификацией как есть. openpyxl сообщит вам, если данные отсутствуют, и позволит вам вычислить их (прочитав весь рабочий лист). 11.09.2015
  • @CharlieClark Спасибо, я этого не знал. К счастью, мое приложение должно поддерживать только файлы Excel, сохраненные приложением Excel. 11.09.2015
  • Может быть, есть умный способ сделать это — формат упаковки вроде как поддерживает потоковую передачу, с чем что-то иерархическое, такое как XML, не очень хорошо — но Microsoft лучше всего знает об этом. Похоже, внутри он по-прежнему делает много вещей по-старому, в то время как все остальные пытаются работать со спецификацией. 11.09.2015
  • @Hubro get_highest_row() устарела и больше не работает в openpyxl-2.4.1. Этот ответ следует обновить. 23.12.2016
  • @sabbahillel Спасибо, я изменил принятый ответ. 23.12.2016

  • 3

    Это может быть чрезвычайно запутанным, и я могу упустить очевидное, но без OpenPyXL, заполняющего column_dimensions в Iterable Worksheets (см. мой комментарий выше), единственный способ найти размер столбца без загрузки всего — это проанализировать xml напрямую :

    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
    
    15.11.2012
  • Кроме того, это, вероятно, плохой стиль для разбора xml, я этого раньше не делал. 15.11.2012

  • 4

    Питон 3

    import openpyxl as xl
    
    wb = xl.load_workbook("Sample.xlsx", enumerate)
    
    #the 2 lines under do the same. 
    sheet = wb.get_sheet_by_name('sheet') 
    sheet = wb.worksheets[0]
    
    row_count = sheet.max_row
    column_count = sheet.max_column
    
    #this works fore me.
    
    15.10.2019

    5

    Варианты с использованием pandas.

    1. Получает все имена листов с количеством строк и столбцов.
    import pandas as pd
    xl = pd.ExcelFile('file.xlsx')
    sheetnames = xl.sheet_names
    for sheet in sheetnames:
        df = xl.parse(sheet)
        dimensions = df.shape
        print('sheetname', ' --> ', dimensions)
    
    1. Количество строк и столбцов на одном листе.
    import pandas as pd
    xl = pd.ExcelFile('file.xlsx')
    sheetnames = xl.sheet_names
    df = xl.parse(sheetnames[0])   # [0] get first tab/sheet.
    dimensions = df.shape
    print(f'sheetname: "{sheetnames[0]}" - -> {dimensions}')
    

    выход sheetname "Sheet1" --> (row count, column count)

    21.07.2021

    6

    https://pythonhosted.org/pyexcel/iapi/pyexcel.sheets.Sheet.html см. : row_range() Вспомогательная функция для получения диапазона строк

    если вы используете pyexcel, вы можете вызвать row_range для получения максимального количества строк.

    Тестовый прохождение Python 3.4.

    08.01.2016
  • python 3.4 тест в порядке. 08.01.2016
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]