63

In this post there is a Python example to convert from csv to xls.

However, my file has more than 65536 rows so xls does not work. If I name the file xlsx it doesnt make a difference. Is there a Python package to convert to xlsx?

Community
  • 1
  • 1
user670186
  • 2,588
  • 6
  • 37
  • 55

8 Answers8

105

Here's an example using xlsxwriter:

import os
import glob
import csv
from xlsxwriter.workbook import Workbook


for csvfile in glob.glob(os.path.join('.', '*.csv')):
    workbook = Workbook(csvfile[:-4] + '.xlsx')
    worksheet = workbook.add_worksheet()
    with open(csvfile, 'rt', encoding='utf8') as f:
        reader = csv.reader(f)
        for r, row in enumerate(reader):
            for c, col in enumerate(row):
                worksheet.write(r, c, col)
    workbook.close()

FYI, there is also a package called openpyxl, that can read/write Excel 2007 xlsx/xlsm files.

starball
  • 20,030
  • 7
  • 43
  • 238
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • 4
    Thanks for this very helpful code snippet. While using large files, it's better to use 'constant_memory' for controlled memory usage like: `workbook = Workbook(csvfile + '.xlsx', {'constant_memory': True})`. Ref: http://xlsxwriter.readthedocs.org/en/latest/working_with_memory.html – Ethan Jul 31 '15 at 17:24
  • 2
    Nice... However, the xlsx files created are full of all number fields having errors that the fields are stored as text instead of numbers... – MrMobileMan Dec 22 '15 at 22:23
  • 2
    Found a fix to the numbers as text issue here: http://stackoverflow.com/questions/24971556/openpyxl-python-writing-csv-to-excel-gives-number-formatted-as-text – MrMobileMan Dec 22 '15 at 22:40
  • I had to add these lines to make it work with Western European languages import sys reload(sys) sys.setdefaultencoding('latin-1') – Diego Jun 01 '16 at 11:33
  • What if I want to convert files in a certain directory? Where do I write the path to the files? – Razvan Zamfir Jan 06 '17 at 10:18
  • Worked great after I changed the file open mode to 'r' instead of 'rb'. Thanks. – thephez Jan 31 '17 at 17:10
  • @xeon : I m sorry, I don't have any comment anywhere on this page. Why tagged me? – Abhishek dot py Jul 31 '17 at 17:00
  • @Abhishekdotpy I'm sorry, I was replying to a comment. Might have mis-typed the username. – xeon Aug 01 '17 at 09:33
  • 3
    @MrMobileMan It is better to use the xlsxwriter constuctor option `strings_to_numbers`. For example, `workbook = Workbook('output.xlsx',{'strings_to_numbers':True})` – pookie Mar 01 '18 at 21:34
  • Everything works fine except when input data itself have comma(,) in the fields. I'm using pipe delimited file but my input data as comma in it. So when I tried to write the csv data to excel, the for loop enumerate for row is splitting the fields by "comma" in the input value which is present in the data. Any solution for this problem? – Rajashree Gr Sep 09 '18 at 02:34
  • Worked great for me after removing `, encoding='utf8'`. And it was easy to modify into creating worksheets with names different from the CSVs. – RonJohn Jan 25 '19 at 10:15
  • @RajashreeGr https://docs.python.org/3.5/library/csv.html Change the reader() delimiter. – RonJohn Jan 25 '19 at 10:17
  • Beyond 'strings_to_numbers', which is a good approach for the whole sheet, you can have additional flexibility using xslxwriter by creating a format object and using set_column() or set_row() e.g. `col_format.set_num_format('0.000')` and `sheet.set_col(0, 15, col_format)` Works for dates and other things too. – Colin Helms May 27 '19 at 20:12
  • If one wants to put all the csv in a unique Excel the code could be easily modificated putting the workbook out of the cycle: workbook = Workbook(workbook_name + '.xlsx') for csvfile in glob.glob(os.path.join('.', '*.csv')): worksheet = workbook.add_worksheet() with open(csvfile, 'rt', encoding='utf8') as f: reader = csv.reader(f) for r, row in enumerate(reader): for c, col in enumerate(row): col = col.replace('.',',').replace(',',';') worksheet.write(r, c, col) workbook.close() – Andrea Ianni Mar 24 '21 at 11:03
45

With my library pyexcel,

 $ pip install pyexcel pyexcel-xlsx

you can do it in one command line:

from pyexcel.cookbook import merge_all_to_a_book
# import pyexcel.ext.xlsx # no longer required if you use pyexcel >= 0.2.2 
import glob


merge_all_to_a_book(glob.glob("your_csv_directory/*.csv"), "output.xlsx")

Each csv will have its own sheet and the name will be their file name.

chfw
  • 4,502
  • 2
  • 29
  • 32
  • 1
    Very nice... Thanks! I up-voted this one. One issue I'm having, however, is that both this and xlswriter create xlsx's full of errors that the text fields are formatted as text instead of numbers... – MrMobileMan Dec 22 '15 at 22:22
  • 1
    Found the fix to the numbers as text issue here... http://stackoverflow.com/questions/24971556/openpyxl-python-writing-csv-to-excel-gives-number-formatted-as-text – MrMobileMan Dec 22 '15 at 22:39
  • If additional formatting is needed, you may not use merge_all_to_a_book but use pyexcel.Sheet, with which you can use format() function to [convert float into int](https://github.com/chfw/pyexcel/issues/18) first, then use [sheet operations](http://pyexcel.readthedocs.org/en/latest/tutorial04.html) to merge them and save as csv. – chfw Dec 23 '15 at 09:09
  • 1
    with pyexcel-cli package and pyexcel, pyexcel-xlsx, you can do that in command line: `$ pyexcel merge your_csv_directory/*.csv out.xlsx` – chfw Jul 29 '16 at 13:57
  • How to specify the sheet name if I have the only 1 file to be written to `xlsx` file? – Underoos Dec 12 '19 at 17:51
  • then, dig into `merge_all_to_a_book` to write a bit more code. you are welcome to submit a PR to https://github.com/pyexcel/pyexcel. – chfw Jan 09 '20 at 22:33
29

Simple two line code solution using pandas

import pandas as pd

read_file = pd.read_csv('File name.csv')
read_file.to_excel('File name.xlsx', index=None, header=True)
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Bhanu Sinha
  • 1,566
  • 13
  • 10
26

First install openpyxl:

pip install openpyxl

Then:

from openpyxl import Workbook
import csv


wb = Workbook()
ws = wb.active
with open('test.csv', 'r') as f:
    for row in csv.reader(f):
        ws.append(row)
wb.save('name.xlsx')
Paolo
  • 20,112
  • 21
  • 72
  • 113
zhuhuren
  • 337
  • 4
  • 7
12

Adding an answer that exclusively uses the pandas library to read in a .csv file and save as a .xlsx file. This example makes use of pandas.read_csv (Link to docs) and pandas.dataframe.to_excel (Link to docs).

The fully reproducible example uses numpy to generate random numbers only, and this can be removed if you would like to use your own .csv file.

import pandas as pd
import numpy as np

# Creating a dataframe and saving as test.csv in current directory
df = pd.DataFrame(np.random.randn(100000, 3), columns=list('ABC'))
df.to_csv('test.csv', index = False)

# Reading in test.csv and saving as test.xlsx

df_new = pd.read_csv('test.csv')
writer = pd.ExcelWriter('test.xlsx')
df_new.to_excel(writer, index = False)
writer.save()
patrickjlong1
  • 3,683
  • 1
  • 18
  • 32
6

Simple 1-to-1 CSV to XLSX file conversion without enumerating/looping through the rows:

import pyexcel

sheet = pyexcel.get_sheet(file_name="myFile.csv", delimiter=",")
sheet.save_as("myFile.xlsx")

Notes:

  1. I have found that if the file_name is really long (>30 characters excluding path) then the resultant XLSX file will throw an error when Excel tries to load it. Excel will offer to fix the error which it does, but it is frustrating.
  2. There is a great answer previously provided that combines all of the CSV files in a directory into one XLSX workbook, which fits a different use case than just trying to do a 1-to-1 CSV file to XLSX file conversion.
Larry W
  • 111
  • 2
  • 5
4

How I do it with openpyxl lib:

import csv
from openpyxl import Workbook

def convert_csv_to_xlsx(self):
    wb = Workbook()
    sheet = wb.active

    CSV_SEPARATOR = "#"

    with open("my_file.csv") as f:
        reader = csv.reader(f)
        for r, row in enumerate(reader):
            for c, col in enumerate(row):
                for idx, val in enumerate(col.split(CSV_SEPARATOR)):
                    cell = sheet.cell(row=r+1, column=idx+1)
                    cell.value = val

    wb.save("my_file.xlsx")
mcarton
  • 27,633
  • 5
  • 85
  • 95
Rubycon
  • 18,156
  • 10
  • 49
  • 70
1

There is a simple way

import os
import csv
import sys

from openpyxl import Workbook

reload(sys)
sys.setdefaultencoding('utf8')

if __name__ == '__main__':
    workbook = Workbook()
    worksheet = workbook.active
    with open('input.csv', 'r') as f:
        reader = csv.reader(f)
        for r, row in enumerate(reader):
            for c, col in enumerate(row):
                for idx, val in enumerate(col.split(',')):
                    cell = worksheet.cell(row=r+1, column=c+1)
                    cell.value = val
    workbook.save('output.xlsx')
David Ding
  • 1,473
  • 1
  • 15
  • 13