Copy pasting a excel column from one excel document to another - python

I am going crazy here. My code works but the "was2.cell(row = 1, column = 2).value = c.value" line is not saving no matter what I do. I keep getting a "int object has no attribute value" error message. Any ideas or suggestions ?
import openpyxl as xl;
from openpyxl import load_workbook;
# opens the source excel file
#"C:\Users\wwwya\Desktop\mkPox.xlsx" <-- needs to have double backwords slash for xl to understand
mkPox ="C:\\Users\\wwwya\\Desktop\\mkPox.xlsx"
wbMonkey1 = xl.load_workbook(mkPox)
ws1 = wbMonkey1.worksheets[0]
# opens the destination excel file
mkPaste ="C:\\Users\\wwwya\\Desktop\\mkPaste.xlsx"
wbPaste2 = xl.load_workbook(mkPaste)
ws2 = wbPaste2.active
# calculate total number of rows and
# columns in source excel file
mr = ws1.max_row
mc = ws1.max_column
# copying the cell values from source
# excel file to destination excel file
for row in range(2, mr + 1):
for column in "B": #Here you can add or reduce the columns
cell_name = "{}{}".format(column, row)
c = ws1[cell_name].value # the value of the specific cell
print(c)
# writing the read value to destination excel file
ws2.cell(row=2, column=2).value = c.value
# saving the destination excel file
wbPaste2.save(str(mkPaste))```

Your code had a couple of issues around this section
c = ws1[cell_name].value # the value of the specific cell
print(c)
# writing the read value to destination excel file
ws2.cell(row=2, column=2).value = c.value
You assigned c already to the 'value' of the cell, ws1[cell_name].value therefore c is a literal equal to the value of that cell, it has no attributes. When you attempt to assign the cell value on the 2nd sheet, you just want the variable 'c', as #norie indicated.
The next issue in that section is that is the row and column for ws2.cell doesn't change. Therefore whatever you are writing to the 2nd sheet is always going to cell 'B2' making the iteration thru the 1st sheet a waste of time, only cell 'B2' will have a value and it will be from the last cell in column 'B' in the 1st sheet.
Also there is no need to include a file path/name in wbPaste2.save(str(mkPaste)) if saving to the same file. It's only necessary if you want to save to a different path and filename. However if you include the filename it would still work. There is no need to cast as string since mkPaste is already a string.
The code example below shows how you can simplify the whole operation to a few lines;
Note; the loop uses enumerate to create two variables that update each loop iteration.
for enum, c in enumerate(ws1['B'][1:], 2):
enum is used as the row position in ws2, the '2' in the enumerate function means the enum variable initial value is 2, so the first row to be written on the 2nd sheet is row 2.
c is the cell object from ws1, column 'B'. The loop starts at the second cell due to the [1:] param in line with your code starting the copy from row 2.
There is no need to use intermediary variables, just assign each cell in the 2nd sheet the value of the corresponding cell in the 1st sheet then save the file.
import openpyxl as xl;
mkPox ="C:\\Users\\wwwya\\Desktop\\mkPox.xlsx"
wbMonkey1 = xl.load_workbook(mkPox)
ws1 = wbMonkey1.worksheets[0]
# opens the destination excel file
mkPaste ="C:\\Users\\wwwya\\Desktop\\mkPaste.xlsx"
wbPaste2 = xl.load_workbook(mkPaste)
ws2 = wbPaste2.active
for enum, c in enumerate(ws1['B'][1:], 2):
ws2.cell(row=enum, column=c.column).value = c.value
# saving the destination excel file
wbPaste2.save()

Related

Python Openpyxl Copy Data From Rows Based on Cell Value& Paste In Specific Rows of ExcelSheet

I am trying to copy data by rows based on Column ['A'] cell value from one sheet and paste in row2 of another sheet. The paste in sheet is an existing worksheet, row 1 of the worksheet is my header row so i want to paste the copied data starting from row2. I do not want to append as I have existing formula columns in the paste in sheet that will be overwritten, also with append I lose formatting. So say Column A of my copy from sheet is States, i want to copy all rows where Column ['A'] cell.value is 'Georgia' and paste in row2 of sheet2, copy rows where Column ['A'] cell.value = Texas and paste in row2 of sheet 3 etc(pasting every state in different sheets). I am able to copy the data and paste but I am not able to get it to paste in row 2 it is pasting in whatever row the data is in my copy from sheet. So if Texas starts from row 3000, my code is copying from row 3000 of the copy from sheet and pasting in row 3000 of sheet 2 meaning rows 1-2999 of my sheet 2 is all empty rows,
Copy from file looks like this:
Paste in file looks like this:
see my code below
import openpyxl
from openpyxl import load_workbook
from openpyxl import Workbook
from openpyxl.utils import range_boundaries
from sys import argv
script, inpath, outpath = argv
# load copy from file
wb_cpy = load_workbook(r'C:\Users\me\documents\sourcefolder\copyfromfile.xlsx')
#ws = wb_src["sheet1"] #previous inconsistency referred to in thecomment
ws = wb_cpy["sheet1"] #edited fixed
# load paste in file
wb_pst = load_workbook(r'C:\Users\me\documents\sourcefolder\pasteinfile.xlsx')
#ws2 = wb_dst["sheet2"] #previous inconsistency referred to inthecomment
ws2 = wb_pst["sheet2"] #edited fixed
for row in ws.iter_rows(min_col=1, max_col=1, min_row=9):
for row2 in ws2.iter_rows(min_col=1, max_col=1, min_row=2):
for cell in row:
for cell2 in row2:
if cell.value == "GEORGIA":
ws2.cell(row=cell.row, column=1).value = ws.cell(row=cell.row, column=1).value
ws2.cell(row=cell.row, column=2).value = ws.cell(row=cell.row, column=2).value
ws2.cell(row=cell.row, column=6).value = ws.cell(row=cell.row, column=6).value
wb_pst.save(r'C:\Users\me\documents\sourcefolder\pasteinfile.xlsx')
#ps: i will repeat the script for each state
I maybe approaching it all wrong but I have tried multiple other approaches with no success, I cannot get the copied data to paste in row 2 of the paste in sheet
There seems to be some inconsistencies in your code e.g.
wb_cpy = load_workbook(r'C:\Users\me\documents\sourcefolder\copyfromfile.xlsx')
ws = wb_src["sheet1"]
ws is referencing a workbook object different to that just created or indeed does not appear to exist anywhere in your code. Similar with the next workbook and worksheet objects
When you are writing code should try to avoid duplication, so reuse code where you can.
Below is some example code is based on the assumption in my comment and that the states are in order as shown in your example data i.e. not jumbled together and the States list is in that same order.
The code uses a python list of the States to search then copy the consecutive rows to the current 'pasteinfile.xlsx' sheet until the next State data. It then copies that State data to the next 'pasteinfile.xlsx' Sheet and so on for each State.
Summary
The States list is manually added here however it could be obtained from the values in Column A prior if these change each time. A search on Column A is made for each State in the list starting at A2, then subsequently from the last row of the last copied State data, i.e. after GEORGIA rows are copied and ALABAMA is the next search its will start from row 7 which is the end of the GEORGIA rows.
As a 'State' matches it sets the first row to paste data in the 'pasteinfile.xlsx' Sheet to row 2 then iterates through the cells in the first matched row and copies each cell value to 'pasteinfile.xlsx' (starting at row 2). Then checks next row in Column A for a State match again and if true copies the next row to row 3 of 'pasteinfile.xlsx' and so on until the State no longer matches. At this point it loops to the next State and resets the start row back to 2 and sets the next numeric Sheet name. Then the same process is repeated until all States in the list are searched.
For each State the 'pasteinfile.xlsx' Sheet name is incremented by 1, i.e. 'Sheet1', 'Sheet2', etc. The code starts naming at 'Sheet1' however that can be changed to start at another number if desired.
...
from copy import copy # Import copy if used
# load copy from file
wb_cpy = load_workbook('copyfromfile.xlsx')
# ws = wb_src["sheet1"]
ws = wb_cpy["Sheet1"]
# load paste in file
wb_pst = load_workbook('pasteinfile.xlsx')
# ws2 = wb_dst["sheet2"]
copyfrom_max_columns = ws.max_column
paste_start_min_row = 1
states_list = ['GEORGIA', 'ALABAMA', 'TEXAS'] # States list to search for rows
for sheet_number, state in enumerate(states_list, 1):
ws2 = wb_pst["Sheet" + str(sheet_number)] # Set Sheet name for current pasted data
search_min_row = paste_start_min_row # Start search for States at top row then from the end of the last copy/paste
paste_start_min_row = 1 # Reset the row number for each new sheet so the copy starts at row 2
for row in ws.iter_rows(max_col=1, min_row=search_min_row): # min_col defaults to 1
for cell in row:
if cell.value == state: # Search ColA for the State, when match is found proceed to copy/paste
paste_start_min_row += 1 # Set first row for 'copy to' to 2
for i in range(copyfrom_max_columns): # Iterate the cells in the row to max column
# Set the copy and paste Cells
copy_cell = cell.offset(column=i)
paste_cell = ws2.cell(row=paste_start_min_row, column=i + 1)
# Paste the copied value to the 'pasteinfile.xlsx' Sheet
paste_cell.value = copy_cell.value
# Set the number format of the cell to same as original
paste_cell.number_format = copy_cell.number_format
### Copy other Cell formatting if desired
### Requires 'from copy import copy'
paste_cell.font = copy(copy_cell.font)
paste_cell.alignment = copy(copy_cell.alignment)
paste_cell.border = copy(copy_cell.border)
paste_cell.fill = copy(copy_cell.fill)
wb_pst.save('pasteinfile.xlsx')
This image is an example of the Sheet for ALABAMA in 'pasteinfile.xlsx' (Sheet2 in this case), before and after running the code. Note I set each row in the Type column to a numeric value as a unique identifier for each row of the data.
#-------------Additional Information---------#
I have updated the code to include some style and formatting copying. The specific format noted is 'number_format' which can be copied across the same way as the value per the code. If you need/want other formatting like font, orientation, fill etc these need the 'copy' function and you'll need to import copy as shown in the code, **from copy import copy**. If you just want the number format omit those lines and there is no need to import copy.

How do I loop through each source file and copy a specific column into a new workbook with each new "paste" shifting to the adjacent column?

I have 3 Excel files with a column of data in cells A1 to A10 (the "Source Cells") in each workbook (on sheet 1 in each workbook). I would like to copy the data from the Source Cells into a new workbook, but the data must shift into a new column each time.
For example:
the Source Cells in File 1 must be copied to cells A1 to A10 in the new workbook;
the Source Cells in File 2 must be copied to cells B1 to B10 in the new workbook; and
the Source Cells in File 3 must be copied to cells C1 to C10 in the new workbook.
I'm struggling to figure the best way to adjust "j" in my code on each iteration. I'm also not sure what the cleanest way is to run each function for the different source files.
All suggestions on how to make this code cleaner will also be appreciated because I admit it's so messy at the moment!
Thanks in advance!
import openpyxl as xl
filename_1 = "C:\\workspace\\scripts\\file1.xlsx"
filename_2 = "C:\\workspace\\scripts\\file2.xlsx"
filename_3 = "C:\\workspace\\scripts\\file3.xlsx"
destination_filename = "C:\\workspace\\scripts\\new_file.xlsx"
num_rows = 10
num_columns = 1
def open_source_workbook(path):
'''Open the workbook and worksheet in the source Excel file'''
workbook = xl.load_workbook(path)
worksheet = workbook.worksheets[0]
return worksheet
def open_destination_workbook(path):
'''Open the destination workbook I want to copy the data to.'''
new_workbook = xl.load_workbook(path)
return new_workbook
def open_destination_worksheet(path):
'''Open the worksheet of the destination workbook I want to copy the data to.'''
new_worksheet = new_workbook.active
return new_worksheet
def copy_to_new_file(worksheet, new_worksheet):
for i in range (1, num_rows + 1):
for j in range (1, num_columns + 1):
c = worksheet.cell(row = i, column = j)
new_worksheet.cell(row = i, column = j).value = c.value
worksheet = open_source_workbook(filename_1)
new_workbook = open_destination_workbook(destination_filename)
new_worksheet = open_destination_worksheet(new_workbook)
copy_to_new_file(worksheet, new_worksheet)
new_workbook.save(str(destination_filename))
Question: Loop files, copy a specific column, with each new “paste” shifting to the adjacent column?
This approach first aggregates from all files the Column Cell values.
Then rearange it so, that it can be used by the openpyxl.append(... method.
Therefore, no target Column knowledge are needed.
Reference:
class collections.OrderedDict([items])
Ordered dictionaries are just like regular dictionaries but have some extra capabilities relating to ordering operations.
openpyxl.utils.cell.coordinate_to_tuple(coordinate)
Convert an Excel style coordinate to (row, colum) tuple
iter_rows(min_row=None, max_row=None, min_col=None, max_col=None, values_only=False)
Produces cells from the worksheet, by row. Specify the iteration range using indices of rows and columns.
map(function, iterable, ...)
Return an iterator that applies function to every item of iterable, yielding the results.
zip(*iterables)
Make an iterator that aggregates elements from each of the iterables.
Used imports
import openpyxl as opxl
from collections import OrderedDict
Define the files in a OrderedDict to retain file <=> column order
file = OrderedDict.fromkeys(('file1', 'file2', 'file3'))
Define the Range as index values.
Convert the Excel A1 notation into index values
min_col, max_col, min_row, max_row =
opxl.utils.cell.range_to_tuple('DUMMY!A1:A10')[1]
Loop the defined files,
load every Workbook and get a reference to the default Worksheet
get the cell values from the defined range:
min_col=1, max_col=1, min_row=1, max_row=10
for fname in file.keys():
wb = openpyxl.load_workbook(fname)
ws = wb.current()
file[fname] = ws.iter_rows(min_row=min_row,
max_row=max_row,
min_col=min_col,
max_col=max_col,
values_only=True)
Define a new Workbook and get a reference to the default Worksheet
wb2 = opxl.Workbook()
ws2 = wb2.current()
Zip the values, Row per Row from all files
Map the ziped list of tuples using a lambda to flatten to a list of Row values.
Append the list of values to the new Worksheet
for row_value in map(lambda r:tuple(v for c in r for v in c),
zip(*(file[k] for k in file))
):
ws2.append(row_value)
Save the new Workbook
# wb2.save(...)

How can you Create a copy of a worksheet by iterating through another while excluding certain rows in a array.?

I'm comparing two workbooks using Openpyxl I have it incrementing a counter for later usage and then keeping track of rows that should be removed from the initial workbook. How do I go about getting rid of these rows from that workbook or creating a new sheet(With the Original then deleted) or workbook with those rows removed?
I've written the code up until this point but I havent found much in terms of writing or deleting rows from a workbook and I haven't any concrete luck, I was advised by someone to instead create a copy of the workbook but I also have had no success at doing such.
from openpyxl import load_workbook
from tkinter import Tk
from tkinter.filedialog import askopenfilename
import datetime
import time
class ManualReporter:
def __init__(self):
'''
Initializes Variables for use within the Class
Hides the tkinter pop-up when using the file dialog
'''
Tk().withdraw()
self.sap_file = None
self.tracker_file = None
self.wb_sap = None
self.wb_wt = None
self.XT = 0
self.deadrows = []
def open_sapfile(self):
'''
Sets the sap_file variable to be the first directory to the SAP Report based on what the User Selects in the File Dialog
Sets that directory and the file as the current workbook under the variable self.wb_sap
Creates a Backup of the SAP Report so that if Errors Occur a Fresh Clean Copy is Present
'''
self.sap_file = askopenfilename()
self.wb_sap = load_workbook(filename=self.sap_file)
# Code to create a backup File in-case of Error or Fault
copyfile = "Untimed_Report_SAP_" + str(datetime.date.today())+".xlsx"
self.wb_sap.save(copyfile)
print(self.sap_file)
def open_tracker(self):
'''
Same as Above, sets self.tracker_file as a filedialog which retrieves the file's directory (User Inputted)
Loads the File Workbook as self.wb_wt
Creates a Backup of the Second SAP Report so that if Error Occurs a Clean Copy is Present.
'''
self.tracker_file = askopenfilename()
self.wb_wt = load_workbook(filename=self.tracker_file)
print(self.tracker_file)
def check_rows(self):
'''
Sets the Active Sheets in Both the Workbook Variables,
Creates a New Sheet in the Newest Report to Contain the Modified Data,
Iterates through the Rows of the Two Sheets checking for a Comparison in Part Number,
OpCode and then Compares the X/T/P Classification and Adjusts Data in Second Sheet
'''
start = time.time()
sap = self.wb_sap.worksheets[0] #Sets The First Sheet in the Excel Workbook as the variable sap
wt = self.wb_wt.worksheets[0]#Sets the First Sheet in the Second Report as the var wt
ws1 = self.wb_sap.create_sheet("Sheet1", 1)#Create a Spare Sheet in the First Report to place the Adjusted Data
ws1 = self.wb_sap.worksheets[1]#Sets ws1 as the Active Second Sheet for New Data
for saprow in sap.iter_rows():
for wtrow in wt.iter_rows():
if (saprow[3].value == wtrow[4].value and int(saprow[2].value) == int(wtrow[5].value)):# IF Material NUM & OPCode MATCH DO:
if wtrow[7].value in ("T","P"): #WT Entry is Marked as T/P
if saprow[4].value is "X": #SAP Report Entry is Marked as X
self.XT += 1#Increment X->Ts Counts
#print("X->T")
self.deadrows.append(saprow)
else:
if saprow not in self.deadrows:
ws1.append(saprow)
end = time.time()
#print("Finished, Total X->Ts: ", self.XT)
print("Time Taken: ", (end - start))
x = ManualReporter()
x.open_sapfile()
x.open_tracker()
x.check_rows()
My expectation is that the output would be an exact copy of workbook one but the rows that had a certain change in values are removed from that workbook. I expected to be able to delete them but no methods I've done have achieved anything other than broken code or issues.
self.deadrows.append(saprow)
else:
if saprow not in self.deadrows:
for i in saprow:
#Code to Create a row in ws1.
#Code to Append value of saprow[i] to current ws1 rows
EDIT 1: I included my Attempts to append the rows to a copied worksheet.
EDIT 2: I though about manually iterating through the Saprow and appending the data into the rows of the new sheet but I've stumped myself thinking about it.
After Ample help I have reached the conclusion that to copy data from one sheet to another you can copy over data row by row through this Method:
self.workbook = load_workbook(filename="filepath")
sheet1 = self.workbook.worksheet[0]
sheet2 = self.workbook.create_sheet("Sheet 2")
sheet2 = self.workbook.worksheets[1]
for row in sheet1.iter_rows():
sheet2.append([cell.value for cell in row])
I also figured out if you want to filter out data you can add if statements inside of the for-loop above that can limit what rows have their cells written into the new worksheet.
self.RowsToExclude = Some List containing row data that will be excluded.
for row in sheet1.iter_rows():
if row not in self.RowsToExclude:
ws1.append([cell.value for cell in row])
Finally, I'd like to thank all those who contributed towards me reaching this conclusion.

python error when adding a formula to a cell below the last row

With some help I have been able to put together a script but with this block I keep getting an error:
import openpyxl
import xlrd
import requests
# loads the workbook - assumes the sussex.xlsx file is in the same directory as the script
wb = openpyxl.load_workbook("sussex.xlsx")
# load first worksheet
ws = wb.worksheets[0]
#go to the British Fencing Association website and download this file (specified)
url = "https://www.britishfencing.com/wp-content/uploads/2018/10/mf_oct_2018.xls"
downloaded_file = requests.get(url)
#write the contents to a new file called rankings.xls
with open("rankings.xls", 'wb') as file:
file.write(downloaded_file.content)
# Use xlrd to open older style .xls workbook
rank_wb = xlrd.open_workbook('rankings.xls')
# Get the first sheet of the ranked workbook
rank_ws = rank_wb.sheet_by_index(0)
# Get the total number of rows to be used to create our license list
rows = rank_ws.nrows
# Due to formatting, real numbers don't start until here
startrow = 5
# Create list of lic numbers
rank_lic = rank_ws.col_values(colx=4, start_rowx=startrow, end_rowx=rows)
# print the values in the second column of the first sheet
for row in ws['B1:B{}'.format(ws.max_row)]:
for cell in row:
print(cell.value)
# Putting values in same row as "Rank, Name, First name,...." adjust as necessary
ws.cell(2, 7).value = 'Fencer NIF'
ws.cell(2, 8).value = 'Points scored'
# Define function to lookup NIF and return value
def get_nif(x):
startrow = 5
for y in rank_lic:
if int(x) == y:
try:
return int(rank_ws.cell_value(startrow, 9))
except ValueError:
pass
startrow = startrow + 1
#sum of NIF values
Grand_Total_Row = ws.max_row + 1
ws.cell(Grand_Total_Row, 1).value = "Grand Total"
ws.cell(Grand_Total_Row, 4).value = "=SUM(G4:G{})".format(ws.max_row - 1)
for row in ws['D3:D{}'.format(ws.max_row)]:
for cell in row:
nif_val = get_nif(cell.value)
ws.cell(cell.row, 7).value = nif_val
# While testing I always save to a different workbook so I don't overwrite my test spreadsheet
wb.save('sussex2.xlsx')
The error is:
Traceback (most recent call last):
File "clubranking.py", line 63, in <module>
nif_val = get_nif(cell.value)
File "clubranking.py", line 48, in get_nif
if int(x) == y:
ValueError: invalid literal for int() with base 10: '=SUM(G4:G35)'
What I am trying to do is take cell G4 to the last cell with a value in that column, and on the row below it sum those values.
Does anyone have any ideas on how to resolve this?
FYI I am using request; xlrd; and openpyxl
Your issue is that the libraries you're using work with Excel files and this is not quite the same thing as working within the Excel program. The Excel program does quite a lot of things automatically that are not done by openpyxl or xlrd.
For example, one thing you have to know about Excel files is that formulas and their results are two completely separate things. They are stored separately and read independently. In openpyxl, if you write a formula to a cell, then that cell only has a formula stored in it. It does not (and cannot) calculate the result of the formula.
Similarly, when it comes time to read a cell, openpyxl will either give you the formula or the result, but not both (you have to choose which one you want; by default you get the formula if there is one). xlrd will only ever give you the result. And I cannot stress enough: In your case there is no result to read because it simply hasn't been calculated. So even if you tell openpyxl to give you the result instead of the formula, that won't help you.
In contrast, the Excel program (by default) always recalculates formulas, and stores both the formulas and their results at the same time, keeping them synchronized. This isn't the case with the libraries you're using.
The error message you showed is what you get when you try to convert '=SUM(G4:G35)' into an integer. Note that Python's int function has no idea what Excel is or what cells are or what formulas are. It is trying to convert an equals sign, a capital 'S', a capital 'U', a capital 'M', a left paren, a capital 'G', the digit 4, a colon, another capital 'G', the digits 3 and 5, and a right paren into an integer. Python is telling you that it can't make sense of that as an integer.
Your main options if you want to keep doing this with Python are (1) calculate the sum yourself, in Python, and use that; or (2) use a differently library, such as xlwings, which will work with the Excel program, rather than raw files.

Python 3x win32com: Copying used cells from worksheets in workbook

I have 6 work sheets in my workbook. I want to copy data (all used cells except the header) from 5 worksheets and paste them into the 1st. Snippet of code that applies:
`
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(mergedXL)
wsSIR = wb.Sheets(1)
sheetList = wb.Sheets
for ws in sheetList:
used = ws.UsedRange
if ws.Name != "1st sheet":
print ("Copying cells from "+ws.Name)
used.Copy()
`
used.Copy() will copy ALL used cells, however I don't want the first row from any of the worksheets. I want to be able to copy from each sheet and paste it into the first blank row in the 1st sheet. So when cells from the first sheet (that is NOT the sheet I want to copy to) are pasted in the 1st sheet, they will be pasted starting in A3. Every subsequent paste needs to happen in the first available blank row. I probably haven't done a great job of explaining this, but would love some help. Haven't worked with win32com a ton.
I also have this code from one of my old scripts, but I don't understand exactly how it's copying stuff and how I can modify it to work for me this time around:
ws.Range(ws.Cells(1,1),ws.Cells(ws.UsedRange.Rows.Count,ws.UsedRange.Columns.Count)).Copy()
wsNew.Paste(wsNew.Cells(wsNew.UsedRange.Rows.Count,1))
If I understand well your problem, I think this code will do the job:
import win32com.client
# create an instance of Excel
excel = win32com.client.gencache.EnsureDispatch('Excel.Application')
# Open the workbook
file_name = 'path_to_your\file.xlsx'
wb = excel.Workbooks.Open(file_name)
# Select the first sheet on which you want to write your data from the other sheets
ws_paste = wb.Sheets('Sheet1')
# Loop over all the sheets
for ws in wb.Sheets:
if ws.Name != 'Sheet1': # Not the first sheet
used_range = ws.UsedRange.SpecialCells(11) # 11 = xlCellTypeLastCell from VBA Range.SpecialCells Method
# With used_range.Row and used_range.Col you get the number of row and col in your range
# Copy the Range from the cell A2 to the last row/col
ws.Range("A2", ws.Cells(used_range.Row, used_range.Column)).Copy()
# Get the last row used in your first sheet
# NOTE: +1 to go to the next line to not overlapse
row_copy = ws_paste.UsedRange.SpecialCells(11).Row + 1
# Paste on the first sheet starting the first empty row and column A(1)
ws_paste.Paste(ws_paste.Cells(row_copy, 1))
# Save and close the workbook
wb.Save()
wb.Close()
# Quit excel instance
excel.Quit()
I hope it helps you to understand your old code as well.
Have you considered using pandas?
import pandas as pd
# create list of panda dataframes for each sheet (data starts ar E6
dfs=[pd.read_excel("source.xlsx",sheet_name=n,skiprows=5,usecols="E:J") for n in range(0,4)]
# concatenate the dataframes
df=pd.concat(dfs)
# write the dataframe to another spreadsheet
writer = pd.ExcelWriter('merged.xlsx')
df.to_excel(writer,'Sheet1')
writer.save()

Categories

Resources