• ベストアンサー

ユーザー定義関数の再計算

ユーザー定義関数を作りました。 ところが、この関数が自動再計算をしてくれません。 どうしたら自動再計算するようになるのでしょうか? よろしくお願いします。 ちなにこの関数は、自分のシートのB2とsheet1~sheet4のB9を比較して、正しければB9の4つ右のセルの値を合計して返すものです。 =SheetLook($B$2,"sheet1,sheet2,sheet3,sheet4",B9,4) コードです。 Function SheetLook(参照元 As Variant, 比較対象シート As String, 比較対象セル As Range, 参照セル位置 As Integer) As Variant   Dim i As Integer   Dim rng As Range   Dim sss As Variant   Dim kei As Variant   Dim cnt As Integer   sss = Split(比較対象シート, ",")   kei = 0   cnt = 0   For i = 0 To UBound(sss)     Set rng = Sheets(sss(i)).Range(比較対象セル.Address)     If 参照元 = rng Then       kei = kei + rng.Offset(0, 参照セル位置)       cnt = cnt + 1     End If   Next   If cnt <> 0 Then     SheetLook = kei   Else     SheetLook = ""   End If End Function

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんにちは。 まず、そのユーザー定義関数は、ちょっと無理があるかもしれませんね。 どこかというと、     Set rng = Sheets(sss(i)).Range(比較対象セル.Address)      この部分です。文字で入れて、シートを認識させるのは悪くはないけれども、そのコードにはブックの概念が、ここには含まれていません。 臨時の措置としては、   Set rng = ThisWorkbook.Sheets(sss(i)).Range(比較対象セル.Address) のようにしないと、ActiveWorkbook のシートを探すようになります。 本格的には、 '---------------------------   On Error Resume Next    Dim myRng As Range    Dim myBk As Workbook   Set myRng = Application.Caller   If myRng Is Nothing Then  'ルーチンで使った場合     Set myBk = ThisWorkbook 'Set myBk = ActiveWorkbook ''いずれか   Else    Set myBk = myRng.Parent.Parent   End If '-----------------------------   For i = 0 To UBound(sss)     Set rng = myBk.Sheets(sss(i)).Range(比較対象セル.Address) '** なお、 >この関数が自動再計算をしてくれません。 Volitile を入れると、引数の参照先の変更があったときにも、再計算がされます。 Volitile を入れなければ、引数の直接の変更があったときに、再計算がされます。だから、本来は、どちらでもよいことです。 その代わりに、このような方法もあります。 =SheetLook($B$2,"sheet1,sheet2,sheet3,sheet4",B9,4)+NOW()*0 Volitile でも、上記のようにしても、必ず、再計算してしまいますから、ワークシートを変更がなくても、開いただけでCalculate の命令があったというように、Excelは解釈してしまいますから、変更があった(ThisWorkbook.Saved =False) となって、保存を要求されます。

st-kanda
質問者

お礼

回答ありがとうございます。 とりあえず、+NOW()*0でやってみました。 何とか解決しました。 ありがとうございました。

その他の回答 (2)

  • Sinogi
  • ベストアンサー率27% (72/260)
回答No.2

>私のExcel2003では、変化有りませんでした。 Application.Volatile は有効なはずです。 オプション 計算方法のチェックはOK?

st-kanda
質問者

お礼

オプション 計算方法のチェックは自動でした。 いろいろやってみると、動くときと動かないときがあるようです。 そして、一度動いたシートでは動き続けました。 規則性はちょっと掴めませんでした。

  • kybo
  • ベストアンサー率53% (349/647)
回答No.1

最初の方に以下の1文を入れてみてください。 Application.Volatile

st-kanda
質問者

お礼

早速の回答、ありがとうございます。 私のExcel2003では、変化有りませんでした。

関連するQ&A

  • エクセル 複数シート( VLOOKUP ユーザー定義関数

    複数シート(範囲)を指定できるVLOOKUP関数をユーザー定義で作りたいと思ってます。下記のコードではうまく動かないので教えてください。 Function VLOOKUPM(検索値 As Variant, 対象シート As String, 対象セル As Range, 列番号 As Integer) As Variant Dim i As Integer Dim r As Range Dim sh As Variant Application.Volatile sh = Split(対象シート, ",") For i = 0 To UBound(sh) Set r = Sheets(sh(i)).Range(対象セル) If 検索値 = r Then VLOOKUPM = r.Offset(0, 列番号) Exit Function End If Next End Function

  • VBAで統計プログラムを作成しています。

    現在VBA(Excel)にて統計のプログラムを作成しています。 Sheet2に統計表 統計対象のシートはシートタブの色が赤色(枚数不特定) 統計表の縦軸には、B4~15に4~3(1年度の月)。横軸にはF~J4に1~5。 統計対象シートの構成は同じで セルE4に1~5の数字のどれか セルE24には1~12の数字のどれかが入ります 統計表イメージ A    B    C    D 1    1    2    3 2 4月 3 5月 4 6月 5 7月 入力画面(シート名部分赤シート) E4 ←1~5のどれか E24 ←1~12のどれか この場合において、たとえばE4が"1"、E24が"4"だった場合 統計表のB2にカウントされるというプログラムが作りたいのですが、 Option Explicit Private Sub CommandButton2_Click() Dim Ws As Worksheet Dim cnt As Variant Dim grade() As Variant 'grade = grd = 学年 grade = Array("1", "2", "3", "4", "5") Dim month() As Variant 'month = mnt = 月 month = Array("4", "5", "6", "7", "8", "9", "10", "11", "12", "1", "2", "3") Dim grd As Integer '各変数宣言 Dim mnt As Integer Dim set1 As Integer Dim set2 As Integer Dim 月ー所 As Worksheet For grd = 1 To 5 If Cells(4, 5).Value = grade(grd - 1) Then cnt = 0 set1 = grd + 5 End If For mnt = 1 To 12 If Cells(24, 5).Value = month(mnt - 1) Then set2 = mnt + 3 End If   For Each Ws In Worksheets If Ws.Tab.ColorIndex = red Then cnt = cnt + 1 End If Next Worksheets("月ー所").Cells(set2, set1).Value = cnt ←この行でエラー1004 Next mnt Next grd MsgBox "統計しました。" End Sub 矢印で示した行のエラー1004の解除方法が分からず悩んでいます どうかよろしくお願いいたします。

  • なぜない?フィルタの使えるCOUNTIF関数

    VBA初心者です。 エクセルでフィルターをかけた上で、特定のデータを数えたいと思うのですが・・・。 例 A        B 東京都    ● 神奈川県   ▲ 東京都    ▲ 愛知県    ● 静岡県    ● 東京都    ▲ このようにデータが入力されているとして、A列でオートフィルターをかけてA列が「東京都」でB列が「●」のセルをカウントしたいとします。 作業列を使ったり、SUMPRODUCT関数を使う方法もありますが、他の方に教えて頂き以下のようなユーザー定義関数を使っております。 Function AAA(myRange As Range, myStr As Variant) As Long  Dim Rng As Range  Dim Cnt As Long  For Each Rng In myRange   If Rng.EntireRow.Hidden = False And Rng.Value = myStr Then     Cnt = Cnt + 1   End If  Next Rng  AAA = Cnt End Function これで確かに希望通りの動作にはなるのですが、他のマクロを動作させるとエラーになってしまうケースが多いようです。 エラーになると、セル内の表示は「######」になってしまい、何らかの原因で非常に桁数の大きな結果が返っているのかと思いましたが、そうでもないようです。 この状態になっても、別セルに1つデータを入れたりするとまた正常に戻ったりして、ちょっと原因が掴めない状態でいます。 しかし疑問に思っているのは、フィルターの使えるCOUNTIF関数は、非常に需要が高いように思うのですが、なぜEXCELにはこういう関数が標準で存在していないのでしょうか? 何か理由をご存じの方いらっしゃいますか?

  • エクセルのマクロで exit について

    よろしくおねがいします 各々のシートのX1セルを値を参照して ゼロ以外の時は 印刷の処理をして ゼロの時は処理をしない という内容を書きたく思います。 このままで記述だとX1セルの値がゼロの場合 いきなりsubを抜けてしまうのですが 1,2枚目でゼロの場合 その次のシートにきちんと処理が 継続したいのですが どこを修正したらよろしいでしょうか? Sub マクロ() Dim shAry As Variant Dim i As Integer, cnt As Integer, x As Integer shAry = Array("東京", "千葉", "群馬") For cnt = LBound(shAry) To UBound(shAry) Sheets(shAry(cnt)).Select x = Int(((Range("x1").Value) - 1) / 5) + 1 If x = 0 Then GoTo ゼロの場合の処理 Else MsgBox "印刷枚数は " & x & "枚です" ここにいんさつの処理があります End If Next Exit Sub ゼロの場合の処理: MsgBox "印刷する内容はありません" End Sub

  • 【VBA】別々のシートに列ごとコピーしていきたい

    エクセルVBA初心者です 以下のような表を、地区別にわけられたシートで、種別を選んで貼り付けていきたいのですが 地区 種別 1 大阪 金 2 東京 銀 3 名古屋 銀 4 大阪 金 5 大阪 銅 6 名古屋 銅 7 東京 金 8 名古屋 金 9 大阪 銅 金と銀のみ、地区に分けられたシートに貼り付け シート【大阪】 1 大阪 金 4 大阪 金 シート【東京】 2 東京 銀 7 東京 金 シート【名古屋】 3 名古屋 銀 8 名古屋 金 以下のVBAを加工してみましたが組んでみましたがうまくいきません どうかご教示のほどよろしくお願いします ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ Public Sub cptest() Dim sht1 As Worksheet Dim sht2 As Worksheet Dim rng As Range Dim cel As Range Dim stcrng As New Collection Dim lastRow As Integer Dim cnt As Integer Set sht1 = ThisWorkbook.Worksheets("Sheet1") Set sht2 = ThisWorkbook.Worksheets("Sheet2") lastRow = Range("G65535").End(xlUp).Row Set rng = sht1.Range("G1:G" & lastRow) For Each cel In rng If cel.Value = "あり" Then Set cel = sht1.Range(cel.Offset(0, -4), cel.Offset(0, -1)) stcrng.Add cel End If Next sht2.Cells.Clear cnt = 0 Set rng = sht2.Range("A1") For Each cel In stcrng cel.Copy rng.Offset(cnt, 0).PasteSpecial rng.Offset(cnt, 4).Value = "_" cnt = cnt + 1 Next Application.CutCopyMode = False End Sub

  • エクセルマクロで定義した関数が動きません

    以前にマクロの記述について教えて頂いた件の続きになります. ご指導頂いたとおりExcelマクロで複素数を扱う関数を下記HPから 標準モジュールにコピペしました.今度は正しくコピーできたと思いますが, 実行するとエラーになります. 標準の組込み関数を用いて「実数」の行列を計算すれば正しく 計算できますが,当然ながら「複素数」は計算できません. この「複素数」を扱う新しく定義した関数が動かない理由, 「End if に対するifブロックがありません」とか 計算結果が「#VALUE!」となってしまうのは何故でしょうか? マクロの記述内容はほとんど理解できないのですが, どなたか助けて頂けませんか! ちなみにエクセルは2016版です. http://www.geocities.jp/tomtomf/denki/AC2/ac2.htm http://www.geocities.jp/tomtomf/denki/AC1/ac1.htm 以下はコピー定義した「 IMMULT」関数と「 IMINVERS」関数のマクロです. Public Function IMMULT(a As Range, b As Range) As Variant Dim r1 As Integer, r2 As Integer, c1 As Integer, c2 As Integer, nn As Integer Dim r As Integer, c As Integer Dim cr As Integer, cc As Integer Dim n As Integer Dim mm() As Variant r1 = a.Rows.Count r2 = b.Rows.Count c1 = a.Columns.Count c2 = b.Columns.Count If (c1 = r2) Then nn = c1 Else Exit Function End If cr = r1 cc = c2 ReDim mm(1 To cr, 1 To cc) For r = 1 To cr For c = 1 To cc mm(r, c) = 0 For n = 1 To nn mm(r, c) = IMSUMa(mm(r, c), IMPRODUCTa(a.Cells(r, n), b.Cells(n, c))) Next Next Next IMMULT = mm End Function Public Function IMINVERS(a As Range) As Variant Dim n As Integer, n1 As Integer, n2 As Integer Dim r1 As Integer, r2 As Integer, c As Integer Dim max As Variant Dim i As Integer Dim m() As Variant Dim inm() As Variant Dim rr As Integer, cc As Integer Dim no As Integer, ex As Variant n1 = a.Rows.Count n2 = a.Columns.Count n = n1 ReDim inm(1 To n1, 1 To n2) For rr = 1 To n1 For cc = 1 To n2 If rr <> cc Then inm(rr, cc) = 0 Else inm(rr, cc) = 1 'End If Next Next ReDim m(1 To n1, 1 To n2) m = a If n1 <> n2 Then IMINVERS = False Exit Function End If For r1 = 1 To n max = m(r1, r1) no = r1 If r1 < n Then For i = r1 + 1 To n If IMABSa(m(i, r1)) > IMABSa(max) Then max = m(i, r1) no = i End If Next If (r1 <> no) Then For i = 1 To n ex = m(r1, i) m(r1, i) = m(no, i) m(no, i) = ex Debug.Print m(r1, i), m(no, i) ex = inm(r1, i) inm(r1, i) = inm(no, i) inm(no, i) = ex Next End If End If max = m(r1, r1) For i = 1 To n m(r1, i) = IMDIVa(m(r1, i), max) inm(r1, i) = IMDIVa(inm(r1, i), max) Next For r2 = 1 To n If r1 <> r2 Then max = m(r2, r1) For i = 1 To n m(r2, i) = IMSUBa(m(r2, i), IMPRODUCTa(m(r1, i), max)) inm(r2, i) = IMSUBa(inm(r2, i), IMPRODUCTa(inm(r1, i), max)) Next End If Next Next IMINVERS = inm End Function

  • シート内セルに条件付着色でエラーメッセージ

    Excelのチェックボタンをクリックしたときにシート1のセル"C4:G50"内に条件付書式により着色(ColorIndex =7)されたセルがあった場合、エラーメッセージ(" ヶ所 日付が入力されていません")を表示したいのですが? 下記のコードでセルに直接着色("C7")されたものは添付のようにメッセージが出たのですが条件付書式による着色がカウントしメッセージが出るようにしたいのですが、コード表示が解る方どうかよろしくお願いします。 尚、C列とG列のみ50行まで条件下で着色するよう同じ条件付書式が入っています。 Sub チェック() Dim CheckRange As Range Dim rng As Range Dim cnt As Long Set CheckRange = Range("C4:G50") For Each rng In CheckRange If rng.Interior.ColorIndex = 7 Then cnt = cnt + 1 End If Next If cnt > 0 Then MsgBox cnt & "ヶ所、日付が入力されていません。", vbCritical Exit Sub End If Worksheets("sheet1").Range("D1") = "1" End Sub

  • ユーザ定義関数がうまく動きません。

    ユーザ定義関数がうまく動きません。 2月のA1セル値が1になっていたりします。 どこがおかしいのかわかりません。解決方法を教えていただけませんでしょうか。 よろしくお願いします。 【シートの設定】 シート名は1月・・・12月です。 各シートの A1セルは「=sheetname()」 B1セルは「月のチェックシート」 が入っています。 【VBAの設定】 Function SheetName() As String 'Application.Volatile If Len(ActiveSheet.Name) = 3 Then SheetName = Left(ActiveSheet.Name, 2) Else SheetName = Left(ActiveSheet.Name, 1) End If End Function

  • Excelで同一セル内に入力されているデータを他のセルに分割したい

    http://okwave.jp/qa4369634.html?ans_count_asc=20 で質問をして、何度かやりとりをさせていただいて エクセルで同一セル内に、セル内改行で1~6列ほどのデータが入力されています。 縦にデータが入力されていて、それぞれのセルにセル内改行を含み、データが入力されています。 それぞれのセル内のデータを… 例えば、A1セル内に5行入力されていたら、A2セルから入力されている行数分(ここでいうと5行)挿入し、それぞれにデータを分割して入力させたい。 かつ、B・Cセルは増えたセルにそれぞれのデータをコピーしたいと言ったら、 Sub Macro1() Dim idx, cnt As Integer Dim wkStr() As String Dim rng As Range   ActiveSheet.Copy after:=ActiveSheet   For idx = Range("A65536").End(xlUp).Row To 1 Step -1     If InStr(Cells(idx, "A"), Chr(10)) > 0 Then       wkStr = Split(Cells(idx, "A").Value, Chr(10))       Set rng = Cells(idx, "B")       For cnt = UBound(wkStr) To 0 Step -1         Cells(idx, "A").Value = wkStr(cnt)         Cells(idx, "B").Value = rng.Value         Cells(idx, "C").Value = rng.Offset(0, 1).Value         If cnt > 0 Then           Cells(idx, "A").Resize(1, 3).Insert shift:=xlDown         End If       Next cnt     End If   Next idx End Sub といったマクロのご回答をいただきました。 これを元に、 ・データが入っているセルをA列→B列に変更 ・A列のデータはセルが増えた分だけ増やしたい ・A1に対応するデータがC1・D1に入っていた場合、対応するデータは残したまま、B列が増えただけ、列を増やしたい と変更したいのですが…。 すいませんが、宜しくお願い致します。

  • アルゴリズムについての質問です

    アルゴリズムについての質問です。 以下のようなプログラムを考えています。 プログラムの目的 ある建物で各部屋同士の机の移動を行うため、その労力を最小にする組み合わせを求める。 ※このシステムは他の人が使用することを考え、わかりやすいExcel(VBA)を使用しています。 画像に関して <図1>は「No(部屋)」の距離(数字が小さい方が労力が少ない)を表しています。 ※プログラムでこの表は出力されています <図2>のようにA群とB群があり、A群からB群に移動する(複数移動も含む)場合について考えます。 <図3>のような最小の組み合わせを探します。 正しい結果は出るのですが、1件増えるだけで何倍何十倍と時間がかかってしまいます。 多少結果は妥協して(最小に近い値)でも処理を早くしたいと思っていますが、そのアルゴリズムが思いつきません。 作成したプログラムを下記にありますので、アドバイスをお願いいたします。 作成したプログラムで処理を遅くしている原因があれば指摘もお願いします。 ---現在作成したプログラムです。(すべてのパターンを検証)----------------- Dim 重みtab As Variant Dim t01(100) As Integer '←A群が、「t01(1)」から順に入っています。 Dim t02(100) As Integer '←B群が、「t02(1)」から順に入っています。 Dim ttt(100) As Integer '←B群を並び替えた結果が入ります。 Sub 計算(移動数 As Integer) '「移動数」は「t01」「t02」の要素の数 Dim t03(100) As Integer Dim a As Integer 重みtab = Range("重み表") 'Range("重み表") は <図1>の「No」を含まないセル '仮の最小の計算-------- min = 0 For a = 1 To 移動数 min = min + 重みtab(t01(a), t02(a)) ttt(a) = a Next '---------------------- Call 再帰関数(移動数, t03, 1) 'Sheet2に出力---------- For a = 1 To 移動数 Sheets("Sheet2").Cells(a, 1) = t01(a) Sheets("Sheet2").Cells(a, 2) = t02(ttt(a)) Next '---------------------- End Sub Sub 再帰関数(移動数 As Integer, t03() As Integer, cnt1 As Integer) Dim cnt2 As Integer Dim flg As Boolean For a = 1 To 移動数 flg = True For b = 1 To cnt1 - 1 If t03(b) = a Then flg = False End If Next If flg Then t03(cnt1) = a If cnt1 < 移動数 Then cnt2 = cnt1 cnt1 = cnt1 + 1 Call 再帰関数(移動数, t03, cnt1) cnt1 = cnt2 Else Call 処理(移動数, t03) End If t03(cnt1) = 0 End If Next End Sub Sub 処理(移動数 As Integer, t03() As Integer)  ’最小であるか確認 Dim a As Integer Dim b As Integer For a = 1 To 移動数 b = b + 重みtab(t01(a), t02(t03(a))) Next If min > b Then min = b For a = 1 To 移動数 ttt(a) = t03(a) Next End If End Sub

専門家に質問してみよう