openpyxl ValueError formatting new rows of data - python-3.x

The following code works great the first time I run it (when it creates a new spreadsheet).
When I try to run it again (update existing sheet) to add more data (additional rows) I get the following error
Traceback (most recent call last):
File "C:/PythonPrograms/Workout Program/test_excel_format.py", line 35, in
cell.style = wdata
File "C:\Users\Mark\AppData\Local\Programs\Python\Python37\lib\site-packages\openpyxl\styles\named_styles.py", line 193, in append
raise ValueError("""Style {0} exists already""".format(style.name))
ValueError: Style wdata exists already
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl import load_workbook
from openpyxl.styles import Font, Color, Alignment, Border, Side, colors
from openpyxl.styles import NamedStyle
from datetime import date
from os import path
filename = "format_wb_test.xlsx"
if path.exists(filename):
workbook = load_workbook(filename)
else:
workbook = Workbook()
sheet = workbook.active
tdate = date.today()
data = [tdate, "Data 1", "Data 2", "Data 3"]
wdata = NamedStyle(name="wdata")
wdata.font = Font(bold=True)
wdata.alignment = Alignment(horizontal="center", vertical="center")
for x in range(1, 3):
sheet.append(data) # appends the data to the first empty row.
print("current row: ", sheet._current_row)
ucell = "A" + str(sheet._current_row)
wdata_row = sheet[sheet._current_row]
for cell in wdata_row:
cell.style = wdata
sheet[ucell] = tdate
workbook.save(filename=filename)
I want to be able to add new rows of formatted data esch time I run this code.

I don't see any way to use a NamedStyle to update the format for rows added to an existing
workbook/sheet. If you define the NamedStyle you get the "Already Exists" error. If you don't then you get an error that the "NamedStyle is not defined". The doc states pretty much verbatim what Charlie Clark said in his comment above, "Styles registered automatically on their first use and can then be referenced by name." It does not elaborate or show examples of how to use an existing NamedStyle. Given this I gave up trying to use a NamedStyle and updated the code as follows to make it work. If there is a way to do this with NamedStyle I'd love to see it.
Here's the updated code.
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl import load_workbook
from openpyxl.styles import Font, Color, Alignment, Border, Side, colors
from openpyxl.styles import NamedStyle
from datetime import date
from os import path
filename = "format_wb_test.xlsx"
if path.exists(filename):
workbook = load_workbook(filename)
else:
workbook = Workbook()
sheet = workbook.active
tdate = date.today()
data = [tdate, "Data 1", "Data 2", "Data 3"]
# wdata = NamedStyle(name="wdata")
# wdata.font = Font(bold=True)
# wdata.alignment = Alignment(horizontal="center", vertical="center")
for x in range(1, 3):
sheet.append(data) # appends the data to the first empty row.
print("current row: ", sheet._current_row)
ucell = "A" + str(sheet._current_row)
wdata_row = sheet[sheet._current_row]
for cell in wdata_row:
#cell.style = wdata
sheet[str(cell.coordinate)].font = Font(bold=True)
sheet[str(cell.coordinate)].alignment = Alignment \
(horizontal="center", vertical="center")
sheet[ucell] = tdate
workbook.save(filename=filename)

Related

Trying to edit a ms word document and save as a pdfusing django

I want to read data from a ms excel file and edit an existing words document using the data from excel to fill in bookmarks and then save it as a pdf. So far I have been able to read to data successfully using openpyxl but I'm struggling with the editing and saving part. It would be great if someone can help.
my code:
from django.shortcuts import render
from django.http import HttpResponse
import openpyxl
from reportlab.pdfgen import canvas
import io
from io import BytesIO
def index(request):
if "GET" == request.method:
return render(request, 'letters/index.html', {})
else:
excel_file = request.FILES["excel_file"]
# you may put validations here to check extension or file size
wb = openpyxl.load_workbook(excel_file)
# getting a particular sheet by name out of many sheets
worksheet = wb.sheetnames
if 'sheet name' in wb.sheetnames:
sheet = wb['sheet name']
print(worksheet)
excel_data = list()
# iterating over the rows and
# getting value from each cell in row
for name in wb.sheetnames:
sheet = wb[name]
first = False
for row in sheet.iter_rows():
row_data = list()
for cell in row:
row_data.append(str(cell.value))
print (row_data)
if first == False:
pass
else:
buffer = io.BytesIO()
p = canvas.Canvas(buffer)
f = open("media/template.docx", "w+")
for x in range (5):
def BookMarkReplace():
f.Bookmark = name,
string = row_data[0])
{
Admission = row_data[2]
p.drawString(doc)
p.showPage()
p.save()
response ['Content-Disposition'] = 'attachment;filename=Admission.docx'
return response
first = True
excel_data.append(row_data)
return render(request, 'letters/index.html', {"excel_data":excel_data})
I'm not having any luck with this method. Does anyone know how to do this or any other way of doing this.
Solved it!!!
I used python-doxc to edit my word documents. I still couldn'f figure out how to use bookmarks, but instead I replaced the parts I want to edit like so:
for paragraph in document.paragraphs:
if 'Name of the student : ' in paragraph.text:
paragraph.text = 'Name of the student : ' + Name
Then I used pypandoc to covnvert them to pdfs.
pypandoc.convert_file('template.docx', 'pdf', outputfile='S' + ' ' + Name + '.pdf')

multiple column style with python openpyxl

I want to specify the style of the columns in the table. If I select only one column as the style, it works, but if I want to specify more than one of the columns. I get this error message: AttributeError: 'tuple' object has no attribute 'style'
import openpyxl
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Font, Color, Alignment, Border, Side, colors
from openpyxl.styles import NamedStyle
path = "my xlsx file path"
workbook = load_workbook(path)
sheet = workbook.active
sheet
shetnames_str = workbook.sheetnames
print(shetnames_str)
print(sheet)
dimensions = sheet.dimensions
print("Dimenzió: "+dimensions)
selected_sheetname = workbook["Munka1"]
#Style definition
highlight = NamedStyle(name="highlight")
bd = Side(style='thin', color="000000")
highlight.border = Border(left=bd, top=bd, right=bd, bottom=bd)
for cell in sheet["A:B"]:
print(cell)
cell.style = highlight
workbook.save(filename="moddedxlsx.xlsx")
I modified my code
import openpyxl
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Font, Color, Alignment, Border, Side, colors
from openpyxl.styles import NamedStyle
path = "C:\\Users\\Jutasig\\Documents\\python_jegyzetek\\Dev\\Style\\master_xls_style\\szamla.xlsx"
workbook = load_workbook(path)
sheet = workbook.active
sheet
shetnames_str = workbook.sheetnames
print(shetnames_str)
print(sheet)
dimensions = "\""+sheet.dimensions+"\""
print("Dimenzió: "+dimensions)
selected_sheetname = workbook["Munka1"]
#Style definition
def set_border(ws, cell_range):
border = Border(left=Side(border_style='thin', color='000000'),
right=Side(border_style='thin', color='000000'),
top=Side(border_style='thin', color='000000'),
bottom=Side(border_style='thin', color='000000'))
rows = ws[cell_range]
for row in rows:
for cell in row:
cell.border = border
set_border(sheet, sheet.dimensions)
workbook.save(filename="moddedxlsx.xlsx")

Printing the value of a formula with openpyxl

I have been trying to research this for the past 2 days and the most regular answer I see is to use data_only=True however that does not seem to fix the issue of printing the value of a formula. Here is my scrip. Does anyone have an answer for this?
import os
import openpyxl
from openpyxl import Workbook
from openpyxl.reader.excel import load_workbook
from openpyxl import load_workbook
import csv
directoryPath = r'c:\users\username\documents\reporting\export\q3'
os.chdir(directoryPath)
folder_list = os.listdir(directoryPath)
for folders, sub_folders, file in os.walk(directoryPath):
for name in file:
if name.startswith("BEA"):
filename = os.path.join(folders, name)
print filename
wb = load_workbook(filename, data_only=True)
sheet = wb.get_sheet_by_name("Sensor Status")
for row_cells in sheet.iter_rows(min_row=1, max_row=4, min_col=8, max_col=13):
for cell in row_cells:
print cell.internal_value

Apply same process on multiple files on the same folder using Python

I need to read all the csv files on a specific folder and then apply a specific process (calculate some parametres) on each file and for each file I need to ceate an excel file in which I have to store the results.
For now I have been able to apply the calculation for each file manually, but I need to automate the process, which means the only input should be the folder's name instead of going through the folder and each csv file is considered as an input.
I have been advised to use Pandas for the matter but I couldn't figure out how.
My question is, is it even possible to do it with Python?
This is a part of my code :
main.py
from Dlt2Excel_Fct import *
from ModePrvPblc_Fct import *
from FilePaths import filename_csv, filename_asc, filepath
start = time.time()
dlt2excel()
ModePrvPblcGps()
duree = time.time()-start
print('duree', duree)
Dlt2Excel_Fct.py
import pandas as pd
import xlsxwriter
import sys
import os
from tkinter import filedialog
from tkinter import *
from FilePaths import filename_csv
def dlt2excel():
""" Enter the directory of the exported csv file"""
user_input=filename_csv
# user_input = input("Enter the path of your file: ")
assert os.path.exists(user_input), "I did not find the file at, "+str(user_input)
f = open(user_input,'r+')
print("We found your file!")
"""Organize the exported file """
inputFile = f
workbook = xlsxwriter.Workbook('output01.xlsx')
worksheet = workbook.add_worksheet()
exportFile = open('output01.xlsx', 'w')
workbook.close()
for line in inputFile:
new_line = line.replace(',', '\t')
exportFile.write(new_line)
f.close()
inputFile.close()
exportFile.close()
df = pd.read_table('output01.xlsx', error_bad_lines=False) # for '\t'
df.to_excel('output1.xlsx', 'Sheet1')
"""Count the number of duplicates """
data = pd.read_excel(r'output1.xlsx', header = 0)
data.count()
data['count'] = data.groupby(['Payload'])['Index'].transform('count')
data.to_excel('OutputDLT.xlsx', sheet_name='sheet1', index=False)
print("Conversion is done!\n")
ModePrvPblc_Fct.py
import openpyxl
from openpyxl import Workbook
from openpyxl import load_workbook
#from ExcelName import filepath
from FilePaths import filepath
filename =filepath
def ModePrvPblcGps():
file_name='OutputDLT.xlsx'
wb = openpyxl.load_workbook(file_name, read_only=False)
ws = wb.active
sheet = wb['sheet1']
ls = []
PsgPrv=0
PsgPblc=0
for row in ws.iter_rows():
for cell in row:
#print('Cell: [{}] is type({}): "{}"'.format(cell.coordinate, type(cell.value).__name__, cell.value))
if cell.value == 'SQLR: K<ATT_PRIVACY_MODE> V<1>':
PsgPrv+=1
if cell.value == 'SQLR: K<ATT_PRIVACY_MODE> V<0>':
PsgPblc+=1
print('Passage en mode public: ', PsgPblc)
print('Passage en mode privé: ', PsgPrv)
wb = load_workbook(filename)
ws = wb.worksheets[0]
parametres = (
['Passage en mode privé ', PsgPrv],
['Passage en mode public ', PsgPblc],
)
for row_ in (parametres):
ws.append(row_ )
wb.save(filename)
FilePaths.py
import tkinter as tk
from tkinter.simpledialog import askstring
from tkinter import filedialog
import os
import openpyxl
import warnings
warnings.filterwarnings("ignore")
root = tk.Tk()
folder_selected = filedialog.askdirectory()
print(folder_selected)
path=folder_selected + "/"
nom = askstring("Name", "Enter the name of the result file")
print(nom)
if nom == None:
nom= str(None)
else:
nom = nom +".xlsx"
if not os.path.exists(path):
os.makedirs(path)
filepath = path +nom
if not os.path.isfile(filepath):
wb = openpyxl.Workbook(filepath)
wb.save(filename = filepath)
root.file_name = filedialog.askopenfilename(initialdir = "/",title = "Select csv file",filetypes = (("csv files","*.csv"),("all files","*.*")))
filename_csv=root.file_name
print (filename_csv)
root.file_name1 = filedialog.askopenfilename(initialdir = "/",title = "Select trace file",filetypes = (("asc files","*.asc"),("all files","*.*")))
filename_asc=root.file_name1
print (filename_asc)
root.withdraw()
I've many folders that contain multiple csv file that's why I need to automate the process.

panda save and read excel in loop

I have a loop where I call a function in which I loop to read an excel, then write and save it. But at the end I only the last result is stored.
As a simple example
for i in range(3):
callfunc(i)
callfunc(i)
panda open excel
for j in range(10:13:1)
write in excel(i,j) in new sheet
save excel
As final result i only get (3,10) (3, 11) (3,12).
It seems when re-opening the excel in the callfunc the excel doesn't get saved but the original excel is kept and I dont get why.
Thank you !
Let's use separate sheet_name:
import pandas as pd
import numpy as np
from openpyxl import load_workbook
path = r"~\Desktop\excelData\data.xlsx"
book = load_workbook(path)
for i in range(3):
writer = pd.ExcelWriter(path, engine = 'openpyxl')
writer.book = book
df = pd.DataFrame(x3)
df.to_excel(writer, sheet_name = '{}__sheet'.format(i))
writer.save()
writer.close()

Resources