Как я могу получить одну строку из файла Excel и добавить ее к другим строкам в определенном месте?

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

Вот мой файл Excel:

файл Excel

Мне нужно получить информацию из первого столбца (кроме слов «Место» и «Все»), пропустить все строки и столбцы, относящиеся к «Году», и получить все столбцы из «1 части», «3 части» и «4 части». , пропуская «2 часть». И строка № 4 мне вообще не нужна. А мне нужно получить информацию из строки №3.

Результат, который я пытаюсь получить:

"1 part": "1_Pl": 4, 5, 6, "3 part": "1_Pl": 10, 11, 12, "4_Part": "1_Pl": 13, 14, 15, "1 part": "2_Pl": 19, 20, 21, "3 part": "2_Pl": 25, 26, 27

И так далее.

Вот мой код:

import openpyxl

START_ROW = 5 # First row with data.
END_ROW = 15 # End of data (row after the last).
TITLE_COL = 1 # Column with title
START_COL = 5 # First column where quarter data starts.
COLS_PER_QUARTER = 3 # Columns per quarter.
QUARTERS_COUNT = 4 # Quarters per year.

wb = openpyxl.load_workbook('C:\\directory\\input.xlsx')
filename='input.xlsx',
read_only=True,
data_only=True
ws = wb.active

entries = []
for row in range(START_ROW, END_ROW):
    def cell(col):
        return ws.cell(row, col).value

    title = cell(TITLE_COL)
    for quarter in range(QUARTERS_COUNT):
        quarter_col = START_COL + quarter * COLS_PER_QUARTER
        entry = f'"{title}": {cell(quarter_col)}, {cell(quarter_col + 1)}, {cell(quarter_col + 2)}'
        entries.append(entry)

Мне нужно получить строку № 3 и поместить ее перед другими ячейками, как показано в моем результате. Мне также нужно удалить информацию из столбцов, принадлежащих «2 части». Может ли кто-нибудь сказать мне, как это сделать? Это должно быть легко, хотя я просто не могу этого понять. Также я знаю, что панды намного лучше подходят для достижения моей цели, но я хочу использовать openpyxl.

🤔 А знаете ли вы, что...
Python был создан Гвидо ван Россумом и впервые выпущен в 1991 году.


63
2

Ответы:

Решено

Это работает для вас?

entries = dict()
for row in ws.iter_rows(min_row=START_ROW, max_row=END_ROW):
    row_data = dict()
    for quarter in (1, 3, 4):
        col_idx = START_COL + COLS_PER_QUARTER * (quarter-1) 
        row_data[f'{quarter} part'] = [row[col_idx + i - 1].value 
                                       for i in range(COLS_PER_QUARTER)]
    entries[row[TITLE_COL-1].value] = row_data

Вычитание единицы необходимо, потому что iter_rows возвращает кортежи ячеек (которые, конечно, имеют индекс 0), в отличие от worksheet.cell() и подобных функций, которые используют индексацию на основе 1 для доступа к данным. Что-то, на что всегда следует обращать внимание при использовании этой библиотеки.

Это создает вложенный вывод в формате JSON:

{
  "1_PL": {
    "1 part": [4.0, 5.0, 6.0],
    "3 part": [10.0, 11.0, 12.0], 
    "4 part": [13.0, 14.0, 15.0]
  },
  "2_PL": {
    "1 part": [19.0, 20.0, 21.0],
     ...
  },
...
}

Я рекомендую извлечь данные из Excel, использовать Python, чтобы получить от них то, что вы хотите, а затем снова записать их обратно в Excel.

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

import openpyxl

path_to_file = 'input.xlsx'
wb = openpyxl.load_workbook(path_to_file)
ws = wb['sheet_name']

final_array = []
array = [row for row in ws.values]  # note: ws.values returns a generator object
for row in array[2:]:  # start at 3rd row for raw data
    place, y1, y2, y3, p11, p12, p13, p21, p22, p23, p31, p32, p33, p41, p42, p43, *_ = row  # **see note below
    final_array.append([place, p13, p23, p33, p43])  # construct new rows in which ever order you wish
# **the "*_" a the end captures any extra data that might be in the sheet but usually isnt needed if you control the spreadsheet

wb = openpyxl.Workbook()
ws = wb.active
for row in final_array:
    ws.append
wb.save('result.xlsx')