为什么无法在读取 Excel 宏中的空白行后给出 shell 输入?

Why is it not possible to give a shell input after reading a blank line in an Excel macro?

我是 VBA 的新手,我想通过 shell 多次查询 MongoDB 数据库。但是,当查询的输出为空时(因为它不存在于数据库中),我似乎无法通过同一个 shell 实例执行另一个命令。有谁知道为什么会这样以及如何解决?

Dim wsh As New WshShell
Dim proc As WshExec
Dim i As Integer
Dim result As String

Set proc = wsh.Exec("mongo")
proc.StdIn.WriteLine "use mydb"

For i = 1 To 4
    If i = 3 Then
        proc.StdIn.WriteLine "db.mycollection.find({'field': 'something non-existent'})"
    Else
        proc.StdIn.WriteLine "db.mycollection.find({'field': '" & i & "'})"
    End If
    result = proc.StdOut.ReadLine
    Debug.Print i
    Debug.Print result
Next i

proc.StdIn.WriteLine "quit()"

导出:

1
{something}
2
{something}
3

4

所以对于第 3 次和第 4 次迭代,我只得到一个空行并且 shell window 最后没有关闭。如果您删除 if 语句(以便查询确实找到某些东西),则每次迭代都会显示一个结果并且 shell 在最后关闭。

我找到了解决问题的方法。问题是如果查询结果为空或 null 而您尝试读取 stdout 行,指针将移动到流的末尾。这意味着“文件”已被读取。

基本上,我需要确保它永远不会 returns blank/null。所以,我这样做了:

Dim wsh As New WshShell
Dim proc As WshExec
Dim i As Integer
Dim check As String
Dim result As String

Set proc = wsh.Exec("mongo")
proc.StdIn.WriteLine "use mydb"

For i = 1 To 4
    proc.StdIn.WriteLine "db.mycollection.find({'field': '" & i & "'}).count()"

    check = proc.StdOut.ReadLine

    If CInt(check) > 0 Then ' Now you are sure it will result in something.
        proc.StdIn.WriteLine "db.mycollection.find({'field': '" & i & "'})"
        result = proc.StdOut.ReadLine
    End If
Next i

proc.StdIn.WriteLine "quit()"
proc.StdOut.ReadLine

也许这不是摆脱“StdOut.AtEndOfStream”问题的最好或最优雅的方法,但它是一个简单的方法。这样您就不必调用单独的脚本 and/or 使用单独的 input/output 文件。