Copy paste column range using OpenPyxl - python

Hi so I am trying to copy and paste W7:W46 column into another worksheet. The code I have so far,
col_j = New_Burden['W']
for idx, cell in enumerate(col_j,1):
ws1.cell(row = idx, column = 10).value = cell.value
is able to copy over the entire column, but unfortunately transfers the various headers as well. One solution I have tried is:
for row in New_Burden['W7:W46']:
for cell in row:
ws1.cell(row = 2, column = 10).value = cell.value
But that only copies the first value of W7

Copy a Range(['W7:W46']) from one Worksheet to another Worksheet:
If the Ranges are not overlapping, it's also possible in the same Worksheet.
from openpyxl import Workbook
# Create a new Workbook
wb = Workbook()
ws = wb.worksheets[0]
from openpyxl.utils import range_boundaries
# Define start Range(['J2']) in the new Worksheet
min_col, min_row, max_col, max_row = range_boundaries('J2')
# Iterate Range you want to copy
for row, row_cells in enumerate(New_Burden['W7:W46'], min_row):
for column, cell in enumerate(row_cells, min_col):
# Copy Value from Copy.Cell to given Worksheet.Cell
ws.cell(row=row, column=column).value = cell.value
If you want to do the above with multiple different Columns,
use the above in a function:
def copy_range(source_range, target_start):
# Define start Range(target_start) in the new Worksheet
min_col, min_row, max_col, max_row = range_boundaries(target_start)
# Iterate Range you want to copy
for row, row_cells in enumerate(New_Burden[source_range], min_row):
for column, cell in enumerate(row_cells, min_col):
# Copy Value from Copy.Cell to given Worksheet.Cell
ws.cell(row=row, column=column).value = cell.value
for source_range, target_start in [('W7:W46','J2'), ('Y7:Y46','A2')]:
copy_range(source_range, target_start)
Tested with Python: 3.4.2 - openpyxl: 2.4.1 - LibreOffice: 4.3.3.2

Related

PYTHON - Copy entire row with formatting

I am new in Python and Openpyxl.
I am trying to copy a range of cells (with their formatting knowing some cells are merged) from a row to an other row on the same worksheet.
Thanks
This is an example to copy cells from one row to another within the same worksheet.
This example takes a range of cells on row 2 from column A to column column J and duplicates to 'row_offset' rows down, in this case row 12. The duplication includes cell style/formatting and merged cells.
from openpyxl.utils import rows_from_range
from openpyxl import load_workbook
from openpyxl.worksheet.cell_range import CellRange
from copy import copy
def copy_range(range_str, sheet, offset):
""" Copy cell values and style to the new row using offset"""
for row in rows_from_range(range_str):
for cell in row:
if sheet[cell].value is not None: # Don't copy other cells in merged unit
dst_cell = sheet[cell].offset(row=offset, column=0)
src_cell = sheet[cell]
### Copy Cell value
dst_cell.value = src_cell.value
### Copy Cell Styles
dst_cell.font = copy(src_cell.font)
dst_cell.alignment = copy(src_cell.alignment)
dst_cell.border = copy(src_cell.border)
dst_cell.fill = copy(src_cell.fill)
dst_cell.number_format = src_cell.number_format
def get_merge_list(r_range, r_offset):
""" Create a list of new cell merges from the existing row"""
area = CellRange(r_range) # Range to check for merged cells
mlist = [] # List of merged cells on existing row offset to the new row
for mc in ws.merged_cells:
if mc.coord not in area:
continue
cr = CellRange(mc.coord)
cr.shift(row_shift=r_offset)
mlist.append(cr.coord)
return mlist
wb = load_workbook("foo.xlsx")
ws = wb['Sheet1']
row_range = 'A2:J2' # Row range to be copied
row_offset = 10 # Offset to the new row
### Create a range list for merged cells on new row
new_merge_list = get_merge_list(row_range, row_offset)
### Create merged cells on new row
for nm in new_merge_list:
ws.merge_cells(nm)
### Copy cell values to new row
copy_range(row_range, ws, row_offset)
### Save workbook
wb.save("foo_out.xlsx")

I want to iterate this list in my excel file, can you show me a different way to do it?

My question is simple and I'm sorry to ask it here. But I tried several ways to iterate through my excel file and I'm having trouble finding the solution.
from openpyxl import workbook, load_workbook
wb = load_workbook("italian_team.xlsx")
ws = wb.active
rows = ws["A"]
equipe = ["Juventus", "Ac Milan", "Torino", "Pescara", "As Roma", "Genoa", "Napoli"]
for cell in rows:
x = equipe[cell]
wb.save("italian_team.xlsx")
Do you mean you just want to insert your list as a row in the workbook?
If so there are a few options, you could just append the list as is to the sheet in which case it will be enter after the last used row.
Or specify the row (and column) to add to.
Both options are shown in the code below
from openpyxl import workbook, load_workbook
wb = load_workbook("italian_team.xlsx")
ws = wb.active
# rows = ws["A"]
equipe = ["Juventus", "Ac Milan", "Torino", "Pescara", "As Roma", "Genoa", "Napoli"]
# for cell in rows:
# x = equipe[cell]
# This will append the list after the last used row
ws.append(equipe)
# This will enter the list at row 1 column 1 to the length of the list
# Use min_row = and max_col = as well if the list is to be on another row or start at another column
for row in ws.iter_rows(max_row=1, max_col=len(equipe)):
for enum, cell in enumerate(row):
cell.value = equipe[enum]
wb.save("italian_team.xlsx")

Openpyxl copy and paste as values in new workbook

I am trying to copy the first 100 rows in a source file to a new destination file with openpyxl. My source file has formulas, but I want to copy and paste as values in the new workbook. When I add data_only=True, (see code below), it copies only the values of my source sheet and therefore not the data in the formula cells - these are just empty in the destination file. How do I copy everything and paste as values in the destination sheet?
WB1 = load_workbook("sample_book.xlsx")
WB1_WS1 = WB1["Ark2"]
WB2 = Workbook()
#Create new worksheet in new workbook
for i in range(1,2):
WB2.create_sheet(f"WS{i}")
#Delete first sheet
WB2.remove(WB2.worksheets[0])
#Define the ranges and sheets
copy_ranges = [100]
copy_to_sheets = ["WS1"]
# Copy the values from the rows in WB1 to WB2
for i in range (len(copy_ranges, data_only=True)):
#Set the sheet to compy to
ws = WB2[copy_to_sheets[i]]
#initialize row offset
offset = 1
for s in range (i):
offset+=copy_ranges[s]
#copy the row and append
for j in range(offset, offset + copy_ranges[i]):
#if j==0:
# continue
for row in WB1_WS1.iter_rows(min_row=j,max_row=j,min_col=1,max_col=WB1_WS1.max_column):
values_row = [cell.value for cell in row]
ws.append(values_row)
#save
WB2.save("WB2.xlsx")
You are using Len() incorrectly. Len() returns the length of a list. copy_ranges is a 1-item list, so Len(copy_ranges) = 1. If you want to access the first item in the list, you need to use an index: Len(copy_ranges[0]) = 100
I don't quite follow the 'offset' code part, and there is an issue with
offset = 1
for s in range (i):
offset+=copy_ranges[s]
On any iteration where i > 1, s will be > 1, which means offset+=copy_ranges[s] will throw an IndexError because copy_ranges is a 1-item list and you are trying to access a non-existing element.
Here are two ways to copy the first 100 rows:
if you want the formula in WB2, don't pass in the data_only parameter.
## VERSION 1: Output will have formulas from WB1
WB1 = load_workbook('int_column.xlsx')
WB1_WS1 = WB1['Sheet']
WB2 = Workbook()
WB2_WS1 = WB2.active # get the active sheet, so you don't need to create then delete one
# copy rows
for x, row in enumerate(WB1_WS1.rows):
if x < 100: # only copy first 100 rows
num_cells_in_row = len(row)
for y in range(num_cells_in_row):
WB2_WS1.cell(row=x + 1, column=y + 1).value = WB1_WS1.cell(row=x + 1, column=y + 1).value
WB2.save('copied.xlsx')
if you set data_only=True, the displayed value of the cell in WB1 will be copied to WB2.
## VERSION 2: Output will have value displayed in cells in WB1
WB1 = load_workbook('int_column.xlsx', data_only=True)
WB1_WS1 = WB1['Sheet']
WB2 = Workbook()
WB2_WS1 = WB2.active # get the active sheet, so you don't need to create then delete one
# copy rows
for x, row in enumerate(WB1_WS1.rows):
if x < 100: # only copy first 100 rows
num_cells_in_row = len(row)
for y in range(num_cells_in_row):
WB2_WS1.cell(row=x + 1, column=y + 1).value = WB1_WS1.cell(row=x + 1, column=y + 1).value
WB2.save('copied.xlsx')

Copy column to another sheet in Python

I've been trying to copy a variable length column to another sheet through openpyxl. What I'm looking to do is copy, for example, column B from row 2 up to row = sheet.max_row and paste it into another sheet within the same workbook. Specifying the first cell in the sheet in which it will start pasting in would be nice too.
I've tried following this tutorial(copy and paste cell ranges into another workbook) to no avail.
So far I have my code set up like this:
import openpyxl
wb = openpyxl.load_workbook('workbook1.xlsx')
wb.create_sheet('sheet2') # this is where I want the cells to be pasted into
sheet = wb['sheet1'] # name of the sheet that is being analyzed
wb.save('workbook1.xlsx') #
Does anyone have any code that could help? If not, what resources are available to look at for information on how to solve this problem?
ws1 = wb.active # source
ws2 = wb['sheet2'] # destination
for cell in ws1['B:B']: #column B
print('Printing from ' + str(cell.column) + str(cell.row))
ws2.cell(row = cell.row, column = 1, value = cell.value)
wb.save('workbook1.xlsx')

Starting iterate from specific column

This is my .xslx file:
data.xlsx
from openpyxl import load_workbook
workbook = load_workbook('/path/', read_only=True)
first_sheet = workbook.sheetnames()[0]
worksheet = workbook[first_sheet]
for row in worksheet:
for cell in row:
print(cell.value)
How can I start iteration from A4? I need to print year and month value.
You can use iter_rows, either by specifying the offset or the range
for row in worksheet.iter_rows('A4:B9'):
for cell in row:
print(cell.value)
Btw: sheetnames()[0] should be sheetnames[0] or get_sheet_names()[0]

Categories