数据结构教程

本教程为您提供了一个快速的介绍,关于使用 xlwings 读取和写入值时最常见的用例和默认行为。对于如何通过方法控制行为的深入文档,请参阅options方法,查看转换器和选项.

下面的所有代码示例都依赖于以下导入:

>>> import xlwings as xw

单元格

默认情况下,单个单元格返回为float, unicode, Nonedatetime对象,具体取决于单元格是否包含数字、字符串、为空或表示日期:

>>> import datetime as dt
>>> sheet = xw.Book().sheets[0]
>>> sheet['A1'].value = 1
>>> sheet['A1'].value
1.0
>>> sheet['A2'].value = 'Hello'
>>> sheet['A2'].value
'Hello'
>>> sheet['A3'].value is None
True
>>> sheet['A4'].value = dt.datetime(2000, 1, 1)
>>> sheet['A4'].value
datetime.datetime(2000, 1, 1, 0, 0)

列表

  • 一维列表:在 Excel 中表示行或列的范围将作为简单列表返回,这意味着一旦它们进入 Python,您将丢失有关方向的信息。如果这是一个问题,下一点将向您展示如何保留此信息:

    >>> sheet = xw.Book().sheets[0]
    >>> sheet['A1'].value = [[1],[2],[3],[4],[5]]  # Column orientation (nested list)
    >>> sheet['A1:A5'].value
    [1.0, 2.0, 3.0, 4.0, 5.0]
    >>> sheet['A1'].value = [1, 2, 3, 4, 5]
    >>> sheet['A1:E1'].value
    [1.0, 2.0, 3.0, 4.0, 5.0]
    

    若要强制单个单元格以列表形式返回,请使用:

    >>> sheet['A1'].options(ndim=1).value
    [1.0]
    

    注意

    要以列方向将列表写入 Excel,请使用transpose: sheet.range('A1').options(transpose=True).value = [1,2,3,4]

  • 二维列表:如果需要保留行或列的方向,请在范围选项中设置ndim。这将使范围作为嵌套列表(“二维列表”)返回:

    >>> sheet['A1:A5'].options(ndim=2).value
    [[1.0], [2.0], [3.0], [4.0], [5.0]]
    >>> sheet['A1:E1'].options(ndim=2).value
    [[1.0, 2.0, 3.0, 4.0, 5.0]]
    
  • 二维范围会自动作为嵌套列表返回。当在 Excel 中的范围内分配(嵌套)列表时,只需指定左上角单元格为目标地址即可。这个示例还使用了索引符号将值重新读回 Python:

    >>> sheet['A10'].value = [['Foo 1', 'Foo 2', 'Foo 3'], [10, 20, 30]]
    >>> sheet.range((10,1),(11,3)).value
    [['Foo 1', 'Foo 2', 'Foo 3'], [10.0, 20.0, 30.0]]
    

注意

尝试尽量减少与 Excel 的交互次数。总是更有效率地执行sheet.range('A1').value = [[1,2],[3,4]]而不是sheet.range('A1').value = [1, 2]sheet.range('A2').value = [3, 4].

范围扩展

您可以通过方法expand或通过expand关键字在options方法中动态获取 Excel 范围的维度。虽然expand返回一个扩展的范围对象,但在访问范围的值时才会评估选项。以下面的例子最好解释了两者的区别:

>>> sheet = xw.Book().sheets[0]
>>> sheet['A1'].value = [[1,2], [3,4]]
>>> range1 = sheet['A1'].expand('table')  # or just .expand()
>>> range2 = sheet['A1'].options(expand='table')
>>> range1.value
[[1.0, 2.0], [3.0, 4.0]]
>>> range2.value
[[1.0, 2.0], [3.0, 4.0]]
>>> sheet['A3'].value = [5, 6]
>>> range1.value
[[1.0, 2.0], [3.0, 4.0]]
>>> range2.value
[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]

'table'扩展为'down''right',还有其他可用选项分别用于仅扩展列或行。

注意

使用expand()与一个命名为左上角单元格的范围结合使用,可以为您提供 Excel 中的灵活设置:您可以移动表格并更改其大小而无需调整代码,例如通过使用类似sheet.range('NamedRange').expand().value.

NumPy 数组

NumPy 数组类似于嵌套列表。但是,空单元格由nan表示,而不是None。如果您希望将范围作为数组读取,请设置convert=np.array的顶部检查options方法:

>>> import numpy as np
>>> sheet = xw.Book().sheets[0]
>>> sheet['A1'].value = np.eye(3)
>>> sheet['A1'].options(np.array, expand='table').value
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

Pandas DataFrame

>>> sheet = xw.Book().sheets[0]
>>> df = pd.DataFrame([[1.1, 2.2], [3.3, None]], columns=['one', 'two'])
>>> df
   one  two
0  1.1  2.2
1  3.3  NaN
>>> sheet['A1'].value = df
>>> sheet['A1:C3'].options(pd.DataFrame).value
   one  two
0  1.1  2.2
1  3.3  NaN
# options: work for reading and writing
>>> sheet['A5'].options(index=False).value = df
>>> sheet['A9'].options(index=False, header=False).value = df

Pandas Series

>>> import pandas as pd
>>> import numpy as np
>>> sheet = xw.Book().sheets[0]
>>> s = pd.Series([1.1, 3.3, 5., np.nan, 6., 8.], name='myseries')
>>> s
0    1.1
1    3.3
2    5.0
3    NaN
4    6.0
5    8.0
Name: myseries, dtype: float64
>>> sheet['A1'].value = s
>>> sheet['A1:B7'].options(pd.Series).value
0    1.1
1    3.3
2    5.0
3    NaN
4    6.0
5    8.0
Name: myseries, dtype: float64

注意

在将列表、NumPy 数组或 Pandas DataFrame 写入 Excel 时,您只需指定左上角单元格即可,例如:sheet['A1'].value = np.eye(10)

分块:读取/写入大数据帧等

当你从大范围读取数据或写入数据时,你可能需要分块处理,否则会遇到超时或内存错误。理想的chunksize将取决于你的系统和数组的大小,因此你需要尝试几种不同的分块大小以找到一个适合的:

import pandas as pd
import numpy as np
sheet = xw.Book().sheets[0]
data = np.arange(75_000 * 20).reshape(75_000, 20)
df = pd.DataFrame(data=data)
sheet['A1'].options(chunksize=10_000).value = df

并且读取也是一样的:

# As DataFrame
df = sheet['A1'].expand().options(pd.DataFrame, chunksize=10_000).value
# As list of list
df = sheet['A1'].expand().options(chunksize=10_000).value