DOBON.NETプログラミング道掲示板

■35503 / 5階層)  vb.netでExcelファイル操作
□投稿者/ 魔界の仮面弁士 大御所(1561回)-(2023/08/24(Thu) 14:16:09)
  • アイコン2023/08/24(Thu) 17:37:12 編集(投稿者)

    No35502に返信(Excel難しいさんの記事)
    > Dim lastRow As Integer = sh.Cells(sh.Rows.Count, "B").End(Microsoft.Office.Interop.Excel.XlDirection.xlUp).row

    先の回答がまるで反映されていないですよね…?
    Range オブジェクトすべてを変数にとり、使用後に廃棄しましょう。

    'Dim lastRow As Integer = sh.Cells(sh.Rows.Count, "B").End(Microsoft.Office.Interop.Excel.XlDirection.xlUp).row
    Dim cells = sh.Cells
    Dim rows = sh.Rows
    Dim rng = cells(rows.Count, "B")
    Dim rngEnd = rng.End(Microsoft.Office.Interop.Excel.XlDirection.xlUp)

    Dim lastRow As Integer = rngEnd.Row

    Marshal.RelaseComObject(rngEnd)
    Marshal.RelaseComObject(rng)
    Marshal.RelaseComObject(rows)
    Marshal.RelaseComObject(cells)

    正直なところ、生の Excel ライブラリを直接扱うのは、COM リソースの管理が面倒なので、
    先に紹介したような、Managed リソースで管理できるライブラリを使った方が楽だと思いますよ。


    > range = Cells.Range("B5:I" & lastRow)を
    この処理自体には何の問題もありません。
    実際のところ、
     Dim lastRow As Integer = 5
     range = Cells.Range("B5:I" & lastRow)
    であれば、問題は出ないですよね?

    問題があったのは、lastRow を求めるための先の手続きです。


    > Private Sub btn作成_Click(sender As Object, e As EventArgs) Handles btn作成.Click
    strCount が何をカウントしているのかの意図が不明瞭ですが、
    提示されたコードでは「If 〜 Then」よりも「End If」の方が多く、文法的に意味が通りません。
    正しいコードを提示しましょう。


    それと、COM オブジェクトの扱いに根本的な誤解があるようです。
     Dim o1 = sheet1.Cells
     Dim o2 = sheet1.Cells
    この場合、o1 と o2 は同一のオブジェクトを指しているように見えますが、
    実際は別物であり、 If o1 Is o2 Then は False となります。

    なのでこのケースでは、
     Marshal.ReleaseComObject(o2)
     Marshal.ReleaseComObject(o1)
    のように、それぞれを解放せねばなりません。

    それゆえに
     Dim o As Excel.Range = Nothing
     For n = 1 To 2
      o = sheet1.Cells
      :
     Next
     Marshal.ReleaseComObject(o)
    のような再代入処理が行われると、Range オブジェクトの解放漏れに繋がります。
    ※Range 以外の COM オブジェクト(Workbooks とか Workbook とか Sheets とか Worksheet とか)も同様です。

    ただし、
     For n = 1 To 2
      Dim o As Excel.Range = sheet1.Cells
      :
      Marshal.ReleaseComObject(o)
     Next
    のように、取得 → 解放の手続きをその都度行うのであれば、問題ありません。
    (とはいえ、何度も取得しなおす方法では、実行コストが高くなってしまいますが)


    > For rw As Integer = 0 To dgv.RowCount - 1
    >  If strCount = 0 Then
    >   wb = books.Open(txtPath.Text)
    >   sheets = wb.Worksheets
    >   sh = sheets("発注一覧")
    ということで、この書き方は NG 。

    そもそも、COM オブジェクトの問題が無かったとしても、
    このコードもあまりに不自然というものです。

    ループ内で、txtPath.Text が変化するわけでは無いのですから、
    毎回、COM オブジェクトを再取得する意味は無いはずです。
    ループの外で処理すれば済む話でしょう。

    Dim wb = books.Open(txtPath.Text)
    Dim sheets = wb.Worksheets
    Dim sh = sheets("発注一覧")
    For rw = 0 To dgv.RowCount - 1
      :
    Next
    Marshal.ReleaseComObject(sh)
    Marshal.ReleaseComObject(sheets)
    wb.Save()
    wb.Close(False)
    Marshal.ReleaseComObject(wb)
    ex.Quit()
    Marshal.ReleaseComObject(ex)


    それにしても、『For rw As Integer = 0 To dgv.RowCount - 1』って何の意味があるのでしょうか?
    dgv が DataGridView であるというのは想像がつきますが、
    ループ内で変数 rw が一度も使われていませんし、ループさせる意味が皆無に見えるのですが。
違反を報告
削除キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[4]: vb.netでExcelファイル操作 /Excel難しい 返信無し
 
上記関連ツリー

Nomalアイコン vb.netでExcelファイル操作 / Excel難しい (23/08/22(Tue) 14:55) #35490
Nomalアイコン Re[1]: vb.netでExcelファイル操作 / Hongliang (23/08/22(Tue) 15:04) #35491
│└Nomalアイコン Re[2]: vb.netでExcelファイル操作 / Excel難しい (23/08/22(Tue) 15:13) #35492
Nomalアイコン Re[1]: vb.netでExcelファイル操作 / 魔界の仮面弁士 (23/08/22(Tue) 15:37) #35493
  └Nomalアイコン Re[2]: vb.netでExcelファイル操作 / Excel難しい (23/08/23(Wed) 07:03) #35499
    └Nomalアイコン Re[3]: vb.netでExcelファイル操作 / 魔界の仮面弁士 (23/08/23(Wed) 15:12) #35500
      └Nomalアイコン Re[4]: vb.netでExcelファイル操作 / Excel難しい (23/08/24(Thu) 11:13) #35502
        └Nomalアイコン vb.netでExcelファイル操作 / 魔界の仮面弁士 (23/08/24(Thu) 14:16) #35503 ←Now

All 上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信

Mode/  Pass/


- Child Tree -