VB.Net - Select an Excel Worksheet, after using a Browse button - vb.net

I have a Browse button code, that when I browse to an Excel file, I then want to be able to select a particular worksheet for that file manually so I can then import that particular sheet into a Datagridview.
I am trying to use either a combobox or a listbox.
My plans are to use the Browse button to populate a Textbox, then via that textbox, select a worksheet, then import it to a Datagridview for review, before exporting it to a SQL Database table.
I have to code for the browse button, I can import the file to a dataviewgrid,and export it to SQL. But only if the Excel file has a Single "predefined" worksheet name.
I need the worksheet selectable after the browse but before the Datagridview import.
This is my Browse Button Code.I am guessing its to simplistic for the takes and must load the file first.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim fd As OpenFileDialog = New OpenFileDialog()
Dim strFileName As String
fd.Title = "Open File Dialog"
fd.InitialDirectory = "H:\COST ACCTG\Inventory\"
fd.Filter = "All files (*.*)|*.*|All files (*.*)|*.*"
fd.FilterIndex = 2
fd.RestoreDirectory = True
If fd.ShowDialog() = DialogResult.OK Then
strFileName = fd.FileName
End If
TextBox1.Text = strFileName
End Sub

After obtaining the path of the Excel spreadsheet you can set up a connection string and find out what tables (Sheets) exist and add each table to a combobox for selection:
Dim excelConnectionString as string
Dim mySheets as Datatable
Dim myConnection as OleDB.OleDBConnection
Try
excelConnectionString = "Provider = Microsoft.ACE.OLEDB.12.0;Data Source=" & _
excelPath & "; Extended Properties = ""Excel 12.0 Xml;HDR=Yes;IMEX=1"""
myConnection = New OleDBConnection(excelConnectionString)
myConnection.Open()
mySheets = myConnection.GetOleDbSchemaTable(OleDB.OleDbSchemaGuid.Tables, Nothing)
For Each row as DataRow in mySheets.Rows
ComboboxExcelSheetsToImport.Items.Add(row("TABLE_NAME")
Next row
Catch ex as Exception
'Exception Handling
End Try
Once the desired table (Sheet) is selected you can use an SQL statement that includes the selected Excel Sheet to bring in the data. Bad example below:
myCommand = new OleDb.OleDbCommand("SELECT * FROM [" & selectedSheet & "]", myConnection)

Related

Excel to DataGridView with OleDbConnection using two DataAdapter

1- Create C:\Book1.xlsx file into C disk.
2- Ensure that you have one sheet in the C:\Book1.xlsx file named Sheet1.
3- Fill Sheet1 cells from A1 cell to E20 cell with some data.
4- Close C:\Book1.xlsx file.
5- Put one DataGridView into the Form1 and named it as DataGridView1.
6- Run code in order to see if you are able to get excel data to DataGridView correctly.
As you can see I have used two OleDbDataAdapters in order to get excel data to DataGridView.
I have prefer to use two OleDbDataAdapters because I come across out of memory exception if excel data is so big.
If you examine my code you will see that myDataAdapter1 gets excel data from A1 cell to E10 cell.
and myDataAdapter2 supposed to get excel data from A11 cell to E20 cell.
If you examine my code you will see that I tried to merge two DataTables and bind to DataGridView1.DataSource with no success.
Please correct my codes and show me how to merge two DataTables and bind to DataGridView1.DataSource?
I want to get excel data from A1 cell to E20 cell and put the DataGridView1 by using two DataAdapters and two DataTables.
If I use one data adapter then my app crashes with big data.
So I try to use two data adapters and two data tables.
The grid must first add columns to accomadate the data. Then add the rows in a While loop. I only have 3 columns in the test data from Excel.
Private Sub PrepareGrid()
DataGridView1.Columns.Add("col1", "Column 1")
DataGridView1.Columns.Add("col2", "Column 2")
DataGridView1.Columns.Add("col3", "Column 3")
End Sub
Private Sub FillFromExcel()
Dim FileName As String = "Book1.xlsx" '"C:\Book1.xlsx"
Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" & FileName & ";" & "Extended Properties=""Excel 12.0 Xml;HDR=NO;IMEX=1"";")
Using cmd As New OleDbCommand("SELECT * FROM [Sheet1$];", cn)
cn.Open()
Using reader = cmd.ExecuteReader
While reader.Read
DataGridView1.Rows.Add(reader(0), reader(1), reader(2))
End While
End Using
End Using
End Using
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PrepareGrid()
FillFromExcel()
End Sub
DataTable.Merge cannot work without a Primary Key. I fooled around with DataTable.Load(IDataReader) but that must use Merge underneath. So, you can either add a Primary Key to the Excel worksheet (just sort of a row number column) and set the appropriate properties in code or manually loop through the second DataTable adding the records to the grid. (slow)
Here is a slightly different method of filling the grid with all the data. I don't have a large Excel worksheet to test. It might address the memory problems but I am afraid it will use the same methods underneath.
Private Sub FillFromExcel()
Dim FileName As String = "Book1.xlsx" '"C:\Book1.xlsx"
Dim dt As New DataTable
Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" & FILENAME & ";" & "Extended Properties=""Excel 12.0 Xml;HDR=NO;IMEX=1"";")
Using cmd As New OleDbCommand("SELECT * FROM [Sheet1$];", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dt
End Sub
You can go from an Excel file to a DGV, like this.
Imports System.Data.SqlClient
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim MyConnection As System.Data.OleDb.OleDbConnection
Dim DtSet As System.Data.DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
MyConnection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='c:\vb.net-informations.xls';Extended Properties=Excel 8.0;")
MyCommand = New System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", MyConnection)
MyCommand.TableMappings.Add("Table", "Net-informations.com")
DtSet = New System.Data.DataSet
MyCommand.Fill(DtSet)
DataGridView1.DataSource = DtSet.Tables(0)
MyConnection.Close()
End Sub
End Class

Update From DataGridView to Database

Dim sb As New MySqlConnectionStringBuilder
sb.Server = Form1.hostname.Text
sb.UserID = Form1.rootuser.Text
sb.Password = Form1.rootpassword.Text
sb.Database = Form1.hostdb.Text
sb.Port = Form1.hostport.Text
Using connection As New MySqlConnection(sb.ConnectionString)
Try
connection.Open()
Dim adapter1 As New MySqlDataAdapter(TextBox1.Text, connection)
Dim cmdb1 = New MySqlCommandBuilder(adapter1)
Dim ds As New DataSet
Dim words As String() = TextBox1.Text.Split(New Char() {" "c})
Dim tablenamewords = (words(3))
adapter1.Update(ds, tablenamewords)
Catch ex As MySqlException
MessageBox.Show(ex.Message)
Finally
connection.Dispose()
End Try
End Using
It's giving me this error:
Update unable to find TableMapping['creature_template'] or DataTable 'creature_template'.
I want to select items then use a DataGrid to update them.
Note: tablenamewords = "creature_template"
You can solve this in alot of different methods.
I prefer to update the DB with a single query every time the the user ends editing a cell.
BUT FIRST you have to bind a source to your DataGridView!
How to bind a source:
Go to your application design an click on your DataGridView
Click on the pause/start like little button as shown:
Click on the "ComboBox" like textbox labeled as "chose data source" as shown and click on it:
It will open a "form", click on the Add data source as shown:
Follow the wizard, you can do it without any furhter explanation!
Well done, you almost completed it. Just go in your code, and look for this sub:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.your_table_nameTableAdapter.Fill(Me.your_db_nameDataSet.your_table_name)
End Sub
The line inside your Form1_Load Sub will upload the data inside your DataGridView, leave it there if you want it to load with the form or cut/paste it wherever you like.
Now you can add this the code to programmatically update the DB:
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
Try
Dim location As Point = DataGridView1.CurrentCellAddress
Dim sqlCmd As String = "UPDATE table_name SET " & _
DataGridView1.Columns(location.X).Name.Replace("DataGridViewTextBoxColumn", "") & " = #Data " & _
"WHERE " & _
DataGridView1.Columns(0).Name.Replace("DataGridViewTextBoxColumn", "") & " = #ID"
Using myConn As New SqlConnection(My.Settings.VISURE_DA_PDFConnectionString)
myConn.Open()
Using myCmd As New SqlCommand(sqlCmd, myConn)
myCmd.Parameters.Add("#Data", SqlDbType.VarChar)
myCmd.Parameters.Add("#ID", SqlDbType.Int)
myCmd.Parameters("#Data").Value = DataGridView1.Rows(location.Y).Cells(location.X).Value
myCmd.Parameters("#ID").Value = DataGridView1.Rows(0).Cells(location.X).Value
myCmd.ExecuteNonQuery()
End Using
myConn.Close()
End Using
Catch ex As Exception
Err.Clear()
End Try
End Sub
Remarks:
location.X is the col index, location.Y is the row index
DataGridView1.Columns(0).Name This is my ID (primary key) and it is always in the first column. Change it with yours.
Don't forget to add .Replace("DataGridViewTextBoxColumn", "") whan you are getting your column name
As previously said, this code will update your DB every time the user edits one cell on your DataGridView updating only the edited cell. This is not a big issue because if you want to edit two ore more cell, every time you leave an edited cell the method DataGridView1_CellEndEdit is fired!

closing mdi child form causes System.ObjectDisposedException

i created a mdi database application. One child form has a datagridview. when clicking on a button on that form a new form opens with a pdfviewer(AxAcroPDF1) on it. This form shows a pdf document stored in the sql server database.
closing this form is done by Me.Close(). It closes it, but when i do it several times, opening that form and closing it, then at one point i get a
System.ObjectDisposedException which says Cannot access a disposed object and it isn't caught either in the try catch block.
It also says The application is in break mode. Your app has entered a break state, but there is no code to show because all threads where executing external code(typically system or framwork code)
Never experienced this kind of problem before.
Here is the code to launch the form with the pdf viewer
Private Sub btnShowDocument_Click(sender As Object, e As EventArgs) Handles btnShowDocument.Click
frmDocument = New frmShowDocumentatie
rowIndex = dgvData.CurrentRow.Index
FileName = dgvData.Item(6, rowIndex).Value
If FileName = "" Then
MessageBox.Show("Can't open documentation" & vbNewLine & "File doesn't exist", "Database Info", MessageBoxButtons.OK, MessageBoxIcon.Information)
Else
frmDocument.Show()
End If
End Sub
And here's the form that opens up then
Imports System.Data.SqlClient
Public Class frmShowDocumentatie
'local variables to get passed the public shared values from
'curent selected row index and document name in datagridview
Private iRow As Integer
Private fName As String
Private Sub frmShowDocumentatie_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'sets the mdi parent
MdiParent = MDIParent1
'sets the text of the form to the filename of pdf bestand
Me.Text = "Document: " & getFilename()
'loads the pdf bestand, need the filepath which is provided by getfilepath function
AxAcroPDF1.src = GetFilePath()
'gets the values from the selected row index and corrsponding filename
iRow = frmDataView.rowIndex
fName = frmDataView.FileName
tsmiDocument.Text = "Document: " & getFilename()
End Sub
'function for getting the filename of selected pdf file in datagridview
Public Function getFilename() As String
fName = frmDataView.FileName
getFilename = fName
End Function
'gets the file path of selected pdf bestand
Function GetFilePath() As String
'Dim i As Integer = frmVerledenOverzicht.dgvData.CurrentRow.Index
'Dim filename As String = frmVerledenOverzicht.dgvData.Item(6, i).Value
Dim sFilePath As String
Dim buffer As Byte()
Using conn As New SqlConnection("Server=.\SQLEXPRESS;Initial Catalog=AndriesKamminga;Integrated Security=True;Pooling=False")
conn.Open()
Using cmd As New SqlCommand("Select Bestand From dbo.PaVerledenOverzicht WHERE Documentatie =" & "'" & getFilename() & "';", conn)
buffer = cmd.ExecuteScalar()
End Using
conn.Close()
End Using
sFilePath = System.IO.Path.GetTempFileName()
System.IO.File.Move(sFilePath, System.IO.Path.ChangeExtension(sFilePath, ".pdf"))
sFilePath = System.IO.Path.ChangeExtension(sFilePath, ".pdf")
System.IO.File.WriteAllBytes(sFilePath, buffer)
'returns the file path needed for AxAcroPDF1
GetFilePath = sFilePath
End Function
Private Sub tsmiSluiten_Click(sender As Object, e As EventArgs) Handles tsmiSluiten.Click
Try
Me.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Database Info", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
End Class
anyone knows what's causing this exception and why is the program crashing instead of being caught in the try catch block
Am using visual studio community edition 2017

select multiple files and load the file names to "Checked List Box"

I need to: open the file dialog box when a button clicked, and then I'll select multiple files, then click ok, then the files will appear on Checkedlistbox1. And I want the dialog box to remember the folder path which I browsed last (so when I click that button again, it will take me to that location). But when I just run "openfiledialog" I can't select multiple files, and when I add further code, the program gives errors. Please shed some light here. :)
Dim fbd As New OpenFileDialog With { _
.Title = "Select multiple files", _
.FileName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)}
If fbd.ShowDialog = DialogResult.OK Then
CheckedListBox1.Items.AddRange(Array.ConvertAll(IO.Directory.GetFiles(fbd.FileNames), Function(f) IO.Path.GetFileName(f)))
End If
I used a List(of String) in my test, you can change it so as to meet your needs.
Dim fbd As New OpenFileDialog With { _
.Title = "Select multiple files", _
.Multiselect = True, _
.FileName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)}
If fbd.ShowDialog = DialogResult.OK Then
CheckedListBox1.AddRange(fbd.FileNames.Select(Function(f) IO.Path.GetFileName(f)))
End If
EDIT
I edited my code so as to use an object. The following is an example. You can use it to create the needed object for CheckBoxList
Public Property CheckedListBox1 As New List(Of TestClass)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim fbd As New OpenFileDialog With { _
.Title = "Select multiple files", _
.Multiselect = True, _
.FileName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)}
If fbd.ShowDialog = DialogResult.OK Then
CheckedListBox1.AddRange(fbd.FileNames.Select(Function(f) New TestClass With {.Name = IO.Path.GetFileName(f)}))
End If
End Sub
Public Class TestClass
Public Property Name As String
End Class
EDIT 2
Dim fbd As New OpenFileDialog With { _
.Title = "Select multiple files", _
.Multiselect = True, _
.FileName = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)}
If fbd.ShowDialog = DialogResult.OK Then
CheckedListBox1.Items.AddRange(fbd.FileNames.Select(Function(f) IO.Path.GetFileName(f)).ToArray)
End If
Use InitialDirectory property and a temporarily global string variable to remember your last open directory.
Dim LastDir As String = ""
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim fbd As New OpenFileDialog
If LastDir = "" Then Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
With fbd
.Title = "Select multiple files" ' Title of your dialog box
.InitialDirectory = LastDir ' Directory appear when you open your dialog.
.Multiselect = True 'allow user to select multiple items (files)
End With
If fbd.ShowDialog() = Windows.Forms.DialogResult.OK Then ' check user click ok or cancel
LastDir = Path.GetDirectoryName(fbd.FileName) 'Update your last Directory.
' do your stuf here i.e add selected files to listbox etc.
For Each mFile As String In fbd.FileNames
CheckedListBox1.Items.Add(mFile, True)
Next
End If
this will remember your last open directory while your program is running/alive.
If you want your dialog box always remember last opened directory store LastDir in your program settings or in computer registry.

Export data from VB to Excel sheet

On VS 2012 I have created a VB.NET calculation application (outputs based on variable inputs), i need to save these input & output data to certain cells in excel sheet,
here is a sample of the code i use:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim xls As Microsoft.Office.Interop.Excel.Application
Dim xlsWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlsWorkSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
xls = New Microsoft.Office.Interop.Excel.Application
xlsWorkBook = xls.Workbooks.Open("D:\bookl.xlsx")
xlsWorkSheet = xlsWorkBook.Sheets("sheet1")
xlsWorkSheet.Cells(1, 1) = TextBox1.Text
xlsWorkBook.Close()
xls.Quit()
End Sub
my problem here is that in every time i click the save button it saves the data to a excel sheet file which i have to specify its path previously.
What i wish to do is if there is any way to load from VB it self then choose where to save it (because iam going to use it in a lot of machines, so i don't want to put the excel file in the same path each time i use the application in any other machine)
Open Excel file from My.Resources location
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim xlsWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlsWorkSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim xls As New Microsoft.Office.Interop.Excel.Application
Dim resourcesFolder = IO.Path.GetFullPath(Application.StartupPath & "\..\..\Resources\")
Dim fileName = "book1.xlsx"
xlsWorkBook = xls.Workbooks.Open(resourcesFolder & fileName)
xlsWorkSheet = xlsWorkBook.Sheets("Sheet1")
xlsWorkSheet.Cells(1, 1) = TextBox1.Text
xlsWorkBook.Close()
xls.Quit()
MsgBox("file saved to " & resourcesFolder)
End Sub
The resource template xlsx file must be copied to the output directory, so edit its properties and choose (actually I'm not super sure you need this...)
Build Action = Content
Copy To Output Directory = Copy Always
P.S. this is just a sample to use with your current code, but I strongly suggest using EPPlus Library if you want to create/save/modify excel files.