Export data from VB to Excel sheet - vb.net

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.

Related

VB.NET Program is always reading last created textfile

Trying to create a login form,
My coding is currently:
Imports System
Imports System.IO
Public Class frmLogin
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String
Dim files As Integer
Dim filepath As String
Public Structure info
Dim U As String
Dim P As String
End Structure
Dim details As info
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
If txtusername.Text = details.U And txtpassword.Text = details.P Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
End Sub
Private Sub btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
files = files + 1
filepath = "C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt"
Dim di As DirectoryInfo = New DirectoryInfo("C:\Users\TheGlove\Desktop\Alex's Program")
folderpath = "C:\Users\TheGlove\Desktop\Alex's Program"
files = System.IO.Directory.GetFiles(folderpath, "*.txt").Count
For Each fi In di.GetFiles()
MsgBox(fi.Name)
Dim FILE = System.IO.File.ReadAllLines("C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt")
Dim myArray As String() = FILE
details.U = myArray(0)
details.P = myArray(1)
Next
End Sub
End Class
Button 1 will be merged with btnlogin when i get it working and for now is currently just a seperate button to read each textfile.
When each button is pressed (Button 1 -> btnlogin), only the last created textfile is correct.
By the looks of things, your code does read all the text files, but keeps overwriting details.u and details.p with the value retrieved from each file. So, when the loop gets to the last file, those values are what ends up in the details object.
I'm assuming that you want to read all the usernames and passwords into a list and check the details in the TextBoxes against that list, so .. Your code should probably be something like the code below (see the code comments for an explanation of some of the differences.
Before we get to the code, can give you a couple of pointers.
Firstly, always try to use names that are meaningful. Defining your structure as Info is not as meaningful as it could be. For example, you would be better calling it UserInfo and rather than use P and U, you would be better using Password and UserName. It may not matter so much right now, but when you start writing larger more complex programs, and have to come back to them in 6 months time to update them, info.P or details.P aren't as informative as the suggested names.
Secondly, as #ajd mentioned. Don't use magic strings. Create one definition at the beginning of your code which can be used throughout. Again it makes maintenance much easier if you only have to change a string once instead of multiple times, and reduces the chance of mistakes.
Finally, several of the variables you have defined aren't used in your code at all. Again, at this level, it isn't a major issue, but with large programs, you could end up with a bigger memory footprint than you want.
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String = "C:\Users\TheGlove\Desktop\Alex's Program"
Dim files As Integer
Dim filepath As String
Public Structure UserInfo
Dim Name As String
Dim Password As String
End Structure
'Change details to a list of info instead of a single instance
Dim userList As New List(Of UserInfo)
Private Sub Btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
'Iterate through the list of details, checking each instance against the textboxes
For Each tempUserInfo As UserInfo In userList
If txtusername.Text = tempUserInfo.Name And txtpassword.Text = tempUserInfo.Password Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
'This is here, because after your form has opened an closed, the loop
'that checks usernames and passwords will continue. The line below exits the loop safely
Exit For
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
Next
End Sub
Private Sub Btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'clear the list of user details otherwise, if the files are loaded a second time,
'you'll get the same details added again
userList.Clear()
'This line replaces several lines in your code that searches the folder for files
'marching the search pattern
Dim fileList() As FileInfo = New DirectoryInfo(folderpath).GetFiles("loginfile*.txt")
For Each fi As FileInfo In fileList
MsgBox(fi.Name)
Dim userDetails() As String = System.IO.File.ReadAllLines(fi.FullName)
Dim tempInfo As New UserInfo With {.Name = userDetails(0), .Password = userDetails(1)}
'An expanded version of the above line is
'Dim tempInfo As New info
'tempInfo.U = userDetails(0)
'tempInfo.P = userDetails(1)
userList.Add(tempInfo)
Next
files = fileList.Count
End Sub

Update one form based on selections from another form

I apologise if the title is a bit vague, i've only been on here a day.
So my problem is I have a menu form in which I input the options from the comboboxes. And then I go to the next form which shows the relevant imported text file info.
However when I click the 'back' button to return to the menu and input different information in the comboboxes, it doesn't take me to the correct text file info, it just shows the info from the previous selection.
here is the student menu pic
here is the text file form
below is the code for the student menu next button:
If OptionBox.Text = "Introduction" Then
Introduction.Show()
Else
If OptionBox.Text = "Explanation" Then
Explanation.Show()
End If
End If
End Sub
below is the code for the text file form load page and the back button
Private Sub Introduction_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Student_Menu.Hide()
Dim font As New System.Drawing.Font("Calibri", 11)
If Student_Menu.TopicSelect.Text = "Computer Systems" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\ComputerSystems.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
sr.Close()
Else
If Student_Menu.TopicSelect.Text = "Hardware" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\Hardware.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
sr.Close()
Else
If Student_Menu.TopicSelect.Text = "Software" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\Software.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
Else
If Student_Menu.TopicSelect.Text = "Representation of Data" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\RepresentationOfData.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
Else
If Student_Menu.TopicSelect.Text = "Databases" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\Databases.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
Else
If Student_Menu.TopicSelect.Text = "Communications & Networks" Then
Dim strFile As String = "C:\Users\Sales\Documents\Visual Studio 2010\Projects\gcsecomputingtask\textfiles\Introduction\Hardware.txt"
Dim sr As New IO.StreamReader(strFile)
IntroductionLabel.Text = sr.ReadToEnd()
End If
End If
End If
End If
End If
End If
IntroductionLabel.Font = font
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
Me.Hide()
Student_Menu.Show()
Student_Menu.TopicSelect.ResetText()
Student_Menu.OptionBox.ResetText()
End Sub
what do i need to do in order to update this information so that the program doesn't skip going through the form again.
There is a lot of repeated code there. Here is a way to reduce it (see DRY) and expose a method to change the topic. In a Module:
Public Enum Topics
ComputerSystems
Hardware
Software
Data
Database
Networks
End Enum
Then in the form that shows the text:
Friend Sub DisplayTopic(topic As Topics)
Dim text As String
Dim filname As String = ""
Select Case topic
Case Topics.ComputerSystems
filname = "ComputerSystems.txt"
Case Topics.Database
filname = "Databases.txt"
'... etc
End Select
' attach path
filname = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"gcsecomputingtask", filname)
text = File.ReadAllText(filname)
IntroductionLabel.Text = text
End Sub
By the way, VB does has an ElseIf which can avoid the "arrow" anti pattern you can see in your code. At the very least, the excessive indentation is annoying.
If topic = Topics.ComputerSystems Then
'...
ElseIf topic = Topics.Software Then
'...
End If
Show that form normally using an instance of the form class:
Public Class MenuForm ' a form is just a class
' declare an object variable to use
Private info As Form2 ' whatever its name is (Explanation???)
....
Private Sub MenuForm_Load(...)
' create an instance to be used later:
info = New Form2
Then invoke the method to tell it which topic to display. Displaying topic info is a separate method from loading a form first because the form load event happens only once. A specialized method to do what we want makes more sense since they really have nothing to do with one another, and makes it easier to see how the code works:
info.DisplayTopic(Topics.ComputerSystems)
info.Show
This way, you dont have one form fiddling with the controls on another, but still have a clear way of communicating which topic to display.
Note that the location of the topics file(s) is a bit different. You'd want a "gcsecomputingtask" folder in MyDocuments for the files. The VS project folder is not a good place for it, the folder location could change depending on which machine you are running on (yours or computer lab etc). They could also be stored as a resource to skip that part too.

Null reference exception when trying to open a workbook, vb.net

I've got an openfiledialog reading a spreadsheet file name from a textbox, then performing some formatting and spitting out a text file. The code works fine one time through; my next task is to get it so that I can open successive spreadsheets (one at a time) without closing the program.
When I try to open a second excel file, I get a null reference exception (object ref not set to an instance of an object) on the line where I'm opening the workbook.
Public Class Form1
Dim xlApp As New Microsoft.Office.Interop.Excel.Application
Dim xlWorkbook, xlWorkbook2 As Microsoft.Office.Interop.Excel.Workbook
Dim xlWsheet, xlWsheet2 As Microsoft.Office.Interop.Excel.Worksheet
Dim strm As System.IO.Stream
Dim FormFile As String = "C:\nitemp.tmp\QuantData.xls"
Private Sub Open_Click(sender As Object, e As EventArgs) Handles Open.Click
'Open button code'
OpenFileDialog1.Title = "Select a File"
OpenFileDialog1.InitialDirectory = directory.Text 'uppermost text box, change to open a different default directory with OPEN button'
OpenFileDialog1.RestoreDirectory = True
OpenFileDialog1.ShowDialog()
End Sub
Private Sub OpenFileDialog1_FileOk(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
Dim lrow As Integer = 0
Try
strm = OpenFileDialog1.OpenFile()
TextBox1.Text = OpenFileDialog1.FileName.ToString()
xlWorkbook = xlApp.Workbooks.Open(TextBox1.Text) 'opens excel file'
xlApp.Visible = False
strm.Close()
I see two possible null references here: 1) the .ToString on the previous line may be empty. WI run the code, the textbox isn't being populated by the correct file path. Only after the error box pops up and I hit 'continue' does the textbox show the correct path.
2) an issue with the platform, 64x vs 32x? This came up in a search, so I tried "New Excel.App" and "New Excel.Workbook", then changed to x86 platform, yet this got me the infamous COM exception 80040154, which makes me think this is not really the issue, but I'm still pretty new to coding..
Can someone find the null?
First things first, you don't need to call OpenFileDialog1.OpenFile(). In fact you don't need to get the filestream at all as you aren't manipulating the file directly (only Excel is).
Secondly, you need to retrieve and dispose of the xlApp.Workbooks collection independently, otherwise you are going to leak some COM wrappers. The null reference exception could be from either the Workbooks collection being null, or the open filename being null. Some error handling will solve your problem.
...
Dim xlWorkbooks as Excel.Workbooks
Dim xlWorkbookOpened as Excel.Workbook
Try
TextBox1.Text = OpenFileDialog1.FileName.ToString()
If (TextBox1.Text IsNot Nothing) Then
xlWorkbooks = xlApp.Workbooks
If (xlWorkbooks IsNot Nothing) Then
xlWorkbookOpened = xlWorkbooks.Open(TextBox1.Text) 'opens excel file'
If (xlWorkbookOpened IsNot Nothing) Then
' DO WHATEVER YOU NEED TO...
Marshal.ReleaseComObject(xlWorkbookOpened)
xlWorkbookOpened = Nothing
End If
Marshal.ReleaseComObject(xlWorkbooks)
xlWorkbooks = Nothing
End If
End If
Catch ex As Exception
' Log error to start with...
Trace.WriteLine(ex.Message)
End Try
Note that I've explicitly released every COM object after use and set the value to Nothing. This is necessary to ensure proper cleanup.

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

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)

Copying files back to a Specific Folder

This program extracts files from a folder that has been modified today, and after the files are placed into another folder a batch file then deletes the rest of the non-modified files in that source folder.
The last thing my program is supposed to do is copy files from separate folder, and place them back into that source folder.
But my program only extracts the modified files, deletes the rest of the files in that folder, but when I run the program to also copy and place the new files into the source folder it just doesn't do it. Does anyone know why?
Imports System.IO
Public Class frmExtractionator
' Dim txtFiles1 As Control
Dim sourceDirectory As String = "F:\CopierFolderforTestDriveCapstone"
Dim archiveDirectory As String = "F:\FilesExtracted"
Dim originalDirectory As String = "F:\OriginalTestFiles"
Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
Try
Dim txtFiles = Directory.EnumerateFiles(sourceDirectory)
If (Not System.IO.Directory.Exists(archiveDirectory)) Then
System.IO.Directory.CreateDirectory(archiveDirectory)
End If
For Each currentFileLoc As String In txtFiles
Dim fileName = currentFileLoc.Substring(sourceDirectory.Length + 1)
If (IO.File.GetLastWriteTime(currentFileLoc).ToString("MM/dd/yyyy") = DateTime.Now.ToString("MM/dd/yyyy")) Then
MessageBox.Show(currentFileLoc & " moved", "Moved Succesfully")
File.Move(currentFileLoc, Path.Combine(archiveDirectory, fileName))
End If
Next
Catch eT As Exception
Console.WriteLine(eT.Message)
End Try
System.Diagnostics.Process.Start("F:\poop.bat")
Try
Dim txtFiles2 = Directory.EnumerateFiles(originalDirectory)
For Each currentFileLoc2 As String In txtFiles2
Dim fileName = currentFileLoc2.Substring(originalDirectory.Length + 1)
File.Move(currentFileLoc2, Path.Combine(sourceDirectory, fileName))
Next
Catch eT As Exception
Console.WriteLine(eT.Message)
End Try
End Sub
End Class
Change
Dim fileName = currentFileLoc2.Substring(originalDirectory.Length + 1)
to
Dim FileName = IO.Path.GetFileName(currentFileLoc2)