Reputation: 15
i am using microsoft.excel.introp.dll to save datagridview data to an excel file, my question is how to save two datagridview data in one file (sheet1 and sheet2)
i am using this code to save the first datagridview as excel file:
Private Sub copyAlltoClipboard()
DataGridView1.SelectAll()
Dim dataObj As DataObject = DataGridView1.GetClipboardContent()
If dataObj IsNot Nothing Then Clipboard.SetDataObject(dataObj)
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
MessageBox.Show("Exception Occurred while releasing object " & ex.ToString())
Finally
GC.Collect()
End Try
End Sub
Dim sfd As SaveFileDialog = New SaveFileDialog()
sfd.Filter = "Microsoft Excel 97-2003 Workbook (*.xls)|*.xls"
sfd.FileName = NomTextBox.Text & "_" & PrenomTextBox.Text
If sfd.ShowDialog() = DialogResult.OK Then
copyAlltoClipboard()
Dim xlexcel As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
xlexcel = New Excel.Application()
xlexcel.Visible = False
xlWorkBook = xlexcel.Workbooks.Add(misValue)
xlWorkSheet = CType(xlWorkBook.Worksheets.Item(1), Excel.Worksheet)
Dim CR As Excel.Range = CType(xlWorkSheet.Cells(1, 1), Excel.Range)
CR.[Select]()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue)
xlexcel.DisplayAlerts = True
xlWorkBook.Close(True, misValue, misValue)
xlexcel.Quit()
releaseObject(xlWorkSheet)
releaseObject(xlWorkBook)
releaseObject(xlexcel)
Clipboard.Clear()
This not my code i have take it from an other person and modified it.
Upvotes: 0
Views: 243
Reputation: 9479
To start, you should be aware that using Interop
is not recommended. There are other third-party libraries that work better in many ways and have some advantages. Namely, using interop requires that the target computer have the same Excel library as the code uses. However, I am aware that this may be required or an only option. If this is the case, then the code below may help.
One issue the current code has is that there is no control over what the “worksheet name” should be. IMHO, it is better to give the worksheet a “specific” name so that the code could later overwrite the file with new data. By simply adding new worksheets, you may end up with a bunch of worksheets with the same data.
Therefore, I created a method GetWorksheet
that takes a Workbook
and String
name.
This method will return a Worksheet
that either “matches” the given name OR if the worksheet name is not found in the given workbook, then, it will return a new worksheet with the given name. This method may look something like…
Private Function GetWorksheet(wb As Excel.Workbook, name As String) As Excel.Worksheet
For Each ws In wb.Sheets
If ws.Name = name Then
Return ws
End If
Next
Dim newWS = wb.Worksheets.Add()
newWS.Name = name
Return newWS
End Function
The code above loops through all the worksheets in the given workbook. If a worksheet’s name is found that matches the given name, then that worksheet is returned. If the worksheet name is not found, then a new worksheet with the given name is returned. This will allow you to name the worksheets to something more intuitive than “Sheet1”, “Sheet2” etc. We can use this method to get an existing worksheet or create a new worksheet for each grid we want to add to the workbook.
Next, a second helper method called AddSheetToWorkbook
that takes a workbook, a DataGridView
and a worksheet name... may make things easier. In this method, the code would select all the cells in the given grid. Use the above method to get a worksheet with the given worksheet name from the given (OPEN) workbook. Then paste the copied cells into the worksheet. It may look something like…
Private Sub AddSheetToWorkbook(xlWorkBook As Excel.Workbook, dgv As DataGridView, wkSheetName As String)
dgv.SelectAll()
Dim dataObj As DataObject = dgv.GetClipboardContent()
If dataObj IsNot Nothing Then Clipboard.SetDataObject(dataObj)
Dim xlWorkSheet = GetWorksheet(xlWorkBook, wkSheetName)
Dim CR As Excel.Range = CType(xlWorkSheet.Cells(1, 1), Excel.Range)
CR.[Select]()
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
End Sub
We can use this method to add each DataGridView
to a different worksheet in the workbook.
Finally, putting all this together may look something like below. I used a little different approach using the Try/Catch/Finally
to make sure the Excel COM objects are disposed of properly, however, in my test, the current code also works.
The code uses the same approach as the current code. Get the file name for the workbook using an SaveFileDialog.
Create a new Excel app, add a workbook, then add the two grids to the workbook. Each grid will be on a sperate worksheet with the supplied worksheet name. The file is saved and Finally
the COM
objects are closed and released.
It is unclear “where” this code is called in the current posted code. In this example, the code is run by pressing a button on the form.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sfd As SaveFileDialog = New SaveFileDialog With {
.Filter = "Microsoft Excel 97-2003 Workbook (*.xls)|*.xls",
.FileName = NomTextBox.Text & "_" & PrenomTextBox.Text
}
If sfd.ShowDialog() = DialogResult.OK Then
Dim xlexcel As Excel.Application = Nothing
Dim xlWorkBook As Excel.Workbook = Nothing
Dim misValue As Object = Reflection.Missing.Value
Try
xlexcel = New Excel.Application()
xlWorkBook = xlexcel.Workbooks.Add()
AddSheetToWorkbook(xlWorkBook, DataGridView1, "Grid1")
AddSheetToWorkbook(xlWorkBook, DataGridView2, "Grid2")
xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue)
Catch ex As Exception
MessageBox.Show("Error: " + ex.Message)
Finally
If (xlWorkBook IsNot Nothing) Then
xlWorkBook.Close()
Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook)
End If
If (xlexcel IsNot Nothing) Then
xlexcel.Quit()
Runtime.InteropServices.Marshal.ReleaseComObject(xlexcel)
End If
MessageBox.Show("Export Complete")
End Try
End If
End Sub
Lastly, I am guessing you do not need the column headers in the Excel file since an OS select all and copy command is not going to grab the grids column header text.
I hope this makes sense.
Upvotes: 1