タイトル | : Re^2: ループ処理後にExcelのタスクが残る |
記事No | : 12014 |
投稿日 | : 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 とは異なるシートという想定で記述しています。
|