我的代码从Google Drive(使用Pydrive)下载一个.xlsx文件,找到一些带有大熊猫的空白单元格,然后用OpenPyxl填充那些空白单元。
当我打开OpenPyXl更改的文件时,一切看起来都很棒。但是,当我使用pandas read_excel函数时,所有具有方程式的单元格被读为空白。我怀疑问题是openpyxl,因为当我在驱动器上预览文件时,这些单元格是空白的。OpenPyXl没有触摸的文件没有任何问题。
看来我的问题与这个问题非常相似,但是由于我的目标只是使配方不受影响(我只想填充空白单元),所以我真的不想解析公式不确定如何或是否应用Felipe的修复程序。
我希望能够下载文件以与散景绘制该文件,用户和Python都将在编辑该程序,因此我真的希望Pandas能够读取该方程式是否修改了用户文件或OpenPyXl修改文件。文件中的方程是单击并拖动"共享方程式",如果可能的话,我想保持这种方式,因此我想避免使用data_only=True
。我尝试指定data_only=False
,但这似乎没有改变任何内容。
我正在使用openpyxl 2.3.5 2.4,我在代码运行时保持Excel关闭。
在此处可用openpyxl修改之前和之后的文件版本。
我的代码在这里,所有OpenPyXl代码均隔离为: #导入库 导入日期 进口 导入操作系统 导入大熊猫作为pd 来自OpenPyXl Import load_workbook 从Itertools Import Islice #散景相互作用的相对进口
dl = imp.load_source('downloader', os.getcwd() +
'/Project/downloader.py')
gdu = imp.load_source('googledriveutils', os.getcwd() +
'/Project/googledriveutils.py')
remove_file = gdu.remove_file
find_folderid = gdu.find_folderid
get_file_list = gdu.get_file_list
# Define constants
COL_LABEL = 'nProbe - '
# TODO: ORP PROBE: REVISE THIS DATE when orp probe is added
IGNORE_BEFORE = pd.to_datetime('5.24.2016')
PROBE_DICT = {'DO (mg/L)': 'DO mg/L',
'pH': 'pH',
'NH4+ (mgN/L)': 'Ammonium',
'ORP (mV)': 'ORP mV'}
TS = 'nTimestamps'
def save_to_workbook(newval,
date,
header,
rows_to_skip=12,
wbname='temp.xlsx',
sheet_name='Reactor Data'):
wb = load_workbook(wbname)
ws = wb[sheet_name]
for cell in ws[rows_to_skip+1]:
# TODO: Error if header isn't found
if cell.value == header:
colno = cell.col_idx
break
for row in ws.iter_rows(min_row=rows_to_skip+1, min_col=1, max_col=1):
for cell in row:
# TODO: Error if date isn't found
if cell.value == date:
rowno = cell.row
break
ws.cell(row=rowno, column=colno).value = newval
wb.save(wbname)
return df
def find_r1masterfile():
# Navigate through the directories
wlab_fid = find_folderid('Winkler Lab', 'root')
kp_fid = find_folderid('KathrynsProjects', wlab_fid)
amxrct_fid = find_folderid('Anammox Reactor', kp_fid)
trials_fid = find_folderid('Reactor Trials', amxrct_fid)
# List files in directory
file_list = get_file_list(trials_fid)
for afile in file_list:
if afile['title'] == 'AMX RCT.xlsx':
# Return the file we asked for
return afile
# TODO: error if there was no file with that name
def save_r1masterfile(csv, rows_to_skip=12, filename='temp.xlsx', sheet_name='Reactor Data'):
# Get the file we want
master_file = find_r1masterfile()
try:
master_file.GetContentFile(filename)
except Exception, e:
print "Warning: Something wrong with file R1 Master File."
print str(e)
# TODO: add an email alarm to responsible user
if csv:
return master_file
else:
# convert to dataframe
wb = load_workbook(filename, data_only=True)
ws = wb[sheet_name]
print ws["B14"].value
data = ws.values
data = list(data)[rows_to_skip:]
cols = list(data[0])
del cols[0]
del data[0]
idx = [r[0] for r in data]
data = (islice(r, 1, None) for r in data)
df = pd.DataFrame(data, index=idx, columns=cols)
print df.dropna(how='all')
remove_file(filename)
return df
def upload_r1masterfile(filename='temp.xlsx'):
# Get the file we want
master_file = find_r1masterfile()
try:
master_file.SetContentFile(filename)
master_file.Upload()
except Exception, e:
print "Warning: Something wrong with file R1 Master File."
print str(e)
# TODO: add an email alarm to responsible user
def populate_r1masterfile(rows_to_skip=12, filename='temp.xlsx'):
# Get the R1 master file as a file
save_r1masterfile(True)
# Convert the juicy stuff to a dataframe
masterdf = pd.read_excel(filename,
sheetname='Reactor Data',
encoding="utf-16",
skiprows=rows_to_skip,
sep='t',
index_col='Date',
keep_default_na=False,
na_values=['-1.#IND', '1.#QNAN', '1.#IND',
'-1.#QNAN', '','N/A', '#NA', 'NA'
'NULL', 'NaN', '-NaN', 'nan', '-nan'])
# Find what we will populate with probe data
# Find timestamps
ts_columns = [col for col in masterdf.columns if TS in col]
tsdf = masterdf[ts_columns]
# Find probes, ignore before given date
probe_columns = [col for col in masterdf.columns if COL_LABEL in col]
probedf = masterdf[probe_columns]
probedf = probedf[masterdf.index > IGNORE_BEFORE]
# Find Indices and column labels of blank values
stackdf = probedf.stack(dropna=False)
empty = stackdf[stackdf.isnull()].index.tolist()
# For each blank look for the probe, time & date of cycle, and return val
for each in empty:
probe, time = each[1].split(COL_LABEL)
time = tsdf.loc[each[0], time+TS]
ts = each[0]+pd.DateOffset(hour=time.hour, minute=time.minute)
val = dl.get_val_from(1, ts, PROBE_DICT.get(probe))
probedf.set_value(each[0], each[1], val)
# Save that value to the workbook
save_to_workbook(val, each[0], each[1])
upload_r1masterfile()
print 'Master file updated. ' + str(datetime.datetime.now())
remove_file('temp.xlsx')
return probedf
更新
我根据查理的建议修改了代码(上面已更新)。但是我仍然在数据框架中得到Nones。为了提供一个更具体的示例,当我运行此代码时为什么会这样:
from openpyxl import load_workbook
wb = load_workbook('AMX RCT mod.xlsx', data_only=True)
ws = wb['Reactor Data']
print 'Value of B14 Formula is: ' + str(ws["B14"].value)
使用此文件,我回来了?:
Value of B14 Formula is: None
有解决方法吗?
使用openpyxl 2.4您可以在一次通过中完成所需的工作。我已经采用了您的第一个功能并改编了它。
from itertools import islice
from pandas import DataFrame
def save_to_workbook(newval,
date,
header,
rows_to_skip=12,
wbname='temp.xlsx',
sheet_name='Reactor Data'):
wb = load_workbook(wbname)
ws = wb[sheet_name]
rowno = None
colno = None
for cell in ws[1]:
# TODO: Error if header isn't found
if cell.value == header:
colno = col
for row in ws.iter_rows(min_row=rows_to_skip+1, min_col=1, max_col=1):
for cell in row:
# TODO: Error if date isn't found
if cell.value == date:
rowno = row
break
# TODO: Fix this
ws.cell(row=rowno, column=colno).value = newval
# convert to dataframe
data = ws.values
cols = next(data)[1:]
data = list(data)
idx = [r[0] for r in data]
data = (islice(r, 1, None) for r in data)
df = DataFrame(data, index=idx, columns=cols)
return df
这可能没有完成您想要的一切,但希望您能使您入门。它还避免了保存和解析整个工作簿,这可能会使它更快。
要与OpenPyxl 2.4一起工作,您要么需要进行pip install -U --pre openpyxl
或与结帐工作。
有关使用openpyxl和pandas一起使用的更多信息,请参阅文档。
查理从邮件列表中的答案:
所以,如果要保留公式,则不能仅使用数据模式。
如前所述,OpenPyXl永远不会评估公式,因此,如果您想
知道A3的值您必须将文件传递给诸如excel
之类的应用程序 或OpenOffice - 您可以为这种事情或
运行OpenOffice无头。 使用XLWING进行Excel-确实进行公式评估。然后你可以
以仅数据模式读取此文件以查看计算结果。
另外,您可以尝试使用pycel之类的东西来做
评估您。但是,基本上,如果您想进行计算:做
在Python。
根据他的建议,我的解决方法是按列重做所有计算,就像在Excel文件中完成的那样。IE。对于这样的Excel文件:
col1 col2 col3 col4
row1 1 3 =A1+B1 =1+3
row2 2 4 =A2+B2 =2+4
我将其导入这样的数据帧(将方程式维持为字符串):
wb = load_workbook(filename, data_only=False)
ws = wb[sheet_name]
data = ws.values
cols = next(data)[1:]
data = list(data)
idx = [r[0] for r in data]
data = (islice(r, 1, None) for r in data)
df = DataFrame(data, index=idx, columns=cols)
然后执行以下操作:
parse_excel = lambda x: eval(str(x)[1:]) if isinstance(x, str) else x
for col in df.columns:
try:
df[col] = df[col].map(parse_excel)
except:
pass
df['col3'] = df['col2']+df['col1']
我敢肯定这也许是最笨拙的方法,但现在起作用。