Увеличьте скорость операций с файлами Excel (используя openpyxl): проверьте значение и удалите строки операций, если условие - PullRequest
0 голосов
/ 17 октября 2018

У меня есть файл Excel среднего размера, с примерно 25000 строками.

В файле Excel я проверяю, есть ли конкретное значение столбца в списке, и, если он есть в списке, я удаляю строку.

Я использую openpyxl.

Код:

   count = 1
    while count <= ws.max_row:
        if ws.cell(row=count, column=2).value in remove_list:
            ws.delete_rows(count, 1)
        else:
            count += 1
    wb.save(src)

Код работает, но очень медленно (занимает часы), чтобы закончить.

Я знаю, что это режимы только для чтения и только для записи, но в моем случае я использую как первую проверку, так и второе удаление.

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Я вижу, вы используете список строк, которые вам нужно удалить.Вместо этого вы можете создавать «последовательности» строк для удаления, таким образом изменяя список удаления, например, [2,3,4,5,6,7,8,45,46,47,48], на список, подобный [[2, 7], [45, 4]]

т.е. удалить 7 строк, начиная со строки 2, затем удалить 4 строки, начиная со строки 45

Массовое удаление выполняется быстрее, чем 1 на 1. Я удалил 6kстрок за 10 секунд

Следующий код преобразует список в список списков / последовательностей:

def get_sequences(list_of_ints):
    sequence_count = 1
    sequences = []
    for row in list_of_ints:
        next_item = None
        if list_of_ints.index(row) < (len(list_of_ints) - 1):
            next_item = list_of_ints[list_of_ints.index(row) + 1]

        if (row + 1) == next_item:
            sequence_count += 1
        else:
            first_in_sequence = list_of_ints[list_of_ints.index(row) - sequence_count + 1]
            sequences.append([first_in_sequence, sequence_count])
            sequence_count = 1

    return sequences

Затем запустите другой цикл для удаления

    for sequence in sequences:
        sheet.delete_rows(sequence[0], sequence[1])
0 голосов
/ 17 октября 2018

Лично я бы сделал две вещи:

сначала преобразовал бы список в набор, чтобы поиск элемента занимал меньше времени

remove_set = set(remove_list)
...
if ws.cell(row=count, column=2).value in remove_set:

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

Я бы создал новый пустой лист и добавил бы к нему только те строки, которые должны быть сохранены.

Затемсохраните новый лист, перезаписав оригинал, если хотите.

Если это все еще занимает слишком много времени, рассмотрите возможность использования формата CSV, чтобы вы могли обрабатывать входные данные как текст и выводить их таким же образом, повторно импортируяданные позже из программы работы с электронными таблицами (например, Ms-Excel)

Посмотрите официальные документы и это руководство , чтобы узнать, как использовать библиотеку CSV

Примечание: как заметил @Charlie Clark, вычисление

ws.max_row

может занять некоторое время, и нет необходимости повторять его.

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

...