• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:関数が“揮発性”か“不揮発性”かを知る方法は?)

関数の揮発性と不揮発性について知りたい

このQ&Aのポイント
  • 関数には揮発性と不揮発性の2種類があります。
  • 揮発性関数では、再計算するたびに返り値が変わる特徴があります。
  • 不揮発性関数では、再計算しても返り値が変わらない特徴があります。

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

  • ベストアンサー
  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.3

んーーー もしかするとこういう言い方も出来ると思いますが,誤解から来た「納得」を納得して貰う方法は提示できません。 >関数の返り値が前と異なっているので、「なるほど揮発性だわい」と得心が行きます。 あなたが着目した,関数の「計算結果が変わる」のは,単に計算の結果に過ぎません。 たとえば「外部ブックを参照している数式」は,外部ブックの参照元データに応じて「ブックを開く都度,計算結果が変わります」が,別にだからといってこれが「揮発性だ」という事にはなりません。 「揮発関数か否か」は,当該の関数が「再計算の必要があってもなくてもいつも再計算される」か,「必要なときだけ再計算され,必要ないときは黙って以前の計算結果を保持している」かという,エクセルの内部事情(設計)の問題です。 ある関数がいま再計算されたのかされなかったかは,ワークシートを眺めているだけでは確認する手段はありません。マクロを使えばある程度可能ですが。 ただし,機能を考えて見ればINDIRECTやOFFSET関数が「揮発性である必然性」は,ある程度理解することはできます。 たとえば,不揮発性関数の例として =INDEX(B:B,3) について見てみると,この関数は関数が引数として受け取っている「B:B」のセル範囲に「変化が起きた」(B列のセルに記入・削除された,B列のセルにある数式に再計算が走った)ときに,それらをトリガーとして再計算されます。 B列に変化が無く,代わりに隣のC列で何かしても,この関数は再計算されません。自分の再計算チェーン(参照元)に連ならないセルが変化しても,何もする必要が無いので,何もしないということです。 一方揮発性関数である A1セルにC2と記入しておいて =INDIRECT(A1) とか =OFFSET(A1,2,2) は機能として,この式ではC2セルやC3セルの値を(再計算して)返す事が求められています。 しかし,これらの関数が調べて値を返すべきセルC2やC3は,引数として受け取っているセルとは全く無関係なセルです。(あるいはINDIRECT("C4")のように書かれたら,そもそもセルを引数で受け取っていません) 従ってこれらの関数は,通常の再計算チェーンによる再計算ルール(不揮発関数の再計算のシクミ)から離れ,とにかくブックの中で「再計算すべきトリガ」が発生したら念のため必ず再計算され,いつでも最新のC2やC3の値を表示します。これが「揮発性である」ということです。

noname#204879
質問者

お礼

懇切丁寧な解説、誠にありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

新規ブックのシート見出しをクリックして コードの表示 Private Sub Worksheet_Calculate()    Cells(1, 10) = Cells(1, 10) + 1 End Sub で 通常の計算が実行されると J1セルが+1される 揮発性は 一気に増える([F9]で再計算もしてみるとよいでしょう) 上記の場合はJ1セルは計算対象にしないような数式にしてください VBAにあまり精通していないので、正解かどうかは判断できかねますm(_ _)m

noname#204879
質問者

お礼

私、VBAはカラッキシできませんが、ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

Googleで「エクセル関数 揮発性」で照会。 沢山きじがあって、拾い読みすればおおよそのことは判るだろう。難しいことを聞いている割には質問の前に、WEB照会をしたのかな。 http://q.hatena.ne.jp/1137503207 http://www.relief.jp/itnote/archives/001519.php http://www.civil-design.net/free/data/excel/function/13.html など。 上記3番目で>INDEX, AREAS, COLUMNS, ROWS関数について、訂正している。 ー #1で回答されているように、テストとして、新しい白紙のブックに、その関数1種けを、1箇所(セル)だけ利用し、名前をつけて保存し、改めてそのブックを開き、何もせず(セル選択さえしてはダメ)、保存すると、「変更しますか」が出るか出ないいかで、確認できるでしょう。 (またVBAでユーザー定義関数など入れていないようにしないと(Volatileなど入れているとテストにならないおそれあり) ーー 過去にここの質問に答えているレベルでは、TODAY、NOW、RAND(BETWEEN)ぐらいは、考えておく必要があるが、その他は、自動再計算しても、差し障るような場面は考えにくい(むしろありがたい)。神経質になる必要は無いのではと思う。揮発性の概念は、一般の他言語を含めて関数一般の考察のもので、エクセル関数には、それを当てはめたに過ぎないのではと想像する。 >変更してないのに保存確認メッセージが表示される」、などの解明・説明に役立つぐらいでは。

全文を見る
すると、全ての回答が全文表示されます。
  • keithin
  • ベストアンサー率66% (5278/7940)
回答No.1

INDEX関数は揮発性関数ではありません。 >どのようにして当該関数が“揮発性”であることを納得できますか? 簡易な検査方法としては, 実施例: 新しいブックを用意する A1セルに =TODAY() のように揮発性関数(若しくは調べたい関数)を記入する ブックを保存し,閉じる 改めてブックを開き,何もせずただ閉じる その際に「保存しますか」を聞いてくれば,それは揮発性関数です。

noname#204879
質問者

補足

》 改めてブックを開き,何もせずただ閉じる 》 その際に「保存しますか」を聞いてくれば,それは揮発性関数です。 その方法は承知していました。 =NOW() や =RAND() もそうですが、これらは「改めてブックを開」いたときには当該関数の返り値が前と異なっているので、「なるほど揮発性だわい」と得心が行きます。 しかし、OFFSET関数の場合は、「改めてブックを開」いても変化が見えないので「何処が揮発性なの?」と思うのです。 「MSが(説明や警告メッセージ等で)そう言っているから」でなく、「なるほど揮発性じゃわい」と“実感”できる方法をお尋ねした次第です。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Excelに関する質問です。

    Excelに関する質問です。 ランダムに乱数を生じさせるべく、RAND関数を使用し、計算を行っています。 その際、特定のセルが特定の条件を満たすまで再計算を繰り返し行うようにしたいのですが、 どなたかよい方法をご存知の方いらっしゃいませんか? 具体的には、 V3セルに以下の文が入力されており =IF(OFFSET(P3,'入力シ-ト'!Q3-1,0)>0.5,"OK","再計算必要") が「OK」になるまで再計算を自動で行いたいのです。 OFFSET(P3,'入力シ-ト'!Q3-1,0)のセルに、Rand関数の絡んだ計算式があります。 上記にこだわらず、条件を満たすまで再計算をさせることはできるのですか?

  • EXCELで変更していないのに『変更を保存しますか』のメッセージが

    EXCELで変更していないのに閉じる時に『変更を保存しますか』のメッセージが出ます。NOW関数やTODAY関数などの自動計算される関数は使っていません。他にどのような理由が考えられますか。

  • エクセルで年齢自動入力をしたい

    どなたか教えてください。 履歴書などで年齢を生年月日と入力日から自動入力するようにしたいのですが簡単にできるでしょうか。 EDATEを使うのでしょうか? たとえばA1にtodayを設定して生年月日の欄から自動的に 年齢を計算するようにしたいです。 today関数とnow関数の違いもよくわかりません。

  • A列が1から始まる連番で、C列を合計欄として結合

    添付画像のようにA列が1から始まる連番で、C列を合計欄として結合し、結合したC列に隣り合う、B列の合計を出す場合のC列の関数を =IF(INDEX($A:$A,ROW())="","",SUM(INDEX($B:$B,ROW()):INDEX($B:$B,IF(COUNTIF(INDEX($A:$A,ROW()+1):INDEX($A:$A,ROWS($A:$A)),"*?"),MATCH("*?",INDEX($A:$A,ROW()+1):INDEX($A:$A,ROWS($A:$A)),0)-1+ROW(),ROWS($A:$A))))) とした場合画像の左のように合計が合いません。 画像の右のようにC列を計算するには =IF(INDEX($A:$A,ROW())="","",SUM(INDEX($B:$B,ROW()):INDEX($B:$B,IF(COUNTIF(INDEX($A:$A,ROW()+1):INDEX($A:$A,ROWS($A:$A)),"*?"),MATCH("*?",INDEX($A:$A,ROW()+1):INDEX($A:$A,ROWS($A:$A)),0)-1+ROW(),ROWS($A:$A))))) をどのように修正すればいいのでしょうか?

  • 選択したセルの値を別シートのセルに取り込む方法

    顧客情報を閲覧・印刷するためのフォームがsheet1とします。顧客の情報が入ったデータベースがsheet2とします。 以下のマクロでsheet2の48列目を空欄にして、48列のいずれかのセルに「出力」と入力すると、そのセルの行の値を出力結果というシートに渡すようにしています。取り込んだ行の顧客番号をsheet1のmach関数の参照先に指定して、index関数で各項目に取り込むようにしています。 Worksheets("sheet2").Activate Dim i, LastRow As Long LastRow = Cells(Rows.Count, 48).End(xlUp).Row For i = 1 To LastRow If Cells(i, 48) = "出力" Then Rows(i).Copy Sheets("出力結果").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0) End If Next i もう少しこれを改良して、Sheet2の顧客番号の入っている1列目の任意のセルを選択して、sheet1のmatch関数の参照先(例としてK4)に選択した顧客番号を渡す方法はありませんでしょうか。sheet1は顧客番号だけ取得できれば、match・index関数でフォームが完成します。 VBAは初心者です。上記マクロは検索で調べて必要な個所をコピーして今の環境にアレンジしました。よろしくお願いします。

  • エクセル 複数シートの値のみコピーで

    こんにちは いつもお世話になっています。 先日、選択した複数のシートを新しいブックに値だけコピーするマクロをこちらで教えていただきました。(関数が入ったシートなのでタブの右クリックからの新規ブックへのコピーでは関数がコピーされてしまうので) 今回、このマクロで失敗するシートがあったので原因を教えてください。 値だけコピーするマクロは以下です。 Sub 値コピー() Dim WS As Worksheet ActiveWindow.SelectedSheets.Copy For Each WS In ActiveWorkbook.Worksheets With WS.Cells .Copy .PasteSpecial Paste:=xlPasteValues End With Next Application.CutCopyMode = False End Sub 失敗するシートにはつぎの関数があります。 A1セルに=REPLACE(CELL("filename",A1),1,FIND(".xlsx]",CELL("filename",A1))+LEN(".xlsx]")-1,) B3セルに=IF(COUNTIF(Sheet2!$1:$1,$A$1),IF(ROWS($3:3)>COUNTIF(OFFSET(Sheet1!$J:$J,,MATCH($A$1&"クラス",Sheet1!$J$1:$N$1,0)-1),B$2),"",COUNTIFS(OFFSET(Sheet1!$C:$C,,MATCH($A$1,Sheet1!$C$1:$G$1,0)-1),">"&INDEX(Sheet1!$C:$G,MATCH(B$2&"☆"&ROWS($3:3),OFFSET(Sheet2!$A:$A,,MATCH($A$1,Sheet2!$A$1:$E$1,0)-1),0),MATCH($A$1,Sheet1!$C$1:$G$1,0)),OFFSET(Sheet1!$J:$J,,MATCH($A$1&"クラス",Sheet1!$J$1:$N$1,0)-1),B$2)+1&"位 "&INDEX(Sheet1!$B:$B,MATCH(B$2&"☆"&ROWS($3:3),OFFSET(Sheet2!$A:$A,,MATCH($A$1,Sheet2!$A$1:$E$1,0)-1),0))&" "&INDEX(Sheet1!$C:$G,MATCH(B$2&"☆"&ROWS($3:3),OFFSET(Sheet2!$A:$A,,MATCH($A$1,Sheet2!$A$1:$E$1,0)-1),0),MATCH($A$1,Sheet1!$C$1:$G$1,0))&"点"),"") 別シートのデータから条件に合うものを引き出す関数です。 これらの関数もおしえていただいたもので、まだ理解できていませんので、説明不十分で申し訳ありません。 これらの関数があるシートではなぜ上記のマクロが失敗するのでしょうか。 もちろん、シートのデータを選択、コピーして新規ブックに値のみコピーはできます。 上記のような関数があるシートでも複数選択シートでの値のみコピーができるマクロを教えていただけないでしょうか。 情報不足がありましたら、教えてください。 よろしくお願いします。 エクセル2007

  • 一度に、任意の列全体へ、関数をコピーするマクロは?

    下記コードのように、 「 E 列 」 だけに実行するのではなく、 「 実行前 」 に、手動にて、好みの任意のセル1つに  「 関数 」 を貼り付けます。 そしてマクロを実行し、 下記 「 実行後 」 のようにするには、どのようなコードになりますでしょうか? 下記のような変数を組み入れるのだと思いますが、うまく出来ません。 ただ、先頭の 「 行番号 ( 変動しますが、例では60 ) 」 は、 手動にて貼り付けますので事前に解かっているとします。 また、 「 オートフィルタ 」 後に、使用する予定です。 何卒、よろしくお願い致します。 ------------------ Sub test() Range("E60").Select ActiveCell.FormulaR1C1 = "=RC[2]" Selection.AutoFill Destination:=Range("E60", Range("C65536").End(xlUp).Offset(0, 2)), Type:=xlFillDefault End Sub ------------------ Dim r As Range, base As Range Dim x, y Dim i Set r = Selection Set base = Selection.Cells(1, 1) x = r.Columns.Count y = r.Rows.Count ---実行前(オートフィルタ後)------------------ C列            E列  ・              ・  ・              ・ 2007/10/13       =G60    2007/10/13 2007/10/13 2007/10/13 2007/10/13 2007/10/14 2007/10/14 --実行後------------------- C列            E列  ・              ・  ・              ・ 2007/10/13       =G60    2007/10/13       =G60 2007/10/13       =G60 2007/10/13       =G60 2007/10/13       =G60 2007/10/14       =G60 2007/10/14       =G60

  • Excel VBAで表組みしたらデバック発生

    Excel VBAの初心者です。Windows Vistaで Excel2007を使っています。 表をマクロの実行で作成したいと思っています。 何もないエクセルブックより 「開発」→「マクロの記録」→「相対参照」 →「表の作成」→「記録終了」→「相対参照で記録の解除」 →「エクセルマクロ有効ブックで保存」 ところがこのマクロ記録が入ったブックを再度立ち上げ、 表をオールクリアにし、マクロボタンより表作成を実行 させようとすると、次のエラーメッセージがでました。 『実行時エラー'9' インデックスが有効範囲にありません。』 デバックからModule1をみると以下の記述となっていました。 Sub 表組み() ' ' 表組み Macro ' ' ActiveCell.Range("A1:E5").Select Selection.Copy Windows("Book1").Activate ActiveSheet.Paste ActiveCell.Columns("A:A").EntireColumn.Select ActiveCell.Rows("1:1").EntireRow.RowHeight = 11.25 ActiveCell.Rows("1:5").EntireRow.Select Selection.RowHeight = 21.75 ActiveCell.Columns("A:A").EntireColumn.ColumnWidth = 14.88 ActiveCell.Offset(0, 4).Range("A1").Select Application.CutCopyMode = False With Selection .HorizontalAlignment = xlCenter .VerticalAlignment = xlCenter .WrapText = False .Orientation = 0 .AddIndent = False .IndentLevel = 0 .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With ActiveCell.Offset(1, -3).Range("A1:D4").Select Selection.NumberFormatLocal = "#,##0_ " ActiveCell.Select ActiveCell.FormulaR1C1 = "78000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "102000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "9800" ActiveCell.Offset(-2, 1).Range("A1").Select ActiveCell.FormulaR1C1 = "65000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "204000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "500" ActiveCell.Offset(-2, 1).Range("A1").Select ActiveCell.FormulaR1C1 = "86000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "151000" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "10200" ActiveCell.Offset(-2, 1).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(RC[-3]:RC[-1])" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(RC[-3]:RC[-1])" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(R[-2]C:R[-1]C)" ActiveCell.Offset(1, 0).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(R[-3]C:R[-1]C)" ActiveCell.Offset(0, -3).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(R[-3]C:R[-1]C)" ActiveCell.Offset(0, 1).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(R[-3]C:R[-1]C)" ActiveCell.Offset(0, 1).Range("A1").Select ActiveCell.FormulaR1C1 = "=SUM(R[-3]C:R[-1]C)" ActiveCell.Offset(-4, -2).Range("A1:D1").Select Selection.AutoFilter End Sub 上から9行目(?)のWindows("Book1").Activateに 黄色い矢印が示され、また行全体が黄色く四角に 覆われていました。 おそらくこの記述に問題があると思いますが、 どんな記述に変えたらいいのか分かりません。 Excel VBAにお詳しい方ご教示願います。 なお、マクロで作成したい図を添付いたします。 参考にしていただければ幸いです。

  • VBA FindメソッドとMatch関数のところ

    まだVBAに慣れていませんが、下記のソースを書いてみました。 ★印の間の部分の処理を、最初はFor Nextで書いていたのですが、理由が解らないですが…うまく処理されない為、タイトルの2種類(セルのFindメソッドとMatch関数)を使って処理しようと思い書き直したのですがうまく処理されません。 どこがいけないのか解らず数時間も悩んでしまいました。 すみませんが、どなたか教えてください。よろしくお願いします。 Sub 外注別案内書作成() Dim ws As Worksheet 'オブジェクト格納 Dim i As Long, j As Long '繰り返す回数格納 Dim annaicode As Variant '案内場所C格納 Dim addwsname As Variant 'シート名前格納(※案内場所名) Dim flag As Boolean '真偽 Dim r As Range 'Findメソッドの返り値格納 Dim K As Long 'Match関数の返り値格納 'レポート元でQ列の情報が入っている時に、案内場所別で情報を作成する。 'レポート元でQ列に値がある時に、annaicode変数へ格納。 For i = 2 To Worksheets("レポート元").Cells(Rows.Count, "A").End(xlUp).Row If Cells(i, "Q").Value <> "" Then annaicode = Cells(i, "Q").Value End If ★ココから-------- '外注一覧でannai変数と一致した時に、addwsname変数へ格納。 FindメソッドとMatch関数 With Worksheets("外注一覧").Columns("1:1") Set r = .Find(What:=annaicode, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns) If r Is Nothing Then MsgBox i & "行目の案内場所Cの入力が不正です。" & vbCrLf & "処理を中断しますね", _ vbOKOnly + vbExclamation, "お知らせ" Else With Worksheets("外注一覧") K = .Match(annaicode, .Range(.Cells(1, "A").Value, .Cells(.Rows.Count, "A").Value), 0) addwsname = .Cells(K, "B").Value + "_案内" End With End If End With ★ココまで-------- 'ワークシートコレクション内でaddwsname変数と一致した時に、flag変数をTrueにする。 For Each ws In Worksheets If ws.Name = addwsname Then flag = True End If Next ws 'flag変数の値により、各々処理をする。 If flag = True Then Worksheets("レポート元").Cells(i, "A").EntireRow.Copy _ Destination:=Worksheets(addwsname).Cells(Rows.Count, "A").End(xlUp).Offset(1, 0) flag = False Else Worksheets.Add ActiveSheet.Name = addwsname Worksheets("レポート元").Cells(i, "A").EntireRow.Copy _ Destination:=Worksheets(addwsname).Cells(Rows.Count, "A").End(xlUp).Offset(1, 0) End If Next i 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

専門家に質問してみよう