python运用win32com,excel始终无法保存到原路径

写了一段代码,此段代码中运用过三次打开保存excel的自定义函数,just_open(),是为了将excel中写入公式的单元格,保存为公式计算结果的值,前面两次运用都没问题,第三次调用的时候,excel始终无法保存到原路径,能不能给看看是咋回事。

import openpyxl
import pandas as pd
from win32com.client import Dispatch

# 文件路径
path = r"D:\python课件\数据分析\python练习集\应收账款-2023\应收账款-测试\测试-全部 - 副本 (69) - 副本 - 副本 - 副本 - 副本.xlsx"
region_path = r"C:\Users\eric\Desktop\应收账款\区域标准库.xlsx"
output_path = r"D:\python课件\数据分析\python练习集\应收账款-2023\应收账款-测试\22.xlsx"

# 整理excel
excel01 = openpyxl.load_workbook(path)

sheet01 = excel01["Sheet"]

sheet01.unmerge_cells('A1:K1')
sheet01.unmerge_cells('A2:K2')
sheet01.unmerge_cells('A3:K3')

sheet01.unmerge_cells('A4:A5')
sheet01.unmerge_cells('B4:B5')
sheet01.unmerge_cells('C4:C5')
sheet01.unmerge_cells('D4:D5')
sheet01.unmerge_cells('E4:E5')
sheet01.unmerge_cells('F4:G4')
sheet01.unmerge_cells('H4:I4')
sheet01.unmerge_cells('J4:K4')

sheet01.delete_rows(1)
sheet01.delete_rows(1)
sheet01.delete_rows(1)
sheet01.delete_rows(1)

sheet01.cell(1, 1).value = "科目编号"
sheet01.cell(1, 2).value = "科目名称"
sheet01.cell(1, 3).value = "部门名称"
sheet01.cell(1, 4).value = "往来单位名称"
sheet01.cell(1, 5).value = "合同项目名称"

sheet01.insert_cols(idx=4)

sheet01.insert_cols(idx=6)

excel01.save(path)
# 数据排序
sheet01 = pd.read_excel(path, sheet_name='Sheet')

sheet01.sort_values(by=['部门名称', '合同项目名称', '往来单位名称'], inplace=True)

sheet01.to_excel(path, sheet_name='Sheet', index=False)
# 计算应收款---------------------------------------------------------
excel01 = openpyxl.load_workbook(path)

sheet01 = excel01["Sheet"]

row01 = sheet01.max_row

row02 = row01 + 1

column01 = sheet01.max_column

a = 1

for j in range(2, row01):
    q = j + 1
    cell01 = sheet01.cell(j, 7)
    cell02 = sheet01.cell(q, 7)
    if cell01.value == cell02.value:
        sheet01.cell(j, 6).value = a
        sheet01.cell(q, 6).value = a
    else:
        a = a + 1
        sheet01.cell(j, 6).value = a - 1
        sheet01.cell(q, 6).value = a
# 往来单位分组

# 1)判断该组项目有行
# GroupRow = 1
# JumpRow = 1
#
# for r in range(2, row02):
#     cell21 = sheet01.cell(r + JumpRow - 1, 6)
#     GroupRow = 1
#     JumpRow = 1
#     for w in range(r + JumpRow, row02):
#         cell22 = sheet01.cell(w, 6)
#         if cell21.value == cell22.value:
#             GroupRow = GroupRow + 1
#             JumpRow = JumpRow + 1
#         else:
#             pass
#     sheet01.cell(cell21.row, 17).value = GroupRow


# 2)分组

sheet01.cell(2, 4).value = 1

EnterpIndex = 1
d = 0

for e in range(2, row01):
    cell03 = sheet01.cell(e, 6)
    cell04 = sheet01.cell(e + 1, 6)
    if cell03.value == cell04.value:
        if sheet01.cell(e, 5).value == sheet01.cell(e + 1, 5).value:
            sheet01.cell(e + 1, 4).value = sheet01.cell(e, 4).value
        else:
            sheet01.cell(e + 1, 4).value = sheet01.cell(e, 4).value + 1
    else:
        sheet01.cell(e + 1, 4).value = EnterpIndex
        EnterpIndex = 1
        d = 0

# 计算数值
for f in range(2, row02):
    if "应收" in str(sheet01.cell(f, 2).value):
        if sheet01.cell(f, 12).value == "借":
            sheet01.cell(f, 14).value = sheet01.cell(f, 13).value
        else:
            sheet01.cell(f, 14).value = 0
    else:
        if sheet01.cell(f, 12).value == "借":
            sheet01.cell(f, 14).value = sheet01.cell(f, 13).value / 6 * 106
        else:
            sheet01.cell(f, 14).value = sheet01.cell(f, 13).value / 6 * 106 * -1

# 合并企业项目数字
for L in range(2, row02):
    cell_a = "O" + str(L)
    cell_b = "F" + str(L)
    cell_c = "D" + str(L)
    sheet01[cell_a] = "="+str(cell_b)+"&\"_\"&"+str(cell_c)

# sheet01["O2"] = "=F2&D2"
excel01.save(path)


# 关闭文件,打开文件

def just_open(filename):
    xlapp = Dispatch("Excel.Application")

    xlapp.Visible = False

    xlbook = xlapp.Workbooks.Open(filename)

    xlbook.Save()

    xlbook.Close()


just_open(path)

excel01 = openpyxl.load_workbook(path, data_only=True)

sheet01 = excel01["Sheet"]
# 比较循环
h = 0

for W in range(2, row02):
    cell_f = "O" + str(W + h)
    cell_g = "N" + str(W + h)
    cell_h = "P" + str(W + h)
    StandValue = sheet01[cell_f]
    Result = sheet01[cell_g].value
    for G in range(W + h + 1, row02):
        cell_d = "O" + str(G)
        cell_u = "N" + str(G)
        CompValue = sheet01[cell_d]
        CompValue_after = sheet01[cell_u]
        if CompValue.value == StandValue.value:
            Result = Result + float(CompValue_after.value)
            h = h + 1
        else:
            pass
    sheet01[cell_h].value = Result
    h = 0
# 删除多余值
for W in range(2, row02):
    cell_f = "O" + str(W)
    StandValue_2 = sheet01[cell_f]
    for G in range(W + 1, row02):
        cell_d = "O" + str(G)
        cell_u = "P" + str(G)
        CompValue_2 = sheet01[cell_d]
        CompValue_before = sheet01[cell_u]
        if CompValue_2.value == StandValue_2.value:
            CompValue_before.value = 0
        else:
            pass

# 标名列
sheet01["P1"] = "应收账款"
sheet01["T1"] = "区域"

sheet01.insert_cols(idx=3)
for DepStr in range(1, row02):
    sheet01.cell(DepStr, 3).value = "=TRIM(D" + str(DepStr) + ")"

excel01.save(path)

just_open(path)

excel01 = openpyxl.load_workbook(path, data_only=True)

sheet01 = excel01["Sheet"]

sheet01.delete_cols(4)

# 匹配区域-----------------------------------------------------------
for T in range(2, row02):
    sheet01.cell(T, 19).value = "=TRIM(G" + str(T) + ")&E" + str(T)

for X in range(2, row02):
    sheet01.cell(X, 20).value = "=VLOOKUP(S" + str(
        X) + ",区域标准库!$AF$2:$AG$10021,2,FALSE)"

excel01.save(path)
# 导入标准库
df2 = pd.read_excel(region_path, sheet_name='Sheet1')

writer2 = pd.ExcelWriter(path, mode='a', engine='openpyxl')

df2.to_excel(writer2, sheet_name="区域标准库", index=False)

writer2.save()
# 将excel中公式转为数值-----------------------------------------------------------------
def just_open(filename):
    xlapp = Dispatch("Excel.Application")

    xlapp.Visible = False

    xlbook = xlapp.Workbooks.Open(filename)

    xlbook.Save()

    xlbook.Close()


just_open(path)

excel01 = openpyxl.load_workbook(path, data_only=True)

sheet01 = excel01["Sheet"]

excel01.save(path)
# 分类写入------------------------------------------------------------------------------
excel01 = openpyxl.load_workbook(path)

writer = pd.ExcelWriter(output_path)

df = pd.read_excel(path, sheet_name='Sheet')
col_data = df.loc[:, '部门名称']

list_dep = []
liat_region = ['东北', '华北', '华东', '华南', '华中', '西北', '西南', '新疆', '中原']

list_dep.append(col_data[0])

for row_a in range(0, len(col_data) - 1):
    row_b = row_a + 1
    if col_data[row_a] != col_data[row_b]:
        list_dep.append(col_data[row_b])
    else:
        pass

for ListNum in range(0, len(list_dep)):
    if list_dep[ListNum] == "直管项目":
        for RegNum in liat_region:
            filtered_data3 = df[(df['应收账款'] != 0) & (df["部门名称"] == list_dep[ListNum]) & (df['区域'] == RegNum)]
            filtered_data4 = filtered_data3[['部门名称', '往来单位名称', '合同项目名称', '应收账款', '区域']]
            filtered_data4.to_excel(writer, sheet_name=RegNum, index=False)
    else:
        filtered_data = df[(df['应收账款'] != 0) & (df["部门名称"] == list_dep[ListNum])]
        filtered_data2 = filtered_data[['部门名称', '往来单位名称', '合同项目名称', '应收账款']]
        filtered_data2.to_excel(writer, sheet_name=list_dep[ListNum], index=False)

writer.save()
# 保存excel
excel01.save(path)

print("程序结束")


所用到的excel文件大概是这个样子的,对应path

img


对应region_path

img


提示错误

C:\Users\eric\AppData\Local\Programs\Python\Python39\python.exe "D:\pycharm\PyCharm 2022.1\plugins\python\helpers\pydev\pydevd.py" --cmd-line --multiprocess --qt-support=auto --client 127.0.0.1 --port 8644 --file "D:/python课件/数据分析/python练习集/应收账款-2023/应收账款_2023 - 全部 - 副本.py"
已连接到 pydev 调试器(内部版本号 221.5080.212)D:/python课件/数据分析/python练习集/应收账款-2023/应收账款_2023 - 全部 - 副本.py:227: FutureWarning: save is not part of the public API, usage can give unexpected results and will be removed in a future version
  writer2.save()
Traceback (most recent call last):
  File "D:\pycharm\PyCharm 2022.1\plugins\python\helpers\pydev\pydevd.py", line 1491, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "D:\pycharm\PyCharm 2022.1\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "D:/python课件/数据分析/python练习集/应收账款-2023/应收账款_2023 - 全部 - 副本.py", line 241, in <module>
    just_open(path)
  File "D:/python课件/数据分析/python练习集/应收账款-2023/应收账款_2023 - 全部 - 副本.py", line 236, in just_open
    xlbook.Save()
  File "<COMObject Open>", line 2, in Save
pywintypes.com_error: (-2147352567, '发生意外。', (0, 'Microsoft Excel', '所做的更改不能保存到“测试-全部 - 副本 (59) - 副本 - 副本 - 副本 - 副本.xlsx”中,但已保存到名为“53102910”的临时文档中。请关闭现有的文档,然后打开临时文档,用新名字保存。', 'xlmain11.chm', 0, -2146827284), None)
python-BaseException

进程已结束,退出代码1

采用chatgpt:
根据错误提示和代码,出现问题的地方在just_open()函数中,它被多次调用来打开Excel文件,并且在第三次调用时出现了问题。问题是Excel报告所做的更改不能保存到原路径,但已保存到名为“53102910”的临时文档中。这可能是由于Excel自动保存机制的原因。

尝试以下步骤来解决问题:

1、移除多余的just_open()函数调用:你已经在代码的开头和中间部分调用了just_open()函数两次,而在第三次调用之前已经做了相应的操作。因此,可以尝试删除第三次调用以及与其相关的代码。这样做之后,代码将不再试图保存多余的Excel实例。

2、关闭Excel应用程序:在每次打开和处理完Excel文件后,确保关闭Excel应用程序,以便释放资源。添加以下代码在相应的位置:

xlapp.Quit()

修改后的代码如下:

# ... 其他代码 ...

# 第一个 just_open() 调用保持不变
just_open(path)

excel01 = openpyxl.load_workbook(path, data_only=True)
sheet01 = excel01["Sheet"]
# ... 其他代码 ...
excel01.save(path)

# 第二个 just_open() 调用保持不变
just_open(path)

excel01 = openpyxl.load_workbook(path, data_only=True)
sheet01 = excel01["Sheet"]
# ... 其他代码 ...
excel01.save(path)

# 删除第三个 just_open() 调用以及相关代码

# 关闭 Excel 应用程序
xlapp.Quit()

print("程序结束")

通过这样的修改,Excel应用程序应该会在代码结束时被正常关闭,而且不再产生无法保存到原路径的问题。同时请注意,由于关闭Excel应用程序可能需要一些时间,请确保在代码中添加适当的延迟或等待,以确保Excel应用程序在继续执行之前完全关闭。可以使用time.sleep()函数来添加延迟。

没有Excel文件,大致看一下 先改一下 文件名“测试-全部 - 副本 (69) - 副本 - 副本 - 副本 - 副本.xlsx”,在运行一下看报什么错误。

这个错误看起来像是由于尝试保存一个文件时发生的错误。具体来说,它似乎是无法将更改保存到文件“测试-全部 - 副本 (59) - 副本 - 副本 - 副本 - 副本.xlsx”中。

这个错误可能是由于以下原因导致的:
1.文件正在被其他程序使用,无法被覆盖或修改。请确保没有其他程序正在使用该文件。
2.文件权限问题,您可能没有足够的权限来保存到该位置。请检查文件所在目录的权限,确保您有写入权限。
3.您的代码或操作可能已经损坏了文件或导致文件变得不可写。请尝试在不保存更改的情况下打开文件,然后尝试保存。
4.另外,关于代码中的警告,它只是警告您有关使用save的方法的一些信息,这可能不会影响代码的执行,但您可能需要查看它以确保您的代码行为符合预期。这可以通过更新您的库或查看有关该警告的文档来完成。

希望这些信息能帮助您解决问题。

从设计上,不建议直接在原文件上进行修改操作并进行覆盖。
建议:每次操作结束后,保存结果到临时文件,并对临时文件建立副本,在副本的基础上进行下一轮操作.

考虑是否由于内存未及时回收导致
在writer2.save()后添加
del writer2
import gc
gc.collect()

python写入excel保存_Python使用win32 COM实现Excel的写入与保存功能示例
可以参考下

import win32com.client as win32

# 1、创建 excel 程序
app = win32.Dispatch("excel.application")  

# 2、打开要转换的文件
wb = app.Workbooks.Open(r"C:\Users\admin\Documents\测试.xls")  

# 3、另存为
wb.SaveAs("test.xlsx", FileFormat=51)

# 4、关闭工作簿
wb.Close()

# 5、退出 Excel程序
app.Application.Quit()


在Python中使用Win32com调用Excel并进行Excel操作是一种常见的应用场景。在进行Excel操作时,有时我们需要将Excel文件进行保存。然而,有时会遇到Excel文件保存不成功的问题,即无法保存到原路径的情况出现。本文将从以下几个方面进行阐述:可能导致Excel文件无法保存到原路径的原因、解决方法以及如何避免Excel文件保存失败。

  1. 可能导致Excel文件无法保存到原路径的原因

1.1 文件被占用
当文件正在被其他程序占用时,我们不能对其进行修改或保存操作。当我们使用Python中的Win32com对Excel进行操作时,如果之前打开的文件正在被其他程序占用,我们无法将Excel文件保存到原路径上。

1.2 文件名包含非法字符
当我们在Python中调用Excel进行文件保存时,如果文件名中包含了非法字符,比如 \ / : * ? " < > | 等,就会导致Excel文件保存不成功。因此,在命名Excel文件名字时要注意,不要包含这些非法字符。

1.3 文件路径不正确
当我们使用Python Win32com对Excel进行文件保存时,如果文件路径不正确,就会出现Excel文件保存不成功的情况。因此,在使用Python Win32com进行Excel文件操作时,要确认文件路径是否正确,确保将Excel文件保存到正确的路径上。

  1. 解决方法

2.1 文件被占用
如果文件被占用,我们可以尝试关闭所有可能占用该文件的程序,然后再对Excel文件进行操作。如果无法确定占用该文件的程序,可以尝试重启计算机,释放所有内存资源。

2.2 文件名包含非法字符
为了避免文件名中包含非法字符,我们可以使用re模块对文件名进行规范化处理。使用Python中re.sub()函数,将文件名中的非法字符替换为空格。
如下代码示例:

import re

filename = "my/file|name.txt"
newfilename = re.sub('[\/:*?"<>|]', ' ', filename)

运行后,newfilename即为“my file name.txt”。

2.3 文件路径不正确
我们需要确保文件路径正确,可以使用os模块进行路径拼接。在Python中,我们可以使用os.path.join()函数进行路径拼接,从而得到正确的路径。
如下代码示例:

import os

path = "C:\\Users\\Documents"
filename = "test.xlsx"

fullpath = os.path.join(path, filename)

运行后,fullpath即为“C:\Users\Documents\test.xlsx”。

  1. 如何避免Excel文件保存失败

为了避免Excel文件保存失败,我们可以采取以下措施:

3.1 在使用Excel进行操作前,先确认文件是否被占用。
当我们使用Python Win32com对Excel进行文件操作时,先调用Python中的os模块,判断Excel文件是否被其他程序占用。

3.2 合法的文件名
在命名Excel文件名字时,不要包含非法字符,这样可以避免Excel文件保存失败。

3.3 确认文件路径
在使用Python Win32com进行Excel文件操作时,要确认文件路径是否正确,确保将Excel文件保存到正确的路径上。

  1. 总结

本文从可能导致Excel文件无法保存到原路径的原因、解决方法以及如何避免Excel文件保存失败三个方面进行了阐述,并给出了示例代码。在使用Python Win32com进行Excel文件操作时,我们需要注意以上内容,避免Excel文件保存失败。

Win32com是Python的一种模块,它可以帮助Python实现与Windows API交互,并且可以通过Python代码控制Windows下的各种应用程序,比如Excel、Word等。这种方法在数据处理、自动化工具等方面非常有用。

在使用win32com模块时,我们可以通过Python代码向Excel表格中写入数据,并将修改后的表格保存到原路径。但在实际操作中,有时候我们会遇到这样的问题:Excel无法保存到原路径,即使我们使用的是绝对路径,Excel依然无法保存。这时,我们需要进行进一步的调试和排查。

首先,我们需要确认一下Excel文件是否被锁定,如果该文件正在被其他进程打开或者正在执行某些操作,那么Excel就无法保存到原路径。我们可以使用系统工具“资源监视器”来查看当前Excel文件是否被其他进程占用。如果Excel文件被锁定,我们需要关闭所有占用该文件的进程或程序,然后再尝试保存Excel文件。

其次,我们还需要检查一下Python代码中是否存在语法错误或逻辑错误。如果代码中存在错误,那么就有可能导致Excel文件无法保存到原路径。我们可以使用Python编程工具来检查代码的语法和逻辑是否正确,并进行必要的更正。如果代码中无法找到错误,我们可以在调试代码时添加一些输出语句,以便更好地了解程序执行过程中的情况。

最后,我们还需要检查一下Excel文件的属性,包括文件的权限、读写属性等等。如果Excel文件的权限不足或者只有只读权限,那么Python代码就无法将修改后的Excel文件保存到原路径。我们可以通过右键点击Excel文件,选择“属性”来进行查看和修改Excel文件的属性。

总结起来,win32com可以帮助Python实现与Windows API交互,并且可以通过Python代码控制Windows下的各种应用程序,包括Excel。在使用win32com模块时,我们需要确认Excel文件是否被锁定,检查Python代码中是否存在错误,以及检查Excel文件的属性等等。只有在排查并解决了这些问题后,我们才能顺利地将修改后的Excel文件保存到原路径。

不知道你的问题现在解决了没有,我仔细读了一下你的代码,感觉有些地方写的有点啰嗦,而且功能也没有封装。。。排查起来应该挺麻烦的。
另外我有几个小问题不太明白:
1.just_open()方法是起什么作用的? 在代码中还出现了两个一模一样的方法,这在调用的时候可能会出问题。

def just_open(filename):
    xlapp = Dispatch("Excel.Application")
 
    xlapp.Visible = False
 
    xlbook = xlapp.Workbooks.Open(filename)
 
    xlbook.Save()
 
    xlbook.Close()

2.就是简单的修改excel里面的数据,然后最终保存的话,我感觉你用openpyxl的save()应该就够了,但是我看你一会儿用的挺乱的,可能也会导致出问题。
3.选择要处理的excel数据区域的时候,你可以用ws.iter_rows()来获取,这样代码量会少很多,也好控制。

有问题可以随时联系,我在这方面还算经验比较丰富,另外,可以看一下我这个博文:https://blog.csdn.net/qq_41308872/article/details/131458711就是专门讲python操作excel的

这个异常表明在Excel中保存文件时发生了错误。应该是之前的文件已经打开了,属于文件占用的状态,所以保存回之前的文件时无法保存。请检查下之前的文件是否在其他地方已经打开过了。

先存到一个临时路径,然后在复制过去覆盖

参考newbing

  1. 检查路径和文件名:确保您提供的路径和文件名是正确的、存在的,并且具有正确的文件扩展名(如 .xls 或 .xlsx)。

  2. 权限问题:确认您的 Python 脚本具有足够的权限来在指定路径中创建和保存文件。有些路径或目录可能需要管理员权限才能写入。

  3. 文件是否被其他程序占用:确认 Excel 文件当前是否被其他程序打开,并且处于写保护模式。请先关闭其他程序中打开的该文件,然后尝试重新保存。

  4. 错误处理:在保存 Excel 文件的过程中,捕获和处理可能出现的异常或错误。这可以通过添加适当的错误处理代码来实现,以便您能够查看在保存过程中是否出现了任何错误信息。

如果尝试了上述解决方案后仍然存在问题,请提供您的代码片段,这将有助于更详细地分析并提供更具体的指导。

试试openpyxl库,挺好用的