There is a similar thread and I like one of the answers there, the one using shell. But it seems to connect to a running instance of mongo.
In my case, there's no running instance, the Mongo db is somewhere else and I can't figure out how to connect to it using this script.
I guess i would need a way to add a connection string to an outside MongoDB using an approach similar to the one below.
How to connect Mongodb from Excel
This is the answer
The Shell Approach
Pretty much anything that interfaces with the Command Line can be accessed with Shell.
Here's a bare-bones example that connects to a running MongoDB instance and prints a query to the Immediate Window. You'll need to add a reference to the Windows Script Host Object Model.
Private Sub Test()
Dim wsh As New WshShell
Dim proc As WshExec
Dim line As String
Set proc = wsh.Exec("mongo")
With proc
.StdIn.WriteLine "use test"
.StdIn.WriteLine "db.restaurants.find({""address.zipcode"":""10075""})"
.StdIn.WriteLine "quit()"
Do While .Status = WshRunning
line = .StdOut.ReadLine
If line = "Type ""it"" for more" Then
.StdIn.WriteLine "it"
ElseIf line Like "{*" Then
Debug.Print line
End If
DoEvents
Loop
End With
End Sub
Just printing the raw JSON strings isn't very exciting or useful, however. You could write your own JSON parser but, for this example, we will use VBA-JSON by Tim Hall (you can find it on GitHub).
At the time of writing, there is one issue with VBA-JSON that has to be tackled when using it to parse strings returned from MongoDB. Any values that contain parentheses, e.g. "_id": ObjectId("..."), will throw an error. A quick and dirty fix for this is to use RegEx to clean the string for the parser. You will need to reference the Microsoft VBScript Regular Expressions 5.5 library for the following function to work.
Private Function CleanString(str As String) As String
Dim temp As String
Dim rx As New RegExp
With rx
.IgnoreCase = True
.Global = True
.Pattern = "[a-z]*\(" ' Left
temp = .Replace(str, "")
.Pattern = "\)" ' Right
temp = .Replace(temp, "")
End With
CleanString = temp
End Function
We can then parse the JSON returned from MongoDB and add each object to a Collection. Accessing the values becomes quite simple.
Private Sub Mongo()
Dim wsh As New WshShell
Dim proc As WshExec
Dim line As String
Dim response As New Collection
Dim json As Object
Set proc = wsh.Exec("mongo")
With proc
.StdIn.WriteLine "use test"
.StdIn.WriteLine "db.restaurants.find({""address.zipcode"":""10075""})"
.StdIn.WriteLine "quit()"
Do While .Status = WshRunning
line = .StdOut.ReadLine
If line = "Type ""it"" for more" Then
.StdIn.WriteLine "it"
ElseIf line Like "{*" Then
response.Add ParseJson(CleanString(line))
End If
DoEvents
Loop
End With
For Each json In response
Debug.Print json("name"), json("address")("street")
Next
End Sub
... Which will produce the following output from the MongoDB Example Dataset.
Nectar Coffee Shop Madison Avenue
Viand Cafe Madison Avenue
Don Filippo Restaurant Lexington Avenue
Lusardi'S Restaurant Second Avenue
Due Third Avenue
Lenox Hill Grill/Pizza Lexington Avenue
Quatorze Bistro East 79 Street
Luke'S Bar & Grill Third Avenue
Starbucks Coffee Lexington Avenue
New York Jr. League East 80 Street
Doc Watsons 2 Avenue
Serafina Fabulous Pizza Madison Avenue
Canyon Road Grill 1 Avenue
Sushi Of Gari East 78 Street
Gotchas
ReadLine and WriteLine are blocking functions.
The window opened by Exec can't be hidden.
A workaround for both of the above would be to use a two-layer approach, where VBA calls a hidden script using wsh.Run, which then runs the Exec (as well as any other code that interacts with the proc). The downside to this approach is that StdIn (and to an extent StdOut) has to be written to a file.
To connect to an external MongoDB, simply adjust the Windows Shell call to point to external address. Per MongoDB docs, mongo by itself defaults to localhost at port 27017. For a remote host, adjust these defaults.
Using connection string:
Set proc = wsh.Exec("mongo ""mongodb://username:password#host:port/database""")
Using args:
Set proc = wsh.Exec("mongo --host <server_or_ip_address>" _
& " --port <port_number>" _
& " --username <username>" _
& " --password <password>")
Above would require having the mongo shell installed on client machine even with no database set up locally. Also, the server machine hosting the MongoDB must allow external connections. Read docs for setup and instructions.
Related
For several years we've been using code similar to the following (a result similar to that of net use) to convert UNC filenames to their legacy (drive letter) equivalents:
Dim network As Object: Set network = CreateObject("WScript.Network")
Dim netDrives As Object: Set netDrives = network.EnumNetworkDrives
Dim myLet As String
Dim myUnc As String
Dim i As Long
' loop through all network drives
For i = 0 To netDrives.count - 1 Step 2
myLet = netDrives.Item(i)
myUnc = netDrives.Item(i + 1)
myUnc = Replace(myUnc, "#SSL", "")
' hopefully we find it here
If InStr(LCase(uncname), LCase(myUnc)) Then
toLegacyName = myLet & Right(uncname, Len(uncname) - Len(myUnc))
Exit Function
End If
Next i
In the recent past, more login options (such as whether to use Citrix, VPN, or use the machine in the office) plus newer "file systems" (like Sharepoint) have rendered this code unreliable, where depending on how the user is signed on, network.EnumNetworkDrives may or may not return complete information. A drive may be present with Citrix but not using VPN, etc.
Are there other ways to do this? In the end, all we want to do is replicate net use.
i'm a beginner of vbscript , i need you help , my question is how do i do to get a variable from cmd and show it in vbscript for example get a ping from www.google.com and show it in a msgbox in vbscript help me code :
dim cmd,x
set cmd = createobject("wscript.shell")
x= cmd.run("cmd /k ping www.google.com ",1,true)
Get that output and show it in a msgbox later , help me
Here an example of how to do that.
The response of the ping that is checked is in Dutch but that doesn't matter for your case.
Set objExec = CreateObject("WScript.Shell").exec("ping www.google.com")
With objExec
Do While .Status = 0
WScript.Sleep 10
Do While Not .StdOut.AtEndOfStream
WScript.Echo .StdOut.ReadLine
'Check the .StdErr to see if it is at the end of its
'stream. If not, call ReadLine on it
If Not .StdErr.AtEndOfStream Then
.StdErr.ReadLine
End If
Loop
Loop
End With
An advise though, don't begin scripting in vbscript, it's a dead end.
Choose some modern scripting language like Python or still better for beginners: Ruby.
Be sure to use cscript as engine in stead of wscript, execute the following to set that as default.
wscript //H:Cscript
Your vbscript is then one single line
puts `ping www.google.com`
As per title. Using this code example (3rd example down) as my starting point.
Here's my effort at VBA code, but it stalls at the first hurdle ("Run time error 438: object doesn't support this property or method")
Sub Test()
Set objConnection = GetObject("WinNT://HM10")
Set colResources = objConnection.Resources
For Each objResource In colResources
Debug.Print objResource.Path
Next
End Sub
HM10 is my computer name. Eventually it will need to be an environmental variable (if that's the right term) for whatever machine it happens to be on.
EDIT: Ok, more searching has led me to this:
Sub test()
Filename = "."
Set wmi = GetObject("winmgmts://./root/cimv2")
qry = "SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" & Filename & "%'"
For Each p In wmi.ExecQuery(qry)
Debug.Print p.commandline
Next
End Sub
which is closer, but only shows local files, not network files. I only need network files, how do I get them?
I had a simple but very important vba rule in Outlook.
This morning my Office upgraded to 16.0.7531.1003 version (64 bit) and
I found my rule unchecked and trying to check it I get message "This rule is unavailable in current mode" (this is a translation as I am not using English version of Outlook).
Furthermore, the option "run script" is no longer visible while trying to configure a new rule.
The only thing the rule does is searching new email body for valid GUID, and if any exists, it inserts the GUID and email SentOn date into database.
Did Microsoft disable VBA rules at all?
Public Sub getGUID(receiptItem As MailItem)
Dim regE As New RegExp
Dim matches As MatchCollection
Dim sql As String: sql = "insert HDSDEB.dbo.ReportCalendar_received(ReportGUID, SentDatetime) values ('__GUID__', '__SentOn__');"
regE.Pattern = "[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}"
regE.IgnoreCase = True
regE.MultiLine = True
Set matches = regE.Execute(receiptItem.body)
If matches.Count = 0 Then Exit Sub
Debug.Print matches.Item(0).Value
sql = Replace(sql, "__GUID__", matches.Item(0).Value)
sql = Replace(sql, "__SentOn__", receiptItem.SentOn)
SQLQueryRun (sql)
Debug.Print sql
End Sub
I had the same issue like yours and this post may be what you need. Adding a new value to my computer's registry (EnableUnsafeClientMailRules) and set it to 1 solved my problem.
i try to connect my xls with access database. Below code work greate when i have installed full access program on my machine. Problem is when i try tu use it on machine what have only installed Run-time version of access.
I have use this references:
Visual Basic For Applications
Microsoft Excel 14.0 Object Library
OLE Automation
Microsoft Office 14.0 Object Library
Microsoft Forms 2.0 Object Library
When i try to run below code i get error: ActiveX component can't create object or return reference to this object (Error 429)
Sub mcGetPromoFromDB()
Application.ScreenUpdating = False
Dim daoDB As DAO.Database
Dim daoQueryDef As DAO.QueryDef
Dim daoRcd As DAO.Recordset
'Error on line below
Set daoDB = Application.DBEngine.OpenDatabase("K:\DR04\Groups\Functional\DC_Magazyn\Sekcja_Kontroli_Magazynu\Layout\dbDDPiZ.accdb")
Set daoRcd = daoDB.OpenRecordset("kwPromoIDX", dbOpenDynaset)
Dim tempTab() As Variant
For Each Article In collecArticle
daoRcd.FindNext "IDX = " & Article.Index
Article.PromoName = daoRcd.Fields(1).Value
Article.PromoEnd = "T" & Format(daoRcd.Fields(2).Value, "ww", vbMonday, vbUseSystem)
Next
Application.ScreenUpdating = True
End Sub
Is IDX an indexed field?
Is kwPromoIDX optimized for this specific purpose? I mean does it only contain the fields required for this update, or are you pulling extra useless fields? Perhaps something like "SELECT IDX, [Field1Name], [Field2Name] FROM kwPromoIDX" would be more efficient.
Since you are only reading the table records, and don't seem to need to actually edit them instead of dbOpenDynaset, use dbOpenSnapshot.
Just throwing out an idea here, you'd have to test to see if it made any difference, but perhaps you could try to reverse your logic. Loop through the recordset 1 by 1 and locate the IDX within your worksheet.
Another thing I've done in the past is use .CopyFromRecordset and copied the entire recordset into a temporary worksheet and done the juggling back and forth entirely within Excel, to eliminate the back and forth.
Lastly, another approach can be to quickly loop through the entire recordset and populate an array, collection, ... and then work with it instead of Access. This way the data is all virtual and you reduce the back and forth with Access.
You'll need to do some testing to see what works best in your situation.