我是新来的Python和我可以使用一些帮助的一个项目工作。 所以我想以比较股票数据修改现有的Excel工作簿。 幸运的是,有是获取我需要的所有数据的节目在线和我有成功的能提取数据,并将数据写入到一个新的Excel文件。 然而,我们的目标是提取数据,并把它变成一个现有的Excel文件。 此外,我需要覆盖现有文件中的单元格值。 我相信xlwings是能够做到这一点,我想我的代码是在正确的轨道上,但是我遇到了一个意外的错误。 我得到的错误是:
TypeError: Objects of type 'Period' can not be converted to a COM VARIANT (but obtaining the buffer() of this object could)
我想知道是否有人知道为什么这个错误想出了? 此外,没有人知道如何解决它? 它是可以解决的? 是我的代码错了吗? 任何帮助或指导表示赞赏。 谢谢。
import good_morning as gm
import pandas as pd
import xlwings as xw
#import income statement, balance sheet, and cash flow of AAPL
fd = gm.FinancialsDownloader()
fd_frames = fd.download('AAPL')
#Creates a DataFrame for only the balance sheet
df1 = pd.DataFrame(list(fd_frames.values())[0])
#connects to workbook I want to modify
wb = xw.Book(r'C:\Users\vince\Project\Spreadsheet.xlsm')
#sheet I would like to modify
sht = wb.sheets[1]
#modifies & overwrites values in my spreadsheet(this is where I get the type_error)
sht.range('M6').value = df1
数据类型 :
type(fd_frames)
>>> <class 'dict'>
fd_frames.values())[0].info()
>>> <class 'pandas.core.frame.DataFrame'>
RangeIndex: 22 entries, 0 to 21
Data columns (total 8 columns):
parent_index 22 non-null int64
title 22 non-null object
2012 19 non-null float64
2013 20 non-null float64
2014 20 non-null float64
2015 20 non-null float64
2016 20 non-null float64
2017 20 non-null float64
dtypes: float64(6), int64(1), object(1)
memory usage: 1.5+ KB
评论 :你的快译通 pandas.DataFrame
。
使用从一个字典选择list(fd_frames.values())[0]
并导致不可预测的结果。 显示词典的按键,然后选择一个你感兴趣的关闭使用这些按键,例如:
print(fd_frames.keys())
>>> dict_keys(['key_1', 'key_2', 'key_n']
df_2 = fd_frames['key_2']
除了这一点,无论是在你的尺寸的pandas.DataFrame
确实匹配M6:M30
= 25,只有8与20个值 的列 。 Therfore你要调整你的工作表区域至20行 。 写专栏2017年的工作表,例如:
wb['M6:M25'] = df_2['2017'].values
注 :我已经更新下面的代码接受numpy.ndarray
也。
问 :......我们的目标是提取数据,并把它变成一个现有的Excel文件
更新工作簿工作表区域与列表值。
使用:OpenPyXL: 一个Python库进行读/写的Excel 2010 XLSX / XLSM文件
注 :观察列表值怎么也得安排!
PARAM值:表:* [第1行(COL1,...,科隆),...,第n行(COL1,...,科隆)]`
from openpyxl import Workbook, load_workbook
class UpdateWorkbook(object):
def __init__(self, fname, worksheet=0):
self.fname = fname
self.wb = load_workbook(fname)
self.ws = self.wb.worksheets[worksheet]
def save(self):
self.wb.save(self.fname)
def __setitem__(self, _range, values):
"""
Assign Values to a Worksheet Range
:param _range: String e.g ['M6:M30']
:param values: List: [row 1(col1, ... ,coln), ..., row n(col1, ... ,coln)]
:return: None
"""
def _gen_value():
for value in values:
yield value
if not isinstance(values, (list, numpy.ndarray)):
raise ValueError('Values Type Error: Values have to be "list": values={}'.
format(type(values)))
if isinstance(values, numpy.ndarray) and values.ndim > 1:
raise ValueError('Values Type Error: Values of Type numpy.ndarray must have ndim=1; values.ndim={}'.
format(values.ndim))
from openpyxl.utils import range_boundaries
min_col, min_row, max_col, max_row = range_boundaries(_range)
cols = ((max_col - min_col)+1)
rows = ((max_row - min_row)+1)
if cols * rows != len(values):
raise ValueError('Number of List Values:{} does not match Range({}):{}'.
format(len(values), _range, cols * rows))
value = _gen_value()
for row_cells in self.ws.iter_rows(min_col=min_col, min_row=min_row,
max_col=max_col, max_row=max_row):
for cell in row_cells:
cell.value = value.__next__()
用法
wb = UpdateWorkbook(r'C:\Users\vince\Project\Spreadsheet.xlsx', worksheet=1) df_2 = fd_frames['key_2'] wb['M6:M25'] = df_2['2017'].values wb.save()
经测试使用Python 3.4.2 - openpyxl:2.4.1 - LibreOffice的:4.3.3.2
以下是我对其他协议栈探险做一个类似的过程:
import pandas as pd
from openpyxl import load_workbook
from openpyxl.utils.dataframe import dataframe_to_rows
... create your pandas dataframe df...
# Writing from pandas back to an existing EXCEL workbook
# Load workbook
wb = load_workbook(filename=target, read_only=False, keep_vba=True)
ws = wb['Sheet1']
# Overwrite Existing data in sheet with a dataframe.
rows = dataframe_to_rows(df, index=False, header=True)
for r_idx, row in enumerate(rows, 1):
for c_idx, value in enumerate(row, 1):
ws.cell(row=r_idx, column=c_idx, value=value)
# Save file
wb.save('outfile.xlsm')