VBAからGDI+を使う資料集
inet上の達人の方々から御教示いただいたコードを少しアレンジさせてもらっています(切り貼りとも言います)。
  1. ホーム
  2. Other
  3. CBからSYLK形式データ取得


セルコピー後、クリップボードからSYLK形式データ取得

エクセルのセルをコピー後、クリップボードからSYLK形式データを取得し、ワークシートに書き出す
何に役立つかって?う~ん、思いつかない。


'----------------------------------------------------------------------------
'クリップボード関連
'----------------------------------------------------------------------------
Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () As Long
Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function RegisterClipboardFormat Lib "user32" Alias "RegisterClipboardFormatA" (ByVal lpString As String) As Long

Private Const CF_BITMAP = 2
Private Const CF_DIB = 8
Private Const CF_DIF = 5
Private Const CF_DSPBITMAP = &H82
Private Const CF_DSPENHMETAFILE = &H8E
Private Const CF_DSPMETAFILEPICT = &H83
Private Const CF_DSPTEXT = &H81
Private Const CF_ENHMETAFILE = 14
Private Const CF_GDIOBJFIRST = &H300
Private Const CF_GDIOBJLAST = &H3FF
Private Const CF_METAFILEPICT = 3
Private Const CF_OEMTEXT = 7
Private Const CF_OWNERDISPLAY = &H80
Private Const CF_PALETTE = 9
Private Const CF_PENDATA = 10
Private Const CF_PRIVATEFIRST = &H200
Private Const CF_PRIVATELAST = &H2FF
Private Const CF_RIFF = 11
Private Const CF_SYLK = 4
Private Const CF_TEXT = 1
Private Const CF_TIFF = 6
Private Const CF_UNICODETEXT = 13
Private Const CF_WAVE = 12

'----------------------------------------------------------------------------
'メモリ関連
'----------------------------------------------------------------------------
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Const GMEM_MOVEABLE = &H2

Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByVal Destination As Long, _
    ByVal Source As Long, _
    ByVal Length As Long)

Declare Function WideCharToMultiByte Lib "kernel32" _
    (ByVal CodePage As Long, _
     ByVal dwFlags As Long, _
     ByVal lpWideCharStr As Long, _
     ByVal cchWideChar As Long, _
     ByRef lpMultiByteStr As Any, _
     ByVal cchMultiByte As Long, _
     ByVal lpDefaultChar As String, _
     ByVal lpUsedDefaultChar As Long) As Long
Declare Function MultiByteToWideChar Lib "kernel32" _
    (ByVal CodePage As Long, _
     ByVal dwFlags As Long, _
     ByRef lpMultiByteStr As Any, _
     ByVal cchMultiByte As Long, _
     ByVal lpWideCharStr As Long, _
     ByVal cchWideChar As Long) As Long

'------------------------------------------------
' クリップボードからデータ取得(SYLK形式)
'------------------------------------------------
'http://www.sanryu.net/acc/tips/tips289.htm
'http://hpcgi1.nifty.com/MADIA/VBBBS/wwwlng.cgi?print+200910/09100010.txt
'http://support.microsoft.com/kb/410409/ja 本家SYLKフォーマット
'http://delfusa.main.jp/delfusafloor/archive/www.nifty.ne.jp_forum_fdelphi/samples/01047.html
Sub test()
    Dim data()  As Byte
    Dim hMem As Long
    Dim dwBytes As Long
    Dim p As Long
    Dim i As Long, j As Long
    Dim strResult As String
    Dim buf As Variant

    Dim S As String, L2 As String
    Dim myData As Variant
    Dim myRow As Long, myCol As Long
    Dim StartRow As Long, StartCol As Long
    Dim StartX As Long, StartY As Long
    'クリップボードを開く
    If OpenClipboard(0&) Then
        hMem = GetClipboardData(CF_SYLK)
        If hMem Then
            'バイト数取得
            dwBytes = GlobalSize(hMem)
            'グローバルメモリオブジェクトをロック(ポインタ取得)
            p = GlobalLock(hMem)
            '再割り当て
            ReDim data(0 To dwBytes - 1)
            'コピー
            MoveMemory VarPtr(data(0)), p, dwBytes
            'メモリオブジェクトのロックを解除
            GlobalUnlock hMem
            CloseClipboard
            For i = 0 To dwBytes - 1
              If data(i) = 0 Then
                  data(i) = Asc(" ")
              End If
            Next i
            strResult = AnsiToUnicode(data())
            buf = Split(strResult, vbCrLf)
            For j = LBound(buf) To UBound(buf)
              If Left(buf(j), 1) = "C" Then
                Debug.Print buf(j)
                '      {X座標のデータがあれば Col を更新}
                If InStr(buf(j), ";X") > 0 Then
                ':Xから後ろを抽出する、最後の引数は大きめに設定している
                  L2 = Mid(buf(j), InStr(buf(j), ";X") + 2, Len(buf(j)))
                  If InStr(L2, ";") > 0 Then L2 = Mid(L2, 1, InStr(L2, ";") - 1)
                  myCol = StartCol - StartX + CLng(L2)
                  myCol = CLng(L2)
                End If
                '{Y座標のデータがあれば Row を更新}
                If InStr(buf(j), ";Y") > 0 Then
                  L2 = Mid(buf(j), InStr(buf(j), ";Y") + 2, Len(buf(j)))
                  If InStr(L2, ";") > 0 Then L2 = Mid(L2, 1, InStr(L2, ";") - 1)
                  myRow = StartRow - StartY + CLng(L2)
                  myRow = CLng(L2)
                End If
              '{データがあるときには読み出してシートに書き込む}
                If (InStr(buf(j), ";K") > 0) And (myRow > 0) And (myCol > 0) Then
                  myData = Mid(buf(j), InStr(buf(j), ";K") + 2, Len(buf(j)))
                  If InStr(myData, ";") > 0 Then _
                    myData = Mid(myData, 1, InStr(myData, ";") - 1)
                  If Left(myData, 1) = """" Then _
                    myData = Mid(myData, 2, Len(myData) - 2)
                  Sheets(2).Cells(myRow, myCol) = myData
                End If
              End If
            Next j
        End If
    End If
End Sub

'SHIFT-JISからUnicodeに変換する
Private Function AnsiToUnicode(ByRef strAnsi() As Byte) As String
On Error GoTo ErrHandler
    Dim lngSize   As Long
    Dim strBuf    As String
    Dim lngBufLen As Long
    Dim lngRtnLen As Long

    lngSize = UBound(strAnsi) + 1
    lngBufLen = lngSize * 2 + 10
    strBuf = String$(lngBufLen, vbNullChar)
    lngRtnLen = MultiByteToWideChar(0, 0, strAnsi(0), lngSize, StrPtr(strBuf), lngBufLen)
    If lngRtnLen > 0 Then
        AnsiToUnicode = Left$(strBuf, lngRtnLen)
    End If
ErrHandler:
End Function