The piece of code reads an Excel file. This excel file holds information such as customer job numbers, customer names, sites, works description ect..
What this code will do when completed (I hope) is read the last line of the worksheet (this is taken from a counter on the worksheet at cell 'P1'), create folders based on cell content, and create a hyperlink on the worksheet to open the lowest local folder that was created.
I have extracted the info I need from the worksheet to understand what folders need to be created, but I am not able to write a hyperlink to the cell on the row in column B.
#Insert Hyperlink to folder
def folder_hyperlink(last_row_position, destination):
cols = 'B'
rows = str(last_row_position)
position = cols + rows
final_position = "".join(position)
print final_position # This is just to check the value
# The statement below should insert hyperlink in eps.xlsm > worksheet jobnoeps at column B and last completed row.
ws.cell(final_position).hyperlink = destination
The complete code is below but here is the section that is meant to create the hyperlink. I have also tried the 'xlswriter' package with no joy. Searched the internet and the above snippet is the result of what I found.
Anyone know what I am doing wrong?
__author__ = 'Paul'
import os
import openpyxl
from openpyxl import load_workbook
import xlsxwriter
site_info_root = 'C:\\Users\\paul.EPSCONSTRUCTION\\PycharmProjects\\Excel_Jobs\\Site Information\\'
# This function returns the last row on eps.xlsm to be populated
def get_last_row(cell_ref = 'P1'): #P1 contains the count of the used rows
global wb
global ws
wb = load_workbook("eps.xlsm", data_only = True) #Workbook
ws = wb["jobnoeps"] #Worksheet
last_row = ws.cell(cell_ref).value #Value of P1 from that worksheet
return last_row
# This function will read the job number in format EPS-XXXX-YR
def read_last_row_jobno(last_row_position):
last_row_data = []
for cols in range(1, 5):
last_row_data += str(ws.cell(column = cols, row = last_row_position).value)
last_row_data_all = "".join(last_row_data)
return last_row_data_all
#This function will return the Customer
def read_last_row_cust(last_row_position):
cols = 5
customer_name = str(ws.cell(column = cols, row = last_row_position).value)
return customer_name
#This function will return the Site
def read_last_row_site(last_row_position):
cols = 6
site_name = str(ws.cell(column = cols, row = last_row_position).value)
return site_name
#This function will return the Job Discription
def read_last_row_disc(last_row_position):
cols = 7
site_disc = str(ws.cell(column = cols, row = last_row_position).value)
return site_disc
last_row = get_last_row()
job_no_details = read_last_row_jobno(last_row)
job_customer = read_last_row_cust(last_row)
job_site = read_last_row_site(last_row)
job_disc = read_last_row_disc(last_row)
cust_folder = job_customer
job_dir = job_no_details + "\\" + job_site + " - " + job_disc
#Insert Hyperlink to folder
def folder_hyperlink(last_row_position, destination):
cols = 'B'
rows = str(last_row_position)
position = cols + rows
final_position = "".join(position)
print final_position # This is just to check the value
# The statement below should insert hyperlink in eps.xlsm > worksheet jobnoeps at column B and last completed row.
ws.cell(final_position).hyperlink = destination
folder_location = site_info_root + job_customer + "\\" + job_dir
print folder_location # This is just to check the value
folder_hyperlink(last_row, folder_location)
Now my hyperlink function looks like this after trying xlsxwriter as advised.
##Insert Hyperlink to folder
def folder_hyperlink(last_row_position, destination):
import xlsxwriter
cols = 'B'
rows = str(last_row_position)
position = cols + rows
final_position = "".join(position)
print final_position # This is just to check the value
workbook = xlsxwriter.Workbook('eps.xlsx')
worksheet = workbook.add_worksheet('jobnoeps')
print worksheet
worksheet.write_url(final_position, 'folder_location')
workbook.close()
The function overwrites the exsisting eps.xlsx, creates a jobnoeps table and then inserts the hyperlink. I have played with the following lines but don't know how to get it to open the existing xlsx and existing jobnoeps tab and then enter the hyperlink.
workbook = xlsxwriter.Workbook('eps.xlsx')
worksheet = workbook.add_worksheet('jobnoeps')
worksheet.write_url(final_position, 'folder_location')
The XlsxWriter write_url() method allows you to link to folders or other workbooks and worksheets as well as internal links and links to web urls. For example:
import xlsxwriter
workbook = xlsxwriter.Workbook('links.xlsx')
worksheet = workbook.add_worksheet()
worksheet.set_column('A:A', 50)
# Link to a Folder.
worksheet.write_url('A1', r'external:C:\Temp')
# Link to a workbook.
worksheet.write_url('A3', r'external:C:\Temp\Book.xlsx')
# Link to a cell in a worksheet.
worksheet.write_url('A5', r'external:C:\Temp\Book.xlsx#Sheet1!C5')
workbook.close()
See the docs linked to above for more details.
Here is the code that did the trick:-
# Creates hyperlink in existing workbook...
def set_hyperlink():
from openpyxl import load_workbook
x = "hyperlink address"
wb = load_workbook("filename.xlsx")
ws = wb.get_sheet_by_name("sheet_name")
ws.cell(row = x?, column = y?).hyperlink = x
wb.save("filename.xlsx")
set_hyperlink()
Tried again with openpyxl as advised.
Related
if i separate the code only for add image and only for copy the format all can work normally.But when i combine it and it's always come out : UserWarning: wmf image format is not supported so the image is being dropped.How to solve it ?
import openpyxl
import copy
from openpyxl.utils import get_column_letter
# It is not required for one to create a workbook on
# filesystem, therefore creating a virtual workbook
wrkb = openpyxl.Workbook()
# Number of sheets in the workbook (1 sheet in our case)
ws = wrkb.worksheets[0]
# Adding a row of data to the worksheet (used to
# distinguish previous excel data from the image)
path = "/Users/LEON/OneDrive/Desktop/copy.xlsx"
save_path = "/Users/LEON/OneDrive/Desktop/paste.xlsx"
wb = openpyxl.load_workbook(path)
wb2 = openpyxl.Workbook()
sheetnames = wb.sheetnames
for sheetname in sheetnames:
print(sheetname)
sheet = wb[sheetname]
sheet2 = wb2.create_sheet(sheetname)
# tab颜色
sheet2.sheet_properties.tabColor = sheet.sheet_properties.tabColor
# 开始处理合并单元格形式为“(<CellRange A1:A4>,),替换掉(<CellRange 和 >,)' 找到合并单元格
wm = list(sheet.merged_cells)
if len(wm) > 0:
for i in range(0, len(wm)):
cell2 = str(wm[i]).replace('(<CellRange ', '').replace('>,)', '')
sheet2.merge_cells(cell2)
for i, row in enumerate(sheet.iter_rows()):
sheet2.row_dimensions[i+1].height = sheet.row_dimensions[i+1].height
for j, cell in enumerate(row):
sheet2.column_dimensions[get_column_letter(j+1)].width = sheet.column_dimensions[get_column_letter(j+1)].width
sheet2.cell(row=i + 1, column=j + 1, value=cell.value)
# 设置单元格格式
source_cell = sheet.cell(i+1, j+1)
target_cell = sheet2.cell(i+1, j+1)
target_cell.fill = copy.copy(source_cell.fill)
if source_cell.has_style:
target_cell._style = copy.copy(source_cell._style)
target_cell.font = copy.copy(source_cell.font)
target_cell.border = copy.copy(source_cell.border)
target_cell.fill = copy.copy(source_cell.fill)
target_cell.number_format = copy.copy(source_cell.number_format)
target_cell.protection = copy.copy(source_cell.protection)
target_cell.alignment = copy.copy(source_cell.alignment)
# A wrapper over PIL.Image, used to provide image
# inclusion properties to openpyxl library
img = openpyxl.drawing.image.Image('hlrb_image.png')
# The Coordinates where the image would be pasted
# (an image could span several rows and columns
# depending on it's size)
img.anchor = 'A2'
# Adding the image to the worksheet
# (with attributes like position)
ws.add_image(img)
# Saving the workbook created under the name of out.xlsx
wrkb.save('out.xlsx')
i need a logo top there and copy format detail down there.If i separate run the code,it will delete the sheet.Like only the logo there or only the copy format there dont hv logo.
So far, I have been able to access csv and xlsx files in python, but I am unsure how to put in user inputs input() to add data to the spreadsheet.
I would also want this input() to only be enterable once per day but for different columns in my spreadsheet. (this is a separate issue)
Here is my code so far, first for csv, second for xlsx, I don't need both just either will do:
# writing to a CSV file
import csv
def main():
filename = "EdProjDBeg.csv"
header = ("Ans1", "Ans2", "Ans3")
data = [(0, 0, 0)]
writer(header, data, filename, "write")
updater(filename)
def writer(header, data, filename, option):
with open(filename, "w", newline = "") as csvfile:
if option == "write":
clidata = csv.writer(csvfile)
clidata.writerow(header)
for x in data:
clidata.writerow(x)
elif option == "update":
writer = csv.DictWriter(csvfile, fieldnames = header)
writer.writeheader()
writer.writerows(data)
else:
print("Option is not known")
# Updating the CSV files with new data
def updater(filename):
with open(filename, newline= "") as file:
readData = [row for row in csv.DictReader(file)]
readData[0]['Ans2'] = 0
readHeader = readData[0].keys()
writer(readHeader, readData, filename, "update")
# Reading and updating xlsx files
import openpyxl
theFile = openpyxl.load_workbook(r'C:\Users\joe_h\OneDrive\Documents\Data Analysis STUDYING\Excel\EdProjDBeg.xlsx')
print(theFile.sheetnames)
currentsheet = theFile['Customer1']
print(currentsheet['B3'].value)
wb = openpyxl.load_workbook(r'C:\Users\joe_h\OneDrive\Documents\Data Analysis STUDYING\Excel\EdProjDBeg.xlsx')
ws = wb.active
i = 0
cell_val = ''
# Finds which row is blank first
while cell_val != '':
cell_val = ws['A' + i].value
i += 1
# Modify Sheet, Starting With Row i
wb.save(r'C:\Users\joe_h\OneDrive\Documents\Data Analysis STUDYING\Excel\EdProjDBeg.xlsx')
x = input('Prompt: ')
This works for inputting data into an xlsx file.
Just use:
ws['A1'] = "data"
to input into cell A1
See code below for example using your original code:
wb = openpyxl.load_workbook('sample.xlsx')
print(wb.sheetnames)
currentsheet = wb['Sheet']
ws = currentsheet
#ws = wb.active <-- defaults to first sheet
i = 0
cell_val = ''
# Finds which row is blank first
while cell_val != None:
i += 1
cell_val = ws['A' + str(i)].value
print(cell_val)
x = input('Prompt: ')
#sets A column of first blank row to be user input
ws['A' + str(i)] = x
#saves spreadsheet
wb.save("sample.xlsx")
Also just made a few edits to your original while loop in the above code:
When a cell is blank, 'None' is returned
A1 is the first cell on the left, not A0 (moved i += 1 above finding value of cell)
Converted variable 'i' to a string when accessing the cell
See https://openpyxl.readthedocs.io/en/stable/ for the full documentation
I have researched through several similar threads of discussion on this forum and tried several things recommended, but I am not able to get all properties of the source worksheet copied over. Here's my code and I see that column widths and a few other things are not coped over. Would have been great if openpyxl implemented a function to copy a worksheet with all its attributes.
def copy_worksheet(src_xl, dest_xl, src_ws, dest_ws):
import openpyxl as xl
from copy import copy
# opening the source excel file
wb1 = xl.load_workbook(src_xl)
sheet_names = wb1.sheetnames
index = sheet_names.index(src_ws)
ws1 = wb1.worksheets[index]
# opening the destination excel file
wb2 = xl.load_workbook(dest_xl)
sheet_names = wb2.sheetnames
try:
index = sheet_names.index(dest_ws)
except:
ws2 = wb2.create_sheet(dest_ws)
else:
ws2 = wb2.worksheets[index]
# calculate total number of rows and
# columns in source excel file
mr = ws1.max_row
mc = ws1.max_column
# copying the cell values from source
# excel file to destination excel file
for i in range (1, mr + 1):
for j in range (1, mc + 1):
# reading cell value from source excel file
c = ws1.cell(row = i, column = j)
cell = c
# writing the read value to destination excel file
ws2.cell(row = i, column = j).value = c.value
new_cell = ws2.cell(row = i, column = j)
new_cell.font = copy(cell.font)
new_cell.border = copy(cell.border)
new_cell.fill = copy(cell.fill)
new_cell.number_format = copy(cell.number_format)
new_cell.protection = copy(cell.protection)
new_cell.alignment = copy(cell.alignment)
# saving the destination excel file
wb2.save(str(dest_xl))
This seems to do the job - to set the column widths:
from openpyxl.utils import get_column_letter
for i in range(ws1.max_column):
ws2.column_dimensions[get_column_letter(i+1)].width = ws1.column_dimensions[get_column_letter(i+1)].width
I have bunch of excel workbooks and I would like to get cell values from them and write to a new sheet.
My code is not appending new data.It is just overwriting cells with values from last workbook.
(I've changed the pasted code.It was pasted incorrect.)
Here is my code
from openpyxl import load_workbook
booklist = ["17_02.xlsx", "17_03.xlsx",
"17_04.xlsx", "17_05.xlsx",
"17_06.xlsx", "17_08.xlsx",
"17_09.xlsx", "17_10.xlsx"]
for wb in booklist:
book = load_workbook(filename =wb,data_only=True)
report = load_workbook(filename="dest.xlsx", data_only=True)
print(book)
sheet = book['Sheet']
reportsheet=report['First']
row_count=sheet.max_row
column_count=sheet.max_column
for r in range(1,row_count+1):
for c in range(1,column_count+1):
source=sheet.cell(row=r, column=c)
dest = reportsheet.cell(row=r, column=c)
dest.value = source.value
sheet.title = 'First'
book.save("dest.xlsx")
Edit:
After the mickNeill's answer I changed the code and it worked for appending.But now there is another problem.
If I run the code (after clearing the cells) second time or more it's appending the data to the rows after the cleared cells.
First run:
Data appended to A1:A20
Clear the cells,save and close the workbook.
Second run:
Data appended to A21:A20 instead of A1:A20 (cleared cells)
Every time I run the code value of the reportRow continues to increase (1,20,40 ...) and appending data to higher number of rows.
from openpyxl import load_workbook
booklist = ["17_02.xlsx", "17_03.xlsx",
"17_04.xlsx", "17_05.xlsx",
"17_06.xlsx", "17_08.xlsx",
"17_09.xlsx", "17_10.xlsx"]
for wb in booklist:
book = load_workbook(filename =wb,data_only=True)
report = load_workbook(filename="dest.xlsx", data_only=True)
print(book)
sheet = book['Sheet']
reportsheet=report['First']
row_count=sheet.max_row
reportRow = reportsheet.max_row
column_count=sheet.max_column
for r in range(1,row_count+2):
for c in range(1,column_count+1):
source=sheet.cell(row=r, column=c)
dest = reportsheet.cell(row=reportRow, column=c)
dest.value = source.value
reportRow += 1
report.save("dest.xlsx")
Try this: Editied, you are saving the wrong book, last line
from openpyxl import load_workbook
booklist = ["Book5.xlsx", "Book6.xlsx","Book7.xlsx"]
report = load_workbook(filename="dest.xlsx", data_only=True)
for wb in booklist:
book = load_workbook(filename =wb,data_only=True)
#print(book)
sheet = book['Sheet1']
reportsheet=report['First']
row_count=sheet.max_row
reportRow = reportsheet.max_row + 1
print reportRow
column_count=sheet.max_column
for r in range(1,row_count+1):
for c in range(1,column_count+1):
print reportRow
source=sheet.cell(row=r, column=c)
dest = reportsheet.cell(row=reportRow, column=c)
dest.value = source.value
sheet.title = 'First'
reportRow += 1
report.save("dest.xlsx")
I'm trying to write multiple excels' column A into a new excel's column A (assuming all the excels have one worksheet each.) I've written some code, which can write one excel's column A into the new excel's column A; but if there are multiple excels, the new excel's column A will be overwritten multiple times. So how could I just add all the column As to the new excel sheet one after another without overwriting each other?
Below are my code:
import os, openpyxl
path = os.getcwd()
def func(file):
for file in os.listdir(path):
if file.endswith('.xlsx'):
wb = openpyxl.load_workbook(file)
sheet = wb.active
colA = sheet['A']
wb = openpyxl.Workbook()
r = 1
for i in colA:
sheet = wb.active
sheet.cell(row=r, column=1).value = i.value
r += 1
wb.save('new.xlsx')
func(file)
Thank you so much!!
you could proceed for example as:
import os, openpyxl
path = os.getcwd()
def func(outputFile):
c = 0
#create output workbook
wbOut = openpyxl.Workbook()
sheetOut = wbOut.active
for fName in os.listdir(path):
if fName.endswith('.xlsx'):
c += 1 #move to the next column in output
wb = openpyxl.load_workbook(fName)
sheet = wb.active #input sheet
#for r in range(1, sheet.max_row+1):
# sheetOut.cell(row=r, column=c).value = sheet.cell(row = r, column = 1).value
for r, cell in enumerate(sheet['A']):
sheetOut.cell(row = r+1, column = c).value = cell.value
wbOut.save(outputFile)
#"concatenate" all columns A into one single column
def funcAppend(outputFile):
wbOut = openpyxl.Workbook()
sheetOut = wbOut.active
r = 1
for fName in os.listdir(path):
if fName.endswith('.xlsx'):
wb = openpyxl.load_workbook(fName)
sheet = wb.active
for cell in sheet['A']:
sheetOut.cell(row = r, column = 1).value = cell.value
r += 1
wbOut.save(outputFile)
func('test.xlsx')