XLS转CSV转换器

59

我在Python中使用win32.client将我的.xlsx和.xls文件转换为.csv。当我执行这段代码时,它会产生一个错误。我的代码如下:

def convertXLS2CSV(aFile):
    '''converts a MS Excel file to csv w/ the same name in the same directory'''

    print "------ beginning to convert XLS to CSV ------"

    try:
        import win32com.client, os
        from win32com.client import constants as c
        excel = win32com.client.Dispatch('Excel.Application')

        fileDir, fileName = os.path.split(aFile)
        nameOnly = os.path.splitext(fileName)
        newName = nameOnly[0] + ".csv"
        outCSV = os.path.join(fileDir, newName)
        workbook = excel.Workbooks.Open(aFile)
        workbook.SaveAs(outCSV, c.xlCSVMSDOS) # 24 represents xlCSVMSDOS
        workbook.Close(False)
        excel.Quit()
        del excel

        print "...Converted " + nameOnly + " to CSV"
    except:
        print ">>>>>>> FAILED to convert " + aFile + " to CSV!"

convertXLS2CSV("G:\\hello.xlsx")

我找不到这段代码中的错误,请帮忙。


2
请发布错误和完整的回溯。 - agf
7
先把 try/except 删掉,否则你不会得到有用的错误提示。 - SpliFF
14个回答

79

我会使用xlrd - 它更快、跨平台并直接处理文件。

从版本0.8.0开始xlrd可以读取XLS和XLSX文件。

但是自版本2.0.0起,支持仅限于XLS文件。

import xlrd
import csv

def csv_from_excel():
    wb = xlrd.open_workbook('your_workbook.xls')
    sh = wb.sheet_by_name('Sheet1')
    your_csv_file = open('your_csv_file.csv', 'wb')
    wr = csv.writer(your_csv_file, quoting=csv.QUOTE_ALL)

    for rownum in xrange(sh.nrows):
        wr.writerow(sh.row_values(rownum))

    your_csv_file.close()

2
难道不应该是 wr.writerow(sh.row_values(rownum)) 吗?请参见这里 - kuujo
8
如果您不知道工作表的名称(即它不是“Sheet1”),则可以使用wb.sheet_by_index(0)来获取第一个工作表,无论其名称如何。 - Li-aung Yip
17
注意:这种方法无法保留某些数字的Excel格式。 整数格式化的数字值将以小数形式写入(例如,2-> 2.0),整数格式化的公式也将以小数形式写入(例如,= A1 / B2显示为1但导出为0.9912319),文本格式化的数字值的前导零将被删除(例如,“007”->“7.0”)。祝你在秘密特工数据库中查询邦德先生好运!如果你幸运的话,这些问题会明显地导致失败。如果你不幸运,它们可能会悄悄地破坏你的数据。 - Stew
2
有什么建议,@Stew? - binarymason
3
对于Python 3:使用your_csv_file = open(xls_path, 'w')(而不是'wb')。CSV模块在文本模式下输入,而不是字节模式。否则,您将会得到以下错误信息:TypeError: a bytes-like object is required, not 'str' - Tyler Dane Hitzeman
显示剩余2条评论

60

我会使用pandas。计算密集的部分是用cython或c扩展编写的,以加快处理速度,语法非常简洁。例如,如果您想要将文件“your_workbook.xls”的“Sheet1”转换为文件“your_csv.csv”,只需使用顶级函数read_excelDataFrame类中的方法to_csv,如下所示:

import pandas as pd
data_xls = pd.read_excel('your_workbook.xls', 'Sheet1', index_col=None)
data_xls.to_csv('your_csv.csv', encoding='utf-8')

设置 encoding='utf-8' 可以缓解其他回答中提到的 UnicodeEncodeError


2
如果行中包含其他语言的文本,则它可能无法正常工作,文本将显示为“?”。 - Muhammad Shauket
4
@philE 这太慢了。使用xlsx2csv。 - CodeFarmer
有没有关于处理可能存在于Excel单元格内容中的换行符的技巧? - Raghav

43

也许有人会发现这个可直接使用的代码很有用。它可以从Excel工作簿中的所有电子表格创建CSV文件。

enter image description here

Python 2:

# -*- coding: utf-8 -*-
import xlrd
import csv
from os import sys
 
def csv_from_excel(excel_file):
    workbook = xlrd.open_workbook(excel_file)
    all_worksheets = workbook.sheet_names()
    for worksheet_name in all_worksheets:
        worksheet = workbook.sheet_by_name(worksheet_name)
        with open(u'{}.csv'.format(worksheet_name), 'wb') as your_csv_file:
            wr = csv.writer(your_csv_file, quoting=csv.QUOTE_ALL)
            for rownum in xrange(worksheet.nrows):
                wr.writerow([unicode(entry).encode("utf-8") for entry in worksheet.row_values(rownum)])

if __name__ == "__main__":
    csv_from_excel(sys.argv[1])

Python 3:

import xlrd
import csv
from os import sys

def csv_from_excel(excel_file):
    workbook = xlrd.open_workbook(excel_file)
    all_worksheets = workbook.sheet_names()
    for worksheet_name in all_worksheets:
        worksheet = workbook.sheet_by_name(worksheet_name)
        with open(u'{}.csv'.format(worksheet_name), 'w', encoding="utf-8") as your_csv_file:
            wr = csv.writer(your_csv_file, quoting=csv.QUOTE_ALL)
            for rownum in range(worksheet.nrows):
                wr.writerow(worksheet.row_values(rownum))

if __name__ == "__main__":
    csv_from_excel(sys.argv[1])

只有几个注释:有些工作表可能是空的。我认为生成空的CSV文件没有任何用处,最好在执行任何操作之前对worksheet.nrows> 0进行先前评估。 - Javier Novoa C.
另外,最好为CSV文件使用上下文。 ;) - Javier Novoa C.
1
你可以使用 if worksheet.nrows == 0: continue 跳过空工作表。 - duhaime
我得到了以下错误信息:`File "<ipython-input-24-5fa644cde9f8>", line 15, in <module> csv_from_excel("Analyse Article Lustucru PF.xlsx") File "<ipython-input-24-5fa644cde9f8>", line 6, in csv_from_excel with open('{}.csv'.format(worksheet_name), 'wb') as your_csv_file:UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 2: ordinal not in range(128)` 你知道如何处理吗? - Orhan Yazar
@OrhanYazar 尝试使用 u'{}.csv'.format(worksheet_name),注意开头的 u 代表 Unicode。 - andilabs

22

我会使用 csvkit,它使用xlrd(用于xls)和openpyxl(用于xlsx)将几乎任何表格数据转换为csv。

安装后,只需执行以下步骤:

python in2csv myfile > myoutput.csv

它可以处理所有格式检测问题,因此您可以传递几乎任何表格数据源。而且它也是跨平台的(没有win32依赖)。


我也喜欢这个工具。虽然与此问题不太相关,但是在这本书中提到了csvkit以及其他一些数据处理工具,它们可以让你在shell中直接转换数据。 - devforfu

8

首先将您的Excel电子表格读入pandas中,以下代码将把您的Excel电子表格导入pandas作为OrderedDict类型,其中包含所有工作表作为数据帧。然后只需使用worksheet_name作为键来访问特定的工作表作为数据帧,并使用df.to_csv()将所需的工作表保存为CSV文件。希望这对您有所帮助。

import pandas as pd
df = pd.read_excel('YourExcel.xlsx', sheet_name=None)
df['worksheet_name'].to_csv('YourCsv.csv')  

如果您的Excel文件只包含一个工作表,请使用以下代码:

import pandas as pd
df = pd.read_excel('YourExcel.xlsx')
df.to_csv('YourCsv.csv') 

如果有人想将单个Excel工作簿中的所有工作表转换为不同的CSV文件,请尝试以下代码:

import pandas as pd
def excelTOcsv(filename):
    df = pd.read_excel(filename, sheet_name=None)  
    for key, value in df.items(): 
        return df[key].to_csv('%s.csv' %key)

这个函数的作用是将同一Excel工作簿中的多个工作表转换为多个csv文件。其中,键是工作表名称,值是工作表内的内容。


3

xlsx2csv比pandas和xlrd更快速

xlsx2csv -s 0 crunchbase_monthly_.xlsx cruchbase

Excel文件通常带有n个工作表名称。

-s is sheetname index.

然后,将创建cruchbase文件夹,将每个xlsx表格转换为单个csv文件。

p.s. csvkit 也很棒。


3

@andi 我测试了你的代码,它很好用,但是

我的表格中有一列是这样的

2013-03-06T04:00:00

日期和时间在同一个单元格里

在导出过程中会变成乱码,导出后文件中的数据是这样的

41275.0416667

其他列都没问题。

csvkit对这一列也处理得很好,但只能导出一个表格,而我的文件有很多个表格。


我也做了同样的事情,结果也得到了相同的垃圾数据。你知道解决方法吗? - Sailanarmo
1
抱歉,我忘记了当时做了什么。我学到了那不是一个随机数,而是Excel使用的日期时间的内部表示方式。因此,有一个算法可以得到正确的日期时间。 - user1632812
1
我不能更加精确,很抱歉。 - user1632812

1

引用 Scott Ming答案,适用于包含多个工作表的工作簿:

这里有一个Python脚本getsheets.py镜像),在使用之前应该安装pandasxlrd

运行此命令:

pip3 install pandas xlrd  # or `pip install pandas xlrd`

它是如何工作的?

$ python3 getsheets.py -h
Usage: getsheets.py [OPTIONS] INPUTFILE

Convert a Excel file with multiple sheets to several file with one sheet.

Examples:

    getsheets filename

    getsheets filename -f csv

Options:
-f, --format [xlsx|csv]  Default xlsx.
-h, --help               Show this message and exit.

转换为多个xlsx文件:
$ python3 getsheets.py goods_temp.xlsx
Sheet.xlsx Done!
Sheet1.xlsx Done!

All Done!

转换为几个 CSV 文件:

$ python3 getsheets.py goods_temp.xlsx -f csv
Sheet.csv Done!
Sheet1.csv Done!

All Done!

getsheets.py:

# -*- coding: utf-8 -*-

import click
import os
import pandas as pd


def file_split(file):
    s = file.split('.')
    name = '.'.join(s[:-1])  # get directory name
    return name


def getsheets(inputfile, fileformat):
    name = file_split(inputfile)
    try:
        os.makedirs(name)
    except:
        pass

    df1 = pd.ExcelFile(inputfile)
    for x in df1.sheet_names:
        print(x + '.' + fileformat, 'Done!')
        df2 = pd.read_excel(inputfile, sheetname=x)
        filename = os.path.join(name, x + '.' + fileformat)
        if fileformat == 'csv':
            df2.to_csv(filename, index=False)
        else:
            df2.to_excel(filename, index=False)
    print('\nAll Done!')


CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])


@click.command(context_settings=CONTEXT_SETTINGS)
@click.argument('inputfile')
@click.option('-f', '--format', type=click.Choice([
    'xlsx', 'csv']), default='xlsx', help='Default xlsx.')
def cli(inputfile, format):
    '''Convert a Excel file with multiple sheets to several file with one sheet.

    Examples:

    \b
        getsheets filename

    \b
        getsheets filename -f csv
    '''
    if format == 'csv':
        getsheets(inputfile, 'csv')
    else:
        getsheets(inputfile, 'xlsx')


cli()

1
我们可以使用Python的Pandas库将xls文件转换为csv文件。 以下代码将把xls文件转换为csv文件。 import pandas as pd
从本地路径读取Excel文件:
df = pd.read_excel("C:/Users/IBM_ADMIN/BU GPA Scorecard.xlsx",sheetname=1)

在列上修剪空格:

df.columns = df.columns.str.strip()

将数据帧发送到CSV文件中,该文件将使用管道符号分隔而不带索引:
df.to_csv("C:/Users/IBM_ADMIN/BU GPA Scorecard csv.csv",sep="|",index=False)

使用您的代码,我遇到了一个错误:>>> dfs = pd.read_excel(file_name, sheet_name=None) >>> dfs.columns = dfs.columns.str.strip() Traceback (most recent call last): File "", line 1, in AttributeError: 'collections.OrderedDict' object has no attribute 'columns' - Aviral Srivastava

1
Python不是这个任务的最佳工具。我尝试了几种Python方法,但没有一种可以100%地工作(例如,10%转换为0.1,或列类型混乱等)。正确的工具是PowerShell,因为它是MS产品(就像Excel一样)并且具有最好的集成。

只需下载this PowerShell脚本,编辑第47行以输入包含Excel文件的文件夹路径,并使用PowerShell运行脚本即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接