Change the data source of a pivot table with xlwings - python

I am currently using the xlwings package to manipulate an excel file. So far, this package is fantastic, but I do not find a lot of specific documentation on how to modify a pivot table. My main question is how can I change the data source for a specific pivot table?
I think this is a general question so I won't provide any kind of code or excel file.
Thank you for the help.

Ok, a friend of mine found this website with an answer https://blog.csdn.net/weixin_39906906/article/details/111374735
but since it's in Chinese, I will post the necessary code below.
I don't understand everything about this answer. The win32c object is unknown to me and therefore, I am not comfortable in explaining everything.
import xlwings as xw
import win32com.client as win32
win32c = win32.constants
# open you excel workbook
wb = xw.Book('excel.xlsx')
# select sheet containing the pivot table
sheet_with_pivot_table = wb.sheets['sheet_pivot_table']
# Write the data range as written in the excel app
data_range = 'sheet_with_data!$A$1:$D$4'
# get the pivot table
pivot_table = sheet_with_pivot_table.api.PivotTables('pivot_table_name')
# This applies the new data
pivot_table.ChangePivotCache(wb.api.PivotCaches().Create(SourceType=win32c.xlDatabase, SourceData=data_range, Version=win32c.xlPivotTableVersion12))
Hopefully, this helps someone else.

See in this example, with the pivotname that you can change.
import xlwings as xw
app_excel = xw.App(visible = False)
wbook = xw.Book( 'Excelfile.xlsx' )
wbook.sheets['datatab'].select()
wbook.api.ActiveSheet.PivotTables('pivotname').PivotCache().refresh()

Related

How to save excel file with openpyxl and preserve pivot table as is?

I have an excel file - one sheet is used for writing data with python, other sheet contains pivot table. I want to keep pivot table exactly the same as source file.
The problem is that after saving new workbook with openpyxl I open excel file and refresh pivot table, it loses 'Field settings..' -> 'Repeat items label' checkbox and I need to manually turn it on each time. That is not very efficient, I would rather solve this with python.
Sample file has it checked, but checkbox seems to disappear after saving new file with openpyxl.
from openpyxl import load_workbook
from pathlib import Path
from datetime import date
import os
sample_file_path = Path('sample_excel.xlsx') # source excel
result_folder_path = Path('results')
wb = load_workbook(sample_file_path)
ws = wb["t_mm"] # worksheet with pivot table I want to preserve as is
# some manipulations to other worksheet
xlsx_filename = "test_my_file_%s.xlsx" % date.today().strftime('%d%m%Y')
completename = os.path.join(result_folder_path, xlsx_filename)
wb.save(completename)
I read the documentation https://openpyxl.readthedocs.io/en/stable/api/openpyxl.pivot.table.html, but couldn't figure out how to keep that checkbox. I am not excel or pivot table expert. I think this is the parameter I need "showMultipleLabel=True", but from docs I understand that it's "True" by default, so my chekbox should remain intact. Maybe other parameter?

Is there a way to protect workbooks using openpyxl or xlswriter?

I'm trying to automate Excel reports, and I'd prefer users didn't try to rename or reorder the worksheets. While I've had no problems protecting individual cells using xlsxwriter, I've failed to see an option to protect the workbook itself. I'm looking to openpyxl, but the tutorial does not seem to have any effect.
Edit: I'm now using this block of code, but does neither produce an error or protect my workbooks.
from openpyxl import load_workbook
from openpyxl.workbook.protection import WorkbookProtection
workbook = load_workbook(filepath, read_only=False, keep_vba=True)
workbook.security = WorkbookProtection(workbookPassword = 'secret-password', lockStructure = True)
workbook.save(filepath)
By the way, I am dealing with .xlsm files. If there are any solutions or points that I've missed, please let me know.
From this code:
from openpyxl.workbook.protection import WorkbookProtection
myWorkbook.security = WorkbookProtection(workBookPassword = 'super-secret-password', lockStructure = True)
myWorkbook.save(filepath)
Change:
WorkbookProtection(workBookPassword = 'super-secret-password', lockStructure = True)
to:
WorkbookProtection(workbookPassword = 'super-secret-password', lockStructure = True)
workBookPassword should be workbookPassword
Tested on Python32 3.8 and OpenPyXL version 3.0.2
Xlsxwriter has the option to protect the workbook with the command worksheet.protect() (have a look at the documentation: https://xlsxwriter.readthedocs.io/worksheet.html )
However take into consideration this:
Worksheet level passwords in Excel offer very weak protection. They do
not encrypt your data and are very easy to deactivate. Full workbook
encryption is not supported by XlsxWriter since it requires a
completely different file format and would take several man months to
implement.
Try using xlwings
import xlwings as xw
wb = xw.Book(r'<path_to_.xlsx file>')
wb.save(password='<your_password>', path=r'<path_to_save_.xlsx file>')

Python: Write a dataframe to an already existing excel which contains a sheet with images

I have been working on this for too long now. I have an Excel with one sheet (sheetname = 'abc') with images in it and I want to have a Python script that writes a dataframe on a second separate sheet (sheetname = 'def') in the same excel file. Can anybody provide me with some example code, because everytime I try to write the dataframe, the first sheet with the images gets emptied.
This is what I tried:
book = load_workbook('filename_of_file_with_pictures_in_it.xlsx')
writer = pd.ExcelWriter('filename_of_file_with_pictures_in_it.xlsx', engine = 'openpyxl')
writer.book = book
x1 = np.random.randn(100, 2)
df = pd.DataFrame(x1)
df.to_excel(writer, sheet_name = 'def')
writer.save()
book.close()
It saves the random numbers in the sheet with the name 'def', but the first sheet 'abc' now becomes empty.
What goes wrong here? Hopefully somebody can help me with this.
Interesting question! With openpyxl you can easily add values, keep the formulas but cannot retain the graphs. Also with the latest version (2.5.4), graphs do not stay. So, I decided to address the issue with
xlwings :
import xlwings as xw
wb = xw.Book(r"filename_of_file_with_pictures_in_it.xlsx")
sht=wb.sheets.add('SheetMod')
sht.range('A1').value = np.random.randn(100, 2)
wb.save(r"path_new_file.xlsx")
With this snippet I managed to insert the random set of values and saved a new copy of the modified xlsx.As you insert the command, the excel file will automatically open showing you the new sheet- without changing the existing ones (graphs and formulas included). Make sure you install all the interdependencies to get xlwings to run in your system. Hope this helps!
You'll need to use an Excel 'reader' like Openpyxl or similar in combnination with Pandas for this, pandas' to_excel function is write only so it will not care what is inside the file when you open it.

Opening, writing, and modifying to an existing workbook using Python

I am new to Python and working on a project that I could use some help on. So I am trying to modify an existing excel workbook in order to compare stock data. Luckily, there was a program online that retrieved all the data I need and I have successful been able to pull the data and write the data into a new excel file. However, the goal is to pull the data and put it into an existing excel file. Furthermore, I need to overwrite the cell values in the existing file. I believe xlwings is able to do this and I think my code is on the right track, but I ran into an unexpected error. The error I get is:
com_error: (-2147352570, 'Unknown name.', None, None)
I was wondering if anyone knew why this error came up? Also, does anyone know how to fix it? Is it fixable? Is my code wrong? Any help or guidance is appreciated. Thank you.
import good_morning as gm
import pandas as pd
import xlwings as xw
#import income statement, balance sheet, and cash flow of AAPL
fd = gm.FinancialsDownloader()
fd_frames = fd.download('AAPL')
#Creates a DataFrame for only the balance sheet
df1 = pd.DataFrame(list(fd_frames.values())[0])
#connects to workbook I want to modify (this is where I get the commerror)
wb = xw.Book(r'C:/Users/vince/Project/Spreadsheet.xlsm')
#sheet I would like to modify
sht = wb.sheets[1]
#modifies & overwrites values in my spreadsheet
sht.range('M6').value = df1

Write data into existing excel file and making summary table

I have to write some data into existing xls file.(i should say that im working on unix and couldnt use windows)
I prefer work with python and have tried some libraries like xlwt, openpyxl, xlutils.
Its not working, cause there is some filter in my xls file. After rewriting this file filter is dissapearing. But i still need this filter.
Could some one tell me about options that i have.
help, please!
Example:
from xlutils.copy import copy
from xlrd import open_workbook
from xlwt import easyxf
start_row=0
rb=open_workbook('file.xls')
r_sheet=rb.sheet_by_index(1)
wb=copy(rb)
w_sheet=wb.get_sheet(1)
for row_index in range(start_row, r_sheet.nrows):
row=r_sheet.row_values(row_index)
call_index=0
for c_el in row:
value=r_sheet.cell(row_index, call_index).value
w_sheet.write(row_index, call_index, value)
call_index+=1
wb.save('file.out.xls');
I also tried:
import xlrd
from openpyxl import Workbook
import unicodedata
rb=xlrd.open_workbook('file.xls')
sheet=rb.sheet_by_index(0)
wb=Workbook()
ws1=wb.create_sheet("Results", 0)
for rownum in range(sheet.nrows):
row=sheet.row_values(rownum)
arr=[]
for c_el in row:
arr.append(c_el)
ws1.append(arr)
ws2=wb.create_sheet("Common", 1)
sheet=rb.sheet_by_index(1)
for rownum in range(sheet.nrows):
row=sheet.row_values(rownum)
arr=[]
for c_el in row:
arr.append(c_el)
ws2.append(arr)
ws2.auto_filter.ref=["A1:A15", "B1:B15"]
#ws['A1']=42
#ws.append([1,2,3])
wb.save('sample.xls')
The problem is still exist. Ok, ill try to find machine running on windows, but i have to admit something else:
There is some rows like this:
enter image description here
Ive understood what i was doing wrong, but i still need help.
First of all, i have one sheet that contains some values
Second sheet contains summary table!!!
If i try to copy this worksheet it did wrong.
So, the question is : how could i make summary table from first sheet?
Suppose your existing excel file has two columns (date and number).
This is how you will append additional rows using openpyxl.
import openpyxl
import datetime
wb = openpyxl.load_workbook('existing_data_file.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')
a = sheet.get_highest_row()
sheet.cell(row=a,column=0).value=datetime.date.today()
sheet.cell(row=a,column=1).value=30378
wb.save('existing_data_file.xlsx')
If you are on Windows, I would suggest you take a look at using the win32com.client approach. This allows you to interact with your spreadsheet using Excel itself. This will ensure that any existing filters, images, tables, macros etc should be preserved.
The following example opens an XLS file adds one entry and saves the whole workbook as a different XLS formatted file:
import win32com.client as win32
import os
excel = win32.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(r'input.xls')
ws = wb.Worksheets(1)
# Write a value at A1
ws.Range("A1").Value = "Hello World"
excel.DisplayAlerts = False # Allow file overwrite
wb.SaveAs(r'sample.xls', FileFormat=56)
excel.Application.Quit()
Note, make sure you add full paths to your input and output files.

Categories