マンガでよめる痔のこと・薬のこと

A1 -> 11(初期値)
A2 -> if(A1>10,1,2)

上記の様に表にデータが入っている場合に以下のマクロを実行した時に再計算されずにマクロの処理が進み遅くなって再計算が実行されるため正確なマクロが実行されないのですが、どうしたら確実に再計算を実行したあとにマクロが処理を継続するようにさせる事が出来るのでしょうか、よろしくお願いします。なお、実際のマクロ及び関数は違います。

Range("A1").value = 1
Calculate
if Range("A2").value = 1 then
 msgbox "OK"
endif
end

以上の場合に『OK』メッセージが表示されるものと理解していますが、表示されずに終了してしまいます。

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

A 回答 (20件中11~20件)

こんばんわぁ。


伝えたいことはわかるのですが、例やマクロの一部を出したのは
再現性がないため、かえって伝わりにくいかもしれませんね。
きっと、同じような状況にならないと理解はできないかもしれません。

msgboxをひとつ入れて思うとおりの結果が得られたということなので、
マクロは思い通りのものができているが、マクロの実行と再計算のタイミングが一致していないので、
うまく動いていないということですよね。

Calculateの後ろに
DoEvents
DoEvents
とDoEventsを2つ入れて試してみてください。

この回答への補足

回答有り難う御座います。

DoEventsを数個入力しても駄目でした。

補足日時:2003/10/21 22:14
    • good
    • 0

再び、#6です。



「※3の頃になって、シート名『合計』が再計算される」とありますが、
(※4の時点で選択されているシートはコピーしたシート『合計 (2)』になってる)

質問1)何をもって※3で再計算されていると判断されているのでしょう?

「再計算のマクロがあるにもかかわらず完全に再計算されない状態でマクロが次ぎの処理を実行する」「msgboxが表示される時間はマクロが中断されているが再計算は処理されているために問題が解決され If Range("AD46").Value <> "" の処理が正常に動作した」

この解釈はどうも納得出来ません。
VBAとシート計算が完全に別スレッドで動いているなら有り得るかも知れませんが、もしそうなら再計算の終了を返す手続きや関数がないと危なくて使えないと思います。

質問2)そのままでは上手く行かない処理が、 Timer と DoEvents を入れたら上手く行きますか?

 End If
 Calculate
   PauseTime = 10   '10秒
   Start = Timer
   Do While Timer < Start + PauseTime
     DoEvents
   Loop
 Sheets("合計").Select
 If Range("AD46").Value <> "" Then ' ※2

質問3)そもそもどう上手く行かないでしょうか?
 合計のA1にループで入る、請求先のB5~の値はどのように変化するのか?
 それによって合計AD46の値はどのように変化するのか?
 それによって合計C26の値はどのように変化するのか?
 それによって合計又は合計(2)のA4の値はどのように変化するのか?

------------------------------------------------------------------------------
以下は、「こんな感じ」と判断しTEST
Sheets("請求先")のB5~下には請求先名が入っている
Sheets("請求先")のB列最終セルは『総合計』と入っている
Sheets("請求先")のB列の請求先毎に計算式を消したシートを作る。
Sheets("合計")のAD46にはA1の値変化に関連したIF関数が入っている
Sheets("合計")のAD46が空白かどうかでシートコピーするかどうかを決めている
Sheets("合計")のC26にはA1の値変化に関連したIF関数が入っている
Sheets("合計")のC26が空白かどうかで印刷範囲を設定している
Sheets("合計")のA4にはA1の値変化に関連したIF関数が入っている(=A1)?
Sheets("合計")をコピーしたシートのシート名に年間計+請求先名を付ける?

Sub TEST()
Dim cs As Worksheet, ws As Worksheet
i2 = 4                      '取あえず B5~B8 まで
Application.Calculation = xlAutomatic      '自動計算
Set ws = Sheets("合計")             '変数に代入
ws.Range("A1").ClearContents           '合計のA1クリア
For i = 1 To i2
 ws.Range("A1").Value = _
   Sheets("請求先").Range("B" & i + 4).Value  '請求先名を合計のA1に※1
 If ws.Range("AD46").Value <> "" Then      '※2はここから
  If ws.Range("C26").Value = "" Then      '印刷範囲を設定
    ws.PageSetup.PrintArea = "$B$1:$AD$25"
  Else
    ws.PageSetup.PrintArea = "$B$1:$AD$46"
  End If
  ws.Copy After:=ws               '合計シートをコピー※4
  Set cs = ActiveSheet             'コピーシートを変数に代入
  cs.Name = "年間計" & cs.Range("A4").Value   'シート名変更
  If cs.Name = "年間計『総合計』" Then     'シート名により移動させる
    cs.Move Before:=Sheets("実績")
  Else
    cs.Move Before:=Sheets("品名等")
  End If
  cs.Cells.Copy                 '※3
  cs.Cells.PasteSpecial xlValues        '関数を全部消すため
  cs.Columns("A:A").Delete           '一時処理用の列削除
  cs.Range("A1").Select
 End If                     '※2はここまで
Next                       '次の請求先
 'Application.Calculation = xlManual
End Sub

この回答への補足

前回のmsgboxの実施時は勘違いがあったのでしょうか?今日、実施したら上手く出来ませんでした。

 Calculate
   PauseTime = 10   '10秒
   Start = Timer
   Do While Timer < Start + PauseTime
     DoEvents
   Loop
 Sheets("合計").Select
 If Range("AD46").Value <> "" Then ' ※2

また、上記を挿入して、実行し静止中に合計の表を確認したと再計算がされず、別のシートが作成された時点にて再計算されていました。
なお、マクロが終了した後に同ファイルを確認しても問題なく関数は処理されていす。

以上、よろしくお願いします。

補足日時:2003/10/21 22:12
    • good
    • 0

#6です。


変数 i2 と i3 と Range("AD46").Value の式、Range("C26").Value のセルに入っている関数式が不明で良く解かりませんのでアドバイスを。

if 条件 then
 真の時
else
 偽の時
end if

のように else を使った方がコードが見渡しやすくなります。

i が 0 のループはループ前に Sheets("合計").Range("A1").ClearContents を入れれば不要に思います。

※2の条件は
Sheets("合計").Range("AD46").Value  が「空白かどうかだけの判断」
で、空白以外なら条件内に入り、※3も実行される仕組みになっていますよね?
ループ中に、Sheets("合計").Range("A1").Value = b が「再計算される」と
Sheets("合計").Range("AD46").Value が「空白になり」
※2が「実行されない」事を望んでいるのですか??

この回答への補足

何回も有り難う御座います。

職場毎のデータがあり、各職場毎に集計表を作成させるマクロなんですが、シート名『合計』は職場別の合計を作成するシートで、
Sheets("合計").Range("AD46").Valueは合計金額欄であり、=IF(SUM(F46,H46,J46,L46,N46,P46,R46,T46,V46,X46,Z46,AB46)=0,"",SUM(F46,H46,J46,L46,N46,P46,R46,T46,V46,X46,Z46,AB46))となっています。
ですから、その職場に実績がある場合には、If内のマクロにて、別シートを作成し、実績が無い場合には、次の職場へ変更して処理を継続させる。
以上です。よろしくお願いします。

補足日時:2003/10/21 21:45
    • good
    • 0
この回答へのお礼

補足漏れをさせて下さい。

AD46が職場別の合計金額であり、私の実行したい処理は、例を言うと
 A.○部署の実績なし(AD46=0) -> IF文内を実行しない(別シートを作成しない)
 B.△部署の実績あり(AD46>0) -> IF文内を実行する(シート名「合計」を別シートにコピーして当該部署の実績表を作成する)
ところが、実績の無い部署を一度処理すると、その後、実績が有ってもIF文内が処理されず、実績なし(AD46=0)と処理されて、職場ごとの実績シートが作成されない。

また、AD46は別に関数を記載しましたがそれ以外が記載漏れであったので、下記に記載します。なお、#6さんの言われた通りに単純にAD46=sum(・・・)に変更しました。

※i2 -> シート名「請求先」に職場名を入力してあるのですが当該請求先の数以上ループさせる必要が無いために、部署数をカウントする関数をSheets("請求先").Range("A5")に入力して、その値を当該変数に代入しています。
※i3 -> 部署番号が連番(同一の番号は付与していません)でないために、シート名「請求先」に入力している部署名の表の上から順番に部署番号を表から抽出する時の当該部署のセルの行数です。
※Sheets("合計").Range("C26") -> =IF($A26="","",VLOOKUP($A26,品名等!$C$6:$F$45,2,FALSE))
※Sheets("合計").Range("A26") -> =IF(ISERROR(SMALL(実績!J$5:J$596,B26))=TRUE,"",SMALL(実績!J$5:J$596,B26))
※Sheets("合計").Range("A26") -> 21(上下に2つの表がありA26は2枚目の1行目のデータセル)
※実績!J$5:J$596 -> 全体で実績のある品目を品目番号を昇順にJ5から列べた

最後に、「if then else end if」等は、この後、実施します。

お礼日時:2003/10/25 14:16

If Range("AD46").Value <> "" Then ~ End If 間が動かないということでしょうか。



なんだか怒られそうなアドバイスですが、Range("AD46")が<>””になるのかは、確認されたのでしょうか。まだでしたら、MsgBox関数で確認されてみては。確認済みでしたらすみません


> Calculate
> Sheets("合計").Select
MsgBox i & "の時 " & Range("AD46").Value
>※2 If Range("AD46").Value <> "" Then
>  If Range("C26").Value = "" Then

この回答への補足

おはよう御座います。

>怒られそうな
折角、回答していただいているのに怒る事なんて・・

>If Range("AD46").Value <> "" Then ~ End If 間が動かないということでしょうか。
テスト動作を何回もしていますが動作はしていると思います。
実際、「msgbox Range("AD46").Value」をテストしていませんでしたが、先ほど実施したところ、msgboxを入力したところ、上手く出来ましたので、私の見解としては、当初の予想通り、msgboxが表示される時間はマクロが中断されているが再計算は処理されているために問題が解決され「If Range("AD46").Value <> ""」の処理が正常に動作したと思っています。
でも、何回も中断させるのは、マクロを使用する意味が無いので別の方法で解決策(私の私見が違えば別ですが)をご存じでしたら、よろしくお願いします。

補足日時:2003/10/20 07:39
    • good
    • 0

A1に 11


A2に =IF(A1<10,1,2)

Sub aaa()
 Range("A1").Value = 1
 Calculate
 If Range("A2").Value = 1 Then
   MsgBox "OK"
 End If
End Sub

上記をExcel97で実行しましたが、メッセージ出ますよ。
マクロ実行中に シートが変わっていて、別のシートの Range("A1") や Range("A2") を対象にしているとか無いですか?

Sub bbb()
 Worksheets(1).Range("A1").Value = 1
 Worksheets(1).Calculate
 If Worksheets(1).Range("A2").Value = 1 Then
   MsgBox "OK"
 End If
End Sub

のように、シートも指定してみては?

この回答への補足

すみません。

実際に問題が発生しているマクロを#5の補足に掲載しましたので、そちらを見て頂けませんか。
今回の問題に対するものは、私が思うところ、マクロの記述が問題ではなく、再計算のマクロがあるにもかかわらず完全に再計算されない状態でマクロが次ぎの処理を実行するものなのかなって勝手に思っています。(思っている事が違うのであれば別ですが・・・)
#5へ記載した内容では次を実行してしまうのであるなら、再計算が完了するまでマクロの実行を中止して、再計算が完了したのちにマクロが実行される方法はないものでしょうか?

以上、よろしくお願いします。

補足日時:2003/10/19 21:52
    • good
    • 0

(元)A1 -> 11(初期値) (正)A1 -> 11(初期値)


(元)A2 -> if(A1>10,1,2)  (正)A2 -> =if(A1<10,1,2)
ですよね。
これだと困っている事象の再現になりません(上手くいっちゃう)。
結論は結局どうなりました?この例では、起こっている事象の置換えになっていないのではないでしょうか?
したがって、例え識者でも答えられない。
したがって、そのまま実際例を出してはどうですか。
職務上困りますか。 

この回答への補足

マクロの一部を掲載します。
※1でデータを入れて、再計算をさせて、※2で計算した結果により条件選択させるのですが※3の頃になって、シート名『合計』が再計算されるため、※2での条件選択が機能しない。
なお、関数は数段階あるため、関数も全て記載するとなると同ファイルを添付しないと分からないと思います。(公然と公開するとなると問題となりますのでチョット無理ですが・・・)
以上です。

Application.Calculation = xlAutomatic
For i = 0 To i2
 Sheets("合計").Select
 Range("A1").Select
 If i = 0 Then
  Range("A1").ClearContents
 End If
 If i <> 0 Then
  Sheets("請求先").Select
  i3 = i + 4
  a = "B" & i3
  Calculate
  b = Range(a).Value
  Sheets("合計").Select
※1  Range("A1").Value = b
 End If
 Calculate
 Sheets("合計").Select
※2 If Range("AD46").Value <> "" Then
  If Range("C26").Value = "" Then
   ActiveSheet.PageSetup.PrintArea = "$B$1:$AD$25"
  End If
  If Range("C26").Value <> "" Then
   ActiveSheet.PageSetup.PrintArea = "$B$1:$AD$46"
  End If
  Sheets("合計").Select
  Sheets("合計").Copy After:=Sheets("合計")
  x = "年間計" & Range("A4").Value
  Sheets("合計 (2)").Name = x
  If x = "年間計『総合計』" Then
   Sheets("年間計『総合計』").Move Before:=ActiveWorkbook.Sheets("実績")
  End If
  If x <> "年間計『総合計』" Then
   Sheets(x).Move Before:=ActiveWorkbook.Sheets("品名等")
  End If
※3 Cells.Select
  Selection.Copy
  Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
  Columns("A:A").Delete
  Range("A1").Select
 End If
Next
Application.Calculation = xlManual

補足日時:2003/10/19 21:25
    • good
    • 0
この回答へのお礼

補足の追加です。

※1と※2の間に、シート名「合計」のセル「AD46」にマクロで計算式を入れ直し、再計算しても駄目でした。

すみません、よろしくお願いします。

お礼日時:2003/10/19 22:13

次のように、デバッグ用のコードを入れて実行とたらどうなります。



Range("X1") = Range("A2") '******
Range("A1").value = 1
Range("X2") = Range("A2") '******
Calculate
Range("X3") = Range("A2") '******
if Range("A2").value = 1 then
 msgbox "OK"
endif
Range("X4") = Range("A2") '******
end

Xはあいてる列に書き換えてください。

この回答への補足

何度もありがとう御座います。

実際のマクロには、A1に値を入れて、再計算後にA2に同じ計算式を入れ直して、また、再計算させて実行しましたが、同様に無理でした。

なお、Calculateだけでなく、先頭にApplication.Calculation = xlAutomaticもいれました。

結果として、条件選択の関数も数個あるうち最後の1個のみ計算式を再入力しただけなので、もっと、計算式を再入力させないと無理なのでしょうか?

補足日時:2003/10/19 16:06
    • good
    • 0

#1の答えどおりlistさんのVBAでは「ok」メッセージは表示されずに終了します。


セルA1に初期値「11」が入っていても
「Range("A1").value = 1」でセルA1は「1」になりますよね?そうするとif文では Range("A2").value = 2 になるためif文の「false」となり、終了します。
なぜ「Range("A1").value = 1」のコーディングが必要なのか趣旨が不明です。

この回答への補足

すみません記載ミスです。
実際に、これだけの関数及びマクロであれば、今までの経験上から問題なく動作すると思っています。
ただ、実際のマクロ及び関数を記載するのが分かってもらううえで必要であることは承知していますが、記載しきれないため、表現したい内容を記載しました。
なお、実際にマクロが実行されているのを画面にて確認するとマクロが再計算の次の行を実行したあと、再計算されている状況であったため、同表現を記載するためのマクロでしたが記載内容に間違いがあったために誤解を招いた事、申し訳ありませんでした。

誤:A2 -> if(A1>10,1,2)
正:A2 -> if(A1<10,1,2)

補足日時:2003/10/19 15:41
    • good
    • 0
この回答へのお礼

すみません、良く確認すると補足の内容が不十分であったために、こちらより補足させて下さい。

>なぜ「Range("A1").value = 1」のコーディングが必要なのか趣旨が不明です。

A1に入力されている初期値に対する、A2の結果を変更させるために「Range("A1").value = 1」を記載しました。
よって、初期値のA1の値に対するA2が変更しても「if ・・・」が初期値に対するA2の結果により条件処理を実行してしまうと言う事が言いただけです。

どの様に表現したら良いか悩んだのですが、結果的に誤解を招きまねいてしまい申し訳ありませんでした。

お礼日時:2003/10/19 16:01

A2 のセルには見かけ上 1 又は 2 と表示されますが、


あくまでもA2セルに格納されている”値”は、"if(A1>10,1,2)" です。

だから if Range("A2").value = 1 then とやっても”真”になることはありません。

この回答への補足

> A2セルに格納されている”値”は、"if(A1>10,1,2)"

「=if(A1>10,1,2)」と記載しなかったために、入力されているのが計算式でなく文字列だから、結果は必ず”偽”であると言われているのでしょうか?
もし、その通りであるなら#1でも記載したのに加えて記載ミスがあった事をお詫びします。

以上、#1の補足も併せて、よろしくお願いします。

補足日時:2003/10/19 15:45
    • good
    • 0

『OK』メッセージが表示されないのが、プログラムどおりだと思います。



Range("A1").value = 1
Calculate
'A2 := if(A1>10,1,2)
if Range("A2").value = 1 then
 msgbox "OK"
endif
end

この回答への補足

すみません記載ミスです。
実際に、これだけの関数及びマクロであれば、今までの経験上から問題なく動作すると思っています。
ただ、実際のマクロ及び関数を記載するのが分かってもらううえで必要であることは承知していますが、記載しきれないため、表現したい内容を記載しました。
なお、実際にマクロが実行されているのを画面にて確認するとマクロが再計算の次の行を実行したあと、再計算されている状況であったため、同表現を記載するためのマクロでしたが記載内容に間違いがあったために誤解を招いた事、申し訳ありませんでした。

誤:A2 -> if(A1>10,1,2)
正:A2 -> if(A1<10,1,2)

補足日時:2003/10/19 15:30
    • good
    • 0

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

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

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

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

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

Qエクセル 再計算とVBA の優先順位??

シュミレーションの結果が合わないのですが

エクセル 列 約70 1パターン6列 の10個と 合計列
行は 約300 300*70= 21.000セル?
セルには 何らかの 式が埋め込まれています。
1パターンの中の列に 手間のかかりそうなのは 1列だけ18行の移動平均があります。他の列は、隣の足し算とか、比較してどうこう・・・(よって 移動平均は 合計10列)

で、このワンパターン に 各パラメーターが有って これを変化させて 再計算して 合計の変化でMAXを 取り出す

プログラムは
c4=0 i4=0 ・・・・10個のパラメーターに初期値代入 
この時点で セルの再計算
do
if max<合計セル then
  do
   Call Sleep(5)
  DoEvents
   z = z + 1
   If z > 5 Then
    Exit Do
   End If
loop
ここに 入れる? 合計セルが遅れて パラメーターが先行してたら意味ないような??
  max=合計セル 
  記録(max、c4.i4・・・・・・)

endif

c4=c4+1 この時再計算
sleepがないと 秒 10回くらい変化する
21.000セルが 10回計算してるとは 思えないのですが?
if c4>6 then
c4=0
i4=i4+1  この時再計算

if i4>6 then
i4=0
o4=o4+1  この時再計算
10個まで同じロジックが続く

ここに sleep を 入れる??

loop

で、問題は sleep を 入れないとき、計算が進んで、別の保存プログラムにパラメータを入れて合計を見るのですが、記録されたパラメーターと合計が合わないのです。
しかし、
MAXが更新されたときの中にブレークポイントを付けて、ストップ状態で(別のことしてたので、かなり止まってた)、保存プログラムにパラメーター代入、合計確認すると合っていました。

で、知りたいのは
再計算とVBAの整合性は エクセルは 取ってくれないのか?
再計算が完了しようが 途中であろうと、VBAだけ お構いなしに ループするのか

はっきりしてるのは パラメータを弄った 後に Sleep入れるのが 最適なのでしょうが、6*6*6*・・・
の仕事量ですから、ここで 0.5秒取られても 合計時間がかかる。

記録の所だけなら、MAXが更新した時だけですから 時間が早いのですが・・・

この辺の状況、ご存知の方が いらっしゃればご教示ください。

シュミレーションの結果が合わないのですが

エクセル 列 約70 1パターン6列 の10個と 合計列
行は 約300 300*70= 21.000セル?
セルには 何らかの 式が埋め込まれています。
1パターンの中の列に 手間のかかりそうなのは 1列だけ18行の移動平均があります。他の列は、隣の足し算とか、比較してどうこう・・・(よって 移動平均は 合計10列)

で、このワンパターン に 各パラメーターが有って これを変化させて 再計算して 合計の変化でMAXを 取り出す

プログラムは
c4=...続きを読む

Aベストアンサー

試したわけではありませんが
http://msdn.microsoft.com/ja-jp/library/ff196047.aspx

セルに値代入後かな?に
(コードを端折られているので特定できません。)
そちらでお考えになってください。
do while Application.CalculationState <> xlDone
sleep 200
loop
で待機

http://msdn.microsoft.com/ja-jp/library/ff821508(v=office.15).aspx
を余計なイベントが発生しないように適当なところに挟み込む
(必要があるかどうかは、そちらで確認してください)

あと、位取りに「.」を使うのは止めてください。 21,000
余計なところで思考がストップしてしまいました (^_^;)
日本語環境でないPCでしたらご容赦。

Qファイルを処理中に次の処理に移ってしまうようなのですが、、

VB.NETですが、
趣味でアプリケーションを作成しています。
下記のコードで処理を実行させています。

Call Shell("C:\aaa.exe c:\test.txt c:\test2.txt", AppWinStyle.Hide)

(A)

Dim sr As New System.IO.StreamReader("c:\test2.txt", System.Text.Encoding.Default)
Dim sb As New System.Text.StringBuilder(CInt(Microsoft.VisualBasic.FileSystem.FileLen("c:\test2.txt") * 1.1))

'ファイルの最後までループ
Do Until sr.Peek = -1
sb.Append(sr.ReadLine & vbCrLf)
Loop
sr.Close()


"aaa"はtest.txtを加工してtest2.txtとして出力するプログラムです。
その後、test2を最後まで読み出しているのですが、
どうもプログラムaaaが処理を終了する前に
次の読み出し処理に移ってしまっているようなのです。
そこで、素人なりに上記(A)の部分に

For i = 0 To 2000000000
Next
For i = 0 To 2000000000
Next

とForループを加えて時間稼ぎしているのですが、
状況によって時間稼ぎがうまくいかない場合があります。どのように問題を回避すべきでしょうか?
aaaはDLLでも組み込み可能になっているプログラム
なのですがDLLで実行させると何らかのメリット
があるのでしょうか?
その点を教えていただけると助かります。
回答よろしくお願いいたします。

VB.NETですが、
趣味でアプリケーションを作成しています。
下記のコードで処理を実行させています。

Call Shell("C:\aaa.exe c:\test.txt c:\test2.txt", AppWinStyle.Hide)

(A)

Dim sr As New System.IO.StreamReader("c:\test2.txt", System.Text.Encoding.Default)
Dim sb As New System.Text.StringBuilder(CInt(Microsoft.VisualBasic.FileSystem.FileLen("c:\test2.txt") * 1.1))

'ファイルの最後までループ
Do Until sr.Peek = -1
sb.Append(sr.ReadLine & vbCrLf)
Loop
sr.Close()...続きを読む

Aベストアンサー

Dim hProc As System.Diagnostics.Process

'プロセス作成
hProc = System.Diagnostics.Process.Start("C:\aaa.exe c:\test.txt c:\test2.txt")
'プロセス終了待機
hProc.WaitForExit()
hProc.Close()
hProc.Dispose()

Dim sr As New System.IO.StreamReader("c:\test2.txt", System.Text.Encoding.Default)
Dim sb As New System.Text.StringBuilder(CInt(Microsoft.VisualBasic.FileSystem.FileLen("c:\test2.txt") * 1.1))

'ファイルの最後までループ
Do Until sr.Peek = -1
sb.Append(sr.ReadLine & vbCrLf)
Loop
sr.Close()

これでどうでしょうか。

Dim hProc As System.Diagnostics.Process

'プロセス作成
hProc = System.Diagnostics.Process.Start("C:\aaa.exe c:\test.txt c:\test2.txt")
'プロセス終了待機
hProc.WaitForExit()
hProc.Close()
hProc.Dispose()

Dim sr As New System.IO.StreamReader("c:\test2.txt", System.Text.Encoding.Default)
Dim sb As New System.Text.StringBuilder(CInt(Microsoft.VisualBasic.FileSystem.FileLen("c:\test2.txt") * 1.1))

'ファイルの最後までループ
Do Until sr.Peek = -1
sb.Append(sr.Read...続きを読む

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エクセル:マクロ「Application.CutCopyMode = False」って?

エクセルのマクロを記録していると

「Application.CutCopyMode = False」

というものがよく出てきますが、これは何でしょう?
どういう意味のものかわかりません。
削除しても差し支えないのもでしょうか?

Aベストアンサー

「Application.CutCopyMode = False」の前で
セルのコピー、または切り取りを行っていると思います。
これは、その操作(セルのコピー、または切り取り)を無効にしているだけです。
------------
Range("A1").Select
Selection.Copy ← これを無効にしている
Range("A2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
------------
上記の場合であれば、「Application.CutCopyMode = False」を削除しても問題ありませんが、
以下の場合、貼り付け処理でエラーになります。
------------
Range("A1").Select
Selection.Copy
Range("A2").Select
Application.CutCopyMode = False
ActiveSheet.Paste ← ココでエラー
------------
ご自分で、セルをコピーしてみると分かると思いますが、コピーした範囲が点線で点滅されます。
「Application.CutCopyMode = False」をすると、
その点滅がなくなります。

「Application.CutCopyMode = False」の前で
セルのコピー、または切り取りを行っていると思います。
これは、その操作(セルのコピー、または切り取り)を無効にしているだけです。
------------
Range("A1").Select
Selection.Copy ← これを無効にしている
Range("A2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
------------
上記の場合であれば、「Application.CutCopyMode = False」を削除しても問題ありませんが、
以下の場合、貼り付け処理でエラーになります。
------------
...続きを読む

Q【Excel】短時間で再計算をすませる方法

たくさんの計算式が入ったシートを保存しようとすると、再計算に入ってとても時間がかかることがあります。
設定で、手動で再計算にしちえるのですが少しでも計算を短くする方法があれば教えてください。

Aベストアンサー

計算式を(もちろん結果は同じになるよう)変える、配列数式を使わない、代入で出来るところは同じような式は入れない、などは出来ても、実際問題として、式を組み変えることは、質問とは別問題でしょうね。
だから式を今のままにして、計算だけ、エクセルの設定などで、早めることは、できるはずが無い。シートの式が決まれば、エクセルの同じプログラムが一気に走るはず。
ーー
ただその瞬間のそのパソコンの内部メモリやディスクの空き状態が影響するかもしれないというのは、ミクロで考えられるが、その場に即してのことを、我々がはっきりいえるだけの知識も持ってないでしょう。
ーー
VBAでプログラムをやれるなら、関数ーー>プログラムに組み替えて、早くなるケースはあるように思う。
計算速度ではないが、このコーナーの質問で、関数では式が長く思いつきにくい式だが、VBAでやると素直なロジックでやれるものも多いと思う。これも計算速度に影響すると思う。
ただ関数とVBAで実行速度はどちらが速いかは前もって、計算できるようなものではないとおもう。
やってみるしかない。
ーーー
VBAでは、ScreenUpdating=Falseという、画面更新について、計算の都度は、毎セルについて表示を行わないセルの設定も出来る。

計算式を(もちろん結果は同じになるよう)変える、配列数式を使わない、代入で出来るところは同じような式は入れない、などは出来ても、実際問題として、式を組み変えることは、質問とは別問題でしょうね。
だから式を今のままにして、計算だけ、エクセルの設定などで、早めることは、できるはずが無い。シートの式が決まれば、エクセルの同じプログラムが一気に走るはず。
ーー
ただその瞬間のそのパソコンの内部メモリやディスクの空き状態が影響するかもしれないというのは、ミクロで考えられるが、その場...続きを読む

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

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

Aベストアンサー

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

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

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でRange("A1:C4")を変数にする方法を教え

EXCELのVBAでRange("A1:C4")を変数にする方法を教えて下さい。

Sub Sample1()
Range("A1:C4").Borders.LineStyle = True
End Sub

上のマクロの"A1:C4"を変数にして成立させるにはどのように設定すればいいのでしょうか?
以下の方法ではエラーになってしまうので、宜しくお願いします。

Sub Sample1()

HENSU = Chr(34) & "A1" & ":" & "C4" & Chr(34)
Range(HENSU).Borders.LineStyle = True
End Sub

Aベストアンサー

こんなので好いですか?
下記をモジュールシートへ貼り付けて試行してみて下さい。

Sub Sample2()
Dim HENSU As String '←変数の宣言をします。

HENSU = Chr(34) & "A1" & ":" & "C4" & Chr(34) ' ""A1:C4"" を返します。←NG
HENSU = "A1" & ":" & "C4" ' "A1:C4" を返します。←OK
HENSU = "A1:C4" ' "A1:C4" を返します。←OK
Range(HENSU).Borders.LineStyle = True ' HENSUの範囲に罫線を引きます。
End Sub

Q特定のシートのみ再計算させない方法は?

特定のシートのみ再計算させない方法はありませんか?

1つのBOOKに2つのシートがあり、
[sheet1]=自動計算
[sheet2]=手動計算
という設定を行いたいと考えています。

BOOKを分けずにスマートな方法はないでしょうか。

Aベストアンサー

こんばんは。

本来は、ワークシートのプロパティの、EnableCalculation を False にしてあげれば、片方のシートは、手動になります。(プロパティの出し方は、ワークシートをアクティブな状態にして、[コントロールツールボックス]のプロパティを押せば、[シート・プロパティ]が出てきます)

しかし、手作業の設定ですと、ブックを閉じて、再び開けた時には、デフォルトの True に戻ってしまいます。


そこで、VBAによる手段しかありません。

[ツール]-[マクロ]-[Visual Basic Editor] (ショートカット= Alt + F11)
で、

左上に、プロジェクトというエクスプローラがありますから、
その中から、

[ThisWorkbook ]

というのを、ダブルクリックして、エディタ画面を開けたら、

以下のコードを貼り付けて、保存し、再び、このブックを開けると、設定されています。

'---------------------------------------
Private Sub Workbook_Open()
'シート2を手動計算にさせる
ThisWorkbook.Worksheets("Sheet2").EnableCalculation = False
End Sub

'---------------------------------------

こんばんは。

本来は、ワークシートのプロパティの、EnableCalculation を False にしてあげれば、片方のシートは、手動になります。(プロパティの出し方は、ワークシートをアクティブな状態にして、[コントロールツールボックス]のプロパティを押せば、[シート・プロパティ]が出てきます)

しかし、手作業の設定ですと、ブックを閉じて、再び開けた時には、デフォルトの True に戻ってしまいます。


そこで、VBAによる手段しかありません。

[ツール]-[マクロ]-[Visual Basic Editor] (ショート...続きを読む

QEXCEL2007 VBAでピボットのフィルタ指定

EXCEL 2007 VBAでピボットテーブルを生成しようとしております。

レポートフィルタで初期表示するデータフィールド「メーカー」の値も
指定できればと思っております。

「メーカー」には今回データで「A」「B」「C」「D」「E」とあったとして
「メーカー」 ... 「A」と「C」だけで表示指定したいとして、
下記操作で記録マクロを取ってみました。

1. レポートフィルタ「メーカー」を追加
2. フィルタ条件で「(すべて)」のチェック外して、全て消す。
3. 「メーカー」 ... 「A」と「C」を指定

結果は希望通りなのですが、
記録マクロを確認すると下記のように「A」と「C」で指定できておりません。

これだとメーカー「F」のデータが追加された際、
希望通りでないと思うのですが、良い方法をどなたかご存じないでしょうか?

ActiveSheet.PivotTables("数量予測").PivotFields("メーカー").CurrentPage = "(All)"
With ActiveSheet.PivotTables("数量予測").PivotFields("メーカー")
.PivotItems("B").Visible = False
.PivotItems("D").Visible = False
.PivotItems("E").Visible = False
End With

EXCEL 2007 VBAでピボットテーブルを生成しようとしております。

レポートフィルタで初期表示するデータフィールド「メーカー」の値も
指定できればと思っております。

「メーカー」には今回データで「A」「B」「C」「D」「E」とあったとして
「メーカー」 ... 「A」と「C」だけで表示指定したいとして、
下記操作で記録マクロを取ってみました。

1. レポートフィルタ「メーカー」を追加
2. フィルタ条件で「(すべて)」のチェック外して、全て消す。
3. 「メーカー」 ... 「A」と「C」を指定

結果は希望通...続きを読む

Aベストアンサー

Ver2007でClearAllFiltersメソッドが追加されました。
繰り返して使う場合も想定して、ClearAllFiltersで一旦全表示にします。
その後、表示したいアイテムを指定して、それ以外(Case Else)は非表示、
という処理で良いかと思います。

Sub try()
  Dim pf As PivotField
  Dim p As PivotItem

  Set pf = ActiveSheet.PivotTables("数量予測").PivotFields("メーカー")
  pf.Orientation = xlPageField
  pf.ClearAllFilters
  For Each p In pf.PivotItems
    Select Case p.Value
    Case "A", "C" '表示アイテム名をカンマ区切りで指定
    Case Else
      p.Visible = False
    End Select
  Next
End Sub

Ver2007以降でないと動作しません。
2003でも使う可能性があるなら以下のようにPageFieldを再配置。
但し、再配置前に更新する必要があります。

Sub try_2()
  Dim pf As PivotField
  Dim p As PivotItem

  Set pf = ActiveSheet.PivotTables("数量予測").PivotFields("メーカー")
  pf.Orientation = xlHidden
  pf.Parent.PivotCache.Refresh
  pf.Orientation = xlPageField
  For Each p In pf.PivotItems
    Select Case p.Value
    Case "A", "C" '表示アイテム名をカンマ区切りで指定
    Case Else
      p.Visible = False
    End Select
  Next
End Sub

Ver2007でClearAllFiltersメソッドが追加されました。
繰り返して使う場合も想定して、ClearAllFiltersで一旦全表示にします。
その後、表示したいアイテムを指定して、それ以外(Case Else)は非表示、
という処理で良いかと思います。

Sub try()
  Dim pf As PivotField
  Dim p As PivotItem

  Set pf = ActiveSheet.PivotTables("数量予測").PivotFields("メーカー")
  pf.Orientation = xlPageField
  pf.ClearAllFilters
  For Each p In pf.PivotItems
    Select Case p.Value
   ...続きを読む


人気Q&Aランキング