Excel VBA質問箱 IV

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

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


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

【33538】名前付きセル範囲がなかったら? サザエ 06/1/14(土) 18:04 質問[未読]
【33540】Re:名前付きセル範囲がなかったら? かみちゃん 06/1/14(土) 18:16 回答[未読]
【33549】Re:名前付きセル範囲がなかったら? サザエ 06/1/14(土) 21:22 お礼[未読]
【33575】Re:名前付きセル範囲がなかったら? ichinose 06/1/16(月) 8:27 発言[未読]
【33544】Re:名前付きセル範囲がなかったら? awu 06/1/14(土) 19:48 回答[未読]
【33547】Re:名前付きセル範囲がなかったら? ichinose 06/1/14(土) 20:15 発言[未読]

【33538】名前付きセル範囲がなかったら?
質問  サザエ  - 06/1/14(土) 18:04 -

引用なし
パスワード
   シートの中に指定した(名前付きセル範囲)が無かった場合
エラーになりますが、あるかないかを判別する方法を教えてください。


If range("sazae") is nothing then
  〜
end if
こんな感じで出来るかな、と思ったらだめでした。

【33540】Re:名前付きセル範囲がなかったら?
回答  かみちゃん  - 06/1/14(土) 18:16 -

引用なし
パスワード
   こんにちは。かみちゃん です。

>シートの中に指定した(名前付きセル範囲)が無かった場合
>エラーになりますが、あるかないかを判別する方法を教えてください。

以下のような感じでいかがでしょうか?

Sub Macro1()
 Dim Nam As Name
 
 On Error Resume Next
 Set Nam = ActiveWorkbook.Names("sazae")
 On Error GoTo 0
 If Nam Is Nothing Then
  MsgBox "名前の定義がありません"
 End If
End Sub

以下のURLを参考にしました。
http://www.moug.net/tech/exvba/0050052.htm

【33544】Re:名前付きセル範囲がなかったら?
回答  awu  - 06/1/14(土) 19:48 -

引用なし
パスワード
   アクティブシートの中にあるかの確認だと思いますので、こんな感じで如何でしょうか。

解析して必要部分を使用すれば良いと思いますが・・・。


Sub NameChk()
Dim N As Integer
Dim Msg As String
Const ChkName = "sazaea" '<--- チェックする名前を指定
With ActiveWorkbook.Names
  For N = 1 To .Count
    If .Item(N).Name = ChkName Then Exit For
  Next N
  If N <= .Count Then
    If InStr(Names(ChkName), "=" & ActiveSheet.Name & "!") = 1 Then
      Msg = ChkName & " は、このシートにあります。"
    Else
      Msg = ChkName & " は、このシートにありません。" & _
        String(2, vbLf) & Mid(Names(ChkName), 2, _
        InStr(Names(ChkName), "!") - 2) & " にあります。 "
    End If
  Else
    Msg = ChkName & " の名前は、この ブック には存在しません。"
  End If
End With
MsgBox Msg, vbInformation
End Sub

【33547】Re:名前付きセル範囲がなかったら?
発言  ichinose  - 06/1/14(土) 20:15 -

引用なし
パスワード
   こんばんは。

'===========================================
Sub test()
  MsgBox exist_name("aaa", ActiveSheet)
End Sub
'==============================================================
Function exist_name(nm As String, sht As Worksheet) As Boolean
  '指定された名前が指定されたシートにあるかをチェックする
  'Input nm---名前  Sht---Worksheetオブジェクト
  'out-----true:存在する  False:存在しない
  Dim rng As Range
  On Error Resume Next
  exist_name = False
  Set rng = Application.Range(nm)
  If Err.Number = 0 Then
    If sht Is rng.Parent Then
     exist_name = True
     End If
    End If
  On Error GoTo 0
End Function

ポイントは Application.Range("aaa")
ApplicationのプロパティであるRangeです。

【33549】Re:名前付きセル範囲がなかったら?
お礼  サザエ  - 06/1/14(土) 21:22 -

引用なし
パスワード
   ありがとうございます。
こんな簡単に出来るとは思いませんでした。

ちょっと疑問に思ったんですが、
On Error nextで抜ける方法と
for であるかないか探す方法と
ありましたが、一見On Error nextでやる方が処理は速そうですが
(名前付きセル範囲)をExcellが探すとき、結局はコンピュータの内部
でも、くり返し文で探していると思うので、処理速度は同じなのでしょうか。

あと計算中、大量のデータが発生し、そのデータを使ってさらに計算するとき
その発生したデータをセルにおくのと、配列に格納するのとではどちらが
処理が早いのでしょうか。

【33575】Re:名前付きセル範囲がなかったら?
発言  ichinose  - 06/1/16(月) 8:27 -

引用なし
パスワード
   皆さん、おはようございます。

>On Error nextで抜ける方法と
>for であるかないか探す方法と
>ありましたが、一見On Error nextでやる方が処理は速そうですが
>(名前付きセル範囲)をExcellが探すとき、結局はコンピュータの内部
>でも、くり返し文で探していると思うので、処理速度は同じなのでしょうか。

私たちが作成するVBAプログラムがインタープリタ言語(解釈実行プログラム言語)であり、
Excelがコンパイラ言語(実行プログラム言語)で作成されていることを考えれば、
仮に同じアルゴリズムだとしても解釈を行わない分だけExcelに任せた方が
処理速度は速いと思います。

さらに

>結局はコンピュータの内部
>でも、くり返し文で探していると思うので、

ここですが、私もVBAがどのような処理をしているのか
知っている訳ではありません。

20年前ぐらいに他言語のインタープリタに関わったことがありますが、
このような場合に内部では「くり返し文で探す」というような
逐次検索のアルゴリズムを使っていませんでした。
(逐次検索と言うのはn個の検索データがあれば、最大検索回数がn回ですね)

この時は、ハッシュ検索と言って検索回数を1に近づける手法が使われていました。
(実際には、1ではないためにオーバーフロー処理が必要でしたが)
ハッシュ検索なんて、名前は仰々しいですが、概念は簡単ですし、
知らず知らずのうちにその手法は名前を知らなくても使っているかもしれませんよ!!
(但し、これを運用するのは難しいと思いますけど)。

ハッシュ検索でNetを検索して調べてみてください。


>
>あと計算中、大量のデータが発生し、そのデータを使ってさらに計算するとき
>その発生したデータをセルにおくのと、配列に格納するのとではどちらが
>処理が早いのでしょうか。

新規ブックの標準モジュールに
'===============================================================
Sub test()
  Dim st As Double
  Dim idx As Long, jdx As Long
'*****************************************************************
' 配列使用
'*****************************************************************
  
  Application.ScreenUpdating = False
  Dim marray As Variant
  Range("a:b").ClearContents
  st = [now()]
  marray = Range("a:b").Value
  For idx = 1 To 2
   For jdx = 1 To 65536
     marray(jdx, idx) = idx * 2 + jdx
     Next
   Next
  Range("a:b").Value = marray
  Application.ScreenUpdating = True
  MsgBox Application.Text([now()] - st, "hh:mm:ss.00")


'*****************************************************************
' 配列使用しない
'*****************************************************************
  Application.ScreenUpdating = False
  Range("a:b").ClearContents
  st = [now()]
  
  For idx = 1 To 2
   For jdx = 1 To 65536
     Cells(jdx, idx).Value = idx * 2 + jdx
     Next
   Next
  Application.ScreenUpdating = True
  MsgBox Application.Text([now()] - st, "hh:mm:ss.00")
End Sub

上記のコードを実行していただければ、
原則としては、結論がでると思います。

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