How to move specific cells in an excel file to a new column with openpyxl in python

Question:

I am trying to moving some specific cells to a designated location. As shown in the image, would like to move data in cells D3 to E2, D5 to E4,….. so on so for. Is it doable with openpyxl? Any suggestions would be greatly appreciate it!!
Click to see the image

Here is what I got so far. It worked per say.

wb=xl.load_workbook(datafile)
ws=wb['Sheet1']

#insert a new column #5
ws.insert_cols(idx=5,amount=1)
wb.save(datafile)

mr=ws.max_row
   
#move cells

for i in range (1,mr+1):
    v=ws.cell(row = i+1,column=4) 
    ws.cell(row=i,column =5).value=v.value

wb.save(datafile)
wb.close

Thanks for the help.

I revised the codes and it worked well. I then wanted to delete the unwanted rows and it didn’t work. Looks like it got into an infinite loop. Codes are shown here. What did I do wrong?

wb=xl.load_workbook(datafile)
ws=wb['Sheet1']
#insert a new column #5
ws.insert_cols(idx=5,amount=1)

#Calculate total number of rows 
mr=ws.max_row
   
#move cells
for i in range (2,mr,2):
    ws.cell(row=i,column=5).value=ws.cell(row=i+1,column=4).value

#delete unwanted rows
for i in range (2,mr,2):
    ws.delete_rows(idx=i+1,amount=1)
    
wb.save(datafile)
Asked By: Michael Jiang

||

Answers:

Thats a good effort.
Here are some comments to help and also on how to skip one row.

  1. Should generally only ever need to save the workbook once at the end of all your edits, unless you are making multiple copies. So the wb.save after the insert command is not necessary.
  2. There shouldn’t be need to use ‘mr + 1’ here. Just the value ‘mr’ is fine, it matches the rows count.
  3. Not necessary to assign an intermediate variable for just copying a value from one cell to another. Assign the new cell value to the existing cell value in one line as shown. However it’s fine if you want to use the variable ‘v’ as an intermediate.
  4. wb.close should be wb.close() however wont do anything on this workbook anyway Only affects read-only and write-only modes which is a method when opening the workbook. So not need to include that line.

To skip rows you can set the stepping in the range. Stepping is the last number in the range params. So

range(2, mr, 2)

Means ‘i’ starts at 2, increases to max value [ws.max_row] in increments of 2.
In this case since the max value is 7, i will be 2, 4 and 6

wb = xl.load_workbook(datafile)
ws = wb['Sheet1']

# insert a new column #5
ws.insert_cols(idx=5, amount=1)
# wb.save(datafile)  # <--- not necessary just save at the end

mr = ws.max_row

# move cells

for i in range(2, mr, 2):
    ws.cell(row=i, column=5).value = ws.cell(row=i + 1, column=4).value
    ###  ws.cell(row=i + 1, column=4).value = None # If moving the value

    # v = ws.cell(row=i + 1, column=4)
    # ws.cell(row=i, column=5).value = v.value

wb.save(datafile)
# wb.close  # <-- Not needed, should have brackets anyway

Finally you are mentioning ‘move’ cells which implies you don’t want those Addresses remaining in the ‘Address’ column after the copy. At the moment the code is just copying the values, not technically moving them.
If you do actually want move rather than copy then its necessary to delete the cell value after the copy. This can be done simply by setting the cell value to None (that is python None not the text word ‘None’).
I have included that line in the code after the copy.
Incidently if you do wish to delete the ‘copy from’ cells then using your intermediate variable ‘v’ to refer to the ‘copy from’ cell for these two commands would then more pythonic.

Answered By: moken
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.