Private Sub _LoadAndWrite()
Dim objWdDoc As Object
Dim objWord As Object
objWord = CreateObject("Word.Application")
objWdDoc = CreateObject("Word.Document")
Dim regKey As RegistryKey
Dim path As String
regKey = Registry.LocalMachine.OpenSubKey("Software\tDocManager", True)
path = regKey.GetValue("DocPath", "")
Dim DocPath As New System.IO.FileInfo(path)
regKey.Close()
Dim FileToCopy As String
FileToCopy = DocPath.FullName
NewCopy = DocPath.DirectoryName & "\" & Date.Now.Ticks.ToString & DocPath.Extension
If System.IO.File.Exists(FileToCopy) = True Then
System.IO.File.Copy(FileToCopy, NewCopy)
End If
objWdDoc = objWord.Documents.Add(NewCopy)
objWord.Visible = True
Dim sQ As String = ""
sQ &= " SELECT ...."
Dim _cmd As New SqlCommand
With _cmd
.CommandText = sQ
.Connection = dbMain
End With
Dim _da As New SqlDataAdapter(_cmd)
Dim _dt As New DataTable
Try
_da.Fill(_dt)
Catch ex As Exception
End Try
If _dt.Rows.Count > 0 Then
For Each dr In _dt.Rows
With objWdDoc.Bookmarks
If .Exists("tt") = True Then
.item("tt").Range.Text = IIf(IsDBNull(dr("tt")), "", dr("tt"))
End If
End With
Next
End If
End Sub
After that i call the function to write to database
Private Sub WriteWordDoc(filename As String, data As Byte())
Dim fs As New System.IO.FileStream(filename, IO.FileMode.Create)
Dim bw As New System.IO.BinaryWriter(fs)
bw.Write(data)
bw.Close()
fs.Close()
End Sub
i Got the error the file is used by another process . Even if i try to kill the process it still wont solve the problem.
Where am i making mistake with this ?
Edit> Button click call this
If MsgBox("Do you want to generate the document for current job ", MsgBoxStyle.YesNoCancel, "Word document") = MsgBoxResult.Yes Then
_LoadAndWrite()
End If
If MsgBox("Do you want to save document with changes ", MsgBoxStyle.YesNoCancel, "Word document") = MsgBoxResult.Yes Then
_SaveDocument(NewCopy)
End If
Public Sub _SaveDocument(ByVal doc2 As String)
Dim file As String = doc2
Dim doc() As Byte = ReadWordDoc(file)
End Sub
Related
Is there a way to convert an excel file into a datatable (without using connection string), so i can show it in a gridview? I already tried something, but I'm getting a System.NullReferenceException and i don't know why. Here's what i did:
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
If File.Exists(OpenFileDialog1.FileName) Then
If Path.GetExtension(OpenFileDialog1.FileName).ToString = ".xlsx" Then
Dim workbook As Workbook
Dim resourceName As String = "IGExcel.Resources." & OpenFileDialog1.FileName
Using stream As Stream = Me.GetType().Assembly.GetManifestResourceStream(resourceName)
Try
Workbook.Load(stream)
Catch ex As System.NullReferenceException
End Try
End Using
Dim dataTable As New DataTable
Dim sheet As Worksheet = workbook.Worksheets(0)
Dim serviceExcel
For Each row As WorksheetRow In sheet.Rows
serviceExcel = New ISAACServiceExcel()
serviceExcel.AufPos = row.Cells(0).Value.ToString()
serviceExcel.UANR = row.Cells(1).Value.ToString()
serviceExcel.K_Art = row.Cells(2).Value.ToString()
serviceExcel.Ueberbegriff = row.Cells(3).Value.ToString()
serviceExcel.Benennung = row.Cells(5).Value.ToString()
serviceExcel.Einheit = row.Cells(6).Value.ToString()
serviceExcel.Einzelkosten = row.Cells(7).ToString()
serviceExcel.Anzahl = row.Cells(8).ToString()
serviceExcel.Komponente = row.Cells(9).ToString()
serviceExcel.Projektbeteiligter = row.Cells(11).ToString()
serviceExcel.Chefblattposition = row.Cells(13).ToString()
serviceExcel.Total = row.Cells(15).ToString()
Next
dataTable = serviceExcel
dgv1.DataSource = dataTable
I will try to convince you that there is nothing to fear from connection strings. Three little functions here and you are displaying your data. I would bet it is somewhat faster than interop also.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim XLPath = GetExcelPath()
If XLPath IsNot Nothing Then
Dim XLSheet = GetSheetName(XLPath)
Dim dt = ExcelToDataTable(XLPath, XLSheet)
DataGridView1.DataSource = dt
Else
MessageBox.Show("No acceptable file selected.")
End If
End Sub
Private Function GetExcelPath() As String
Dim XLPath As String
OpenFileDialog1.Filter = "Excel files (*.xlsx)|*.xlsx"
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
XLPath = OpenFileDialog1.FileName
Return XLPath
End If
Return Nothing
End Function
Private Function GetSheetName(path As String) As String
Dim sn As String
Dim dt As DataTable
Using cn As New OleDbConnection($"Provider=Microsoft.ACE.OLEDB.12.0;Data Source= {path};Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';")
cn.Open()
dt = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
End Using
sn = dt(0)("Table_Name").ToString
Return sn
End Function
Private Function ExcelToDataTable(path As String, SheetName As String) As DataTable
Dim XLConStr = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source= {path};Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';"
Dim dt As New DataTable
Using cn As New OleDbConnection(XLConStr),
cmd As New OleDbCommand($"Select * From [{SheetName}];", cn)
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
i got at my pc (Windows 7 and 10) 3 active LAN-Adapters.
In history I used netsh, because you can choose an adapter
netsh interface ip set address ""LAN-BRIDGED"" static 192.168.255.130 255.255.255.128 192.168.255.129", AppWinStyle.Hide, True)
But sometimes netsh doesn´t work... So thats why I don´t want to use netsh.
Now I try it by another way to change IP + Subnet + Gateway. If I only activate one of these LAN-Adapters, my code works. But if all of them active then it changes the IP at a random LAN-Adapter.
How can i choose one exactly LAN-Adapter with my code?
Option Strict On
Imports System.Net.NetworkInformation
Imports System.Management
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim LAN_Adapter As NetworkInterface
ComboBoxAdapterSelector.Items.Clear()
For Each LAN_Adapter In NetworkInterface.GetAllNetworkInterfaces()
With LAN_Adapter
ComboBoxAdapterSelector.Items.Add(.Name)
End With
Next
End Sub
Private Sub ChangechoosenIPButton_Click(sender As Object, e As EventArgs) Handles ChangechoosenIPButton.Click
ChangechoosenIP()
End Sub
Sub ChangechoosenIP()
Dim IPAddress As String = TextBoxIPAddress.Text
Dim SubnetMask As String = TextBoxSubnetMask.Text
Dim Gateway As String = TextBoxGateway.Text
If ComboBoxAdapterSelector.SelectedText = "Ethernet 2" Then
Dim objMC As ManagementClass = New ManagementClass("Win32_NetworkAdapterConfiguration")
Dim objMOC As ManagementObjectCollection = objMC.GetInstances()
For Each objMO As ManagementObject In objMOC
Try
Dim objNewIP As ManagementBaseObject = Nothing
Dim objSetIP As ManagementBaseObject = Nothing
Dim objNewGate As ManagementBaseObject = Nothing
objNewIP = objMO.GetMethodParameters("EnableStatic")
objNewGate = objMO.GetMethodParameters("SetGateways")
objNewGate("DefaultIPGateway") = New String() {Gateway}
objNewGate("GatewayCostMetric") = New Integer() {1}
objNewIP("IPAddress") = New String() {IPAddress}
objNewIP("SubnetMask") = New String() {SubnetMask}
objSetIP = objMO.InvokeMethod("EnableStatic", objNewIP, Nothing)
objSetIP = objMO.InvokeMethod("SetGateways", objNewGate, Nothing)
Catch ex As Exception
MessageBox.Show("Error : " & ex.Message)
End Try
Next objMO
ElseIf ComboBoxAdapterSelector.SelectedText = "Ethernet" Then
'.
'.
'.
ElseIf ComboBoxAdapterSelector.SelectedText = "LAN-Connection" Then
'.
'.
'.
End If
End Sub
I try this code on (LAN and Wireless)
For Each objMO As ManagementObject In objMOC
If objMO.SystemProperties("MACAddress").Value IsNot Nothing Then
'***** USE THIS
If objMO.SystemProperties("Description").Value <> "RAS Async Adapter" Then
MessageBox.Show("Caption: " & objMO.SystemProperties("Caption").Value)
'your code
End If
'***** OR THIS
'If objMO.SystemProperties("IPEnabled").Value = True And objMO.SystemProperties("DefaultIPGateway").Value IsNot Nothing Then
' MessageBox.Show("Caption: " & objMO.SystemProperties("Caption").Value)
' 'your code
'End If
End If
Next
A : Here is how to list ALL available adapters (Hardware w/without software)
Dim HardwareOnly As Boolean = True
For Each LAN_Adapter As NetworkInterface In NetworkInterface.GetAllNetworkInterfaces()
With LAN_Adapter
If HardwareOnly = True Then 'According to MAC-Address
If LAN_Adapter.GetPhysicalAddress.ToString <> "" Then
If LAN_Adapter.GetPhysicalAddress.ToString.StartsWith("00000000") = False Then
ComboBoxAdapterSelector.Items.Add(LAN_Adapter)
End If
End If
Else
ComboBoxAdapterSelector.Items.Add(LAN_Adapter)
End If
End With
Next
ComboBoxAdapterSelector.DisplayMember = "Name"
B : Now each item in ComboBoxAdapterSelector is refering to an
adapter (NetworkInterface object) 'so using If ComboBoxAdapterSelector.SelectedText = "Ethernet 2" Thenis not
recommanded 'LAN_Adapter.Name = "Ethernet 2" is not a static
field the user can change it from the Control Panel\Network and Internet\Network Connections
If ComboBoxAdapterSelector.SelectedItem IsNot Nothing Then
Dim tmpAdapter As NetworkInterface = DirectCast(ComboBoxAdapterSelector.SelectedItem, NetworkInterface)
Dim objMC As ManagementClass = New ManagementClass("Win32_NetworkAdapterConfiguration")
Dim objMOC As ManagementObjectCollection = objMC.GetInstances()
For Each objMO As ManagementObject In objMOC
'choose a static field to compare `objMO` with selected adapter => `tmpAdapter` <br>
'for example `tmpAdapter.Description` `tmpAdapter.GetPhysicalAddress` `tmpAdapter.Id` etc
If objMO.GetPropertyValue("SettingID") = tmpAdapter.Id Then
'NOW you find the object that refers to what you select in ComboBoxAdapterSelector
Dim objNewIP As ManagementBaseObject = Nothing
Dim objSetIP As ManagementBaseObject = Nothing
'your code
Exit For
End If
Next objMO
End If
I need export a DataTable to an Excel file using vb.net
I try with two different options, this work but generate conflicts with the labels in the front; somebody know other form to do this?
Dim GridTemp As New GridView()
GridTemp.AllowPaging = False
GridTemp.DataSource = baseIngresos
GridTemp.DataBind()
Response.Clear()
Response.Buffer = True
Response.AddHeader("content-disposition", "attachment;filename=NO_Marcados" + Trim(Ipfechainicio.Text) + "_" + Trim(Ipfechafin.Text) + ".xls")
Response.Charset = "UTF-8"
Response.ContentType = "application/vnd.ms-excel"
Dim sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
For i As Integer = 0 To GridTemp.Rows.Count - 1
GridTemp.Rows(i).Attributes.Add("class", "textmode")
Next
GridTemp.RenderControl(hw)
Dim style As String = "<style> .textmode{mso-number-format:\#;}</style>"
Response.Write(style)
Response.Output.Write(sw.ToString())
Response.Flush()
Response.End()
And the other option that I use:
Dim sb As New StringBuilder()
Dim sw As New StringWriter(sb)
Dim htw As New HtmlTextWriter(sw)
Dim pag As New Page()
Dim form As New HtmlForm()
Dim gridV As New GridView()
gridV.EnableViewState = False
gridV.DataSource = baseIngresos
gridV.DataBind()
pag.EnableEventValidation = False
pag.DesignerInitialize()
pag.Controls.Add(form)
form.Controls.Add(gridV)
pag.RenderControl(htw)
Response.Clear()
Response.Buffer = True
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("Content-Disposition", "attachment;filename=NO_Marcados" + Trim(Ipfechainicio.Text) + "_" + Trim(Ipfechafin.Text) + ".xls")
Response.Charset = "UTF-8"
Response.ContentEncoding = Encoding.Default
Response.Write(sb.ToString())
Response.End()
I see that you're using gridview. I'm using a datagridview and used this code:
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim xlApp As Microsoft.Office.Interop.Excel.Application
Dim xlWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer
Dim j As Integer
xlApp = New Microsoft.Office.Interop.Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
'FOR HEADERS
For i = 1 To DataGridView1.ColumnCount
xlWorkSheet.Cells(1, i) = DataGridView1.Columns(i - 1).HeaderText
'FOR ITEMS
For j = 1 To DataGridView1.RowCount
xlWorkSheet.Cells(j + 1, i) = DataGridView1(i - 1, j - 1).Value.ToString()
Next
Next
xlWorkSheet.SaveAs("D:\vbexcel.xlsx")
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
MsgBox("You can find the file D:\vbexcel.xlsx")
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim connetionString As String
Dim connection As OleDbConnection
Dim oledbAdapter As New OleDbDataAdapter
Dim sql As String
connetionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=samplelangtowalangya.mdb;"
connection = New OleDbConnection(connetionString)
sql = "update Users set Password = 'new password' where UserID = 'user1'"
Try
connection.Open()
oledbAdapter.UpdateCommand = connection.CreateCommand
oledbAdapter.UpdateCommand.CommandText = sql
oledbAdapter.UpdateCommand.ExecuteNonQuery()
MsgBox("Row(s) Updated !! ")
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
End Class
A excel file will be created in the path "D:\vbexcel.xlsx" and save it with the file name vbexcel.xlsx. Also, try reading about Crystal Report. It is widely used in generating reports and open it with excel.
So I've finally got this to almost work but now every few times I test the process the form and the progressbar freeze. I'm also sure there are much more efficient ways of doing this so any constructive criticism would be greatly appreciated.
This is the coding for one page of a program that allows the user to click one button to download and install one application and then press the next button to download and install a different application:
Imports System.Net.WebRequestMethods
Public Class Software
'Open link in external browser
Public Sub HandleRequestNavigate(ByVal sender As Object, ByVal e As RequestNavigateEventArgs)
Process.Start(New ProcessStartInfo(e.Uri.AbsoluteUri))
e.Handled = True
End Sub
'Declarations
Shared progressamc As New Progress
Shared progresscti As New ProgressCTI
WithEvents startcti As New Process
WithEvents startamc As New Process
WithEvents startsfstb As New Process
WithEvents amcworker As New ComponentModel.BackgroundWorker
WithEvents ctiworker As New ComponentModel.BackgroundWorker
Dim ProgressBarAMC As Object = Progress.ProgressBar1
Dim blprgrsAMC As Object = Progress.blprgrs
Dim ProgressBarCTI As Object = progresscti.ProgressBar1
Dim blprgrsCTI As Object = progresscti.blprgrs
'FTP Values
Const host As String = "ftp://10.167.16.80/"
Const username As String = "anonymous"
Const password As String = ""
'AMC File Put/Get
Const localfileamc As String = "C:\AMC.exe"
Const Remotefileamc As String = "Bin/AMC.exe"
'CTI File Put/Get
Const localfilecti As String = "C:\CTI.exe"
Const Remotefilecti As String = "Bin/CTI.exe"
'On Init
Public Sub New()
InitializeComponent()
amcworker.WorkerReportsProgress = True
amcworker.WorkerSupportsCancellation = True
ctiworker.WorkerReportsProgress = True
ctiworker.WorkerSupportsCancellation = True
End Sub
'Install AMC Button
Private Sub ButtonAMC(sender As Object, e As RoutedEventArgs)
Dim butt1 As Button = DirectCast(sender, Button)
butt1.IsEnabled = False
Dispatcher.BeginInvoke(New Action(AddressOf progressamc_Show))
AddHandler Progress.Cancel_Click, AddressOf myProcessamc_Exited
amcworker.RunWorkerAsync()
End Sub
'Open Dialog
Private Sub progressamc_Show()
Try
progressamc.ShowDialog()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
End Try
End Sub
'FTP - Download
Private Sub ftpseshamc_DoWork(ByVal sender As System.Object, ByVal e As ComponentModel.DoWorkEventArgs) Handles amcworker.DoWork
Dim URI As String = host & Remotefileamc
Dim FTP As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(URI), System.Net.FtpWebRequest)
'Set the credentials
FTP.Credentials = New System.Net.NetworkCredential(username, password)
'FTP Options
FTP.KeepAlive = False
FTP.UseBinary = True
'Define the action as Download
FTP.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
'Get the response to the Ftp request and the associated stream
Try
Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse)
Dim Length As Long = response.ContentLength
Dim StopWatch As New Stopwatch
Dim CurrentSpeed As Double = Nothing
Using responseStream As IO.Stream = response.GetResponseStream
'loop to read & write to file
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
StopWatch.Start()
amcworker.ReportProgress(CShort(count / Length * 100 + 0.5))
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
StopWatch.Stop()
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
myProcessamc_Exited()
End Try
Installamc()
End Sub
'Starts the installation
Sub Installamc()
startamc.StartInfo.FileName = "C:\AMC.exe"
startamc.EnableRaisingEvents = True
Try
startamc.Start()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Dispatcher.Invoke(New Action(AddressOf Progressamc_Hide))
End Sub
'Hide Dialog during install
Private Sub Progressamc_Hide()
progressamc.Hide()
End Sub
'Report progress
Private Sub amcworker_ProgressChanged(ByVal sender As System.Object, ByVal e As ComponentModel.ProgressChangedEventArgs) Handles amcworker.ProgressChanged
ProgressBarAMC.value = e.ProgressPercentage
blprgrsAMC.Content = "Downloading: " & e.ProgressPercentage & "%"
End Sub
End Class
Again, any help would be greatly appreciated.
Edit: I've made the following edit to the code but I'm not entirely sure it's doing what I think it's doing. Basically what I intended is for the ReportProgress to only run once every 2047 bytes read.
'Get the response to the Ftp request and the associated stream
Try
Dim response As System.Net.FtpWebResponse = CType(FTP.GetResponse, System.Net.FtpWebResponse)
Dim Length As Long = response.ContentLength
Dim StopWatch As New Stopwatch
Dim CurrentSpeed As Double = Nothing
Using responseStream As IO.Stream = response.GetResponseStream
'loop to read & write to file
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
Dim chunk As Integer = Int(2047 / Length)
Dim cycle As Integer = chunk = count
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
StopWatch.Start()
If cycle = True Then
amcworker.ReportProgress(CShort(count / Length * 100 + 0.5))
Else
End
End If
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
StopWatch.Stop()
responseStream.Close()
fs.Flush()
fs.Close()
End Using
responseStream.Close()
End Using
response.Close()
Catch ex As Exception
MessageBox.Show("An error has occurred during the process:" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & "Please close the application and try again." _
& vbCrLf & "If you continue to encounter this error please Email")
myProcessamc_Exited()
End Try
I didn't scrutinize the code carefully, but I don't see why you're using stopwatch, so I took out the references. I'm not sure what starting it multiple times inside the loop and ending it outside would do anyway.
The use of the word END in the second example will comletely end your app! Pretty sure that's what you want there.
Try this modification of your first code. The key is only updating if change is >= 5%:
Using fs As New IO.FileStream(localfileamc, IO.FileMode.Create)
Dim buffer(2047) As Byte
Dim read As Integer = 0
Dim count As Integer
dim LastPct as Short = -5
dim Pct as Short = 0
Do
If amcworker.CancellationPending = True Then
e.Cancel = True
Return
End If
Pct = CShort(count / Length * 100 + 0.5)
if Pct>= (LastPct + 5)
amcworker.ReportProgress(Pct)
LastPCT= Pct
EndIf
read = responseStream.Read(buffer, 0, buffer.Length)
fs.Write(buffer, 0, read)
count += read
Loop Until read = 0
amcworker.ReportProgress(100)
responseStream.Close()
fs.Flush()
fs.Close()
End Using
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.