Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用熊猫修改Excel文件,对布局的更改最小_Python_Excel_Pandas_Openpyxl_Xlsxwriter - Fatal编程技术网

Python 使用熊猫修改Excel文件,对布局的更改最小

Python 使用熊猫修改Excel文件,对布局的更改最小,python,excel,pandas,openpyxl,xlsxwriter,Python,Excel,Pandas,Openpyxl,Xlsxwriter,我已经读过了,但这里我的问题是针对后面提到的布局的 如何使用Pandas打开Excel文件、进行一些修改并将其保存回: # [step 0] boiler plate stuff df = pd.DataFrame( index=pd.date_range("2020-01-01 11:11:11", periods=100, freq="min"), columns=list('abc')) df['a'] = np.random.ra

我已经读过了,但这里我的问题是针对后面提到的布局的

如何使用Pandas打开Excel文件、进行一些修改并将其保存回:

# [step 0] boiler plate stuff
df = pd.DataFrame(
    index=pd.date_range("2020-01-01 11:11:11", periods=100, freq="min"), 
    columns=list('abc'))
df['a'] = np.random.randn(100, 1) 
df['b'] = df['a'] * 2 + 10

# [step 1] google xlwings, and pip/conda install xlwings

# [step 2] open a new excel sheet, no need to save 
#        (basically this code will indiscriminally wipe whatever sheet that is active on your desktop)

# [step 3] magic, ...and things you can do
import xlwings as xw

wb = xw.books.active
ws = wb.sheets.active
ws.range('A1').current_region.options(index=1).value = df 
# I believe this preserves existing formatting, HOWEVER, it will destory filtering

if 1:
# show casing some formatting you can do
    active_window = wb.app.api.ActiveWindow
    active_window.FreezePanes = False
    active_window.SplitColumn = 2 # const_splitcolumn
    active_window.SplitRow = 1
    active_window.FreezePanes = True


    ws.cells.api.Font.Name = 'consolas'
    ws.api.Rows(1).Orientation = 60
    ws.api.Columns(1).Font.Bold = True
    ws.api.Columns(1).Font.ColorIndex = 26
    ws.api.Rows(1).Font.Bold = True
    ws.api.Rows(1).Borders.Weight = 4
    ws.autofit('c') # 'c' means columns, autofitting columns
    ws.range(1,1).api.AutoFilter(1)
  • (1) 在不删除的情况下,第一行上有一个
    过滤器

  • (2) 不修改Excel中显示的列的“显示列宽”

  • (3) 不删除某些单元格上可能存在的公式

以下是我尝试过的,这是一个简短的例子(实际上我对熊猫做了更多的处理):


使用此代码,删除第一行的
过滤器
,并将显示的列宽设置为默认值,这不是很方便(因为我们必须手动为所有列设置正确的宽度)。

我认为这不是panda字段,您必须使用它来处理所有格式化、阻塞的行,名称范围等等。主要区别在于不能像pandas那样使用矢量计算,因此需要引入一些循环。

我建议使用
xlwings
,因为它与excel的COM接口(如内置vba)相连接,所以功能更强大。我从未测试过“过滤或公式保存”,官方文件可能会提供方法

对于我自己的使用,我只是将所有东西都构建到python、过滤、公式中,所以我甚至不去碰excel工作表

演示:

# [step 0] boiler plate stuff
df = pd.DataFrame(
    index=pd.date_range("2020-01-01 11:11:11", periods=100, freq="min"), 
    columns=list('abc'))
df['a'] = np.random.randn(100, 1) 
df['b'] = df['a'] * 2 + 10

# [step 1] google xlwings, and pip/conda install xlwings

# [step 2] open a new excel sheet, no need to save 
#        (basically this code will indiscriminally wipe whatever sheet that is active on your desktop)

# [step 3] magic, ...and things you can do
import xlwings as xw

wb = xw.books.active
ws = wb.sheets.active
ws.range('A1').current_region.options(index=1).value = df 
# I believe this preserves existing formatting, HOWEVER, it will destory filtering

if 1:
# show casing some formatting you can do
    active_window = wb.app.api.ActiveWindow
    active_window.FreezePanes = False
    active_window.SplitColumn = 2 # const_splitcolumn
    active_window.SplitRow = 1
    active_window.FreezePanes = True


    ws.cells.api.Font.Name = 'consolas'
    ws.api.Rows(1).Orientation = 60
    ws.api.Columns(1).Font.Bold = True
    ws.api.Columns(1).Font.ColorIndex = 26
    ws.api.Rows(1).Font.Bold = True
    ws.api.Rows(1).Borders.Weight = 4
    ws.autofit('c') # 'c' means columns, autofitting columns
    ws.range(1,1).api.AutoFilter(1)
这是(1)、(2)的解决方案,而不是我原来问题的(3)。(如果你对(3)有想法,欢迎发表评论和/或另一个答案)

在此解决方案中,我们将打开输入Excel文件两次:

  • 一旦使用
    openpyxl
    :这有助于保持原始布局(当作为
    pandas
    dataframe读取时,它似乎完全被丢弃!)
  • 曾经作为
    pandas
    dataframe
    df
    pandas
    中获益,这是一个操作/修改数据本身的伟大API。注意:
    pandas
    的数据修改比
    openpyxl
    更方便,因为我们有矢量化、过滤
    df[df['foo']=='bar']
    、通过名称直接访问列
    df['foo']
下面的代码修改输入文件并保持布局:第一行“过滤器”未删除,每个列的列宽未修改

import pandas as pd
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl import load_workbook
wb = load_workbook('test.xlsx')  # load as openpyxl workbook; useful to keep the original layout
                                 # which is discarded in the following dataframe
df = pd.read_excel('test.xlsx')  # load as dataframe (modifications will be easier with pandas API!)
ws = wb.active
df.iloc[1, 1] = 'hello world'    # modify a few things
rows = dataframe_to_rows(df, index=False)
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)
wb.save('test2.xlsx')

如果您使用的机器上安装了Excel,那么我强烈建议您使用灵活的API。这回答了你所有的问题

假设我的程序所在的目录中有一个名为
demo.xlxs
的Excel文件

app.py

这将创建一个初始化xl工作簿实例并打开Excel编辑器,以允许您调用Python命令


假设我们有以下数据框,我们想用它来替换ID和Name列:

    new_name
A   John_new
B  Adams_new
C     Mo_new
D  Safia_new

wb.sheets['Sheet1']['A1:B1'].value = df


最后,您可以保存并关闭

wb.save()
wb.close()

这就是我注意到的:使用pandas,我们完全失去了输入XLSX的布局,但是我们有一个很好的API来修改数据。使用openpyxl,我们保留了布局,但是如果没有矢量化,数据修改API就不那么方便了。如果有可能把它们混合在一起,使两者都达到最佳效果,那就太好了。。。使用openpyxl,它可以解决(1)、(2),但不能解决(3)。您是否知道如何修改它,使其同时具有我最初问题中的标准(3)?您能否同时提及您当前的操作系统/环境?@Manakin我正在使用Windows+Python 3.7此解决方案有助于解决问题(3)@Robin您是否可以发布一个答案,显示使用您提到的解决方案(使用pandas+openpyxl)的代码示例?只有openpyxl,这很容易;但是这里的困难是使用pandas+openpyxl。
wb.save()
wb.close()