I want to make a pdf somposed by ranges in all Excel-workbooks located in a given folder (folderwithallfiles). All workbooks will have the same structure so the range reference will be the same for all workbooks.
I thought I got it with the script below, but it does not work.
import win32com.client as win32
import glob
import os
xlfiles = sorted(glob.glob("*.xlsx"))
#print "Reading %d files..."%len(xlfiles)
cwd = "C:\\Users\\user\folderwithallfiles"
#cwd = os.getcwd()
path_to_pdf = r'C:\\Users\\user\folderwithallfiles\multitest.pdf'
excel = win32.gencache.EnsureDispatch('Excel.Application')
for xlfile in xlfiles:
wb = excel.Workbooks.Open(cwd+"\\"+xlfile)
ws = wb.Sheets('sheet 1')
ws.Range("A1:Q59").Select()
wb.ActiveSheet.ExportAsFixedFormat(0, path_to_pdf)
Please check the below code if it works. I have written on the fly. Let me know if you find issues in it.
import pandas as pd
import numpy as np
import glob
import pdfkit as pdf
all_data = pd.DataFrame()
for f in glob.glob("filepath\file*.xlsx"):
df = pd.read_excel(f)
all_data = all_data.append(df, ignore_index=True)
all_data.to_html("filepath\all_data.html)
pdf.from_file("filepath\all_data.html", "filepath\all_data.pdf")
Related
Trying to save Excel files with multiple sheets as corresponding CSV files.
I tried the following method:
import xlrd
from openpyxl import Workbook, load_workbook
import pathlib
import shutil
import pandas as pd
def strip_xlsx(inputdir, file_name, targetdir):
wb = load_workbook(inputdir)
sheets = wb.sheetnames
for s in sheets:
temp_df = pd.read_excel(inputdir, sheet_name=s)
temp_df.to_csv(targetdir + "/" + file_name.strip(".xlsx") + "_" + s + ".csv", encoding='utf-8-sig')
Where inputdir is an absolute path to a the Excel file (say: "/Users/me/test/t.xlsx"), file_name is just the name of the file ("t.xlsx") and target_dir is a path to which I wish to save the csv files.
The methods works well, thought super slow. I'm a newbie to Python and feel like I implemented the method in a very inefficient way.
Would appreciate tips from the masters.
You may have better luck if you keep everything in pandas. I see you are using openpyxl to get the sheet names, you can do this in pandas. As for speed, you'll just have to see:
EDIT:
As Charlie (the person who probably knows the most about openpyxl on the planet) pointed out, using just openpyxl will be faster. In this case about 25% faster (9.29 ms -> 6.87 ms for my two-sheet test):
from os import path, mkdir
from openpyxl import load_workbook
import csv
def xlsx_to_multi_csv(xlsx_path: str, out_dir: str = '.') -> None:
"""Write each sheet of an Excel file to a csv
"""
# make the out directory if it does not exist (this is not EAFP)
if not path.exists(out_dir):
mkdir(out_dir)
# set the prefix
prefix = path.splitext(xlsx_path)[0]
# load the workbook
wb = load_workbook(xlsx_path, read_only=True)
for sheet_name in wb.sheetnames:
# generate the out path
out_path = path.join(out_dir, f'{prefix}_{sheet_name}.csv')
# open that file
with open(out_path, 'w', newline='') as file:
# create the writer
writer = csv.writer(file)
# get the sheet
sheet = wb[sheet_name]
for row in sheet.rows:
# write each row to the csv
writer.writerow([cell.value for cell in row])
xlsx_to_multi_csv('data.xlsx')
You just need to specify a path to save the csv's to, and iterate through a dictionary created by pandas to save the frames to the directory.
csv_path = '\path\to\dir'
for name,df in pd.read_excel('xl_path',sheet_name=None).items():
df.to_excel(os.path.join(csv_path,name)
Python excel methods doesn't work correctly.
import pandas as pd
import os
from openpyxl import load_workbook
path = "C:\\My files\\Staff\\xProject\\ProjektExcelPython\\test_files\\"
spreadsheet_file = pd.read_excel(os.path.join(path, "PlikExcelDoKonwersji.xlsx"), engine='openpyxl', header = 1)
print(spreadsheet_file)
It works perfectly, but if I would like to use methods from openpyxl I have error.
import pandas as pd
import os
from openpyxl import load_workbook
path = "C:\\My files\\Staff\\xProject\\ProjektExcelPython\\test_files\\"
spreadsheet_file = pd.read_excel(os.path.join(path, "PlikExcelDoKonwersji.xlsx"), engine='openpyxl', header = 1)
#sheet = spreadsheet_file.sheet_by_name('sheet')
book = load_workbook(path, "PlikExcelDoKonwersji.xlsx")
sheet = book['SendMail1']
data = []
for row in sheet.rows:
print(row[1].value)
Error:
line 94, in _validate_archive
raise InvalidFileException(msg)
openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support file format, please check you can open it with Excel first. Supported formats are: .xlsx,.xlsm,.xltx,.xltm
Process finished with exit code 1
load_workbook function only takes a single argument for file-path.
try
book = load_workbook(os.path.join(path, "PlikExcelDoKonwersji.xlsx"))
Instead of making the path 2 values, make it 1.
For Example, Try:
book = load_workbook("C:\\My files\\Staff\\xProject\\ProjektExcelPython\\test_files\\PlikExcelDoKonwersji.xlsx")
Thanks guys it works but now another problem occurs.
I would like to start as before without first row, I used header = 1, but now it doesn't work I go for documentation.
def load_workbook(filename, read_only=False, keep_vba=KEEP_VBA,
data_only=False, keep_links=True):
So it isn't there. How you manage it in openpyxl?
I would like to make something like:
Find name in column[1], the same will be in column[2] and get one of data from row[7] using column[1] and column[2].
Thanks for any suggestions.
I have roughly 30 excel workbooks I need to combine into one. Each workbook has a variable number of sheets but the sheet I need to combine from each workbook is called "Output" and the format of the columns in this sheet is consistent.
I need to import the Output sheet from the first file, then append the remaining files and ignore the header row.
I have tried to do this using glob/pandas to no avail.
You could use openpyxl. Here's a sketch of the code:
from openpyxl import load_workbook
compiled_wb = load_workbook(filename = 'yourfile1.xlsx')
compiled_ws = compiled['Output']
for i in range(1, 30):
wb = load_workbook(filename = 'yourfile{}.xlsx'.format(i))
ws = wb['Output']
compiled_ws.append(ws.rows()[1:]) # ignore row 0
compiled_wb.save('compiled.xlsx')
Method shown by Clinton c. Brownley in Foundations for Analytics with Python:
execute in shell indicating the path to the folder with excel files ( make sure the argument defining all_workbooks is correct) and then followed by the excel output file as follows:
python script.py <the /path/ to/ excel folder/> < your/ final/output.xlsx>
script.py:
import pandas as pd
import sys
import os
import glob
input_path = sys.argv[1]
output_file = sys.argv[2]
all_workbooks = glob.glob(os.path.join(input_file, '*.xlsx'))
all_df = []
for workbook in all_workbooks:
all_worksheets = pd.read_excel(workbook, sheetname='Output', index_col=None)
for worksheet, data in all_worksheets.items:
all_df.append(data)
data_concatenated = pd.concat(all_df, axis=0, ignore_index=True)
writer = pd.ExcelWriter(output_file)
data_concatenated.to_excel(writer, sheetname='concatenated_Output', index=False)
writer.save()
This will probably get down-voted because this isn't a Python answer, but honestly, I wouldn't use Python for this kind of task. I think you are far better off installing the AddIn below, and using that for the job.
https://www.rondebruin.nl/win/addins/rdbmerge.htm
Click 'Merge all files from the folder in the Files location selection' and click 'Use a Worksheet name' = 'Output', and finally, I think you want 'First cell'. Good luck!
I am looking to gather all the data from the penultimate worksheet in this Excel file along with all the data in the last Worksheet from "Maturity Years" of 5.5 onward. The code I have below currently grabs data from solely the last workbook and I was wondering what the necessary alterations would be.
import urllib2
import pandas as pd
import os
import xlrd
url = 'http://www.bankofengland.co.uk/statistics/Documents/yieldcurve/uknom05_mdaily.xls'
socket = urllib2.urlopen(url)
xd = pd.ExcelFile(socket)
df = xd.parse(xd.sheet_names[-1], header=None)
print df
I was thinking of using glob but I haven't seen any application of it with an Online Excel file.
Edit: I think the following allows me to combine two worksheets of data into a single Dataframe. However, if there is a better answer please feel free to show it.
import urllib2
import pandas as pd
import os
import xlrd
url = 'http://www.bankofengland.co.uk/statistics/Documents/yieldcurve/uknom05_mdaily.xls'
socket = urllib2.urlopen(url)
xd = pd.ExcelFile(socket)
df1 = xd.parse(xd.sheet_names[-1], header=None)
df2 = xd.parse(xd.sheet_names[-2], header=None)
bigdata = df1.append(df2,ignore_index = True)
print bigdata
Is there a way to simplify this with same kind with os.walk or glob?
from win32com.client import Dispatch
inputwb1 = "D:/apera/Workspace/Sounding/sounding001.xlsx"
inputwb2 = "D:/apera/Workspace/Sounding/sounding002.xlsx"
Sheet = 'OUTPUT'
excel = Dispatch("Excel.Application")
source = excel.Workbooks.Open(inputwb1)
source.Worksheets(Sheet).Range('F1:H500').Copy()
source.Worksheets(Sheet).Range('I1:K500').PasteSpecial(Paste=-4163)
source = excel.Workbooks.Open(inputwb2)
source.Worksheets(Sheet).Range('F1:H500').Copy()
source.Worksheets(Sheet).Range('I1:K500').PasteSpecial(Paste=-4163)
because this thing will take so much space if I want to write hundreds of it.
You seem to have almost answered your own question. Something like this might do it:
import glob
from win32com.client import Dispatch
Sheet = 'OUTPUT'
excel = Dispatch("Excel.Application")
for filename in glob.glob("D:/apera/Workspace/Sounding/sounding*.xlsx"):
source = excel.Workbooks.Open(filename)
source.Worksheets(Sheet).Range('F1:H500').Copy()
source.Worksheets(Sheet).Range('I1:K500').PasteSpecial(Paste=-4163)
you can open multiple excel files like this (example) :
import win32com.client
import os
path = ('D:\\New Folder\\MyExcelFiles\\')
fileslist = os.listdir('D:\\New Folder\\MyExcelFiles\\')
xl = win32com.client.DispatchEx('Excel.Application')
xl.Visible = True
for i in fileslist :
xl.Workbooks.Open(path+i)
if xl.Cells.Find('2014'):
xl.Cells.Replace('2015')
xl.Save()
xl.Workbooks.Close()
else:
xl.Workbooks.Close()