EXCEL 2013以上で絶対に作る関数isFormula2010とセキュリティ上の必要性(2016/06/11訂正）

2016/6/11更新その２
If cells(rng.row,rng.column).Value = cells(rng.row,rng.column).Formula  Then isFormula2010 = True Else isFormula2010 = False
からさらに
If Rng.Value = CStr(Rng.Cells.Formula) Then isFormula2010 = False Else isFormula2010 = True
変更しました
変更前だと反対です

```VB:isFormula2010
Function isFormula2010(Rng As Range) As Boolean
If Rng.Value = CStr(Rng.Cells.Formula) Then isFormula2010 = False Else isFormula2010 = True
End Function
```

 Reliefさんの記事はobjCellなんですけど、こちらはレンジ型にして、結合セルでも対応できるようにしてあります。
　この関数はrangeに数式が入っていたらTrue、それ以外はFalseを返します。
* * *
(追記)なぜそうしていたのか理由を思い出しました。Cells().formulaじゃないと数式を吐かないことがあるのでした。なので訂正します。もとは、
If Rng.Value = Rng.Formula Then isFormula2010 = True Else isFormula2010 = False
　Range.Formulaは式の値が出るときと出ないときがあるみたいです。なのでrngをセルに分解します。
　しかしEXCEL2010だけか？range.cells.Formulaプロパティをみつけたのでこれを使うと簡単になりました。
　もしこれが使えないときは

```vb:isFormua2010
Function isFormula2010(Rng As Range) As Boolean
If Rng.Value = CStr(Rng.Formula) Then isFormula2010 = False Else isFormula2010 = True
End Function
```
を使ってください。この場合はあとで検索で数式を探して確認してください。
EXCEL2013以降はisformulaの出番ですがWorkSheetFunctionを噛ませないとだめみたいです。(というか range.HasFormulaを使うか...)

```vb:isFormua2013
'EXCEL 2013 Later
Function isFormula2013(rng As Excel.Range) As Boolean
If Excel.WorksheetFunction.IsFormula(rng) = True Then isFormula2013 = True Else isFormula2013 = False
End Function
```

* * *
　これはなぜ作る必要性があるのか。それは上記のとおりEXCEL2013で新しくisFormulaが作られてしまったからなのです。
　なので旧バージョンと混在している環境では、isFormulaではなくisFormula2010を作る必要があります。
###この関数の必要性
この関数はお仕事で人に渡すEXCELから数式を消すときに使います。
複数のファイルから値を引っ張ってこれるEXCELですが、さすがに人に渡してはどうしようもないですね。

　なのでこれで式を消すわけです。

```VB:DeleteExecelFunction
Sub DeleteExcelFunctionWithMerging()
'Merge Cells is still Merge
'アクティブシートにおいて、結合セルは結合を維持したまま式を消去します
'QIIQ From Qiita
Dim wb As Excel.Workbook: Set wb = ThisWorkbook
Dim ws As Excel.Worksheet: Set ws = ActiveSheet
Dim str As String
Dim Urng As Range
Dim Rng As Range
Dim v
If MsgBox("警告:このVBAマクロはアクティブシートの式をすべて値に変えてしまいます。" & vbCrLf & "This Macro change active Sheet Formula to value." & vbCrLf & "実行する場合はOKを、違う場合はキャンセルをクリックしてください。" & "If you do not run this Macro, Click Cancel", vbCritical + vbOKCancel, "警告 Warning") = vbCancel Then Exit Sub
Set Urng = ws.UsedRange
For Each Rng In Urng
If isFormula2010(Rng) Then
v = Rng.Value
Rng.Value = ""
Rng.Value = v
End If
Next
End Sub
Function isFormula2010(Rng As Range) As Boolean
If Rng.Count = 1 Then
If Rng.Value = CStr(Rng.Cells.Formula) Then isFormula2010 = False Else isFormula2010 = True
Else isFormula2010 = False
End If
End Function
```
さてこの式の意味ですけど
rngに式が入っている場合、
=1+1だと
rng.value は計算結果2
rng.Cells.formula は=1+1
が返ります。
するとこれが一致するときは、式が入っていないときだということになります。
パソコン裏技道場さんは
If Cstr(rng.value)<>Cstr(rng.Formula)
ってしているけど、文字列に変換するCstrはたぶん要らないと思う。~~ VBAは自動的に型変換するのでCstrで明示する場合が思いつきません。~~思いついたりなにかあれば変えます。Formulaだけはなぜか関数に突っ込んだとき型変換しないときがあるので、式の方だけCSTRをいれました。
とりあえず当方ではこんな感じで動かしています。
あ、上の方のSubの方ですか？
アクティヴシートを指定してUsedrangeを取得してFor Each でUsedRangeのセル（結合を想定してRangeにしている）を確認して数式があったら、一度値を取得して、式を""で消してから値を入れるというものです。
　クリアコンテンツが結合していると効かないのでこうなります。
　rng.clearcontentsにしてみろ動かないから。

　あと、A1:Z40みたいにRangeを設定して関数にぶち込むと動かないとか嫌がらせとみなすから。あとVariantはas Variantなんて書くわけがないだろう。v一個で十分なんだよ。
　は、つい言葉がきつくなってしまいました。いろいろな信じがたいことをする人がいるので。まあそれは自分みたいです。

```VB:isFormula2010Strong
Function isFormula2010Strong(rng As Excel.Range) As Variant
If rng.Count = 1 Then
If rng.Value = CStr(rng.Cells.Formula) Then isFormula2010Strong = True Else isFormula2010Strong = False
Else
isFormula2010Strong = CVErr(Excel.xlErrRef)
End If
End Function
```
　IsFormlaで数式ではない場合エラー処理をすると返る型はVariantになります。
　強化型なので修飾子も使いました。

#おわりに
　この関数はおおむね、
For Each v In Worksheets(1).UsedRange
If isFormula2010(r) Then
こんな展開以外はないと思います。
なのは間違いないでしょう。


[2008.05.15 Thursday
セルが数式かどうかを調べる技じゃ。ちと高等じゃぞ！-パソコン裏技道場](http://pcurawaza.meruta.info/?eid=563036)

[ISFORMULA 関数](https://support.office.com/ja-jp/article/ISFORMULA-%25E9%2596%25A2%25E6%2595%25B0-e4d1355f-7121-4ef2-801e-3839bfd6b1e5?ui=ja-JP&rs=ja-JP&ad=JP&fromAR=1)
[ISFormula関数](http://www.relief.jp/itnote/archives/001232.php)
[Range.Cells Property (Excel)](https://msdn.microsoft.com/en-us/library/ff196273(v=office.14).aspx)
[Range.HasFormula プロパティ](https://msdn.microsoft.com/ja-jp/library/office/ff837123.aspx)
[配列数式かどうかを判定する](http://www.moug.net/tech/exvba/0050160.html)