Package: pyexcel
Support the projectIf your company has embedded pyexcel and its components into a revenue generating
product, please support me on github,patreonorbounty sourceto maintain
the project and develop it further.If you are an individual, you are welcome to support me too and for however long
you feel like. As my backer, you will receiveearly access to pyexcel related contents.And your issues will get prioritized if you would like to become my patreon aspyexcel pro user.With your financial support, I will be able to invest
a little bit more time in coding, documentation and writing interesting posts.Known constraintsFonts, colors and charts are not supported.Nor to read password protected xls, xlsx and ods files.IntroductionFeature HighlightsA list of supported file formatsfile formatdefinitioncsvcomma separated valuestsvtab separated valuescsvza zip file that contains one or many csv filestsvza zip file that contains one or many tsv filesxlsa spreadsheet file format created by
MS-Excel 97-2003xlsxMS-Excel Extensions to the Office Open XML
SpreadsheetML File Format.xlsman MS-Excel Macro-Enabled Workbook fileodsopen document spreadsheetfodsflat open document spreadsheetjsonjava script object notationhtmlhtml table of the data structuresimplesimple presentationrstrStructured Text presentation of the datamediawikimedia wiki tableOne application programming interface(API) to handle multiple data sources:physical filememory fileSQLAlchemy tableDjango ModelPython data structures: dictionary, records and arrayOne API to read and write data in various excel file formats.For large data sets, data streaming are supported. A genenerator can be returned to you. Checkout iget_records, iget_array, isave_as and isave_book_as.InstallationYou can install pyexcel via pip:$pipinstallpyexcelor clone it and install it:$gitclonehttps://github.com/pyexcel/pyexcel.git$cdpyexcel$pythonsetup.pyinstallOne linersThis section shows you how to get data from your excel files and how to
export data to excel files inone lineRead from the excel filesGet a list of dictionariesSuppose you want to processHistory of Classical Music:History of Classical Music:NamePeriodRepresentative ComposersMedievalc.1150-c.1400Machaut, LandiniRenaissancec.1400-c.1600Gibbons, FrescobaldiBaroquec.1600-c.1750JS Bach, VivaldiClassicalc.1750-c.1830Joseph Haydn, Wolfgan Amadeus MozartEarley Romanticc.1830-c.1860Chopin, Mendelssohn, Schumann, LisztLate Romanticc.1860-c.1920Wagner,VerdiLet’s get a list of dictionary out from the xls file:>>>records=p.get_records(file_name="your_file.xls")And let’s check what do we have:>>>forrowinrecords:...print(f"{row['Representative Composers']}are from{row['Name']}period ({row['Period']})")Machaut,LandiniarefromMedievalperiod(c.1150-c.1400)Gibbons,FrescobaldiarefromRenaissanceperiod(c.1400-c.1600)JSBach,VivaldiarefromBaroqueperiod(c.1600-c.1750)JosephHaydn,WolfganAmadeusMozartarefromClassicalperiod(c.1750-c.1830)Chopin,Mendelssohn,Schumann,LisztarefromEarleyRomanticperiod(c.1830-c.1860)Wagner,VerdiarefromLateRomanticperiod(c.1860-c.1920)Get two dimensional arrayInstead, what if you have to usepyexcel.get_arrayto do the same:>>>forrowinp.get_array(file_name="your_file.xls",start_row=1):...print(f"{row[2]}are from{row[0]}period ({row[1]})")Machaut,LandiniarefromMedievalperiod(c.1150-c.1400)Gibbons,FrescobaldiarefromRenaissanceperiod(c.1400-c.1600)JSBach,VivaldiarefromBaroqueperiod(c.1600-c.1750)JosephHaydn,WolfganAmadeusMozartarefromClassicalperiod(c.1750-c.1830)Chopin,Mendelssohn,Schumann,LisztarefromEarleyRomanticperiod(c.1830-c.1860)Wagner,VerdiarefromLateRomanticperiod(c.1860-c.1920)wherestart_rowskips the header row.Get a dictionaryYou can get a dictionary too:Now let’s get a dictionary out from the spreadsheet:>>>my_dict=p.get_dict(file_name="your_file.xls",name_columns_by_row=0)And check what do we have:>>>frompyexcel._compactimportOrderedDict>>>isinstance(my_dict,OrderedDict)True>>>forkey,valuesinmy_dict.items():...print(key+" : "+','.join([str(item)foriteminvalues]))Name:Medieval,Renaissance,Baroque,Classical,EarleyRomantic,LateRomanticPeriod:c.1150-c.1400,c.1400-c.1600,c.1600-c.1750,c.1750-c.1830,c.1830-c.1860,c.1860-c.1920RepresentativeComposers:Machaut,Landini,Gibbons,Frescobaldi,JSBach,Vivaldi,JosephHaydn,WolfganAmadeusMozart,Chopin,Mendelssohn,Schumann,Liszt,Wagner,VerdiPlease note that my_dict is an OrderedDict.Get a dictionary of two dimensional arraySuppose you have a multiple sheet book as the following:pyexcel:Sheet 1:123456789pyexcel:Sheet 2:XYZ123456pyexcel:Sheet 3:OPQ321432Here is the code to obtain those sheets as a single dictionary:>>>book_dict=p.get_book_dict(file_name="book.xls")And check:>>>isinstance(book_dict,OrderedDict)True>>>importjson>>>forkey,iteminbook_dict.items():...print(json.dumps({key:item})){"Sheet 1":[[1,2,3],[4,5,6],[7,8,9]]}{"Sheet 2":[["X","Y","Z"],[1,2,3],[4,5,6]]}{"Sheet 3":[["O","P","Q"],[3,2,1],[4,3,2]]}Write dataExport an arraySuppose you have the following array:>>>data=[[1,2,3],[4,5,6],[7,8,9]]And here is the code to save it as an excel file :>>>p.save_as(array=data,dest_file_name="example.xls")Let’s verify it:>>>p.get_sheet(file_name="example.xls")pyexcel_sheet1:+---+---+---+|1|2|3|+---+---+---+|4|5|6|+---+---+---+|7|8|9|+---+---+---+And here is the code to save it as a csv file :>>>p.save_as(array=data,...dest_file_name="example.csv",...dest_delimiter=':')Let’s verify it:>>>withopen("example.csv")asf:...forlineinf.readlines():...print(line.rstrip())...1:2:34:5:67:8:9Export a list of dictionaries>>>records=[...{"year":1903,"country":"Germany","speed":"206.7km/h"},...{"year":1964,"country":"Japan","speed":"210km/h"},...{"year":2008,"country":"China","speed":"350km/h"}...]>>>p.save_as(records=records,dest_file_name='high_speed_rail.xls')Export a dictionary of single key value pair>>>henley_on_thames_facts={..."area":"5.58 square meters",..."population":"11,619",..."civial parish":"Henley-on-Thames",..."latitude":"51.536",..."longitude":"-0.898"...}>>>p.save_as(adict=henley_on_thames_facts,dest_file_name='henley.xlsx')Export a dictionary of single dimensonal array>>>ccs_insights={..."year":["2017","2018","2019","2020","2021"],..."smart phones":[1.53,1.64,1.74,1.82,1.90],..."feature phones":[0.46,0.38,0.30,0.23,0.17]...}>>>p.save_as(adict=ccs_insights,dest_file_name='ccs.csv')Export a dictionary of two dimensional array as a bookSuppose you want to save the below dictionary to an excel file :>>>a_dictionary_of_two_dimensional_arrays={...'Sheet 1':...[...[1.0,2.0,3.0],...[4.0,5.0,6.0],...[7.0,8.0,9.0]...],...'Sheet 2':...[...['X','Y','Z'],...[1.0,2.0,3.0],...[4.0,5.0,6.0]...],...'Sheet 3':...[...['O','P','Q'],...[3.0,2.0,1.0],...[4.0,3.0,2.0]...]...}Here is the code:>>>p.save_book_as(...bookdict=a_dictionary_of_two_dimensional_arrays,...dest_file_name="book.xls"...)If you want to preserve the order of sheets in your dictionary, you have to
pass on an ordered dictionary to the function itself. For example:>>>data=OrderedDict()>>>data.update({"Sheet 2":a_dictionary_of_two_dimensional_arrays['Sheet 2']})>>>data.update({"Sheet 1":a_dictionary_of_two_dimensional_arrays['Sheet 1']})>>>data.update({"Sheet 3":a_dictionary_of_two_dimensional_arrays['Sheet 3']})>>>p.save_book_as(bookdict=data,dest_file_name="book.xls")Let’s verify its order:>>>book_dict=p.get_book_dict(file_name="book.xls")>>>forkey,iteminbook_dict.items():...print(json.dumps({key:item})){"Sheet 2":[["X","Y","Z"],[1,2,3],[4,5,6]]}{"Sheet 1":[[1,2,3],[4,5,6],[7,8,9]]}{"Sheet 3":[["O","P","Q"],[3,2,1],[4,3,2]]}Please notice that “Sheet 2” is the first item in thebook_dict, meaning the order of sheets are preserved.TranscodingNotePlease note thatpyexcel-clican perform file transcoding at command line.
No need to open your editor, save the problem, then python run.The following code does a simple file format transcoding from xls to csv:>>>p.save_as(file_name="birth.xls",dest_file_name="birth.csv")Again it is really simple. Let’s verify what we have gotten:>>>sheet=p.get_sheet(file_name="birth.csv")>>>sheetbirth.csv:+-------+--------+----------+|name|weight|birth|+-------+--------+----------+|Adam|3.4|03/02/15|+-------+--------+----------+|Smith|4.2|12/11/14|+-------+--------+----------+NotePlease note that csv(comma separate value) file is pure text file. Formula, charts, images and formatting in xls file will disappear no matter which transcoding tool you use. Hence, pyexcel is a quick alternative for this transcoding job.Let use previous example and save it as xlsx instead>>>p.save_as(file_name="birth.xls",...dest_file_name="birth.xlsx")# change the file extensionAgain let’s verify what we have gotten:>>>sheet=p.get_sheet(file_name="birth.xlsx")>>>sheetpyexcel_sheet1:+-------+--------+----------+|name|weight|birth|+-------+--------+----------+|Adam|3.4|03/02/15|+-------+--------+----------+|Smith|4.2|12/11/14|+-------+--------+----------+Excel book merge and split operation in one lineMerge all excel files in directory into  a book where each file become a sheetThe following code will merge every excel files into one file, say “output.xls”:frompyexcel.cookbookimportmerge_all_to_a_bookimportglobmerge_all_to_a_book(glob.glob("your_csv_directory\*.csv"),"output.xls")You can mix and match with other excel formats: xls, xlsm and ods. For example, if you are sure you have only xls, xlsm, xlsx, ods and csv files inyour_excel_file_directory, you can do the following:frompyexcel.cookbookimportmerge_all_to_a_bookimportglobmerge_all_to_a_book(glob.glob("your_excel_file_directory\*.*"),"output.xls")Split a book into single sheet filesSuppose you have many sheets in a work book and you would like to separate each into a single sheet excel file. You can easily do this:>>>frompyexcel.cookbookimportsplit_a_book>>>split_a_book("megabook.xls","output.xls")>>>importglob>>>outputfiles=glob.glob("*_output.xls")>>>forfileinsorted(outputfiles):...print(file)...Sheet1_output.xlsSheet2_output.xlsSheet3_output.xlsfor the output file, you can specify any of the supported formatsExtract just one sheet from a bookSuppose you just want to extract one sheet from many sheets that exists in a work book and you would like to separate it into a single sheet excel file. You can easily do this:>>>frompyexcel.cookbookimportextract_a_sheet_from_a_book>>>extract_a_sheet_from_a_book("megabook.xls","Sheet 1","output.xls")>>>ifos.path.exists("Sheet 1_output.xls"):...print("Sheet 1_output.xls exists")...Sheet1_output.xlsexistsfor the output file, you can specify any of the supported formatsHidden feature: partial readMost pyexcel users do not know, but other library users were requestingpartial readWhen you are dealing with huge amount of data, e.g. 64GB, obviously you would not
like to fill up your memory with those data. What you may want to do is, record
data from Nth line, take M records and stop. And you only want to use your memory
for the M records, not for beginning part nor for the tail part.Hence partial read feature is developed to read partial data into memory for
processing.You can paginate by row, by column and by both, hence you dictate what portion of the
data to read back. But remember only row limit features help you save memory. Let’s
you use this feature to record data from Nth column, take M number of columns and skip
the rest. You are not going to reduce your memory footprint.Why did not I see above benefit?This feature depends heavily on the implementation details.pyexcel-xls(xlrd),pyexcel-xlsx(openpyxl),pyexcel-ods(odfpy) andpyexcel-ods3(pyexcel-ezodf) will read all data into memory. Because xls,
xlsx and ods file are effective a zipped folder, all four will unzip the folder
and read the content in xml format infull, so as to make sense of all details.Hence, during the partial data is been returned, the memory consumption won’t
differ from reading the whole data back. Only after the partial
data is returned, the memory comsumption curve shall jump the cliff. So pagination
code here only limits the data returned to your program.With that said,pyexcel-xlsxr,pyexcel-odsrandpyexcel-htmlrDOES read
partial data into memory. Those three are implemented in such a way that they
consume the xml(html) when needed. When they have read designated portion of the
data, they stop, even if they are half way through.In addition, pyexcel’s csv readers can read partial data into memory too.Let’s assume the following file is a huge csv file:>>>importdatetime>>>importpyexcelaspe>>>data=[...[1,21,31],...[2,22,32],...[3,23,33],...[4,24,34],...[5,25,35],...[6,26,36]...]>>>pe.save_as(array=data,dest_file_name="your_file.csv")And let’s pretend to read partial data:>>>pe.get_sheet(file_name="your_file.csv",start_row=2,row_limit=3)your_file.csv:+---+----+----+|3|23|33|+---+----+----+|4|24|34|+---+----+----+|5|25|35|+---+----+----+And you could as well do the same for columns:>>>pe.get_sheet(file_name="your_file.csv",start_column=1,column_limit=2)your_file.csv:+----+----+|21|31|+----+----+|22|32|+----+----+|23|33|+----+----+|24|34|+----+----+|25|35|+----+----+|26|36|+----+----+Obvious, you could do both at the same time:>>>pe.get_sheet(file_name="your_file.csv",...start_row=2,row_limit=3,...start_column=1,column_limit=2)your_file.csv:+----+----+|23|33|+----+----+|24|34|+----+----+|25|35|+----+----+The pagination support is available across all pyexcel plugins.NoteNo column pagination support for query sets as data source.Formatting while transcoding a big data fileIf you are transcoding a big data set, conventional formatting method would not
help unless a on-demand free RAM is available. However, there is a way to minimize
the memory footprint of pyexcel while the formatting is performed.Let’s continue from previous example. Suppose we want to transcode “your_file.csv”
to “your_file.xls” but increase each element by 1.What we can do is to define a row renderer function as the following:>>>defincrement_by_one(row):...forelementinrow:...yieldelement+1Then pass it onto save_as function using row_renderer:>>>pe.isave_as(file_name="your_file.csv",...row_renderer=increment_by_one,...dest_file_name="your_file.xlsx")NoteIf the data content is from a generator, isave_as has to be used.We can verify if it was done correctly:>>>pe.get_sheet(file_name="your_file.xlsx")your_file.csv:+---+----+----+|2|22|32|+---+----+----+|3|23|33|+---+----+----+|4|24|34|+---+----+----+|5|25|35|+---+----+----+|6|26|36|+---+----+----+|7|27|37|+---+----+----+Stream APIs for big file : A set of two linersWhen you are dealing withBIGexcel files, you will wantpyexcelto use
constant memory.This section shows you how to get data from yourBIGexcel files and how to
export data to excel files intwo linesat most, without eating all
your computer memory.Two liners for get data from big excel filesGet a list of dictionariesSuppose you want to process the following coffee data again:Top 5 coffeine drinks:CoffeesServing SizeCaffeine (mg)Starbucks Coffee Blonde Roastventi(20 oz)475Dunkin’ Donuts Coffee with Turbo Shotlarge(20 oz.)398Starbucks Coffee Pike Place Roastgrande(16 oz.)310Panera Coffee Light Roastregular(16 oz.)300Let’s get a list of dictionary out from the xls file:>>>records=p.iget_records(file_name="your_file.xls")And let’s check what do we have:>>>forrinrecords:...print(f"{r['Serving Size']}of{r['Coffees']}has{r['Caffeine (mg)']}mg")venti(20oz)ofStarbucksCoffeeBlondeRoasthas475mglarge(20oz.)ofDunkin' Donuts Coffee with Turbo Shot has 398 mggrande(16oz.)ofStarbucksCoffeePikePlaceRoasthas310mgregular(16oz.)ofPaneraCoffeeLightRoasthas300mgPlease do not forgot the second line to close the opened file handle:>>>p.free_resources()Get two dimensional arrayInstead, what if you have to usepyexcel.get_arrayto do the same:>>>forrowinp.iget_array(file_name="your_file.xls",start_row=1):...print(f"{row[1]}of{row[0]}has{row[2]}mg")venti(20oz)ofStarbucksCoffeeBlondeRoasthas475mglarge(20oz.)ofDunkin' Donuts Coffee with Turbo Shot has 398 mggrande(16oz.)ofStarbucksCoffeePikePlaceRoasthas310mgregular(16oz.)ofPaneraCoffeeLightRoasthas300mgAgain, do not forgot the second line:>>>p.free_resources()wherestart_rowskips the header row.Data export in one linersExport an arraySuppose you have the following array:>>>data=[[1,2,3],[4,5,6],[7,8,9]]And here is the code to save it as an excel file :>>>p.isave_as(array=data,dest_file_name="example.xls")But the following line is not required because the data source
are not file sources:>>># p.free_resources()Let’s verify it:>>>p.get_sheet(file_name="example.xls")pyexcel_sheet1:+---+---+---+|1|2|3|+---+---+---+|4|5|6|+---+---+---+|7|8|9|+---+---+---+And here is the code to save it as a csv file :>>>p.isave_as(array=data,...dest_file_name="example.csv",...dest_delimiter=':')Let’s verify it:>>>withopen("example.csv")asf:...forlineinf.readlines():...print(line.rstrip())...1:2:34:5:67:8:9Export a list of dictionaries>>>records=[...{"year":1903,"country":"Germany","speed":"206.7km/h"},...{"year":1964,"country":"Japan","speed":"210km/h"},...{"year":2008,"country":"China","speed":"350km/h"}...]>>>p.isave_as(records=records,dest_file_name='high_speed_rail.xls')Export a dictionary of single key value pair>>>henley_on_thames_facts={..."area":"5.58 square meters",..."population":"11,619",..."civial parish":"Henley-on-Thames",..."latitude":"51.536",..."longitude":"-0.898"...}>>>p.isave_as(adict=henley_on_thames_facts,dest_file_name='henley.xlsx')Export a dictionary of single dimensonal array>>>ccs_insights={..."year":["2017","2018","2019","2020","2021"],..."smart phones":[1.53,1.64,1.74,1.82,1.90],..."feature phones":[0.46,0.38,0.30,0.23,0.17]...}>>>p.isave_as(adict=ccs_insights,dest_file_name='ccs.csv')>>>p.free_resources()Export a dictionary of two dimensional array as a bookSuppose you want to save the below dictionary to an excel file :>>>a_dictionary_of_two_dimensional_arrays={...'Sheet 1':...[...[1.0,2.0,3.0],...[4.0,5.0,6.0],...[7.0,8.0,9.0]...],...'Sheet 2':...[...['X','Y','Z'],...[1.0,2.0,3.0],...[4.0,5.0,6.0]...],...'Sheet 3':...[...['O','P','Q'],...[3.0,2.0,1.0],...[4.0,3.0,2.0]...]...}Here is the code:>>>p.isave_book_as(...bookdict=a_dictionary_of_two_dimensional_arrays,...dest_file_name="book.xls"...)If you want to preserve the order of sheets in your dictionary, you have to
pass on an ordered dictionary to the function itself. For example:>>>frompyexcel._compactimportOrderedDict>>>data=OrderedDict()>>>data.update({"Sheet 2":a_dictionary_of_two_dimensional_arrays['Sheet 2']})>>>data.update({"Sheet 1":a_dictionary_of_two_dimensional_arrays['Sheet 1']})>>>data.update({"Sheet 3":a_dictionary_of_two_dimensional_arrays['Sheet 3']})>>>p.isave_book_as(bookdict=data,dest_file_name="book.xls")>>>p.free_resources()Let’s verify its order:>>>importjson>>>book_dict=p.get_book_dict(file_name="book.xls")>>>forkey,iteminbook_dict.items():...print(json.dumps({key:item})){"Sheet 2":[["X","Y","Z"],[1,2,3],[4,5,6]]}{"Sheet 1":[[1,2,3],[4,5,6],[7,8,9]]}{"Sheet 3":[["O","P","Q"],[3,2,1],[4,3,2]]}Please notice that “Sheet 2” is the first item in thebook_dict, meaning the order of sheets are preserved.File format transcoding on one lineNotePlease note that the following file transcoding could be with zero line. Please
install pyexcel-cli and you will do the transcode in one command. No need to
open your editor, save the problem, then python run.The following code does a simple file format transcoding from xls to csv:>>>importpyexcel>>>p.save_as(file_name="birth.xls",dest_file_name="birth.csv")Again it is really simple. Let’s verify what we have gotten:>>>sheet=p.get_sheet(file_name="birth.csv")>>>sheetbirth.csv:+-------+--------+----------+|name|weight|birth|+-------+--------+----------+|Adam|3.4|03/02/15|+-------+--------+----------+|Smith|4.2|12/11/14|+-------+--------+----------+NotePlease note that csv(comma separate value) file is pure text file. Formula, charts, images and formatting in xls file will disappear no matter which transcoding tool you use. Hence, pyexcel is a quick alternative for this transcoding job.Let use previous example and save it as xlsx instead>>>importpyexcel>>>p.isave_as(file_name="birth.xls",...dest_file_name="birth.xlsx")# change the file extensionAgain let’s verify what we have gotten:>>>sheet=p.get_sheet(file_name="birth.xlsx")>>>sheetpyexcel_sheet1:+-------+--------+----------+|name|weight|birth|+-------+--------+----------+|Adam|3.4|03/02/15|+-------+--------+----------+|Smith|4.2|12/11/14|+-------+--------+----------+Available PluginsA list of file formats supported by external pluginsPackage nameSupported file formatsDependenciespyexcel-iocsv, csvz[1], tsv,
tsvz[2]pyexcel-xlsxls, xlsx(read only),
xlsm(read only)xlrd,xlwtpyexcel-xlsxxlsxopenpyxlpyexcel-ods3odspyexcel-ezodf,
lxmlpyexcel-odsodsodfpyDedicated file reader and writersPackage nameSupported file formatsDependenciespyexcel-xlsxwxlsx(write only)XlsxWriterpyexcel-libxlsxwxlsx(write only)libxlsxwriterpyexcel-xlsxrxlsx(read only)lxmlpyexcel-xlsbrxlsb(read only)pyxlsbpyexcel-odsrread only for ods, fodslxmlpyexcel-odswwrite only for odsloxunpyexcel-htmlrhtml(read only)lxml,html5libpyexcel-pdfrpdf(read only)camelotPlugin shopping guideSince 2020, all pyexcel-io plugins have dropped the support for python versions
which are lower than 3.6. If you want to use any of those Python versions, please use pyexcel-io
and its plugins versions that are lower than 0.6.0.Except csv files, xls, xlsx and ods files are a zip of a folder containing a lot of
xml filesThe dedicated readers for excel files can stream readIn order to manage the list of plugins installed, you need to use pip to add or remove
a plugin. When you use virtualenv, you can have different plugins per virtual
environment. In the situation where you have multiple plugins that does the same thing
in your environment, you need to tell pyexcel which plugin to use per function call.
For example, pyexcel-ods and pyexcel-odsr, and you want to get_array to use pyexcel-odsr.
You need to append get_array(…, library=’pyexcel-odsr’).Other data renderersPackage nameSupported file formatsDependenciesPython versionspyexcel-textwrite only:rst,
mediawiki, html,
latex, grid, pipe,
orgtbl, plain simple
read only: ndjson
r/w: jsontabulate2.6, 2.7, 3.3, 3.4
3.5, 3.6, pypypyexcel-handsontablehandsontable in htmlhandsontablesame as abovepyexcel-pygalsvg chartpygal2.7, 3.3, 3.4, 3.5
3.6, pypypyexcel-sortablesortable table in htmlcsvtotablesame as abovepyexcel-ganttgantt chart in htmlfrappe-ganttexcept pypy, same
as aboveFootnotes[1]zipped csv file[2]zipped tsv fileAcknowledgementAll great work have been done by odf, ezodf, xlrd, xlwt, tabulate and other
individual developers. This library unites only the data access code.LicenseNew BSD License19 contributorsIn alphabetical order:Akshaya Kumar SharmaAndre AlmarArunkumar RajendranAyan BanerjeeChris Hill-ScottCraig AndersonDaryl YuJ HarleyJoel NothmanJohn VandenbergLinghui ZengNik NybyRintze M. Zelle, PhDSimeon VisserSimon Allensimon klemencTim GatesWesley A. ChengWilliam Jamir SilvaChange log0.7.0 - 12.2.2022Fixed#250: RecursionError
raised on deepcopy of a sheetUpdated#255: pyexcel.get_array
documentation page seems to be a copy of pyexcel.get_sheetRemoved#249: drop the support for
dummy import statements pyexcel.ext.*0.6.7 - 12.09.2021Updated#243: fix small typo.add chardet as explicit dependency0.6.6 - 14.11.2020Updated#233: dynamically resize
the table matrix on set_value. sheet[‘AA1’] = ‘test’ will work in this
release.0.6.5 - 8.10.2020Updatedupdate queryset source to work with pyexcel-io 0.6.00.6.4 - 18.08.2020Updated#219: book created from
dict no longer discards order.0.6.3 - 01.08.2020fixed#214: remove leading and
trailing whitespace for column namesremovedpython 2 compatibility have been permanently removed.0.6.2 - 8.06.2020fixed#109: Control the column
order when write the data output0.6.1 - 02.05.2020fixed#203: texttable was
dropped out in 0.6.0 as compulsary dependency. end user may experience it
when a sheet/table is printed in a shell. otherwise, new user of pyexcel
won’t see it. As of release date, no issues were created0.6.0 - 21.04.2020updated#199: += in place; = +
shall return new instance#195: documentation
update. however small is welcomeremovedDropping the test support for python version lower than 3.6. v0.6.0 should
work with python 2.7 but is not guaranteed to work. Please upgrade to python
3.6+.0.5.15 - 07.07.2019updated#185: fix a bug with http
data source. The real fix lies in pyexcel-io v0.5.19. this release just put
the version requirement in.0.5.14 - 12.06.2019updated#182: support
dest_force_file_type on save_as and save_book_as0.5.13 - 12.03.2019updated#176: get_sheet
{IndexError}list index out of range // XLSX can’t be opened0.5.12 - 25.02.2019updated#174: include examples in
tarbar0.5.11 - 22.02.2019updated#169: remove
pyexcel-handsontalbe in testadd tests, and docs folder in distribution0.5.10 - 3.12.2018updated#157: Please use
scan_plugins_regex, which lml 0.7 complains aboutupdated dependency on pyexcel-io to 0.5.110.5.9.1 - 30.08.2018updatedto require pyexcel-io 0.5.9.1 and use lml at least version 0.0.20.5.9 - 30.08.2018addedsupport __len__. len(book) returns the number of sheets and len(sheet)
returns the number of rows#144: memory-efficient way
to read sheet names.#148: force_file_type is
introduced. When reading a file on a disk, this parameter allows you to
choose a reader. i.e. csv reader for a text file. xlsx reader for a xlsx file
but with .blob file suffix.finally, pyexcel got import pyexcel.__version__updatedSheet.to_records() returns a generator now, saving memory#115, Fix set membership
test to run faster in python2#140, Direct writes to
cells yield weird results0.5.8 - 26.03.2018added#125, sort book sheetsupdated#126, dest_sheet_name in
save_as will set the sheet name in the output#115, Fix set membership
test to run faster in python20.5.7 - 11.01.2018addedpyexcel-io#46, exposebulk_saveto developer.0.5.6 - 23.10.2017removed#105, remove gease from
setup_requires, introduced by 0.5.5.removed testing against python 2.6#103, include LICENSE file
in MANIFEST.in, meaning LICENSE file will appear in the released tar ball.0.5.5 - 20.10.2017removed#105, remove gease from
setup_requires, introduced by 0.5.5.removed testing against python 2.6#103, include LICENSE file
in MANIFEST.in, meaning LICENSE file will appear in the released tar ball.0.5.4 - 27.09.2017fixed#100, Sheet.to_dict() gets
out of range error because there is only one row.updatedUpdated the baseline of pyexcel-io to 0.5.1.0.5.3 - 01-08-2017added#95, respect the order of
records in iget_records, isave_as and save_as.#97, new feature to allow
intuitive initialization of pyexcel.Book.0.5.2 - 26-07-2017Updatedembeded the enabler for pyexcel-htmlr. http source does not support text/html
as mime type.0.5.1 - 12.06.2017Updatedsupport saving SheetStream and BookStream to database targets. This is needed
for pyexcel-webio and its downstream projects.0.5.0 - 19.06.2017AddedSheet.top() and Sheet.top_left() for data browsingadd html as default rich display in Jupyter notebook when pyexcel-text and
pyexcel-chart is installedadd svg as default rich display in Jupyter notebook when pyexcel-chart and
one of its implementation plugin(pyexcel-pygal, etc.) are is installednew dictionary source supported: a dictionary of key value pair could be read
into a sheet.added dynamic external plugin loading. meaning if a pyexcel plugin is
installed, it will be loaded implicitly. And this change would remove
unnecessary info log for those who do not use pyexcel-text and pyexcel-galsave_book_as before 0.5.0 becomes isave_book_as and save_book_as in 0.5.0
convert BookStream to Book before saving.#83, file closing mechanism
is enfored. free_resource is added and it should be called when iget_array,
iget_records, isave_as and/or isave_book_as are used.Updatedarray is passed to pyexcel.Sheet as reference. it means your array data will
be modified.Removedpyexcel.Writer and pyexcel.BookWriter were removedpyexcel.load_book_from_sql and pyexcel.load_from_sql were removedpyexcel.deprecated.load_from_query_sets,
pyexcel.deprecated.load_book_from_django_models and
pyexcel.deprecated.load_from_django_model were removedRemoved plugin loading code and lml is used instead0.4.5 - 17.03.2017Updated#80: remove pyexcel-chart
import from v0.4.x0.4.4 - 06.02.2017Updated#68: regression
save_to_memory() should have returned a stream instance which has been reset
to zero if possible. The exception is sys.stdout, which cannot be reset.#74: Not able to handle
decimal.DecimalRemovedremove get_{{file_type}}_stream functions from pyexcel.Sheet and pyexcel.Book
introduced since 0.4.3.0.4.3 - 26.01.2017Added‘.stream’ attribute are attached to~pyexcel.Sheetand~pyexcel.Bookto
get direct access the underneath stream in responding to file type
attributes, such as sheet.xls. it helps provide a custom stream to external
world, for example, Sheet.stream.csv gives a text stream that contains csv
formatted data. Book.stream.xls returns a xls format data in a byte stream.UpdatedBetter error reporting when an unknown parameters or unsupported file types
were given to the signature functions.0.4.2 - 17.01.2017UpdatedRaise exception if the incoming sheet does not have column names. In other
words, only sheet with column names could be saved to database. sheet with
row names cannot be saved. The alternative is to transpose the sheet, then
name_columns_by_row and then save.fix iget_records where a non-uniform content should be given, e.g. [[“x”,
“y”], [1, 2], [3]], some record would become non-uniform, e.g. key ‘y’ would
be missing from the second record.skip_empty_rowsis applicable when saving a python data structure to
another data source. For example, if your array contains a row which is
consisted of empty string, such as [‘’, ‘’, ‘’ … ‘’], please specifyskip_empty_rows=Falsein order to preserve it. This becomes subtle when you
try save a python dictionary where empty rows is not easy to be spotted.#69: better documentation
for save_book_as.0.4.1 - 23.12.2016Updated#68: regression
save_to_memory() should have returned a stream instance.0.4.0 - 22.12.2016AddedFlask-Excel#19allow
sheet_name parameterpyexcel-xls#11case-insensitive for file_type.xlsandXLSare treated in the same wayUpdated#66:export_columnsis
ignoredUpdate dependency on pyexcel-io v0.3.00.3.3 - 07.11.2016Updated#63: cannot display empty
sheet(hence book with empty sheet) as texttable0.3.2 - 02.11.2016Updated#62: optional module import
error become visible.0.3.0 - 28.10.2016Added:file type setters for Sheet and Book, and its documentationiget_recordsreturns a generator for a list of records and should have
better memory performance, especially dealing with large csv files.iget_arrayreturns a generator for a list of two dimensional array and
should have better memory performance, especially dealing with large csv
files.Enable pagination support, and custom row renderer via pyexcel-io v0.2.3UpdatedTakeisave_asout fromsave_as. Hence two functions are there for save a
sheet as#60: encode ‘utf-8’ if the
console is of ascii encoding.#59: custom row renderer#56: set cell value does
not workpyexcel.transpose becomespyexcel.sheets.transposeiterator functions ofpyexcel.Sheetwere converted to generator functionspyexcel.Sheet.enumerate()pyexcel.Sheet.reverse()pyexcel.Sheet.vertical()pyexcel.Sheet.rvertical()pyexcel.Sheet.rows()pyexcel.Sheet.rrows()pyexcel.Sheet.columns()pyexcel.Sheet.rcolumns()pyexcel.Sheet.named_rows()pyexcel.Sheet.named_columns()~pyexcel.Sheet.save_to_memoryand~pyexcel.Book.save_to_memoryreturn the
actual content. No longer they will return a io object hence you cannot call
getvalue() on them.Removed:contentandout_fileas function parameters to the signature functions
are no longer supported.SourceFactory and RendererFactory are removedThe following methods are removedpyexcel.to_arraypyexcel.to_dictpyexcel.utils.to_one_dimensional_arraypyexcel.dict_to_arraypyexcel.from_recordspyexcel.to_recordspyexcel.Sheet.filterhas been re-implemented and all filters were removed:pyexcel.filters.ColumnIndexFilterpyexcel.filters.ColumnFilterpyexcel.filters.RowFilterpyexcel.filters.EvenColumnFilterpyexcel.filters.OddColumnFilterpyexcel.filters.EvenRowFilterpyexcel.filters.OddRowFilterpyexcel.filters.RowIndexFilterpyexcel.filters.SingleColumnFilterpyexcel.filters.RowValueFilterpyexcel.filters.NamedRowValueFilterpyexcel.filters.ColumnValueFilterpyexcel.filters.NamedColumnValueFilterpyexcel.filters.SingleRowFilterthe following functions have been removedadd_formatterremove_formatterclear_formattersfreeze_formattersadd_filterremove_filterclear_filtersfreeze_formatterspyexcel.Sheet.filterhas been re-implemented and all filters were removed:pyexcel.formatters.SheetFormatter0.2.5 - 31.08.2016Updated:#58: texttable should have
been made as compulsory requirement0.2.4 - 14.07.2016Updated:For python 2, writing to sys.stdout by pyexcel-cli raise IOError.0.2.3 - 11.07.2016Updated:For python 3, do not seek 0 when saving to memory if sys.stdout is passed on.
Hence, adding support for sys.stdin and sys.stdout.0.2.2 - 01.06.2016Updated:Explicit imports, no longer neededDepends on latest setuptools 18.0.1NotImplementedError will be raised if parameters to core functions are not
supported, e.g. get_sheet(cannot_find_me_option=”will be thrown out as
NotImplementedError”)0.2.1 - 23.04.2016Added:add pyexcel-text file types as attributes of pyexcel.Sheet and pyexcel.Book,
related to#31auto import pyexcel-text if it is pip installedUpdated:code refactoring done for easy addition of sources.bug fix#29, Even if the
format is a string it is displayed as a floatpyexcel-text is no longer a plugin to pyexcel-io but to pyexcel.sources, seepyexcel-text#22Removed:pyexcel.presentation is removed. No longer the internal decorate @outsource
is used. related to#310.2.0 - 17.01.2016Updatedadopt pyexcel-io yield key word to return generator as contentpyexcel.save_as and pyexcel.save_book_as get performance improvements0.1.7 - 03.07.2015AddedSupport pyramid-excel which does the database commit on its own.0.1.6 - 13.06.2015Addedget excel data from a http url0.0.13 - 07.02.2015AddedSupport djangotexttable as default renderer0.0.12 - 25.01.2015AddedAdded sqlalchemy support0.0.10 - 15.12.2015Addedadded csvz and tsvz format0.0.4 - 12.10.2014UpdatedSupport python 30.0.1 - 14.09.2014Features:read and write csv, ods, xls, xlsx and xlsm files(which are referred later as
excel files)various iterators for the readerrow and column filters for the readerutilities to get array and dictionary out from excel files.cookbok receipes for some common and simple usage of this library.