簡體   English   中英

Python Openpyxl - 修改excel文件及其值

[英]Python Openpyxl - Modify excel file and its value

我得到一個導出的 Excel 文件,其中顯示了 ProductItems、位置和一些銷售編號。

現在,問題是 ProductItems 和 Locations 都在一列中,縮進了一點,如下所示:

ProductItem_1
   Location_a | Quantity  | Price
   Location_b | Quantity  | Price
   Location_c | Quantity  | Price
   (110 locations total)
ProductItem_2
   Location_a | Quantity  | Price
   Location_b | Quantity  | Price
   Location_c | Quantity  | Price
ProductItem_1
   Location_a | Quantity  | Price
   Location_b | Quantity  | Price
   Location_c | Quantity  | Price

....等等...例如 150 個 ProductItems x 110 個位置...

我的想法是在左邊插入一個列,它會是空的,然后將 ProductItem name 的名稱復制到每一行,如下所示:

ProductItem_1 | Location_a | QuantityVal  | PriceVal
ProductItem_1 | Location_b | QuantityVal  | PriceVal
ProductItem_1 | Location_c | QuantityVal  | PriceVal
ProductItem_2 | Location_a | QuantityVal  | PriceVal
ProductItem_2 | Location_b | QuantityVal  | PriceVal
ProductItem_2 | Location_c | QuantityVal  | PriceVal
ProductItem_3 | Location_a | QuantityVal  | PriceVal
ProductItem_3 | Location_b | QuantityVal  | PriceVal
ProductItem_3 | Location_c | QuantityVal  | PriceVal

我該怎么做? 我附上了 Excel 文件的屏幕截圖...知道如何在 Python 中使用 Openpyxl 解決這個問題嗎? 謝謝在此處輸入圖像描述

期望的結果如下所示: 在此處輸入圖像描述

此示例根據您之前的圖像生成請求的格式,並包括原始工作表中未更改的第 1 -4 行。
基本上,代碼循環遍歷第 5 行中的行,即 header 行中 B 列、C、D 和 E 中的數據。它將每個范圍從 A 到 E 移動 1,以便 A 列為空,並設置使用變量“colA_val”將該行的 A 列中的值更改為最新確定的“ProductItems”的值。

“ProductItems”由變量“num_indent”設置的單元格文本中的前導空格確定。 從圖片來看有1個前導空間。 如果有更明確的方法來確定“ProductItems”行,則可以更改此部分。

以下步驟可選

  1. 在數據移動 1 列后,循環用於應用列寬 1,以便標題保持與以前相同的寬度。 由於現在 B 列中的文本寬度較大,因此 A 列的寬度略有減少。
  2. header 行中的單元格 B5 添加了輪廓邊框。 該單元格不包含文本,因為問題中未指定。

...

from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.styles import Border, Side

filename = "openpyxl2.xlsx"

# Open workbook and select sheet
wb = load_workbook(filename)
ws = wb.active

### Loop the cells
colA_val = '' # Hold the text value to enter in to Col A
col_width = {} # This dict holds the column dimenions so the col widths can be readjusted
num_indent = 1 # How many leading spaces for the 'ProductItems' cell

for row in ws.iter_rows(min_row=5, max_row=ws.max_row):
    cur_row =row[0].row
    row_colA_value = row[0].value
    ### If this is a row with data
    if row_colA_value is not None:
        ### Determine if 'ProductItems' row from the leading spaces, set by 'num_indent'
        leading_spaces = len(row_colA_value) - len(row_colA_value.lstrip(' '))
        ### Is current row a ProductItems row, if so get details and delete row
        if leading_spaces == num_indent:
            ### One off row 5 header adjustment and column widths collection
            if not col_width:
                ### Adjust header row 5 one column across
                ws.move_range(f'A{cur_row - 1}:E{cur_row - 1}', cols=1)
                ### Get column dimensions 
                for x in range(ws.max_column-1):
                    col_width[row[x].column] = ws.column_dimensions[row[x].column_letter].width
            ### Get next ProductItem name
            colA_val = row_colA_value.lstrip()
            ### Delete the row the ProductItem was on
            ws.delete_rows(cur_row)

        ### move name, units, sales etc cells 1 column across
        ws.move_range(f'A{cur_row}:E{cur_row}', cols=1)
        ### Enter the ProductItem name into cell in column A
        ws.cell(row=cur_row, column=1).value = colA_val


### Reset the column widths using the sizes saved in the col_width dictionary
for c, d in col_width.items():
    ### Adjust Column A to be a little smaller than before
    if c == 1:
        ws.column_dimensions['A'].width = d - 10
    ### Set the columns to the same width as before
    ws.column_dimensions[get_column_letter(c + 1)].width = d

### Add Text and Border to header section cell B5
ws.cell(row=5, column=2).value = 'Enter text here'

med_border = Border(left=Side(style='medium'),
                     right=Side(style='medium'),
                     top=Side(style='medium'),
                     bottom=Side(style='medium'))
ws.cell(row=5, column=2).border = med_border

wb.save('out_' + filename)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM