Combining Formatting and Databinding from the database - sql-server

I have a set of labels in a DataRepeater. The labels get their values from a table in a SQL database (Let say GetSQLResults gets the data from SQL database and returns a DataTable).
Dim salesDataTable As DataTable = GetSQLResults()
And for the binding
SalesLabel.DataBindings.Add("Text", salesDataTable , "Sales")
Where SalesLabel is a label in the form and "Sales" is the name of the column in the database.
What I want to do is to apply let say US money formatting to this Sales value that comes from the database. I don't know how to combine formatting information with the command that I wrote above for DataBinding. It is a Windows Form application and I am using VB .Net. Any help will be appreciated.

The Binding class has a FormatString property which you should be able to feed the standard or custom format string you desire.
I think perhaps something like:
Dim salesBinding As Binding = new Binding("Text", salesDataTable , "Sales")
salesBinding.FormatString = "C"
SalesLabel.DataBindings.Add(salesBinding)
Would do the trick.

I tried this based on nkvu answer and a post at http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/c860168f-46e5-4786-a68d-ac69c6a7a248/
Dim WithEvents salesBinding As Binding
salesBinding = New Binding("Text", salesDataTable , "Sales")
SalesLabel.DataBindings.Add(salesBinding)
Private Sub salesBinding_Format(ByVal sender As Object, ByVal e As System.Windows.Forms.ConvertEventArgs) Handles salesBinding .Format
If e.Value Is DBNull.Value Then
Else
e.Value = Format(e.Value, "c")
End If
End Sub
This did the trick for me.

Related

Exception with sqlite database "no such table"

First of all I´m developing a database with autosuggest box. I´ve created a database with DB Browser and imported data. I was reading documentation in C# how connect database and retrieve data. The issue is show up an exception error:
enter image description here
I´ve connected the database in properties with content option. I paste the code:
Public NotInheritable Class METARTAF
Inherits Page
Dim dbpath As String = Path.Combine(ApplicationData.Current.LocalFolder.Path, "airportsdb.sqlite3")
Dim conn As SQLite.Net.SQLiteConnection = New SQLite.Net.SQLiteConnection(New WinRT.SQLitePlatformWinRT(), dbpath)
Dim airportinfo As List(Of String) = Nothing
Public Sub New()
' This call is required by the designer.
InitializeComponent()
End Sub
Private Sub AutoSuggestBox_TextChanged(sender As AutoSuggestBox, args As AutoSuggestBoxTextChangedEventArgs)
Dim datairport As New List(Of String)
Dim retrieve = conn.Table(Of flugzeuginfo)().ToList
If args.Reason = AutoSuggestionBoxTextChangeReason.UserInput Then
If sender.Text.Length > 1 Then
For Each item In retrieve
datairport.Add(item.IATA)
datairport.Add(item.ICAO)
datairport.Add(item.Location)
datairport.Add(item.Airport)
datairport.Add(item.Country)
Next
airportinfo = datairport.Where(Function(x) x.StartsWith(sender.Text)).ToList()
sender.ItemsSource = airportinfo
End If
Else
sender.ItemsSource = "No results..."
End If
End Sub
Private Sub AutoSuggestBox_SuggestionChosen(sender As AutoSuggestBox, args As AutoSuggestBoxSuggestionChosenEventArgs)
Dim selectedItem = args.SelectedItem.ToString()
sender.Text = selectedItem
End Sub
Private Sub AutoSuggestBox_QuerySubmitted(sender As AutoSuggestBox, args As AutoSuggestBoxQuerySubmittedEventArgs)
If args.ChosenSuggestion Is Nothing Then
stationidtxt.Text = args.ChosenSuggestion.ToString
End If
End Sub
Anyone could help about this?
Before you query or insert into a table, you should CREATE it. This tells SQLite what columns you have and suggests datatypes (on other rdbms's you get actual data type enforcement but SQLite does not do that). If this is your problem, you will want to spend some time with the SQLite documentation on data types and the ability to hook them into your application.
On the other hand, as you seem to be trying to retrieve data, this suggess one of two things is wrong. Either you care connecting to the wrong db (in which case SQLite will usually helpfully create an empty db for you!) or else you are specifying the wrong table.

Calling selection from Combo box on form to be used in SQL query

I have been able to figure out how to populate my combo box with information pulled from a SQL query. What I need to do now is take the item selected from that combo box and run another query with that info using a button. This is what I have so far.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myconn As New SqlClient.SqlConnection("server=myserver;UID=User;PWD=Password;database=myDB")
Dim myTable As New DataTable()
Dim myCmd As New SqlCommand()
Dim myAdapter As New SqlDataAdapter(myCmd)
myCmd.Connection = myconn
myCmd.Connection.Open()
myCmd.CommandText = "UPDATE myDB.<*Selected list from combo box*> SET example = x WHERE example = y"
myCmd.ExecuteNonQuery()
myCmd.Connection.Close()
MsgBox("Done!")
End Sub
As you can see the issue is the portion I have named <Selected list from combo box> I am not asking for answers on how to do this, I am asking that you all point me in the right direction if possible.
If I understand your question, I believe all you need to do is build a string for your update statement to concatenate the table name in. Something like this would be functional:
myCmd.CommandText = "UPDATE myDB." & listbox1.SelectedItem.Value & " SET example = x WHERE example = y"
One important thing you want to keep in mind though is that a bad value in your list box could cause you to a security vulnerability called SQL Injection. So within your button procedure you might want to do some validation checks to be absolutely sure that the value in listbox1.SelectedItem.Value is strictly a valid table name that you allow to be updated before just passing it along as a SQL command.

Tying ComboBox/NumericUpDown selections to an array?

I'm working on a VB project that has a lot of comboboxes and numericupdown items.
Lets say we have ComboBox1, 2, 3, 4, and 5; and we have NumericUpDown1, 2, 3, 4, 5.
When the user clicks the "Save" button, I want to save all of their selected combobox items and numericupdown numbers to a CSV file. Is there an elegant/automatic way to tie all of the .SelectedIndex and .Value for these items to an array so I can easily write the array out to a CSV?
The only way I know to do this so far is to manually associate each one with an array position:
Arr(0) = ComboBox1.SelectedIndex
Arr(1) = ComboBox2.SelectedIndex
...
Arr(5) = NumericUpDown1.Value
Arr(6) = NumericUpDown2.Value
...
etc.
This wouldnt be too bad, except I have a LOT of these items, and writing a line for each one seems silly. I'm new to VB, so this might be an obvious solution to some. Any ideas?
Having them bound to an array would be really handy because I also allow the user to Load a CSV file, which I would like to automatically populate the ComboBoxes and NumericUpDowns from the CSV values. The only way I know to do this is to manually move each array item to the respective combobox/numeric item when they click the Load file button:
ComboBox1.SelectedIndex = Arr(0)
ComboBox2.SelectedIndex = Arr(1)
...
NumericUpDown1.Value = Arr(5)
NumericUpDown2.Value = Arr(6)
...
etc.
Edit: Here is some application info as requested...
The CSV file that can be saved/loaded looks like this:
#"Device Info","123456","asdfgh","0000","1.0x","1"
000F,0000,0032,0000,00C8,0001,0078,0101,0000,0001,0000,0001
010F,0078,0000,0103,0001,0000,000A,0005,0007,0006,0000
0001,000A,000A,000A,000A,0005,0005,0005,0002
...etc
The header line just has serial number, version, and other misc info; it is automatically generated by the target device. All of the other lines are configuration setpoints that the target device reads in and automatically configures itself. I'm writing this PC program to be able to edit (and create from scratch) these configuration CSV files with a nice GUI interface. Each item is tied to a specific setpoint, such as 000F = Language, 0032 = System Frequency, 00C8 = System Voltage, etc. The easiest way I saw to make this configuration program was to use numeric entry and drop-down comboboxes that the user can select what they want. Each NUD and CBOX equates to one of the CSV file data fields.
You can use Controls.Find() to get a reference to the desired control based on an index value. Here's a quick example to demonstrate what I mean:
For i As Integer = 1 To 30
Dim matches() As Control = Me.Controls.Find("NumericUpDown" & i, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is NumericUpDown Then
DirectCast(matches(0), NumericUpDown).Value = i
End If
Next
You can incorporate code like that into the load/save routines.
I would use binary serialization. This eliminates the need to format strings or xml when saving control properties. Similar to Plutonix's solution, it only works on certain types of control. However, it can be modified to work on any type of control - but only supports a single property to be loaded for each control. It will work on all controls of type X instead of controls named xName. You can add further restrictions by grouping the controls to be serialized in a panel or other means.
Make a new Form called Form1. Add some NumericUpDowns, TextBoxes, and ComboBoxes. Put some values in the ComboBoxes at design time, otherwise calling loadState() in Form_Load will be meaningless. However, loadState() can be called whenever (i.e. after the comboboxes have been populated).
You will need to import these two namespaces:
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
In your class:
Private Shared stateFileName As String = "SavedState.bin"
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
saveState(Me)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
loadState(Me)
End Sub
And these are the methods you will use to save and load states. The save state method:
Private Shared Sub saveState(instance As Form)
Dim controlProperties As Dictionary(Of String, Object) =
instance.Controls.OfType(Of Control).ToDictionary(Of String, Object)(
Function(c) c.Name,
Function(c)
' You can support different types of controls here too
If TypeOf c Is NumericUpDown Then
Return CType(c, NumericUpDown).Value
ElseIf TypeOf c Is ComboBox Then
Return CType(c, ComboBox).SelectedIndex
Else
' All other controls get their text property saved
' .Text is a property of Control
Return c.Text
End If
End Function)
Using myFileStream As Stream = File.Create(stateFileName)
Dim serializer As New BinaryFormatter
serializer.Serialize(myFileStream, controlProperties)
End Using
End Sub
The load state method:
Private Shared Sub loadState(instance As Form)
If File.Exists(stateFileName) Then
Using myFileStream As Stream = File.OpenRead(stateFileName)
Dim deserializer As New BinaryFormatter()
Dim controlProperties = CType(deserializer.Deserialize(myFileStream), Dictionary(Of String, Object))
For Each c As Control In instance.Controls
If controlProperties.ContainsKey(c.Name) Then
' You can support different types of controls here too
If TypeOf c Is NumericUpDown Then
CType(c, NumericUpDown).Value = CDec(controlProperties(c.Name))
ElseIf TypeOf c Is ComboBox Then
CType(c, ComboBox).SelectedIndex = CInt(controlProperties(c.Name))
Else
c.Text = controlProperties(c.Name).ToString()
End If
End If
Next
End Using
End If
End Sub
You should add exception handling, and note that a binary file is not meant to be edited by a human without the assistance of a machine.

VB.NET issue loading textboxes with data from SQL Server

I have some textboxes (using VS2010) I'm trying to populate with values from columns in a SQL Server database based on what item someone selects from a combobox. At first I was able to display the values for the first item in the combobox, but now nothing at all displays when I debug. Code:
Private Sub loadfields(sender As System.Object, e As System.EventArgs) Handles client_selection_combobox.SelectedIndexChanged
Using myconnection As New SqlConnection("connection string")
Dim loadfields As String = "SELECT company FROM ClientFileDatabase WHERE ClientFileDatabase.File_Name=#company;"
Dim loadfields_sqlcommand As New SqlCommand(loadfields, myconnection)
loadfields_sqlcommand.Parameters.Add("#company", SqlDbType.NVarChar)
loadfields_sqlcommand.Parameters("#company").Value = client_selection_combobox.SelectedIndex.ToString
Dim loadfields_dataadapter As New SqlDataAdapter
loadfields_dataadapter.SelectCommand = loadfields_sqlcommand
Dim loadfields_dataset As DataSet = New DataSet()
loadfields_dataadapter.Fill(loadfields_dataset, "ClientFileDatabase")
Dim loadfields_dataview = New DataView(loadfields_dataset.Tables("ClientFileDatabase"))
companyname_textbox.DataBindings.Clear()
companyname_textbox.DataBindings.Add("Text", loadfields_dataview, "Company")
taxid_textbox.DataBindings.Clear()
taxid_textbox.DataBindings.Add("Text", loadfields_dataview, "TaxIDNumber")
accountmanager_textbox.DataBindings.Clear()
accountmanager_textbox.DataBindings.Add("Text", loadfields_dataview, "AccountManager")
etc...
End Using
End Sub
I've also tried using the SelectedValueChanged and SelectionChangeCommitted event handlers to no avail. Also tried using a refresh after setting the databindings, didn't help. Any advice welcome, thanks!
I personally like to use datatables, I find them easier to work with. I'm sure you will have more code to check to make sure dt.rows.count > 0 before actually attempting to work with the data, but here is how I would do it.
Dim loadfields_dataadapter As New SqlDataAdapter
Dim dt As New DataTable
loadfields_dataadapter.Fill(dt)
companyname_textbox.text = dt.Rows(0).Item("Company")
taxid_textbox.text = dt.Rows(0).Item("TaxIDNumber")
accountmanager_textbox.text = dt.Rows(0).Item("AccountManager")
Also, keep in mind that NULL fields in the database can cause runtime errors, so you may have to check for those as well.

ADO.NET: Need help to understand the basics of 'Dataset'

As context, I am new to ADO.NET and have been using 'Programming ADO.NET 2.0' by David Sceppa to help build my knowledge.
I have been trying to understand the Dataset object but think I may have completely misunderstood the point and am looking for guidance.
As an example, I have built a really simple Form with a combobox with an aim of filling the combobox with the names of people in a database ("MyDatabase"). The following code works fine for me:
Private Sub frmEmployee_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim strConn, strSQL As String
strConn = "Data Source=.\SQLExpress;Initial Catalog=MyDatabase;Integrated Security=True;"
strSQL = "SELECT LastName, FirstName FROM EmployeeTable"
Dim da As New SqlDataAdapter(strSQL, strConn)
Dim ds As New DataSet()
da.Fill(ds, "AllEmployeesList")
For i As Integer = 0 To ds.Tables("AllEmployeesList").Rows.Count - 1
Dim row As DataRow = ds.Tables("AllEmployeesList").Rows(i)
cbAllEmployeesList.Items.Add(row("LastName") & ", " & row("FirstName"))
Next
End Sub
Now suppose I have a button on my Form ('GetAge') which is designed to retrieve the age of the employee selected in the combobox from the dataset "AllEmployeesList" and display in a TextBox on the same Form.
The bit I really don't understand is how I can interact with the original dataset that I have created to get the age? It seems to me that the dataset is only in memory during the Load event? If my dataset persists beyond the Load event then where can I find it?
My understanding is that a dataset object is an offline cache of data and has no links to the underlying database.This is useful as it allows you to manipulate the data without keeping a connection open and later on you can submit any changes in the Dataset back to the original database. So once I have built my dataset in the Load event how can I then further interact with it?
I suspect there is a large error in my understanding of what a Dataset object is. Can anybody set me straight?
Thanks to anybody who can help
Alex
A data set can hold multiple data tables, so if you fill that same dataset that already has the "AllEmployeesList" datatable filled, you can fill another datatable with the age under another table name. Picture a dataset as an in-memory database.
You can store the dataset in the datasource of the datagrid view, or make it a form level variable so you can interact with it without casting anytime.
Another part of datasets to be aware of is you can make a design-time dataset so things are more type-safe and explicit.
You seem to have a good grasp on the concept and reason of the DataSet. Your question is really more about managing state than the ins and outs of a DataSet.
You never stated if you are using WebForms, WinForms, or something else. If you're using WinForms, promote the DataSet to be a member variable of the form. It'll stay in memory as long as the form is open.
If you're using WebForms, then this becomes much more complex. This is a good overview to get you started.
Unless your application needs to operate in a disconnected mode, it's not strictly necessary nor always a good idea to cache database data on the client. In this case, you're extracting the age data for all employees without knowing whether you'll ever need it for any of them.
I would just pull the first and last name data (probably using SqlCommand.ExecuteReader) to populate the list box, and then make a separate call to the database to get the age if the user clicks the button. I posted an example of something similar using SqlCommand.ExecuteScalar on your other question.
When a Function or Sub has finished executing, all the variables you declared with the Dim statement will be gone. If you want a variable to exist as long as your form exists then declare a variable outside your Sub/Function:
Public Class frmEmployee
Private dsEmployeeList As DataSet
Private Sub frmEmployee_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
dsEmployeeList = New DataSet()
da.Fill(dsEmployeeList, "AllEmployeesList")
...
End Sub
Private Sub GetAge_Click(sender As Object, e As EventArgs) Handles GetAge.Click
Dim iRowIndex As Integer
iRowIndex = cbAllEmployeesList.SelectedIndex 'In this case the rownumber is the same as the index of the selected item in the combobox
'Check to see if an item from the combobox has been selected
If iRowIndex >= 0 Then
txtEmployeeAge.Text = dsEmployeeList.Tables("AllEmployeesList").Rows(iRowIndex).Item("Age").ToString()
End If
End Sub
This code might work but it's not a recommended solution. Like the previous poster said: only get the data you want, when you need it.
You should bind the DataGrid to the DataSet. When reqd you can retrieve the DataSet back from the DataGrid.DataSource and cast it to a DataSet.
Edit: Added sample code
DataSet ds = new DataSet();
// Code to populate DataSet from your DB
...
...
Assign ds to the datasource of data grid
this.dataGridView1.DataSource = ds;
To retrieve the dataset use the code below
DataSet retrievedFromGrid = (DataSet)this.dataGridView1.DataSource;
However, if you need to perform operations on this DataSet a number of times and memory is not an issue, I would suggest you store it in a class variable to avoid the overhead of casting in a DataSet object from the DataGrid again and again.

Resources