EXCEL VBA で Series オブジェクトをソートできなかった話

 Series オブジェクトを PlotOrder プロパティでソートする必要があった話をした.今回,Series オブジェクトをソートするために Collection オブジェクトに代入したのだが,配列の最終要素を取得するところで実行時エラーとなり,解決していない.

 Series オブジェクトをソートするための方法としては,元のデータで比較する方法と,Series オブジェクトの最終 Point オブジェクトの Top プロパティを比較する方法がある.

 意味としてはどちらも同じだが,どうせなら元のデータで比較するのが王道と思われたのでそちらを試したのだが,今の自分にはスキル不足で手に負えなかった.悔しい.

Collection オブジェクトに代入した Series オブジェクトから Values プロパティを取得することは不可能

 理由は不明だが,Series オブジェクトを Collection オブジェクトに代入してしまうと Variant 型配列である Values プロパティの個々の要素を取得することはできなかった.これが,直接 Series オブジェクト経由でなら取得できるのは不可解である.

 上記のコードのうち,11 行目は正常に動作する.しかし,20 行目と 23 行目は実行時エラー ‘451’ が発生する.

実行時エラー '451': Property Letプロシージャが定義されておらず,Property Getプロシージャからオブジェクトが返されませんでした
実行時エラー ‘451’: Property Letプロシージャが定義されておらず,Property Getプロシージャからオブジェクトが返されませんでした

 エラーが発生してコードが停止した時点でローカルウィンドウを見てみる.Values プロパティは Variant 型の配列になっており,要素に値が格納されているのが分かる.

ローカルウィンドウでオブジェクトのプロパティを観察
ローカルウィンドウでオブジェクトのプロパティを観察

配列を Variant 型変数に代入すると取得できる

 その後のテストで,Collection の要素である Series オブジェクトの Values プロパティを Variant 型の変数に代入すると,ループにより各要素を取得できた.下記のテストコードには 2 つの Debug.Print があるが,どちらも動作する.

 この線で進めるなら Variant 型変数をもう一つ宣言してバブルソートすればよい.

 バブルソートは VBA Collectionのバブルソート ~ 単純実装からリフレクションを使った汎用化まで から引用した.

ソートの結果

 下記のテストコードをソート前とソート後に置いて,結果を比較する.

 さて,結果であるが,少し不可解なものとなった.例として沖縄県の結果を示す.なんとなく昇順に見えるが,所々おかしい.

 こちらはソート前である.

 おそらくどこかでコードの転記ミスをしている.

Series オブジェクトの PlotOrder プロパティを変更する方法は?

 もう少し考察を進めて,データ系列を示す Series オブジェクトにおいては .NewSeries メソッドで追加された順に .PlotOrder プロパティが増えていくことを思い出そう.PlotOrder プロパティは SeriesCollection のインデックスにもなっている.

 事実,Series オブジェクトの PlotOrder プロパティを変更することでデータ系列の順番を変更することもできる.これをソートに使えないだろうか.

(6)-2 の結果

 これも結果がおかしい.何となく昇順に見える程度で,実際にはめちゃくちゃだ.

(6)-3 の結果

 桁数程度しか昇順になっていない.

(6)-4 は失敗する

 実行時エラーが発生してしまう.

結局ループなのか

 どうにもうまく行かない.結局,Collection オブジェクトに Series オブジェクトを代入してソートし,二重ループで SeriesCollection と Name プロパティが一致した場合に PlotOrder を書き換えるという方法しか思いつかない.

 で,やってみた.

(6)-6 の結果

(6)-7 の結果

 結果が不安定である.

そもそも Collection オブジェクトに正常に格納できているのだろうか?

 テストしてみるしかない.

For Each ~ Next ステートメントの結果

For ~ Next ステートメントの結果

Collection オブジェクトには正常に格納されている

 これはきちんと取得できているようだ.となると,ソートに問題があることになる.

課題

 2019 年 12 月 25 日時点で Series オブジェクトのソートは解決できていない.2 週間ほど粘ったが,駄目だった.これは今後の課題だ.

“EXCEL VBA で Series オブジェクトをソートできなかった話” への2件の返信

  1. はじめまして。たまたまSeriesのソートをしたくて検索していたらこのブログに行き当たりました。

    自分のやりたいことは解決しましたが、何となく気になる結末だったので(お節介ですが)この記事のコードがうまくいかなかった理由を考えてみました。

    ・まずバブルソートの実装ですが、系列をSwapしてもmyArray1,myArray2が更新されない点が参照元の記事と異なります。特にmyArray1がそれまで調べた中での最小値になっておらず、予定外のSwapが発生していました。

    ・次にPlotOder。Seriesのソートが終わってもPlotOderはソート前のままです。ソート完了後に前から1,2,…でもいいですし、もしくは例えばp=1でqのループが終わった時、1番目は(最も少ない)渡名喜村になっているはずなので、next p の直前で myCall(p).PlotOder=p とできます。

    上記の2点を修正すればSeriesオブジェクトのソート+グラフのプロットへ反映されるかと思います。

    1. ぼん 様

      貴重なコメント,ありがとうございます.
      ただ今,時間がなくて試せないのですが,時間ができた時に試してみたく存じます.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください