Retrieve excel file stored in sql server using vb.net - sql-server

I have a desktop application using vb.net, to process some excel files, those files are stored in a sql server database.
Here is the code I have:
Try
conDCS.Open()
comDCS.Connection = conDCS
comDCS.CommandType = CommandType.Text
comDCS.CommandText = "select top 2 [Filename], [File] " & _
"from tblFiles (nolock) " & _
"where ([Filename] like 'DIG%' or [Filename] like 'FAC%') and " & _
"(UploadDate>='" & FromDate & "' and UploadDate<'" & ToDate & "')"
comDCS.ExecuteNonQuery()
rdrDCS = comDCS.ExecuteReader
If rdrDCS.HasRows Then
While rdrDCS.Read
Dim imageInBytes As Byte() = rdrDCS(1)
Dim memoryStream As System.IO.MemoryStream = New System.IO.MemoryStream(imageInBytes, False)
Dim image As System.Drawing.Image = System.Drawing.Image.FromStream(memoryStream)
image.Save(TempPath & rdrDCS(0))
End While
ToProcess = True
End If
rdrDCS.Close()
Catch ex As Exception
ToProcess = False
MessageBox.Show("Error accessing to the files: " & ex.Message)
Finally
conDCS.Close()
End Try
I'm getting: "Parameter is not valid" in this line:
Dim image As System.Drawing.Image = System.Drawing.Image.FromStream(memoryStream)
I have understood that this error is related to an invalid image data, but I can't figure it out what could be the problem.
imageInBytes has a length of 41473. And some items of the array have zero as value.
What could be wrong here, or perhaps, can anyone supply a working code to achieve this?

We use a common method to save a file from a database field to a file:
Public Function FieldToFile(ByVal sFileName As String, ByVal theField As Object) As Boolean
' Exceptions are handled by the caller
If theField IsNot DBNull.Value Then
Using oStream As New System.IO.FileStream(sFileName, IO.FileMode.Create, IO.FileAccess.Write)
If oStream IsNot Nothing Then
Dim aBytes As Byte()
aBytes = DirectCast(theField, Byte())
oStream.Write(aBytes, 0, aBytes.Length)
oStream.Close()
End If
End Using
End If
Return True
End Function
This can be called as follows:
Call FieldToFile(someFileName, rdrDCS(1)

Related

saving PDF/word/jpeg files as image in sql server database

I am working on an existing database structure. The database has a field to store PDF/Word/Jpeg files as images. Unfortunately I cannot change the database field format.
I am able to successfully read the pdf stored as image and display the pdf file, but cannot get to insert the image in database. I tried different version from many sites, but could not get it to work.
Here is my current code
Dim sql As String
Dim da As New OleDb.OleDbDataAdapter
Dim sqlquery As New OleDb.OleDbCommand
Dim sqlconn As New OleDb.OleDbConnection
Try
sqlconn.ConnectionString = dbConnectStr1
sqlquery.Connection = sqlconn
sqlconn.Open()
For cnt1 = 0 To dgv1.Rows.Count - 1
Dim fInfo As New FileInfo(dgv1.Rows(cnt1).Cells(3).Value)
Dim numBytes As Long = fInfo.Length
Dim fStream As New FileStream(dgv1.Rows(cnt1).Cells(3).Value, FileMode.Open, FileAccess.Read)
Dim br As New BinaryReader(fStream)
Dim data As Byte() = br.ReadBytes(CInt(numBytes))
br.Close()
fStream.Close()
sql = "INSERT INTO " & attachmentTbl & " (DocID, DocName, DocType, DocFile, DocLength) " &
"VALUES ('" & dgv1.Rows(cnt1).Cells(0).Value & "', '" & dgv1.Rows(cnt1).Cells(1).Value & "', '" & dgv1.Rows(cnt1).Cells(2).Value & "', " data ", " & numBytes & ")"
sqlquery.CommandText = sql
'"VALUES (#DocID, #DocName, #DocType, #DocFile, #DocLength)"
'sqlquery.OleDbParameter.Add(New System.Data.SqlClient.SqlParameter("#DocID", dgv1.Rows(cnt1).Cells(0).Value))
'sqlquery.Parameters.Add(New System.Data.SqlClient.SqlParameter("#DocName", dgv1.Rows(cnt1).Cells(1).Value))
'sqlquery.Parameters.Add(New System.Data.SqlClient.SqlParameter("#DocType", dgv1.Rows(cnt1).Cells(2).Value))
'sqlquery.Parameters.Add(New System.Data.SqlClient.SqlParameter("#DocFile", data))
'sqlquery.Parameters.Add(New System.Data.SqlClient.SqlParameter("#DoDocLength", numBytes))
'sqlquery.ExecuteNonQuery()
Next
sqlconn.Close()
Catch ex As Exception
errorFlag = True
MessageBox.Show("Error#060 " & ex.Message)
Exit Sub
End Try
Also, Is there a way to get the file type displayed in windows explorer. I.e. for .pdf file the display with would "adobe acrobat document" .xls file would be "Microsoft excel worksheet"
I tried using the below code but I don't get the above stuff
extn = Path.GetExtension(txtFileName.Text)
Dim regKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(extn)
If Not regKey Is Nothing Then
Dim ct As Object = regKey.GetValue("Content Type")
If Not ct Is Nothing Then
extn = ct.ToString()
End If
End If
Appreicate your help.

Database only adds (x) amount of rows before error system resources exceeded

I am having a problem with my code where i am only able to add so many lines of text before i get an error "system resources exceeded".
This is my code:
Dim x As Integer = MsgBox("Update Record?", MsgBoxStyle.YesNo, "Are you sure?")
If x = MsgBoxResult.Yes Then
Dim accessconn As New _
System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & "MyDB.accdb")
Dim com As System.Data.OleDb.OleDbCommand
accessconn.Close()
Try
For Each strLine As String In TextBox1.Text.Split(vbNewLine)
accessconn.Open()
Dim str As String
Dim dr As OleDbDataReader
str = "SELECT * FROM Table4 WHERE MD5='" & strLine & "'"
Dim cmd As OleDbCommand = New OleDbCommand(str, accessconn)
dr = cmd.ExecuteReader
If dr.Read() Then
Label2.Text = Label2.Text + 1
Else
accessconn.Open()
com = New System.Data.OleDb.OleDbCommand("INSERT INTO Table4(MD5) VALUES('" & strLine & "')", accessconn)
com.ExecuteReader(CommandBehavior.CloseConnection)
Label3.Text = Label3.Text + 1
com.Dispose()
accessconn.Close()
End If
Next
accessconn.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
MsgBox("Done")
PopulateGridview4()
End If
I would like to be able to add unlimited rows of text to the database if possible. Please Help.
You should change your code to something like the following. Note that
Everything that returns an object like OleDbConnection, OleDbCommand, or OleDbDataReader is wrapped in a Using block. These objects all implement the IDisposable interface, which means they should be cleaned up as soon as you're done with them.
Also note that your INSERT did not return any data, so you should use ExecuteNonQuery instead of ExecuteReader.
Finally, please don't get into the habit of putting Try/Catch/End Try blocks around everything. You were displaying the exception (you displayed ex.ToString, which is a good thing), but you then ignored the exception. As a good general rule, don't catch exceptions unless you can fix them.
Code:
Dim x As Integer = MsgBox("Update Record?", MsgBoxStyle.YesNo, "Are you sure?")
If x = MsgBoxResult.Yes Then
Using accessconn As New _
System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & "MyDB.accdb")
accessconn.Open()
For Each strLine As String In TextBox1.Text.Split(vbNewLine)
Dim str As String = "SELECT * FROM Table4 WHERE MD5='" & strLine & "'"
Using cmd As OleDbCommand = New OleDbCommand(str, accessconn)
Using dr As OleDbDataReader = cmd.ExecuteReader
If dr.Read() Then
Label2.Text = Label2.Text + 1
Else
Using com As OleDbCommand = New System.Data.OleDb.OleDbCommand("INSERT INTO Table4(MD5) VALUES('" & strLine & "')", accessconn)
com.ExecuteNonQuery()
End Using
Label3.Text = Label3.Text + 1
End If
End Using
End Using
Next
MsgBox("Done")
PopulateGridview4()
End Using
End If
P.S. you could probably have made this a little less indented by using If x <> MsgBoxResult.Yes Then get out, but I don't know if this is inside of a Sub or Function, so "get out" could be different.

how to store values data reader values from database into an array? vb.net

Is there a way to store data from a sql data reader values to an array?
this is my code
Dim machines() As Integer
Sub machine_entire()
Try
'getting lines from the database
If conn.State = ConnectionState.Closed Then conn.Open()
With cmd
.Connection = conn
.CommandText = "select machineID from tbl_prod_machine where lineID = '" & lineID & "' order by machineID asc"
End With
dr = cmd.ExecuteReader
If dr.HasRows Then
While dr.Read
machines = {dr.GetInt32(dr.GetOrdinal("machineID"))}
End While
dr.Close()
End If
dr.Close()
Catch ex As DataException
MessageBox.Show(ex.Message, ex.GetType.ToString)
Catch ex As SqlException
MessageBox.Show("Sql Server Error # " & ex.Number & ": " & ex.GetType.ToString)
End Try
End Sub
thank you! for the help
If it's just a list of integer, I would use a List(Of )
Dim machines As New List(Of Integer)
After than you just add the values to the list
machines.Add(dr.GetInt32(dr.GetOrdinal("machineID")))
Side note, I would rename your function and make it return the list. In this context, lineId and machines do not seem a good idea to be outside of the function.
Function GetMachineIdsFromLine(ByVal lineId) As List(Of Integer)
Also, it is recomended to open connection only when needed and close them as soon as possible.

How to load csv files from the internet into an Access database?

I have the following array that contains ticker symbols: Public Shared tickerArray() As String = {"GOOG", "AAPL", "V", "MSFT"}. I need to use this loop: For Each tickerValue In Form1.tickerArray to load the csv file for each ticker symbol into one large table in Microsoft Access. The csv files are located at "http://ichart.yahoo.com/table.csv?s=" & tickerValue. I also need the respective ticker symbol to be loaded into each line of the table that is imported from the csv file in order to make each line unique. So the columns in the database should be: "Ticker, Date, Open, High, Low, Close, Volumne & Adj Close".
I've found information about loading a local csv file into Access but I can't seem to figure out how to load csv files from the internet into Access through vb.net.
Also, I will need to update this table frequently so I need to only insert new unique lines from the csv file. No duplicates.
Any suggestions? Thanks!
UPDATE:
Here is the code I have so far.
Imports System.Data
Imports System.Data.OleDb
Imports System.Net
Imports System.IO
Public Class Form1
Public Shared tickerArray() As String = {"GOOG", "AAPL", "V", "MSFT"}
Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUpdate.Click
Dim myConnection As OleDbConnection
Dim DBpath As String =
Dim sConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & DBpath & ";Persist Security Info=True"
myConnection = New OleDbConnection(sConnectionString)
myConnection.Open()
Dim strURL As String
Dim strBuffer As String
For Each tickerValue In Form1.tickerArray
'Creates the request URL for Yahoo.
strURL = "http://ichart.yahoo.com/table.csv?s=" & tickerValue
strBuffer = RequestWebData(strURL)
'Create array.
Dim sReader As New StringReader(strBuffer)
Dim List As New List(Of String)
Do While sReader.Peek >= 0
List.Add(sReader.ReadLine)
Loop
Dim lines As String() = List.ToArray
sReader.Close()
For Each Line In lines.Skip(1)
MsgBox(Line)
Dim myInsert As String = TextToInsert(Line, tickerValue)
Dim cmd As New OleDbCommand(myInsert, myConnection)
cmd.ExecuteNonQuery()
Next
Next
End Sub
Function TextToInsert(ByVal inputString As String, ByVal ticker As String)
Dim Dt As String = inputString.Split(",")(0).Trim
Dim Open As String = inputString.Split(",")(1).Trim
Dim High As String = inputString.Split(",")(1).Trim
Dim Low As String = inputString.Split(",")(1).Trim
Dim Close As String = inputString.Split(",")(1).Trim
Dim Volume As String = inputString.Split(",")(1).Trim
Dim Adj_Close As String = inputString.Split(",")(1).Trim
Dim SQLstr As String
SQLstr = "INSERT INTO Historical (Ticker, Date, Open, High, Low, Close, Volume, Adj Close) " & "VALUES (" & "'" & ticker & "','" & Dt & "','" & Open & "','" & High & "'," & "'" & Low & "','" & Close & "','" & Volume & "','" & Adj_Close & "'" & ")"
Return SQLstr
End Function
Private Function RequestWebData(ByVal pstrURL As String) As String
Dim objWReq As WebRequest
Dim objWResp As WebResponse
Dim strBuffer As String
'Contact the website
objWReq = HttpWebRequest.Create(pstrURL)
objWResp = objWReq.GetResponse()
'Read the answer from the Web site and store it into a stream
Dim objSR As StreamReader
objSR = New StreamReader(objWResp.GetResponseStream)
strBuffer = objSR.ReadToEnd
objSR.Close()
objWResp.Close()
Return strBuffer
End Function
End Class
I get error code "OleDBException was unhandled. Syntax error in INSERT INTO statement." at line cmd.ExecuteNonQuery() Please help!
you may use the System.Data.OleDb Namespace to define function to make insert into the db.
Something like (in a very rough way):
Dim myConnection As OleDbConnection
Dim sConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" & DBpath & ";Persist Security Info=True"
myConnection = New OleDbConnection(sConnectionString)
myConnection.Open()
Then make a cycle on each line in the csv
Dim myInsert as String= functionTextToInsert(inputString)
Dim cmd As New OleDbCommand(myInsert, myConnection)
cmd.ExecuteNonQuery()
The functionTextToInsert(ByVal inputString as string) is a function that converts a line from the csv in a insert string: "max;min;vol" -> "Insert into MYTABLE (Column_01,Column_02,Column_03) VALUES (max,min,vol);"
Try this:
Writing large number of records (bulk insert) to Access in .NET/C#
I've never worked with DAO, so I can't be much help here, but...
if this MSSQL syntax works on MS ACCESS, use a command object and pass it a parameter containing your csv as a varchar(max), or similar access data type, which will the content of the CSV from your app:
BULK
INSERT mytable
FROM #myCSVstring
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)
GO
Two things, the SO post states that DAO is a lot faster, and your terminators may be different, but I'd start with these.
I think the previous answers are unnecessarily complicated. All you need to do it send an XMLHTTP request. That fetches the CSV data as a string, which can then be parsed into a table.
Below is a VBA subroutine that does that. Documentation of where I found the techniques is in the code comments. I've run this in Access 2019, and it works.
The modifications of the data indicated in the question can be performed before or after inserting the data into the table.
Sub pImportOnlineCsvAsTable(sURL As String, sTableName As String, Optional sKey As String)
' Download a CSV file from the Internet and parse it into an Access table (all strings).
' Adapted from "www.stackoverflow.com/questions/52142757/vba-download-csv-from-a-link/#52175815"
' This shows how to download an online CSV file into an ADO stream, then save it as a local file.
' and "www.stackoverflow.com/questions/33860833/convert-adodb-binary-stream-to-string-vba/#33883789"
' This shows I don't need the stream, but can use the CSV data as a string and parse it into a table.
' Documentation on "XMLHTTP" object:
' "https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms760305(v=vs.85)"
Dim oWinHttpReq As Object
Dim oDB As Database
Dim sSQL As String, sCSVdata As String, _
asCSVrows As Variant, asCSVfields As Variant, _
nCSVrows As Long, nCSVfields As Integer, _
nCountRows As Long, nCountFields As Integer
Set oDB = CurrentDb()
Set oWinHttpReq = CreateObject("Microsoft.XMLHTTP")
oWinHttpReq.Open "get", sURL, False
oWinHttpReq.send
If oWinHttpReq.status = 200 Then
sCSVdata = oWinHttpReq.ResponseText
asCSVrows = Split(sCSVdata, Chr(10))
nCSVrows = UBound(asCSVrows) + 1
asCSVfields = Split(asCSVrows(0), ",")
nCSVfields = UBound(asCSVfields) + 1
sSQL = ""
For nCountFields = 0 To (nCSVfields - 1)
sSQL = sSQL & "[" & asCSVfields(nCountFields) & "] varchar(255)" & _
IIf(nCountFields = nCSVfields - 1, "", ", ")
Next
sSQL = "create table [" & sTableName & "] (" & sSQL & ");"
oDB.Execute (sSQL)
For nCountRows = 1 To (nCSVrows - 1)
asCSVfields = Split(asCSVrows(nCountRows), ",")
sSQL = ""
For nCountFields = 0 To (nCSVfields - 1)
sSQL = sSQL & """" & asCSVfields(nCountFields) & """" & _
IIf(nCountFields = nCSVfields - 1, "", ", ")
Next
sSQL = "insert into [" & sTableName & "] values (" & sSQL & ");"
oDB.Execute (sSQL)
Next
If sKey <> "" Then _
oDB.Execute "alter table [" & sTableName & "] add primary key ([" & sKey & "]);"
End If
Set oWinHttpReq = Nothing
Set oDB = Nothing
End Sub ' pImportOnlineCsvAsTable()

How to return database fields from checkbox selection?

the code below returns the fields of a given table ("Employee"), but I need to return the fields of ALL the tables in the given database, is this possible? My assumption is a For loop which loops round the tables in the database and prints the corresponding fields but my efforts seem to be in vain
Public Sub getDbFields()
Dim i As Integer
Dim dbcon As New System.Data.OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = " & dblocation & _
"\" & dbname)
Try
dbcon.Open()
dbDt = dbcon.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Columns, New Object() _
{Nothing, Nothing, "Employee", Nothing})
For i = 0 To dbDt.Rows.Count - 1
'compile lbtables with a list of available tables from the database
newLine()
frmMain.lstTables.Items.Add(dbDt.Rows(i)!COLUMN_NAME.ToString())
Next
Catch ex As Exception
MessageBox.Show(ex.Message.ToString(), "Data Load Error", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
End Try
End Sub
This routine will be fired from the selection of a checkbox
This will return all columns on a database
Using con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + dblocation + "\" + dbname)
con.Open()
Dim schema as DataTable = con.GetSchema("COLUMNS")
Dim dr as DataRow
For Each dr in schema.Rows
Dim tablename as string = dr("TABLE_NAME").ToString()
if Not tablename.StartsWith("MSys") then
Console.WriteLine(dr("TABLE_NAME").ToString() + " " + dr("COLUMN_NAME").ToString())
End if
Next
End Using
Please note that the bang (!) syntax is not allowed in vb.net.
Also your code could work if you change
dbDt = dbcon.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Columns, New Object() _
{Nothing, Nothing, Nothing, Nothing})
and this line
frmMain.lstTables.Items.Add(dbDt.Rows(i)("COLUMN_NAME").ToString())

Resources