I have a report that I need to print after a sale has completed.
I am having issues with the length and printing when using PrintForm and PrintDocument components however if I right click and select Print from the list the report prints perfectly.
Is there any way that I could write code in my form load event that would imitate the right click print?
Ive been struggling with this part of my project for ages now and the whole thing is now way behind schedule.
My Code for the whole Receipt form page is:
Imports System.Data.OleDb
Imports System.IO
Imports System.Drawing.Printing
Public Class Receipt
Public PicLocation As String
Dim Ctrl1, Ctrl2 As Control
Dim CN As New OleDb.OleDbConnection
Dim CMD As New OleDb.OleDbCommand
Dim DataR As OleDb.OleDbDataReader
'To display into datagrid purpose
Dim dataS As New DataSet
Dim dataAd As New OleDb.OleDbDataAdapter
Public SqlStr, SqlStr1, DBPath, DBStatus, SearchBox As String
Dim X, Y, SqlH, Onh As Integer
Dim SqlUser As String
Dim DataP As Decimal
Dim Balance As Integer
Private Sub Receipt_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'ProductListDataSet' table.
DBPath = (Application.StartupPath & "\ProductList.accdb")
If CN.State = ConnectionState.Open Then
CN.Close()
DBStatus = ("Not Connected")
End If
SqlStr = ("Provider = Microsoft.ACE.OLEDB.12.0;Data Source =" & DBPath)
CN.ConnectionString = SqlStr
CN.Open()
Onh = Nothing
lblTime.Text = DateAndTime.Now
lblUser.Text = Login.userTB.Text
Dim sql As String
sql = "SELECT * Receipt"
Me.ReceiptTableAdapter.ClearBeforeFill = True
Me.ReceiptTableAdapter.Connection = CN
Me.ReceiptTableAdapter.Connection.CreateCommand.CommandText = sql
Me.ReceiptTableAdapter.Fill(Me.ProductListDataSet.Receipt)
Me.ReportViewer1.RefreshReport()
Me.Refresh()
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
With Me.PrintForm1
.PrintAction = Printing.PrintAction.PrintToPrinter
Dim MyMargins As New Margins
With MyMargins
.Left = 0
.Right = 0
.Top = 0
.Bottom = 0
End With
.PrinterSettings.DefaultPageSettings.Margins = MyMargins
.Print(Me, PowerPacks.Printing.PrintForm.PrintOption.CompatibleModeClientAreaOnly)
End With
End Sub
End Class
Related
I have linked an Access database to my program. It populates the DataGridView as it is intended to so that part of the program works. However the new data that i add to my DataGridView wont show up and I don't know what is wrong with my code.
Can anyone see anything wrong or something I've missed out that would cause the code not to function as desired? Thank you in advance :)
Imports System.Data.OleDb
Public Class Form1
Dim j As OleDbConnection
Dim a As OleDbDataAdapter
Dim s As DataSet
Dim lokasidb As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Call jaringan()
a = New OleDbDataAdapter("Select * From datadairy", j)
s = New DataSet
s.Clear()
a.Fill(s, "datadairy")
DataGridDairy.DataSource = (s.Tables("datadairy"))
End Sub
Private Sub eksekusiSql(ByVal Sql As String)
Dim objcmd As New System.Data.OleDb.OleDbCommand
Call jaringan()
Try
objcmd.Connection = j
objcmd.CommandType = CommandType.Text
objcmd.CommandText = Sql
objcmd.ExecuteNonQuery()
objcmd.Dispose()
MsgBox("The new data successfully saved", vbInformation)
Catch ex As Exception
MsgBox("The new data is failed to save", vbInformation)
End Try
End Sub
Sub jaringan()
lokasidb = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\19106060045_Tugas Modul 5.accdb"
j = New OleDbConnection(lokasidb)
If j.State = ConnectionState.Closed Then j.Open()
End Sub
Private Sub ButtonAdd_Click(sender As Object, e As EventArgs) Handles ButtonAdd.Click
Dim No As String = TextNo.Text
Dim Jenis_Susu_Sapi As String = TextSusu.Text
Dim Jenis_Olahan As String = TextOlahan.Text
Dim Harga_per_kg As String = TextHarga.Text
Dim Tempat_Penjualan As String = TextPasar.Text
Dim Sql_Simpan_Dairy As String = "Insert into datadairy (No, Jenis_Susu_Sapi, Jenis_Olahan, Harga_per_kg, Tempat_Penjualan) values (" + No + ",'" + Jenis_Susu_Sapi + "','" + Jenis_Olahan + "','" + Harga_per_kg + "','" + Tempat_Penjualan + "')"
eksekusiSql(Sql_Simpan_Dairy)
ShowDairydata()
End Sub
Public Sub ShowDairydata()
Call jaringan()
a = New OleDbDataAdapter("Select * from datadairy", j)
s = New DataSet
s.Clear()
a.Fill(s, "datadairy")
DataGridDairy.DataSource = (s.Tables("datadairy"))
End Sub
After adding new data to your database, just use
'DataGridDairy.Databind()'
to refresh.
I am having an issue with filling a DataGridView from an Excel file that is online. On button click, the app should create a new tab, add a DataGridView and populate with values from the Excel file. How can I do it?
Here is what I did so far:
Public Class Form1
Dim tempTabExist = False
Private Sub SiteList_Click(sender As Object, e As EventArgs) Handles SiteList.Click
Dim xlApp As Excel.Application
Dim wkbTemplRaspored As Excel.Workbook
Dim xlWorkSheet As Excel.Worksheet
If tempTabExist = False Then
Call CreateNewTabPage()
End If
xlApp = New Excel.Application
xlApp.Visible = True
wkbTemplRaspored = xlApp.Workbooks.Open("http://CRNO/RAN/Raspored%20R%20A%20N_v1.xlsx")
xlWorkSheet = wkbTemplRaspored.Worksheets("Sheet1")
End Sub
Private Sub CreateNewTabPage()
Dim tp As New TabPage
tempTabExist = True
tp.Name = "SiteList"
tp.Text = "SiteList"
Call CreateNewGrid(tp)
Me.TabControl.TabPages.Add(tp)
End Sub
Private Sub CreateNewGrid(ByRef TP As TabPage)
Dim dg As New DataGridView
dg.Dock = DockStyle.Fill
dg.Name = "Raspored"
dg.Columns.Add(dg.Name, "Site Name")
dg.Columns.Add(dg.Name, "Technology")
dg.Columns.Add(dg.Name, "Week")
dg.Columns.Add(dg.Name, "Engineer")
TP.Controls.Add(dg)
End Sub
End Class
Most of your code seems to be working. I would change a few things however apart from listing the data in your DataGridView the code does appear to work.
To retrieve data from Excel and view in a DataGridView I would look at the following code:
Using con As New Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\Test.xlsx'; Extended Properties='Excel 12.0;';"),
com As Data.OleDb.OleDbCommand = con.CreateCommand()
con.Open()
Dim dtSheetName As DataTable
dtSheetName = con.GetSchema("Tables")
If dtSheetName.Rows.Count > 0 Then
com.CommandText = "select * from [" & dtSheetName.Rows(0)("TABLE_NAME").ToString() & "]"
com.CommandType = CommandType.Text
dtRows.Load(com.ExecuteReader())
End If
End Using
There are bits of code here you may need to change as I haven't tested with your Data Source. Instead I used my own.
I would look at changing your method CreateNewTabPage slightly to return a TabPage:
Private Function CreateNewTabPage() As TabPage
Dim tp As New TabPage
tp.Name = "SiteList"
tp.Text = "SiteList"
Return tp
End Function
Instead of calling CreateNewGrid from CreateNewTabPage I would do this on your button click. I would however pass through the DataTable as well as the TabPage.
Additionally since we are assigning a DataTable as the DataSource we don't need to add columns manually. Here is what I would do:
Private Sub CreateNewGrid(ByRef TP As TabPage,
ByVal dt As DataTable)
Dim dg As New DataGridView
dg.Dock = DockStyle.Fill
dg.Name = "Raspored"
dg.DataSource = dt
TP.Controls.Add(dg)
End Sub
This is how I would call both methods:
If dtRows.Rows.Count > 0 Then
Dim tabPage As TabPage = CreateNewTabPage()
If tabPage IsNot Nothing Then
If TabControl1.TabPages.ContainsKey(tabPage.Name) Then
TabControl1.TabPages.RemoveByKey(tabPage.Name)
End If
CreateNewGrid(tabPage, dtRows)
TabControl1.TabPages.Add(tabPage)
End If
End If
Notice that I check for the tab and should it exist, I remove it. You may want to do something similar.
All together your code would look something like this:
Private Sub SiteList_Click(sender As Object, e As EventArgs) Handles SiteList.Click
Dim dtRows As New DataTable
Using con As New Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='http://CRNO/RAN/Raspored%20R%20A%20N_v1.xlsx'; Extended Properties='Excel 12.0;';"),
com As Data.OleDb.OleDbCommand = con.CreateCommand()
con.Open()
Dim dtSheetName As DataTable
dtSheetName = con.GetSchema("Tables")
If dtSheetName.Rows.Count > 0 Then
com.CommandText = "select * from [" & dtSheetName.Rows(0)("TABLE_NAME").ToString() & "]"
com.CommandType = CommandType.Text
dtRows.Load(com.ExecuteReader())
End If
End Using
If dtRows.Rows.Count > 0 Then
Dim tabPage As TabPage = CreateNewTabPage()
If tabPage IsNot Nothing Then
If TabControl1.TabPages.ContainsKey(tabPage.Name) Then
TabControl1.TabPages.RemoveByKey(tabPage.Name)
End If
CreateNewGrid(tabPage, dtRows)
TabControl1.TabPages.Add(tabPage)
End If
End If
End Sub
Private Function CreateNewTabPage() As TabPage
Dim tp As New TabPage
tp.Name = "SiteList"
tp.Text = "SiteList"
Return tp
End Function
Private Sub CreateNewGrid(ByRef TP As TabPage,
ByVal dt As DataTable)
Dim dg As New DataGridView
dg.Dock = DockStyle.Fill
dg.Name = "Raspored"
dg.DataSource = dt
TP.Controls.Add(dg)
End Sub
If you haven't already you may need to download Microsoft Access Database Engine 2010 Redistributable.
There are several ways to do this. Here are two ideas for you to muse over.
Imports System.Data.SqlClient
Imports Microsoft.Office.Interop.Excel
Imports Microsoft.Office.Interop
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:\Users\Excel\Desktop\Book1.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
Also, try this.
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Data.OleDb
'~~> Define your Excel Objects
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim xlApp As New Excel.Application
'Dim xlWorkBook As Excel.Workbook
'Dim xlWorkSheet As Excel.Worksheet
Dim strConn As String
Dim da As OleDbDataAdapter
Dim ds As New DataSet
Dim dao_dbE As dao.DBEngine
Dim dao_DB As DAO.Database
Dim strFirstSheetName As String
dao_dbE = New dao.DBEngine
dao_DB = dao_dbE.OpenDatabase("C:\Users\Excel\Desktop\Coding\DOT.NET\Samples VB\Import into DataGrid from Excel & Export from DataGrid to Excel #2\Book3.xls", False, True, "Excel 8.0;")
strFirstSheetName = dao_DB.TableDefs(0).Name
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Users\Excel\Desktop\Coding\DOT.NET\Samples VB\Import into DataGrid from Excel & Export from DataGrid to Excel #2\Book3.xls;Extended Properties=""Excel 8.0;"""
da = New OleDbDataAdapter("SELECT * FROM [" & _
strFirstSheetName & "]", strConn)
da.TableMappings.Add("Table", "Excel")
da.Fill(ds)
DataGridView1.DataSource = ds.Tables(0).DefaultView
da.Dispose()
dao_DB.Close()
End Sub
End Class
I am having a hard time trying to populate a textbox, and two dropdown lists. What I am attempting to do is this: when the Company dropdownlist has been selected, it will display a grid of its respective values from a sqldatasource, which it does. Now the next step is once a selection from the company dropdown has been made, a textbox will display the membertype as well as the second dropdownlist. The third dropdown displays the groupid. All these three components have their outputs after a selection has been made. But I cannot seem to get the values to show. I also added code for clarification.
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Web.UI.WebControls
Partial Class companydropdown
Inherits System.Web.UI.Page
Private Sub BindDropDownList(DropdownList1 As DropDownList, query As String, text As String, value As String, defaultText As String)
If Not IsPostBack Then
' Read sql server connection string from web.config file
Dim sConstr As String = ConfigurationManager.ConnectionStrings("ds17701ConnectionString").ConnectionString
Dim Conn As New SqlConnection(sConstr)
Dim dt As New DataTable("tbl")
Using Conn
Conn.Open()
Dim comm As New SqlCommand("SELECT CompanyName,CompanyID FROM CompanyList ORDER BY CompanyName", Conn)
Dim da As New SqlDataAdapter(comm)
'da.Fill(dt)
End Using
'DropdownList1.DataSource = dt
DropdownList1.DataTextField = "CompanyName"
DropdownList1.DataValueField = "CompanyID"
DropdownList1.DataBind()
'DropdownList1.Items.Insert(0, New ListItem("--Select--"))
End If
End Sub
Protected Sub Member_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
If DropDownList1.SelectedIndex > 0 Then
Dim sConstr As String = ConfigurationManager.ConnectionStrings("ds17701ConnectionString").ConnectionString
Dim Conn As New SqlConnection(sConstr)
Dim dt As New DataTable("tbl")
Using Conn
Conn.Open()
Dim comm As New SqlCommand("SELECT CompanyName,CompanyID FROM CompanyList " + DropDownList1.SelectedValue & " ORDER BY CompanyName", Conn)
Dim da As New SqlDataAdapter(comm)
da.Fill(dt)
End Using
'DropDownList2.DataSource = dt
DropDownList2.DataTextField = "MembershipStatus"
DropDownList2.DataValueField = "MemberTypeID"
' Bind sql server data into the Dropdown List
DropDownList2.DataBind()
Else
DropDownList2.Items.Clear()
End If
End Sub
Protected Sub Group_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged
If DropDownList1.SelectedIndex > 0 Then
Dim sConstr As String = ConfigurationManager.ConnectionStrings("ds17701ConnectionString").ConnectionString
Dim Conn As New SqlConnection(sConstr)
Dim dt As New DataTable("tbl")
Using Conn
Conn.Open()
Dim comm As New SqlCommand("SELECT CompanyName,CompanyID FROM CompanyList " + DropDownList1.SelectedValue & " ORDER BY CompanyName", Conn)
Dim da As New SqlDataAdapter(comm)
da.Fill(dt)
End Using
'DropDownList2.DataSource = dt
DropDownList3.DataTextField = "GroupID"
DropDownList3.DataValueField = "GroupID"
' Bind sql server data into the Dropdown List
DropDownList3.DataBind()
Else
DropDownList3.Items.Clear()
End If
End Sub
Protected Sub DropDownList1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles DropDownList1.SelectedIndexChanged
DropDownList2.Enabled = False
'DropDownList3.Items.Clear()
DropDownList3.Items.Insert(0, New ListItem("", "0"))
Dim stateId As Integer = Integer.Parse(DropDownList1.SelectedItem.Value)
If stateId > 0 Then
Dim query As String = String.Format("", stateId)
BindDropDownList(DropDownList1, query, "CompanyName", "CompanyId", "")
DropDownList3.Enabled = True
DropDownList2.Enabled = True
End If
End Sub
End Class
I am currently working in windows form applications using vb.net 2013. I have two forms, we can call them form1 and form 2 for now. Form1 has a datagridview with a checkbox column that the end user will click to open form2 as a dialog form. Once form2 opens I want it to automatically load and fill two text boxes that have information from corresponding columns from the original DGV. In short, the DGV on form1 has 3 columns; JobNumber, LineNumber, and the checkbox. The end user will click the checkbox to bring up form2 and I want the Jobnumber and Linenumber to automaticaly fill into two textboxes on form2. Here is my code from form1.
'assembly dialog result form
dr = f.ShowDialog
If dr = Windows.Forms.DialogResult.OK Then
'dim y as job string
Dim Y As String = DataGridOrdered.Rows(e.RowIndex).Cells(3).Value
'open connection
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("UPDATE Production.dbo.tblFCOrdered SET Complete = 1, RackIn = 1 WHERE JobNumber = '" & Y & "'", conn1)
comm1.ExecuteNonQuery()
conn1.Close()
End Using
End Using
Call DGVOrderedRefresh()
ElseIf dr = Windows.Forms.DialogResult.Yes Then
'dim M as job string
Dim M As String = DataGridOrdered.Rows(e.RowIndex).Cells(3).Value
'open connection
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("UPDATE Production.dbo.tblFCOrdered SET Complete = 1, RackIn = 1 WHERE JobNumber = '" & M & "'", conn1)
comm1.ExecuteNonQuery()
conn1.Close()
End Using
End Using
Call DGVOrderedRefresh()
ElseIf dr = Windows.Forms.DialogResult.Cancel Then
'refresh datagridview ordered
Call DGVOrderedRefresh()
End If
ElseIf e.ColumnIndex = 0 Then
'fail safe to make sure the header is not clicked
If e.RowIndex = -1 Then
Exit Sub
End If
The code for my dialog is as follows
Imports System.Data
Imports System.Data.SqlClient
Public Class BuildName
' Dim connstring As String = "DATA SOURCE = BNSigma\CORE; integrated security = true"
Dim connstring As String = "DATA SOURCE = BNSigma\TEST; integrated security = true"
Private Sub Label3_Click(sender As Object, e As EventArgs) Handles Label3.Click
End Sub
Private Sub BuildName_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ds As New DataTable
Try
'load name combo box
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("SELECT Name FROM Production.dbo.FCNames", conn1)
Dim adapater As New SqlDataAdapter
adapater.SelectCommand = comm1
adapater.Fill(ds)
adapater.Dispose()
conn1.Close()
CBName.DataSource = ds
CBName.DisplayMember = "Name"
CBName.ValueMember = "Name"
End Using
End Using
Catch ex As Exception
MsgBox("Error loading name List, please contact a mfg. Engr.!")
MsgBox(ex.ToString)
End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Update built by name
Dim v As Object = TBFloor.Text
Dim G As Object = TBLine.Text
Dim O As Object = TBJobNumber.Text
Try
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("UPDATE Production.dbo.tblFCOrdered SET BuiltBy = #Name Where JobNumber = '" & O & "'", conn1)
comm1.Parameters.AddWithValue("#Name", CBName.Text)
comm1.ExecuteNonQuery()
conn1.Close()
End Using
End Using
Catch ex As Exception
MsgBox("Error updating Ordered table, please contact a MFG. ENGR.!")
MsgBox(ex.ToString)
End Try
End Sub
End Class
UPDATED CODE FOR VALTER
Form1 code
Public row_Index As Integer = 0
Private Sub DataGridOrdered_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles DataGridOrdered.CurrentCellDirtyStateChanged
If DataGridOrdered.IsCurrentCellDirty Then
DataGridOrdered.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
Private Sub DataGridOrdered_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridOrdered.CellValueChanged
If DataGridOrdered.Columns(e.ColumnIndex).Name = 9 Then
Dim checkCell As DataGridViewCheckBoxCell = CType(DataGridOrdered.Rows(e.RowIndex).Cells(9), DataGridViewCheckBoxCell)
If CType(checkCell.Value, [Boolean]) = True Then
row_Index = e.RowIndex
BuildName.ShowDialog(Me)
End If
End If
End Sub
Form 2 code
Private Sub BuildName_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim value1 As Object = FormOrdered.DataGridOrdered.Rows(FormOrdered.row_Index).Cells(3).Value
Dim value2 As Object = FormOrdered.DataGridOrdered.Rows(FormOrdered.row_Index).Cells(4).Value
TBJobNumber.Text = CType(value1, String)
TBFloor.Text = CType(value2, String)
In your form1 add:
Public Row_Index As Integer = 0 //use a simple variable
Sub datagridOrdered_CurrentCellDirtyStateChanged( _
ByVal sender As Object, ByVal e As EventArgs) _
Handles datagridOrdered.CurrentCellDirtyStateChanged
If datagridOrdered.IsCurrentCellDirty Then
datagridOrdered.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If
End Sub
Private Sub datagridOrdered_CellValueChanged(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles datagridOrdered.CellValueChanged
If datagridOrdered.Columns(e.ColumnIndex).Name = "Assemble" Then //<- here
Dim checkCell As DataGridViewCheckBoxCell = _
CType(datagridOrdered.Rows(e.RowIndex).Cells(2), _ //<- here
DataGridViewCheckBoxCell)
If CType(checkCell.Value, [Boolean]) = True Then
//RowIndex = e.RowIndex you dont need this
Row_Index = e.RowIndex
BuildName.ShowDialog(Me)
End If
End If
End Sub
//Nor this
//Private _count As Integer
//Public Property RowIndex() As Integer
//Get
//Return _count
//End Get
//Set(value As Integer)
//_count = value
//End Set
//End Property
And in dialog load event use Form1.Row_Index instead:
Private Sub BuildName_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim value1 As Object = FormOrdered.datagridOrdered.Rows(Form1.Row_Index).Cells(0).Value //<- here
Dim value2 As Object = FormOrdered.datagridOrdered.Rows(Form1.Row_Index).Cells(1).Value //<- here
TBJobNumber.Text = CType(value1, String)
TBFloor.Text = CType(value2, String)
...
...
End Sub
or add a module and add the Row_Index there. You can use it then as is
Private Sub BuildName_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim value1 As Object = FormOrdered.DataGridView1.Rows(Row_Index).Cells(0).Value
Dim value2 As Object = FormOrdered.DataGridView1.Rows(Row_Index).Cells(1).Value
TBJobNumber.Text = CType(value1, String)
TBFloor.Text = CType(value2, String)
...
...
End Sub
My program is able to retrieve data from an excel macro 2010 workbook and change contents and save changes made, all using the datagridview within VB.NET. However I'm facing a problem where the program saves but will not close. When I look at the processes in the task manager its still showing Excel 2010 as running. If anyone can help me find a way to quit this application I would greatly appreciate it!
Imports System.Data.OleDb
Imports Microsoft.Office.Interop.Excel
Imports Microsoft.Office.Interop
Imports System.IO
Public Class Form1
Dim SheetList As New ArrayList
Private excelObj As ExcelObject
Private dt As DataTable = Nothing
Dim DS As DataSet
Dim DS2 As DataSet
Dim ds3 As DataSet
Dim ds4 As DataSet
Dim ds5 As DataSet
Dim ds6 As DataSet
Dim ds7 As DataSet
Dim ds8 As DataSet
Dim ds9 As DataSet
Dim ds10 As DataSet
Dim ds11 As DataSet
Dim ds12 As DataSet
Dim ds13 As DataSet
Dim ds14 As DataSet
Dim ds15 As DataSet
Dim ds16 As DataSet
Dim ds17 As DataSet
Dim ds18 As DataSet
Dim MyCommand As OleDb.OleDbDataAdapter
Dim MyCommand2 As OleDb.OleDbDataAdapter
Dim MyCommand3 As OleDb.OleDbDataAdapter
Dim MyCommand4 As OleDb.OleDbDataAdapter
Dim MyCommand5 As OleDb.OleDbDataAdapter
Dim MyCommand6 As OleDb.OleDbDataAdapter
Dim MyCommand7 As OleDb.OleDbDataAdapter
Dim MyCommand8 As OleDb.OleDbDataAdapter
Dim MyCommand9 As OleDb.OleDbDataAdapter
Dim MyCommand10 As OleDb.OleDbDataAdapter
Dim MyCommand11 As OleDb.OleDbDataAdapter
Dim MyCommand12 As OleDb.OleDbDataAdapter
Dim MyCommand13 As OleDb.OleDbDataAdapter
Dim MyCommand14 As OleDb.OleDbDataAdapter
Dim MyCommand15 As OleDb.OleDbDataAdapter
Dim MyCommand16 As OleDb.OleDbDataAdapter
Dim MyCommand17 As OleDb.OleDbDataAdapter
Dim MyCommand18 As OleDb.OleDbDataAdapter
Dim objExcel As New Excel.Application()
Dim objWorkBook As Excel.Workbook = objExcel.Workbooks.Add
Dim objWorkSheet1 As Excel.Worksheet = objExcel.ActiveSheet
Dim objWorkSheet2 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet3 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet10 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet11 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet12 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet13 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet23 As Excel.Worksheet = objExcel.ActiveSheet
Dim objworksheet24 As Excel.Worksheet = objExcel.ActiveSheet
'<TBD make 15 more of these>
Dim MyConnection As OleDb.OleDbConnection
Dim MYDBConnection As DAO.Connection
Public MyWorkspace As DAO.Workspace
Public sizetable As DAO.Recordset
Public MyDatabase As DAO.Database
Public ReadOnly Property Excel() As ExcelObject
Get
If excelObj Is Nothing Then
excelObj = New ExcelObject(txtFilePath.Text)
End If
Return excelObj
End Get
End Property
Sub openExcelfile()
Dim dlg As New OpenFileDialog()
dlg.Filter = "Excel Macro Enabled Files|*.xlsm*|Excel Files|*.xls|Excel 2007 Files|*.xlsx|All Files|*.*"
If dlg.ShowDialog() = DialogResult.OK Then
excelObj = New ExcelObject(dlg.FileName)
txtFilePath.Text = dlg.FileName
btnRetrieve.Enabled = txtFilePath.Text.Length > 0
End If
Dim ExcelSheetName As String = ""
'open the excel workbook and create an object for it
objExcel = CreateObject("Excel.Application")
'do some exception handling on a blank txtfilepath.text
objWorkBook = objExcel.Workbooks.Open(txtFilePath.Text)
Dim i As Integer
i = 1
For Each objWorkSheets In objWorkBook.Worksheets
SheetList.Add(objWorkSheets.Name)
Select Case i
Case 4
objWorkSheet1 = objExcel.Worksheets(objWorkSheets.Name)
Case 5
objWorkSheet2 = objExcel.Worksheets(objWorkSheets.Name)
'ListBox1.Items.Add(objWorkSheets.Name)
'etc
End Select
i = i + 1
Next
End Sub
Sub Write2Excel()
Dim rowindex As Integer
Dim columnindex As Integer
For rowindex = 1 To DataGridView1.RowCount
For columnindex = 1 To DataGridView1.ColumnCount
objWorkSheet1.Cells(rowindex + 4, columnindex + 0) = DataGridView1(columnindex - 1, rowindex - 1).Value
Next
Next
'etc
End Sub
Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
openExcelfile()
End Sub
Sub oldretrieve()
' Dim dt As DataTable = Me.Excel.GetSchema()
' cmbTableName.DataSource = (From dr In dt.AsEnumerable() Where Not dr("TABLE_NAME").ToString().EndsWith("$") Select dr("TABLE_NAME")).ToList()
' cmbTableName.Enabled = cmbTableName.Items.Count > 0
' btnGo.Enabled = cmbTableName.Items.Count > 0
' btnDrop.Enabled = cmbTableName.Items.Count > 0
End Sub
Sub RetrieveExcel()
'Create a connection to either 2007 and 2010 xls file
Dim fi As New FileInfo(txtFilePath.Text)
If fi.Extension.Equals(".xls") Then
MyConnection = New OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.8.0; " & "data source=" & txtFilePath.Text & "; " & "Extended Properties=Excel 8.0;")
ElseIf fi.Extension.Equals(".xlsx") Then
MyConnection = New OleDb.OleDbConnection( _
"provider=Microsoft.Ace.OLEDB.12.0; " & _
"data source=" & txtFilePath.Text & "; " & "Extended Properties=Excel 12.0;")
ElseIf fi.Extension.Equals(".xlsm") Then
MyConnection = New OleDb.OleDbConnection( _
"provider=Microsoft.Ace.OLEDB.12.0; " & _
"data source=" & txtFilePath.Text & "; " & "Extended Properties=Excel 12.0;")
End If
'First worksheet'
MyCommand = New OleDbDataAdapter("select * from [1- COTS Worksheet$A4:I150]", MyConnection)
'1- COTS Worksheet.Column(1).Locked = True
DS = New System.Data.DataSet()
MyCommand.Fill(DS)
'---This will prevent the user from editing the size of the rows and columns of the datagrid---'
DataGridView1.AllowUserToResizeColumns = False
DataGridView1.AllowUserToResizeRows = False
DataGridView1.AllowUserToOrderColumns = False
DataGridView1.AllowUserToAddRows = False
DataGridView1.AllowUserToDeleteRows = False
DataGridView1.DataSource = DS.Tables(0).DefaultView
'---The following line makes the column read only---'
DataGridView1.Columns(5).ReadOnly = True
DataGridView1.Columns(6).ReadOnly = True
'''''''if the column is editible then the foreground = blue ''''''''
DataGridView1.Columns(0).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(1).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(2).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(3).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(4).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(7).DefaultCellStyle.ForeColor = Color.Blue
DataGridView1.Columns(8).DefaultCellStyle.ForeColor = Color.Blue
' ''''''This will get rid of the selection blue color for the cells''''''''''''''''''''
DataGridView1.DefaultCellStyle.SelectionBackColor = DataGridView1.DefaultCellStyle.BackColor
DataGridView1.DefaultCellStyle.SelectionForeColor = DataGridView1.DefaultCellStyle.ForeColor
'TABLE TO WRITE TO -
'FIELD TO WRITE TO -
End Sub
Private Sub btnRetrieve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRetrieve.Click
Try
Cursor.Current = Cursors.WaitCursor
RetrieveExcel()
Finally
Cursor.Current = Cursors.Default
End Try
End Sub
Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles Me.Activated
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' btnRetrieve.Enabled = True
MyWorkspace = DAODBEngine_definst.Workspaces(0)
End Sub
Private Sub txtFilePath_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtFilePath.TextChanged
btnRetrieve.Enabled = System.IO.File.Exists(txtFilePath.Text)
End Sub
Private Sub Form1_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed
If Me.excelObj IsNot Nothing Then
Me.excelObj.Dispose()
End If
closexlsfile()
End Sub
Private Sub DBFilePath_TextChanged(sender As Object, e As EventArgs) Handles DBFilePath.TextChanged
End Sub
Private Sub BtnBrowseDB_Click(sender As Object, e As EventArgs) Handles BtnBrowseDB.Click
opendbfile()
End Sub
Function opendbfile() As Boolean
Dim dlg As New OpenFileDialog()
dlg.Filter = "DB files|*.mdb|Access DB files|*.accdb|All Files|*.*"
If dlg.ShowDialog() = DialogResult.OK Then
DBFilePath.Text = dlg.FileName
'temporarily myfile will be set to c:/Exceltest/template.mdb
' myfile = "c:/Exceltest/template.mdb"
Try
If DBFilePath.Text <> "" Then
'On Error GoTo errorhandler
MYDBConnection = MyWorkspace.OpenConnection("provider=Microsoft.Ace.OLEDB.12.0; " & "data source=" & txtFilePath.Text)
MyDatabase = MyWorkspace.OpenDatabase(DBFilePath.Text)
sizetable = MyDatabase.OpenRecordset("size", DAO.RecordsetTypeEnum.dbOpenTable)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Function
Private Sub btnWrite_Click(sender As Object, e As EventArgs) Handles btnWrite.Click
'---This Try Finally block with set current cursor to waiting cursor while the program write to excel---'
Try
Cursor.Current = Cursors.WaitCursor
Write2Excel()
Finally
Cursor.Current = Cursors.Default
End Try
End Sub
Sub closexlsfile()
Try
''Do we need to save the file first?
objWorkBook.Save()
objWorkBook.Close()
objExcel.Quit()
'something weird happening on this line
MyConnection.Close()
MyConnection.Dispose()
objWorkBook = Nothing
objExcel = Nothing
Catch
End Try
'TBD the other objworksheets get closed here
End Sub
Private Sub closexls_Click(sender As Object, e As EventArgs) Handles closexls.Click
closexlsfile()
NAR(objWorkSheet1)
NAR(objWorkSheet2)
NAR(objworksheet3)
NAR(objworksheet10)
NAR(objworksheet11)
NAR(objworksheet12)
NAR(objworksheet13)
NAR(objworksheet23)
NAR(objworksheet24)
objWorkBook.Close(False)
NAR(objWorkBook)
NAR(MyConnection)
objExcel.Quit()
NAR(objExcel)
Debug.WriteLine("Sleeping...")
System.Threading.Thread.Sleep(5000)
Debug.WriteLine("End Excel")
End Sub
'---This is a method that I found of MSDN to quit an office application but it doesn't seem to work---'
Private Sub NAR(ByVal obj As Object)
Try
While (System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0)
End While
Catch
Finally
obj = Nothing
End Try
End Sub
End Class
You obviously have a lot of code and I can't go through all of that. However I dealt with this problem in the past. It is usually due to an unreleased object of some kind. For example lots of code samples from the intertubes suggests that you do things like
objWorkBook = objExcel.Workbooks.Open(txtFilePath.Text)
This is potentially dangerous, you should never have more than ONE . in a single right hand value. Instead go for something like
Workbooks wrkbks = objExcel.Workbooks
objWorkBook = wrkbks.Open(txtFilePath.Text)
Otherwise there will be memory allocated for the WorkBooks that isn't explicitly released. This is really a pain to go through all your code base once you've discovered this, but it solved the problem for me.
Your NAR sub should have it handled, but I far prefer Marshal.FinalReleaseComObject method - no loop required. You need to make sure all instances have been addressed - like in the closexlsfile() method you do not call NAR for these Com objects. I suggest some code cleanup.