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

タイトル Re^2: ループ処理後にExcelのタスクが残る
投稿日: 2020/03/01(Sun) 17:40
投稿者魔界の仮面弁士
> もしも、xlwkSheet2 のインスタンスがセット済みだとしても、渡すべき引数が
>> xlwkSheet2.Copy(After:=xlSheet(i+1))
> になっていては、引数に渡した COM オブジェクトを解放できなくなるという問題があります。
> 引数に渡す COM オブジェクトも変数に受け、解放するようにしてください。
> 正しい Copy 手順については、次の投稿にて後述します。

というわけで、引数のインスタンスも解放されるよう、下記に修正案を示します。
ここでは 2 種類の実装例を用意してみました。

【パターン1】は
 i = 0 の時は、xlSheet(1) の直後に、xlwkSheet2 のコピーを挿入
 i = 1 の時は、「i=0 でコピーしたシート」の直後に、xlwkSheet2 のコピーを挿入
 i = 2 の時は、「i=1 でコピーしたシート」の直後に、xlwkSheet2 のコピーを挿入
という場合であり、【パターン2】方は
 i = 0 の時は、xlSheet("Sheet1") の直後に、xlwkSheet2 のコピーを挿入
 i = 1 の時は、「i=0 でコピーしたシート」の直後に、xlwkSheet2 のコピーを挿入
 i = 2 の時は、「i=1 でコピーしたシート」の直後に、xlwkSheet2 のコピーを挿入
という場合の記述方法です。


元々の指定方法だと、元のワークブック構成によっては、
xlSheet(i+1) が指し示すシートが "Sheet1" である可能性もあれば
xlSheet(i+1) と "Sheet1" が別物という可能性もあったため、
後者では明示的に、"Sheet1" を基準とするよう記述してみました。


【パターン1】
For i = 0 To …
  xlwkSheet2 = …
  Dim xlWorksheet1 = DirectCast(xlSheet(i + 1), Worksheet)
  xlwkSheet2.Copy(After:=xlWorksheet1)
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet1)
  Dim xlWorksheet2 = DirectCast(xlSheet(i + 2), Worksheet)
  xlWorksheet2.Name = "新しい名前"
   :
   :
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet2)
   :
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlwkSheet2)
Next


【パターン2】
xlwkSheet = DirectCast(xlSheet("Sheet1"), Worksheet)
For i = 0 To …
  xlwkSheet2 = …
  Dim xlWorksheet1 = DirectCast(xlSheet(xlwkSheet.Index + i), Worksheet)
  xlwkSheet2.Copy(After:=xlWorksheet1)
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet1)
  Dim xlWorksheet2 = DirectCast(xlSheet(xlwkSheet.Index + i + 1), Worksheet)
  xlWorksheet2.Name = "新しい名前"
   :
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlwkSheet2)
   :
  System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet2)
Next



上記では、ワークシートの選択方法も見直しています。
元のコードにあった "Sheet1 (2)" という名前は
「コピー時に生成された名前」を指しているのですよね。

そして元のコードでは、ループに入る前には
 xlwkSheet = DirectCast(xlSheet("Sheet1"),Worksheet)
という「固定的な名前」で指定しているのに対し、ループ内のコピー時には
 xlwkSheet2.Copy(After:=xlSheet(i+1))
という「数値での指定」に変わっており、さらにコピー後には、
 xlwkSheet2 = DirectCast(xlSheet("Sheet1 (2)"),Worksheet)
という「コピー時に生成されたであろう動的な名前」で指定されており、
指定方法に統一性が無く、曖昧に見えます

コピー後に自動生成される名前は、同一名があればさらに別の名になるため不確実です。
After:= や Copy:= は、コピー先の位置が明確になっているわけですから、
Index で指定した方が確実だと思いますので、その点を書き換えてみました。



なお上記では、xlwkSheet2 のインスタンスが xlwkSheet とは異なるシートという想定で記述しています。

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

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