tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^3: SeriesCollection.Add後、Excelのタスクが残る
投稿日: 2020/01/29(Wed) 13:06
投稿者魔界の仮面弁士
> ObjRelease関数を以下のように書き換えました。
その実装パターンなら、ReleaseComObject は呼ばずに、
いきなり FinalReleaseComObject を呼ぶだけでも良さそうですね。



> Dim SeriesCollectionObj As Object = Nothing 'SeriesCollection宣言ではプロパティ代入時になぜかエラー。
どのプロパティの代入時に失敗していますか?
(なお、chtObj.SeriesCollection はプロパティではなくメソッドです)


> srsObj = SeriesCollectionObj(1) 'コレクションは代入して消去が必要。
これなんですが、SeriesCollection が IEnumerable であるという点に注意が必要です。

相互運用機能アセンブリの実装如何によっては、上記が最初の系列ではなく、
その次の系列を返してくる可能性があるのです。


つまり、SeriesCollectionObj.Count = 2 な状態においては、マネージ呼び出しによって
 srsObj = SeriesCollectionObj(0) ' 系列1
 srsObj = SeriesCollectionObj(1) ' 系列2
が返されてしまうという事です。最初の要素は 0 から始まります。

なお要素数が 1 の時に SeriesCollectionObj(1) を指定した場合、srsObj は Nothing になります。
この書き方の場合、範囲外の整数を引数に渡した場合に Nothing が返されるためです。

※ Enumerable.ElementAtOrDefault(Of T) 拡張メソッドと同様の動作


一方 Excel VBA で使う時のように、最初の要素が 1 から始まる指定にする場合は、
以下のいずれかの構文が必要となります。
 srsObj = chtObj.SeriesCollection(1)
 srsObj = SeriesCollectionObj.Item(1)
 srsObj = SeriesCollectionObj._Default(1)
 srsObj = CallByName(SeriesCollectionObj, "[DispId=0]", CallType.Method, 1)
 srsObj = CallByName(SeriesCollectionObj, "", CallType.Method, 1)

この書き方の場合、範囲外の整数を引数に渡すと Excel ライブラリから COM 例外が返されます。


> SeriesCollectionObj.Add(Source:=rngObj)
> の引数の方だったのですね。

以下、参照カウントの内部増加を軽減させるための修正案を載せておきます。
一応 Option Strict On にも対応させたうえで、変数のスコープはできるだけ狭くしてあります。


Dim shcolObj As SeriesCollection = DirectCast(chtObj.SeriesCollection(Type.Missing), SeriesCollection)
Do Until shcolObj.Count = 0
    Dim foo As Series = DirectCast(chtObj.SeriesCollection(1), Series)
    foo.Delete()
    ObjRelease(foo)
Loop
Dim rngB1B5 As Range = wstObj.Range("B1:B5")
' Source:=(rngB1B5) でも良いのですが、式として渡していることを明確にするため、
' Source:=CObj(rngB1B5) という回りくどい表現にしています
srsObj = DirectCast(shcolObj.Add(Source:=CObj(rngB1B5)), Series)
ObjRelease(rngB1B5)
ObjRelease(shcolObj)

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。