VBA技術解説
VBAでクリップボードへ文字列を送信・取得する3つの方法

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
公開日:2023-12-07 最終更新日:2023-12-07

VBAでクリップボードへ文字列を送信・取得する3つの方法


VBAでデータをクリップボードに送信したり取得したり、そういう要望は結構多くあります。
このVBAでクリップボードを扱う方法を3通り紹介します。
ただし、データといってもここではあくまで文字列データ(テキストデータ)だけを扱います。


当サイトでは、クリップボードを扱うVBAは以下で紹介しています。

クリップボードに2次元配列を作成してシートに貼り付ける|VBA技術解説
・クリップボードのデータ取得/クリップボードへデータ送信 ・エクセルの行・列のデータ ・クリップボードに2次元配列を作成してシートに貼り付けるVBA ・クリップボードに2次元配列の最後に

今回はVBAでクリップボードを扱う方法だけに焦点をあてて、そのVBAの3つの方法についての紹介記事となります。
それぞれのVBAは決して目新しいものでも、私が特段の創意工夫をしたものでもありません。
あくまで、3つの方法のまとめ記事になります。



VBAの3つの方法について

1. DataObject を使う方法
2. TextBox を使う方法
3. Win32 API を使う方法

VBAでは、DataObjectを使う方法が一番良く使われていると思います。
しかしこの方法では、環境によっては上手く動かないとか文字化けが発生するとかの報告があるようです。

これに対して、TextBoxを使う方法が良く紹介されていて、これでうまくいったという報告も多いようです。
なぜTextBoxなのかと、ちょっと不思議な感じですが、要はクリップボードに対応したメソッドが装備されているコントロールを使うという事ですね。

最後はWin32 API、これならもちろん良いのですが、いかんせん大げさです(笑)
VBAコードはコピーで使えるので長さは気にしなくても良いとはいえ、もうちょっと簡単なコードなら良かったのですが・・・

以下では、
クリップボードへ文字列を送信するSubを、
SetClipboard
クリップボードの文字列を取得するFunctionを、
GetClipboard
このように共通の命名にしています。
使い方はそのまま普通に使ってもらえれば良いです。

Sub test()
  Call SetClipboard(Range("A1"))
  Range("A2") = GetClipboard
End Sub


1. DataObjectを使うVBA

'クリップボードへ文字列を送信
Public Sub SetClipboard(ByVal aText As String)
  With New DataObject
    .SetText aText
    .PutInClipboard
  End With
End Sub

'クリップボードの文字列を取得
Public Function GetClipboard() As String
  On Error Resume Next
  With New DataObject
    .GetFromClipboard
    GetClipboard = .GetText
  End With
End Function

参照設定:Microsoft Forms 2.0 Object Library
参照設定の「参照可能なライブラリ ファイル」に「Microsoft Forms 2.0 Object Library」が表示されていない場合は、
挿入でユーザーフォームを作成すると自動的に参照設定されます。

もしくは、New DataObjectを以下に変更してください。
CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")


2. TextBox を使うVBA

'クリップボードへ文字列を送信
Private Sub SetClipboard(ByVal aText As String)
 With CreateObject("Forms.TextBox.1")
  .MultiLine = True
  .Text = aText
  .SelStart = 0
  .SelLength = .TextLength
  .Copy
 End With
End Sub

'クリップボードの文字列を取得
Private Function GetClipboard() As String
 With CreateObject("Forms.TextBox.1")
  .MultiLine = True
  If .CanPaste = True Then .Paste
  GetClipboard = .Text
 End With
End Function

この方法については、以下のブログが古くから紹介している方法です。
[VBA]DataObjectを使ったクリップボード操作が上手くいかない場合の対処法


3. Win32 API を使うVBA

'Win32 API 宣言
Private Declare PtrSafe Function OpenClipboard Lib "user32.dll" (ByVal hWnd As LongPtr) As LongPtr
Private Declare PtrSafe Function EmptyClipboard Lib "user32.dll" () As LongPtr
Private Declare PtrSafe Function CloseClipboard Lib "user32.dll" () As LongPtr
Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32.dll" (ByVal wFormat As LongPtr) As LongPtr
Private Declare PtrSafe Function GetClipboardData Lib "user32.dll" (ByVal wFormat As LongPtr) As LongPtr
Private Declare PtrSafe Function SetClipboardData Lib "user32.dll" (ByVal wFormat As LongPtr, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32.dll" (ByVal wFlags As LongPtr, ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalLock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalSize Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyW" (ByVal lpString1 As LongPtr, ByVal lpString2 As LongPtr) As LongPtr

'クリップボードへ文字列を送信
Public Sub SetClipboard(ByVal aText As String)
  Dim iStrPtr As LongPtr
  Dim iLen As LongPtr
  Dim iLock As LongPtr
  Const GMEM_MOVEABLE As LongPtr = &H2
  Const GMEM_ZEROINIT As LongPtr = &H40
  Const CF_UNICODETEXT As LongPtr = &HD
  OpenClipboard 0&
  EmptyClipboard
  iLen = LenB(aText) + 2&
  iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen)
  iLock = GlobalLock(iStrPtr)
  lstrcpy iLock, StrPtr(aText)
  GlobalUnlock iStrPtr
  SetClipboardData CF_UNICODETEXT, iStrPtr
  CloseClipboard
End Sub

'クリップボードの文字列を取得
Public Function GetClipboard() As String
  Dim iStrPtr As LongPtr
  Dim iLen As LongPtr
  Dim iLock As LongPtr
  Dim sUniText As String
  Const CF_UNICODETEXT As LongPtr = 13&
  OpenClipboard 0&
  If IsClipboardFormatAvailable(CF_UNICODETEXT) Then
    iStrPtr = GetClipboardData(CF_UNICODETEXT)
    If iStrPtr Then
      iLock = GlobalLock(iStrPtr)
      iLen = GlobalSize(iStrPtr)
      sUniText = String$(CLng(iLen \ 2& - 1&), vbNullChar)
      lstrcpy StrPtr(sUniText), iLock
      GlobalUnlock iStrPtr
    End If
    GetClipboard = sUniText
  End If
  CloseClipboard
End Function

上記のVBAは、
Docs / Office VBA リファレンス / Access / 概念 / Windows API /
クリップボードに情報を送信する
https://docs.microsoft.com/ja-jp/office/vba/access/concepts/windows-api/send-information-to-the-clipboard
ここに掲載されているものを、64bitで使えるように変更したものです。




同じテーマ「マクロVBA技術解説」の記事

ユーザーに絶対に停止させたくない場合のVBA設定
印刷範囲の設定・印刷範囲のクリア
VBAの省略可能な記述について
VBAのVariant型について
VBAのインデントについて
VBAの演算子まとめ(演算子の優先順位)
列幅不足による###表示や指数表示を判定する
OneDrive使用時のThisWorkbook.Pathの扱い方
セル個数を返すRange.CountLargeプロパティとは
画像「セルに配置」のVBAについて(365の新機能)
VBAでクリップボードへ文字列を送信・取得する3つの方法


新着記事NEW ・・・新着記事一覧を見る

無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)
VBAでクリップボードへ文字列を送信・取得する3つの方法|VBA技術解説(2023-12-07)
難しい数式とは何か?|エクセル雑感(2023-12-07)
スピらない スピル数式 スピらせる|エクセル雑感(2023-12-06)
イータ縮小ラムダ(eta reduced lambda)|エクセル入門(2023-11-20)
PIVOTBY関数(縦軸と横軸でグループ化して集計)|エクセル入門(2023-11-19)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.並べ替え(Sort)|VBA入門
8.条件分岐(IF)|VBA入門
9.マクロとは?VBAとは?VBAでできること|VBA入門
10.セルのクリア(Clear,ClearContents)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ