Is there a way to modify existing xlsm file using python? - python

I have an xlsm file and I have come across various methods to modify the file by creating a new file using openpyxl or xlw. Is there any way that I can modify my current file without having to create a new one everytime in the process?
from openpyxl import workbook
wb = openpyxl.load_workbook(filename = 'filename', read_only = False, keep_vba = True)
sheet = wb.get_sheet_by_name('UI')
wb.save('outfile.xlsm')
However, I do not want to create a new file each time I run the code and just want to modify my current file but openpyxl is not compatible with .xlsm type files?
Is there any way to do this?

OpenPyXL 2.6.2 does support xlsm files. Just overwrite your existing workbook.
import openpyxl
wb = openpyxl.load_workbook(filename = 'filename.xlsm', read_only = False, keep_vba = True)
sheet = wb['UI']
wb.save('filename.xlsm')

Related

openpyxl save workbook to file with path

I use Openpyxl in Python to write some data in an Excel file using Workbook.
When I want to save the workbook to a file, I can only provide a filename argument, so I can not write files in other directories.
here is my sample code:
import openpyxl
file_name = "sample.xlsx"
wb = openpyxl.Workbook()
# writing some data to workbook
wb.save(filename=file_name)
I have checked the documentation via this link and found nothing more.
Python: 3.10.7
Openpyxl: 3.0.10
Can you help me provide workarounds to solve this problem?
You can indicate a full path + filename, and it will create a file where you need it:
wb = Workbook()
wb.save(r'D:\folder\folder\folder\Filename.xlsx')

Pandas dataframe to specific sheet in a excel file without losing formatting

I have a dataframe like as shown below
Date,cust,region,Abr,Number,
12/01/2010,Company_Name,Somecity,Chi,36,
12/02/2010,Company_Name,Someothercity,Nyc,156,
df = pd.read_clipboard(sep=',')
I would like to write this dataframe to a specific sheet (called temp_data) in the file output.xlsx
Therfore I tried the below
import pandas
from openpyxl import load_workbook
book = load_workbook('output.xlsx')
writer = pandas.ExcelWriter('output.xlsx', engine='openpyxl')
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
I also tried the below
path = 'output.xlsx'
with pd.ExcelWriter(path) as writer:
writer.book = openpyxl.load_workbook(path)
final_df.to_excel(writer, sheet_name='temp_data',startrow=10)
writer.save()
But am not sure whether I am overcomplicating it. I get an error like as shown below. But I verifiedd in task manager, no excel file/task is running
BadZipFile: File is not a zip file
Moreover, I also lose my formatting of the output.xlsx file when I manage to write the file based on below suggestions. I already have a neatly formatted font,color file etc and just need to put the data inside.
Is there anyway to write the pandas dataframe to a specific sheet in an existing excel file? WITHOUT LOSING FORMATTING OF THE DESTIATION FILE
You need to just use to_excel from pandas dataframe.
Try below snippet:
df1.to_excel("output.xlsx",sheet_name='Sheet_name')
If there is existing data please try below snippet:
writer = pd.ExcelWriter('output.xlsx', engine='openpyxl')
# try to open an existing workbook
writer.book = load_workbook('output.xlsx')
df.to_excel(writer,index=False,header=False,startrow=len(reader)+1)
writer.save()
writer.close()
Are you restricted to using pandas or openpyxl?
Because if you're comfortable using other libraries, the easiest way is probably using win32com to puppet excel as if you were a user manually copying and pasting the information over.
import pandas as pd
import io
import win32com.client as win32
import os
csv_text = """Date,cust,region,Abr,Number
12/01/2010,Company_Name,Somecity,Chi,36
12/02/2010,Company_Name,Someothercity,Nyc,156"""
df = pd.read_csv(io.StringIO(csv_text),sep = ',')
temp_path = r"C:\Users\[User]\Desktop\temp.xlsx" #temporary location where to write this dataframe
df.to_excel(temp_path,index = False) #temporarily write this file to excel, change the output path as needed
excel = win32.Dispatch("Excel.Application")
excel.Visible = True #Switch these attributes to False if you'd prefer Excel to be invisible while excecuting this script
excel.ScreenUpdating = True
temp_wb = excel.Workbooks.Open(temp_path)
temp_ws = temp_wb.Sheets("Sheet1")
output_path = r"C:\Users\[User]\Desktop\output.xlsx" #Path to your output excel file
output_wb = excel.Workbooks.Open(output_path)
output_ws = output_wb.Sheets("Output_sheet")
temp_ws.Range('A1').CurrentRegion.Copy(Destination = output_ws.Range('A1')) # Feel free to modify the Cell where you'd like the data to be copied to
input('Check that output looks like you expected\n') # Added pause here to make sure script doesn't overwrite your file before you've looked at the output
temp_wb.Close()
output_wb.Close(True) #Close output workbook and save changes
excel.Quit() #Close excel
os.remove(temp_path) #Delete temporary excel file
Let me know if this achieves what you were after.
I spent all day on this (and a co-worker of mine spent even longer). Thankfully, it seems to work for my purposes - pasting a dataframe into an Excel sheet without changing any of the Excel source formatting. It requires the pywin32 package, which "drives" Excel as if it a user, using VBA.
import pandas as pd
from win32com import client
# Grab your source data any way you please - I'm defining it manually here:
df = pd.DataFrame([
['LOOK','','','','','','','',''],
['','MA!','','','','','','',''],
['','','I pasted','','','','','',''],
['','','','into','','','','',''],
['','','','','Excel','','','',''],
['','','','','','without','','',''],
['','','','','','','breaking','',''],
['','','','','','','','all the',''],
['','','','','','','','','FORMATTING!']
])
# Copy the df to clipboard, so we can later paste it as text.
df.to_clipboard(index=False, header=False)
excel_app = client.gencache.EnsureDispatch("Excel.Application") # Initialize instance
wb = excel_app.Workbooks.Open("Template.xlsx") # Load your (formatted) template workbook
ws = wb.Worksheets(1) # First worksheet becomes active - you could also refer to a sheet by name
ws.Range("A3").Select() # Only select a single cell using Excel nomenclature, otherwise this breaks
ws.PasteSpecial(Format='Unicode Text') # Paste as text
wb.SaveAs("Updated Template.xlsx") # Save our work
excel_app.Quit() # End the Excel instance
In general, when using the win32com approach, it's helpful to record yourself (with a macro) doing what you want to accomplish in Excel, then reading the generated macro code. Often this will give you excellent clues as to what commands you could invoke.
The solution to your problem exists here: How to save a new sheet in an existing excel file, using Pandas?
To add a new sheet from a df:
import pandas as pd
from openpyxl import load_workbook
import os
import numpy as np
os.chdir(r'C:\workdir')
path = 'output.xlsx'
book = load_workbook(path)
writer = pd.ExcelWriter(path, engine = 'openpyxl')
writer.book = book
### replace with your df ###
x = np.random.randn(100, 2)
df = pd.DataFrame(x)
df.to_excel(writer, sheet_name = 'x')
writer.save()
writer.close()
You can try xltpl.
Create a template file based on your output.xlsx file.
Render a file with your data.
from xltpl.writerx import BookWriterx
writer = BookWriterx('template.xlsx')
d = {'rows': df.values}
d['tpl_name'] = 'tpl_sheet'
d['sheet_name'] = 'temp_data'
writer.render_sheet(d)
d['tpl_name'] = 'other_sheet'
d['sheet_name'] = 'other'
writer.render_sheet(d)
writer.save('out.xls')
See examples.

Getting sheet names from a large Excel file

I am using Python 3.7 and using OpenPyxl to read the sheet names from a large excel workbook (29MB) with 10 tabs.
import openpyxl
from openpyxl import load_workbook
wb = load_workbook(filename='h:\\Master_Portfoliio.xlsx')
print(wb.sheetnames)
The code above works for smaller files but when I use the same code for this file, the code just hangs. I would like to read the sheet names and then remove a tab and then copy a tab from another excel workbook into this workbook.
Have you tried the read_only = True flag?
wb = load_workbook(filename='h:\\Master_Portfoliio.xlsx', read_only = True)

Writing into existing excel file

I have a .xlsx file in which multiple worksheets are there (with some content). I want to write some data into specific sheets say sheet1 and sheet5. Right now I am doing it using xlrd, xlwt, and xlutils copy() function. But is there any way to do it by opening the file in append mode and adding the data and save it (Like as we do it for the text/CSV files)?
Here is my code:
rb = open_workbook("C:\text.xlsx",formatting_info='True')
wb = copy(rb)
Sheet1 = wb.get_sheet(8)
Sheet2 = wb.get_sheet(7)
Sheet1.write(0,8,'Obtained_Value')
Sheet2.write(0,8,'Obtained_Value')
value1 = [1,2,3,4]
value2 = [5,6,7,8]
for i in range(len(value1)):
Sheet1.write(i+1,8,value1[i])
for j in range(len(value2)):
Sheet2.write(j+1,8,value2[j])
wb.save("C:\text.xlsx")
You can do it using the openpyxl module or using the xlwings module
Using openpyxl
from openpyxl import workbook #pip install openpyxl
from openpyxl import load_workbook
wb = load_workbook("C:\text.xlsx")
sheets = wb.sheetnames
Sheet1 = wb[sheets[8]]
Sheet2 = wb[sheets[7]]
#Then update as you want it
Sheet1 .cell(row = 2, column = 4).value = 5 #This will change the cell(2,4) to 4
wb.save("HERE PUT THE NEW EXCEL PATH")
the text.xlsx file will be used as a template, all the values from text.xlsx file together with the updated values will be saved in the new file
Using xlwings
import xlwings
wb = xlwings.Book("C:\text.xlsx")
Sheet1 = wb.sheets[8]
Sheet2 = wb.sheets[7]
#Then update as you want it
Sheet1.range(2, 4).value = 4 #This will change the cell(2,4) to 4
wb.save()
wb.close()
Here the file will be updated in the text.xlsx file but if you want to have a copy of the file you can use the code below
shutil.copy("C:\text.xlsx", "C:\newFile.xlsx") #copies text.xslx file to newFile.xslx
and use
wb = xlwings.Book("C:\newFile.xlsx") instead of wb = xlwings.Book("C:\text.xlsx")
As a user of both modules I prefer the second one over the first one.
For manipulating existing excel files you should use openpyxl. Other common libraries like the ones you are using dont support manipulating existing excel files. A workaround is to
save your output file as a different name - text_temp.xlsx
delete your original file - text.xlsx
rename your output file - text_temp.xlsx to text.xlsx

Data not present in excel sheet

I'm reading a existing excel file by using openpyxl package and trying to save that file it, and it got saved but after opening that excel file no data is present. I used the following code and my requirement is to open the file in use_iterators = True mode only
from openpyxl import load_workbook
wb = load_workbook(filename = 'large_file.xlsx', use_iterators = True)
ws = wb.get_sheet_by_name(name = 'big_data')
for row in ws.iter_rows():
for cell in row:
print cell.internal_value
wb.save("large_file.xlsx")
can u guys show how to save the file and close the file after saving with out losing the data
Try loading with use_iterators = False, as use_iterators = True loads the data information differently, such that it may not contain all the information you wish to save.
Openpyxl writes and entirely new excel file based on the information it has read in, so it's not like you make a small change and just update the file. (This also means if certain features aren't supported in openpyxl (such as VB macros), these won't exist in the file you've saved.)

Categories