外出自粛中でも楽しく過ごす!QAまとめ>>

エクセルVBAでNumLockキーの状態を確認することはできますでしょうか?

検索の結果
http://detail.chiebukuro.yahoo.co.jp/qa/question …
のページを見つけましたが、

Private Declare Sub GetKeyboardState Lib "user32" (pbKeyState As Byte)

でエラーになってしまいます。

なぜかと検索してみると、どうやら私のWindows が64ビットだからのようです。

64ビットに対応し、EXCEL、 エクセルVBAでNumLockキーの状態を確認し、offだったらonにするということが出来るでしょうか。

勿論、VBAでSendKeysを連発するとNamLockキーがOffになってしまう時があるということや、APIのSendInput 、keybd_eventイベントもあると思いますが、何が適当なのか、64ビットに対応させるのはどうするのか、教えて頂けるとありがたいです。よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (6件)

こんにちは、#2#4です。


迷ったのですけれど、
このスレ読んで誤解する人いると悲しいので
指摘しておきますね。
 > Windows7には対応していないようなので
これは間違いです。
#3さんは、【64ビット版 Windows7 & 32ビット版 Office】環境で"問題なく動く"と仰っています。
#1さんも同様のことを仰っているのだと思います。
#2#4で私は【64ビット版 Windows7 & 64ビット版 Office】環境で
Win32APIを使えるようにするにはどうしたらいいか書いています。
今回3つのサンプルコードが紹介されていますが
(順に)
↓最初のご質問
http://detail.chiebukuro.yahoo.co.jp/qa/question …
↓#3さんご紹介のもの
http://www.accessclub.jp/samplefile/samplefile_2 …
↓#4へのレスでkichi4182さんがあらたにご提示なさったもの
http://oshiete.goo.ne.jp/qa/5156553.html
(#3と#4は、Functionで書くかSubで書くかの違いだけで
まったく同じものですから、実際には2種類なのですけれど)
今回のこのスレッド全体としては
 【64ビット版 Windows7 & 32ビット版 Office】環境
 【64ビット版 Windows7 & 64ビット版 Office】環境
どのサンプルコードも、
 "問題なく機能することを確認した"
という話になっているのです。
 【Windows7】 はこの際関係なくて(問題ではなくて)、
 【64ビット版 Office】 では、
   そのままの記述ではAPIが通らないから 
   実際に動く様にするために
   どうしたらいいか、という話を書いているのです。
今回紹介された3つのサンプルコード、のいすれも、ちゃんと動きます。
  Excel でも
  Access でも
  ユーザーフォームモジュール でも
 勿論
  標準モジュールでも
何度やっても動きます。
いくつかのイベントトリガーで NUMLOCK がかかることを実際に試してもいます。

今回紹介された3つのサンプルコードの場合、
【64ビット版 Office】 で動くようにするには
単純に
1■ リンク先のサンプルコードを丸ごとそのままコピペして(コンパイルエラーは[OK]で無視して)
2■ Ctrl + H で置換ダイアログを表示して
   "Declare" を "Declare PtrSafe" に
   モジュールごと、すべて置換する
これだけで、最低限(*)の動作確認はできます。
(例えば、プロシージャにカーソルを当てて F5 キーを押すだけ)

今回紹介された3つのサンプルコード、のいすれも、ちゃんと動きます。
動作を確認出来ないということのようなので、あらためて単純化して書いてみました。

(*)推奨された手順としては、続いて、Long型の置換が必要だということは#4で触れています。

要は
【Office 2010 64ビット版】だけは、API の書き方が他のバージョンとは違うってだけの話
ですので、ご理解いただきたいです。
    • good
    • 0
この回答へのお礼

何度もありがとうございます。

私が

 > Windows7には対応していないようなので

と書いたのは、
http://support.microsoft.com/kb/177674/ja
の詳細にWindows7が書かれていないのを見て、そう思ってしまいました。誤解させてしまったようで、大変申し訳ありません。

今回は 取りあえず注意喚起のMsgboxを使い、少しずつでも勉強しながら対応していこうと思います。

ありがとうございました。

お礼日時:2012/10/01 14:34

さすがにOfficeの64bitバージョンをインストールして


検証する元気はありません。

MS社自身、32bit バージョンの使用を推奨しています。
開発目的ならともかく、実務に使うのなら周囲の環境が整っている32bit かと。

64 ビット版の Office 2010
http://technet.microsoft.com/ja-jp/library/ee681 …
    • good
    • 0

#2です。



Office 2010 バージョン:14.0.6123.5001 (64ビット)
(Win7・64ビット)
↑この環境では、
PtrSafe 抜きで正しいDeclare文をタイプし終えてキャレットを動か(Enter)した瞬間にコンパイルエラーでした。
回答No.3 nicotinism さんご紹介の「強制的にNumLockキーをオンにするプロシージャ」
も、Declaration 宣言部に修正(というより対策?)を加えた上で、動作を確認しましたので、
せっかくなので、対策後の記述を載せておきます。

' ' =========================以下、筆者加筆によるもの
  'API declarations:

  Private Declare PtrSafe Function GetVersionEx Lib "kernel32" _
    Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As LongPtr

  Private Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, _
    ByVal dwFlags As LongPtr, ByVal dwExtraInfo As LongPtr)

  Private Declare PtrSafe Function GetKeyboardState Lib "user32" (pbKeyState As Byte) As LongPtr

  Private Declare PtrSafe Function SetKeyboardState Lib "user32" (lppbKeyState As Byte) As LongPtr
' ' 以上=============================================

(1)
 Declare → Declare PtrSafe
4カ所置換
(2)
 Long → LongPtr
5か所置換

手元の環境では(1)は必須のようですが、(2)はそのままでも動くようです。一応ヘルプに従ったつもりです。
ヘルプを読んだ私の解釈では、2010/VBA7 環境では 32ビット/64ビット 共通で動く記述のようですが
32ビット環境での動作はこちらで確認していません。

大事な話が後になりましたが、
> どうやら私のWindows が64ビットだからのようです。
というのを勝手に拡大解釈して、Office も2010、64ビット、、、
だとすると、話が理解しやすい、、、という憶測を前提にレスをしています。
違っていたら(他勘違いなどあれば)ただのお騒がせ、その時はすみません。
でも、なんかの役に立つかも知れませんので、ヘルプの引用も、最後に載せておきます。

==============以下引用

LongPtr - VBA に可変の型エイリアス LongPtr が追加されました。LongPtr が解決された後の実際のデータ型は、コードが実行される Office のバージョンによって異なります。LongPtr は 32 ビット版 Office の場合は Long、64 ビット版 Office の場合は LongLong に解決されます。ポインターおよびハンドルには LongPtr 型を使用してください。
LongLong - LongLong データ型は 64 ビットの符号付き整数型で、64 ビット版の Office でのみ使用できます。64 ビットの整数には LongLong 型を使用してください。LongLong (64 ビット プラットフォーム上の LongPtr も含む) をより小さいサイズの整数型に明示的に割り当てるには、変換関数を使用する必要があります。LongLong をより小さいサイズの整数型に暗黙的に変換することはできません。
PtrSafe - PtrSafe は、Declare ステートメントを 64 ビット版の Office で実行しても安全であることを示すキーワードです。
コードを 64 ビット版 Office で実行する場合は、すべての Declare ステートメントに PtrSafe キーワードを含めることが必須となりました。PtrSafe キーワードを単に Declare ステートメントに追加しただけでは、その Declare ステートメントの実行対象が 64 ビット環境であると指定したにすぎません。そのうえで、ステートメント内のデータ型 (戻り値やパラメーターなど) のうち 64 ビット値を格納する必要があるものをすべて、64 ビット値を格納できるように修正する必要があります。

以上引用==============

それでは失礼します。

この回答への補足

すみません。書き忘れておりましたが、EXCEL(Office 2010)も64ビット版です。

あと、ユーザーフォームは作っていないので、すべて標準モジュールでの話です。

補足日時:2012/09/28 13:16
    • good
    • 0
この回答へのお礼

ありがとうございます。

とりあえず、対象セルを選んだ時にMsgBoxで注意を促すようにして時間稼ぎをすることにしました。

http://okwave.jp/qa/q5156553.html

上記を参考にして組んでみましたが、Windows7には対応していないようなので、7に対応させることを考えてみたいと思います。

しかし、よく分かっていないので、あきらめようかとも思っています。

もうしばらく粘ってみますが。。。。

お礼日時:2012/09/28 16:06

質問者さんが見つけられたページのコードで問題なく動きましたけどね?


当方 Windows7 64bit & Office 2010 32bit です。
NumLock をOn にするのは少し面倒です。
下記サイトのコードは標準モジュール上で
丸コピペで機能するのをExcel上で確認しています。
http://www.accessclub.jp/samplefile/samplefile_2 …


Option Compare Database はAccessでの話なので削除
Option Explicit は重複して宣言しないように

この回答への補足

すみません。書き忘れておりましたが、EXCEL(Office 2010)も64ビット版です。

あと、ユーザーフォームは作っていないので、すべて標準モジュールでの話です。

補足日時:2012/09/28 13:13
    • good
    • 0

Private Declare PtrSafe Sub GetKeyboardState Lib "user32" (pbKeyState As Byte)



ですね。

PtrSafe をVBAのヘルプで検索して、64Bit版での32APIの扱い方、一度調べておいた方がよいかと。
    • good
    • 0
この回答へのお礼

ありがとうございます。勉強します。

お礼日時:2012/09/28 13:05

64ビットOSであることは、関係ありません。

EXCEが32ビットソフトなので、EXCEL内のマクロも32ビット互換モードで動いています。むしろ64ビットのAPI呼び出しなどを使うと動かなくなるはずです。

どんなエラーが出ているのですか?
その内容によって、それ相応の対応が必要です。

API呼び出しは、Declare文が必要なのですが、書いてありますか?
フォームモジュールでなく、標準モジュールに書いてみるとどうなりますか?
(参考)
http://www.excellenceweb.net/vba/api/what_window …

この回答への補足

すみません、エラー内容です。

『このプロジェクトのコードは、64ビットシステムで使用するために更新する必要があります。Declareステートメントの確認および更新を行い、次にDeclareステートメントにPtrSafe属性を設定してください。』

よろしくお願いします。

補足日時:2012/09/28 13:04
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qエクセル NUMLOCKキーの常時オンについて

表題の質問をさせていただきます。

仕事場に入っているシステムがキーボード上部のボタンに様々な機能を割り当てていまして、システム独自の機能を有するように設計されています。
 割り当てられているのは↓です。
  デスクトップ用キーボードで、ファンクションキーやテンキー上部のキー(Num / * -)

このシステムを利用しながらエクセルも同じPCで稼動させています。
ファンクションキーはさほど困らないのですが、NumLockキーをシステムで利用するので頻繁にONになったりOFFになったりします。

システムからエクセルに変更をした際にNumLockがオフになっていることが確率的に半数あり、その際はテンキー入力をすると あらぬ位置に入力セルが飛んでいってしまい困っています。

あらぬ位置に飛んでいってしまったときはマクロ登録してあるボタンで所定の位置に戻ってくるように設定しています。
 ウインドウ枠の固定で画面を上下に分割していて 上部にマクロボタンを設置してあります。

いろいろと調べてWorkbookやWorksheetのActivateイベントに↓を記述しました。
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys "{NUMLOCK}"

しかし、システムから切り替わった場合には動作しませんでしたし、エクセル内での動きとしてもシートチェンジ毎にONとOFFになってしまい、いい動きにはなりませんでした。

システムから切り替わったタイミングをと思い、SelectionChangeにも記述しましたが、当然ながらクリックするたびにON・OFFになってしまい…。

どうにか、エクセルがアクティブになっている時は NumLockを常時ONにする方法はないでしょうか。
お知恵を拝借したく投稿しました。

エクセル2003です。よろしくお願いいたします。

表題の質問をさせていただきます。

仕事場に入っているシステムがキーボード上部のボタンに様々な機能を割り当てていまして、システム独自の機能を有するように設計されています。
 割り当てられているのは↓です。
  デスクトップ用キーボードで、ファンクションキーやテンキー上部のキー(Num / * -)

このシステムを利用しながらエクセルも同じPCで稼動させています。
ファンクションキーはさほど困らないのですが、NumLockキーをシステムで利用するので頻繁にONになったりOFFになったりします。

...続きを読む

Aベストアンサー

#1の回答者です。
#どうやら、キーボードが壊れているようですね。

>上部のボタンに様々な機能を割り当てていまして

を読み落としていました。#1の仮想キーボードで、その都度、直すしかないかもしれません。イベント・ドリブン型は、キーの変わるタイミングを良く観察して選ぶと良いかと思います。シートに数式などがあれば、例えば、Calculate イベントでもよいと思います。

Q【Excel VBA】マクロでExcel自体を終了させたい

環境:WindowsXP、Excel2003

マクロでエクセルを終了(ブックを閉じて、アプリケーション自体も終了)させたいのですが、以下のコードではアプリケーションが閉じてくれません。

ThisWorkbook.Close
ExcObj.Quit
Application.Quit

どこか悪いところはありますでしょうか?

よろしくお願いします。

Aベストアンサー

普通に考えれば質問者のコードで上手くいきそうですが
hana-hana3さんの回答にもあるようにThisWorkBook.Closeでコード終了となりますので
Application.QuitをThisWorkBook.Closeの前にもってこないといけません。
Application.Quitはそれがあるプロシージャのコードが全て終わるまで
その実行を保留するちょと特別動作をします。

'-------------------------------------
 Application.Quit
 ThisWorkbook.Close
'-------------------------------------
 
 

QEXCEL VBA で現在開いているブックのファイル名を取得する方法

EXCEL2003 VBAで業務を簡素化するために、現在開いているブックのファイル名を取得する方法が分かりません。
作業手順をマクロを使って処理していますが、オリジナルのワークブックをファイル名を変えて保存し、以後、このワークブックを読み込んで使用しています。
このときのVBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり、以後の業務に使用できません。
常にファイル名を取得出来るVBAをどなたか、教えて下さい。

Aベストアンサー

>現在開いているブックのファイル名
 ちょっと曖昧な表現かなぁという気もいたしますが、VBAが書いてあるブックのブック名は
ThisWorkbook.Name
で、現在 "アクティブにして" 操作対象になっているブックの名前は
ActiveWorkbook.Name
ですね。

 しかし、
>VBAは、オリジナルのファイル名を使っているため、ファイル名を変更するとエラーになり
というような文脈からすると、
ThisWorkbook.Name
の方ですかね。

QVBAで、なぜかSendkeyが効きません。

一年くらい前に作ったSendkeyを含んだマクロをまた使うことになりました。
再使用してみると、他のコードの部分は正常なのにSendkeyの部分だけが正常作動せず、空打ちしたように変化しないまま次のコードに移ります。

Excel2003使用ですが、Excel97の入った他のPCでやっても同じ現象が起こります。
そこで、テストにヘルプのSendkey例文をVBEに貼り付けてみましたが、やはりその部分だけ作業せず先へ進んでしまいます。
Sendkeyの行では、不適切なキーをキーボードから打った時によく鳴るビービーという音がPCから聞こえてきます。

自分が基本的な操作を1つ忘れているのじゃないかと思うのですが、それが何なのか見当が付きません。
なにかお気づきの点はないでしょうか?
キーロガーを防止の為、ウィルスソフトがはねているのかと思いOFFにしてみましたが、関係ありませんでした。


テストした例文は下記です。
Sub x()

Dim ReturnValue, I
ReturnValue = Shell("CALC.EXE", 1)
AppActivate ReturnValue
For I = 1 To 20
SendKeys I & "{+}", True
Next I
SendKeys "=", True
SendKeys "%{F4}", True
End Sub

一年くらい前に作ったSendkeyを含んだマクロをまた使うことになりました。
再使用してみると、他のコードの部分は正常なのにSendkeyの部分だけが正常作動せず、空打ちしたように変化しないまま次のコードに移ります。

Excel2003使用ですが、Excel97の入った他のPCでやっても同じ現象が起こります。
そこで、テストにヘルプのSendkey例文をVBEに貼り付けてみましたが、やはりその部分だけ作業せず先へ進んでしまいます。
Sendkeyの行では、不適切なキーをキーボードから打った時によく鳴るビービーという音が...続きを読む

Aベストアンサー

こんばんは。

>Sendkeyステートメントがどんな仕組みなのか全く知らないので原因が分からないです。

私も、動かない現象自体は、私も悩まされてきた経験はあります。それが、以下で出すようなコードです。もし、動かないとすれば、常駐しているソフトには違いないのですが、セキュリティソフトではなさそうなのです。(以前、試した範囲です)

ただし、ステップインではうまく行かないことがあります。

>MS-IMEは削除しATOKにているのでその影響かも知れないです。

私の知っている範囲ですと、ATOK は、MS-Office に入り込むような仕組みにはなっているのですが、Sendkey が動かないということは、ちょっと、今のところ想像がつきませんね。

それで、昔、やっていた方法を披露しておきます。
しょせん、Sendkeyは、どこから送ろうが関係ないから、VBScript のExcel外部から動かす方法を私は考えました。

>これは一度キーボードのソフトに渡されてそこから目的のアプリケーションへキーが送られているんでしょうか。それともVBAから直接にアプリケーションに送られているんでしょうか。

それは、VBAから、ほんの短い間、バッファに入って、送られるようですね。
その理由は、外部ソフトによっては、まとめて、2段階の処理でも、キーの処理は1回でまとめて送っても、2段階の動作が動くからです。

逆に、バッファ自体が、何かで阻止されるか、チェックを受けるようにされていれば、確かに動きません。セキュリティソフトの種類かな?

それと、おっしゃるような、「一度キーボードのソフトに渡されてそこから目的のアプリケーションへキーが送られている」という、別のテクニックがあったはずですが、私は、正直なところ、VBAで、そこまでするのかなって思いがあって、あまり追求していないのです。


Dim ReturnValue, I
ReturnValue = Shell("CALC.EXE", 1)
AppActivate ReturnValue

With CreateObject("Wscript.Shell")
For I = 1 To 20
 .SendKeys I & "{+}", True
Next I
 .SendKeys "=", True
 Application.Wait Now() + TimeValue("00:00:05")
 .SendKeys "%{F4}", True
End With


ところで、念のためなのですが、これらの一連のコードは、私は、VBE からです。ワークシートからではないのです。それと、ちょっと表現が分かりにくいかもしれませんが、Excel自体は、静的な状態でマクロを動かしています。自動保存や時間で動くようなツールは、一切ありません。

こんばんは。

>Sendkeyステートメントがどんな仕組みなのか全く知らないので原因が分からないです。

私も、動かない現象自体は、私も悩まされてきた経験はあります。それが、以下で出すようなコードです。もし、動かないとすれば、常駐しているソフトには違いないのですが、セキュリティソフトではなさそうなのです。(以前、試した範囲です)

ただし、ステップインではうまく行かないことがあります。

>MS-IMEは削除しATOKにているのでその影響かも知れないです。

私の知っている範囲ですと、ATO...続きを読む

QEXCEL VBAで計算値を四捨五入、切り上げ、切捨てする方法

ネットで探してみたのですが、計算結果を四捨五入して特定のセルを
返すにはどうしたらいいのでしょうか?

Sub hokangosa()

Dim ZPS As Double
Dim ZPOS As Double
Dim DMN As Double
MsgBox (" >>> 補間誤差自動計算 <<< ")
MsgBox (" >>> 初期値入力します <<< ")
ZPS = InputBox(">>> ステップを入力してください<<<")
ZPOS = Sheet1.Cells(22, 4).Value
DMN = ZPOS / ZPS
Sheet1.Cells(23, 6).Value = DMN
End Sub

ここでDMNの値を四捨五入したいです。

またこれとは別に切上げ、切捨ても教えていただけるとありがたいです。

Aベストアンサー

DMN = Application.WorksheetFunction.Round(ZPOS / ZPS, 0)
で、四捨五入
DMN = Application.RoundDown(ZPOS / ZPS, 0)
で切り捨て
DMN = Application.RoundUp(ZPOS / ZPS, 0)
で切り上げです。

引数で、対象桁を変更できます。

QEXCEL VBAから他アプリケーションを操作することは可能ですか?

こんばんは。

VBAの本を購入し勉強していますが、VBAと他アプリケーションとの連携について記載が少なく(txtやcsvファイル操作)、どこまで出来るんだろうという不安があり質問しました。

(1)EXCEL VBAから他アプリケーションを起動し、設定操作、命令を送り操作することは可能でしょうか?
イメージとしては他アプリに一方的に命令を送り操作できれば良しです。(アプリ側からのリターン要求はしません。)

(2)第2の質問です。
VBAで他アプリを起動した状態で人が操作している感覚でマウスを操作できますか?(利用方法:他アプリの●ボタンを押したい!!)
目の前にソフトがあるのに触る操作は出来ないものでしょうか?
いろいろ調べて見ましたが、この様な事例はありません。
駄目元ですが、こんな操作を知っていましたら教えてください。
こんな操作ができればいいな~

Aベストアンサー

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  Dim rChange   As Range
  Dim sCommand  As String
  Dim sScriptFile As String

  ' // 実行する UWSC スクリプト
  sScriptFile = "C:\sample.uws"
  ' // UWSC の起動オプションは UWSC のヘルプを参照
  sCommand = DQ & EXE_PATHNAME & DQ & " " & _
        DQ & sScriptFile & DQ
  
  ' // 変更されたのが単一セルかつ A 列でなければ終了
  If Target.Cells.Count > 1 Then Exit Sub
  Set rChange = Intersect(Target, Columns("A"))
  If rChange Is Nothing Then
    Exit Sub
  End If
  
  ' // さらに値が TEST だった場合のみ実行
  If rChange.Value = "TEST" Then
    Shell sCommand, vbNormalFocus
  End If

End Sub

#2,4 です。

> EXCEL2000内の特定のセルに規定値外のデータが入力された場合に
> UWSCを起動して...

UWSC のスクリプトが完成しているとすれば、起動オプション付きで
バッチ処理すれば良いでしょう。実行タイミングは、シートまたは
ThisWorkbook の Change イベントが使えます。

例)シートモジュール

Private Const EXE_PATHNAME As String = "C:\Program Files\uwsc\uwsc.exe"
Private Const DQ      As String = """"

Private Sub Worksheet_Change(ByVal Target As Range)

  ...続きを読む

QエクセルVBAでクリップボード内容をクリア

こんにちは。
エクセルのVBAの処理の中で、ある部分をコピーしてそれを、
貼り付けする処理をしています。
処理終了後、ファイルを閉じるときに、クリップボードに
コピーの内容が残っている旨のメッセージがでてきます。
このメッセージを出さない様に、クリップボードの内容を
クリアするにはどのようにすればよろしいでしょうか?
申し訳ありませんが、お教え頂きますようお願いいたします。

Aベストアンサー

Excel.Application.CutCopyMode = False
Workbooks(fName).Close savechanges:=False

かな。1行目だけでいいかも。

Qエクセル VBA ユーザーフォームを閉じる

ユーザーフォームを開く時は
UserForm1.Showですが
閉じる時は?
UserForm1.Close
だとコンパイルエラーになります。
End
にするしかないですか?

Aベストアンサー

Unload Me とか Unload UserForm1 でユーザーフォームを閉じることができます。

QEXCELファイルのカレントフォルダを取得するには?

EXCELファイルのカレントフォルダを取得するには?

C:\経理\予算.xls

D:\2005年度\予算.xls

EXCEL97ファイルがあります。

VBAで
  カレントフォルダ名
(C:\経理\,D:\2005年度\)
を取得する事は可能でしょうか?

CURDIRでは上手い方法が見つかりませんでした。

Aベストアンサー

こんばんは。
Excel97 でも、同じですね。以下で試してみてください。

Sub test()
'このブックのパス
a = ThisWorkbook.Path
'アクティブブックのパス
b = ActiveWorkbook.Path
'Excelで設定されたデフォルトパス
c = Application.DefaultFilePath
'カレントディレクトリ
d = CurDir
MsgBox "このブックのパス   : " & a & Chr(13) & _
   "アクティブブックのパス: " & b & Chr(13) & _
   "デフォルトパス    : " & c & Chr(13) & _
   "カレントディレクトリ : " & d & Chr(13)
End Sub

QDoEvents関数って何?

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そこで「EXCEL VBA パーフェクトマスター」という本を見たら

for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
DoEvents
next i
unload userform1
と入力すれば解決することがわかりました。

しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、
「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」

と書いてあるのですが正直、書いてあることがよくわかりません。

どなたかDoEvents関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

こんにちは。

VBAやプログラミングに詳しい皆様に
教えていただきたい質問があります。

cells(1,1)からcells(5000,1)までの値を消去するときに
処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。

そこで下記のようなコードを入力しました。

userform1.show
for i =1 to 5000
cells(i,1)=""
userform1.progressbar1.value=i/5000*100
next i
unload userform1

しかしこれだとuserformの背景が真っ白になってしまい
ラベルの文字も消えてしまいます。
そ...続きを読む

Aベストアンサー

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
    DoEvents
    Cells(i,1) = ""
  Next i
End Sub

Private Sub CommandButton2_Click()
  MsgBox "hoge"
End Sub

っていうフォームのコードがあった場合、
DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。
CommandButton1 のクリック イベントではループの前に
CommandButton1.Enabled = False
CommandButton2.Enabled = False
を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら
CommandButton1.Enabled = True
CommandButton2.Enabled = True
と書いて CommandButton を有効に戻してください。

これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。

Private Canceled As Boolean

Private Sub CommandButton1_Click()

  CommandButton2.Enabled = False

  Dim i As Long
  For i = 1 To 50000
    DoEvents

    If Canceled = True Then
      MsgBox "キャンセルしました"
      Exit Sub
    End If

    Cells(i, 1).Value = ""
  Next i
End Sub

Private CommandButton2_Click()
  Canceled = True
End Sub



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。

簡単に言うと、
OS に制御を渡すってことです。(ヘルプそのまんま)
時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。
ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。
途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。
結果、フォームの再描画などが行われることになります。

注意点ですが、
Private Sub CommandButton1_Click()
  Dim i As Long

  For i = 1 To 50000
...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング