用win32com在python中编写数组到excel

Eri*_*ric 6 python excel win32com

我正在制作一个解析数据文件的python.然后将解析的数据发送到excel文件.数据可能相当庞大.我正在看10到20列,但行数可以超过100.000.

使用win32com将此数据量写入excel需要相当长的时间.我的第一步是在excel文件中迭代遍历单元格,这非常耗时.经过一番挖掘后,我发现如何通过一次调用来编写一行,从而大大减少了所需的时间.

但是,当我需要向excel发送100.000行数据时,仍然需要花费很多时间.我很确定通过一次调用发送完整的数组,我可以进一步提高速度.但是到目前为止我无法做到这一点.

请参阅下面的代码,该代码演示了该问题.代码显示了时间上的差异.但是,第三步,通过一次调用向一个范围发送完整数组不会导致excel中的正确数据.我究竟做错了什么?

import win32com.client
import time

#create data array
row = range(0,10)
i = 0
data_array = []
while i < 1000:
    data_array.append(row)
    i += 1

#write the array to an excel file
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = True
excel.ScreenUpdating = False
book = excel.Workbooks.Add()
sh1 = book.Worksheets(1)
sh2 = book.Worksheets(2)
sh3 = book.Worksheets(3)

#double loop, writing individual cells
print "Writing with double loop to inidividual cells."
start = time.time()
row = 0
for line in data_array:
    row += 1
    col = 0
    for field in line:
        col += 1
        sh1.Cells(row, col).Value = field
print "Processing time: " + str(time.time() - start) + " seconds."

#single loop, writing a row to a range
print "Writing with double loop to inidividual cells."
start = time.time()
row = 0
for line in data_array:
    row += 1
    sh2.Range(sh2.Cells(row,1), sh2.Cells(row, len(line))).Value = line
print "Processing time: " + str(time.time() - start) + " seconds."

#no loop, write array to range
print "Writing with double loop to inidividual cells."
start = time.time()
try:
    sh3.Range(sh3.Cells(row,1), sh3.Cells(len(data_array), len(data_array[0]))).Value = data_array
    print "Processing time: " + str(time.time() - start) + " seconds."
except:
    print "Failed to write array to excel file."

excel.ScreenUpdating = True
sheet = None
book = None
excel.Quit()
excel = None
Run Code Online (Sandbox Code Playgroud)

Eri*_*ric 5

我一直在对此进行一些研究。并得出了一些有趣的结论。

确实有多种解决方案可以从 python 将数据写入 Excel。我最终专注于三个模块。

win32com客户端

工作缓慢。但是该文档可以在 Excel 中打开。因此,最终结果可供用户在 Excel 中开始处理。对于大量数据来说不太好。

在我的电脑(核心 i5)应用程序上编写 10,000 行 10 列。70秒。

import win32com.client
import time

#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
    data_array.append(row)
    i += 1

#write the array to an excel file
excel = win32com.client.Dispatch("Excel.Application")
excel.Visible = True
excel.ScreenUpdating = False
book = excel.Workbooks.Add()
sheet = book.Worksheets(1)

#single loop, writing a row to a range
print "Writing using win32com.client"
start = time.time()
row = 0
for line in data_array:
    row += 1
    sheet.Range(sheet.Cells(row,1), sheet.Cells(row, len(line))).Value = line
print "Processing time: " + str(time.time() - start) + " seconds."

print "Completed: " + str(time.time() - start) + " seconds."
excel.ScreenUpdating = True
sheet = None
book = None
excel.Quit()
excel = None
Run Code Online (Sandbox Code Playgroud)

开放式pyxl

有点快,但仍然不是很好。该模块将数据传输到 Excel 内存对象的速度很慢,但保存速度非常快。它在 22.3 秒内创建 10,000 行、10 列,并在另外 0.5 秒内保存文件。当我用 100,000 行和 10 列对此进行测试时。数据创建时间为 228.3 秒,文件保存时间为 2.9 秒。相当慢,但文件保存速度很快。因此,openpyxl 可能适合对现有数据进行更改(格式化),尽管我尚未对此进行测试。另一个优点是使用 openpyxl 编码比使用 win32com.client 更容易。

import openpyxl
import sys
import time

#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
    data_array.append(row)
    i += 1

#create an excel workbook and sheet object
book = openpyxl.Workbook(optimized_write = True)

#single loop, writing rows
start = time.time()
print "Writing with single loop using openpyxl"
sheet = book.create_sheet()
for line in data_array:
    sheet.append(line)
print "Processing time: " + str(time.time() - start) + " seconds."

#close and save the file.
book.save('openpyxl.xlsx')
print "Total time: " + str(time.time() - start) + " seconds."
Run Code Online (Sandbox Code Playgroud)

我面临 openpyxl 的另一个问题。在我的真实工具中,openpyxl 在保存大量数据(> 10,000 行)时遇到问题。这个我还没有弄清楚,也许我不会费心去进一步研究它。

PyExcelerate

这个首先是快的。它在短短 0.17 秒内创建了 10,000 行和 10 列。然而保存文件需要 2.2 秒。迄今为止,这三个选项中最快的一个。当我尝试使用此模块保存 100,000 行和 10 列时,Excel 数据仅在 1.8 秒内创建。然而,保存文件现在需要 21.7 秒。因此,这个模块确实很快,但是在写入文件时会受到惩罚。总体而言仍然是其中最快的。PyExcelerate 的另一个优点是编码非常简单,就像 openpyxl 一样容易。

import pyexcelerate
import sys
import time

#create data array
row = range(0,10)
i = 0
data_array = []
while i < 10000:
    data_array.append(row)
    i += 1

print sys.version

#create an excel workbook and sheet object
book = pyexcelerate.Workbook()

#single loop, writing rows
start = time.time()
print "Writing with single loop using PyExcelerate"
book.new_sheet("data", data = data_array)

print "Processing time: " + str(time.time() - start) + " seconds."

#close and save the file.
book.save('pyexcelerate.xlsx')
print "Total time: " + str(time.time() - start) + " seconds."
Run Code Online (Sandbox Code Playgroud)

所以我的结论是 PyExcelerate 是迄今为止最快的。win32com.client的优点是创建的excel文件可以在excel中打开,以便用户可以开始使用创建的数据。Openpyxl 在创建后进行样式更改可能会很有趣。但是,我还没有对此进行测试。因此,将 win32com.client、openpyxl 和 PyExcelerate 组合在一个应用程序中可能会很有好处。


bgu*_*ach 3

使用 COM 从 Excel 文件中读取文件是一种极大的时间浪费。这就像用坦克杀死苍蝇一样。考虑到 win32com 使用 Windows API 进行复杂的调用,与 excel 通信,检索数据并将其发送回 python。当信息已经作为文件存在时为什么还要这样做?

有些库可以直接解析 excel 文件,正如您可以想象的那样,它们的速度可以提高 100 倍,因为没有对 win API 的过于复杂的调用。

我已经使用openpyxl取得了很多成功,但是还有其他库可以同样好甚至更好。

只是大数据的一个例子(使用生成器而不是将所有内容加载到内存中):

from openpyxl import load_workbook
wb = load_workbook(filename='large_file.xlsx', use_iterators=True)
ws = wb.get_sheet_by_name(name='big_data') # ws is now an IterableWorksheet

for row in ws.iter_rows(): # it brings a new method: iter_rows()
     for cell in row:
         print cell.internal_value
Run Code Online (Sandbox Code Playgroud)

可使用等效方法写入单元格。您甚至可以格式化它们,尽管它不是(或曾经)非常完整。

编辑

有关如何将大量信息写入文件的示例xlsx

from openpyxl import Workbook
from openpyxl.cell import get_column_letter

wb = Workbook()
dest_filename = r'empty_book.xlsx'
ws = wb.active
ws.title = "range names"

for col_idx in xrange(1, 40):
    col = get_column_letter(col_idx)
    for row in xrange(1, 600):
        ws.cell('%s%s'%(col, row)).value = '%s%s' % (col, row)

ws = wb.create_sheet()
ws.title = 'Pi'
ws['F5'] = 3.14
wb.save(filename=dest_filename)
Run Code Online (Sandbox Code Playgroud)