The Issue:
I populate a checkbox list from a SQL table:
public static List<string> populateCheckBoxes(string type)
{
List<string> items = new List<string>();
items.Add("");
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand sqlcmd;
switch (type)
{
case "referralorsignposting":
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment WHERE type = 'Referral or Signposting' ORDER BY order_no, name", conn);
break;
case "actionstaken":
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment WHERE type = 'Actions Taken' ORDER BY order_no, name", conn);
break;
default:
sqlcmd = new SqlCommand("SELECT * FROM SWApp_List_Equipment", conn);
break;
}
SqlDataAdapter da = new SqlDataAdapter(sqlcmd);
DataTable dt = new DataTable();
da.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
items.Add(dr["name"].ToString());
CheckboxIDRecord = dr["id"].ToString();
//items.Add(dr["VisitTime"] + " " + dr["PropPostcode"]);
}
return items;
}
I have iterated through each value that is selected in the "checkboxlist" and this inserts each value selected:
foreach (var item in saw.actionsTakenCheckBoxList)
{ //ADD ACTIONS AND REFERRAL
SqlCommand add = new SqlCommand("INSERT INTO SWApp_CheckboxAnswers (SW_ID, Checkbox_ID, Checkbox_Section, Checkbox_Type, Checkbox_Answer) VALUES(#SW_ID,#Checkbox_ID,#Checkbox_Section,#Checkbox_Type,#Checkbox_Answer) ");
add.CommandType = CommandType.Text;
add.Connection = sqlcon;
add.Parameters.AddWithValue("#SW_ID", "");
add.Parameters.AddWithValue("#Checkbox_ID", "");
add.Parameters.AddWithValue("#Checkbox_Section", "");
add.Parameters.AddWithValue("#Checkbox_Type", "");
add.Parameters.AddWithValue("#Checkbox_Answer", "");
add.Parameters["#SW_ID"].Value = saw.EntryID.ToString();
add.Parameters["#Checkbox_ID"].Value = CheckboxIDRecord.ToString();
add.Parameters["#Checkbox_Section"].Value = "SmokeDetectionReferral";
add.Parameters["#Checkbox_Type"].Value = "";
add.Parameters["#Checkbox_Answer"].Value = item.ToString();
sqlcon.Open();
add.ExecuteNonQuery();
sqlcon.Close();
}
As you can see what i have currently tried only inputs the ID for the first value selected in the Checkboxlist.
The Aim:
The aim is to have insert the value of the checkbox which is "name" and also the "id" of the each item.
Research:
I tried following this article to put the items into an array but ended up with a 'Array was out of bounds of the index' which led me to the second article.
Pass items from checkboxlist to SQL Server table
Index was out of bounds of array? c# forms
I would appreciate any guidance with this. Thanks.
I see several issues, rather than attempting to rectify them here is a proposal for how to work this out.
The overall picture can be seen in my MSDN code sample on CheckedListBox and SQL-Server which includes an sql script to generate the datbase and data.
https://code.msdn.microsoft.com/Working-with-CheckedListBox-3b765442?redir=0
Taken from the link above in Operations.cs, this method gets our data (next code block populates the CheckedListBox)
/// <summary>
/// Get all records to show in the CheckedListBox
/// </summary>
/// <returns></returns>
public DataTable GetAll()
{
var dt = new DataTable();
using (SqlConnection cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (SqlCommand cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText = "SELECT id, Description, Quantity, CheckedStatus FROM Products ---WHERE (Quantity > 0)";
cn.Open();
dt.Load(cmd.ExecuteReader());
}
}
return dt;
}
Form code
/// <summary>
/// Load CheckedListBox from database table
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
var ops = new Operations();
// read data from database table
var dt = ops.GetAll();
int LastIndex = 0;
/*
* Here we iterate the rows in the DataTable while in
* CoursesCodeSample I set the DataSource of the CheckedListBox
* to the DataTable. The method shown here has always been the
* way to go as many indicated that since the DataSource property
* of the CheckedListBox is not documented it could go away, well
* many years later it's still here so guess what, it's okay.
*/
foreach (DataRow row in dt.Rows)
{
checkedListBox1.Items.Add(new CheckListBoxItem()
{
Description = row.Field<string>("Description"),
PrimaryKey = row.Field<int>("id"),
Quantity = row.Field<int>("Quantity"),
IsDirty = false
});
LastIndex = checkedListBox1.Items.Count - 1;
checkedListBox1.SetItemChecked(LastIndex, row.Field<bool>("CheckedStatus"));
}
checkedListBox1.ItemCheck += CheckedListBox1_ItemCheck;
}
From Opertions.cs - insertion method
public void Insert(List<CheckListBoxItem> items)
{
// optionally used for obtaining new primary key
//int newIdentifier;
using (SqlConnection cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (SqlCommand cmd = new SqlCommand { Connection = cn })
{
// uncomment ending select statement and use commented to get new primary key
cmd.CommandText = "INSERT INTO Products " +
"([Description],Quantity,CheckedStatus) " +
"VALUES (#Description,#Quantity,#CheckedStatus); " +
"-- SELECT CAST(scope_identity() AS int);";
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#Description", SqlDbType = SqlDbType.NVarChar });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#Quantity", SqlDbType = SqlDbType.Int });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#CheckedStatus", SqlDbType = SqlDbType.Bit });
cmd.Parameters.Add(new SqlParameter()
{ ParameterName = "#CategoryIdentifier", SqlDbType = SqlDbType.Int });
cn.Open();
foreach (CheckListBoxItem item in items)
{
cmd.Parameters["#Description"].Value = item.Description;
cmd.Parameters["#Quantity"].Value = item.Quantity;
cmd.Parameters["#CheckedStatus"].Value = item.Checked;
//newIdentifier = (int)cmd.ExecuteNonQuery();
if ((int)cmd.ExecuteNonQuery() > -1)
{
// inserted
}
else
{
// failed
}
}
}
}
}
The above is basic, the commented out code shows (if needed) how to get the new primary key.
Call the method above
private void iterateButton_Click(object sender, EventArgs e)
{
var items = new List<CheckListBoxItem>();
for (int index = 0; index < checkedListBox1.Items.Count; index++)
{
if (((CheckListBoxItem)checkedListBox1.Items[index]).IsDirty)
{
items.Add(new CheckListBoxItem()
{
PrimaryKey = ((CheckListBoxItem)checkedListBox1.Items[index]).PrimaryKey,
Checked = checkedListBox1.GetItemChecked(index),
Description = ((CheckListBoxItem)checkedListBox1.Items[index]).Description
});
}
}
if (items.Count >0)
{
Ops.Insert(items);
}
}
Finally the class used to populate the CheckedListBox
namespace CheckListBoxFromSQL_Server
{
public class CheckListBoxItem
{
/// <summary>
/// Identifier for database table
/// </summary>
public int PrimaryKey;
/// <summary>
/// Display member for CheckedListBox and a field in the table
/// </summary>
public string Description;
public int Quantity;
/// <summary>
/// Indicates the checked state in the database table and for setting a Checked item in the CheckedListbox
/// </summary>
public bool Checked;
/// <summary>
/// Used to determine if a item changed after loaded in the CheckedListBox
/// </summary>
public bool IsDirty;
public override string ToString() { return Description; }
}
}
Hope this is helpful
I implemented a dictionary for the items to be placed into the checkboxlist. This allows me to use the value within the checkbox items and then use the Key in the INSERT to the SQL DB.
Dictionary<string, string> referral = new Dictionary<string, string>();
On form load populate the checkboxlist with items from dictionary.
private void Section3_Load(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("select Id, name from SWApp_List_Equipment WHERE type = 'referral or signposting' ORDER BY order_no,name", conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
referral.Add(dr["id"].ToString(), dr["name"].ToString());
}
}
foreach (KeyValuePair<string, string> refs in referral)
{
box = new CheckBox();
box.Text = refs.Value.ToString();
actionsTakenCheckBoxList.Items.Add(box.Text);
box.CheckedChanged += new EventHandler(this.CheckedChange);
}
}
Insert values into table on Close Button of form.
private void closeButton_Click(object sender, EventArgs e)
{
using (SqlConnection sqlcon = new SqlConnection(connectionString)) {
//summary
foreach (var item in actionsTakenCheckBoxList.CheckedItems.OfType<string>().ToList())
{
//ADD ACTIONS AND REFERRAL
SqlCommand add = new SqlCommand("INSERT INTO SWApp_CheckboxAnswers (SW_ID, Checkbox_ID, Checkbox_Section, Checkbox_Type, Checkbox_Answer) VALUES(#SW_ID,#Checkbox_ID,#Checkbox_Section,#Checkbox_Type,#Checkbox_Answer) ");
add.CommandType = CommandType.Text;
add.Connection = sqlcon;
add.Parameters.AddWithValue("#SW_ID", "");
add.Parameters.AddWithValue("#Checkbox_ID", "");
add.Parameters.AddWithValue("#Checkbox_Section", "");
add.Parameters.AddWithValue("#Checkbox_Type", "");
add.Parameters.AddWithValue("#Checkbox_Answer", "");
add.Parameters["#SW_ID"].Value = entry.entryID.ToString();
var myKey = referral.FirstOrDefault(x => x.Value == item.ToString()).Key;
add.Parameters["#Checkbox_ID"].Value = myKey;
add.Parameters["#Checkbox_Section"].Value = "SmokeDetection";
add.Parameters["#Checkbox_Type"].Value = "Referral";
add.Parameters["#Checkbox_Answer"].Value = item.ToString();
sqlcon.Open();
add.ExecuteNonQuery();
sqlcon.Close();
}
}
}
Related
I have a list of combobox items generated from a database
private void Outlet1_DropDown(object sender, EventArgs e)
{
SqlDataReader dr7;
SqlConnection Conadd1 = new SqlConnection("Data Source=PC-PC\\MIKO;Initial Catalog=Caproj;Integrated Security=True;");
Conadd1.Open();
SqlCommand cmd6 = new SqlCommand("select Address from [Outlet Table] where ClientID='" + clientid + "'", Conadd1);
cmd6.Connection = Conadd1;
dr7 = cmd6.ExecuteReader();
DataTable dt8 = new DataTable();
dt8.Columns.Add("Address", typeof(string));
dt8.Load(dr7);
Outlet1.DisplayMember = "Address";
Outlet1.DataSource = dt8;
Conadd1.Close();
colorcombo();
}
A user can select a certain item in the said combobox and it will be inserted in a listbox. Once the listbox contains the said address, I want the item color to be made red, so it will remind the user that it's already selected
my attempt to code, I have no idea on how to use the drawmode event:
private void colorcombo()
{
if (outletlist.Items.Contains(Outlet1.Items.ToString()))
{
Con.Open();
for (int i = Outlet.Items.Count - 1; i >= 0; --i)
{
using (var cmd = new SqlCommand("UPDATE [Outlet Table] SET [Address] = Address WHERE [Address] = #address", Con))
{
cmd.Parameters.AddWithValue("#address", (Outlet.Items[i].Text));
if (cmd.ExecuteNonQuery() > 0)
{
//Outlet.Items[i].BackColor = Color.Red;
}
else
{
//Outlet.Items[i].BackColor = Color.Black;
}
}
}
}
}
Some details:
Outlet1 = name of my combobox
outletlist = name of my listbox
private void DeleteClient_Load(object sender, EventArgs e)
{
try
{
connection = new SqlConnection(new DatabaseConnection().cnnString.ToString());
connection.Open();
}
catch (Exception exp)
{
MessageBox.Show(exp.Message, "Could not establish connection to the database.", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
cmd = new SqlCommand(new DatabaseAdd().addToComboBoxSE.ToString(), connection);
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
foreach(DataRow dr in dt.Rows)
{
comboBox1.Items.Add(dr["Id"] + ". " + dr["FirstName"] + " " + dr["Surname"]);
}
connection.Close();
}
Here i am adding items to a comboBox from a database. I am adding the ID(int), FirstName(varchar) and Surname(varchar) to each item for each row in the database.
My question is, how do i go about deleting a row from the database depending on a list item i have selected within the comboBox? I am able to do it when i just add the ID(int) to the comboBox but since i need the id, firstname and surname, i am unable to retrieve the ID from whatever list option i have selected.
Any help is appreciated. Thank you.
You need to create an instance of ComboBoxItem class and set its Value property to the id you want, then add it to your combobox.
The Class ComboBoxItem.cs:
public class ComboBoxItem
{
public string Text { get; set; }
public object Value { get; set; }
public override string ToString()
{
return Text;
}
}
Inside your foreach loop should be:
ComboBoxItem itm = new ComboBoxItem();
itm.Value = dr["Id"];
itm.Text = dr["Id"] + ". " + dr["FirstName"] + " " + dr["Surname"];
ComboBox1.Items.Add(itm);
You can get the selected item's id like this:
String selectedId = ((ComboBoxItem)(ComboBox1.SelectedItem)).Value.ToString();
Hope it helps.
Assuming that the Id is a numeric field, what you need to do is to split your string and extract the value of ID from the list. Since the format of the item is identical for all items, we can use the ". " as the separator string.
So, you can write something like this:
var str = selectedItem; // this is the value of selected item from the combo box and it's type is string. Example: "123. John Doe"
int ID = 0;
var str = selectedItem.Trim(); // this is the value of selected item from the combo box and it's type is string
var index = selectedItem.IndexOf(". ");
if (index > 1)
{
ID = Int32.Parse(selectedItem.Substring(0, index ) );
}
I was not sure
if you're asking to remove a row from the ComboBox once selected then
or delete from the db
This handles both, remove from Combo or delete from DB RowDeleter(string cmbName = "", bool deleteFromComboxBox )
Edit 1 updated the code based on comment:
//added optional parameter to pass combobox value after successfully record operations, or just call it
private void RowDeleter(ComboBox myComboBox)
{
try
{
SqlConnection conn = new SqlConnection(dataconnection);
SqlCommand cmd = new SqlCommand("myconn", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "yourtableset");
//look at what it is
String selectedId = (ComboBoxItem)(myComboBox.SelectedItem).Value.ToString();
DeleteRecord(selectedId);
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
// delete Helper
private void DeleteRecord(string row)
{
return if (StringIsNullOrEmpty(row))
string sql = "DELETE FROM Table1 WHERE RowID = #row";
SqlCommand deleteRecord = new SqlCommand();
deleteRecord.Connection = someconnection;
deleteRecord.CommandType = CommandType.Text;
deleteRecord.CommandText = sql;
SqlParameter RowParameter = new SqlParameter();
RowParameter.ParameterName = "#RowID";
RowParameter.SqlDbType = SqlDbType.string; //or int
RowParameter.IsNullable = false;
RowParameter.Value = row;
deleteRecord.Parameters.Add(RowParameter);
deleteRecord.Connection.Open();
deleteRecord.ExecuteNonQuery();
deleteRecord.Connection.Close();
booksDataset1.GetChanges();
// sqlDataAdapter1.Fill(someDataset.WHatverEmployees);
}
I'm trying to get all data from an SQL table and store it in a List using the C# programming language.
the SQL statement I'm using is:
private string cmdShowEmployees = "SELECT * FROM Employees;";
This is being used in the same class as a function
public List<string> showAllIdData()
{
List<string> id = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
id.Add(reader[0].ToString());
}
return id;
}
}
and here
public List<string> showAllActiveData()
{
List<string> active = new List<string>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read()) {
active.Add(reader[1].ToString());
}
return active;
}
I would have to create 9 more functions this way in order to get all the data out of the Employees table. This seems very inefficient and I was wondering if there was a more elegant way to do this.
I know using an adapter is one way to do it but I don't think it is possible to convert a filled adapter to a list, list list etc.
SqlDataAdapter adapter = sqlDataCollection.getAdapter();
DataSet dataset = new DataSet();
adapter.Fill(dataset, "idEmployees");
dataGridView1.DataSource = dataset;
dataGridView1.DataMember = "idEmployees";
Any ideas?
If you must use the reader in this way, why not create an object which holds the table row data.
public class SomeComplexItem
{
public string SomeColumnValue { get; set;}
public string SomeColumnValue2 { get; set;}
public string SomeColumnValue3 { get; set;}
public string SomeColumnValue4 { get; set;}
}
That way you can loop through with your reader as follows:
public List<SomeComplexItem> showAllActiveData()
{
List<SomeComplexItem> active = new List<SomeComplexItem>();
using (sqlConnection = getSqlConnection())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = cmdShowEmployees;
SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{
var someComplexItem = new SomeComplexItem();
someComplexItem.SomeColumnValue = reader[1].ToString();
someComplexItem.SomeColumnValue2 = reader[2].ToString();
someComplexItem.SomeColumnValue3 = reader[3].ToString();
active.Add(someComplexItem);
}
return active;
}
You could use two select statements to populate two List<string> as shown in the example below where the key between reads is reader.NextResult();.
The database used is the standard Microsoft NorthWind database.
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
namespace SQL_Server_TwoList
{
public class DataOperations
{
public List<string> Titles { get; set; }
public List<string> Names { get; set; }
/// <summary>
/// Trigger code to load two list above
/// </summary>
public DataOperations()
{
Titles = new List<string>();
Names = new List<string>();
}
public bool LoadData()
{
try
{
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
string commandText = #"
SELECT [TitleOfCourtesy] + ' ' + [LastName] + ' ' + [FirstName] As FullName FROM [NORTHWND.MDF].[dbo].[Employees];
SELECT DISTINCT [Title] FROM [NORTHWND.MDF].[dbo].[Employees];";
using (SqlCommand cmd = new SqlCommand(commandText, cn))
{
cn.Open();
SqlDataReader reader = cmd.ExecuteReader();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Names.Add(reader.GetString(0));
}
// move on to second select
reader.NextResult();
// get results into first list from first select
if (reader.HasRows)
{
while (reader.Read())
{
Titles.Add(reader.GetString(0));
}
}
}
}
}
return true;
}
catch (Exception)
{
return false;
}
}
}
}
Form code
namespace SQL_Server_TwoList
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataOperations dataOps = new DataOperations();
if (dataOps.LoadData())
{
listBox1.DataSource = dataOps.Names;
listBox2.DataSource = dataOps.Titles;
}
}
}
}
You could always add it all to a dataset or datatable instead of looping through using datareader to add to an array, dataset allows you to access data in similar way to array anyway.
Connstr = "Data Source = " + SelectedIP + "; Initial Catalog = " + dbName + "; User ID = " + txtUsername.Text +"; Password = "+ txtPassword.Text +"";
conn = new SqlConnection(Connstr);
try
{
string contents = "SELECT * FROM ..."
conn.Open();
SqlDataAdapter da_1 = new SqlDataAdapter(contents, conn); //create command using contents of sql file
da_1.SelectCommand.CommandTimeout = 120; //set timeout in seconds
DataSet ds_1 = new DataSet(); //create dataset to hold any errors that are rturned from the database
try
{
//manipulate database
da_1.Fill(ds_1);
if (ds_1.Tables[0].Rows.Count > 0) //loop through all rows of dataset
{
for (int i = 0; i < ds_1.Tables[0].Rows.Count; i++)
{
//rows[rownumber][column number/ "columnName"]
Console.Write(ds_1.Tables[0].Rows[i][0].ToString() + " ");
}
}
}
catch(Exception err)
{}
conn.Close();
}
catch(Exception ex)
{}
My problem is that when it gets updated it adds the previous data which was in it Again and again
and i use a telerik grid view
here my code in 3 layers
first one
private void btnSbmt_Click(object sender, EventArgs e)
{
foreach (var row in radGridView1.Rows)
{
_MyName.Add((string)row.Cells[1].Value);
}
foreach (var row in radGridView1.Rows)
{ // 0 - first column
_MyAmount.Add((int)row.Cells[2].Value);
}
foreach (var row in radGridView1.Rows)
{
_MyPrice.Add((decimal)row.Cells[3].Value);
}
Ref_View_Model = new View_model._View_Model();
Ref_View_Model.GetInsertProduct(_myName, _myAmount, _myPrice, txtDt.Text);
radGridView1.CurrentRow.Delete();
productTableAdapter.Update(sales_and_Inventory_SystemDataSet);
productTableAdapter.Fill(sales_and_Inventory_SystemDataSet.Product);
MessageBox.Show("Product(s) were added", "Done", MessageBoxButtons.OK);}
second one
public void GetInsertProduct( List<string> _name, List<int> _amount, List<decimal> _price, string _date)
{
Ref_Model = new Model._Model();
Ref_Model.InsertProduct( _name, _amount, _price, _date);
}
and the Third one
public void InsertProduct(List<string> _myName,
List<int> _myAmount,
List<decimal> _myPrice, string _date)
{
Connection_String = myconnection string
Query = #"INSERT INTO dbo.product(Name, Amount, Price, [date])
VALUES(#Name, #Amount, #Price, #Date);";
using ( Con = new SqlConnection(Connection_String))
using ( Cmd = new SqlCommand(Query, Con))
{
Cmd.Parameters.Add("#Name", SqlDbType.NVarChar);
Cmd.Parameters.Add("#Amount", SqlDbType.Int);
Cmd.Parameters.Add("#Price", SqlDbType.Decimal);
// Cmd.Parameters.Add("#Date", SqlDbType.NVarChar);
Cmd.Parameters.Add("#Date", SqlDbType.DateTime).Value = Convert.ToDateTime(_date);
Cmd.Connection = Con;
Con.Open();
int recordsToAdd = _myName.Count();
for(int x = 0; x < recordsToAdd; x++)
{
Cmd.Parameters["#Name"].Value = _myName[x];
Cmd.Parameters["#Amount"].Value = _myAmount[x];
Cmd.Parameters["#Price"].Value = _myPrice[x];
Cmd.Parameters["#Date"].Value = _date;
Cmd.ExecuteNonQuery();
}
}
}
It seems that you are using global variables to keep the values that you read from the grid. If you don't clear them after the first insert, you have still the values in the global lists and you add them again to the datatable
Of course you can use just one loop to reload the global variables with the actual values present in the grid
private void btnSbmt_Click(object sender, EventArgs e)
{
// This removes whatever is in the lists
_MyName.Clear();
_MyAmount.Clear();
_MyPrice.Clear();
// and now start adding items from scratch
foreach (var row in radGridView1.Rows)
{
_MyName.Add((string)row.Cells[1].Value);
_MyAmount.Add((int)row.Cells[2].Value);
_MyPrice.Add((decimal)row.Cells[3].Value);
}
....
I want to build a custom interface (a separate aspx page) to manage the data that is put into the webforms for marketeers (WFFM) database, and that for just one form. It must be possible to edit the data and select records with particular sortings and pagings. The database is configured to be SQLite.
Is this possible and recommended, or is it just plain xml that is saved into the WFFM database? And how should I go about it?
This is completely doable, though the select query to get data out of WFFM is a bit funky because everything is stored loose in one huge table called "field" with only a trail of GUIDs to tie the stored values back to what form they came from and what field.
Provided below is part of an Export to Excel utility I wrote for WFFM data. It builds a DataTable object from submitted form results. You could adapt it to some other structure without much work though.
public string connectionStringWFFM = "user id=sitecore_admin;password=xxx;Data Source=SitecoreDBServer.com;Database=Sitecore_WebForms";
protected DataTable BuildDataTable(Item formItem)
{
List<FormResult> formResults = FormResults(formItem.ID.Guid);
List<Field> distinctFields = DistinctFields(formItem.ID.Guid);
var dt = new DataTable();
dt.Columns.Add("Submission_DateTime", typeof (string));
foreach (Field field in distinctFields)
{
var dataColumn = new DataColumn("_" + field.id.ToString("N"), typeof (string));
dataColumn.Caption = field.name.Replace(" ", "_");
dt.Columns.Add(dataColumn);
}
foreach (FormResult formResult in formResults)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select fieldid, value from field where formid=#formid order by fieldid";
command.Parameters.Add("#formid", SqlDbType.UniqueIdentifier).Value = formResult.id;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
DataRow dataRow = dt.NewRow();
dataRow["Submission_DateTime"] = formResult.timestamp.ToString("MM/dd/yyyy HH:mm:ss");
while (reader.Read())
{
dataRow["_" + reader.GetGuid(0).ToString("N")] = reader.GetValue(1).ToString().Replace("<item>", "").Replace("</item>", "");
}
dt.Rows.Add(dataRow);
reader.Close();
connection.Close();
}
return dt;
}
public List<Field> DistinctFields(Guid formitemid)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select distinct fieldid from field where formid in (select id from form where formitemid=#formitemid) order by fieldid";
command.Parameters.Add("#formitemid", SqlDbType.UniqueIdentifier).Value = formitemid;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
var results = new List<Field>();
int count = 0;
while (reader.Read())
{
var field = new Field();
field.id = reader.GetGuid(0);
Database database = Factory.GetDatabase("master");
Item i = database.GetItem(new ID(field.id));
if (i != null && i.DisplayName != null)
{
field.name = i.DisplayName;
}
else
{
field.name = "Field" + count;
}
results.Add(field);
count += 1;
}
reader.Close();
connection.Close();
return results;
}
public List<FormResult> FormResults(Guid formitemid)
{
var connection = new SqlConnection();
connection.ConnectionString = connectionStringWFFM;
var command = new SqlCommand();
command.Connection = connection;
command.CommandText = "select id, timestamp from form where formitemid=#formitemid";
command.Parameters.Add("#formitemid", SqlDbType.UniqueIdentifier).Value = formitemid;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
var results = new List<FormResult>();
while (reader.Read())
{
var result = new FormResult();
result.id = reader.GetGuid(0);
result.timestamp = reader.GetDateTime(1);
results.Add(result);
}
reader.Close();
connection.Close();
return results;
}
public class FormResult
{
public Guid id { get; set; }
public DateTime timestamp { get; set; }
}
public class Field
{
public Guid id { get; set; }
public string name { get; set; }
}