• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:エクセルVBA 他の仕事を止めない時間稼ぎ)

エクセルVBAで他の仕事を止めずに時間を稼ぐ方法

cj_moverの回答

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.2

(1/2) こんにちは。お邪魔します。 すみませんが、長くなるので連投します。 ニーズを正確に理解出来ている訳ではないので、それぞれのパーツの話、、、です。 > で、時間を稼ぎたいのですが、 > 今は、タイマーで > act時刻 = Now > act時刻 = DateAdd("n", 2, act時刻 ) > 待ち時間 = DateAdd("s", 20, act時刻 ) > Application.OnTime act時刻 , "next-job", 待ち時間 > このタイマーが不正確(動作したりしなかったり)で 上の式は 2分待ちですが 1分以下だと 100%起動せず、 > 1分40秒以上でどうやら・・・ 本題とは関係ないですが、OnTime メソッドの話から。 考え方として、  ×| EarliestTime | ★ | LatestTime |× EarliestTime と LatestTime の間★の期間に、【タイミング】が合えば、Procedureは実行されます。 i)「OnTime メソッドを実行したプロシージャ」 を抜け(の処理が終り)、 ii)「OnTime メソッドを実行したプロシージャ、を呼び出した大元を含む実行中のすべてプロシージャ」 を抜け(の処理が終り)、 iii)「他に実行されるべきアプリケーションのタスク」 の処理が済んだ後 この【タイミング】が★の期間内に収まっていれば、Procedureが実行されます。 ですから、EarliestTimeを「早め」に設定し、LatestTime「遅め」に設定し、★の期間を「長く」取った方が、 Procedureは実行され易い、ということになります。 そういう意味では  Application.OnTime Now, "proc", DateAdd("n", 20, Now) 「今、から、20分後、まで」みたいに書いておけば、【タイミング】が来次第、Procedureは実行されます。 しかし、今回の課題の意味からすると、引数LatestTimeは指定しないで、  Application.OnTime Now, "proc" のようなことがなさりたいのではないでしょうか? 引数LatestTimeの意味、としては、指定した時刻を過ぎたら、Procedureを実行しない、です。 もし、この点で不明瞭なのでしたら、今一度、VBAのヘルプ等で確認してみて下さい・ Procedureが実行可能になる【タイミング】について補足しますが、 例えば、ActiveXのコマンドボタンで呼び出すような場合、 1: コマンドボタン押下げ 2: Private Sub CommandButton1_Click() 3:   SubProc 8: End Sub 4: Sub SubProc() 5:   Application.OnTime Now, "proc" 6:   時間の掛かる処理 7: End Sub 9:コマンドボタンの押下げ表示を元に戻す既定の処理 10:OnTime メソッドで設定したProcedureが実行可能になる 11: Sub Proc() 12:   処理 13: End Sub のような順番に処理されることになります。 直接的には、この順番を替えたり、割り込んだりすることは出来ません。 また、上の順番の中で8:9:を4:より前に済ませておく必要があるような場面など ある程度処理の順番を操作したい場合に、 有効な方法として用意されているのがOnTime メソッドでもあり、 この例では、3:の呼び出し部分をOnTime メソッドに書き換えるような使い方 が、重要度の高いOnTime メソッドの代表的な使用例でもあります。 たぶん、今回の課題は直接的にはOnTime メソッドとは無縁だと思います。 (5:6:の順が逆になるように書くことはあると思いますが、、、。) ただ、処理の流れを時系列で把握することは重要ですから、 概念提示という意味では、比較的解り易い例だったと思います。 どのタイミングで End Sub を通るのか、ぐらいは把握していないと書けないものも多いですしね。 > シートにデータ送り込むVBA(15分毎のタイマー)の続きに  > 計算完了、もしくは、セル式の仕事を止めないで、 > セル式計算完了を まって、”next-job” の 仕事をさせたいのですが > セル式の計算 これって「ワークシート(セル範囲)の再計算」のことでいいしょうか? > セル式の仕事を止めない時間稼ぎは無いでしょうか "セルの仕事を止め"る、とは、再計算を中断または終了させる?という意味に読めますけど、 何故そんなことが問題になるのか私には理解できないので教えて頂けませんか。 例えば、セルA1の値を変更(追加)するとして、 値を入力し、Enterキーを押しても、 直接・間接にA1を参照先に持つワークシート上のすべての再計算が終了するまで、 A1セルは確定しませんよね。 VBAでも同じで、  Cells(1, 1) = "hoge" に追従する再計算が終了するまでは次の行の処理に進めません。 なので、次の行を実行する時には、前の行の処理に連動した再計算は終了しているのでは? これが普通で、それ以外は特殊、というのが、これまでの私の常識でしたので、 何か自信無くしそうですが、少し補足説明を戴けたら助かります。 Sleep関数を使っていることも気になっているのですが、 再計算を非同期で実行させるような状況なのでしょうか? 私はマルチスレッドの再計算関連に詳しくないので、私が知らない何か、なのでしょうけれども、、、。 不躾ながら、 Application.CalculationState が使える、というのも、私の理解の外ですが、 それなら、Application_AfterCalculate イベントを使って、 VBAの処理に割り込ませることが有効なケースもあろうかと。 これは本題に近い話だと思いますが、、、。 /// ThisWorkbook モジュール Option Explicit Private WithEvents xlApp As Application Private Sub Workbook_Open()   Set xlApp = Application End Sub Private Sub xlApp_AfterCalculate()   DoEvents End Sub ///(Workbook_Open()を(が)実行すれ(されれ)ばxlApp_AfterCalculate()が有効に) 仮に、DoEventsだけを処理させていますが、 これは再計算時に、ひとつの参照チェーン毎に計算が終了する度に発生するイベントですので、 "セル式の仕事を止めない時間稼ぎ"という言葉の指す意味合いによっては有効な手段かも、です。 (再計算に掛かる時間が長過ぎて、PCがスリープしちゃうとか?) 実際には、Publicなフラグ変数を用意しておいて、セル値の変更処理の度に  フラグ=n → セル値変更 → 再計算  → _AfterCalculate() → フラグ>0ならば、n番めの再計算終了と判断して 必要な処理 → フラグ=0 のようにしてみれば使い道は色々ありそうですけれど。  フラグ = n  Cells(1, 1) = "hoge"   ↓  再計算   ↓ ←ここに_AfterCalculate()が割り込みます。  フラグ = n + 1  次の処理 (次の投稿に続きます)

参考URL:
http://msdn.microsoft.com/ja-jp/library/office/ff840621(v=office.15).aspx
2014itochan
質問者

お礼

恐縮です。 我流でコマンド書いている身としましては、赤面の限りです さて、  Application.OnTime Now, "proc", DateAdd("n", 20, Now) 「今、から、20分後、まで」みたいに書いておけば、【タイミング】が来次第、Procedureは実行されます。 しかし、今回の課題の意味からすると、引数LatestTimeは指定しないで、  Application.OnTime Now, "proc" のようなことがなさりたいのではないでしょうか? 当方の理解では、 タイマー指定時間に実行できる環境でなければ、スルーされ、実行されない。その為のLatestTimeで もう一度この時間にトライされる。よって、トライは2回。 開始時間から、LatestTimeまで パルス的にトライしてくれるかどうか、調べたのですが、探せませんでした。 よって Application.OnTime Now, "proc" パルス的にトライして可能な時間に成ったら・・・ この概念は有りませんでした。これが可能なら、最速の可能な時間に処理が行われることに成り、当方としては、これで願ったり・・・です。 基本なロジックは アドオンで、設定セル(5個ほど)にネット経由でデータの変更が有るたびに送り込まれます。設定セルだけですから、全て上書きです。 それを、Worksheet_Calculate()(これ以外不可)で変化を捉え、時系列に記録を伸ばします。 早い話、株価ですが、以上はコントロール不可能。まったく、相手任せ。いつ仕事がされるか不明(変化したら・・・ですから) 現状は 朝の起動時から9:00 から 15分ピッチで 反復時刻 = 反復時刻 + インターバル 待ち時間 = DateAdd("s", 20, 反復時刻) Application.OnTime 反復時刻, "orgdata.15job", 待ち時間 タイマーを予約し、その時間に 集まったデータを15分データとして、集約します。集約の後、シートにデータを 飛ばします。 15job() 次の15分タイマーを予約 2分後に、セル計算後の”評価JOB”をタイマー予約 コピー開始 orgdata.Range("a4:b4").Copy Destination:=fun15.Range("A" & endsisu) orgdata.Range("c4:f4").Copy Destination:=fun15.Range("d" & endsisu) fun15.Range("c" & 100 & ":c" & 100).Copy fun15.Range("c" & endsisu & ":c" & endsisu).PasteSpecial Paste:=xlPasteFormulas fun15.Range("H" & 100 & ":AZ" & 100).Copy fun15.Range("H"&endsisu&":AZ" & endsisu).PasteSpecial Paste:=xlPasteFormulas fun60.Cells(end60, 1) = fun15.Cells(st15, 1) 省略 fun60.Cells(end60, 7) = fun15.Cells(end15, 7) fun60.Range("c" & 100 & ":c" & 100).Copy fun60.Range("c"&end60& ":c" & end60).PasteSpecial Paste:=xlPasteFormulas fun60.Range("H" & 100 & ":Z" & 100).Copy fun60.Range("H"&end60&":Z" & end60).PasteSpecial Paste:=xlPasteFormulas 15job end 2分後の 評価JOB シートfun15の特定の(4個ほど)セル変化をとらえてアクションを起こす、起こさないを決定します。セル変化を単純に IF文で 比較するだけです。 その結果がTRUEなら フォーム および IEを起動して、証券会社にアクションが起きます。 ここが、お説のようなら(セル式の計算の完了を待って次のコードを実行する) 待ち時間など考慮せず(2分後のタイマー予約なしで)、15job end の続きに、当方は IFの比較文(タイマー中身)を記述すればいいことに成ります。 タイマー有りの時が、時間を短く予約すると タイマー不発 90秒でもやや不安定(アドオンのデータ更新が影響か)。2分でどうにか・・・ で、次のテストが 2分後タイマーを止めて コピーのあと Do Sleep (10) DoEvents xxx = xxx + 1 If xxx > 10000 Then ’ CalculationState = xlDone使ったことないので、念のため yy = orgdata.Cells(1000, 14).End(xlUp).Row + 1 orgdata.Cells(yy, 14) = "ループ-out" & Now Exit Do End If If Application.CalculationState = xlDone Then yy = orgdata.Cells(1000, 14).End(xlUp).Row + 1 orgdata.Cells(yy, 14) = "State = xlDone-out" & Now しまった、ここに xxx の数値を 記録すれば、このループが必要か判明する(来週の話) Exit Do End If Loop Call 評価JOB これで、不発は無いようですが マクロin2014/09/13 1:00:12 マクロcopy-in2014/09/13 1:00:35 マクロfun copy-in2014/09/13 1:00:41 マクロ 60fun copy-out2014/09/13 1:00:51 nothing2014/09/13 1:00:52 State = xlDone-out2014/09/13 1:00:53 注文確認-in2014/09/13 1:00:54 注文確認-suru-out2014/09/13 1:00:55 マクロin2014/09/13 1:15:13 マクロcopy-in2014/09/13 1:15:36 マクロfun copy-in2014/09/13 1:15:41 マクロ 60fun copy-out2014/09/13 1:15:49 変化 買いから 売り State = xlDone-out2014/09/13 1:15:52 注文確認-in2014/09/13 1:15:53 2014/09/13 1:16:00返済 doTradeAfterNoon  2014/09/13 1:17:01新規売り  2014/09/13 1:17:51返済注文 Morning2  マクロin2014/09/13 1:00:12 のスタートから(12秒は無視してください) State = xlDone-out2014/09/13 1:15:52 まで 40秒掛かっている計算。 (それ以降の時間はスルーしてください、IEが絡みますので) さて、頂いたご提案 xlApp_AfterCalculate() について、 話がかなり戻るのですが、本来なら、Worksheet_Change(ByVal Target As Range)で 計算式完了後の変化を捉えることが出来るはずなんですが、これも、不発で むしろ、これの方が 良いかも・・・テストさせていただきます。 時間短縮、あれや、これや、ご教示ありがとうございました。時間がかかりそうですが、検証させていただきたく。 感謝

関連するQ&A

  • エクセル VBAで 再計算をコントロールしたい

    早速ですが。シートは ORGDATA と 計算 の2枚 ORGDATA は WEB経由で 秒単位で 7セルほどのデータを受信します。 それを、5分単位で データを集約し 7セルほどのデータとして、計算シートに コピーで 送ります。 計算シートは、生データは 7セルの 2万行 I列から BU列 50行?位数式が 埋まっています。 基本 ORGDATAシートは Worksheet_Calculate() で 受信しますので、計算を止められません。 で、計算シートの 再計算を止めて、データが送り込まれたとき(5分ピッチ)のみ 再計算させたい。 が リクエストです。 下記が やってみたことの要約です。 Workbook_Open() 5分タイマーセット Application.Calculation = xlCalculationAutomatic Me.Worksheets("計算").Select Me.Worksheets("計算").Activate ActiveSheet.EnableCalculation = False  これが機能してないような?タスクバーに再計算してる%表示が出ている。 Me.Worksheets("orgdata").Select データ受信、5分後のタイマーで endsisu = keisan.Cells(1000, 2).End(xlDown).Row + 1 orgdata.Range("a4:g4").Copy Destination:=keisan.Range("b" & endsisu) keisan.Range("i" & endsisu - 2 & ":bu" & endsisu - 2).Copy keisan.Range("i" & endsisu & ":bu" & endsisu).PasteSpecial Paste:=xlPasteFormulas ここまでは 実行される。 下記のどちらかで VBエラー400(タイマーで 実行しているから) keisan.Range("i" & endsisu - 2 & ":bu" & endsisu).Select Selection.Calculate 要は OREGDATAは 常時再計算ON 計算シートは 常時再計算OFFで データが送り込まれた時だけ 再計算で 済んだら OFF が希望なのですが。 ご教示願えれば助かります。

  • エクセルVBAのコードの書き方を教えてください

    エクセルVBAの初心者です。 下記①-⑲のようなコードを書きたいのですが、どなたかお分かりになる方がいましたら、 ご教示いただけますと幸いです。 ① オートフィルターでシート[list]のA列に"●"がある特定の行だけを以下作業の対象にしたい ② ①で特定した行のE列セルの値を、シート[output]のB9セルにコピペする ③ ①で特定した行のF列セルの値を、シート[output]のB12セルにコピペする ④ ①で特定した行のG列セルの値を、シート[output]のB15セルにコピペする ⑤ ①で特定した行のH列セルの値を、シート[output]のB18セルにコピペする ⑥ ①で特定した行のI列セルの値を、シート[output]のB21セルにコピペする ⑦ ①で特定した行のJ列セルの値を、シート[output]のB24セルにコピペする ⑧ ①で特定した行のK列セルの値を、シート[output]のB27セルにコピペする ⑨ ①で特定した行のL列セルの値を、シート[output]のB30セルにコピペする ⑩ ①で特定した行のM列セルの値を、シート[output]のB33セルにコピペする ⑪ ①で特定した行のN列セルの値を、シート[output]のB36セルにコピペする ⑫ ①で特定した行のO列セルの値を、シート[output]のB39セルにコピペする ⑬ ①で特定した行のP列セルの値を、シート[output]のB42セルにコピペする ⑭ ①で特定した行のQ列セルの値を、シート[output]のB45セルにコピペする ⑮ ①で特定した行のR列セルの値を、シート[output]のB48セルにコピペする ⑯ ①で特定した行のS列セルの値を、シート[output]のB51セルにコピペする ⑰ ①で特定した行のT列セルの値を、シート[output]のB54セルにコピペする ⑱ ①で特定した行のU列セルの値を、シート[output]のB57セルにコピペする ⑲ シート[output]のB3:B59をテキストファイルを呼び出してコピペする ※このとき、上記②-⑱で記述したB9からB57のセルには改行が含まれる場合が  あるため、テキストファイルへのペースト時に""が表示されてしまうが、  もし可能であれば、この""が表示されないようにしたい。

  • エクセルVBAの(Range オブジェクト)の構文を教えて下さい

    Dim ACT As String ・・・・文字列型変数を宣言して セルを選択する場合 ACT = 14 Range("F" & "ACT").Select とした時、(F14) のセルが選択出来ません どこが間違っているのでしょうか、 For-Next 文で繰り返し処理をしたいのですが どのように書けば良いか教えてください。 エクセル2000を使用しています。宜しくお願いいたします。

  • エクセル VBA

    最終行から順番に下へ同列で入力するVBAを教えて下さい。 EXCELのVBAで教えて下さい。 シート1のA列にはB列が入力されると自動入力されるNo.があり、C~G列もB列が入力されると自動入力されます。 B列には日付が、H列には3~4桁の数字が入力したいのですが、 入力行は必ず最下行のセルB、Gな為、VBAでフォームを作成し、 入力実行ボタンを押すことにより、最下行のセルB、Gに反映されるように したいです。 又、上記入力後に、シート2のH~N列をコピーして、シート3のA~G列に値のみの貼り付けを行い保存した後、シート3のA~G列をコピーして csvファイルを作成して保存したいです。 一連の流れを、フォームの入力実行ボタンを押すことで実行したいのですができるのでしょうか? 宜しく御願い致します。

  • Excel VBA

    Excel VBAについて シート1にはデータが入ってます。 G列に日付、L列に商品名、N列に件数。 シート2には集計結果を入力したいです。 セルB2に、日付が10月1日から15日までで、商品名がAの件数の合計。 セルB3は、日付が10月16日から末日まで、セルB4は、日付が11月1日から15日までと半月毎に集計を半年後の末日まで繰返し、B2の数行下には、商品名Bの集計行を作り、その数行下には商品名Cの集計行を作りたいです。 これまでは関数SUMIFSで集計していましたが、複数店舗分のシートの更新・メンテナンスが大変なので、VBAでの集計を考えいろいろ調べてるのですが、方法が思い付かないので、ご教授ください。

  • EXCEL VBAについて

    いつも識者の皆様にはお世話になっております。 Excel VBAのことで質問させてください。 下記のようなシートがあります。 データの状態は下記です。 1. 1行目は必ずタイトル行になっています。 2. 1行目が「入荷_1」になっている列以降の日付はシリアル値となっています。 ※必ずしもG1が「入荷_1」となっているとは限りません。H1だったりI1だったりします。 VBAでやりたいことは下記です。 1. 過去取引と現在取引の状態によってA列に入力する文字列を変える。 過去取引_1=有 現在取引_1=有 の場合 「OK」 過去取引_1=有 現在取引_1=無 の場合 「NG」 過去取引_1=ブランク 現在取引_1=有 の場合 「確認要」 2. 「入荷_1」以降の列で「入荷_1」「出荷_1」など、アンダーバー以降の文字列が同じになっている2列を一まとめとして、そのどちらかもしくは両方に日付の入っているセルを探し、その列の1行目の、アンダーバーの次の文字から最後の文字までを[]で囲んだ文字列をB列に入力する。 ※_1にも_2にもある場合は、アンダーバーを使って文字列を連結する。(B2セル) ※パイナップルやぶどうのように入荷か出荷のいずれかにしか日付が入っていないものもある。 3. タイトル行が「入荷_1」となっている列以降で日付の入っている列を探し、出荷から入荷を引いた数字をC列に入力する。 ※_1にも_2にもある場合は、アンダーバーを使って文字列を連結する。(C2セル) これを2行目から1行ずつ最後の行まで行い、かつ、このシートはブックにある複数のシートの中の1つですが、BA1セルが空白ではないシートにだけこの処理をしたいのです。 どうやらSelect Caseという構文を使えばできそうだというところまで突き止めたものの、条件が僕には複雑すぎて(特に2列を1まとめにするところ)まったく進みません。 どなたか、上記内容の場合どのような構文になるのか教えていただけませんでしょうか。 よろしくお願いいたします。

  • Excelで別のシートの内容を表示させたい

    Sheet1のA2からC50までの範囲にデータを出力し(どこのセルに入るかは可変)、 その内容に従ってSheet2の決まったセルに表示させたいのですが、どのような式にすれば良いか教えて下さい。 条件を言葉で書くと、 Sheet1のA列に001があれば、その行のC列の値をSheet2のJ8に表示する。 参考に、Sheet1のA列はコード名、B列は計算内容、C列は計算結果が別のデータベースから出力されます。 計算結果が0だと出力されず、出力したものは2行目(1行目はタイトル行)から詰めて入ります。 その結果、A2からC50までの範囲のどこに入るかわからないのです。 よろしくお願いします。

  • Excelの時間の計算

    時間の計算の算出方法について質問です。 セルE16に 2015/11/25  17:59 という日付けと時間が入力されています。 セルH16に同じような形式で日付けと時間が入力された場合 セルK16に経過時間を表示する方法を教えて下さい。 ちなみにK16の経過時間は30分以上いくことは絶対にないので 分表示のみで大丈夫です(○○min と表示したい) またE16、H16ともに、マクロにて、セルの所でダブルクリックすると日付けと時間が 入るようになっています。 理想としてはH16の所でダブルクリックしたときにH16に日付けと時間が入力され K16に経過時間を表示という形にしたいです。 このような計算をした箇所が20行あります。 列は変わりません。 16から35行まで。 ご指導の程、宜しくお願いします。

  • エクセルVBA プログレスバー表示について

    いつもお世話になります。 ワークシート関数の計算中に、プログレスバーの目盛りを進めることは出来るでしょうか。 というのは、マクロで約1200行×50列=60000個のセルにワークシート関数(SUMPRODUCT関数などの、かなり時間のかかる関数が多く含まれています)を書き込んでいるのですが、中々計算が終わらないので、固まっているように見えるのです。 以上宜しくお願い致します。

  • EXCELの時間計算

    セルA1に、「9:43:20」と時刻が入力されています。 セルB1に、「3.2」と時間(分)が入力されています。 セルC3には、A1の時刻から,B1の時間が経過した後の時刻を 表示させたいです。 ※B1の「3.2」を3.2分(3分12秒)として計算したいです。 C3の計算式を教えてください。 ※計算した結果の時刻は,9:46:32です