Excel VBAの覚え書(クリップボード編)~Microsoft FormsのDataObjectによるClipboard操作

2024-01-07

Excelでクリップボード操作を行う場合、Microsoft Formsで提供されている、DataObjectを使用するのが便利です。

もともとクリップボードはWindowsが提供している機能ですので、Excel VBAでクリップボードを取扱う場合も、Windows APIを使用すればきめ細かな操作が可能ですが、使用方法が煩雑なので、通常はDataObjectで充分だと思います。

■Microsoft Formsの概要

Excelのワークシート上で使用できる標準的なフォーム(ユーザ・フォーム、コマンド・ボタン、テキスト・ボックス等の各種コントロール)には、フォーム・コントロールとActveXコントロールの2種類があり、ActiveXコントロールを提供しているのがMicrosoft Formsです。

[開発]タブで[挿入]をクリックすると、下図のようなコントロールの一覧が表示されますが、下半分にある「ActiveX コントロール」がMicrosoft Formsに対応しており、1段目には「コマンド・ボタン」「コンボ・ボックス」「チェック・ボックス」「リスト・ボックス」「テキスト・ボックス」「スクロール・バー」、2段目に「スピン・ボタン」「オプション・ボタン」「ラベル」「イメージ」「トグル・ボタン」「コントロールの選択」といったボタンが並んでいます。

DataObjectはコントロールではありませんので、この一覧には表示されておらず、プログラムの中でインスタンス化して使用します。

■DataObjectの詳細

DataObjectで提供されている機能と使用方法を説明します。

DataObjectのメソッド

DataObjectで提供されているメソッドは、下表の通りです(プロパティはありません)。
⇒詳細はMicrosoftのサイト(Microsoft Forms)を参照して下さい。

(DataObjectのメソッド)

Clearメソッド
説明 DataObject上にある全てのデータを削除する
定義 Sub Clear()
GetFormatメソッド
説明 DataObject上にあるデータの形式を示す整数値を取得する

(※)Formatで指定したデータが存在する場合、Trueを返す

定義 Function GetFormat(Format As Variant) As Boolean
GetFromClipboardメソッド
説明 クリップボードからDataObjectにデータをコピーする
定義 Sub GetFromClipboard()
GetTextメソッド
説明 指定した形式を使用して、DataObjectからテキスト文字列を取得する
定義 Function GetText([Format As Variant]) As String
PutInClipboardメソッド
説明 DataObjectからクリップボードにデータを移動する
定義 Sub PutInClipboard()
SetTextメソッド
説明 指定した形式を使用して、テキスト文字列をDataObjectにコピーする
定義 Sub SetText(Text As String, [Format As Variant])
StartDragメソッド
説明 DataObjectのドラッグ・アンド・ドロップ操作を開始する

(※)fmDropEffect列挙体の値は、以下の通り。
fmDropEffectNone(0):コピーまたは移動しない
fmDropEffectCopy(1):コピーする
fmDropEffectMove(2):移動する
fmDropEffectCopyOrMove(3):コピーまたは移動する

定義 Function StartDrag(OKEffect As Variant) As fmDropEffect

(※)Formatの値は、以下の通り。
1:テキスト形式
文字列または1以外の整数:ユーザー定義のDataObject形式(SetTextメソッドで設定した値)

DataObjectを使用するための事前準備

DataObjectを使用するための事前準備は、以下の3ステップです。
⇒オブジェクトを使用するための事前準備とオブジェクトブラウザによる調査方法については、Excel VBAでオブジェクト指向プログラミング(事前準備編)を参照して下さい。

①ライブラリの参照設定
Visual Basic Editor(VBE)のファイルメニューから[ツール]-[参照設定]を選択し、

参照設定ダイアログで[参照]ボタンを押下し、使用する「FM20.DLL(※)」を指定し、

Microsoft Forms 2.0 Object Libraryのチェックボックスにチェックを入れ、[OK]ボタンを押下。

(※)64ビット版は「C:\Windows\SysWOW64\FM20.DLL」、32ビット版は「C:\Windows\System32\FM20.DLL」を選択します。
なお、ActiveXコントロールを使用すると、自動的に参照設定されます。

②オブジェクト変数の定義
プログラムの宣言部でオブジェクト変数を定義。

  1. Dim cb As DataObject

③インスタンスの生成
プログラムの処理部でインスタンスを生成。

  1. Set cb = New DataObject
  2. 'ここにオブジェクトを使用した処理を記述
  3. Set cb = Nothing

■DataObjectの使用方法

基本的な使用法は、以下の通りです。

クリップボードにテキストを設定

SetTextメソッドでDataObjectにテキストをコピーし、PutInClipboardメソッドでクリップボードに移動します。

  1. cb.SetText 文字列
  2. cb.PutInClipboard

Format引数を省略した場合は『1(テキスト)』が仮定されますので、「cb.SetText 文字列」は「cb.SetText 文字列, 1」と同義です。

クリップボードからテキストを取得

GetFromClipboardメソッドでクリップボードからDataObjectにデータをコピーし、GetTextメソッドでDataObjectからテキストを取得します。

  1. cb.GetFromClipboard
  2. 文字列 = cb.GetText

DataObjectにテキストデータが入っていることを確認し、データがある場合だけテキストを取得したい場合は、以下のようにコーディングします。

  1. cb.GetFromClipboard
  2. If cb.GetFormat(1) = True Then
  3.     文字列 = cb.GetText
  4. End If

Formatを明示したい場合は、「文字列 = cb.GetText」を「文字列 = cb.GetText(1)」のようにコーディングします。

■クリップボード関連のデータ形式

クリップボード関連データの形式については、DataObject、Excel、Windowsでそれぞれ取扱いが異なりますので、順に説明します。

DataObjectのデータ形式~GetFormatメソッド

DataObjectで扱えるデータはテキストのみですが、SetTextメソッドのFormat引数に1以外の値を指定することにより、DataObjectに複数のデータを登録することが可能です。

  1. cb.SetText 文字列, 2
  2. cb.SetText 文字列, 3
  3. 文字列 = cb.GetText(2)
  4. 文字列 = cb.GetText(3)

SetTextメソッドのFormat引数に指定した値がデータ形式を表しますので、GetTextメソッドのFormat引数でデータ形式を指定すれば、該当するデータを取出すことができますが、PutInClipboardメソッドでクリップボードに登録すると、データ形式を表す値が別の値に変換されてしまいます(詳細は次項を参照して下さい)。

DataObjectに登録されているデータ形式を確認するためには、GetFormatメソッドを使用しますが、Format引数を省略できないため、「実行結果がTrueであれば、そのデータ形式が登録されている」と判断するしかありません。

Excelにおけるクリップボードのデータ形式~ClipboardFormatsプロパティ

Excelでクリップボード操作を行う際、通常はRangeオブジェクト等のCopyメソッドやCutメソッドを使用しますが、この場合、セルに入力された値(Valueプロパティ)だけではなく、さまざまな形式のデータがクリップボードに格納されます。

ApplicationオブジェクトのClipboardFormatsプロパティを参照すると、クリップボードに登録された全データの形式を参照することができます。
以下のサンプル・プログラムを実行すると、ExcelシートのA列にクリップボードに登録されているデータ形式が一覧で表示されます。

  1. Dim Tbl As Variant
  2. Dim cnt As Integer
  3. Dim i As Integer
  4. Private Sub Sample1()
  5.     Set sht = ActiveSheet
  6.     Tbl = Application.ClipboardFormats
  7.     cnt = 0
  8.     For i = LBound(Tbl) To UBound(Tbl)
  9.         cnt = cnt + 1
  10.         sht.Cells(cnt, 1) = Tbl(i)
  11.     Next i
  12. End Sub

Excelの標準データ形式については、下表の通りXlClipboardFormat列挙体で定義されています。

(XlClipboardFormat列挙体)

名前
XlClipboardFormat列挙体
xlClipboardFormatText 0
xlClipboardFormatVALU 1
xlClipboardFormatPICT 2
xlClipboardFormatPrintPICT 3
xlClipboardFormatDIF 4
xlClipboardFormatCSV 5
xlClipboardFormatSYLK 6
xlClipboardFormatRTF 7
xlClipboardFormatBIFF 8
xlClipboardFormatBitmap 9
xlClipboardFormatWK1 10
xlClipboardFormatLink 11
xlClipboardFormatDspText 12
xlClipboardFormatCGM 13
xlClipboardFormatNative 14
xlClipboardFormatBinary 15
xlClipboardFormatTable 16
xlClipboardFormatOwnerLink 17
xlClipboardFormatBIFF2 18
xlClipboardFormatObjectLink 19
xlClipboardFormatBIFF3 20
xlClipboardFormatEmbeddedObject 21
xlClipboardFormatEmbedSource 22
xlClipboardFormatLinkSource 23
xlClipboardFormatMovie 24
xlClipboardFormatToolFace 25
xlClipboardFormatToolFacePICT 26
xlClipboardFormatStandardScale 27
xlClipboardFormatStandardFont 28
xlClipboardFormatScreenPICT 29
xlClipboardFormatBIFF4 30
xlClipboardFormatObjectDesc 31
xlClipboardFormatLinkSourceDesc 32
xlClipboardFormatBIFF12 63

Windowsにおけるクリップボードのデータ形式~EnumClipboardFormats関数、GetClipboardFormatName関数

WindowsのAPIを使用してクリップボード操作を行う場合は、user32.dllで提供されているAPIを使用します。

EnumClipboardFormats関数を使用すると、クリップボードに登録された全データの形式を参照することができます。
Windows標準のデータ形式については、下表の通り定義されています(Excelの標準データ形式とは、値が異なります)が、これ以外のデータ形式については、GetClipboardFormatName関数でデータ形式の名前を取得することができます。

(Windows標準のデータ形式)

名前
Windows標準のデータ形式
CF_TEXT 1
CF_BITMAP 2
CF_METAFILEPICT 3
CF_SYLK 4
CF_DIF 5
CF_TIFF 6
CF_OEMTEXT 7
CF_DIB 8
CF_PALETTE 9
CF_PENDATA 10
CF_RIFF 11
CF_WAVE 12
CF_UNICODETEXT 13
CF_ENHMETAFILE 14
CF_HDROP 15
CF_LOCALE 16
CF_DIBV5 17
CF_OWNERDISPLAY &H80
CF_DSPTEXT &H81
CF_DSPBITMAP &H82
CF_DSPMETAFILEPICT &H83
CF_DSPENHMETAFILE &H8E
CF_PRIVATEFIRST &H200
CF_PRIVATELAST &H2FF
CF_GDIOBJFIRST &H300
CF_GDIOBJLAST H3FF

■サンプル・プログラム~クリップボード関連のデータ形式を一覧表示する処理

DataObject経由でクリップボードにデータを登録したうえ、A列にDataObjectのデータ形式、B列にExcelにおけるクリップボードのデータ形式、C列にWindowsにおけるクリップボードのデータ形式を表示するExcelツールです。

メイン・プロシジャ

行番号10~11で文字列をDataObjectとクリップボードに登録した後、行番号13~19でDataObjectのデータ形式、行番号21~26でExcelにおけるクリップボードのデータ形式、行番号28~33でWindowsにおけるクリップボードのデータ形式を表示しています。

行番号28~33の処理の中では、行番号28でGetFormat関数(※)を呼び出し、戻って来たvbLf区切りの文字列をSplit関数で配列に格納したうえ、行番号30~33で配列の各要素をExcelシートに転記しています。

(※)GetFormat関数は自作の関数ですが、Windows APIを使用しているため、標準モジュール内に記述する必要があります。

  1. Dim sht As Worksheet
  2. Dim cb As DataObject
  3. Dim Tbl As Variant
  4. Dim cnt As Integer
  5. Dim i As Integer
  6. Private Sub Sample2()
  7.     Set sht = ActiveSheet
  8.     Set cb = New DataObject
  9.     cb.SetText “test"
  10.     cb.PutInClipboard
  11.     'DataObjectのデータ形式を表示
  12.     cnt = 0
  13.     For i = 0 To 255
  14.         If cb.GetFormat(i) = True Then
  15.             cnt = cnt + 1
  16.             sht.Cells(cnt, 1) = i
  17.         End If
  18.     Next i
  19.     'Excelにおけるクリップボードのデータ形式を表示
  20.     Tbl = Application.ClipboardFormats
  21.     cnt = 0
  22.     For i = LBound(Tbl) To UBound(Tbl)
  23.         cnt = cnt + 1
  24.         sht.Cells(cnt, 2) = Tbl(i)
  25.     Next i
  26.     'Windowsにおけるクリップボードのデータ形式を表示
  27.     Tbl = Split(GetFormat, vbLf)
  28.     cnt = 0
  29.     For i = LBound(Tbl) To UBound(Tbl)
  30.         cnt = cnt + 1
  31.         sht.Cells(cnt, 3) = Tbl(i)
  32.     Next i
  33.     Set cb = Nothing
  34.     Set sht = Nothing
  35. End Sub

GetFormat関数

GetFormat関数はWindows APIを使用して、Windowsにおけるクリップボードのデータ形式を全て取得し、vbLf区切りの文字列にして返す関数です。

行番号14でクリップボードをオープンし、行番号18~56の繰返し処理を行い、行番号57でクリップボードをクローズしています。

繰返し処理の中は、行番号19でデータ形式を取得し、行番号22~47でWindows標準のデータ形式、行番号50でWindows標準でないデータ形式の名称を取得しています。

  1. Option Explicit
  2. Declare Function OpenClipboard Lib “user32.dll" _
  3.         (ByVal hWndNewOwner As Long) As Long
  4. Declare Function EnumClipboardFormats Lib “user32.dll" _
  5.         (ByVal format As Long) As Long
  6. Declare Function GetClipboardFormatName Lib “user32.dll" Alias “GetClipboardFormatNameA" _
  7.         (ByVal format As Long, ByVal lpszFormatName As String, ByVal cchMaxCount As Long) As Long
  8. Declare Function CloseClipboard Lib “user32.dll" () As Long
  9. Dim rc As Long
  10. Dim fc As Long
  11. Dim buf As String
  12. Function GetFormat() As String
  13.     rc = OpenClipboard(Application.Hwnd)
  14.     If rc <> 0 Then
  15.         GetFormat = “"
  16.         fc = 0
  17.         Do
  18.             fc = EnumClipboardFormats(fc)
  19.             If fc <> 0 Then
  20.                 Select Case fc
  21.                     Case 1: buf = “CF_TEXT"
  22.                     Case 2: buf = “CF_BITMAP"
  23.                     Case 3: buf = “CF_METAFILEPICT"
  24.                     Case 4: buf = “CF_SYLK"
  25.                     Case 5: buf = “CF_DIF"
  26.                     Case 6: buf = “CF_TIFF"
  27.                     Case 7: buf = “CF_OEMTEXT"
  28.                     Case 8: buf = “CF_DIB"
  29.                     Case 9: buf = “CF_PALETTE"
  30.                     Case 10: buf = “CF_PENDATA"
  31.                     Case 11: buf = “CF_RIFF"
  32.                     Case 12: buf = “CF_WAVE"
  33.                     Case 13: buf = “CF_UNICODETEXT"
  34.                     Case 14: buf = “CF_ENHMETAFILE"
  35.                     Case 15: buf = “CF_HDROP"
  36.                     Case 16: buf = “CF_LOCALE"
  37.                     Case 17: buf = “CF_DIBV5"
  38.                     Case &H80: buf = “CF_OWNERDISPLAY"
  39.                     Case &H81: buf = “CF_DSPTEXT"
  40.                     Case &H82: buf = “CF_DSPBITMAP"
  41.                     Case &H83: buf = “CF_DSPMETAFILEPICT"
  42.                     Case &H8E: buf = “CF_DSPENHMETAFILE"
  43.                     Case &H200: buf = “CF_PRIVATEFIRST"
  44.                     Case &H2FF: buf = “CF_PRIVATELAST"
  45.                     Case &H300: buf = “CF_GDIOBJFIRST"
  46.                     Case &H3FF: buf = “CF_GDIOBJLAST"
  47.                     Case Else
  48.                     buf = String(255, vbNullChar)
  49.                     rc = GetClipboardFormatName(fc, buf, 254&)
  50.                     buf = Left(buf, rc)
  51.                 End Select
  52.                 GetFormat = GetFormat & fc & “:" & buf & vbLf
  53.             End If
  54.             DoEvents
  55.         Loop Until fc = 0
  56.         rc = CloseClipboard()
  57.     End If
  58. End Function

実行結果(1)~DataObject経由でクリップボードに登録した場合のデータ形式

前掲のサンプル・プログラムを実行すると、以下のような結果が表示されます。

1 0 49161:DataObject
13 44 1:CF_TEXT
13:CF_UNICODETEXT
49171:Ole Private Data
16:CF_LOCALE
7:CF_OEMTEXT

実行結果(2)~直接クリップボードに登録した場合のデータ形式

前掲のサンプル・プログラム中、行番号10~11のDataObjectに登録する処理をコメント・アウトしたうえ、Excelシートの任意のセルをCtrl+Cで直接クリップボードに登録してプログラムを実行すると、以下のような結果が表示されます。

0 49161:DataObject
2 14:CF_ENHMETAFILE
4 3:CF_METAFILEPICT
5 2:CF_BITMAP
6 49627:Biff12
7 49604:Biff8
8 49606:Biff5
9 4:CF_SYLK
11 5:CF_DIF
12 49625:XML Spreadsheet
14 49322:HTML Format
17 13:CF_UNICODETEXT
19 1:CF_TEXT
22 49607:Csv
23 49624:Hyperlink
31 49450:Rich Text Format
32 49163:Embed Source
33 49156:Native
42 49155:OwnerLink
44 49166:Object Descriptor
45 49165:Link Source
50 49167:Link Source Descriptor
58 49603:Link
63 129:CF_DSPTEXT
49154:ObjectLink
49171:Ole Private Data
16:CF_LOCALE
7:CF_OEMTEXT
8:CF_DIB
17:CF_DIBV5

国本温子(著),緑川吉行(著),できるシリーズ編集部(著)
出版社:インプレス
発売日:2022/3/23
単行本(ソフトカバー):A5判/912ページ

大村あつし(著),古川順平(著)
出版社:技術評論社
発売日:2021/1/9
単行本(ソフトカバー):A5判/800ページ

高橋宣成(著)
出版社:技術評論社
発売日:2019/11/25
単行本(ソフトカバー):B5変形判/576ページ

覚え書

Posted by hides