openpyxl copy from one workbook to another - python

I am trying to copy the cells from one workbook to another, to do some manipulation. While i am able to assign style/value and assign it to new workbook i am unable to assign the font,fill from the existing workbook to new workbook.
Below is the snippet of my code
from openpyxl import load_workbook
from openpyxl import Workbook
File = load_workbook(filename='testcopy.xlsx')
FileSheets = File.get_sheet_names()
AcSheet = File.active
write_file = Workbook()
wr_ac_sheet = write_file.active
wr_ac_sheet['A1'].value = AcSheet['A1'].value
wr_ac_sheet['A1'].style = AcSheet['A1'].style
write_file.save('copied_excel.xlsx')
This works fine, but if i use
wr_ac_sheet['A1'].font= AcSheet['A1'].font
i get the below error
File "C:\Python27\lib\site-packages\openpyxl\writer\excel.py", line 90, in write_data
stylesheet = write_stylesheet(self.workbook)
File "C:\Python27\lib\site-packages\openpyxl\styles\stylesheet.py", line 206, in write_stylesheet
stylesheet.fonts = wb._fonts
File "C:\Python27\lib\site-packages\openpyxl\descriptors\sequence.py", line 27, in __set__
seq = [_convert(self.expected_type, value) for value in seq]
File "C:\Python27\lib\site-packages\openpyxl\descriptors\base.py", line 59, in _convert
raise TypeError('expected ' + str(expected_type))
TypeError: expected <class 'openpyxl.styles.fonts.Font'>
If i try to print the existing workbook font, i get this, so it's reading properly
print wr_ac_sheet['A1'].font
<openpyxl.styles.fonts.Font object>
Parameters:
name='Calibri', charset=None, family=2.0, b=False, i=False, strike=None,
outline=None, shadow=None, condense=None, color=
<openpyxl.styles.colors.Color
object>
Parameters:
tint=0.0, auto=None, theme=1L, rgb=None, indexed=None, type='theme',
extend=None, sz=11.0, u=None, vertAlign=None, scheme='minor'
i would like to assign all the properties of the cell (similar to format painter) to the new workbook, any guidance on how to do that?

As explained in the documentation you need to copy the style information.

Why do you set the explicit style?
#!/usr/bin/python3
# -*- coding: utf8 -*-
import sys
import openpyxl
import warnings
warnings.simplefilter("ignore")
xlsxfile = sys.argv[1]
xlscopy = sys.argv[2]
wb = openpyxl.load_workbook(xlsxfile)
sheet = wb['Sheet1']
val = sheet['J7'] # set up an initial value, eg. 34
val.value = 2
wb.save(xlscopy)
This works for me for big and complex formatted XLSX files.

Related

Copy Complete Excel row with values, formatting, formulas etc

Well I've a row which i want to copy complete.
I dont know how i can do that correctly in python.
i try to copy the code from another stackoverflow page. But if i test the code i get errors
my own code is this.
# Copy input to output
output_table = input_table.copy()
# conda install -c anaconda openpyxl
import os
import openpyxl
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
from copy import copy
from copy import deepcopy
from openpyxl.styles import Font, colors, Color, PatternFill, Border, Side, Alignment, Protection
def move_cell(source_cell, dest_row, dest_col, preserve_original=False):
#param source_cell: cell to be moved to new coordinates
#param dest_row: 1-indexed destination row
#param dest_col: 1-indexed destination column
#param preserve_original: if True, does a copy instead of a move
if preserve_original:
cell_to_move = copy.copy(source_cell)
else:
cell_to_move = source_cell
worksheet = cell_to_move.parent
source_address = (cell_to_move.row, cell_to_move.col_idx)
dest_address = (dest_row, dest_col)
cell_to_move.row = dest_row
cell_to_move.col_idx = dest_col
worksheet._cells[dest_address] = cell_to_move
if not preserve_original:
del worksheet._cells[source_address]
return cell_to_move
var_data_path = "C:/"
#var_path_excel_file = var_data_path + os.path.sep + "data.xlsx"
wb = load_workbook(var_path_excel_file)
ws = wb["test"]
# activate the ws 'data'
for s in range(len(wb.sheetnames)):
if wb.sheetnames[s] == ws:
break
wb.active = s
mr = ws.max_row
mc = ws.max_column
# copying the cell values from source
# excel file to destination excel file
for j in range (1, mc + 1):
c = ws.cell(row = 10, column = j)
#ws.cells is my idea. But it don't copy the style and dont manipulate the formulas. i.e. =D10 to =D12 . Dependent from the row. Move cell function is the function which i copied from another great user. But i get errors for that. i test this all with the row 10. I want to copy the row 10 to 15. My error is function' object has no attribute 'copy' Traceback (most recent call #last): File "<string>", line 85, in <module>
# File "<string>", line 19, in move_cell
#AttributeError: 'function' object has no attribute 'copy'
ws.cell(15, column = j).value = c.value
move_cell(c, 15, j, preserve_original=True)
#ws[15] = ws[10]
wb.save(var_path_excel_file)
In openpyxl, how to move or copy a cell range with formatting, merged cells, formulas and hyperlinks

Pandas and Tkinter , opening and saving files

I am trying to save the excel file as a .xlsx file then I want to import that new file back into python using pandas and numpy to allow for statistical analysis.
I want the USER to have the option of where to save the file with the 'asksaveasfile' and another dialog box 'askopenwhen opening the file for pandas and numpy.
Also, if someone can show how to convert specific columns from bytes to str. See below...
TypeError: write() argument must be str, not bytes.
Here's the end of the code:
import csv
import pandas as pd
import os
import tkinter as tk
from tkinter import filedialog
fn = filedialog.asksaveasfile(mode='w', defaultextension=".xlsx")
result = pdf_to_csv(fn)
lines = result.split('\n')
import openpyxl as pxl
wb = pxl.Workbook(fn)
ws = wb.active
for line in lines:
ws.append(line.split(';'))
# appending a list gives a complete row in xlsx
print("Successfully Saved! ")
root = tk.Tk()
root.withdraw()
dataFile=pd.read_excel(fn)#,usecols=['Last Name','First Name','Assignment Title','Department Code','Calendar Year', 'Compensation'])
dataFile.to_excel(fn)
print(fn)
df = fn
DataFrame = df
df1 = DataFrame
df1.columns = ['Last Name','First Name','Assignment Title','Department Code','Calendar Year', 'Compensation']
df1.drop(df1.index[0], inplace=True)
print(df1.head(11))

tkinter drop down menu from excel

I want to use tkinter to browse an excel sheet and make a drop down menu of the rows of that excel sheet.
I am pretty new to python and do not know how to work it through. The code until now looks like this:
import xlrd
import os
from subprocess import call
import Tkinter,tkFileDialog
root = Tkinter.Tk()
root.withdraw()
filename = tkFileDialog.askopenfiles(title='Choose an excel file')
print(filename)
print type(filename)
#file = str(filename)
file = [filetypes for filetypes in filename if ".xlsx" in filetypes]
workbook = xlrd.open_workbook(filename)
for file in filename:
sheet = workbook.sheet_by_index(0)
print(sheet)
for value in sheet.row_values(0):
print(value)
This throws an error:
Traceback (most recent call last):
File "C:/Geocoding/test.py", line 14, in
workbook = xlrd.open_workbook(filename)
File "C:\Python27\ArcGIS10.3\lib\site-packages\xlrd__init__.py", line 394, in open_workbook
f = open(filename, "rb")
TypeError: coercing to Unicode: need string or buffer, list found
I am not even able to read the excel sheet that the user browses. I have no idea why this error. I would really appreciate if anybody can help me with it. Am I on the right path ?
Thanks
The new code that works:
import xlrd
from Tkinter import *
import Tkinter,tkFileDialog
root = Tkinter.Tk()
root.withdraw()
filename = tkFileDialog.askopenfilename(title='Choose an excel file')
print(filename)
print type(filename)
#file = str(filename)
file = [filetypes for filetypes in filename if ".xlsx" in filetypes]
workbook = xlrd.open_workbook(filename)
#for file in filename:
sheet = workbook.sheet_by_index(0)
print(sheet)
for value in sheet.row_values(0):
print(value)
print(type(value))
master = Tk()
variable=StringVar(master)
#variable=sheet.row_values(0)[0]
variable.set(sheet.row_values(0)[0])
#for var in value:
# variable = StringVar(master)
# variable.set(value) # default value
#w = OptionMenu(master, variable, value)
w = apply(OptionMenu, (master, variable) + tuple(sheet.row_values(0)))
w.pack()
mainloop()
You may have more errors along the way but in your code here:
filename = tkFileDialog.askopenfiles(title='Choose an excel file')
the result from that dialog is a list of file objects. So you are passing that list of fileobjects to open_workbook here:
workbook = xlrd.open_workbook(filename)
Instead what you need to do is pass the name of the file you care about as a string to open_workbook:
workbook = xlrd.open_workbook(filename[0].name) # the name of the first file in the list
here is a working Python3 (sorry I abandoned Python2) example for tkinter to properly select filenames:
from tkinter import filedialog
from tkinter import *
root = Tk()
root.withdraw()
filename = filedialog.askopenfiles(title='Choose an excel file')
print(filename) # filename is a list of file objects
print(filename[0].name) # this is the name of the first selected in the dialog that you can pass to xlrd

insert text file into existing xlsx using Python

I have a .xlsx file with 11 worksheets and I need to insert the contents of a text file (tab delim, roughly 30 columns with 100 rows) from Row 3 onwards. I tried the code below but I end up with errors. (using bash/Linux)
#!/usr/bin/env python
import csv
from openpyxl.reader.excel import load_workbook
from xlrd import open_workbook
from xlutils import copy as xl_copy
with open('S12_final.txt') as tab_file: #open tab text file
tab_reader = csv.reader(tab_file, delimiter='\t')
xls_readable_book = load_workbook('S12.xlsx') #load workbook
xls_writeable_book = xl_copy.copy(xls_readable_book)
xls_writeable_sheet = xls_writeable_book.get_sheet_by_name('Filtered') #write data on this sheet
for row_index, row in enumerate(tab_reader):
xls_writeable_sheet.write(row_index, 0, row[0])
xls_writeable_sheet.write(row_index, 1, row[1])
xls_writeable_book.save('S12.xlsx') #save excel file
Errors:
> Traceback (most recent call last): File "./tab2excel_a.py", line 23,
> in <module>
> xls_writeable_book = xl_copy.copy(xls_readable_book) File "/usr/local/lib/python2.7/dist-packages/xlutils-1.6.0-py2.7.egg/xlutils/copy.py",
> line 19, in copy
> w File "/usr/local/lib/python2.7/dist-packages/xlutils-1.6.0-py2.7.egg/xlutils/filter.py",
> line 937, in process
> reader(chain[0]) File "/usr/local/lib/python2.7/dist-packages/xlutils-1.6.0-py2.7.egg/xlutils/filter.py",
> line 61, in __call__
> filter.workbook(workbook,filename) File "/usr/local/lib/python2.7/dist-packages/xlutils-1.6.0-py2.7.egg/xlutils/filter.py",
> line 287, in workbook
> self.wtbook.dates_1904 = rdbook.datemode AttributeError: 'Workbook' object has no attribute 'datemode'
Any suggestions ?
It seems (and by no means I'm knowledgeable about those particular libraries) that you are attempting to input an openpyxl object into an xlutils method in these lines:
xls_readable_book = load_workbook('S12.xlsx') #load workbook
xls_writeable_book = xl_copy.copy(xls_readable_book)
So the interpreter complains that this "unknown" object has no attribute datemode. As so try using xlrd open_workbook method since it seems to return a Book object which, according to the documentation, is fully compatible with xlrd.copy methods:
xls_readable_book = open_workbook('S12.xlsx') #load workbook
xls_writeable_book = xl_copy.copy(xls_readable_book)
Consider this openpyxl example:
from openpyxl.workbook.workbook import Workbook # as _Workbook
import csv
wb = Workbook()
wb.create_sheet('Filtered')
ws = wb['Filtered']
with open('test/S12_final.csv') as tab_file:
tab_reader = csv.reader(tab_file, delimiter='\t')
# Skipt first 2 Lines
[next(tab_reader) for skip in range(2)]
# Append list(rowData) after Sheets last accessed Row
for rowData in tab_reader:
ws.append(rowData)
wb.save('test/S12.xlsx')
Tested with Python: 3.4.2 - openpyxl: 2.4.1 - LibreOffice: 4.3.3.2

Python: Autofill cells in Excel according to a formula in previous cells

Using Python and win32com:
I have a formula in an Excel file, at cells A5:A54. I'm trying to fill the cells A55:A61 with values according to the same formula. I searched online and found this:
http://pythonexcels.com/python-excel-mini-cookbook/
Quote from the link:
"This script uses Excel’s autofill capability to examine data in cells A1 and A2, then autofill the remaining column of cells through A10." The code from the link:
#
# Autofill cell contents
#
import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Add()
ws = wb.Worksheets("Sheet1")
ws.Range("A1").Value = 1
ws.Range("A2").Value = 2
ws.Range("A1:A2").AutoFill(ws.Range("A1:A10"),win32.constants.xlFillDefault)
wb.SaveAs('autofill_cells.xlsx')
excel.Application.Quit()
So I tried it in my code:
from win32com.client import Dispatch
from win32com.client import constants
import os
from Tkinter import Tk
from tkFileDialog import askopenfilename
import win32com.client as win32
xlApp = Dispatch("Excel.Application")
...
print "Choose the excel file that you want to copy the data to"
Tk().withdraw()
filename_to = askopenfilename()
xlBook_to = xlApp.Workbooks.Open(filename_to)
xlApp.Visible=1
xlSheet_to_final = xlBook_to.Sheets(1)
xlBook_to.Activate()
xlSheet_to_final.Range("A53:A54").Select()
xlSheet_to_final.Range("A53:A54").AutoFill(xlSheet_to_final.Range("A55:A61"),win32.constants.xlFillDefault)
And I get this error:
File "C:\Users\<user>\excel_test.py", line 74, in <module>
xlSheet_to_final.Range("A53:A54").AutoFill(xlSheet_to_final.Range("A55:A61"),win32.constants.xlFillDefault)
File "C:\Python27\Lib\site-packages\win32com\gen_py\00020813-0000-0000-C000-000000000046x0x1x8\Range.py", line 66, in AutoFill
, Type)
File "C:\Python27\Lib\site-packages\win32com\client\__init__.py", line 459, in _ApplyTypes_
self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, u'Microsoft Excel', u'AutoFill method of Range class failed', u'xlmain11.chm', 0, -2146827284), None)
How do I fix it? How do I apply the formulas of the previous cells on the following cells?
Try
from win32com.constants import xlFillDefault
....
xlSheet_to_final.Range("A53:A54").AutoFill(xlSheet_to_final.Range("A53:A61"), xlFillDefault)

Categories

Resources