openpyxl 脚本在附加到电子表格第二列时跳过行

问题描述 投票:0回答:1

我正在编写一个小脚本来填充电子表格中 2 个模块的时间值和功率值。 A 列和 C 列将存储模块 1 的时间和功率值,而 B 列和 D 列将存储模块 2 的时间和功率值。我在将值附加到第二个模块的初始行时遇到困难。任何帮助表示赞赏。下面是代码:

# get user inputs
try:
    step_size = float(self.step_size_entry.get())
    hold_time = float(self.hold_time_entry.get())
    upper_bound = float(self.upper_bound_entry.get())
    lower_bound = float(self.lower_bound_entry.get())
    ramping = self.ramping_var.get()
    selected_module = self.selected_module_var.get()



# create excel workbook and sheet
try:
   wb = load_workbook("Test.xlsx")
   if "data" in wb.sheetnames:
        sheet = wb["data"]
   else:
        # add another sheet to the workbook
        sheet = wb.create_sheet("data")
except FileNotFoundError:
   wb = Workbook()
   sheet = wb.active
   sheet.title = "data"

# check if "data" sheet already exists
   if "data" in wb.sheetnames:
       sheet = wb["data"]
   else:
       # add another sheet to the workbook
       sheet = wb.create_sheet("data")

# populate header row
sheet["A1"] = "Time 1"
sheet["B1"] = "Time 2"
sheet["C1"] = "Module 1"
sheet["D1"] = "Module 2"


# initialize variables
power = lower_bound
prev_power = None

# get the index of the last filled row for Module 1
last_row_m1 = len(sheet['A'])
last_row_m2 = len(sheet['B'])
# get the index of the last filled row for Module 2


# Calculate time_1 and time_2
if last_row_m1 > 1:
    time_1 = (sheet.cell(row=last_row_m1, column=1).value) + (sheet.cell(row=last_row_m1, column=1).value - sheet.cell(row=last_row_m1- 1, column=1).value)
else:
    time_1 = 1

if last_row_m2 > 1:
    time_2_prev_value = sheet.cell(row=last_row_m2, column=2).value
    if time_2_prev_value is None:
         time_2_prev_value = 0
    time_2 = time_2_prev_value + hold_time
else:
    time_2 = 1



# if the sheet is empty, set last_row to 0
if last_row_m1 == 1 and sheet.cell(row=1, column=1).value is None:
    last_row_m1 = 0

if last_row_m2 == 1 and sheet.cell(row=1, column=2).value is None:
    last_row_m2 = 0


# populate power column based on ramping selection
if ramping == "Ascending" and selected_module == "Module 1":
    while power <= upper_bound:
        for i in range(int(hold_time)):
            if power != prev_power:  # Add row only if power value is changing
                sheet.append([time_1, None, power, None])
                prev_power = power
            time_1 = time_1 + hold_time
        power += step_size
    
if ramping == "Ascending" and selected_module == "Module 2":
    while power <= upper_bound:
        for i in range(int(hold_time)):
            if power != prev_power:  # Add row only if power value is changing
                sheet.append([None, time_2, None, power])
                prev_power = power
            time_2 = time_2 + hold_time
        power += step_size

# save and close workbook
wb.save("Test.xlsx")
wb.close()


#User Input 1:
#step_size = 10
#hold_time = 5
#upper_bound = 120
#lower_bound = 100
#ramping = "Ascending"
#selected_module = "Module 1"

#User Input 2:
#step_size = 10
#hold_time = 5
#upper_bound = 120
#lower_bound = 100
#ramping = "Ascending"
#selected_module = "Module 2"

电流输出:

时间1 时间2 电源1 电源2
1 空白 100 空白
6 空白 110 空白
11 空白 120 空白
空白 1 空白 100
空白 6 空白 110
空白 11 空白 120

所需输出:

时间1 时间2 电源1 电源2
5 5 100 100
10 10 110 110
15 15 120 120
空白 空白 空白 空白
空白 空白 空白 空白
空白 空白 空白 空白

enter image description here

openpyxl
1个回答
0
投票

感谢您的编辑,使展示示例变得更容易。

正如 @Redox 在他的评论中提到的,你的对齐问题是由于你使用了追加造成的。
如所示追加always添加到最后使用的行之后的下一个
例如如果最后使用的行是 10 并且我“工作表附加”一些数据,它将被放置在第 11 行。如果我执行另一个“工作表附加”,它将被放置在第 12 行和下一个附加、第 13 行等。
因此,为了添加“第二个”数据集(在添加第一个数据集之后),您不能使用“工作表附加”。您只能将值单独添加到所需的单元格。

另请注意
列的长度不返回指定列的最后使用的行。因此这些行;

last_row_m1 = len(sheet['A'])
last_row_m2 = len(sheet['B'])

将始终返回相同的结果,这也将与
sheet.max_row

要获取列中最后使用的行,您可以使用像这样的列表理解(例如,对于“A”列);

last_row_m1 = [x.row for x in sheet['A'] if x.value is not None][-1]

我对您的代码进行了一些修改,这将产生您想要的结果。它只是作为一个示例,因为它可能无法完全适应您的现实生活应用程序。
主要更改是允许通过附加或逐个单元格添加数据的方法,具体取决于数据是添加到新行还是插入到现有的已使用行中。
我还更改了添加要在同一块中完成的数据,因为使用的两个块基本上是代码重复。

为了进行测试,我在启用

### User Input 1:
数据和禁用
### User Input 2:
数据且没有现有工作簿“Test.xlsx”的情况下运行了一次代码。然后在第一次运行中生成的工作簿上启用
### User Input 2:
数据并禁用
### User Input 1:
数据。
我还修改了设置 time_2 值的块,因此
time_2
将使用值 5 而不是 1 进行初始化,以区分模块 1 到模块 2 的数据集并复制提供的屏幕截图数据。

time_2 = 5  # Modified for debug testing 

在此代码示例中,使用附加功能添加来自“### User Input 1:”的 A 列(“时间 1”)和 C(“模块 1”)中的数据,因为该数据是新行上的第一个数据。 “### 用户输入 2:”中的 B 列(“时间 2”)和 D(“模块 2”)中的数据是通过迭代每行列中的单元格并使用相同的列表数据来添加的。

from openpyxl import load_workbook, Workbook

### Enable each input data set one after the other 
### User Input 1:
# step_size = 10
# hold_time = 5
# upper_bound = 120
# lower_bound = 100
# ramping = "Ascending"
# selected_module = "Module 1"

### User Input 2:
# step_size = 10
# hold_time = 5
# upper_bound = 120
# lower_bound = 100
# ramping = "Ascending"
# selected_module = "Module 2"

# create excel workbook and sheet
try:
    wb = load_workbook("Test.xlsx")
    if "data" in wb.sheetnames:
        sheet = wb["data"]
    else:
        # add another sheet to the workbook
        sheet = wb.create_sheet("data")
except FileNotFoundError:
    wb = Workbook()
    sheet = wb.active
    sheet.title = "data"

    # check if "data" sheet already exists
    if "data" in wb.sheetnames:
        sheet = wb["data"]
    else:
        # add another sheet to the workbook
        sheet = wb.create_sheet("data")

# populate header row
sheet["A1"] = "Time 1"
sheet["B1"] = "Time 2"
sheet["C1"] = "Module 1"
sheet["D1"] = "Module 2"

# initialize variables
power = lower_bound
prev_power = None

# get the index of the last filled row for Module 1
# last_row_m1 = len(sheet['A'])
last_row_m1 = [x.row for x in sheet['A'] if x.value is not None][-1]
print(f"Last row m1 'last_row_m1: {last_row_m1}")
# last_row_m2 = len(sheet['B'])
last_row_m2 = [x.row for x in sheet['B'] if x.value is not None][-1]
print(f"Last row m2 'last_row_m2: {last_row_m2}")
sheet_last_row = sheet.max_row
print(f"Sheet last row 'sheet_last_row: {sheet_last_row}")
# get the index of the last filled row for Module 2


# Calculate time_1 and time_2
if last_row_m1 > 1:
    time_1 = sheet.cell(row=last_row_m1, column=1).value + (
            sheet.cell(row=last_row_m1, column=1).value - sheet.cell(row=last_row_m1 - 1, column=1).value)
else:
    time_1 = 1

if last_row_m2 > 1:
    time_2_prev_value = sheet.cell(row=last_row_m2, column=2).value
    if time_2_prev_value is None:
        time_2_prev_value = 0
    time_2 = time_2_prev_value + hold_time
else:
    time_2 = 5  # Modified for debug testing

# if the sheet is empty, set last_row to 0
if last_row_m1 == 1 and sheet.cell(row=1, column=1).value is None:
    last_row_m1 = 0

if last_row_m2 == 1 and sheet.cell(row=1, column=2).value is None:
    last_row_m2 = 0

# populate power column based on ramping selection
# if ramping == "Ascending" and selected_module == "Module 1":

### Determine if both column A and B are equal length.
### If Column B is shorter than Column A set the row to 2 (next after Header row)
### Otherwise start a next unused row
if last_row_m2 < last_row_m1:
    row = 2
else:
    row = sheet_last_row

### If input data is 'module 1' set time to time1 otherwise set to time_2
time = time_1 if selected_module == "Module 1" else time_2

add_list = []

while power <= upper_bound:
    for i in range(int(hold_time)):
        if power != prev_power:  # Add row only if power value is changing
            ### Update the list of data to add depending on if we have 'Module 1' or 'Module 2'
            add_list = [time, None, power, None] if selected_module == "Module 1" else [None, time, None, power]

            ### If there is no data already entered in the block i.e. first insert the
            ### data can be added using append
            if sheet_last_row == 1:
                sheet.append(add_list)
            ### If data has already been entered in the sheet then must add data cell by cell
            else:
                ### Iterate the columns and enter the data from the list cell by cell
                for x in range(len(add_list)):
                    new_value = add_list[x]
                    if new_value is not None:
                        sheet.cell(row=row, column=x+1).value = new_value

            prev_power = power
            row += 1
        time = time + hold_time # Change time to be generic
    power += step_size


wb.save("Test.xlsx")
wb.close()

© www.soinside.com 2019 - 2024. All rights reserved.