首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从Excel连接Mongodb

如何从Excel连接Mongodb
EN

Stack Overflow用户
提问于 2010-10-24 22:12:24
回答 7查看 22.4K关注 0票数 22

我想使用excel宏连接到一个mongodb数据库,有谁知道如何完成这个任务吗?

EN

回答 7

Stack Overflow用户

发布于 2016-05-06 18:42:25

可以从progress (下面提到)、easysoft和cdata获得ODBC驱动程序。

我已经尝试了进度,它做得很好。所有这些驱动程序都是授权软件,也有试用版可用。

最容易使用的是cdata Excel Add-In,它可以进行查询、更新,还允许使用基于excel的公式和VBA。它也是有许可证的。

另一种方法是在python中使用pymongo而不是mongo客户端进行查询,将结果转储到csv文件并通过VBA导入csv。从python查询mongoDB相当简单。

以下是从MongoDB示例数据集中查询的示例。

查询的Python文件"queryMongoDB.py“

代码语言:javascript
复制
SERVER = "192.168.43.22" # Replace wit with Server IP or Hostname running mongod
PORT   = "27017"

def queryMongoDB():
    try:
       from pymongo import MongoClient
       client = MongoClient("mongodb://" + SERVER + ":" + PORT)
       db = client.test
       queryResp = db.restaurants.find({'address.zipcode': "11215", 'cuisine': 'Indian'}, {'name': 1, 'address.building': 1, 'address.street': 1, 'borough': 1, '_id': 0})

       if queryResp.count() > 0 :
          for row in queryResp:
             printStr = ""
             if 'name' in row:
                printStr = row['name'] + ","
             else:
                printStr = ","
             if 'building' in str(row):
                printStr = printStr + row['address']['building'] + ","
             else:
                printStr = printStr + ","
             if 'street' in str(row):
                printStr = printStr + row['address']['street'] + ","
             else:
                printStr = printStr + ","
             if 'borough' in row:
                printStr = printStr + row['borough']
             print(printStr)
       else:
          return -2
       return 0
    except ImportError:
       return -1

queryMongoDB()

执行此脚本将打印到标准输出,格式为

代码语言:javascript
复制
Kinara Indian Restaurant,473,5 Avenue,Brooklyn
Baluchi'S,310,5 Avenue,Brooklyn
Kanan Indian Restaurant,452,3Rd Ave,Brooklyn
New Aarpan,396,5Th Ave,Brooklyn
Indian Spice,351,7Th Ave,Brooklyn

使用WshShell的Excel VBA宏,macro_queryMongoDB()

代码语言:javascript
复制
Sub macro_queryMongoDB()
   Dim pythonExecutable  As String
   Dim pythonQueryScript As String
   pythonExecuatble = "python.exe" ' Path to python interpreter
   pythonQueryScript = "queryMongoDB.py" 'Full path to the above Python script

   If Dir(pythonExecuatble) <> "" And Dir(pythonQueryScript) <> "" Then
      Dim objShell         As Object
      Dim objWshScriptExec As Object
      Dim objStdOut        As Object

      Set objShell = CreateObject("WScript.Shell")
      Set objWshScriptExec = objShell.Exec(pythonExecuatble & " " & pythonQueryScript) ' Execute the Python script
      Set objStdOut = objWshScriptExec.StdOut

      Set mybook = Excel.ActiveWorkbook
      Set mybookSheet = mybook.ActiveSheet

      Dim rline            As String
      Dim strline          As String
      Dim lineCount        As Long

      ' Parse the results
      lineCount = 1
      While Not objStdOut.AtEndOfStream
         rline = objStdOut.ReadLine
         If rline <> "" Then
            strline = rline & vbCrLf
            mybookSheet.Range(mybookSheet.Cells(lineCount, "A"), mybookSheet.Cells(lineCount, "D")).Value = Split(strline, ",")
            lineCount = lineCount + 1
         End If
      Wend
      MsgBox "Query Successful"
   Else
      MsgBox "Python executable or Python query DB script doesn't exist."
   End If
End Sub

运行此宏将把逗号分隔的数据填充到行中,如下所示

票数 5
EN

Stack Overflow用户

发布于 2014-01-10 18:42:35

我自己的解决方案是让Python使用pymongo和win32com将它们粘合在一起。然后就可以很直接地运行你想要的任何东西了。在我的例子中,Python循环只是不断地“监听”某些Excel单元格,从Mongo调用它所需的内容,然后将其放回Excel中。它很灵活,很多事情都可以通过这种方式来完成。下面是完整的代码库,但您必须更改对Mongodb的调用以匹配您自己的数据库。在这里,您还将看到在Python中更改Excel单元格的颜色和内容的某些方法。哦,我应该提一下,它充满了ansi转义序列,所以你可能想要从ansiconConEmu运行Python。

代码语言:javascript
复制
import win32com.client as win32
import time    # will need this for time parsing
from optparse import OptionParser
import pdb     # debugger, when necessary
import string  # for string parsing and the alphabet
from pymongo import MongoClient
import inspect
from datetime import datetime, timedelta, tzinfo
from dateutil import tz
from bson.son import SON
import msvcrt # for getch
import os
import sys # for stdout.write
from collections import OrderedDict


def parseCmdLine():
    parser = OptionParser(description="Retrieve realtime data.")
    parser.add_option("--f",
                      dest="file",
                      help="filename",
                      default="bbcapture.xls")
    parser.add_option("--mongohost",
                      dest="mongohost",
                      default="192.168.1.30")
    parser.add_option("--mongoport",
                      dest="mongoport",
                      type="int",
                      default=27017)

    (options, args) = parser.parse_args()
    return(options)

options = parseCmdLine() # parse the commandline
client = MongoClient(options.mongohost, options.mongoport) # link to mongo
db = client.bb # the database
bbsecs = db.bbsecs # now all the collections
bbdaily = db.bbdaily
bbticks = db.bbticks
linkstatusperiod = False # for the moving period in the top left excel cell showing we're linked

def ansi(colour = "white", bright = False, back = "black"):
# ansi colour sequences
    brit = {True:       "\033[1m",
            False:      "\033[0m"}
    colo = {"black":    "\033[30m", 
            "red":      "\033[31m",
            "green":    "\033[32m",
            "yellow":   "\033[33m",
            "blue":     "\033[34m",
            "magenta":  "\033[35m",
            "cyan":     "\033[36m",
            "white":    "\033[37m"}
    bakk = {"black":    "\033[40m", 
            "red":      "\033[41m",
            "green":    "\033[42m",
            "yellow":   "\033[43m",
            "blue":     "\033[44m",
            "magenta":  "\033[45m",
            "cyan":     "\033[46m",
            "white":    "\033[47m"}
    sys.stdout.write(brit[bright])
    sys.stdout.write(colo[colour])
    sys.stdout.write(bakk[back])


def mdaily(ticker = "USDEUR Curncy", field = "LAST_PRICE", sortdirection = 1, numget = 1000000):
    ansi("cyan", False)
    print "\nGetting", ticker, "field", field, "from Mongo...",
    lister = OrderedDict()
    #for post in bbdaily.find({"ticker": ticker, "fieldname": field}).limit(numget).sort("time", sortdirection):
    for post in bbdaily.find({"$query": {"ticker": ticker, "fieldname": field}, "$orderby": {"time": -1}}).limit(numget):
        lister[str(post["time"])] = post["fieldvalue"]
    ansi("cyan", True)
    print "got", len(lister), "values",
    ansi()
    return lister

def mtick(tickers, sortdirection = 1, numget = 1000000):
    if len(tickers) == 0:
        return []
    else:
        ansi("green", False)
        print "\n Getting minutes for for", tickers, 
        tickerdic = OrderedDict()
        for eachticker in tickers:
            eachdic = dict()
            print numget
            for post in bbticks.find({"ticker": eachticker}).limit(numget):
                eachdic[post["time"]] = [post["open"], post["high"], post["low"], post["close"]]
            ansi("green")
            tickerdic[eachticker] = eachdic
            print "got", len(eachdic), "for ticker", eachticker, 
        ansi("green", True)
        print "got", len(tickerdic), "tickers",
        dates = [set(tickerdic[x].keys()) for x in tickerdic] # get all the dates
        dates = set.intersection(*dates) # get the unique ones
        dates = [x for x in dates] # convert to list
        if sortdirection == -1:
            dates = sorted(dates, reverse = True)
        else:
            dates = sorted(dates, reverse = False)
        retlist = [[[x, tickerdic[y][x][0], tickerdic[y][x][1], tickerdic[y][x][2], tickerdic[y][x][3]] for x in dates] for y in tickerdic.keys()]
        ansi()
        return retlist

def getsecs():
    seclist = []
    for post in bbsecs.find():
        seclist.append(post["ticker"])
    return(seclist)




def offsetString(startrow, startcol, endrow, endcol):
    startrowstr = str(startrow)
    endrowstr = str(endrow)
    if(startcol > 26):
        startcolstr = string.uppercase[startcol / 26 - 1] + string.uppercase[startcol % 26 - 1]
    else:
        startcolstr = string.uppercase[startcol - 1]
    if(endcol > 26):
        endcolstr = string.uppercase[endcol / 26 - 1] + string.uppercase[endcol % 26 - 1]
    else:
        endcolstr = string.uppercase[endcol - 1]
    return(startcolstr + startrowstr + ":" + endcolstr + endrowstr)

def main():
    excel = win32.gencache.EnsureDispatch("Excel.Application")
    excel.Visible = 1
    try: # try to link to the file
        ansi("red", False)
        print "Linking to", options.file
        wb = excel.Workbooks(options.file)
        ws = wb.Worksheets("MongoData")
        ansi()
    except: # not open then try to load it
        try:
            ansi("red", False)
            print "Not open.... trying to open in current directory", os.getcwd()
            ansi()
            wb = excel.Workbooks.Open(os.getcwd() + "\\" + options.file)
            ws = wb.Worksheets("MongoData")
            ansi()
        except: # can't load then ask to create it
            ansi("red", True)
            print options.file, "not found here. Create? (y/n) ",
            ansi("yellow", True)
            response = msvcrt.getch()
            print response
            ansi()
            if response.upper() == "Y":
                wb = excel.Workbooks.Add()
                ws = excel.Worksheets.Add()
                ws.Name = "MongoData"
                wb.SaveAs(os.getcwd() + "\\" + options.file)
            else: # don't wanna create it then exit
                print "bye."
                return
    # see if ticks sheet works otherwise add it
    try:
        wst = wb.Worksheets("MongoTicks")
    except:
        wst = excel.Worksheets.Add()
        wst.Name = "MongoTicks"
        wst.Cells(3, 2).Value = 1
    # see if securities list sheet works otherwise add it
    try:
        wall = wb.Worksheets("AllSecurities")
        wall.Cells(1, 1).Value = "List of all securities"
        wall.Range("A1:A1").Interior.ColorIndex = 8
        wall.Range("A:A").ColumnWidth = 22
    except:
        wall = excel.Worksheets.Add()
        wall.Name = "AllSecurities"
        wall.Cells(1, 1).Value = "List of all securities"
        wall.Range("A1:A1").Interior.ColorIndex = 8
        wall.Range("A:A").ColumnWidth = 22

    ansi("green", True)
    print "talking to", options.file, 
    ansi("green", False)
    print "... press any key when this console has the focus, to end communication"
    ansi()
    def linkstatusupdate():
        global linkstatusperiod
        if linkstatusperiod:
            ws.Cells(1, 1).Value = "Talking to Python|"
            wst.Cells(1, 1).Value = "Talking to Python!"
            linkstatusperiod = False
        else:
            ws.Cells(1, 1).Value = "Talking to Python|"
            wst.Cells(1, 1).Value = "Talking to Python!"
            linkstatusperiod = True
        ws.Cells(1, 2).Value = datetime.now()
    # daily worksheet header formatting
    ws.Cells(1, 1).Value = "Excel linked to Python"
    ws.Cells(1, 3).Value = "Sort direction:"
    ws.Cells(1, 4).Value = 1
    ws.Cells(1, 5).Value = "Fetch max:"
    ws.Cells(2, 1).Value = "Enter tickers:"
    ws.Cells(3, 1).Value = "Start data:"
    ws.Cells(4, 1).Value = "End data:"
    ws.Range("A:A").ColumnWidth = 22
    ws.Range("B:B").ColumnWidth = 20
    ws.Range("A2:GS2").Interior.ColorIndex = 19 # beige 200 columns
    ws.Range("A3:GS4").Interior.ColorIndex = 15 # grey
    ws.Range("A2").Interior.ColorIndex = 3 # red
    ws.Range("A3:A4").Interior.ColorIndex = 16 # dark grey
    # minute worksheet header formatting
    wst.Cells(1, 1).Value = "Excel linked to Python"
    wst.Cells(2, 1).Value = "Enter tickers:"
    #wst.Cells(3, 1).Value = "Enter periodicity:"
    wst.Cells(1, 3).Value = "Sort direction:"
    wst.Cells(1, 4).Value = 1
    wst.Cells(1, 5).Value = "Fetch max:"
    wst.Range("A:A").ColumnWidth = 22
    wst.Range("B:B").ColumnWidth = 20
    wst.Range("A2:GS3").Interior.ColorIndex = 19 # beige 200 columns
    wst.Range("A4:GS5").Interior.ColorIndex = 15 # grey
    wst.Range("A2:A3").Interior.ColorIndex = 4 # red
    wst.Range("6:100000").Clear()
    linkstatusperiod = False
    oldsecd = []
    oldseci = []
    oldnumget = oldsortdir = toldnumget = toldsortdir = 0
    while not msvcrt.kbhit():
        try:
            print "...", wb.Name,
            securities = ws.Range("B2:GS2").Value[0]
            sortdir = ws.Cells(1, 4).Value
            if sortdir == None:
                sortdir = 1
            sortdir = int(sortdir)
            numget = ws.Cells(1, 6).Value
            if numget == None:
                numget = 1000000
            numget = int(numget)
            securities = [x for x in securities if x is not None]
            if not ((oldsecd == securities) and (oldnumget == numget) and (oldsortdir == sortdir)): # clear content of cells 
                ws.Range("5:1000000").Clear()
                ws.Range("B3:GS4").Clear()
                ws.Range("B3:GS4").Interior.ColorIndex = 15 # grey
                oldsecd = securities
                oldnumget = numget
                oldsortdir = sortdir
            currentcol = 0
            for sec in securities:
                linkstatusupdate()
                secdata = mdaily(sec, "LAST_PRICE", sortdir, numget)
                currentrow = 0
                vallist = []
                datelist = []
                if sortdir == -1:
                    sortedkeys = sorted(secdata, reverse = True)
                else: 
                    sortedkeys = sorted(secdata, reverse = False)
                for eachkey in sortedkeys:
                    datelist.append(eachkey)
                    vallist.append(secdata[eachkey])
                #now stick them in Excel
                ws.Range(offsetString(5 + currentrow, 2 + currentcol, 5 + currentrow + len(vallist) - 1, 2 + currentcol)).Value = \
                        tuple([(x, ) for x in vallist])
                if currentcol == 0:
                    ws.Range(offsetString(5 + currentrow, 1, 5 + currentrow + len(vallist) - 1, 1)).Value = \
                        tuple([(x, ) for x in datelist])
                if len(sortedkeys) > 0:
                    ws.Cells(3, 2 + currentcol).Value = sortedkeys[len(sortedkeys) - 1].split()[0] # start data date
                    ws.Cells(4, 2 + currentcol).Value = sortedkeys[0].split()[0] # end data date
                currentcol += 1
            # now do the tick data
            securitiest = wst.Range("B2:GS2").Value[0]
            securitiest = [x for x in securitiest if x is not None]
            tsortdir = wst.Cells(1, 4).Value
            if tsortdir == None:
                tsortdir = 1
            tsortdir = int(tsortdir)
            tnumget = wst.Cells(1, 6).Value
            if tnumget == None:
                tnumget = 1000000
            tnumget = int(tnumget)
            if not ((oldseci == securitiest) and (toldnumget == tnumget) and (toldsortdir == tsortdir)): # clear the contents of the cells 
                wst.Range("6:1000000").Clear()
                wst.Range("B4:GS5").Clear()
                wst.Range("B4:GS5").Interior.ColorIndex = 15 # grey
                oldseci = securitiest
                toldnumget = tnumget
                toldsortdir = tsortdir
            secdata = mtick(securitiest, tsortdir, tnumget)
            currentsec = 0
            for x in secdata:
                sender = [tuple(y[1:5]) for y in x]
                wst.Range(offsetString(6, 2 + currentsec * 4, 6 + len(x) - 1, 5 + currentsec * 4)).Value = sender
                if currentsec == 0: # then put the dates in 
                    dates = [tuple([y[0], ]) for y in x]
                    wst.Range(offsetString(6, 1, 6 + len(x) - 1, 1)).Value = dates
                wst.Range(offsetString(5, 2 + currentsec * 4, 5, 5 + currentsec * 4)).Value = ["open", "high", "low", "close"]
                currentsec += 1
            for x in range(0, len(securitiest)):
                wst.Cells(4, 2 + x * 4).Value = securitiest[x]
            linkstatusupdate()
            allsecs = tuple([(yy, ) for yy in getsecs()])
            wall.Range(offsetString(2, 1, len(allsecs) + 1, 1)).Value = allsecs

        except:
            print "\nExcel busy",
        time.sleep(1)

    endchar = msvcrt.getch() # capture the last character so it doesn't go to console
    print "\nbye."


if __name__ == "__main__":
    main()
票数 4
EN

Stack Overflow用户

发布于 2016-05-06 23:44:57

关于使用ODBC驱动程序连接到Excel中的MongoDB数据,我可以回答其他问题。当然,问题是你没有办法使用宏。

正如Irfan提到的,CData Excel Add-In将允许您这样做。(完全公开,我在CData软件公司工作)。您可以在我们的Help documentation中阅读有关使用宏连接到MongoDB的内容,但我在这里包含了相关的代码片段,以演示将MongoDB数据读取到excel中的基本功能:

代码语言:javascript
复制
Sub DoSelect()
  On Error GoTo Error
  p_id = InputBox("_id:", "Get _id")
  If p_id = False Then
    Exit Sub
  End If
  Dim module As New ExcelComModule
  module.SetProviderName ("MongoDB")
  Cursor = Application.Cursor
  Application.Cursor = xlWait
  Dim nameArray
  nameArray = Array("_idparam")
  Dim valueArray
  valueArray = Array(p_id)
  Query = "SELECT City, CompanyName FROM Customers WHERE _id = @_idparam"
  module.SetConnectionString ("Server=127.0.0.1;Port=27017;Database=test;User=test;Password=test;")
  If module.Select(Query, nameArray, valueArray) Then
    Dim ColumnCount As Integer
    ColumnCount = module.GetColumnCount
    For Count = 0 To ColumnCount - 1
      Application.ActiveSheet.Cells(1, Count + 1).Value = module.GetColumnName(Count)
    Next
    Dim RowIndex As Integer
    RowIndex = 2
    While (Not module.EOF)
      For columnIndex = 0 To ColumnCount - 1
        If Conversion.CInt(module.GetColumnType(columnIndex)) = Conversion.CInt(vbDate) And Not IsNull(module.GetValue(columnIndex)) Then
          Application.ActiveSheet.Cells(RowIndex, columnIndex + 1).Value = Conversion.CDate(module.GetValue(columnIndex))
        Else
          Application.ActiveSheet.Cells(RowIndex, columnIndex + 1).Value = module.GetValue(columnIndex)
        End If
      Next
      module.MoveNext
      RowIndex = RowIndex + 1
    Wend
    MsgBox "The SELECT query successful."
  Else
    MsgBox "The SELECT query failed."
  End If
  Application.Cursor = Cursor
  Exit Sub
Error:
  MsgBox "ERROR: " & Err.Description
  Application.Cursor = Cursor
End Sub

我们的2016版本目前处于测试阶段,所以你可以从今天开始在Excel中免费使用MongoDB数据。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4008598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档