Openpyxl - компиляция идентичных листов в новый лист

У меня есть книга Excel, состоящая из нескольких вкладок одного стиля таблицы (одинаковое количество столбцов, одинаковые типы данных). Я хочу объединить (добавить? Стек? Внешнее соединение? Что угодно!) Каждую из таблиц в один новый рабочий лист со следующими требованиями:

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

Пока что мой концептуальный процесс выглядит так:

  1. Загрузить в книгу
  2. Получите список листов
  3. Прокрутите список созданных мною листов.
  4. Добавьте новый столбец A, содержащий имя листа в каждой ячейке.
  5. Добавить новый пустой лист
  6. Прокрутите список листов, которые я создал снова
  7. Добавить данные в мой новый лист, исключая первую строку после первой итерации.
  8. Сохраните книгу

Вот код, который у меня есть:

def combine(path):
    # Load in workbook
    wb = xl.load_workbook(filename=path)

    # Get a list of sheets
    ws_list = wb.sheetnames

    # Loop over the list of sheets I created
    for i, ws in enumerate(ws_list):
        # Add a new column A
        wb[ws].insert_cols(idx=0)  
        for column in wb[ws]['A{0}:A{1}'.format(wb[ws].min_row, wb[ws].max_row)]:
            for cell in column:
                # that contains the name of the sheet in every cell
                cell.value = str(ws)

    # Add a new empty sheet
    wb.create_sheet(title=u'COMBINED',index=0)
    # Loop over the list of sheets I created againv
    for i, ws in enumerate(ws_list):
        # Append the data (currently should copy headers as well)
        wb['COMBINED'].append(wb[ws].rows)

    # Save workbook
    wb.save(path) 

И это ошибка, которую я получаю

Обратите внимание, что «Fall 03» - это имя первой вкладки и текст, добавленный в первый столбец первой вкладки. Из-за этого я предполагаю, что процесс продолжается до шага 5.

Traceback (most recent call last):
  File "test.py", line 194, in <module>
    main()
  File "test.py", line 188, in main
    combine(excel_path)
  File "test.py", line 166, in combine
    wb['COMBINED'].append(wb[ws].rows)                          <- my script
  File "C:\Python27\ArcGISx6410.5\lib\site-packages\openpyxl\worksheet\worksheet.py", line 777, in append
    cell = Cell(self, row=row_idx, col_idx=col_idx, value=content)
  File "C:\Python27\ArcGISx6410.5\lib\site-packages\openpyxl\cell\cell.py", line 115, in __init__
    self.value = value
  File "C:\Python27\ArcGISx6410.5\lib\site-packages\openpyxl\cell\cell.py", line 294, in value
    self._bind_value(value)
  File "C:\Python27\ArcGISx6410.5\lib\site-packages\openpyxl\cell\cell.py", line 207, in _bind_value
    raise ValueError("Cannot convert {0!r} to Excel".format(value))
ValueError: Cannot convert (<Cell u'Fall 03'.A1>, <Cell u'Fall 03'.B1>, <Cell u'Fall 03'.C1>, <Cell u'Fall 03'.D1>, <Cell u'Fall 03'.E1>, <Cell u'Fall 03'.F1>, <Cell u'Fall 03'.G1>, <Cell u'Fall 03'.H1>, <Cell u'Fall 03'.I1>, <Cell u'Fall 03'.J1>, <Cell u'Fall 03'.K1>, <Cell u'Fall 03'.L1>, <Cell u'Fall 03'.M1>, <Cell u'Fall 03'.N1>, <Cell u'Fall 03'.O1>, <Cell u'Fall 03'.P1>, <Cell u'Fall 03'.Q1>, <Cell u'Fall 03'.R1>, <Cell u'Fall 03'.S1>, <Cell u'Fall 03'.T1>, <Cell u'Fall 03'.U1>, <Cell u'Fall 03'.V1>, <Cell u'Fall 03'.W1>, <Cell u'Fall 03'.X1>, <Cell u'Fall 03'.Y1>, <Cell u'Fall 03'.Z1>, <Cell u'Fall 03'.AA1>, <Cell u'Fall 03'.AB1>, <Cell u'Fall 03'.AC1>, <Cell u'Fall 03'.AD1>, <Cell u'Fall 03'.AE1>, <Cell u'Fall 03'.AF1>, <Cell u'Fall 03'.AG1>, <Cell u'Fall 03'.AH1>, <Cell u'Fall 03'.AI1>, <Cell u'Fall 03'.AJ1>, <Cell u'Fall 03'.AK1>, <Cell u'Fall 03'.AL1>) to Excel

Если я могу быть разборчивым

Пока я пытаюсь придерживаться openpyxl, потому что знаю, что он установлен на всех машинах, которые мне понадобятся. Я также могу использовать любой модуль, входящий в стандартный дистрибутив ArcGIS 10.5 ArcPy.

Я просмотрел эти решения, и ни одно из них, похоже, не работает:

  1. Этот, кажется, неправильно использует итерацию '.rows'
  2. Этот не работает, потому что я не знаю количество строк в существующих таблицах.
  3. Этот не будет работать, потому что они просят копировать между таблицами, что по какой-то причине является нетривиальным отклонением.
0
0
145
1

Ответы 1

Вы не можете сделать это wb['COMBINED'].append(wb[ws].rows). Вы можете добавить только последовательность простых элементов, таких как числа или строки, и пытаетесь передать последовательность кортежей, содержащих объекты Cell. for row in ws1.values: ws.append(row) было бы возможно.

Ваш код также слишком сложен: вы можете просто перебрать листы в книге: for ws in wb и использовать ws.iter_rows() и ws.iter_cols() для параметрического доступа.

Посмотрим, понимаю ли я: похоже, что «строки» - это самый базовый уровень, который я могу добавить с помощью метода ws.append. Это правда? И я не знал об этом поведении __iter__ по умолчанию, используемом for ws in wb:, это действительно полезно.

Zach Roy 01.11.2018 22:14

Нет, вы можете добавить только последовательность стандартных типов Python.

Charlie Clark 02.11.2018 09:55

Другие вопросы по теме