データグリッドビューをエクセルに出力したいです
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/8/9 10:22:36
クリップボードを使っても構わないのであれば、
.ClipboardCopyMode プロパティを指定して
.SelectAll メソッドで全選択して
.GetClipboardContent メソッドで得たデータを
Clipboard オブジェクトに(加工してから)渡す
という手順を採ることで、データを一括転送できます。
http://dobon.net/vb/dotnet/datagridview/clipboardcopy.html
貼り付けには、Worksheet オブジェクトあるいは Range オブジェクトの
PasteSpecial メソッドを使うことができるでしょう。大抵の場合、
セル単位でひとつずつ貼り付けるよりも高速になると思います。
クリップボードを汚したくない場合には、ActiveX Data Object の PIA を
参照設定して、切断型 Recordset に DataGridView の内容を転写してから、
Range オブジェクトの CopyFromRecordset メソッドに渡すという手もあります。
> book = app.Workbooks.Open("C:\form3\Book1.xlsx")
> sheet = book.Worksheets(1)
ReleaseComObject のために、
books = app.Workbooks
book = books.Open("C:\form3\Book1.xlsx")
sheets = book.Worksheets
sheet = DirectCast(sheets(1), Excel.Worksheet)
のようにするべきです。Workbooks や Sheets も解放対象です。
> sheet.Range("A2").Value = "aaa"
こちらも同様に、
rng = sheet.Range("A2")
rng.Value = "aaa"
Marshal.ReleaseComObject(rng)
のようにします。
> System.Threading.Thread.Sleep(5000)
UI スレッドから Sleep メソッドを呼び出してはいけません。
Excel オートメーションの利用中ならば尚の事。
.ClipboardCopyMode プロパティを指定して
.SelectAll メソッドで全選択して
.GetClipboardContent メソッドで得たデータを
Clipboard オブジェクトに(加工してから)渡す
という手順を採ることで、データを一括転送できます。
http://dobon.net/vb/dotnet/datagridview/clipboardcopy.html
貼り付けには、Worksheet オブジェクトあるいは Range オブジェクトの
PasteSpecial メソッドを使うことができるでしょう。大抵の場合、
セル単位でひとつずつ貼り付けるよりも高速になると思います。
クリップボードを汚したくない場合には、ActiveX Data Object の PIA を
参照設定して、切断型 Recordset に DataGridView の内容を転写してから、
Range オブジェクトの CopyFromRecordset メソッドに渡すという手もあります。
> book = app.Workbooks.Open("C:\form3\Book1.xlsx")
> sheet = book.Worksheets(1)
ReleaseComObject のために、
books = app.Workbooks
book = books.Open("C:\form3\Book1.xlsx")
sheets = book.Worksheets
sheet = DirectCast(sheets(1), Excel.Worksheet)
のようにするべきです。Workbooks や Sheets も解放対象です。
> sheet.Range("A2").Value = "aaa"
こちらも同様に、
rng = sheet.Range("A2")
rng.Value = "aaa"
Marshal.ReleaseComObject(rng)
のようにします。
> System.Threading.Thread.Sleep(5000)
UI スレッドから Sleep メソッドを呼び出してはいけません。
Excel オートメーションの利用中ならば尚の事。
投稿者 (削除されました)  ()
投稿日時
2017/8/9 10:24:08
(削除されました)
投稿者 初心者  (社会人)
投稿日時
2017/8/9 11:21:20
回答ありがとうございます。
ご指摘いただいた箇所は後で修正します。
For i As Integer = 0 To DataGridView1.Rows.Count - 1
For j As Integer = 2 To DataGridView1.Rows.Count - 1
sheet.Range("A2").Value = DataGridView1.Rows(i).Cells(1).Value
sheet.Range("B2").Value = DataGridView1.Rows(i).Cells(4).Value
sheet.Range("C2").Value = DataGridView1.Rows(i).Cells(5).Value
sheet.Range("D2").Value = DataGridView1.Rows(i).Cells(6).Value
sheet.Range("E2").Value = DataGridView1.Rows(i).Cells(7).Value
Next
Next
これでデータグリッドの一行だけはExcelに出力できるようになりました。
jをExcelのセルの値に持ってきたいのですが、HRESULT からの例外:0x800A03ECとエラーが出てしまいます。どうしたらいいでしょうか??
ご指摘いただいた箇所は後で修正します。
For i As Integer = 0 To DataGridView1.Rows.Count - 1
For j As Integer = 2 To DataGridView1.Rows.Count - 1
sheet.Range("A2").Value = DataGridView1.Rows(i).Cells(1).Value
sheet.Range("B2").Value = DataGridView1.Rows(i).Cells(4).Value
sheet.Range("C2").Value = DataGridView1.Rows(i).Cells(5).Value
sheet.Range("D2").Value = DataGridView1.Rows(i).Cells(6).Value
sheet.Range("E2").Value = DataGridView1.Rows(i).Cells(7).Value
Next
Next
これでデータグリッドの一行だけはExcelに出力できるようになりました。
jをExcelのセルの値に持ってきたいのですが、HRESULT からの例外:0x800A03ECとエラーが出てしまいます。どうしたらいいでしょうか??
投稿者 YuO  (社会人)
投稿日時
2017/8/9 11:42:46
とりあえず,DataGridViewの行とExcelの行が1対1の対応をするのであれば,二重ループはいりません。
DataGridViewの行番号であるiでループを回して,Excelの行番号は(i + 2)を使えば良いです。
つまり,
2015以降,
0x800A03ECのCOMExceptionですが,状況に依存して色々な理由で出るようです。
とりあえず,魔界の仮面弁士さんの書かれているようにCOMの解放をきっちりやると起きなくなることもあるようです。
根本的には,Excelのオートメーションを使わなければCOMExceptionは発生しません。
EPPlusとかNPOIとかClosedXMLとかのライブラリが存在します。
使い方もExcelオートメーションとそれほど変わらないようですし,こちらに切り替えてみるのも良いでしょう。
# 選択基準はnuget.orgでExcelを検索して出てくる,オートメーションを使っておらず,書き込み可能な上位3つ。
DataGridViewの行番号であるiでループを回して,Excelの行番号は(i + 2)を使えば良いです。
つまり,
"A" & (i + 2).ToString()
のように書けば"A2", "A3", ...となります。2015以降,
$"A{i + 2}"
と書いても同じようになります。0x800A03ECのCOMExceptionですが,状況に依存して色々な理由で出るようです。
とりあえず,魔界の仮面弁士さんの書かれているようにCOMの解放をきっちりやると起きなくなることもあるようです。
根本的には,Excelのオートメーションを使わなければCOMExceptionは発生しません。
EPPlusとかNPOIとかClosedXMLとかのライブラリが存在します。
使い方もExcelオートメーションとそれほど変わらないようですし,こちらに切り替えてみるのも良いでしょう。
# 選択基準はnuget.orgでExcelを検索して出てくる,オートメーションを使っておらず,書き込み可能な上位3つ。
投稿者 初心者  (社会人)
投稿日時
2017/8/9 11:59:32
Yuoさん
回答ありがとうございます。
For i As Integer = 0 To DataGridView1.Rows.Count - 1
sheet.Range("A" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(1).Value
sheet.Range("B" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(4).Value
sheet.Range("C" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(5).Value
sheet.Range("D" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(6).Value
sheet.Range("E" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(7).Value
Next
これでできるようになりました!!
後は、細かい修正をしていきたいと思います。ありがとうございました。
回答ありがとうございます。
For i As Integer = 0 To DataGridView1.Rows.Count - 1
sheet.Range("A" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(1).Value
sheet.Range("B" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(4).Value
sheet.Range("C" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(5).Value
sheet.Range("D" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(6).Value
sheet.Range("E" & i + 2 & "").Value = DataGridView1.Rows(i).Cells(7).Value
Next
これでできるようになりました!!
後は、細かい修正をしていきたいと思います。ありがとうございました。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/8/9 12:44:01
> DataGridView1.Rows(i).Cells(1).Value
実はこれも無駄で、
DataGridView1(xIndex, yIndex).Value
で十分です。
実はこれも無駄で、
DataGridView1(xIndex, yIndex).Value
で十分です。
「DataGridView1.Rows(i).Cells(1).Value」は
.Rows → DataGridViewRowCollection 型
(i) → DataGridViewRow 型
.Cells → DataGridViewCellCollection 型
(1) → DataGridViewCell 型
.Value → Object 型
という段階を経てオブジェクトが参照されますが、
「DataGridView1(xIndex, yIndex).Value」を使えば、
(xIndex, yIndex) → DataGridViewCell 型
.Value → Object 型
だけで済みます。
.Rows → DataGridViewRowCollection 型
(i) → DataGridViewRow 型
.Cells → DataGridViewCellCollection 型
(1) → DataGridViewCell 型
.Value → Object 型
という段階を経てオブジェクトが参照されますが、
「DataGridView1(xIndex, yIndex).Value」を使えば、
(xIndex, yIndex) → DataGridViewCell 型
.Value → Object 型
だけで済みます。
投稿者 初心者  (社会人)
投稿日時
2017/8/9 13:46:42
返信ありがとうございます。そして追加の情報ありがとうございます。
> sheets = book.Worksheets
修正していたところ上記の箇所で
「型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Microsoft.Office.Interop.Excel.Worksheets' にキャストできません。」
エラーがでてしまいました。
> sheets = book.Worksheets
修正していたところ上記の箇所で
「型 'System.__ComObject' の COM オブジェクトをインターフェイス型 'Microsoft.Office.Interop.Excel.Worksheets' にキャストできません。」
エラーがでてしまいました。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/8/9 20:11:06
Worksheets オブジェクトは、As Worksheets ではなく As Sheets で受けてください。
投稿者 (削除されました)  ()
投稿日時
2017/8/10 09:22:43
(削除されました)
投稿者 初心者  (社会人)
投稿日時
2017/8/10 09:23:57
返信ありがとうございます。
一応正常に動くことは確認できたのですが、COMの解放がちゃんとできていないせいかタスクが残ってしまいます。
for文の箇所をコメントアウトして動かしたらタスクは残らなかったのでfor文がおかしいと思うのですがどこがおかしいのでしょうか、、、お願いします。
'出力ボタン
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim app As Excel.Application = Nothing
Dim books As Excel.Workbooks = Nothing
Dim book As Excel.Workbook = Nothing
Dim sheets As Excel.Sheets = Nothing
Dim sheet As Excel.Worksheet = Nothing
Dim range As Excel.Range = Nothing
Try
'Excelを開く
app = New Excel.Application()
'Bookを開く
books = app.Workbooks
book = books.Open("C:\form3\Book1.xlsx")
'シートの指定
sheets = book.Worksheets
sheet = DirectCast(sheets(1), Excel.Worksheet)
range = sheet.Range("B2")
range.Value = LoginForm1.username & "さん"
'Excelに出力する
For i As Integer = 0 To DataGridView1.Rows.Count - 1
range = sheet.Range("B" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(1).Value
range = sheet.Range("C" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(4).Value
range = sheet.Range("D" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(5).Value
range = sheet.Range("E" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(6).Value
range = sheet.Range("F" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(7).Value
'range = sheet.Range("B" & i + 5 & "")
'range.Value = DataGridView1(i, 1).Value
'range = sheet.Range("C" & i + 5 & "")
'range.Value = DataGridView1(i, 4).Value
'range = sheet.Range("D" & i + 5 & "")
'range.Value = DataGridView1(i, 5).Value
'range = sheet.Range("E" & i + 5 & "")
'range.Value = DataGridView1(i, 6).Value
'range = sheet.Range("F" & i + 5 & "")
'range.Value = DataGridView1(i, 7).Value
Next
'Excelの表示
app.Visible = True
''5秒だけ表示する
System.Threading.Thread.Sleep(1000)
'保存する
book.Save()
Catch ex As Exception
Throw ex
Finally
Marshal.ReleaseComObject(range)
Marshal.ReleaseComObject(sheet)
Marshal.ReleaseComObject(sheets)
Marshal.ReleaseComObject(book)
Marshal.ReleaseComObject(books)
'閉じる
app.Quit()
Marshal.ReleaseComObject(app)
End Try
End Sub
一応正常に動くことは確認できたのですが、COMの解放がちゃんとできていないせいかタスクが残ってしまいます。
for文の箇所をコメントアウトして動かしたらタスクは残らなかったのでfor文がおかしいと思うのですがどこがおかしいのでしょうか、、、お願いします。
'出力ボタン
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim app As Excel.Application = Nothing
Dim books As Excel.Workbooks = Nothing
Dim book As Excel.Workbook = Nothing
Dim sheets As Excel.Sheets = Nothing
Dim sheet As Excel.Worksheet = Nothing
Dim range As Excel.Range = Nothing
Try
'Excelを開く
app = New Excel.Application()
'Bookを開く
books = app.Workbooks
book = books.Open("C:\form3\Book1.xlsx")
'シートの指定
sheets = book.Worksheets
sheet = DirectCast(sheets(1), Excel.Worksheet)
range = sheet.Range("B2")
range.Value = LoginForm1.username & "さん"
'Excelに出力する
For i As Integer = 0 To DataGridView1.Rows.Count - 1
range = sheet.Range("B" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(1).Value
range = sheet.Range("C" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(4).Value
range = sheet.Range("D" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(5).Value
range = sheet.Range("E" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(6).Value
range = sheet.Range("F" & i + 5 & "")
range.Value = DataGridView1.Rows(i).Cells(7).Value
'range = sheet.Range("B" & i + 5 & "")
'range.Value = DataGridView1(i, 1).Value
'range = sheet.Range("C" & i + 5 & "")
'range.Value = DataGridView1(i, 4).Value
'range = sheet.Range("D" & i + 5 & "")
'range.Value = DataGridView1(i, 5).Value
'range = sheet.Range("E" & i + 5 & "")
'range.Value = DataGridView1(i, 6).Value
'range = sheet.Range("F" & i + 5 & "")
'range.Value = DataGridView1(i, 7).Value
Next
'Excelの表示
app.Visible = True
''5秒だけ表示する
System.Threading.Thread.Sleep(1000)
'保存する
book.Save()
Catch ex As Exception
Throw ex
Finally
Marshal.ReleaseComObject(range)
Marshal.ReleaseComObject(sheet)
Marshal.ReleaseComObject(sheets)
Marshal.ReleaseComObject(book)
Marshal.ReleaseComObject(books)
'閉じる
app.Quit()
Marshal.ReleaseComObject(app)
End Try
End Sub
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/8/10 10:54:27
> range = sheet.Range("B" & i + 5 & "")
range オブジェクトには、「B5セル」を現す Range オブジェクトが格納されています。
それを解放しないまま、
> range = sheet.Range("C" & i + 5 & "")
にて、その参照先を「C5セル」のインスタンスに差し替えています。これが原因ですね。
解放処理は「変数」ではなく、「変数が指し示すインスタンス」に対して行われますので、
別のインスタンスに差し替えるのであれば、差し替える前のインスタンスも ReleaseComObject せねばなりません。
なお、連続した領域であるならば、Range("B5:F5") などの範囲で取得し、
Value プロパティに「配列」で渡す形にするのがお奨めです。
通信回数を減らすことができるため、処理速度がUPしますし、
COM 解放の手間も減らすことができます。
> ''5秒だけ表示する
> System.Threading.Thread.Sleep(1000)
これでは 5 秒になっていませんよね。
そもそも先にも述べたように、この場所での Sleep の利用は厳禁です。
(メッセージループを阻害するため、Windows Forms の UI スレッドから利用すべきでは無い)
どうしても待ち合わせをしたいなら、Timer コンポーネントを利用するか、
もしくは、『Await task.Delay(5000)』などを使うようにします。
> Catch ex As Exception
> Throw ex
これは悪手です。このような例外処理を書いてはいけません。
これでは例外のスタックトレースが握りつぶされますので、
どこで発生した問題なのかが分からなくなってしまいます。
別の例外に変換するのであればさておき、例外をそのまま再スローしたいだけであれば、
「Throw ex」ではなく「Throw」とするべきです。
また、今回のようにそもそも例外処理を行わないのであれば、
Catch 句無しの「Try~Finally~End Try」を使うのが望ましいです。
> Finally
> Marshal.ReleaseComObject(range)
> Marshal.ReleaseComObject(sheet)
> Marshal.ReleaseComObject(sheets)
> Marshal.ReleaseComObject(book)
> Marshal.ReleaseComObject(books)
> '閉じる
> app.Quit()
> Marshal.ReleaseComObject(app)
>
> End Try
これも非常にまずいです。
たとえばこの処理だと、Book1.xlsx を開けずに処理が中断した場合、
app と books のみが設定され、それ以外は Nothing の状態に陥ります。
しかし ReleaseComObject にNothing を渡すことはできませんので、
その時点で、NullReferenceException の例外が発生して
Finally 句が中断されます。結果、COM オブジェクトは一切解放されません。
ということはつまり、Finally 句としては何の役目も果たしていない、ということです。
しかも Catch 句でスタックトレースが潰されているので、処理としては
Try ブロックを使わずに書いたケースよりも、むしろ悪化しているほどです。
Finally 句で対処するのであれば、
Marshal.ReleaseComObject(sheets)
ではなく、それぞれを
If sheets IsNot Nothing AndAlso Marshal.IsComObject(sheets) Then
Marshal.ReleaseComObject(sheets)
End If
と書くべきです。これなら、Finally ブロック内での例外の発生を抑えられます。
上記で IsComObject は呼ばなくても構いませんが、COM オブジェクトではなく
マネージオブジェクトを返すような修正が入った場合には、ReleaseComObject に
渡すわけには行かなくなるので、念のための保険です。
とはいえ、If 文を毎回書くのは面倒だと思いますので、解放処理を行うために
http://hanatyan.sakura.ne.jp/dotnet/Excel01.htm
の末尾にある MRComObject メソッドを用意しておくのも良いでしょう。
そうすれば、下記のように簡潔に書けます。
range オブジェクトには、「B5セル」を現す Range オブジェクトが格納されています。
それを解放しないまま、
> range = sheet.Range("C" & i + 5 & "")
にて、その参照先を「C5セル」のインスタンスに差し替えています。これが原因ですね。
解放処理は「変数」ではなく、「変数が指し示すインスタンス」に対して行われますので、
別のインスタンスに差し替えるのであれば、差し替える前のインスタンスも ReleaseComObject せねばなりません。
なお、連続した領域であるならば、Range("B5:F5") などの範囲で取得し、
Value プロパティに「配列」で渡す形にするのがお奨めです。
通信回数を減らすことができるため、処理速度がUPしますし、
COM 解放の手間も減らすことができます。
> ''5秒だけ表示する
> System.Threading.Thread.Sleep(1000)
これでは 5 秒になっていませんよね。
そもそも先にも述べたように、この場所での Sleep の利用は厳禁です。
(メッセージループを阻害するため、Windows Forms の UI スレッドから利用すべきでは無い)
どうしても待ち合わせをしたいなら、Timer コンポーネントを利用するか、
もしくは、『Await task.Delay(5000)』などを使うようにします。
> Catch ex As Exception
> Throw ex
これは悪手です。このような例外処理を書いてはいけません。
これでは例外のスタックトレースが握りつぶされますので、
どこで発生した問題なのかが分からなくなってしまいます。
別の例外に変換するのであればさておき、例外をそのまま再スローしたいだけであれば、
「Throw ex」ではなく「Throw」とするべきです。
また、今回のようにそもそも例外処理を行わないのであれば、
Catch 句無しの「Try~Finally~End Try」を使うのが望ましいです。
> Finally
> Marshal.ReleaseComObject(range)
> Marshal.ReleaseComObject(sheet)
> Marshal.ReleaseComObject(sheets)
> Marshal.ReleaseComObject(book)
> Marshal.ReleaseComObject(books)
> '閉じる
> app.Quit()
> Marshal.ReleaseComObject(app)
>
> End Try
これも非常にまずいです。
たとえばこの処理だと、Book1.xlsx を開けずに処理が中断した場合、
app と books のみが設定され、それ以外は Nothing の状態に陥ります。
しかし ReleaseComObject にNothing を渡すことはできませんので、
その時点で、NullReferenceException の例外が発生して
Finally 句が中断されます。結果、COM オブジェクトは一切解放されません。
ということはつまり、Finally 句としては何の役目も果たしていない、ということです。
しかも Catch 句でスタックトレースが潰されているので、処理としては
Try ブロックを使わずに書いたケースよりも、むしろ悪化しているほどです。
Finally 句で対処するのであれば、
Marshal.ReleaseComObject(sheets)
ではなく、それぞれを
If sheets IsNot Nothing AndAlso Marshal.IsComObject(sheets) Then
Marshal.ReleaseComObject(sheets)
End If
と書くべきです。これなら、Finally ブロック内での例外の発生を抑えられます。
上記で IsComObject は呼ばなくても構いませんが、COM オブジェクトではなく
マネージオブジェクトを返すような修正が入った場合には、ReleaseComObject に
渡すわけには行かなくなるので、念のための保険です。
とはいえ、If 文を毎回書くのは面倒だと思いますので、解放処理を行うために
http://hanatyan.sakura.ne.jp/dotnet/Excel01.htm
の末尾にある MRComObject メソッドを用意しておくのも良いでしょう。
そうすれば、下記のように簡潔に書けます。
Finally
MRComObject(range)
MRComObject(sheet)
MRComObject(sheets)
MRComObject(book)
MRComObject(books)
If app IsNot Nothing Then
app.Quit()
End If
MRComObject(app)
End Type
投稿者 初心者  (社会人)
投稿日時
2017/8/18 11:25:56
返信ありがとうございます。
ご指摘いただいた箇所は修正して完成させることができました。
あとひとつ質問なのですが、セルを初期化したくて
sheet.Rows("5:50").Delete()
というコードを追加したらCOMが正常に解放されなくなりました。
どうしてでしょうか??
ご指摘いただいた箇所は修正して完成させることができました。
あとひとつ質問なのですが、セルを初期化したくて
sheet.Rows("5:50").Delete()
というコードを追加したらCOMが正常に解放されなくなりました。
どうしてでしょうか??
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/8/18 13:05:06
> あとひとつ質問なのですが、セルを初期化したくて
初期化なら Clear メソッドなのでは。
> sheet.Rows("5:50").Delete()
先の指摘と同じ理由により NG です。(^_^;)
> ご指摘いただいた箇所は修正して完成させることができました。
「指摘した箇所」だけではなく、
「指摘した内容」を見直しましょう。
'Worksheet の Rows プロパティは引数の無いプロパティであり、
'戻り値として、Excel.Range オブジェクトを返します。
oRows1 = sheet.Rows
'Range のインデクサは、別の Range オブジェクトを返します。
'これは ._Default("5:50") というプロパティ呼び出しと同義です。
oRows2 = oRows("5:50")
'Range の Delete メソッドは、削除に成功すると True を返します。
'この戻り値は COM オブジェクトではないため、
'変数に受けて解放する必要はありません。
oRows.Delete()
あとは、上記の oRows1 と oRows2 を処分すれば OK です。
初期化なら Clear メソッドなのでは。
> sheet.Rows("5:50").Delete()
先の指摘と同じ理由により NG です。(^_^;)
> ご指摘いただいた箇所は修正して完成させることができました。
「指摘した箇所」だけではなく、
「指摘した内容」を見直しましょう。
'Worksheet の Rows プロパティは引数の無いプロパティであり、
'戻り値として、Excel.Range オブジェクトを返します。
oRows1 = sheet.Rows
'Range のインデクサは、別の Range オブジェクトを返します。
'これは ._Default("5:50") というプロパティ呼び出しと同義です。
oRows2 = oRows("5:50")
'Range の Delete メソッドは、削除に成功すると True を返します。
'この戻り値は COM オブジェクトではないため、
'変数に受けて解放する必要はありません。
oRows.Delete()
あとは、上記の oRows1 と oRows2 を処分すれば OK です。
DBと接続してデータグリッドビューにテーブルの情報を表示しています。
そこで、出力ボタンを押下した際にデータグリッドビューに表示しているデータをExcelに入力できるようにしたいです。
Excelにはあらかじめカラム名だけ書いていて後はそこにデータを入力していきたいです。
'出力ボタン
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim app As Excel.Application = Nothing
Dim book As Excel.Workbook = Nothing
Dim sheet As Excel.Worksheet = Nothing
Try
app = New Excel.Application()
app = CreateObject("Excel.Application")
book = app.Workbooks.Open("C:\form3\Book1.xlsx")
sheet = book.Worksheets(1)
'For i As Integer = 0 To DataGridView1.Rows.Count - 1
'For x As Integer = 0 To DataGridView1.ColumnCount - 1
sheet.Range("A2").Value = "aaa"
sheet.Range("B2").Value = "ab"
sheet.Range("C2").Value = "abc"
sheet.Range("D2").Value = "a"
sheet.Range("E2").Value = "a"
'Next
'Next
app.Visible = True
System.Threading.Thread.Sleep(5000)
book.Save()
app.Quit()
Catch ex As Exception
Throw ex
Finally
Marshal.ReleaseComObject(sheet)
Marshal.ReleaseComObject(book)
Marshal.ReleaseComObject(app)
End Try
End Sub
一応今はこれでExcelにベタ書きで文字を入力することはできています。
お願いします。
for文で回して出力していくと思うのですが書き方がわかっていません。。。