I am trying to create a multi dimension array
What I have so far is...
ArrayList iEFiles = (ArrayList)Session["Files"];
iEFiles.Add(Server.MapPath(FileName));
FileName = "Testing123"
FileName = "AnotherTest"
What I want it to do is have it come out like this...
FileName = ("Testing123", "Waterproof")
FileName = ("AnotherTest", "Non-Waterproof")
Like Array[,]
Any ideas?
To display the records...
BindGridview(iEFiles);
private void BindGridview(ArrayList list)
{
DataTable dt = new DataTable();
dt.Columns.Add("FileName");
dt.Columns.Add("id");
dt.Columns.Add("snFile");
int c = list.Count;
for (int i = 0; i < c; i++)
{
dt.Rows.Add();
dt.Rows[i]["FileName"] = list[i].ToString().ToUpper();
dt.Rows[i]["id"] = i;
dt.Rows[i]["snFile"] = list[i].ToString();
}
GridView1.DataSource = dt;
GridView1.DataBind();
}
You could use the Hashtable / Dictionary to store the key value pair. If you do not want that you can make a class having two attributes FileName and Value and store object of that class in ArrayList or preferably generic List<T>.
class FileInformation
{
public FileInformation(string fileName, string value)
{
FileName = fileName;
Value = value;
}
public string FileName;
public string Value;
}
List<FileInformation> lst = new List<FileInformation>();
lst.Add(new FileInformation("fileName", "somevalue"));
An ArrayList is a bit of a .net 1.x throwback before we had generics.
You could use Dictionary<string,string> to store these values but the first item is a key and has to be unique. If you just want to store a list of 2 values you could use something like List<KeyValuePair<string,string>> or List<string[]>.
Related
I have a string like this:
"Product,Price,Condition
Cd,13,New
Book,9,Used
"
Which is being passed like this:
"Product,Price,Condition\r\Cd,13,New\r\nBook,9,Used"
How could I convert it to DataTable?
Trying to do it with this helper function:
DataTable dataTable = new DataTable();
bool columnsAdded = false;
foreach (string row in data.Split(new string[] { "\r\n" }, StringSplitOptions.None))
{
DataRow dataRow = dataTable.NewRow();
foreach (string cell in row.Split(','))
{
string[] keyValue = cell.Split('~');
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(keyValue[0]);
dataTable.Columns.Add(dataColumn);
}
dataRow[keyValue[0]] = keyValue[1];
}
columnsAdded = true;
dataTable.Rows.Add(dataRow);
}
return dataTable;
However I don't get that "connecting cells with appropriate columns" part - my cells don't have ~ in string[] keyValue = cell.Split('~'); and I obviously get an IndexOutOfRange at DataColumn dataColumn = new DataColumn(keyValue[0]);
Based on your implementation, I have written the code for you, I have not tested it. But you can use the concept.
DataRow dataRow = dataTable.NewRow();
int i = 0;
foreach (string cell in row.Split(','))
{
if (!columnsAdded)
{
DataColumn dataColumn = new DataColumn(cell);
dataTable.Columns.Add(dataColumn);
}
else
{
dataRow[i] = cell;
}
i++;
}
if(columnsAdded)
{
dataTable.Rows.Add(dataRow);
}
columnsAdded = true;
You can do that simply with Linq (and actually there is LinqToCSV on Nuget, maybe you would prefer that):
void Main()
{
string data = #"Product,Price,Condition
Cd,13,New
Book,9,Used
";
var table = ToTable(data);
Form f = new Form();
var dgv = new DataGridView { Dock = DockStyle.Fill, DataSource = table };
f.Controls.Add(dgv);
f.Show();
}
private DataTable ToTable(string CSV)
{
DataTable dataTable = new DataTable();
var lines = CSV.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var colname in lines[0].Split(','))
{
dataTable.Columns.Add(new DataColumn(colname));
}
foreach (var row in lines.Where((r, i) => i > 0))
{
dataTable.Rows.Add(row.Split(','));
}
return dataTable;
}
You can split given string into flattened string array in one call. Then you can iterate through the array and populate list of objects.
That part is optional, since you can immediately populate DataTable but I think it's way easier (more maintainable) to work with strongly-typed objects when dealing with DataTable.
string input = "Product,Price,Condition\r\nCd,13,New\r\nBook,9,Used";
string[] deconstructedInput = input.Split(new string[] { "\r\n", "," }, StringSplitOptions.None);
List<Product> products = new List<Product>();
for (int i = 3; i < deconstructedInput.Length; i += 3)
{
products.Add(new Product
{
Name = deconstructedInput[i],
Price = Decimal.Parse(deconstructedInput[i + 1]),
Condition = deconstructedInput[i + 2]
});
}
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string Condition { get; set; }
}
So, products collection holds 2 objects which you can easily iterate over and populate your DataTable.
Note: This requires further checks to avoid possible runtime exceptions, also it is not dynamic. That means, if you have differently structured input it won't work.
DataTable dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn(nameof(Product.Name)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Price)));
dataTable.Columns.Add(new DataColumn(nameof(Product.Condition)));
foreach (var product in products)
{
var row = dataTable.NewRow();
row[nameof(Product.Name)] = product.Name;
row[nameof(Product.Price)] = product.Price;
row[nameof(Product.Condition)] = product.Condition;
dataTable.Rows.Add(row);
}
This is my first question here, so sorry for any wrong information or about my English.
I need to convert a List<Object> to List<Hashtable>
string IdsLista = string.Empty;
foreach (DataRow rows in ListaItensTransferencia.Rows)
{
IdsLista += Convert.ToString(rows["Id Bem"]) + ",";
}
string[] idsSelecionadosListaTransferencia = IdsLista.Split(',');
List<object> listaIdsSelecionadosListTransferencia = new List<object>(idsSelecionadosListaTransferencia.Length);
listaIdsSelecionadosListTransferencia.AddRange(idsSelecionadosListaTransferencia);
wuc_itensTransferencia.checkBoxGrid = listaIdsSelecionadosListTransferencia;
//v this is the list<hashtable> v this is the list<object>
wuc_itensTransferencia.ItensSelecionados = listaIdsSelecionadosListTransferencia;
How do I do this ?
Instead of putting data into list of object, put directly into list of hashtable. Why you want to create the comma separated string. Try this
List<HashTable> hashTable = new List<HashTable>();
foreach (DataRow rows in ListaItensTransferencia.Rows)
{
hashTable.Add(new HashTable("Id Bem", Convert.ToString(rows["Id Bem"])));
}
I'm trying to accomplish the following and would appreciate any help.
I have a CSV file containing 2 columns, 1 a list of names and the other a list of associated IDs.
Eg.
Test1, 00001
Test2, 00002
I have read these into my program into 2 lists.
1. nameList
2. idList
I have populated the datasource of a combobox with the values of nameList.
Now, when a name is selected in the combobox and a button pressed, I would like to get the ID. So if Test1 is selected, when the button is pressed 00001 is returned where as if Test2 is selected and the button pressed, 00002 is returned.
If it helps at all, this is what im currently using to populate the Lists.
public void nameCSV()
{
var reader = new StreamReader(File.OpenRead(#"C:\temp\nameList.csv"));
List<string> nameList = new List<string>();
List<string> idList = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
nameList.Add(values[0]);
idList.Add(values[1]);
}
cmbxName.DataSource = releaseNameList;
}
public void nameCSV()
{
var reader = new StreamReader(File.OpenRead(#"C:\temp\nameList.csv"));
DataTable tbl = new DataTable();
tbl.Columns.Add("Name", typeof(string));
tbl.Columns.Add("ID", typeof(string));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
DataRow row = tbl.NewRow();
row["Name"]=values[0];
row["ID"] = values[1];
tbl.Rows.Add(row);
}
cmbxName.DisplayMember = "Name";
cmbxName.ValueMember = "ID";
cmbxName.DataSource = tbl;
}
You need something like that. Check properties DisplayMember and ValueMember of ComboBox.
So when the button is clicked and you want to take the Value not the display text.
protected void Button1_Click(object sender, EventArgs e)
{
string id = cmbxName.SelectedValue;
}
N.B: Your title is misleading !
Use a Dictionary
public void nameCSV()
{
var reader = new StreamReader(File.OpenRead(#"C:\temp\nameList.csv"));
Dictionary<string, int> userDict = new Dictionary<string, int>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
userDict.Add(values[0], values[1]);
}
cmbxName.DataSource = userDict;
}
to call the value of a given user id just use the key. For example, 'Test1'
string Username = "Test1";
int userid;
userid = userDict[Username];
One note, dictionaries work better with numeric values as the key, not strings. Put in your case you're looking up the string name, so it should be this way. As long as the string lengths are short - aka no more than 10 characters. Peformance wise, you should be okay.
Ive created a Directory Searcher to pull multiple properties from each user.
objSearchADAM = new DirectorySearcher(objADAM);
objSearchADAM.PropertiesToLoad.Add("givenname");
objSearchADAM.PropertiesToLoad.Add("lastlogontimestamp");
ect...
objSearchResults = objSearchADAM.FindAll();
I then enumerate them, and convert the interger8 timestamp to standard date/time, and save to csv file with
List<string> timeProps = new List<string>() { "lastlogontimestamp", "accountexpires", "pwdlastset", "lastlogoff", "lockouttime", "maxstorage", "usnchanged", "usncreated", "usndsalastobjremoved", "usnlastobjrem", "usnsource" };
foreach (SearchResult objResult in objSearchResults)
{
objEntry = objResult.GetDirectoryEntry();
ResultPropertyCollection myResultProp = objResult.Properties;
foreach (string myKey in myResultProp.PropertyNames)
{
foreach (Object myCollection in myResultProp[myKey])
{
Object sample = myCollection;
if (timeProps.Contains(myKey))
{
String times = sample.ToString();
long ft = Int64.Parse(times);
DateTime date;
try
{
date = DateTime.FromFileTime(ft);
}
catch (ArgumentOutOfRangeException ex)
{
date = DateTime.MinValue;
Console.WriteLine("Out of range: " + ft);
Console.WriteLine(ex.ToString());
}
sample = date;
Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
}
else
{
Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
}
}
now i need to create an object for each user with the strings from each result that i can put into an SQL command ive built. where the LDAP query to SQL would be givenname = FirstName and lastlogontimestamp = LastLogon and so on.
StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO activedirectory.dimUserST (FirstName, LastName) VALUES (#FirstName, #LastName)");
loadStagingCommand.Parameters.AddWithValue("#FirstName", FirstName).DbType = DbType.AnsiString;
ect...
loadStagingCommand.CommandText = sb.ToString();
loadStagingCommand.ExecuteNonQuery();
i tried to use IDictionary in my first foreach (similar to code found here http://ideone.com/vChWD ) but couldn't get it to work. I read about IList and reflection, but im not sure how i could incorporate these.
UPDATE
I researched and found ExpandoObjects and attempted to write in code based off of what i saw in here Creating Dynamic Objects
however i run this new code I return "employeenumber System.Collections.Generic.List`1[System.Dynamic.ExpandoObject]"
if(employeeNumber.Contains(myKey))
{
string[] columnNames = { "EmployeeNumber" };
List<string[]> listOfUsers = new List<string[]>();
for (int i = 0; i < 10; i++)
{
listOfUsers.Add(new[] { myKey});
}
var testData = new List<ExpandoObject>();
foreach (string[] columnValue in listOfUsers)
{
dynamic data = new ExpandoObject();
for (int j = 0; j < columnNames.Count(); j++)
{
((IDictionary<String, Object>)data).Add(columnNames[j], listOfUsers[j]);
}
testData.Add(data);
Console.WriteLine("{0}{1}", myKey.PadRight(25), testData);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), testData);
}
}
I am obviously missing something here and cant seem to wrap my head around what the problem is. I might even be going about this the wrong way. Basically all i need to do is pull users and their properties from Active Directory and put into SQL database tabels. And I've worked out how to do both separately, but I cant figure out how to put it all together.
If the CSV is just being used to cache the results, you could use a Dictionary to store the contents of the search results instead. Separating your code into functions could be helpful:
private static object GetFirstValue(ResultPropertyCollection properties,
string propertyName)
{
var propertyValues = properties[propertyName];
var result = propertyValues.Count == 0 ? null : propertyValues[0];
return result;
}
Then you could either use a dictionary to hold the property values, or you could create a type:
var results = new List<Dictionary<string, object>>();
foreach(SearchResult objResult in objSearchResults)
{
var properties = objResult.Properties;
var propertyDictionary = new Dictionary<string, object> {
{"FirstName", GetFirstValue(properties, "givenname")},
{"LastName", GetFirstValue(properties, "sn")},
{"UserName", GetFirstValue(properties, "samaccountname")},
};
results.Add(propertyDictionary);
}
Now you have a list of property bags.
This could also be a simple LINQ statement:
var results = objSearchResults.OfType<SearchResult>()
.Select(s => s.Properties)
.Select(p => new {
FirstName = (string)GetFirstValue(properties, "givenname"),
LastName = (string)GetFirstValue(properties, "sn"),
UserName = (string)GetValue(properties, "samaccountname"),
AccountExpires = GetDateTimeValue(properties, "accountexpires")
});
Use the dictionaries like this:
foreach(var item in results)
{
var command = new SqlCommand();
...
command.Parameters.AddWithValue("firstName", item["FirstName"]);
...
}
I am using C# to import a CSV file into my application
Currently I had a 1 field CSV file. It worked great but now I wanted to add a 3 field CSV file into the same application.
Once the data is stored into the List, I'm binding it to my DataGridView
Here is the relevent code I've written. If you see any issue(s) that aren't part of my problem but can be a problem, please feel free to shout them out. Im always looking to learn and improve my code.
BindingList<StringValue> data = new BindingList<StringValue>();
private void importExcelFile()
{
TextFieldParser parser = new TextFieldParser(fileName);
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
//Processing row
string[] fields = parser.ReadFields();
foreach (string field in fields)
{
StringValue s = new StringValue(field);
// Issue is here. It adds it to a single dimension array. What can I do to make it multi-dimension?
data.Add(s);
}
}
parser.Close();
}
private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
importExcelFile();
}
private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dataGridView1.DataSource = data;
dataGridView1.Columns[1].Name = "URL";
dataGridView1.Columns[1].HeaderText = "URL";
dataGridView1.Columns[1].Width = 300;
dataGridView1.Columns[1].ReadOnly = true;
dataGridView1.AutoResizeColumns();
toolStripStatusLabel1.Text = dataGridView1.RowCount.ToString() + " Number Of Websites";
}
class StringValue
{
string day, time, url;
public StringValue(string s)
{
_value = s;
}
public StringValue(string[] s)
{
day = s[0];
time = s[1];
url = s[2];
}
public string Value { get { return _value; } set { _value = value; } }
string _value;
}
I think I should modify my StringValue class to hold the multiple fields that I'm importing from my CSV file. I'm not sure how to modify the Value part to return the data I need when I bind it to my dataGridView
Thank you for your input and help/
Why not juste put the csv into a datatable like so?
private DataTable GetDataTableFromCsv(string path)
{
DataTable dataTable = new DataTable();
String[] csv = File.ReadAllLines(path);
foreach (string csvrow in csv)
{
var fields = csvrow.Split(','); // csv delimiter
var row = dataTable.NewRow();
row.ItemArray = fields;
dataTable.Rows.Add(row);
}
return dataTable;
}
after that juste import the datatable into your datagridview.
In your entity (StringValue) you can add as many properties as you want, containing as many values as your want.
You can bind each column of your dataGridView by setting the columns DataPropertyName with the name of the property you are binding to.
For example, your entity has two properties:
class MyValues
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
You add a collection of this to yuur data-collection, which you bind to your grid.
Your grid can be configures as:
dataGridView1.Columns[0].Name = "FirstName";
dataGridView1.Columns[0].HeaderText = "FirstName";
dataGridView1.Columns[0].DataPropertyName = "FirstName";
dataGridView1.Columns[1].Name = "LastName";
dataGridView1.Columns[1].HeaderText = "LastName";
dataGridView1.Columns[1].DataPropertyName = "LastName";