Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


8844 / 13646 ツリー ←次へ | 前へ→

【30694】イベントプロシージャーを自作関数 川崎 05/11/3(木) 3:44 質問[未読]
【30699】Re:イベントプロシージャーを自作関数 Kein 05/11/3(木) 11:41 回答[未読]
【30702】Re:イベントプロシージャーを自作関数 川崎 05/11/3(木) 13:42 質問[未読]
【30707】Re:イベントプロシージャーを自作関数 Kein 05/11/3(木) 15:45 発言[未読]
【30710】Re:イベントプロシージャーを自作関数 川崎 05/11/3(木) 18:57 質問[未読]
【30711】Re:イベントプロシージャーを自作関数 ichinose 05/11/3(木) 21:16 発言[未読]
【30725】Re:イベントプロシージャーを自作関数 川崎 05/11/4(金) 0:25 質問[未読]
【30727】Re:イベントプロシージャーを自作関数 ichinose 05/11/4(金) 7:02 発言[未読]
【30758】Re:イベントプロシージャーを自作関数 フレッツ 05/11/4(金) 14:33 お礼[未読]
【30790】Re:イベントプロシージャーを自作関数 ichinose 05/11/4(金) 19:40 発言[未読]
【30805】Re:イベントプロシージャーを自作関数 川崎 05/11/4(金) 23:01 質問[未読]
【30811】Re:イベントプロシージャーを自作関数 川崎 05/11/4(金) 23:30 質問[未読]
【30815】Re:イベントプロシージャーを自作関数 こたつねこ 05/11/4(金) 23:48 回答[未読]
【30812】Re:イベントプロシージャーを自作関数 こたつねこ 05/11/4(金) 23:33 発言[未読]
【30817】Re:イベントプロシージャーを自作関数 川崎 05/11/5(土) 0:05 回答[未読]
【30819】Re:イベントプロシージャーを自作関数 こたつねこ 05/11/5(土) 0:51 発言[未読]

【30694】イベントプロシージャーを自作関数
質問  川崎  - 05/11/3(木) 3:44 -

引用なし
パスワード
   Option Explicit

Sub Workbook_SheetCalculate(ByVal Sh As Object)
Dim Dt1() As Double, Dt2() As Double
If Not IsNumeric(Range("E2").Value) Then Exit Sub
If Range("E2").Value > Dt2 Then
    Dt2 = Range("E2").Value '入力された値
    If Dt1 > 0 Then
      With Application
        .EnableEvents = False
      Range("F2").Value = Dt2 - Dt1
        .EnableEvents = True
      End With

    End If
     Dt1 = Dt2
    
  End If
End Sub

☆このイベントプロシージャーを自作関数にすることはできるのでしょうか?
どこをどのようにしたら自作関数になるのでしょうか?

【30699】Re:イベントプロシージャーを自作関数
回答  Kein  - 05/11/3(木) 11:41 -

引用なし
パスワード
   数式を入力するセルの、1つ左のセルの値を Dt2 として

Function MyClc(Dt1 As Double) As Double
  With ActiveCell.Offset(, -1)
   If IsEmpty(.Value) Then Exit Function
   If Not IsNumeric(.Value) Then Exit Function
   Dt2 = .Value
  End With
  MyClc = Dt2 - Dt1
End Function

という式で =MyClc(数値Dt1) と入力すれば、計算結果が出ます。

【30702】Re:イベントプロシージャーを自作関数
質問  川崎  - 05/11/3(木) 13:42 -

引用なし
パスワード
   ▼Kein さん:
>数式を入力するセルの、1つ左のセルの値を Dt2 として
>
>Function MyClc(Dt1 As Double) As Double
>  With ActiveCell.Offset(, -1)
>   If IsEmpty(.Value) Then Exit Function
>   If Not IsNumeric(.Value) Then Exit Function
>   Dt2 = .Value
>  End With
>  MyClc = Dt2 - Dt1
>End Function
>
>という式で =MyClc(数値Dt1) と入力すれば、計算結果が出ます。

ご回答ありがとうございます!
あの〜大事な部分なので解説を頂ければと思います。
ActiveCell.Offset(, -1)はなぜ−1になっているのでしょうか?
それとWorkbook_SheetCalculateの部分はどこにいってしまったのでしょう?
数値Dt1に入るのは数式なんですが、直接数式を入力して
大丈夫ですか?
よろしくお願いします。

【30707】Re:イベントプロシージャーを自作関数
発言  Kein  - 05/11/3(木) 15:45 -

引用なし
パスワード
   >ActiveCell.Offset(, -1)はなぜ−1になっているのでしょうか?
もとのマクロでは、E1とF1の関係がそうなっていたからです。
つまりF1を、この数式を入れる任意のセルとすれば、Dt2 はその1つ左のセル(E1)
の値、という解釈をしたためです。
>Workbook_SheetCalculateの部分はどこにいってしまったのでしょう?
自作関数にしたいと言うのだから、そのようなイベントマクロではなくなる
でしょう。当然のことですが。
>数値Dt1に入るのは数式なんですが、直接数式を入力して大丈夫ですか?
これは "関数の中に数式を入れる" ということでしょーか ?
それとも "数式で結果を表示しているセルを参照する" ということなんでしょーか ?

【30710】Re:イベントプロシージャーを自作関数
質問  川崎  - 05/11/3(木) 18:57 -

引用なし
パスワード
   すいません、説明不足でしたね。
私がしたいことを具体的にあげると
たとえばA1セルにある数式を入れます。その数式が100の値を返した
とします。次にそのA1が150を返したとするとその差分の
150-100=50を計算してB1セルならB1セルに代入したいのです。

ここで問題なのが、こういったことを何百ものセルで行いたいのです。
たとえばF3〜F115など
ですので関数にしたほうが記述上、運用上扱いやすくなるのではないかと
思ったのです。
それとWorkbook_SheetCalculateはできるだけ必須にしてもらいたいのですが。
関数にすると同じことはできないのでしょうか?
数式がいつ値を返すのか不定期なため再計算のとき動作させたいのですが・・

>これは "関数の中に数式を入れる" ということでしょーか ?
>それとも "数式で結果を表示しているセルを参照する" ということなんでしょー>か ?
とりあえず結果が求まれば参照でもいいんですが、できれば簡潔な関数
にしたいと思っていますので、直接数式をいれる方でお願いしたいです。
無理ですかね。無理だったら参照する方でもかまわないです。
よろしくお願いします。

【30711】Re:イベントプロシージャーを自作関数
発言  ichinose  - 05/11/3(木) 21:16 -

引用なし
パスワード
   川崎 さん、Keinさん、こんばんは。

>すいません、説明不足でしたね。
そうですねえ・・、↓こういう説明は最初に記述しないとね!!

>私がしたいことを具体的にあげると
>たとえばA1セルにある数式を入れます。その数式が100の値を返した
>とします。次にそのA1が150を返したとするとその差分の
>150-100=50を計算してB1セルならB1セルに代入したいのです。
>ここで問題なのが、こういったことを何百ものセルで行いたいのです。
>たとえばF3〜F115など
>ですので関数にしたほうが記述上、運用上扱いやすくなるのではないかと
>思ったのです。
それと関連トピックはリンクしてください。

http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=29696;id=excel


>それとWorkbook_SheetCalculateはできるだけ必須にしてもらいたいのですが。
ユーザー定義関数を作成するのですから、↑の意味がわかりませんが・・・。

以下のような仕様の関数を考えます。

ユーザー定義関数名

calc_dsub_fvalue

機能

指定されたセルに連続して変化したデータの差を求める。

呼び出し形式

calc_dsub_fvalue(rng)
    
入力: rng-----rangeオブジェクト(単一セルに限る)
出力: calc_dsub_fvalue-----指定されたセル(rng)に連続して変化した2数の差


使用例


あるシートの

セルC1に「=calc_dsub_fvalue(B1)」と指定します。
セルB1に「=A1*20」と指定します。

セルA1には、最初に「20」と指定してEnterキーで確定してください。
セルB1、及び、C1は、共に「400」と表示されます。

次いで、セルA1に「25」と指定してEnterキーで確定してください。
セルB1は、「500」と表示され、
セルC1は、500−400の解である「100」が表示されます。


では、コードです。

標準モジュールに
'==================================================================
  Dim add_array() As String
  Dim val_array() As Double
'==================================================================
Function calc_dsub_fvalue(rng As Range)
  Dim array_idx As Variant
  Dim fvalue As Double
  Dim retcode As Long
  Dim wk As Variant
  With rng
    fvalue = 0
    array_idx = CVErr(1004)
    On Error Resume Next
    wk = UBound(add_array())
    retcode = Err.Number
    On Error GoTo 0
    If retcode = 0 Then
      array_idx = Application.Match(.Address(, , , True), add_array(), 0)
      If Not IsError(array_idx) Then
       fvalue = val_array(array_idx)
       End If
      End If
    calc_dsub_fvalue = Val(.Value) - fvalue
    If IsError(array_idx) Then
      If retcode <> 0 Then
       ReDim add_array(1 To 1)
       ReDim val_array(1 To 1)
      Else
       ReDim Preserve add_array(1 To UBound(add_array()) + 1)
       ReDim Preserve val_array(1 To UBound(val_array()) + 1)
       End If
      add_array(UBound(add_array())) = .Address(, , , True)
      val_array(UBound(val_array())) = Val(.Value)
    Else
      val_array(array_idx) = Val(.Value)
      End If
    End With
End Function


留意点                

この関数calc_dsub_fvalueは、複数のセルに同時に使用できますが、

Excel2000で最高でも約5000件、Excel2002以上でも65536までです。

尚、りんさんもおっしゃってましたが、

>グローバル変数は今一つ信用できないので(どのタイミングかで値が失われることがある)

この危険性はありますし、ユーザー定義関数にしてしまうと他のセルに保存と言うことも
出来ませんから、その場合は別の事を考えなくてはなりません。


以上です。

【30725】Re:イベントプロシージャーを自作関数
質問  川崎  - 05/11/4(金) 0:25 -

引用なし
パスワード
    >それとWorkbook_SheetCalculateはできるだけ必須にしてもらいたいのですが。
ユーザー定義関数を作成するのですから、↑の意味がわかりませんが・・・。

ここが絶対はずせないポイントだということです。
これが出来ないのであればユーザー定義関数をつくる意味がなくなるので。
ユーザー定義関数でこれと同じ動作をするものを作れないか?
ということです。

ちなみに提示してもらったコードを実行してみたところ
wk = UBound(add_array())のadd_array()のところでコンパイルエラーが
でます?
どうしたらいいのでしょうか?
ちなみに私がやりたいのは手入力での差分を求めるコードでは
なくて数式自体が値を返しますのでその変化をプログラムが勝手に
察知して差分を求めるものです。
これはちょっと違うような気がするのですが?

【30727】Re:イベントプロシージャーを自作関数
発言  ichinose  - 05/11/4(金) 7:02 -

引用なし
パスワード
   ▼川崎 さん:
おはようございます。
>ちなみに提示してもらったコードを実行してみたところ
>wk = UBound(add_array())のadd_array()のところでコンパイルエラーが
>でます?
>どうしたらいいのでしょうか?
まずこれ↑について。
VBEにて、

・「ツール」----「オプション」とクリックしてオプションダイアログを表示させてください。

・「全般」タブ」の「エラートラップ」という項目で「エラー発生時に中断」が選択されていませんか?そうだとしたら、「エラー処理対象外で中断」を選択して「OK」ボタンを押してください。

この設定になっていれば、本来は、

>wk = UBound(add_array())のadd_array()

のコードでエラーになることはありません
(エラーにならないようにこのコードのちょっと上の行で
On error resume next というステートメントを記述しています)。


> >それとWorkbook_SheetCalculateはできるだけ必須にしてもらいたいのですが。
>ユーザー定義関数を作成するのですから、↑の意味がわかりませんが・・・。
>
>ここが絶対はずせないポイントだということです。
>これが出来ないのであればユーザー定義関数をつくる意味がなくなるので。
>ユーザー定義関数でこれと同じ動作をするものを作れないか?
>ということです。
Workbook_SheetCalculateイベントプロシジャーが作動するタイミングで
ご希望の処理がなされているのなら、提示して関数のコードでもいけるはずです。

>使用例


>あるシートの

>セルC1に「=calc_dsub_fvalue(B1)」と指定します。
>セルB1に「=A1*20」と指定します。

>セルA1には、最初に「20」と指定してEnterキーで確定してください。
>セルB1、及び、C1は、共に「400」と表示されます。

>次いで、セルA1に「25」と指定してEnterキーで確定してください。
>セルB1は、「500」と表示され、
>セルC1は、500−400の解である「100」が表示されます。

この例のcalc_dsub_fvalue関数は、セルA1のデータの手入力に
反応して、作動するのではありません。

セルB1に入力されている数式の値の変化に反応して作動します。
この例では、セルBIの値を変化させるためにセルA1に数値を入力しているに
すぎません。


何はともあれ、このエラーの原因を見つけるのが先決ですが・・・。
確認してください。

【30758】Re:イベントプロシージャーを自作関数
お礼  フレッツ  - 05/11/4(金) 14:33 -

引用なし
パスワード
   ・゚・(ノД`)・゚・。うわ〜んすごーい!!!
すばらしいコードを教えていただいてありがとうございます!!
私みたいな素人に毛が生えた程度の人間にはとても思いつかない
コードでございます!!
へんなこといっていしまってごめんなさい。
エラーの件ですが、設定を変更しなくても動作しました。
とういかichinoseさんの教えてもった設定でした。
手で入力したときはなんでエラーがでたのだろう??
それはさておき、このコード難易度が高すぎて少し私が理解するには
敷居が高いようなきがします。
仕様をかえる場合のために主要なところにコメント解説を
そえて頂けると有難いのですが?
例えば Worksheets(2).Range("A1") = Worksheets(1).Range("C2")
の様に値を別のシートに移す場合どのようにしたらよろしいのでしょうか?
教えてください。
度々申し訳ないですがよろしくお願いします。<(_ _)>

【30790】Re:イベントプロシージャーを自作関数
発言  ichinose  - 05/11/4(金) 19:40 -

引用なし
パスワード
   ▼フレッツ さん:
こんばんは。
フレッツ さん=川崎さん  ですか?


>それはさておき、このコード難易度が高すぎて少し私が理解するには
>敷居が高いようなきがします。
>仕様をかえる場合のために主要なところにコメント解説を
>そえて頂けると有難いのですが?

これは、HELPを調べながら解析してみてください。
その上でわからない箇所を詰めた質問をしてみてください。


>例えば Worksheets(2).Range("A1") = Worksheets(1).Range("C2")
>の様に値を別のシートに移す場合どのようにしたらよろしいのでしょうか?
>教えてください。
この例の意味がわかりませんが、

新規ブックの(標準モジュールにcalc_dsub_fvalue関数のコードをコピーし、
calc_dsub_fvalue関数が使用可能な状態で)
シートSheet1のセルA1に

「=calc_dsub_fvalue(Sheet2!B1)」指定してください。

次にSheet2のセルB1に
「=a1*2」と指定してください。


Sheet2のA1に10と入力すると
Sheet2のB1、Sheet1のA1共に 20と表示します。

次いで

Sheet2のA1に30と入力すると
Sheet2のB1は、60と、Sheet1のA1は 60-20である「40」と表示します。

こういうことですか?


留意点の補足

現在の仕様では

セルA1に「=calc_dsub_fvalue(b1)」

さらに

セルA2に「=calc_dsub_fvalue(b1)」

と指定すると両方のセルに正しい値が入りませんので注意してください。


この場合は、セルA2は「=A1」としてください。

以上です。

【30805】Re:イベントプロシージャーを自作関数
質問  川崎  - 05/11/4(金) 23:01 -

引用なし
パスワード
   私がいいたかったのは、ファンクションプロシージャーが実行して
差分を割り出したと同時に差分を別シートに写して
記録して行きたいと思っているのです。
コードのコメントは簡単でいいので要点を教えてもらえんで
しょうか?
出来るだけ自分でも調べますが、ヒントとなるキーワードだけでも
よろしくお願いします。

【30811】Re:イベントプロシージャーを自作関数
質問  川崎  - 05/11/4(金) 23:30 -

引用なし
パスワード
   add_array     
val_array

というのはなんなんでしょうか?
ヘルプにも載っていませんでしたし、
変数も宣言してないみたいです?
使い方が謎なのですが・・・

【30812】Re:イベントプロシージャーを自作関数
発言  こたつねこ  - 05/11/4(金) 23:33 -

引用なし
パスワード
   川崎 さん、みなさん、こんばんは

横から失礼します。

>私がいいたかったのは、ファンクションプロシージャーが実行して
>差分を割り出したと同時に差分を別シートに写して
>記録して行きたいと思っているのです。

なにも全部一緒にしなくてもいいのでは?
差分を取る処理と、別シートに吐き出す処理を分ければ
ichinoseさんのコードそのままでいいのではありませんか?

コードを提示して頂いているのですから、キーワードはコードの
中にありますよね?^^;
ご自分でコードを調べてみて、わからない部分を質問するほうが
お互いにとって良いと思いますが・・・

【30815】Re:イベントプロシージャーを自作関数
回答  こたつねこ  - 05/11/4(金) 23:48 -

引用なし
パスワード
   川崎さん、こんばんは

>add_array     
>val_array
>
>というのはなんなんでしょうか?
>ヘルプにも載っていませんでしたし、
>変数も宣言してないみたいです?

標準モジュールで変数宣言されていますよ。

>標準モジュールに
>'==================================================================
>  Dim add_array() As String
>  Dim val_array() As Double
>'==================================================================

【30817】Re:イベントプロシージャーを自作関数
回答  川崎  - 05/11/5(土) 0:05 -

引用なし
パスワード
   >なにも全部一緒にしなくてもいいのでは?
>差分を取る処理と、別シートに吐き出す処理を分ければ
う〜んそれでもいいんですけど、
コードの意味があいまいな部分がちょっとあるのと
ファンクションが動作した瞬間に値を別シートに移すように
した方がいいかなと。
このコードが理解できないと別シートに吐き出す処理の
コードも書けないんですよね〜

それと
>add_array     
>val_array
ありましたね。
自分のVBEを見てたので。一番上に変数を移動させてたの忘れていました。

【30819】Re:イベントプロシージャーを自作関数
発言  こたつねこ  - 05/11/5(土) 0:51 -

引用なし
パスワード
   川崎さん、こんばんは

>このコードが理解できないと別シートに吐き出す処理の
>コードも書けないんですよね〜

コードを理解するなと言ってる訳ではありませんよ(念のため)
理解はしなくてはいけません!!

>なにも全部一緒にしなくてもいいのでは?
>差分を取る処理と、別シートに吐き出す処理を分ければ

この発言は、その方が後々修正にしろデバックにしろ楽じゃない
かと思ってした訳です。

川崎さんが

>ファンクションが動作した瞬間に値を別シートに移すように
>した方がいいかなと

と思うのなら、そうしたほうが良いと思います。

8844 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free