【问题标题】:python library or code to read already open Excel filepython库或代码读取已经打开的Excel文件
【发布时间】:2015-04-06 01:50:31
【问题描述】:

假设我已经打开了一个 Excel 2013 文件(比如 XYZ.xlsx)——该文件通过 DDE 链接获取一些数据。假设我想从工作表(比如 Sheet1)中读取某些单元格(比如 A1:B3)。如何在 Python 3 中做到这一点(我正在使用 Python 3.4.2.4 / Winpython 安装)?

我找到了openpyxl 包,但我不明白如何让它读取活动的打开工作簿?

【问题讨论】:

标签: python excel python-3.x


【解决方案1】:

我不能 100% 确定此解决方案是否适用于 DDE(文件是否正在某个地方写入磁盘?)

我建议使用xlrd (https://github.com/python-excel/xlrd)。我个人是通过 pip 安装的。然后简单地阅读 A1:B3 这样做(撕掉文档):

from xlrd import open_workbook

wb = open_workbook('spreadsheet.xlsx')
for s in wb.sheets():
     print('Sheet:',s.name) # you can check for the sheet name here if you want
     for row in range(2): #the first 2 rows (A and B) (use s.nrows for all)
         values = []
         for col in range(3): #the first 3 columns (use s.ncols for all)
            values.append(str(s.cell(row,col).value))
         print(','.join(values))

【讨论】:

    【解决方案2】:

    我需要完全相同的解决方案,这就是我所做的(它已经在工作):

    1. 我使用 Node.js(使用 Node Webkit,但您可以使用纯 Node.js)在不同端口(8080 和 3000)上创建了一个本地 http 服务器和一个本地 websocket 服务器。

    2. 在 http 服务器上,我设置 http://localhost:8080/write/ 以接收带有我想要的参数的 GET 请求,并使用这些参数向 websocket 服务器广播一条消息。

    3. 我编写了一个 VBA 代码,使用 Worksheet_Calculate sub 将数据推送到本地 http 服务器(每次工作表刷新其内容时都会触发一个事件)。

    4. 最后我做了 Python 来监听 websocket 服务器(ws://localhost:3000/),等待服务器信号。


    深入了解编码细节:

    为了创建本地服务器,我使用了 Express 和 ws 模块。第一个创建http服务器,第二个创建websocket服务器:

    快递详情:

    var express = require('express');
    var app = express();
    app.get('/', function (req, res) { res.send('Hello World!') }) // to see if server is on
    
    // broadcast data on q GET variable: http://localhost:8080/write/?q=32,34,23
    app.get('/write/', function (req, res) {   
        wss.broadcast(req.query.q); // this line uses the variable created below
        res.send();
    }); 
    
    var server = app.listen(8080, function () {});
    

    ws 详细信息:

    var WebSocketServer = require('ws').Server;
    
    wss = new WebSocketServer({port: 3000});
    wss.on('connection', function(ws) {
        // you can use this event to perform some action when python get connected
        ws.send("you're connected");        
    
        // use this event if you need websocket to receive message
        ws.on('message', function(message) { 
            ws.send(message);
        });
    });
    
    wss.broadcast = function broadcast(data) {
        wss.clients.forEach(function each(client) {
            client.send(data);
        });
     };
    

    将数据从 Excel 发送到 http 服务器(我尝试使用 websocket,但无法弄清楚 Excel 如何连接到 websocket):

    Function postServer(url, data)
        Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
        objHTTP.Open "GET", url & data, False ' true para asynchronous calls
        objHTTP.send '(dados)
    
        postServer = 1 'It's a good idea to get the responseHTML from server and verifies if the everything is all right
    End Function
    

    在 Worksheet_Calculate() 中使用这个函数来发送数据:

    Private Sub Worksheet_Calculate()
        server = "http://localhost:8080/write/?q="
        'data = <something> 'catch your data with vba code
        postServer(server,data)
    End sub
    

    这里的技巧细节是如何知道某些数据何时已发送,因此您可以避免发送两次或更多。您必须根据数据在工作表上的组织方式来创建方法。对我来说,有一个有序的数字列和一个记录我发送的最后一个数字的单元格。

    好的!现在你必须准备 Python 来接收这些数据:

    我下载了 websocket-client 0.25.0 模块。这是监听websocket服务器的python代码:

    import sys
    import websocket
    import thread
    import time
    
    wsAddress = "ws://localhost:3000/"     
    
    def on_message(ws, message):
        print message # you got it!
    
    def on_error(ws, error):
        print error
    
    def on_close(ws):
        print "### closed ###"
    
    def on_open(ws):
        print "conectado"
    
    if __name__ == "__main__":
        websocket.enableTrace(True)
        ws = websocket.WebSocketApp(wsAddress,
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
        ws.on_open = on_open
        ws.run_forever()
    

    如果您在本地网络上,您可以使用 IP(或机器名称)来发布和收听服务器(这很棒)。下面是使用 node.js 发现 id 的代码:

    var os = require('os');
    var ifaces=os.networkInterfaces();
    for (var dev in ifaces) {
        var alias=0;
        ifaces[dev].forEach(function(details){
            if ((details.family=='IPv4')&&(details.address!="127.0.0.1")&&(details.internal === false)) {
                console.log(details.address);
                ++alias;
            }
        });
    }  
    

    我希望我有所帮助。如果您提出一些问题,请告诉我。

    【讨论】:

    • 这是一个令人印象深刻的答案,但这个问题并没有说明需要客户端-服务器解决方案。如果工作簿在客户端计算机上打开并且所需数据在其他客户端或服务器上实时使用,则此解决方案将有意义。
    • 我知道,查理。但我认为它可以帮助其他找到此页面的人寻找有关将 excel 文件集成到 Python 的解决方案! :)
    • 我很感激。我只是建议不要在顶部说您需要“完全相同的解决方案”,而是澄清您要解决的问题,因为它与问题不同。
    【解决方案3】:

    我想分享一个很大程度上从这个StackOverflow solution 窃取的解决方案,因为我发现 xlrd 在打开网络上其他用户可能打开也可能不打开的 Excel 文件时结果不一致。使用 win32com(到目前为止)对我来说效果更好。

    #using path to avoid escape character errors
    from pathlib import Path
    path = Path(r'/full/filepath')
    
    from win32com import client
    
    xlApp = client.GetObject(None, "Excel.Application")
    books = xlApp.Workbooks.Open(path)
    ws = books.Worksheets[0]
    ws.Visible = 1
    #returns tuple
    shift_1 = ws.Range("A1:B2").Value
    
    import numpy as np
    #selection of 0 element of tuple would depend on use case.
    shift_1 = np.asarray(shift_1[0])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 2018-06-13
      • 2013-11-01
      • 2019-11-08
      • 2019-03-26
      • 2012-06-09
      • 2020-01-19
      相关资源
      最近更新 更多