I have created an xls file in which I write some user inputs into the cells. So far so good, the program works; it writes the first line. But when I run again the program instead of appending the rows it writes on top of the first one. I'm trying to understand how to make it append a new row into the excel sheet save it and close it etc
import xlsxwriter
workbook = xlsxwriter.Workbook("test.xlsx",)
worksheet = workbook.add_worksheet()
row = 0
col = 0
worksheet.write(row, col, 'odhgos')
worksheet.write(row, col + 1, 'e/p')
worksheet.write(row, col + 2, 'dromologio')
worksheet.write(row, col + 3, 'ora')
row += 1
worksheet.write_string(row, col, odigosou)
worksheet.write_string(row, col + 1, dromou)
worksheet.write_string(row, col + 2, dromologio)
worksheet.write_string(row, col + 3, ora)
workbook.close()
With this code I created I'm able to write in the file but how do I make it to append a row in the existing sheet. All tutorials I watched, all instructions I researched, just don't work; I'm doing something wrong obviously but I'm not able to spot it.
Question: ... how do I make it to append a row in the existing sheet
Solution using openpyxl, for instance:
from openpyxl import load_workbook
new_row_data = [
['odhgos', 'e/p', 'dromologio', 'ora'],
['odigosou', 'dromou', 'dromologio', 'ora']]
wb = load_workbook("test/test.xlsx")
# Select First Worksheet
ws = wb.worksheets[0]
# Append 2 new Rows - Columns A - D
for row_data in new_row_data:
# Append Row Values
ws.append(row_data)
wb.save("test/test.xlsx")
Tested with Python: 3.4.2 - openpyxl: 2.4.1 - LibreOffice: 4.3.3.2
Another solution which avoids FileNotFound errors by creating the file if it doesn't exist:
from openpyxl import Workbook
from openpyxl import load_workbook
filename = "myfile.xlsx"
new_row = ['1', '2', '3']
# Confirm file exists.
# If not, create it, add headers, then append new data
try:
wb = load_workbook(filename)
ws = wb.worksheets[0] # select first worksheet
except FileNotFoundError:
headers_row = ['Header 1', 'Header 2', 'Header 3']
wb = Workbook()
ws = wb.active
ws.append(headers_row)
ws.append(new_row)
wb.save(filename)
# Note: if you're adding values from a list, you could instead use:
# new_row = ""
# new_row += [val for val in list]
# Similarly, for adding values from a dict:
# new_row = ""
# new_row = += [val for val in mydict['mykey'].values()]
Related
There are two excel files, where the data on condition should be appended to another excel file.
CONDITION: If Any value in Column A is equal to 'x' then it should get value from col B and get it appended directly to col A/B in excel file 2.
The below table is present in Excel File 1.
The below should be the output... which is in Excel file 2.
Am new to this.. please help with this code, and preferably if code is done using "Openpyxl", it would be much helpful !
Thanks in advance.
A slight improvement on Redox's solution:
import openpyxl
#Open Input File open (file1)
wb1 = openpyxl.load_workbook('file1.xlsx')
ws1 = wb1['Sheet1']
wb2 = openpyxl.Workbook()
ws2 = wb2.active
ws2.append(["Base", "A/B"])
for row in ws1.iter_rows(min_row=2, max_col=3, values_only=True):
base, a, b = row
if a != "x":
new_row = [base, a]
else:
new_row = [base, b]
ws2.append(new_row)
Ideally you should also check that the third column has a valid value.
So, a simple solution and a more complicated one:
Then between files you can use a link or index() or indirect().
To do this using python-openpyxl, you can use the below code... added comments so it is easy to understand... hope this helps. Let me know in case of questions.
The python code
import openpyxl
#Open Input File open (file1)
wb1 = openpyxl.load_workbook('file1.xlsx')
ws1 = wb1['Sheet1']
#Create new file for Output (file2)
wb2 = openpyxl.Workbook()
ws2 = wb2.active
#Add header to output file
ws2.cell(row=1,column=1).value = "BASE"
ws2.cell(row=1,column=2).value = "A/B"
# Iterate through each line in input file from row 2 (skipping header) to last row
for row in ws1.iter_rows(min_row=2, max_row=ws1.max_row, min_col=1, max_col=3):
for col, cell in enumerate(row):
if col == 0: #First column, write to output
ws2.cell(cell.row, col+1).value = cell.value
elif col == 1:
if cell.value != "X": #2nd column, write to output if not X
ws2.cell(cell.row, col+1).value = cell.value
else: #2nd column, write 3rd column if X
ws2.cell(cell.row, col+1).value = ws1.cell(cell.row, col+2).value
wb2.save('file2.xlsx')
Output excel after running
This question already has an answer here:
Copy paste column range using OpenPyxl
(1 answer)
Closed 5 years ago.
I have data in an excel file, but for it to be useful I need to copy & paste the columns into a different order.
I have figured out how to open & read my file and to write a new excel file. I can also get the data from the original, and paste it into my new file but not in a loop.
here's an example of the data i'm working with to visualize my issue i need A1,B1,C1 next to each other and then A2,B2,C2, etc etc.
Here is my code from a smaller test file I created to play around with:
import openpyxl as op
wb = op.load_workbook('coding_test.xlsx')
ws = wb.active
mylist = []
mylist2 = []
mylist3 = []
for row in ws.iter_rows('H13:H23'):
for cell in row:
mylist.append(cell.value)
for row in ws.iter_rows('L13:L23'):
for cell in row:
mylist2.append(cell.value)
for row in ws.iter_rows('P13:P23'):
for cell in row:
mylist3.append(cell.value)
print (mylist, mylist2, mylist3)
new_wb = op.Workbook()
dest_filename = 'empty_coding_test.xlsx'
new_ws = new_wb.active
for row in zip (mylist, mylist2, mylist3):
new_ws.append(row)
new_wb.save(filename=dest_filename)
I want to create a loop to do the rest of the work, but I can't figure out how to design it so that I don't have to code for each column and set.
well, you can recycle code doing something like:
import openpyxl as op
wb = op.load_workbook('coding_test.xlsx')
ws = wb.active
new_wb = op.Workbook()
dest_filename = 'empty_coding_test.xlsx'
new_ws = new_wb.active
for row in ws.iter_rows('H13:H23'):
for cell in row:
new_ws['A%s' % cell].value = cell.value
for row in ws.iter_rows('L13:L23'):
for cell in row:
new_ws['B%s' % cell].value = cell.value
for row in ws.iter_rows('P13:P23'):
for cell in row:
new_ws['C%s' % cell].value = cell.value
new_wb.save(filename=dest_filename)
tell me if that work for you
I'm trying to build a report generator which reads excel sheets and returns rows which contain values. I built a version which works as I require but only works for csv this is only my 1st code-mash-together, but it worked. I now would like to include conditional formatting as well (highlight certain cells values eg. if <65 format red) and so that required that I rewrite with xlsx sheets rather than csv.
Below is my attempt at getting this to work...
I can find the values and return the row, but on the second run through it returns an error
AttributeError: 'Worksheet' object has no attribute 'cell_value'
Which is surprising because it worked just previously and stepping through the code retuns the values I want.... I have tried changing it to .value, but returns:
AttributeError: 'function' object has no attribute 'value'
Help, I have no idea what I'm doing now. If it doens't make any sense i'm happy to post my original code for the csv to 'explain'
Thanks
import xlsxwriter
import xlrd
import os
import xlwt
# open original excelbook and access first sheet
for excelDocs in os.listdir('.'):
if not excelDocs.endswith('.xlsx'):
continue # skip non-xlsx files
workbook = xlrd.open_workbook(excelDocs)
sheet = workbook.sheet_by_index(0)
cellslist = []
i = 0
#########WORKS!#####################
for row in range(sheet.nrows):
for col in range(sheet.ncols):
if sheet.cell_value(row, col) == 'CP' or sheet.cell_value(row, col) == 'LNA' or sheet.cell_value(row, col) == 'Last Name':
i = i + 1
data = [sheet.cell_value(0, col) for col in range(sheet.ncols)]
workbook = xlsxwriter.Workbook()
sheet = workbook.add_worksheet('excelDocs')
for index, value in enumerate(data):
sheet.write(i, index, value)
workbook = xlrd.open_workbook(excelDocs)
I have no experience with xlsxwriter, xlrd or xlwt. As this is your "1st code-mash-together" I figured I would offer an alternative using openpyxl.
I do not have your data, so testing is a little difficult, but any syntax errors could be fixed. Please let me know if this does not run and I will help fix if required.
I am assuming your output is to a seperate file(report.xlsx here) and a tab for each workbook checked(each tab named for source book name).
import openpyxl
from openpyxl import *
from openpyxl.utils import get_column_letter
interestingValues = ['CP','LNA', 'LastName']
report = Workbook()
dest_filename = 'report.xlsx'
# open original excelbook and access first sheet
for excelDocs in os.listdir('.'):
if not excelDocs.endswith('.xlsx'):
continue # skip non-xlsx files
workbook = load_workbook(excelDocs)
sheet = workbook.active
workingReportSheet = report.create_sheet(str(excelDocs.split('.')[0]))
i = 0
for row in range(1,sheet.max_row):
for col in range(sheet.max_column):
columnLetter = get_column_letter(col +1)
if str(sheet['%s%s' % (columnLetter,row)].value) in interestingValues:
i += 1
data = [sheet['%s%s' % (str(get_column_letter(col)),i)].value for col in range(1,sheet.max_column +1)]
for index, value in enumerate(data):
workingReportSheet['%s%s' % (str(get_column_letter(index+1)),i)].value = value
report.save(filename = dest_filename)
Reading your code again, it may be that you are discarding your output.
Try the below.
import xlsxwriter
import xlrd
import os
import xlwt
#Create output sheet
outputworkbook = xlsxwriter.Workbook()
# open original excelbook and access first sheet
for excelDocs in os.listdir('.'):
if not excelDocs.endswith('.xlsx'):
continue # skip non-xlsx files
workbook = xlrd.open_workbook(excelDocs)
sheet = workbook.sheet_by_index(0)
cellslist = []
i = 0
outputsheet = outputworkbook.add_worksheet('excelDocs')
for row in range(sheet.nrows):
for col in range(sheet.ncols):
if sheet.cell_value(row, col) == 'CP' or sheet.cell_value(row, col) == 'LNA' or sheet.cell_value(row, col) == 'Last Name':
i = i + 1
data = [sheet.cell_value(0, col) for col in range(sheet.ncols)]
for index, value in enumerate(data):
outputsheet.write(i, index, value)
I want to transfer my data which is in 'Sheet1' into worksheet 'Sheet2'in the same workbook, using python.I have written the script below, but facing an 'IndexError: list index out of range'. I know this is not the best way to go about it. I will appreciate if anyone can guide me with a more efficient way to go about it. I am sharing the Snapshot of excel file below
Can I directly enter 'Sheet1' cell value ---> 'Sheet2' cell value rather than doing 'Sheet1' cell value ---> List---->'Sheet2' cell value?
import openpyxl
wb = openpyxl.load_workbook('C:\Users\laban\Desktop\Par-emails1.xlsx')
type(wb)
wb.get_sheet_names()
sheet = wb.get_sheet_by_name('Sheet1')
type(sheet)
anotherSheet = wb.active
sheet1 = wb.get_sheet_by_name('Sheet2')
type(sheet1)
par=[sheet.cell(row= col, column=1).value for col in range(1, 2450)]
email_no=[sheet.cell(row= col, column=2).value for col in range(1, 2450)]
Domain=[sheet.cell(row= col, column=3).value for col in range(1, 2450)]
email=[sheet.cell(row= col, column=4).value for col in range(1, 2450)]
for x in range(0,2450):
if email_no[x]<9:
sheet1.cell(row= x+1, column=1).value=par[x]
sheet1.cell(row= x+1, column=2).value=email_no[x]
sheet1.cell(row= x+1, column=3).value=Domain[x]
sheet1.cell(row= x+1, column=4).value=email[x]
wb.save('C:\Users\laban\Desktop\Par-emails1.xlsx')
You can use:
wb = openpyxl.load_workbook('C:/Users/laban/Desktop/Par-emails1.xlsx')
sheet1 = wb.get_sheet_by_name('Sheet1')
sheet2 = wb.get_sheet_by_name('Sheet2')
for i,row in enumerate(sheet1.iter_rows()):
for j,col in enumerate(row):
sheet2.cell(row=i+1,column=j+1).value = col.value
Apparently in 2.4 you can do this with one command: Copy whole worksheet with openpyxl
Obviously this is very simplified version from what I am currently using.
Here is a code snippet to copy data from sheet1 to sheet2 without any formatting.
You dont need to specify max rows , max columns as you can get it using
sheet.max_row and sheet.max_columns methods.
from openpyxl.cell import Cell
max_row = sheet1.max_row #Get max row of first sheet
max_col = sheet1.max_column #Get max column of first sheet
for row_num in range(1,max_row + 1): #Iterate through rows
for col_num in range(1, max_col + 1): #Iterate through columns
_cell1 = sheet1.cell(row=row_num, column=col_num)
_cell2 = sheet2.cell(row=row_num, column=col_num)
_cell2.value = _cell1.value
Added extra variables for understanding. You can compact at your end.
bernie probably has the best answer here (Copy whole worksheet) but your index error might be coming from:
par=[sheet.cell(row= col, column=1).value for col in range(1, 2450)]
being 1 cell shorter than:
for x in range(0,2450):
def excel_op():
filename='D://Python//excelread.xlsx'
sheet_name='Sheet1'
book = xlrd.open_workbook(str(filename))
sheet = book.sheet_by_name(sheet_name)
workbook = xlsxwriter.Workbook('excelwrite.xlsx')
worksheet = workbook.add_worksheet()
row_count = int(sheet.nrows)
col_count = int(sheet.ncols)
for row in range(0, int(row_count)):
for col in range(0, int(col_count)):
worksheet.write(row,col,str(sheet.cell(row, col).value))
workbook.close()
del book
shutil.copy("Source.xlsx", "target.xlsx")
I'm working on a script that modifies an existing excel document and I need to have the ability to insert a column between two other columns like the VBA macro command .EntireColumn.Insert.
Is there any method with openpyxl to insert a column like this?
If not, any advice on writing one?
Here is an example of a much much faster way:
import openpyxl
wb = openpyxl.load_workbook(filename)
sheet = wb.worksheets[0]
# this statement inserts a column before column 2
sheet.insert_cols(2)
wb.save("filename.xlsx")
Haven't found anything like .EntireColumn.Insert in openpyxl.
First thought coming into my mind is to insert column manually by modifying _cells on a worksheet. I don't think it's the best way to insert column but it works:
from openpyxl.workbook import Workbook
from openpyxl.cell import get_column_letter, Cell, column_index_from_string, coordinate_from_string
wb = Workbook()
dest_filename = r'empty_book.xlsx'
ws = wb.worksheets[0]
ws.title = "range names"
# inserting sample data
for col_idx in xrange(1, 10):
col = get_column_letter(col_idx)
for row in xrange(1, 10):
ws.cell('%s%s' % (col, row)).value = '%s%s' % (col, row)
# inserting column between 4 and 5
column_index = 5
new_cells = {}
ws.column_dimensions = {}
for coordinate, cell in ws._cells.iteritems():
column_letter, row = coordinate_from_string(coordinate)
column = column_index_from_string(column_letter)
# shifting columns
if column >= column_index:
column += 1
column_letter = get_column_letter(column)
coordinate = '%s%s' % (column_letter, row)
# it's important to create new Cell object
new_cells[coordinate] = Cell(ws, column_letter, row, cell.value)
ws._cells = new_cells
wb.save(filename=dest_filename)
I understand that this solution is very ugly but I hope it'll help you to think in a right direction.