こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

SendKeys "^V", True(貼り付け)のミス

エクセルシートに設定したリアルタイム関数(楽天マーケットスピード)でデータを取得し、フィルターをかけてメモパッドに表示しています。
 
エクセルでクリップボードに格納したものを下記のプログラムで[Ctrl]+[V]キーを転送しています。

問題は[Ctrl]+[V]キーがしばしば他のアプリケーションのカーソルに転送されてしまいメモパッドがパスされてしまいます。

AppActivateが効かないのか分かりませんが対策を是非ご教示下さい。

Sub NotePad書き出し()
Dim myPath As String
dim y as long
If nsw <> 0 Then GoTo 即貼り付け'メモ帳起動は一度だけ

nsw = 1
myPath = ActiveWorkbook.Path & "\"

'メモ帳を起動する
myID = Shell("Notepad.exe", vbNormalFocus)
For y = 1 To 3000 'notePadが開く余裕を3秒間取る
DoEvents
Sleep 1
Next y

即貼り付け:

'[ENTER]キーを転送して1行空ける
SendKeys "{ENTER}", True

'メモ帳をアクティブにする
AppActivate myID

'[Ctrl]+[V]キーを転送してコピーした内容を貼り付ける
SendKeys "^V", True

'コピーモードを解除する
Application.CutCopyMode = False
End Sub

投稿日時 - 2005-10-01 13:45:16

QNo.1684946

すぐに回答ほしいです

質問者が選んだベストアンサー

こんにちは。Wendy02です。

>1.テキストウィンドウのスクロールを常に最後備が見られるように下ろしてお


 以下を見ていただければ分ります。旧式のテクニックです。

>2.エクセルの時刻書式のデータhh:mm:ss AM or PMをそのまま表示。シリアル
>に変換されてしまうので・・

本来、見たままをテキストに出力する時は、RangeオブジェクトのValueプロパティではなくて、Text プロパティを使います。

'<標準モジュール>
'--------------------------------------------
Option Explicit
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
   ByVal lpClassName As String, _
   ByVal lpWindowName As String) As Long

Sub SampleMacro2()
Dim Fno As Integer
Dim rtn As Long
Dim strClassName As String
Dim ServiceSet As Object
Dim Process As Object
Dim myRng As Range
Dim buf As String
Dim j As Long, i As Long
Dim myID As Long
Dim Fname As String
Dim 適格銘柄開始行 As Long
Dim 適格銘柄終了行 As Long
'-------------------------
'設定 (ファイル名)
Fname = ThisWorkbook.Path & "\myData.txt"
'-------------------------

strClassName = "NotePad"
rtn = FindWindow(strClassName, vbNullString)
If rtn <> 0& Then
 Set ServiceSet = _
GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("select * from Win32_Process where Name='NOTEPAD.EXE'")
 For Each Process In ServiceSet
   Process.Terminate
 Next
 Set ServiceSet = Nothing
End If
'
適格銘柄開始行 = 1
適格銘柄終了行 = 10

Fno = FreeFile()

'最初からアペンドモード

Open Fname For Append As #Fno

Set myRng = Range("A" & 適格銘柄開始行 & ":I" & 適格銘柄終了行)
For i = 1 To myRng.Rows.Count
 For j = 1 To myRng.Columns.Count
   buf = buf & vbTab & myRng.Cells(i, j).Text '変更
 Next j
 Print #Fno, Mid$(buf, 2)
 buf = ""
Next i
Close #Fno
If FileLen(Fname) > 1 Then
 myID = Shell("Notepad.exe " & Fname, vbNormalFocus)
 CreateObject("WScript.Shell").SendKeys "^{END}"
Else
 MsgBox "出力できませんでした。", vbCritical
End If
End Sub
'----------------------------------------------

私は、株式のほうは、作ったことがないので、あまりお役には立てていないような気がしますが、ある程度、頭の中でイメージはあります。しかし、専用ツールを使いこなしたほうが、安定しているかもしれません。

それと 「1.複数シートを使って計算していますが、~3.現在所定」のまでの問題は、スプレッドシートコントロールを使ってもよいかもしれませんね。スプレッドシートコントロールは、ユーザーフォームですから、Excel2000以降なら、開いたまま、問題なくExcel本体とと行き来できます。

投稿日時 - 2005-10-10 08:54:25

お礼

Wendy02さん、遅くなりました。昨日実際のデータで試した結果。メモ帳に表示する今回の問題は新しいことを教わった分も合わせ200%解決しました。本当に長く面倒を看ていただき心からお礼を申し上げます。
 最後に厚かましいのですが、
>スプレッドシートコントロールを使ってもよいかもしれません
”スプレッドシートコントロール”というのは初見です。
関連の質問を#5420の監視シート・・・にしていますが、なぜかレスがつきません。もしこちらのスレッドでヒントをいただければ望外の喜びです。

なにもお返しできなくてすまない気持ちですが、Wendy02さんの今後のご活躍を祈念いたします。

投稿日時 - 2005-10-13 04:14:51

ANo.6

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

こんにちは。Wendy02です。

>関連の質問を#5420の監視シート・・・にしていますが、なぜかレスがつきません。
たぶん、こちらは、VBカテゴリですから、みなさん、ご存知なのでしょうけれども、Officeという枠組みが付きますと、逆に、答えがしづらくなるのかもしれませんね。だからといって、Office カテゴリでも、ちょっと回答がつくか分りません。

#1688905 監視ウインドウの常時表示 のほうに、回答をつけておきました。

こちらのほうは、簡単に、”スプレッドシートコントロール”について触れておきます。これは、Webコンポーネントのひとつで、ユーザーフォームの「その他のコントロール」から探して利用できます。

それが、元からあるものなのか、それとも、ダウンロードをしなければならないのか、私は、いろいろ入れているせいで良く知りません。#1688905 で、調べる方法を詳しく書いておきました。

ユーザーフォームは、ご存知のように、Excel 2000 以上ですと、モードレスモードがありますから、ワークシートと行き来できます。マイクロソフトの「Microsoft Office ダウンロードホームページ」から、検索で、Web コンポーネントとお探しになれば、ヒットするかと思います。

Microsoft Office ダウンロード ホームページ
http://office.microsoft.com/ja-jp/officeupdate/default.aspx

投稿日時 - 2005-10-13 11:31:06

ANo.5

こんばんは。Wendy02です。

>追加モードで扱うためか古いウインドウが次々と開いて溜まってしまうことです。

それは、メモ帳のことですよね。もし、メモ帳が開いていたら、一旦、終了させるようにしました。

メモ帳を一旦終了させるために、WMI を使いますが、古いパソコンですと、マイクロソフトから、WMIコアをインストールする必要がありますので、うまくいかなかったら、回答に対するお礼に返事をつけてください。遅くなっても、必ず、返事はつけます。

それから、長丁場になっていますが、気にしなくてもよいです。

今のところ、あまり複雑なものも抱えていませんし、これは面白いですから。もしも、AdvancedFilter をお使いになる場合は、どのようにするか、教えてください。考えてみます。

ところで、ついでなのですが、話を最初に戻してまことに恐縮なんですが、なぜ、メモ帳=テキストファイルなんですか?Excelは、Excel内で処理したほうが便利な気がします。メモ帳とは使い方が違いますが、オブジェクトとしてExcelを使っていきますので、現在のメモ帳の使い方とは、かけ離れているわけではありません。つまり、コピーした構造が、Excel用に出来たものは、Excelで表示させるのが便利ではないか、と思ったわけです。それに、グラフとか関数とかも取れますしね。

それで、もしも、Excelで処理しきれないようでしたら、今度は、CSVファイルにしていって、最終的には、Accessを使って処理するというわけです。

'<標準モジュール>
'---------------------------------------------------
Option Explicit
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
   ByVal lpClassName As String, _
   ByVal lpWindowName As String) As Long

Sub SampleMacro2()
Dim Fno As Integer
Dim rtn As Long
Dim strClassName As String
Dim ServiceSet As Object
Dim Process As Object
Dim myRng As Range
Dim buf As String
Dim j As Long, i As Long
Dim myID As Long
Dim Fname As String
Dim 適格銘柄開始行 As Long
Dim 適格銘柄終了行 As Long
'-------------------------
'設定 (ファイル名)
Fname = ThisWorkbook.Path & "\myData.txt"
'-------------------------

strClassName = "NotePad"
rtn = FindWindow(strClassName, vbNullString)
If rtn <> 0& Then
 Set ServiceSet = _
GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("select * from Win32_Process where Name='NOTEPAD.EXE'")
 For Each Process In ServiceSet
   Process.Terminate
 Next
 Set ServiceSet = Nothing
End If

'ここは、ユーザー設定による
適格銘柄開始行 = 1
適格銘柄終了行 = 10

Fno = FreeFile()

'最初からアペンドモードで可。

Open Fname For Append As #Fno

Set myRng = Range("A" & 適格銘柄開始行 & ":I" & 適格銘柄終了行)
For i = 1 To myRng.Rows.Count
 For j = 1 To myRng.Columns.Count
   buf = buf & vbTab & myRng.Cells(i, j).Value
 Next j
 Print #Fno, Mid$(buf, 2)
 buf = ""
Next i
Close #Fno
If FileLen(Fname) > 1 Then
 myID = Shell("Notepad.exe " & Fname, vbNormalFocus)
Else
 MsgBox "出力できませんでした。", vbCritical
End If
End Sub

投稿日時 - 2005-10-09 23:44:54

お礼

Wendy02さん。有難うございました。ウインドウがスッキリしました。

>なぜ、メモ帳=テキストファイルなんですか?Excelは、Excel内で処理したほうが便利

1.複数シートを使って計算していますが、selectでアクティブウインドウが動き、常時抽出した画面を表示しておく方法がわからない
2.抽出対象シートは66列あるので必要部分を抜き出して適格銘柄シートに
転記しています
3.現在所定の条件の下に値上りしている銘柄名だけ分かればよいのでエクセルではメニューなど目障り
4.その後銘柄を楽天のリアルタイムソフトに入力してチャートをチェックしています

>長丁場になっていますが、気にしなくてもよいです

お言葉に甘えて教えていただいたマクロにあと2点対策が取れると望外の幸せです。
1.テキストウィンドウのスクロールを常に最後備が見られるように下ろしておく
2.エクセルの時刻書式のデータhh:mm:ss AM or PMをそのまま表示。シリアルに変換されてしまうので・・

お礼分は短めにということらしいので素っ気無い文面で失礼します。あつかましいですが、最後の2点よろしくお願いいたします。

投稿日時 - 2005-10-10 05:27:08

ANo.4

こんにちは。Wendy02です。

#2 のレスに対してですが、

こんにちは。

確か、AdvancedFilterで出したものは、Copy で取れますね。(つまり、非表示行は取らない)

ということは、

もともと、こういう作業が入らないのではありませんか?
Set myRng = Range("A" & 適格銘柄開始行 & ":I" & 適格銘柄終了行)

単に、
Selection だけで済むように思います。

その上で、ログテキストを

If Dir(FName) <>"" Then
 Open Fname For Append As #Fno
Else
 Open Fname For Output As #Fno
End If

とすれば、どんどんテキストファイルに溜まりますね。
あまり大きくなる前に、専用のテキストEditor に変えることをお勧めします。多くのテキストEditor には、アウトライン表示が出ますから、左端に、小題や見出しをつけることが出来ます。

投稿日時 - 2005-10-07 15:58:30

お礼

Wendy02さん重ね重ね恐縮です。サンプルを参考にいろいろやってみましたが、結局ご教示いただいたマクロを修正できればそれが一番確実のようだと思います。マクロをサブルーティンとして使い、エクセルVBAのなかで何度も呼び出します。

サンプルで困ったのは追加モードで扱うためか古いウインドウが次々と開いて溜まってしまうことです。最新のウインドウだけ表示するコードを教えていただけないでしょうか。よろしくお願いします。

投稿日時 - 2005-10-09 20:11:24

ANo.3

こんばんは。

お礼のほうに書いていただいたおかげで、すぐに、反応できました。どうもご理解ありがとうございました。それで、#1で書いたときに、私の暖めていた案ですから、お気に召さないかもしれません。ただ、クリップボードに入れる →テキストファイルに吐き出し の組合わせが良くないように思います。

適格銘柄開始行 , 適格銘柄終了行
ここの部分がどうやって取っているか分りませんが、以下を参考にしてみてください。

ただ、これを付け足し(Append)ていくのでしたら、少し変えなくてはなりません。
例えば、

Fno = FreeFile()
If Dir(FName) <>"" Then
 Open Fname For Append As #Fno
Else
 Open Fname For Output As #Fno
End If
というような分岐をすることが出来ます。

'--------------------------------------
Sub SampleMacro1()
Dim Fno As Integer
Dim myRng As Range
Dim buf As String
Dim j As Long, i As Long
Dim myID As Long
Dim Fname As String
Dim 適格銘柄開始行 As Long
Dim 適格銘柄終了行 As Long
'-------------------------
'設定 (ファイル名)
Fname = ThisWorkbook.Path & "\myData.txt"
'-------------------------
'
適格銘柄開始行 = 1
適格銘柄終了行 = 10

Fno = FreeFile()
Open Fname For Output As #Fno
'Append Modeでしたら、Output → Append を入れます。
Set myRng = Range("A" & 適格銘柄開始行 & ":I" & 適格銘柄終了行)
For i = 1 To myRng.Rows.Count
 For j = 1 To myRng.Columns.Count
   buf = buf & vbTab & myRng.Cells(i, j).Value
 Next j
 Print #Fno, Mid$(buf, 2)
 buf = ""
Next i
Close #Fno
If FileLen(Fname) > 1 Then
 myID = Shell("Notepad.exe " & Fname, vbNormalFocus)
Else
 MsgBox "出力できませんでした。", vbCritical
End If
End Sub

タブ付きで出力しましたが、きれいに出るようですね。

投稿日時 - 2005-10-05 23:51:06

ANo.2

こんばんは。返事が遅くなってすみません。

私は、こちらは、メインでは書いておりませんのと、「回答のお礼」側に一言書いていただければ、こちらに直接メールが来るのですが、「補足」側だけですと、どうしても遅くなってしまいます。

話を戻して恐縮ですが、もう一度最初から考え直します。私は、最初のコードに書かれていない部分が理解しておりません。

>エクセルでクリップボードに格納したものを下記のプログラムで[Ctrl]+[V]キーを転送しています。

問題になるのはここの部分です。Excelのクリップボードに格納させるのは、何によって格納するのですか?範囲を選択して、Ctrl+ C ですか?

それによって、VBAのクリップボードの使い方が決まってきます。

>'コピーモードを解除する
>Application.CutCopyMode = False

最後に、こんなコードが出てくるわけですね。
Sendkey "^c" が出てこないのは正解でよいのですが、それに変わることを何かしているはずです。最初は、何をしているのですか?

それを教えてください。任意で範囲を取っているのでしょうか?CutCopyMode だけなので、それが分らないし、それが分れば、最後まで通ると思いますね。

投稿日時 - 2005-10-05 18:48:02

お礼

Wendy02さん、再三のご教示ありがとうございました。試してみたところ確かにエクセルシートの内容をテキストファイルにできました。

実はもっともやりたいことは画面を開き放しにしてエクセルVBAでアドバンスフィルターにかかる都度次々と表示することです。

サンプルを参考に勉強してみます。

有難うございました。

投稿日時 - 2005-10-07 10:00:27

ANo.1

こんばんは。

最初に、それはExcelですか?Sleep 1 とは何ですか?
API関数で、Loopして、3秒を取るというのは、ナンセンスです。単に、Sleep 3000 でよいのではありませんか?

>AppActivateが効かないのか分かりませんが対策を是非ご教示下さい。

たぶん、空のメモ帳だからでしょうね。
たまたま、同じような種類のサンプルで、こちらで書いたものは、メモ帳は閉じません。

http://oshiete1.goo.ne.jp/kotaeru.php3?q=1682506

私は、ご質問のコードでは、やっていることが良く分りませんが、例えば、末尾に書かれたように、メモ帳を待機させれば、メモ帳は開いていますね。

それから、クリップボードは、参照設定のMicrosoft Forms xx Object Library の DataObjectを設定しておいて、

Dim objDO As New DataObject
Dim buf As String

With objDO
    .GetFromClipboard ''クリップボードからDataObjectにデータを取得する
    buf = .GetText ''DataObjectのデータを変数に取得する
End With
'以下、buf をテキスト出力する。

それを、上のサンプルコードのような方式で、一旦、
myPath = ActiveWorkbook.Path & "\" の の適当な名前のテキストファイルに吐き出させて、メモ帳で呼び出せば、以下のような API関数は使わずに済みますね。後は、いろいろ研究してみてください。

'--------------------------------------------
Private Declare Function OpenProcess Lib "kernel32.dll" ( _
   ByVal dwDesiredAccess As Long, _
   ByVal bInheritHandle As Long, _
   ByVal dwProcessId As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32.dll" ( _
   ByVal hProcess As Long, _
   ByRef lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" ( _
  ByVal hObject As Long) As Long
Private Const PROCESS_QUERY_INFORMATION As Long = (&H400)
Private Const STATUS_PENDING As Long = &H103
Private Const STILL_ACTIVE As Long = STATUS_PENDING

Sub OpenMemoPad()
Dim myId As Long
Dim myProcess As Long
Dim ExitCode As Long
Dim ret As Long
 myId = Shell("Notepad.exe", vbNormalFocus)
 myProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 1, myId)
 Do
  ret = GetExitCodeProcess(myId, ExitCode)
  DoEvents
 Loop While ExitCode = STILL_ACTIVE
ret = CloseHandle(myProcess)
End Sub

投稿日時 - 2005-10-01 22:44:01

補足

早速のご返答有難うございます。
やっていることはエクセルVBAでフィルターを通過してくる4から5行の株の銘柄情報をクリップボードコピーする。それを開き放しのメモ帳に貼り付けて画面前面に表示して見ています。

API関数はメモ帳が開くまで待っているつもりで、見よう見まねでいれてみました。この部分は機能しているようです。

問題はSendKeyで貼り付けるのですがAppActivate myID
でメモ帳をアクティブにしているのに他の開いているアプリケーションに時々貼り付けてしまいます。どんな場合にミスするのか特定できません。

アドバイスいただいた
>With objDO
    .GetFromClipboard ''クリップボードからDataObjectにデータを取得する
    buf = .GetText ''DataObjectのデータを変数に取得する
>End With
>'以下、buf をテキスト出力する。

開き放しの画面に"buf をテキスト出力"する方法が分かりません。この辺は不案内でテキストファイルに書き出すサンプルなら出来ますが、開き放しというところがミソです。

ご教示の内容を未消化で申し訳ない気がしますがよろしくお願いいたします。

投稿日時 - 2005-10-02 12:49:26

お礼

Wendy02さん追伸有難うございます。
サブルーティンにわたる前のメインのコピーはこうなっています。

Range("A" & 適格銘柄開始行 & ":I" & 適格銘柄終了行).Copy
'適格銘柄シートの次の書き込み開始行を更新
適格銘柄開始行 = 適格銘柄終了行 + 1
NotePad書き出し

Application.CutCopyMode = Falseは最初サブルーティン内でコピーしていたものの遺物です。

その後分かったのですがAppActivate myIDで制御を持ってきてもすぐ失って楽天のリアルタイムデータ取得プログラム(マーケットスピード)に行っているようです。

それで当てずっぽうでAppActivate myIDを次のループの中に入れるとミス率が2パーセントほどになり実用的には我慢しています。しかしすっきりしません。

For y = 1 To 1000 'notePadがアクティブになる余裕を1秒間取る

'メモ帳をアクティブにする。すぐコンとロールを失うのでループさせる
AppActivate myID
DoEvents
Sleep 1
If y = 500 Then

'[Ctrl]+[V]キーを転送してコピーした内容を貼り付ける
SendKeys "^V", True
Exit For

End If
Next y

お恥ずかしい仕儀ですが、よろしくお願いいたします。

投稿日時 - 2005-10-05 20:41:32

あなたにオススメの質問