Read data from excel and store them in the list. (Vb.net) - excel

I have an excel sheet having 2 columns. Now i want that all values of column 1 should be stored in one list lets say ListTime and all values of column 2 should be stored in another list lets say ListAcceleration. I dont know how to do this.
Thanks in advance.

this is a good way:
Imports Microsoft.Office.Interop
Imports Microsoft.WindowsAPICodePack.Dialogs
Public NotInheritable Class FormMain
Private xlApp As Microsoft.Office.Interop.Excel.Application = New Microsoft.Office.Interop.Excel.Application
Private xlWorkBook As Microsoft.Office.Interop.Excel.Workbook
Private ListTime As New List(Of Double)
Private ListAcceleration As New List(Of Double)
Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
Dim Path As String
Using OFD1 As New CommonOpenFileDialog
OFD1.Title = "Exceldatei auswählen"
OFD1.Filters.Add(New CommonFileDialogFilter("Excel", ".xlsx"))
OFD1.IsFolderPicker = False
OFD1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
If OFD1.ShowDialog = CommonFileDialogResult.Ok Then
Path = OFD1.FileName
Else
Return
End If
End Using
xlWorkBook = xlApp.Workbooks.Open(Path)
Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet = CType(xlWorkBook.Worksheets("Tabelle1"), Microsoft.Office.Interop.Excel.Worksheet)
Dim xlRange As Microsoft.Office.Interop.Excel.Range = xlWorkSheet.UsedRange
Dim ER As Microsoft.Office.Interop.Excel.Range
For rCnt As Integer = 1 To xlRange.Rows.Count Step 1
ER = CType(xlRange.Cells(rCnt, 1), Microsoft.Office.Interop.Excel.Range)
ListTime.Add(CDbl(ER.Value))
ER = CType(xlRange.Cells(rCnt, 2), Microsoft.Office.Interop.Excel.Range)
ListAcceleration.Add(CDbl(ER.Value))
Next
xlWorkBook.Save()
xlWorkBook.Close()
xlApp.Quit()
If xlWorkSheet IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet)
If xlWorkBook IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook)
If xlApp IsNot Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
xlApp = Nothing
xlWorkBook = Nothing
xlWorkSheet = Nothing
End Sub
Private Sub FormMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If xlWorkBook IsNot Nothing Then xlWorkBook.Close()
If xlApp IsNot Nothing Then xlApp.Quit()
End Sub
End Class
There are just a few things you need to consider: First you have to download the “Microsoft.Office.Interop.Excel” package from Visual Studio's own NuGet package manager. Also the package “Microsoft.WindowsAPICodePack.Dialogs” to have a reasonable OpenFileDialog.
In the case of MS Office files, it is important to release the file using System.Runtime.InteropServices.Marshal.ReleaseComObject(..), otherwise you cannot edit it later when you click it on your desktop. In that case you would have to restart the PC. So don't forget. 😉
Oh and by the way: This word – in my case “Tabelle1” – will be named differently in your language. You have to change this.

Related

Export more than 2000 row of data from a data gridview to excel file in vb.net

I did succeed to export data from a DataGridView to excel file by using a loop and writing cell by cell, but the problem is i have more than 2000 rows so the exporting process takes a lot of time.
My question is : Is there anything to change so i can minimize the exportation time ?
Thanks
'exporter
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
xlApp = New Excel.Application
xlBook = xlApp.Workbooks.Open(Filename:=Path.Combine(Application.StartupPath, "EMP_.xlsx"), IgnoreReadOnlyRecommended:=True, ReadOnly:=False, Editable:=True)
xlSheet = xlBook.Worksheets(1)
If DataGridView1.DataSource IsNot Nothing Then
Dim i, j As Integer
For i = 1 To DataGridView1.RowCount - 1
For j = 1 To DataGridView1.ColumnCount
xlSheet.Cells(i + 1, j) = DataGridView1.Rows(i - 1).Cells(j - 1).Value
Next
Next
xlApp.Visible = True
xlApp.UserControl = True
xlApp.Quit()
xlApp = Nothing
Else
MsgBox("Le tableau est vide")
End If
End Sub
Not sure if this is something might be open too. By chance if you could load your DataGridView via setting the DataSource of the DataGridView to a DataTable then the following would be an option.
Using SpreadSheetLight (installed via NuGet) you can use a function like the sample below. Pass in the following, full path and file name, sheet name, the DataTable from the DataGridView e.g. Dim dt As DataTable = CType(DataGridView1.DataSource,DataTable) and the last argument if True included column headers (DataColumn names) or False exclude column names.
SpreadSheetLight home page.
Public Sub SimpleExportRaw(
pFileName As String,
pSheetName As String,
pDataTable As DataTable,
pColumnHeaders As Boolean)
Using doc As New SLDocument()
doc.SelectWorksheet(pSheetName)
doc.ImportDataTable(1, SLConvert.ToColumnIndex("A"), pDataTable, pColumnHeaders)
doc.SaveAs(pFileName)
End Using
End Sub

Can't properly close Excel application

i am very new to VB.net and i'm trying to proceed step by step with my application.
The application i'm trying to build will collect a series of macros i've written in Excel VBA environment.
Now, the following code pasted below, is the initial part, where basically i try to load a workbook (to be used as Active workbook) and to "unload it".
The issue comes when, after "unloading" the workbook, i try to open the very same workbook in excel.
Excel application return an error that is "Open in read-only". This cannot be accepted, and i need to understand how to unload the workbook and release it from the myAPP.
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Dim workbook As Excel.Workbook
Dim worksheet As Excel.Worksheet
Dim APP As New Excel.Application
Private Sub opn_btn_Click(sender As Object, e As EventArgs) Handles opn_btn.Click
Dim strname As String
Dim cellname As String
With OpenFileDialog1
.InitialDirectory = "E:\Vs_Excel"
.Title = "Open xlsx file"
.ShowDialog()
End With
workbook = APP.Workbooks.Open(OpenFileDialog1.FileName)
worksheet = workbook.Worksheets("sheet1")
cellname = worksheet.Range("A1").Value
strname = OpenFileDialog1.FileName
Me.TextBox1.Text = strname
Me.TextBox2.Text = cellname
Dim lvwReport As View = View.List
With Me.ListView1
.GridLines = True
.View = lvwReport
.CheckBoxes = True
End With
'LoadListView() 'thi sroutine is written but not used yet. Must solve first the problem wioth closing ExcelApplication
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
workbook.Close()
APP.Quit()
Me.TextBox1.Text = ""
Me.TextBox2.Text = ""
ReleaseObject(worksheet)
worksheet = Nothing
ReleaseObject(workbook)
workbook = Nothing
ReleaseObject(APP)
APP = Nothing
End Sub
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
MsgBox("Final Released obj # " & intRel)
Catch ex As Exception
MsgBox("Error releasing object" & ex.ToString)
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End class

How to add multiple sheets to an Excel workbook and save it (infinite loading)

I want to add multiple empty sheets to a existing workbook, the langage is VB.net and the code is launched on a local server
The complete code :
Dim objApp As Excel.Application
Dim objBook As Excel._Workbook
Dim objBooks As Excel.Workbooks
objApp = New Excel.Application()
objApp.Visible = True
objBooks = objApp.Workbooks
objBook = objApp.Workbooks.Open(MyPath)
For i As Integer = 1 To 10
objBook.Sheets.Add()
Next
objBook.Save()
objBook.Close()
objApp.Quit()
When the code is executed, the xls file is saved but no sheets have been added.
And i have infinite loading with my localhost
Thanks for your help.
Your code works fine .....
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Dim objApp As Excel.Application
Dim objBook As Excel._Workbook
Dim objBooks As Excel.Workbooks
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
objApp = New Excel.Application()
objApp.Visible = True
objBooks = objApp.Workbooks
objBook = objApp.Workbooks.Open("\\PC1\1.xlsx")
For i As Integer = 1 To 10
objBook.Sheets.Add()
Next
objBook.Save()
objBook.Close()
objApp.Quit()
End Sub
End Class
Just make the executable and then run it in the mode
Run as administrator
By pressing the right click program and then clicking on Run as administrator

VB.NET: Excel Crashes when Updating Data in a Word Chart

Update: Releasing objects has no effect on Excel crashing. The problematic line is:
Dim wChartData = wChart.ChartData
I have written a VB.Net application that opens a word document, iterates through the inline shapes, and updates each chart with data from the database. Sometimes Excel will crash when opening the sheet containing the chart data. Can anyone tell me how I fix this?
Here is the code that iterates through the shapes:
wApp = New Word.Application
wApp.Visible = True
wDoc = wApp.Documents.Add("Some_File_Name.docx")
Console.WriteLine("Updating Charts")
Dim chartName As String
For Each wShape As Word.InlineShape In wDoc.InlineShapes
If wShape.HasChart = Core.MsoTriState.msoTrue Then
If wShape.Chart.HasTitle Then
chartName = wShape.Chart.ChartTitle.Text
Else
chartName = "NO_TITLE"
End If
UpdateChart(wShape.Chart, reportID, reportTitle,
reportUser, curriculumYear, chartName)
End If
Next
The UpdateChart subroutine grabs a SQL query and some options related to the chart, then fires off the FillChartData subroutine below:
Public Sub FillChartData(ByRef wChart As Word.Chart, ByVal sql As String,
Optional ByVal addDataPointsToLabels As Boolean = False)
If sql = "" Then Exit Sub
Dim cmd = O.factory.CreateCommand()
cmd.CommandText = sql
cmd.Connection = O.con
O.factory.CreateDataAdapter()
Dim adapter = O.factory.CreateDataAdapter
adapter.SelectCommand = cmd
Dim dt As New System.Data.DataTable()
Dim ds As New System.Data.DataSet()
adapter.Fill(ds, "report_name")
dt = ds.Tables(0)
Dim wChartData = wChart.ChartData
Dim wChartWb As Excel.Workbook = wChartData.Workbook
Dim wChartSheet As Excel.Worksheet = wChartWb.Sheets(1)
Dim title As String = "No title"
If wChart.HasTitle Then title = wChart.ChartTitle.Text.ToString
Dim r As Excel.Range
r = wChartSheet.Range("A1")
r.CurrentRegion.Clear()
For i = 0 To dt.Columns.Count - 1
Dim c As System.Data.DataColumn = dt.Columns(i)
r.Offset(0, i).Value2 = c.ColumnName
Next
r = wChartSheet.Range("A2")
For Each row As System.Data.DataRow In dt.Rows
For i = 0 To row.ItemArray.Count - 1
r.Offset(0, i).Value2 = row.Item(i)
Next
r = r.Offset(1)
Next
r = wChartSheet.Range("A1")
If addDataPointsToLabels Then
While r.Value <> ""
r.Value &= " " & r.Offset(1).Value
r = r.Offset(0, 1)
End While
End If
wChartWb.Close()
releaseObject(r)
releaseObject(wChartSheet)
releaseObject(wChartWb)
releaseObject(wChartData)
r = Nothing
wChartSheet = Nothing
wChartWb = Nothing
wChartData = Nothing
GC.Collect()
End Sub
The releaseObject subroutine is as follows:
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
MessageBox.Show(ex.ToString)
obj = Nothing
End Try
End Sub
And here's the crash report:
Problem signature:
Problem Event Name: APPCRASH
Application Name: EXCEL.EXE
Application Version: 15.0.5007.1000
Application Timestamp: 5a5eb36d
Fault Module Name: EXCEL.EXE
Fault Module Version: 15.0.5007.1000
Fault Module Timestamp: 5a5eb36d
Exception Code: c0000005
Exception Offset: 002b71c8
OS Version: 6.1.7601.2.1.0.256.4
Locale ID: 1033
Additional information about the problem:
LCID: 1033
skulcid: 1033
Read our privacy statement online:
http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409
If the online privacy statement is not available, please read our privacy statement offline:
C:\Windows\system32\en-US\erofflps.txt
Thanks for your help!
You need to Activate the Word ChartData object to begin the inter-process communication between Word and Excel.
The example below is a simplified demonstration of code pattern and contains no error handling. This example also demonstrates releasing out of scope COM objects via the garbage collector. See this answer for more discussion on this COM clean-up procedure.
This code was verified against Office 2007.
Imports System.Runtime.InteropServices
Imports Excel = Microsoft.Office.Interop.Excel
Imports Word = Microsoft.Office.Interop.Word
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
InterOpWork("Embedded Excel Chart.docx")
COMCleanup()
End Sub
Sub InterOpWork(filePath As String)
Dim appWord As New Word.Application
Dim doc As Word.Document = appWord.Documents.Open((filePath))
Dim shp As Word.InlineShape = doc.InlineShapes(1)
Dim ch As Word.Chart = shp.Chart
Dim chData As Word.ChartData = ch.ChartData
chData.Activate() ' **** This is what your code is missing
Dim wb As Excel.Workbook = DirectCast(chData.Workbook, Excel.Workbook)
Dim appExcel As Excel.Application = DirectCast(wb.Application, Excel.Application)
Dim ws As Excel.Worksheet = DirectCast(wb.Worksheets("Sheet1"), Excel.Worksheet)
Dim rng As Excel.Range = ws.Range("B2:B4")
Dim dataToChange As Object(,) = DirectCast(rng.Value2, Object(,))
For i As Int32 = dataToChange.GetLowerBound(0) To dataToChange.GetUpperBound(0)
dataToChange(i, 1) = i * 2 + (5 - i)
Next
rng.Value = dataToChange
wb.Save()
wb.Close(False)
appExcel.Quit()
doc.Save()
doc.Close(False)
appWord.Quit()
End Sub
Private Sub COMCleanup()
Do
GC.Collect()
GC.WaitForPendingFinalizers()
Loop While Marshal.AreComObjectsAvailableForCleanup
End Sub
End Class

Count lines (max) with values

I would like to count the lines that have values. I tried oSheet.Rows.Count but that doesn't work. Any idea about this?
My code is the following:
Dim oExcel As Object
Dim oBook As Object
Dim oSheet As Object
oExcel = CreateObject("Excel.Application")
oBook = oExcel.Workbooks.Add
oSheet = oBook.Worksheets("Sheet")
oSheet.Range("A" & max).Value = "0000111"
oSheet.Range("B1").Value ="Name"
oBook.SaveAs("C:\New folder\excel\" & datenw & ".xlsx")
oExcel.Quit()
As said in the comments, the following code should get you the count of rows that have values based on your Range:
Dim rowCount As Integer = oSheet.UsedRange.Rows.Count()
There is however a slight issue with your code I believe. This probably won't work:
oSheet = oBook.Worksheets("Sheet")
The reason it won't, is because "Sheet" doesn't exist on a new Workbook. "Sheet1" does, so this needs to be changed to:
oSheet = oBook.Worksheets("Sheet1")
'or
oSheet = oBook.Worksheets(1) 'remember Excel collections are one based not zero based
Lastly I would look at the way you are closing Excel as oExcel.Quit() is probably leaving an instance of Excel running. Have a look at this answer which links to Siddharth Rout's bit of code:
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
You also to make sure you release in the right order and release everything. This is usually in backwards order:
ReleaseObject(oSheet)
oBook.Close()
ReleaseObject(oBook)
oExcel.Quit()
ReleaseObject(oExcel)
However with all that said I would look at using the Microsoft.Office.Interop.Excel namespace directly rather than declaring objects:
Imports Microsoft.Office.Interop
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim oExcel As New Excel.Application
Dim oWorkbooks As Excel.Workbooks = oExcel.Workbooks
Dim oWorkbook As Excel.Workbook = oWorkbooks.Add()
Dim oSheets As Excel.Sheets = CType(oWorkbook.Sheets, Excel.Sheets)
Dim oWorksheet As Excel.Worksheet = CType(oSheets(1), Excel.Worksheet)
Dim oARange As Excel.Range = oWorksheet.Range("A" & max.ToString()) 'Not sure what max is but I took the assumption it's an Integer
oARange.Value = "0000111"
Dim oBRange As Excel.Range = oWorksheet.Range("B1")
oBRange.Value = "Name"
Dim oUsedRange As Excel.Range = oWorksheet.UsedRange()
Dim rowCount As Integer = oUsedRange.Rows.Count()
oWorkbook.SaveAs("C:\Test.xlsx")
ReleaseObject(oUsedRange)
ReleaseObject(oBRange)
ReleaseObject(oARange)
ReleaseObject(oWorksheet)
ReleaseObject(oSheets)
oWorkbook.Close()
ReleaseObject(oWorkbook)
ReleaseObject(oWorkbooks)
oExcel.Quit()
ReleaseObject(oExcel)
End Sub
Private Sub ReleaseObject(ByVal obj As Object)
Try
Dim intRel As Integer = 0
Do
intRel = System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
Loop While intRel > 0
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
I would also then look at turning Option Strict On:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
Define a row variable as Long, then start a loop which will end when it finds a blank value in column A:
Dim lRow as Long = 1
Do until oSheet.Range("A" & lRow).Value=""
' increment the loop variable
lRow+=1
Loop
' display the result in a message block
MsgBox(lRow-1)

Resources