none
クリップボードからのpasteによる貼り付けが「高頻度に」失敗する RRS feed

  • 質問

  • 下記は、ExcelのVBAで、DataObject を用いて、クリップボードに格納したデータ(テキスト)をpaste によってセルに貼り付けるプログラムですが、最後の方の ActiveSheet.Paste Cells(i, 1) で高頻度でエラーとなります。

    ただし、やっかいなことに、エラーにならずにうまく行く場合もあります。実は、エラーになったとき、デバッグモードで、F8によって、手動でステップを実行すると、必ずうまく行きます。したがって、コードの誤りと言うよりは、言語の仕様(バグ)かも知れません。

    たいへん困っているので、実行時にこのエラーを回避する方法を教えていただければ、ありがたいです(デバッグ時F8では正常動作という所にヒントがありそうですが・・・)。

    '*****< クリップボードからの貼り付け >*****
    Sub PasteFromClipboad()
        Dim ClipBoadBuf As New DataObject
        Dim i As Integer
        Cells.Clear
        For i = 1 To 10
            With ClipBoadBuf
                .SetText "貼り付けるテキスト-その" & i   'テキストを DataObject に格納する
                .PutInClipboard                           'DataObjectのテキストをクリップボードに格納する
            End With
            ActiveSheet.Paste Cells(i, 1)                 '表示シートの選択セルにテキストを貼り付ける
        Next
    End Sub

        
    • 編集済み DemoTra21 2015年3月6日 5:22
    2015年3月6日 5:05

すべての返信

  • こんにちは。

    VBAの環境(Officeのバージョン、OSバージョンなど)を記載してください。
    また、「失敗」について具体的に記載してください。

    (追記)
    Excel2010で確認しましたが、一度もエラーが発生しませんでした。
    どういうエラーが発生するんでしょうか。
    2015年3月6日 5:33
    モデレータ
  • クリップボードを監視するようなアプリが他にいて、そいつが邪魔している気がしますね。
    クリーンな環境(たとえば、WindowsとExcelしか入っていない)などで実行してみては。


    jzkey

    2015年3月6日 6:14
  • Tak1wa さん、ご回答ありがとうございます。

    ● 実行環境は下記の通りです。
    -----
    Windows 7 Professional
    Service Pack 1 ビルド7601
    -----
    Microsoft Office Professional Plus 2010
    Microsoft Excel バージョン: 14.0.7143.5000 (32ビット)
    -----
    Microsoft Visual Basic for Application 7.0
    Verstion 1628   VBA: Retail 7.0.1628  Forms3: 14.0.7140.5001

    ● また、エラーメッセージは下記の通りです。
    -------------------------------------------------------
    実行時エラー'1004'
    Worksheet クラスの Paste メソッドが失敗しました。
    -------------------------------------------------------

    上記エラーメッセージの後、デバッグモードに入って、ステップ実行を行うと、
    paste が正常に実行されます。

    再現性がないエラーほどやっかいなものはありませんが、ネットを検索したところ、
    同様のエラーの方がいらっしゃるようです。そこでは「Active... が問題では」と
    なっていましたが、"Active"を使わず、シート名を指定したりしても症状は変わりま
    せん。

    症状が出ない方には、回答のしようがないかも知れませんね。すみません。

    しかし、こうした現象の存在自体が不可解でなりません。paste という基本動作が
    いったいどういう仕様で実装されているのか・・・。せめてVBA開発担当の方には
    知っていただきたい気がします。

    2015年3月6日 7:18
  • 再現が取れないことには難しいので、
    まずは切り分けですね。

    新規ブックを作成し、セルの書式設定や保護設定を一切せずに
    ご提示頂いたペーストのコードのみを実装した場合でも発生しますでしょうか。
    2015年3月6日 7:50
    モデレータ
  • jzkey さん、ご助言ありがとうございます。

    WindowsとExcelだけ、とまでは行きませんが、外せるものはすべて外して実行しても、症状変わりません・・・。

    この状況だと、「クリップボードを監視するようなアプリ」で一番あやしいのは Office ということになりそうです。

    ちなみに、上記プログラムで、1回も貼り付けできないとき、2回できるとき、3回できるとき、10回できるときなど、

    実行するたびにどこで失敗するかがランダムに異なり、その条件が何なのか、さっぱり見当がつきません。

    仮に他の方(かた)のPCで、ほとんど起こらないとすると、私の Excel ないし Office が、壊れているのでしょうか。

    迷宮入りっぽいですね。

    2015年3月6日 8:08
  • 少し調べてみました。
    先の投稿のとおり新規作成ブックでシンプルなペースト処理のみで失敗するのであれば環境依存の可能性が高いですね。
    失敗しないのであればペースト処理以外が原因の可能性があります。

    失敗した場合はどこに問題があるのか、以下を試してみるのが良いと思います。

    1.http://www.mrexcel.com/forum/excel-questions/454348-error-1004-paste-method-worksheet-class-failed.html

    Private Sub CommandButton1_Click()
        Dim ClipBoadBuf As New DataObject
        Dim i As Integer
        Cells.Clear
        For i = 1 To 10
            With ClipBoadBuf
                .SetText "貼り付けるテキスト-その" & i   'テキストを DataObject に格納する
                .PutInClipboard                           'DataObjectのテキストをクリップボードに格納する
            End With
            'START==========
            DoEvents
            Sleep 75
            DoEvents
            'END==========
            ActiveSheet.Paste Cells(i, 1)                 '表示シートの選択セルにテキストを貼り付ける
        Next
    End Sub

    別途以下の定義が必要です。

    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

    2.形式を指定して貼り付けに変更

    'ActiveSheet.Paste Cells(i, 1)
    Cells(i, 1).PasteSpecial


    ステップ実行でうまく行くということはおそらく1.の方法であればうまく行く気がします。(クリップボードに格納できていない状態でペーストしてしまっている)

    2015年3月6日 9:44
    モデレータ
  • クリップボードは、全てアプリが共用するものです。
    ですから、入れたものが他のアプリで書き換えられる事は普通にあり得ます。
    また、あなたの書いたプログラムが、クリップボードを利用する操作に悪影響を及ぼすことも有るでしょう。

    VBAに限らず、ユーザによる操作やその補助以外の目的でクリップボードを使うべきではありません。

    • 編集済み hihijiji 2015年3月7日 2:51
    2015年3月7日 2:09
  • Tak1wa さん、ありがとうございます。

    結論から言えば、DoEvents が効くようです。

    サンプルコード程度のテキストの格納なら、必ずしも sleep は無くても、DoEvents でワンテンポ置くだけで、ほぼうまく行くようです。

    つまり、ご指摘の通り、APIによるクリップボードへの格納動作が、その次のVBAによる貼り付け動作に追いついていかなかったことが原因のようです。

    また、.PutInClipboard (クリップボードに格納動作) 自体も希に失敗するので、その前の.SetText に間に合わないことがあるようです。

    なお、サンプルコードでの paste の失敗は、環境の異なる他のPCでも確認できたので、同じエラーは割と頻繁に起こるものとみられます。

    VBAの機能を補うためには、ときに API を使わざるを得ないわけですが、動作のタイミング調整には気をつけないといけませんね。勉強になりました。

    Tak1wa さん、有益なご助言本当にありがとうございました。

    (もうお判りのとおり、Cells(i, 1).PasteSpecial の方は×でした。)



    • 編集済み DemoTra21 2015年3月8日 13:55
    2015年3月8日 13:52