Excel VBA質問箱 IV

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

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


2467 / 13645 ツリー ←次へ | 前へ→

【67739】TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも極寒 11/1/6(木) 10:49 質問[未読]
【67740】Re:TreeView.Nodes.Clearが遅い kanabun 11/1/6(木) 11:11 発言[未読]
【67742】Re:TreeView.Nodes.Clearが遅い 四国は久々に晴れ、でも 11/1/6(木) 12:10 回答[未読]
【67746】Re:TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも 11/1/6(木) 14:20 発言[未読]
【67749】Re:TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも 11/1/6(木) 15:40 発言[未読]
【67750】Re:TreeView.Nodes.Clearが遅い neptune 11/1/6(木) 15:59 発言[未読]
【67771】Re:TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも 11/1/7(金) 11:06 発言[未読]
【67776】Re:TreeView.Nodes.Clearが遅い neptune 11/1/7(金) 18:07 発言[未読]
【67777】Re:TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも 11/1/7(金) 18:20 お礼[未読]
【67871】Re:TreeView.Nodes.Clearが遅い 四国は久々晴れ、でも 11/1/14(金) 10:33 お礼[未読]

【67739】TreeView.Nodes.Clearが遅い
質問  四国は久々晴れ、でも極寒  - 11/1/6(木) 10:49 -

引用なし
パスワード
   TreeViewに、親ノードが12ヶ月分で、子ノードに各月の行事を表示できました。子ノードは1段だけです。TreeViewに合計、約120のノードが表示されます。
さて、年月がComboBox等で切り替えられると、TreeView.Nodes.Clearして再表示させています。しかしNodes.Clearの1行だけで0.8秒もかかります(利用者が不満)。
ノードを1行ずつ消去する方法は知っていますが、年月がいっきに切り替わるので、Nodes.Clearがシンプルです。
Application.ScreenUpdatingやEnableEvents等の4つをFalseにしても高速化しません。画期的な方法はありませんか?

【67740】Re:TreeView.Nodes.Clearが遅い
発言  kanabun  - 11/1/6(木) 11:11 -

引用なし
パスワード
   こんにちは〜

TreeViewはUserFormにあるのですか?

Excelではあまり使ったことはなくて、憶測ですすが、
処理をする直前で一時的に
.Visibleプロパティを False にし、
処理が終わったら Trueに戻す
とかしたら多少よくならないですか?

> Application.ScreenUpdating
などはApplication(= Excel)の機能なので、
UserFormなどには 働かないです。

【67742】Re:TreeView.Nodes.Clearが遅い
回答  四国は久々に晴れ、でも  - 11/1/6(木) 12:10 -

引用なし
パスワード
   早速、返信をもらえまして感謝します。
TreeViewはForm1の中に置かれています。
Form1Moduleの中に作成したサブルーチンを、次のように5通りに書き換えて実行してみました。
1) 何もFalseにせず、ただTreeView.Nodes.Clearだけ実行する。
結果 正常終了。Nodes.Clearに約0.8秒かかった。
2) TreeView.Enabled=False : TreeView.Nodes.Clear : TreeView.Enabled=True の3行を記述して複数回実行した。
結果 正常終了。Nodes.Clearに約0.8秒かかった。
3) TreeView.Visible=False : TreeView.Nodes.Clear : TreeView.Visible=True の3行を記述して複数回実行した。
結果 TreeViewに1行でもノードがあった場合に、第3行で「オートメーションエラー」が発生した。On Errorで飛ばせる軽度のエラーみたい。
4) Form1.Enabled=False : TreeView.Nodes.Clear : Form1.Enabled=True の3行を記述して複数回実行した。
結果 2度目までは正常終了。3度目でフリーズして、CommandBotton等の一切のコントロールが反応しなくなった。
5) Form1.Visible=False : TreeView.Nodes.Clear : Form1.Visible=True の3行を記述して複数回実行した。
結果 マクロ実行直後に、第1行で「コンパイルエラー:関数またはインターフェイスが予約されているか、または〜」が発生してマクロ実行できなかった。

【67746】Re:TreeView.Nodes.Clearが遅い
発言  四国は久々晴れ、でも  - 11/1/6(木) 14:20 -

引用なし
パスワード
   Net.Framework ですと次のように記述できるようです。
 TreeView.BeginUpdate
 TreeView.Nodes.Clear
 TreeView.Nodes.Add
 ........
 TreeView.EndUpdate

しかし、Excel VBAにはBeginUpdate も EndUpdateもないようです。
また、BeginUpdate と EndUpdate で[高速化]できるか、も不明です。

【67749】Re:TreeView.Nodes.Clearが遅い
発言  四国は久々晴れ、でも  - 11/1/6(木) 15:40 -

引用なし
パスワード
   TreeView.Nodes.Clear が遅いPCは、職場の事務系で使用される標準的な
もので、XPのサポートが切れるまでは買い換えられない見込みです。
仕様は以下の通りです。

Pentium4 3GHz
512MB RAM
Windows XP Pro

【67750】Re:TreeView.Nodes.Clearが遅い
発言  neptune  - 11/1/6(木) 15:59 -

引用なし
パスワード
   ▼四国は久々晴れ、でも さん:
120のノードで0.8secって遅いような気がする。

似たような環境があるので再現できる最低限のソースUPしてもらえます?
FormとTreeviewだけのもの。
約束は出来ませんけどTestしてみます。

それとその方が皆さんからResが付き易いと思いますよ。

【67771】Re:TreeView.Nodes.Clearが遅い
発言  四国は久々晴れ、でも  - 11/1/7(金) 11:06 -

引用なし
パスワード
   ▼neptune さん:

3月初旬までに解決できるとうれしいです。よろしくお願いします。

'−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
1)標準モジュール[Module1]を追加して、次の行を追加してして下さい。
Public Sub Auto_Open : Form1.Show vbModeless : End Sub
2)フォーム[Form1]を追加して、コマンドボタン[cmd1]と、ツリービュー[tvw1]を置いて下さい。
3)[Form1]に以下の行を挿入して下さい。
4)実行してみて下さい。

'−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Option Explicit
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Private Type EventData
 datDate As Date
 strTitle As String
End Type
Private Events() As EventData
Private Type ListKey
 datKey As Date
 strKey As String
 strName As String
End Type
Private ListKeys(1 To 12) As ListKey
Private intY As Integer  '[年]
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Private Sub cmd1_Click()
 Call UpdateTreeView  'TreeViewを再描画します。
End Sub
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Private Sub UserForm_Initialize()
 intY = Year(Now())
 Call CreateDummyEvent  'テスト用データを作成します。
 With cmd1
  .Caption = "TreeViewを再描画します"
 End With
 With tvw1
  .HotTracking = True     'True:表示文字に下線を表示する。
  .BorderStyle = ccNone    '線の種類
  .Font.Size = 12
  .FullRowSelect = False   'False:選択された文字だけ色付けする。 True:選択された行全体を色付けする。
  .Indentation = 14      'インデントの幅
  .LabelEdit = tvwManual   'ラベル編集の許可
  .LineStyle = tvwRootLines  'ルート(最上位)線の表示
  .HideSelection = False   '非アクティブ時の選択解除
  .Scroll = True
  .CheckBoxes = False     'True:チェックボックスを表示する。
  '.ImageList = ImageList1  'イメージリストの初期化
 End With
 Call UpdateTreeView  'TreeViewを再描画します。
End Sub
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Private Sub UpdateTreeView()
 Dim intM As Integer, intI As Integer, intJ As Integer, intK As Integer
 With tvw1
  .Nodes.Clear '[TreeView]を一括クリアする。'大問題!)[Nodes.Clear]はめちゃくちゃ時間がかかる。
  '親(第1位の)ノードを表示する。
  For intM = 1 To 12
   ListKeys(intM).datKey = DateSerial(intY, intM, 1)
   ListKeys(intM).strKey = "KEY" & Format(ListKeys(intM).datKey, "YYYYMM")
   ListKeys(intM).strName = Format(ListKeys(intM).datKey, "gggee年MM月") & "(" & Format(ListKeys(intM).datKey, "YYYY年") & ")"
   .Nodes.Add Key:=ListKeys(intM).strKey, Text:=ListKeys(intM).strName
   .Nodes(ListKeys(intM).strKey).Expanded = True  'ノードを展開する(このノードの子ノードを表示する)。
  Next intM
  '子(第2位の)ノードを表示する。
  intI = 1: intJ = 1          '初期値を設定する。
  For intM = 1 To UBound(ListKeys)    '=親ノード数
   intK = 1               '初期値を設定する。
   For intI = intJ To UBound(Events)
    If (Year(ListKeys(intM).datKey) = Year(Events(intI).datDate)) And (Month(ListKeys(intM).datKey) = Month(Events(intI).datDate)) Then
     '下位の(第2位の)ノードを格納する。
     .Nodes.Add Relative:=ListKeys(intM).strKey, Relationship:=tvwChild, Key:=ListKeys(intM).strKey & Format(intK, "_00"), Text:=Events(intI).strTitle
     intK = intK + 1
    Else '翌月の[行事]が見つかった。
     Exit For
    End If
   Next intI
   intJ = intI
  Next intM
 End With
End Sub
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Private Sub CreateDummyEvent()
 Dim intM As Integer, intI As Integer, intJ As Integer, intK As Integer, datDate As Date, strTitle As String
 ReDim Events(1 To 500)
 intK = 0
 For intM = 1 To 12
  For intI = 1 To 20
   datDate = DateSerial(intY, intM, intI)
   strTitle = Format(datDate, "gggee年MM月DD日(aaa)") & "_行事_"
   For intJ = 1 To 10:  strTitle = strTitle & Format(intI, "00"): Next intJ
   intK = intK + 1: Events(intK).datDate = datDate: Events(intK).strTitle = strTitle
  Next intI
 Next intM
 ReDim Preserve Events(1 To UBound(Events))
End Sub
'−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

【67776】Re:TreeView.Nodes.Clearが遅い
発言  neptune  - 11/1/7(金) 18:07 -

引用なし
パスワード
   ▼四国は久々晴れ、でも さん:
UPされたソースそのまんまで検証してみました。
私の環境 winxp sp3 pen4 2.8G ,office 2K ,では0.26secでした。

全部を展開、表示した状態では正常な時間と思います。

で、なぜかしら、clearメソッドの上下にvisibleを操作する文を入れると
エラーが出ますね。
・・・よくは考えていませんけど、何故かは多分私にはわからんと思います。

必要なノードのみを展開状態にしておくともっと早くなるとは思います。
エクスプローラもどきをプログラムの部品として何度か作ったことありますけど、
必要な情報のみを必要なとき、若しくは必要になる可能性があるとき
に入力するような感じにすれば殆どストレスは感じませんでしたよ。
その辺り検討してみては如何ですか?

【67777】Re:TreeView.Nodes.Clearが遅い
お礼  四国は久々晴れ、でも  - 11/1/7(金) 18:20 -

引用なし
パスワード
   ▼neptune さん:

>winxp sp3 pen4 2.8G ,office 2K ,では0.26secでした。
はい、私が与えられたPCは512MB RAMですが、2GB RAMのPCを一時的に
使わせてもらって実行しましたら、処理時間は体感的に約半分でした。
問題は職場PCの性能みたいです。

>必要なノードのみを展開しておくともっと早くなると思います。
>その辺り検討してみては如何ですか?

はい、おっしゃる通り、現実路線でいこうと思います。
ありがとうございました。

【67871】Re:TreeView.Nodes.Clearが遅い
お礼  四国は久々晴れ、でも  - 11/1/14(金) 10:33 -

引用なし
パスワード
   今後、本欄を見つけた方へご参考までに記載しておきます。

>必要なノードのみを展開しておくともっと早くなると思います。
>その辺り検討してみては如何ですか?

neptuneさんの助言通り、必要なノードのみを展開しておいて
(表示ノード数をできるだけ少なくしておいて)、Nodes.Clear
する様に改善しました。
しかし、当方のPC(512MB RAM, WinXP, Excel2003)において、
Nodes.Clearの実行速度は単純に[表示されたノード数]に
比例して高速化できませんでした。例えば表示ノード数120
から12へと1/10にしても、実行速度は約25%しか低減できま
せんでした。

結論[WinXPでExcelを快適に実行するには512MB RAMは不足]

推論[閉じられた子ノードも.Nodes.Clearに影響していそう]

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