vb.net writer to excel function working on one pc but not on another - vb.net

I have a vb.net function which uses oledb to create a spreadsheet, then treat it like a database, creating tables and inserting values. The function takes in a filename and a dataset, and returns the filename if it worked. The function works beautifully on my dev machine, but not other PCs. Below is my function, is there anything wrong with the code? Any suggestions?
EDIT: There are no errors being thrown, the resulting file doesn't contain any data.
Imports System
Imports System.Configuration
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient
Imports System.Drawing
Imports System.IO
Imports System.Net.Mail
Imports System.Text
Imports System.Web
Imports Microsoft.Office.Interop
....
Public Shared Function writeToExcelFile(ByVal template As String, ByVal filename As String, ByVal data As DataSet) As String
If File.Exists(filename) Then
File.Delete(filename)
End If
If template <> String.Empty AndAlso filename <> String.Empty Then
File.Copy(template, filename)
End If
Dim connString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + ";Extended Properties=""Excel 8.0;HDR=Yes;"""
Dim conn As New OleDbConnection(connString)
Try
conn.Open()
Dim cmd As New OleDbCommand()
For Each table As DataTable In data.Tables
Dim tableName As String = table.TableName.Replace(" ", "")
Dim tableCreate As String = "CREATE TABLE [" + tableName + "] ("
Dim sql As String = "INSERT INTO [" + tableName + "$]("
Dim colName As String = String.Empty
For Each col As DataColumn In table.Columns
colName = col.ColumnName.Replace("#", "num")
If colName.Contains(" ") Then
sql += " [" + colName.Replace("'", "") + "],"
Else
sql += " " + colName.Replace("'", "") + ","
End If
tableCreate += " [" + colName + "] varchar(255),"
Next
If tableCreate.EndsWith(",") Then
tableCreate = tableCreate.TrimEnd(New [Char]() {","c})
End If
tableCreate += ") "
cmd = New OleDbCommand(tableCreate, conn)
cmd.ExecuteNonQuery()
If sql.EndsWith(",") Then
sql = sql.TrimEnd(New [Char]() {","c})
End If
sql += ") "
For Each row As DataRow In table.Rows
Dim values As String = " VALUES("
For Each col As DataColumn In table.Columns
Try
values += "'" + cleanString(row(col).ToString()).Substring(0, 250) + "...',"
Catch e As Exception
values += "'" + cleanString(row(col).ToString()) + "',"
End Try
Next
If values.EndsWith(",") Then
values = values.TrimEnd(New [Char]() {","c})
End If
values += ") "
cmd = New OleDbCommand(sql + values, conn)
cmd.ExecuteNonQuery()
Next
Next
conn.Close()
Return filename
Catch e As Exception
Throw New Exception(e.Message)
Return String.Empty
End Try
End Function

Check your system's Regional Settings vs other machines' Regional Settings.
If they differ, try to match them.
Also, when working with Office Automation you should force the thread's culture to en-US.
Set this just before calling writeToExcelFile() (C# syntax):
System.Threading.Thread.CurrentThread.CultureInfo = new System.Globalization.CultureInfo("en-US");
After calling the method, restore the culture (if needed).

Problem is not with this code. Problem is with the dataset that's being passed in.

Related

System.InvalidOperationException: ExecuteReader requires an open and available connection. The connection's current state is closed

I am having a problem with a customer service module which is in a different solution. the problem I think is in my method of calling or getting a connection
here is my class called DBConnForAccess
Imports System.Data.OleDb
Imports System.Data.Odbc
Public Class DBConnForAccess
Dim Conn As New OleDbConnection
Dim cmd As New OleDbCommand
Dim Trans As OleDbTransaction
Public Function DBConnect(ByVal filePath As String, pass As String)
Try
' open Database
'Conn = New SqlConnection("Data Source=" + ServerName + "\" + DBName + ";User ID=" + DBUsername + ";Password=" + DBPassword + ";Initial Catalog= '" + TB + "'")
Conn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Jet OLEDB:Database Password=" + pass + ";")
' "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\mydatabase.mdb;Jet OLEDB:Database Password=MyDbPassword;"
If Conn.State = ConnectionState.Closed Then
Conn.Open()
End If
' create transaction
Trans = Conn.BeginTransaction
Return "Ok"
Catch ex As Exception
Return ex.Message
End Try
End Function
Public Sub ExecuteSQL(ByVal sql As String, ByVal ParamArray Obj() As Object)
' command Object
Dim CMD As New OleDbCommand(sql, Me.Conn, Me.Trans)
'add the parameters to the sql command
Dim I As Integer
For I = 0 To Obj.Length - 1
CMD.Parameters.AddWithValue("#" & I, Obj(I))
Next
'execute the sql
CMD.ExecuteNonQuery()
End Sub
Public Sub commit()
Me.Trans.Commit()
Me.Trans = Me.Conn.BeginTransaction
End Sub
Public Sub rollback()
Me.Trans.Rollback()
Me.Trans = Me.Conn.BeginTransaction
End Sub
Public Sub CloseDB()
Me.Conn.Close()
Me.Conn.Dispose()
Me.Trans.Dispose()
End Sub
Public Function ReadData(ByVal sql As String, ByVal ParamArray Obj() As Object)
' command Object
Dim CMD As New OleDbCommand(sql, Me.Conn, Me.Trans)
'add the parameters to the sql command
Dim I As Integer
For I = 0 To Obj.Length - 1
CMD.Parameters.AddWithValue("#" & I, Obj(I))
Next
Dim R = CMD.ExecuteReader()
'Do While R.Read
'Loop
Return R
End Function
End Class
Here is the Sub I use to fetch Data:
Dim connection As String = txt_util.readFromTextFile("ConnStr_2.txt", 0) + "Billing.mdb"
'connection string is in a text file with text at line 0 as "C:\BILLSERV\"
Private Sub searchAccnt(ByVal SIN As String)
'clear other fields
Clear("Acct")
Try
AccntDetail.DBConnect("ConcessionairesAccnt")
'Dim RS = AccntDetail.ReadData("Select * From AllAccounts Where SIN=#0", txtSIN.Text.Trim)
Dim RS = AccntDetail.ReadData("Select * From viewCSFAccnt Where SIN=#0", SIN)
RS.Read()
If RS.Hasrows = 0 Then
MsgBox("Accounts not found. Check the SIN you Enter.", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Records not found.")
'txtAppNo.Focus()
Exit Sub
Else
'MsgBox("Accounts correct.", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Records found.")
txtZoneNo.Text = RS.Item("Zone").ToString
txtSeq.Text = RS.Item("SeqNo").ToString
txtAccntName.Text = RS.Item("AccountName").ToString
txtAccntAddress.Text = RS.Item("HouseNo").ToString + " " + RS.Item("BLDGName").ToString + " " + RS.Item("Street").ToString + _
" " + RS.Item("BRGY").ToString
txtMeterNo.Text = RS.Item("MeterNo").ToString
txtAccntStatus.Text = varA.AccntStatus(RS.Item("Status").ToString)
'Dim con = AccessAccnt.DBConnect(connection, "")
'If con <> "Ok" Then
' MsgBox("Cannot establish a Connection to the server.", MsgBoxStyle.Critical, "Connection Lost...")
'End If
Dim ZoneNo = "Z" + GetChar(txtZoneNo.Text, 1) + GetChar(txtZoneNo.Text, 2) + "B" + GetChar(txtZoneNo.Text, 3) + GetChar(txtZoneNo.Text, 4)
AccessAccnt.DBConnect(connection, "")
Dim Acc = AccessAccnt.ReadData("SELECT * FROM " & ZoneNo & " WHERE AcctNo3=#1", txtSeq.Text)
Acc.Read()
txtLastReading.Text = Acc.Item("LastReading").ToString
Acc.close()
AccessAccnt.CloseDB()
End If
RS.Dispose()
AccntDetail.CloseDB()
dbCounter.DBConnect("ConcessionairesAccnt")
Dim result = dbCounter.ReadData("Select Top 1 CSFNo From CSFMaster WHERE (CSFNo LIKE '%" & ctrDate() & "%') order by CSFNo Desc")
result.read()
If result.hasrows = 0 Then
txtTrackingNo.Text = ctrDate() & "-" & "000001"
Else
txtTrackingNo.Text = counter.CtrLastItemWithChar("ConcessionairesAccnt", "CSFNo", "CSFMaster", "WHERE (CSFNo LIKE '%" & ctrDate() & "%') ORDER BY CSFNo DESC", 5)
End If
dbCounter.CloseDB()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
The Error is thrown here:
Dim Acc = AccessAccnt.ReadData("SELECT * FROM " & ZoneNo & " WHERE AcctNo3=#1", txtSeq.Text)
It Says:
System.InvalidOperationException: ExecuteReader requires an open and available connection. The connection's current state is closed.
The Other Parts of the Sub Works fine, The part where I fetch Data on my MSSQL Server database. The Problem lies in the Access data-Fetching Code.
I tried Using the code on another project (just the code where i fetch access data) I worked on other solutions. But I copy and paste my code on any form in this solution I keeps giving the Error.
I thought Maybe I closed the connection somewhere but this is the only instance I used this code in this entire project. (Just to get the last reading record.)
The Database is in the correct place (C:\BILLSERV)
I've Tried searching it here on SE but all I can see where suggestions about maybe forgetting to open the connection. I used this code before and this code works on my other solutions. I just cant seem to have it work here on this particular project. I wonder Why..
I tried running another project using this code and it works fine.
Is there a bug about Access connection on VB.net 2012, I have been using this code (DBConnForAccess Class) for about a year now and this is the first time I have encountered this error. btw I use Access 2003 because this database used to be for an old system created in VB6.
Lastly could this be because the solution came from another computer using a VB.Net Program same as mine. Because We work as a team here. Hope someone with a better knowledge on these systems could help. Thanks in advance.
EDIT
If a connection has been made, there should be a .ldb file in access which should appear. (I tested this on another project and an ldb file appear once a connection has been made, as we all know ldb file contains the data of the user using the db file.) I tried to re-run the system and while I'm using the system no ldb file was created.
Also,I thought Maybe I closed the connection somewhere but this is the only instance I opened a connection in access and which I used the code in this entire project. (Just to get the last reading record.)
So this is NOT a duplicate of “There is already an open DataReader…” Reuse or Dispose DB Connections? Just for clarifications
After a week of debugging and reading articles in the web.
We have found the culprit of the Error.
Seems that the Target CPU Option in Advance compiler Settings was change to AnuCPU.
We noticed this after we checked the other application projects we used.
Changing it Back to x86 solves the connection problem.
I wonder why this affected the connection to the access.
All is working fine now. thank you Plutonix and Steve for all your suggestions we'll be having a change in our codes.

easiest way to add a SQL column through VB

What i want to do is first check if a certain column already exists in a table and if not add it. I want to implement this through visual basic. If somebody took a little time to comment and briefly explain each step i would greatly appreciate it.
There are two ways to determine if a column exists: either try to use it and catch the error if it doesn't exist, or read the metadata from the database see SQL Server: Extract Table Meta-Data (description, fields and their data types)
Once you know that you need to add the column you use the ALTER TABLE command to add the column to the table.
Here is vb.net script to check if column exist, if not, create it..
''' summary
''' Checks to see if a table exists in Database or not.
'''
''' Table name to check
''' Connection String to connect to
''' Works with Access or SQL
'''
Public Function DoesTableExist(ByVal tblName As String, ByVal cnnStr As String) As Boolean
' For Access Connection String,
' use "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
' accessFilePathAndName
' Open connection to the database
Dim dbConn As New OleDbConnection(cnnStr)
dbConn.Open()
' Specify restriction to get table definition schema
' For reference on GetSchema see:
' http://msdn2.microsoft.com/en-us/library/ms254934(VS.80).aspx
Dim restrictions(3) As String
restrictions(2) = tblName
Dim dbTbl As DataTable = dbConn.GetSchema("Tables", restrictions)
If dbTbl.Rows.Count = 0 Then
'Table does not exist
DoesTableExist = False
Else
'Table exists
DoesTableExist = True
End If
dbTbl.Dispose()
dbConn.Close()
dbConn.Dispose()
End Function
'''
''' Checks to see if a field exists in table or not.
'''
''' Table name to check in
''' Field name to check
''' Connection String to connect to
'''
'''
Public Function DoesFieldExist(ByVal tblName As String, _
ByVal fldName As String, _
ByVal cnnStr As String) As Boolean
' For Access Connection String,
' use "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
' accessFilePathAndName
' Open connection to the database
Dim dbConn As New OleDbConnection(cnnStr)
dbConn.Open()
Dim dbTbl As New DataTable
' Get the table definition loaded in a table adapter
Dim strSql As String = "Select TOP 1 * from " & tblName
Dim dbAdapater As New OleDbDataAdapter(strSql, dbConn)
dbAdapater.Fill(dbTbl)
' Get the index of the field name
Dim i As Integer = dbTbl.Columns.IndexOf(fldName)
If i = -1 Then
'Field is missing
DoesFieldExist = False
Else
'Field is there
DoesFieldExist = True
End If
dbTbl.Dispose()
dbConn.Close()
dbConn.Dispose()
End Function
Dim connString As String = "Data Source=NameOfMachine\InstanceofSQLServer;Initial Catalog=NameOfDataBase;Integrated Security=True"
Dim MyCol As String = "NameOfColumn"
Dim MyTable As String = "[NameOfTable]" ' or "[Name Of Table]" use brackets if table name contains spaces or other illegal Characters
Dim MySql As String = "IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS" & vbCrLf &
"WHERE TABLE_NAME = '" & MyTable & "' AND COLUMN_NAME = '" & MyCol & "')" & vbCrLf &
"BEGIN" & vbCrLf &
"ALTER TABLE [dbo]." & MyTable & " ADD" & vbCrLf & "[" & MyCol & "] INT NULL ;" & vbCrLf & "END"
Try
' MsgBox(MySql)- this msg box shows the Query so I can check for errors- Not required for code.
Dim dbConn = New SqlConnection(connString)' Note ConnString must be declared in the form class or within this Sub. Connstring is your connection string
Dim dbCmd = New SqlCommand(MySql, dbConn)
dbConn.Open()
dbCmd.ExecuteNonQuery()
'MessageBox.Show("Ready To Load Addendums")
dbConn.Close()
Catch ex As Exception
MsgBox("We've encountered an error;" & vbCrLf & ex.Message)
End Try

"Could not find installable ISAM" error in VB.NET

Im new to visual basic.. I would like to ask on how to fixed the problem "Could not find installable ISAM.". I used Visual Basic as programming language. I used MS access as the database. My program is to fetch data from access. This would be my code.
Imports System.Data.OleDb
Module Main
Dim mDataPath As String
Sub Main()
GetPupils()
Console.ReadLine()
End Sub
Private Function GetConnection() As OleDb.OleDbConnection
'return a new connection to the database5
Return New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Database Password=oNer00FooR3n0 " & "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb")
End Function
Public Function GetPupils() As DataSet
Dim conn As OleDb.OleDbConnection = GetConnection()
Try
Dim ds As New DataSet 'temporary storage
Dim sql As String = "select * from SESSIONS" 'query
Dim da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sql, conn) 'connection
Try
da.Fill(ds, "SESSIONS") 'fetch data from db
Finally
da.Dispose() 'in case something goes wrong
End Try
Dim startVal = 0 'first record
Dim endVal = ds.Tables(0).Rows.Count 'total number records
For var = startVal To endVal - 1 'display records
Console.WriteLine(ds.Tables(0).Rows(var).Item(0).ToString() + " " + ds.Tables(0).Rows(var).Item(1).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString()) 'code for display id and name
Next
Return ds
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Module
I would like to know what is the cause of the error so that I can proceed to my program.. Thank you so much for the feedback..
You seem to be missing a delimiter after your password attribute.
I think you also need to use Jet OLEDB:Database Password=... instead (if indeed you have an access database protected with a password):
"Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb;" _
& "Jet OLEDB:Database Password=oNer00FooR3n0;"
Missing ; delimiter here:
...Password=oNer00FooR3n0 " & "Data Sourc...
Needs to be
...Password=oNer00FooR3n0 " & ";Data Sourc...
Also just Password instead of Database Password.
Initially, i too got this sort of error, but when i wrote the connection string in a single line (i mean without using [& _] or breaking in 2 lines, then this worked properly.
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\USER1\Desktop\MSaccessDB\MSaccessDB\my_database_file.mdb;Database Password=MyPassword"
Hope this helps.
Mukesh L.

vb.net generalized write of data to excel

I need to create an excel file from scratch in VB.NET given a DataTable from asp.net.
I can do this for a specific file, but I don't know how to do it for a general database.
That is, where I use the "CREATE TABLE ..." I don't know how to tell it what types to use for the data in the table.
The DataTable is derived from a FoxPro database. (I don't know if that matters.)
I invoke the table similar to as follows:
<%
return_value = make_excel( sql_table, excel_filename)
%>
make_excel is defined as
Option Explicit On
'Option Strict On
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.Page
Imports System.IO
Imports Microsoft.VisualBasic
Imports System.Diagnostics
Imports System.Data
Imports System.Data.OleDb
Public Class clsCommon
Inherits Page
' buncha other stuff defined in here.
Public Shared Function make_excel(ByVal sqlTable As DataTable, ByVal xls_fn As String) As Boolean
Dim conn As System.Data.OleDb.OleDbConnection
Dim ds As System.Data.DataSet
Dim cmd As New System.Data.OleDb.OleDbCommand()
conn = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & xls_fn & "';Extended Properties=Excel 8.0;")
conn.Open()
cmd.Connection = conn
cmd.CommandText = "CREATE TABLE MyTable ( Admin char(20), first_name char(20));"
cmd.ExecuteNonQuery()
cmd.CommandText = "INSERT INTO MyTable ( Admin, first_name ) VALUES ('true', 'Bob')"
cmd.ExecuteNonQuery()
conn.Close()
Return True
End Function
End Class
What I need to be able to do is run through the values in sqlTable above, check their type and then build the sql to write them. Pointers?
Have you looked into the copyfromrecordset function? You'll need to do a bit of work and its a bit of a change of approach but it might be something you can look into. An MS article is available here (Sorry, the article is based around VBA, but it should help as a guide).
I have a solution to the problem. I'm not happy about it as a general solution, but it works well enough for the cases I'm currently dealing with.
In this solution, I create a template of the excel file that has the column headings I want to use. When I do the select in the forward code, I change the name of the fields as appropriate (or drop whatever fields I don't want).
Public Shared Function TestXL(ByVal resp As HttpResponse, ByVal sqlTable As DataTable, ByVal xls_template_fn As String, ByVal xls_fn As String) As Boolean
Dim conn As System.Data.OleDb.OleDbConnection
Dim ds As System.Data.DataSet
Dim cmd As New System.Data.OleDb.OleDbCommand()
Dim r As DataRow
Dim c As DataColumn
Dim i As Integer
Dim sql As String
dim str as string
If File.Exists(xls_template_fn) Then
try
If File.Exists(xls_fn) Then
File.Delete(xls_fn)
Else
File.Copy(xls_template_fn, xls_fn)
End If
catch ex1 as Exception
File.Copy(xls_template_fn, xls_fn)
End Try
Else
resp.Write("Unable to locate template file: " & xls_template_fn)
Return False
End If
conn = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & xls_fn & "';Extended Properties=Excel 8.0;")
conn.Open()
cmd.Connection = conn
cmd.CommandText = sql
For Each r In sqlTable.Rows
sql = "INSERT INTO MyTable ("
For i = 0 To sqlTable.Columns.Count - 1
sql = sql & " " & sqlTable.Columns(i).ColumnName & ","
Next
sql = Left(sql, sql.Length - 1) & " ) VALUES ( "
For i = 0 To sqlTable.Columns.Count - 1
str = r(i).toString()
dim str2 as string = str.replace("'", "''")
sql = sql & " '" & str2 & "',"
Next
sql = Left(sql, sql.Length - 1) & " );"
'resp.Write(sql & "<br/>")
cmd.CommandText = sql
cmd.ExecuteNonQuery()
Next
conn.Close()
Return True
End Function
Note the name of the the worksheet is the name of the table for the oledb call.
There's a link to other ways of doing this:
http://blogs.msdn.com/b/erikaehrli/archive/2009/01/30/how-to-export-data-to-excel-from-an-asp-net-application-avoid-the-file-format-differ-prompt.aspx
If I have to revisit this problem I'll probably start there.

Connecting to SOTAMAS90 ODBC?

How do I connect to Mas90's file using their ODBC that they setup - SOTAMAS90? how do I do this in vb.net ?
I found this as an example - I have not tried it myself to know 100% sure if it works or not, nor do I profess myself as a vb.net programmer but it's at least something to try...
Imports System.Data
Imports Microsoft.Data.Odbc
' Database Connection
Public dbConn As OdbcConnection = Nothing
Public dbCmnd As OdbcCommand
Public dbReader As OdbcDataReader
Public dbConnStr As String
Public dbError As Exception
' Connect to MAS90 using ODBC; dbError stores the
' exception if any
Sub connectToDatabase(ByVal company As String, ByVal uid As String, ByVal pwd As String)
Dim dsn As String = "SOTAMAS90"
Dim timeout As String = "360"
' Build the connection string
dbConnStr = "DSN=" + dsn + _
";Directory=M:\MAS90" + _
";Prefix=M:\MAS90\soa\" + _
";ViewDLL=M:\MAS90\Home\" + _
";SERVER=NotTheServer" + _
";Company=" + company + _
";UID=" + uid + ";PWD=" + pwd + ";"
' Connect if not already
If (dbConn Is Nothing) Then
Try
dbConn = New OdbcConnection(dbConnStr)
dbConn.ConnectionTimeout = timeout
dbConn.Open()
dbError = Nothing
Catch ex As Exception
dbError = ex
dbConn = Nothing
End Try
End If
End Sub