V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
JCZ2MkKb5S8ZX9pq
V2EX  ›  Python

如果用 Python 打开 Excel 中正在编辑的文件

  •  
  •   JCZ2MkKb5S8ZX9pq · 2020-03-16 16:41:02 +08:00 · 3745 次点击
    这是一个创建于 1510 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    • 我拿 Excel 作为部分需要手动编辑的数据的 GUI 来用。
    • 系统是 windows。
    • Excel 打开文件 a.excel。
    • 因为有些动作会交替进行,所以在 excel 未关闭该文件的情况下(已保存改动),会进行 python 操作。
      后续所有操作都是在 excel 未关闭该文件的情况下进行。
    • 比如这时候再在 python 里打开 excel,比如用 pandas。

    问题点

    • python 绝大部分情况下会报错。我理解就是该 excel 文件已经被占用了。关闭该 excel 文件后恢复正常。
    PermissionError: [Errno 13] Permission denied: {filename}
    

    尝试解决

    1. 最糟的方法,每次 excel 存盘关文件。python 读完,再打开 excel。

    2. 直接在资源管理器复制粘贴该文件,生成副本。python 访问副本,可以。但是这个方法很麻烦。

    3. 尝试用 python 做创建副本的操作,失败,同样提示文件被占用。

    4. 远程访问该文件,未提示权限问题,但需要远程电脑开个 api 做创建副本的操作,也有点繁琐。


    请问

    • 这个可能涉及 windows 的基础知识,刚好是我的盲区。想知道为什么资源管理器可以复制,但 python 复制就会提示被占用?

    • 有没有办法更方便地在 excel 不关闭文件的情况下,让 python 读取到该文件的内容。比如 pandas 有没有只读参数啥的?

    • 同理,如果是只读操作,那 python 在复制该文件时,也会被提示占用?复制文件我用的 shutil.copy,是不是它同时还会复制某些属性,导致了问题?

    第 1 条附言  ·  2020-03-16 19:31:59 +08:00

    发现问题可能和 Onedrive 有关

    测试1

    • 新建 test.xlsx,随意录入数据,并保存到 D:\。
    • 关闭,重新用excel打开该文件。
    file = 'D:\\test.xlsx'
    out = 'D:\\test_copy.xlsx'
    with open(file, 'rb') as f:
        data = f.read()
    with open(out, 'wb') as f:
        f.write(data)
    os.system(f'copy "{file}" "{out}"')
    
    • 两种操作都顺利通过。
    • PS:其中copy的路径一定要反斜杠,正斜杠会找不到文件。(感觉有时候正斜杠也管用?)

    测试2

    • 将上述文件放入我的 Onedrive 同步目录,D:\Onedrive。
    • 修改路径后同样运行上述命令,出现 PermissionError。

    猜测原因

    • 在 D:/ 目录用 Excel 打开该文件时,会创建一个临时副本,~$test.xlsx。
    • 而在 Onedrive 目录下不会。
    • 我猜测,可能创建副本时,Excel没有对原文件锁定操作,所以Python可以正常读取。而Onedrive下,不知为何没有产生这个副本,所以导致了Python的访问错误。具体原理还是不大明白。
    第 2 条附言  ·  2020-03-16 23:39:45 +08:00

    解决了!!!

    • 搜到一篇文章(不让我贴链接,标题如下。)
      ~$ versions of files appearing in onedrive folder (viewed - Microsoft Community

    • 受到启发之后,直接修改了Onedrive的设置。(这里不要勾选。我之前勾了。)
      8tE6wn.png

    • 然后excel编辑文件时,所谓的 ~$ Owner File 出现了。于是各种读写也都通过了。

    • 感谢各位给出建议,和帮助我一步步找到答案的朋友们。

    16 条回复    2020-03-16 19:34:18 +08:00
    aec4d
        1
    aec4d  
       2020-03-16 16:54:35 +08:00
    你可以尝试另外一种方案
    https://docs.xlwings.org/en/stable/udfs.html
    将在 VBA 里面使用 python

    不过我还是觉得和 excel 搭配最好的是 C#
    ysc3839
        2
    ysc3839  
       2020-03-16 16:57:51 +08:00
    1. 你复制的代码是怎样的?
    2. 也许用文件映射是可以读到的?试试用记事本打开这个文件,看看能不能读出里面的内容?
    ysc3839
        3
    ysc3839  
       2020-03-16 17:03:20 +08:00
    刚刚在本地测试了一下,是可以正常读取的。
    测试代码:
    with open("Book1.xls", 'rb') as f: print(f.read(2))
    superrichman
        4
    superrichman  
       2020-03-16 17:05:32 +08:00
    如果只是表格的话,可以改成 markdown 格式的表格,python 读写都方便,要编辑随便找个 markdown 编辑器就能改。

    数据多的话,存到数据库里,找个数据库 gui 工具操作。
    augustheart
        5
    augustheart  
       2020-03-16 17:05:59 +08:00
    FILE_SHARE_READ ,FILE_SHARE_WRITE
    正常情况是不会允许 FILE_SHARE_WRITE 的,这和线程安全同理。
    minami
        6
    minami  
       2020-03-16 17:22:06 +08:00
    用 copyfile,或者调 console 命令行
    JCZ2MkKb5S8ZX9pq
        7
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-16 17:45:47 +08:00 via iPhone
    @ysc3839 你倒提醒我了 直接 rb 然后再写个新文件也许可以
    krixaar
        8
    krixaar  
       2020-03-16 17:51:14 +08:00
    是否可以考虑用 Access,或者 Excel 连接 Access,然后 Python 从 Access 获得数据?
    JCZ2MkKb5S8ZX9pq
        9
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-16 18:16:52 +08:00
    @ysc3839
    请问你的 excel 文件是打开状态嘛?
    为啥我用 rb 也提示权限问题……

    我是在 sublime 里直接 build 的,不知道有没有影响。
    JCZ2MkKb5S8ZX9pq
        10
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-16 18:59:06 +08:00
    @minami
    试了 os.system(copy ...) 失败

    另一个程序正在使用此文件,进程无法访问。
    已复制 0 个文件。
    ysc3839
        11
    ysc3839  
       2020-03-16 19:08:00 +08:00
    @JCZ2MkKb5S8ZX9pq 是打开状态。
    ysc3839
        12
    ysc3839  
       2020-03-16 19:09:17 +08:00
    @JCZ2MkKb5S8ZX9pq Excel 版本是 2002 (Build 12527.20278)
    binsys
        13
    binsys  
       2020-03-16 19:14:52 +08:00
    告诉你方案吧,不要对文件动脑筋了,那个没用。Office 系列都有自动化 API,直接用 COM 相关 API 可以操纵 Office 套装内的软件包括 Excel。Python 支持 Windows 的 COM 操作,直接调用就完了。
    https://adndevblog.typepad.com/autocad/2013/12/accessing-com-applications-from-the-running-object-table.html

    https://stackoverflow.com/questions/22842023/accessing-excel-application-objects-of-other-excel-instances-in-running-object-t

    COM 可以跨语言,找个 Python 的 COM 库吧
    LokiSharp
        14
    LokiSharp  
       2020-03-16 19:22:48 +08:00
    用 C# 绑定个 API 处理一下,或者直接 COM 操作
    JCZ2MkKb5S8ZX9pq
        15
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-16 19:23:57 +08:00
    @ysc3839
    我测了下,发现可能和 Onedrive 有关。

    我在 D 盘根目录测试,rb 或者调系统 copy 都可以。
    但是如果放到 Onedrive 下的任一目录,就会发生 permission error。
    JCZ2MkKb5S8ZX9pq
        16
    JCZ2MkKb5S8ZX9pq  
    OP
       2020-03-16 19:34:18 +08:00
    @binsys
    @LokiSharp
    不好意思,不太懂 COM 操作怎么搞。
    但是测试下来好想跟 Onedrive 有关,具体可以麻烦看一下我的 Append。请问了解其中原理嘛?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2379 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:58 · PVG 17:58 · LAX 02:58 · JFK 05:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.