トップ回答者
ActiveDocument.ListParagraphs(箇条書き番号設定段落)について

質問
-
はじめまして、マイクロソフト_コミュニティーへ投稿した質問を
現在、目次ページの箇条書き付き段落にページ数を自動でつける処理マクロを
フォーラムモデレータ様からの紹介でこちらにも投稿させていただき
ます。マルチポストとなりますが、よろしく、お願いいたします。
作成しています。
念のために、確認しておきたいことがありますので、ご存じの方がおられたら
コメントお願いいたします。
<コードの一部>
MsgBox ActiveDocument.CountNumberedItems '文書全体の箇条書き段落の総数
For i = 1 To ActiveDocument.CountNumberedItems
ActiveDocument.ListParagraphs(i).Range.Select
Next i
とすると、インデックス番号=1は、実際に箇条書き設定付き段落の先頭を選択し
順次、インデックス番号が増すと下方向の箇条書き設定付き段落を選択することを
確認できました。
ところが、
For Each 段落 In ActiveDocument.ListParagraphs
MsgBox 段落.Range.ListFormat.ListValue
Set 検索範囲 = 段落.Range
段落.Range.Select
Selection.HomeKey
以降省略、とすると、最初に処理される段落は、箇条書き設定付き段落の最終でした。
for Eacheで、処理を回す場合には、最後から上に向かって処理をすすめるようです。
コレクションやオブジェクトの種類によって、処理順序は違っているのか、種類ごと
に決まりなどがあるのでしょうか?
for Eacheでの処理順序について、詳細説明されているドキュメントはありますか?
また、処理順番を制御することはできるのでしょうか?今のところ、処理順が明確でないという前提で、処理を工夫しコード記述はこなせていますが
処理順についてもう少し詳しく知っておきたいと思っています。よろしく、お願いいたします。
回答
-
For Each 文自体は処理順を保障しません。
ただし、扱うコレクションによっては For Each でループしたときの処理順を保障しているものが有るのかもしれません。
また、コレクションにインデックスが付いているかどうかは、処理順とはあまり関係ないはずです。
感覚的には 先入れ先出し に近いイメージを持っています。
>様々なコレクションでの動作状況を記録して、実態を把握していくしかないでしょうか?
これはお勧めできません。
特定の環境での動作が、一般的な動作になるとは限りません。
それに、内部仕様が変更されても、保障外の動作に対しては通知されないでしょう。
ですから kiga_yoさんの現状の対応がベストだと思います。
「処理順を気にしない時だけ For Each 文を使う」が単純で解りやすいと思います。- 回答としてマーク kiga_yo 2015年7月15日 5:23
すべての返信
-
自己レスです。
コレクション毎の処理順ルールの初期値のようなものがあるのか、どうかを知りたいのですが
様々なコレクションでの動作状況を記録して、実態を把握していくしかないでしょうか?
同じコードを、処理対象を変えて実行して処理順パターンに違いがあったということは
今のところないので、コレクション毎の特性合わせて何かしらの処理順ルールが設定されて
いるのではと、思っています。
水面下の初期値設定が変更されるような場合には、違う順序ルールになることになり、
結果として処理順序は保障されないとされているのでは?と推測しています。
水面下の設定条件を変更することなど一般庶民には難解でありますから、初期設定内容が解れば
十分なのです。
For Eachを利用すると、すっきりとコード記述できるので避けるのではなく、上手く活用していきたいので、コレクション毎の整理された情報を手に入れたいものです。
ちなみに、フォルダー内のファイル一覧を出力するエクセルvbaでの下記コードでは、
結果として、ファイル名称のⅠ文字目の文字コード(unicode)順で処理されたようです。
<コードの一部>
Dim objFileSys As Object
Set objFileSys = CreateObject("Scripting.FileSystemObject")
Dim oItem As Object
i = 2
With CreateObject("Shell.Application").Namespace(フォルダパス)
'フォルダパスの型はvariantで定義する。
For Each oItem In .Items
i = i + 1
Cells(i, 2) = oItem.Name
ファイルパス = oItem.path
Cells(i, 3) = objFileSys.GetExtensionName(ファイルパス)
If 頁cnt = True Then
'-------------------------------------------------------------------
If Cells(i, 3) = "pdf" Then
Call PDF頁取得
Cells(i, 4) = 頁数
End If
'-------------------------------------------------------------------
If Cells(i, 3) = "doc" Or Cells(i, 3) = "docx" Then
Call word頁取得
Cells(i, 4) = 頁数
End If
'-------------------------------------------------------------------
End If
Next
End With
Set oItem = Nothing
Set objFileSys=nothing
コード実行記録として、追記しておきます。
-
回答ではなく情報としてですが、あちらでも同じ質問を見つけました。結局、よくわからないということでした。
ActiveDocument.ListParagraphs not sorted: bug in Word?
http://social.msdn.microsoft.com/Forums/en-US/aa49b14d-2099-4cf6-b524-f2d948cb218c/activedocumentlistparagraphs-not-sorted-bug-in-word★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
-
trapemiya 様
情報提供、どうもありがとうございました。
Seb1732さんも、ListParagraphsの場合、for Eachの処理がインデックス番号の最終から処理される現象
についてひっかりがあり質問投稿されたようですね。
アメリカでのやり取りの記録で気になった部分は、
モデレータのCindyさんの回答で、”I can't reproduce "not sorted"”の部分です。
つまり、現象は確認できず、逆順にはならなかった、というところです。(読解力に自信なしですが)
となると、あらかじめ設定されている処理ルールは簡単には把握できないということになりそうです。
立ち寄って読まれている皆さんも、逆順にはなりませんか?
動作確認後、ランダムを前提に、現在処理しているListParagraphのインデックス番号を判定して
その番号を基に必要情報を拾ってくるという処理としたので、何かのきっかけで突如順序が変わって
しまっても問題はないのですが、本当かなあ?
どこかのドキュメントで、内部的にmovenextの処理に依存しているとか、云々を拾い読みしたことがあり
奥が深い感じではあります。
もうしばらく、コメントを待ちたいと思いますので、よろしくお願いいたします。 -
ふたたび、自己レスで申し訳ございません。
昨日の投稿文の一部に誤りがありましたので、一応訂正しておきます。
(枝葉の部分ですので、大勢には影響いたしませんが気持ち悪いので)
<訂正前>
動作確認後、ランダムを前提に、現在処理しているListParagraphのインデックス番号を判定して
その番号を基に必要情報を拾ってくるという処理としたので、・・・
<訂正補足>
動作確認後、ランダムを前提に、現在処理しているListParagraphのListFormat.ListValueを判定して、
対象段落の冒頭に表示されている番号を基に必要情報を拾ってくるという処理としたので、何かのきっかけで突如for Eachの処理順序が変わってしまっても問題はない。
※メモ※
段落冒頭に表示される番号は、ListParagraph.Range.ListFormat.ListValueで取得できる。
(参照しているドキュメントが適当でないの理解力が無いのか、
これを調べるのもちょっと時間がかかりました。模索中の方は参考にしてください。)
引き続き、コメントお待ちしております♪ -
For Each 文自体は処理順を保障しません。
ただし、扱うコレクションによっては For Each でループしたときの処理順を保障しているものが有るのかもしれません。
また、コレクションにインデックスが付いているかどうかは、処理順とはあまり関係ないはずです。
感覚的には 先入れ先出し に近いイメージを持っています。
>様々なコレクションでの動作状況を記録して、実態を把握していくしかないでしょうか?
これはお勧めできません。
特定の環境での動作が、一般的な動作になるとは限りません。
それに、内部仕様が変更されても、保障外の動作に対しては通知されないでしょう。
ですから kiga_yoさんの現状の対応がベストだと思います。
「処理順を気にしない時だけ For Each 文を使う」が単純で解りやすいと思います。- 回答としてマーク kiga_yo 2015年7月15日 5:23
-
hihijiji 様
返信、どうもありがとうございました。
「処理順を気にしない時だけ For Each 文を使う」べし
の教え、徹底することにいたします。
これまで、気楽にFor Each 文を利用しておりましたが
事故にたまたま遭遇していなかったのだ、と認識を改めて考えをめぐらすようにします。
ワードのコードサンプルは、コレクション単位に処理を回すことが都合がよいので
For Eachを使用したものが多いのに比べ、エクセルでは添字でカウントしながら
繰り返し処理を回すサンプルの方が多いのですが、何故だろう?古臭いのか?
と思っていたこともありました。
「使う場面を慎重に選びリスクを考慮した結果である」
ということですね。
目の届かない不特定多数の人にコードを公開する場合には、
迷惑をかけないよう注意していくようにします。
目の前の現象にとらわれず、
”For Each 文の処理順は保証されない”の一文に忠実に向き合い組み上げること、
を解決策とすればよいようですね。