2017-06-14 123 views
-1

我是Python新手,正在开发一个项目,我可以使用一些帮助。所以我试图修改一个现有的Excel工作簿以比较库存数据。幸运的是,有一个在线程序可以检索我需要的所有数据,并且我已经成功地将数据提取出来并将数据写入新的excel文件。但是,目标是提取数据并将其放入现有的Excel文件中。此外,我需要覆盖现有文件中的单元格值。我相信xlwings能够做到这一点,我认为我的代码在正确的轨道上,但我遇到了一个意想不到的错误。我得到的错误是:使用Python将数据覆盖到现有工作簿

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 
+0

可能的复制[使用Python编写和修改现有工作簿](https://stackoverflow.com/questions/44489950/writing-and-modifying-an-existing-workbo OK-using-python) –

+0

pandas.DataFrame.append如何提供帮助?我有我想要的数据框。我无法用我拥有的数据框覆盖我的Excel文件中的现有数据。我仍然感到困惑,我如何获取数据到现有的工作簿 – vdub32

+0

我不认为我能够使用这些功能更新现有的工作簿。我在网上搜索过,并不认为有可能通过这些功能来完成。很难找到能够修改现有工作场所并替换其中的数据的功能。感谢您的帮助和建议。 – vdub32

回答

0

Comments: You have a Dict of 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价值观。因此,您必须将工作表范围调整为20行。写专栏2017年的工作表,例如:

wb['M6:M25'] = df_2['2017'].values 

Note: I have updated the code below to accept numpy.ndarray also.


Question: ... the goal is to pull the data and put it into an existing excel file

更新一个工作簿工作表区域与列表值。
使用:OpenPyXLA Python library to read/write Excel 2010 xlsx/xlsm files

Note: Observe how the List Values have to be arranged!
param values: List: *[row 1(col1, ... ,coln), ..., row n(col1, ... ,coln)]`

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__() 

Usage

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

+0

当我使用此代码时,它可以将数据放入现有的工作簿文件中。但是,它会覆盖整个工作簿。我很抱歉,我不是很清楚,但我只想覆盖现有工作簿中的某些单元格,而不是从工作簿中删除所有数据。你知道这是可能的吗?用我想要的熊猫数据框替换特定的单元格?例如,我想用名为data的数据表替换单元格M6到M30,并创建数据框。 – vdub32

+0

是的,这正是我想要做的,不用删除或删除电子表格中的任何现有数据。非常感谢! – vdub32

+0

感谢伟大的代码!我仍然遇到了一个我不明白的意外错误。出于某种原因,它给了我一个价值错误。错误状态: ValueError:值类型错误:值必须是“list”:values = 。 这对我来说没有任何意义,因为我们将数据帧转换为列表,但我可能看错了。谢谢你的帮助。如果你能给我更多的建议,我会非常感激!再次感谢 – vdub32

相关问题