DOSプロンプトから Excelマクロにパイプ処理を行う。 VBAで標準入力


DOSプロンプトから Excelマクロにパイプしたいことないですか?

普通はないと思います。
DOSプロンプトに詳しい人は、DOSプロンプトだけでいろいろできちゃうんだと思います。
でも、私はやってみたかったんです。
Dir | "C:\Temp\Test.xls"
とか
Sort "C:\temp\test.txt" | "C:\Temp\Test.xls"
とかできたら夢が広がりませんか?
あれっ、そんなことない!?
「それなら最初から全部マクロでファイルの列挙とかソートすれば、DOSプロンプトいらないじゃん!?」って思っちゃいました!?
いいんです。VBAでパイプしてみたかっただけなんです。
C++で作ったExeにはできて、VBAにはできないってことがあるのが癪なんです。

ただ、実はすいません。
Dir | "C:\Temp\Test.xls"
はできません!

こうなります。
Dir | "[Excel.exeのフルパス]" "C:\Temp\Test.xls"

たとえば、私の場合だと
Dir | "C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE" "C:\Temp\Test.xls"
です。

しかも、これをするには、マクロのセキュリティレベルをさげておかないといけません。

VBAの説明はすっとぱして、コードだけ載せてみます。
ご興味があれば、やってみてください。
以下のコードは必ず ThisWorkBook オブジェクトに記入してください。

Const STD_INPUT_HANDLE = -10&
Const INVALID_HANDLE_VALUE = -1
Private Declare PtrSafe Function GetStdHandle Lib "kernel32" _
        (ByVal nStdHandle As Long) As LongPtr
Private Declare PtrSafe Function ReadFile Lib "kernel32" _
        (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
         lpNumberOfBytesRead As Long, ByVal lpOverlapped As LongPtr) As Long

Private Sub Workbook_Open()
    Dim hStdIn As Long
    hStdIn = GetStdHandle(STD_INPUT_HANDLE)

    Sheet1.Cells.Clear

    If hStdIn = INVALID_HANDLE_VALUE Then
        Sheet1.Cells(1, 1) = "INVALID_HANDLE_VALUE"
        End
    End If

    Dim sBuf As String
    Dim sResult As String
    Dim NumberOfBytesToRead As Long

    Do
        sBuf = String(10240, vbNullChar)
        If ReadFile(hStdIn, ByVal sBuf, Len(sBuf) - 1, NumberOfBytesToRead, 0) Then
            sResult = sResult & Mid(sBuf, 1, InStr(1, sBuf, vbNullChar) - 1)
        Else
            Exit Do
        End If
        DoEvents
    Loop

    Dim i As Long
    Dim vResult
    vResult = Split(sResult, vbLf)
    For i = LBound(vResult) To UBound(vResult)
        Sheet1.Cells(i + 1, 1) = "'" & vResult(i)
    Next
End Sub

実行するとこうなります。