【问题标题】:How to write to an existing excel file with openpyxl, while preserving pivot tables如何使用 openpyxl 写入现有的 excel 文件,同时保留数据透视表
【发布时间】:2020-05-29 00:27:55
【问题描述】:

我有这个带有多个工作表的 excel 文件。一张表包含两个数据透视表,基于数据透视的普通表,以及基于数据透视的一些图表。

我正在使用下面的代码更新没有枢轴的工作表。这些工作表的内容生成为数据框,并直接生成为数据框。

方法一

book = xl.load_workbook(fn)
writer = pd.ExcelWriter(fn,engine='openpyxl')
writer.book = book
writer.sheets = dict((ws.title, ws) for ws in book.worksheets)
DF.to_excel(writer, 'ABC', header=None, startrow=book.active.max_row)
writer.save()

但是,在写入文件时,数据透视表会转换为纯文本。我发现保留数据透视表的解决方案是使用以下方法读取和写入工作簿。

方法二

workbook = load_workbook(filename=updating_file)
sheet = workbook["Pivot"]
pivot = sheet._pivots[0]
# any will do as they share the same cache
pivot.cache.refreshOnLoad = True
workbook.save(filename=updating_file)

这会在数据透视表中添加一个额外的行作为“值”,这会破坏基于数据透视表的值。

根据here,使用pd.ExcelWriter 不会保留数据透视表。我发现使用数据框更新现有 excel 文件的唯一示例需要 pandas ExcelWriter。

我们将不胜感激,因为我无法找到满足这两个要求的方法。

目前我能看到的唯一选择是使用 Pandas 编写数据部分。然后,删除现有的数据透视表并从原始文件复制一张表。但是,我必须再次找到一种基于枢轴清除表格的方法,并使用第二种方法用 openpyxl 重写。 (我们无法在工作簿之间复制工作表)

【问题讨论】:

    标签: excel pandas dataframe pivot-table openpyxl


    【解决方案1】:

    坚持您的方法1:如果您将df 转换为pandas 中的数据透视表,然后然后导出到excel,它将起作用。

    一个例子:

    import pandas as pd 
    import numpy as np 
    
    # create dataframe 
    df = pd.DataFrame({'A': ['John', 'Boby', 'Mina', 'Peter', 'Nicky'], 
          'B': ['Masters', 'Graduate', 'Graduate', 'Masters', 'Graduate'], 
          'C': [27, 23, 21, 23, 24]}) 
    
    table = pd.pivot_table(df, values ='A', index =['B', 'C'], 
                             columns =['B'], aggfunc = np.sum)
    
    table.to_excel("filename.xlsx")
    

    输出

    【讨论】:

      【解决方案2】:

      我找到了一种将数据框迭代为行的方法。如果它在现有表的末尾添加行,这会容易得多。因为,我必须在中间插入行,所以我按照下面的方法插入空白行并写入单元格值。

      current_sheet.insert_rows(idx=11, amount=len(backend_report_df))
      sheet_row_idx = 11
      is_valid_row = False
      for row in dataframe_to_rows(backend_report_df, index=True, header=True):
          is_valid_row = False
          for col_idx in range (0, len(row)):
              if col_idx == 0 and row[col_idx] is None:
                  logger.info("Header row/blank row")
                  break
              else:
                  is_valid_row = True
                  if col_idx != 0:
                      current_sheet.cell(row=sheet_row_idx, column=col_idx).value = row[col_idx]
          if is_valid_row:
              sheet_row_idx = sheet_row_idx + 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-18
        • 1970-01-01
        • 2020-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-09
        • 2019-10-26
        相关资源
        最近更新 更多