如何从 python 中的 xlsx(而不是公式)读取数据?

How to read data from xlsx (instead of formulas) in python?

我将从 posting 用于为该线程创建测试用例 (foo.xlsx) 的代码示例开始。

这个简单的代码创建了一个包含数字条目和公式的 xlsx 文件:

[boris@E7490-DELL temp]$ cat xlsx1.py
#!/bin/env python

import pandas as pd

d = {'col1': [7, 2, 5, 9, 1], 'col2': [3, 6, 6, 7, 9]}
df = pd.DataFrame(data=d)

writer = pd.ExcelWriter("foo.xlsx", engine="xlsxwriter")
df["prod"] = None
df["prod"] = (
    '=INDIRECT("R[0]C[%s]", 0)*INDIRECT("R[0]C[%s]", 0)'
    % (
        df.columns.get_loc("col1") - df.columns.get_loc("prod"),
        df.columns.get_loc("col2") - df.columns.get_loc("prod"),
    )
)
df["sum"] = None
df["sum"] = (
    '=SUM(INDIRECT("R[0]C[%s]:R[0]C[%s]",0))'
    % (
        df.columns.get_loc("col1") - df.columns.get_loc("sum"),
        df.columns.get_loc("col2") - df.columns.get_loc("sum"),
    )
)
df["max"] = None
df["max"] = (
    '=MAX(INDIRECT("R[0]C[%s]:R[0]C[%s]",0))'
    % (
        df.columns.get_loc("col1") - df.columns.get_loc("max"),
        df.columns.get_loc("col2") - df.columns.get_loc("max"),
    )
)
df["min"] = None
df["min"] = (
    '=MIN(INDIRECT("R[0]C[%s]:R[0]C[%s]",0))'
    % (
        df.columns.get_loc("col1") - df.columns.get_loc("min"),
        df.columns.get_loc("col2") - df.columns.get_loc("min"),
    )
)
print(df)

df.to_excel(writer, index=False)
writer.save()

执行上述代码后的CLI输出,即print(df):

[boris@E7490-DELL temp]$ ./xlsx1.py
   col1  col2                                               prod                                      sum                                      max                                      min
0     7     3  =INDIRECT("R[0]C[-2]", 0)*INDIRECT("R[0]C[-1]"...  =SUM(INDIRECT("R[0]C[-3]:R[0]C[-2]",0))  =MAX(INDIRECT("R[0]C[-4]:R[0]C[-3]",0))  =MIN(INDIRECT("R[0]C[-5]:R[0]C[-4]",0))
1     2     6  =INDIRECT("R[0]C[-2]", 0)*INDIRECT("R[0]C[-1]"...  =SUM(INDIRECT("R[0]C[-3]:R[0]C[-2]",0))  =MAX(INDIRECT("R[0]C[-4]:R[0]C[-3]",0))  =MIN(INDIRECT("R[0]C[-5]:R[0]C[-4]",0))
2     5     6  =INDIRECT("R[0]C[-2]", 0)*INDIRECT("R[0]C[-1]"...  =SUM(INDIRECT("R[0]C[-3]:R[0]C[-2]",0))  =MAX(INDIRECT("R[0]C[-4]:R[0]C[-3]",0))  =MIN(INDIRECT("R[0]C[-5]:R[0]C[-4]",0))
3     9     7  =INDIRECT("R[0]C[-2]", 0)*INDIRECT("R[0]C[-1]"...  =SUM(INDIRECT("R[0]C[-3]:R[0]C[-2]",0))  =MAX(INDIRECT("R[0]C[-4]:R[0]C[-3]",0))  =MIN(INDIRECT("R[0]C[-5]:R[0]C[-4]",0))
4     1     9  =INDIRECT("R[0]C[-2]", 0)*INDIRECT("R[0]C[-1]"...  =SUM(INDIRECT("R[0]C[-3]:R[0]C[-2]",0))  =MAX(INDIRECT("R[0]C[-4]:R[0]C[-3]",0))  =MIN(INDIRECT("R[0]C[-5]:R[0]C[-4]",0))

foo.xlsx 文件内容(屏幕截图显示 LibreOffice Calc 显示的 foo.xlsx)

这就是我的测试用例 (foo.xlsx) 的创建方式。这个xlsx里面只有数值,有的是整数,有的是公式计算出来的。现在我想在 pandas 数据框中读取此 xlsx 文件以进行 post 处理(不需要公式,但需要公式计算的实际值)。 我尝试了两种方法(均未成功),接下来将进行说明...

方法 1) 使用 pandas.read_excel:

代码:

[boris@E7490-DELL temp]$ cat xlsx2.py
#!/bin/env python

import pandas as pd

read_file = pd.read_excel("foo.xlsx")
print(read_file)

read_file.to_csv ("foo.csv", index = None, header=True)

CLI 输出:

[boris@E7490-DELL temp]$ ./xlsx2.py
   col1  col2  prod  sum  max  min
0     7     3     0    0    0    0
1     2     6     0    0    0    0
2     5     6     0    0    0    0
3     9     7     0    0    0    0
4     1     9     0    0    0    0

foo.csv文件内容:

[boris@E7490-DELL temp]$ cat foo.csv
col1,col2,prod,sum,max,min
7,3,0,0,0,0
2,6,0,0,0,0
5,6,0,0,0,0
9,7,0,0,0,0
1,9,0,0,0,0

方法 2) 使用 openpyxl.load_workbook:

代码:

[boris@E7490-DELL temp]$ cat xlsx3.py
#!/bin/env python

import pandas as pd
from openpyxl import load_workbook

wb = load_workbook("foo.xlsx", data_only=True)
ws = wb['Sheet1']
df = pd.DataFrame(ws.values)
print(df.head())

df.to_csv ("foo.csv", index = None, header=True)

CLI 输出:

[boris@E7490-DELL temp]$ ./xlsx3.py
      0     1     2    3    4    5
0  col1  col2  prod  sum  max  min
1     7     3     0    0    0    0
2     2     6     0    0    0    0
3     5     6     0    0    0    0
4     9     7     0    0    0    0

foo.csv文件内容:

[boris@E7490-DELL temp]$ cat foo.csv
0,1,2,3,4,5
col1,col2,prod,sum,max,min
7,3,0,0,0,0
2,6,0,0,0,0
5,6,0,0,0,0
9,7,0,0,0,0
1,9,0,0,0,0

两种方法都无法从 xlsx 中获取数值。我被困在这里,非常感谢任何帮助。

这里有一些解决方法,不是对正在发生的事情的真正解释,但是...

我得到的结果和你一样,但是如果我打开 excel 文件并保存它,然后在 pandas 中读取它就会得到你想要的数字。所以试试看,打开 excel 并保存它。您可以轻松编写脚本。

由于我不知道如何进一步自动化,我将继续执行无头执行:

soffice --headless --convert-to csv foo.xlsx

foo.csv 文件内容:

[boris@E7490-DELL temp]$ cat foo.csv
col1,col2,prod,sum,max,min
7,3,21,10,7,3
2,6,12,8,6,2
5,6,30,11,6,5
9,7,63,16,9,7
1,9,9,10,9,1

然后我将把这个 csv 文件读到 pandas data-frame post-processing。