8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Excel VBAAdvent Calendar 2017

Day 5

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

Last updated at Posted at 2017-12-04

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

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

image.png

image.png

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?