|
Here it is again.
This time I'll try to paste it properly.
<pre>
public class FieldMappingDictionary : Dictionary<string, List<string>>
{
public void Add(string key, string value)
{
// if the key is already in the list
if (base.Keys.Contains(key))
{
// only do it if not already there
if (!base[key].Contains(value))
{
// add the new value
base[key].Add(value);
}
}
else
{
// if the key ain't there, add it and a new values list
List<string> list = new List<string>();
list.Add(value);
base.Add(key, list);
}
}
}
</pre>
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Hi Henry,
Almost there! I have one more problem. I am getting the error:
'System.Collections.Generic.Dictionary<string,System.Collections.Generic.List<string>>.KeyCollection' does not contain a definition for 'Contains'
This occurs on line 6:
if (base.Keys.Contains(key))
|
|
|
|
|
I keep forgetting that you are using VS2005.
Slight modification:
<pre>
public class FieldMappingDictionary : Dictionary<string, List<string>>
{
public void Add(string key, string value)
{
// if the key is already in the list
if (this.KeysContains(key)) // <================= Modified Line
{
// only do it if not already there
if (!base[key].Contains(value))
{
// add the new value
base[key].Add(value);
}
}
else
{
// if the key ain't there, add it and a new values list
List<string> list = new List<string>();
list.Add(value);
base.Add(key, list);
}
}
public bool KeysContains(string key) // <=========== New Method, just iterates over keys collection, returns true if found
{
bool result = false;
foreach (string s in base.Keys)
{
if (s == key)
{
result = true;
break;
}
}
return result;
}
}
</pre>
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Incidentally I keep forgetting this.
You could save one step in your overall scheme, if loading the modified data into Excel is not a requirement.
SSIS can read XML directly, and both DataSet and DataTable have a method called WriteXML, which believe it, or not, writes their data (and/or schema) to an XML file.
As I said, if the Excel step is not a requirement, simply write the data to an XML file ready for SSIS.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Hi Henry,
Looks like I have added all the code I need and the code compiles without warnings but the dgv doesn't get populated. I belive the only place I needed to add code too is here. If I am wrong then please advise further.
private void ProcessMods()
{
// Create a copy of original table structure with
// standardized column names**
// load original file data into it
// then do a series of updates using the docsDictionary, and the
// other Dictionaries
// STEP THROUGH THIS TO WATCH UPDATE STATEMENT BUILDING
StringBuilder selectBuilder = null;
foreach (string key in this.docsDictionary.Keys)
{
foreach (string val in this.docsDictionary[key])
{
selectBuilder = new StringBuilder();
selectBuilder.Append("UPDATE TestData SET Documentation = ");
selectBuilder.Append(key);
selectBuilder.Append(" WHERE Documentation = ");
selectBuilder.Append(val);
string updateQuery = selectBuilder.ToString();
// execute the query here
// you know OleDbConnection, OleDbcommand etc.
// then go round for next mod
//This is where I added the connection
DataTable dFill = null;
String comString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Path.GetDirectoryName(Path.GetFullPath(this.dataFile)) + @";Extended Properties=""Text;HDR=YES;FMT=Delimited;IMEX=1\""";
using (OleDbConnection conCSV = new OleDbConnection(comString))
{
conCSV.Open();
OleDbCommand dbCommand = new OleDbCommand(updateQuery, conCSV);
OleDbDataAdapter dAdapter = new OleDbDataAdapter(dbCommand);
dFill = new DataTable();
dAdapter.Fill(dFill);
}
bindingSource1.DataSource = dFill;
dataGridView1.DataSource = bindingSource1;
}
// go round for next key
}
// then do same for next dictionary
}
Do I need to add code for a ShowDialog and capture the full path of the file? Also, the test file is in the debug folder. Maybe it would be easier to hardcode the path of the file in the com string. What do you think?
Thank you,
Brenton
modified on Wednesday, May 27, 2009 11:50 AM
|
|
|
|
|
Strictly speaking ProcessMods() was intended merely, to create a copy of the table containing client-data but with your standard column names (See the comments at start of the method). I have left that bit for you to do as I am not sure about the best method for that process. Then it should process all the updates retrieved from MappingForm. You could fill the grid during that operation, but it would slow it down enormously, although it would show progress.
The alternative would be to show the modifications after they are completed. In which case your dgv filling code should either be the very last thing in ProcessMods() , or immediately after the call to ProcessMods() in the MappingForm_Closed event handler (this would be my preference).
For ProcessMods() the parts left to be done are, as mentioned above, copying the data to a new table with proper column names (incidentally I suggested copying so that the original data remains intact, in case of accidents. ), and this bit:
which is immediately above your new dgv fill code.
bwood2020 wrote: Do I need to add code for a ShowDialog and capture the full path of the file?
Yes, for the production version, you probably would. Putting the test data in the debug folder was simply for convenience for what is a demo of a concept.
If you stepped through the query building bit, I hope that you could see that for each of your standardised pieces of data the method builds an update query for each of the versions the client has used. It might turn out that using a query is not the best way to perform this operation, but the point of the exercise is to show that the data required to do the mods, is in a format which will enable the changes to be done fairly easily.
I am currently looking at methods for copying the client data into a table with standard column names.
I'll be back with you shortly. Of course, if you already know how to do this, let me know.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Just when you thought it was safe to .........
Some mods to the first form, I am posting the whole thing, because there are some renames, as well as some new methods and fields:
List<string> standardList = new List<string>();
Dictionary<string, string> clientHeaders = new Dictionary<string, string>();
Dictionary<string, string> standardHeaders = new Dictionary<string, string>();
DataSet testDataSet = null;
DataTable headerTable = null;
DataTable clientDataTable = null;
DataTable standardDataTable = null;
MappingForm mappingForm = null;
readonly string dataFile = "TestData.csv";
FieldMappingDictionary docsDictionary = null;
public ListEditorForm()
{
InitializeComponent();
InitStandardList();
}
private void InitStandardList()
{
standardList.AddRange(new string[] { "Property", "Offer", "Documentation", "Figures", "Guarantee" });
}
private void ProcessMods()
{
this.GetClientData();
this.CreateStandardTable();
foreach (string key in this.docsDictionary.Keys)
{
foreach (string val in this.docsDictionary[key])
{
foreach (DataRow row in this.standardDataTable.Rows)
{
if (row["Documentation"].ToString() == val)
{
row["Documentation"] = key;
}
}
}
}
}
private void MakeHeaderDictionaries()
{
this.clientHeaders = this.MakeHeaderDictionary();
this.standardHeaders = this.MakeStandardHeaderDictionary();
}
private Dictionary<string, string> MakeStandardHeaderDictionary()
{
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (DataRow row in this.headerTable.Rows)
{
result.Add(row[0].ToString().Trim(), row[1].ToString().Trim());
}
return result;
}
private Dictionary<string, string> MakeHeaderDictionary()
{
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (DataRow row in this.headerTable.Rows)
{
result.Add(row[1].ToString().Trim(), row[0].ToString().Trim());
}
return result;
}
private void GetClientData()
{
String comString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
Path.GetDirectoryName(Path.GetFullPath(this.dataFile)) + @";Extended Properties=""Text;HDR=YES;FMT=Delimited;IMEX=1\""";
String strSql = "SELECT * FROM [" + Path.GetFileName(this.dataFile) + "]";
using (OleDbConnection conCSV = new OleDbConnection(comString))
{
conCSV.Open();
OleDbCommand dbCommand = new OleDbCommand(strSql, conCSV);
OleDbDataAdapter dAdapter = new OleDbDataAdapter(dbCommand);
clientDataTable = new DataTable("ClientData");
dAdapter.Fill(clientDataTable);
this.testDataSet.Tables.Add(clientDataTable);
}
}
private void CreateStandardTable()
{
this.standardDataTable = this.clientDataTable.Copy();
this.standardDataTable.TableName = "StandardData";
for (int i = 0; i < this.standardDataTable.Columns.Count; i++)
{
this.standardDataTable.Columns[i].ColumnName =
this.standardHeaders[this.clientDataTable.Columns[i].ColumnName.Trim()];
}
this.testDataSet.Tables.Add(standardDataTable);
}
#region ListEditorForm PROPERTIES ...............................
public Dictionary<string, string> ClientHeaders
{
get
{
return this.clientHeaders;
}
private set
{
this.clientHeaders = value;
}
}
public Dictionary<string, string> StandardHeaders
{
get
{
return this.standardHeaders;
}
private set
{
this.standardHeaders = value;
}
}
private MappingForm MappingForm
{
get
{
if (this.mappingForm == null)
{
this.mappingForm = new MappingForm();
}
return this.mappingForm;
}
}
#endregion ListEditorForm PROPERTIES
private void ListEditorForm_Load(object sender, EventArgs e)
{
string headerLine;
using (StreamReader sr = new StreamReader(dataFile))
{
headerLine = sr.ReadLine();
}
testDataSet = new DataSet("HeaderDataSet");
headerTable = new DataTable("ClientHeaders");
DataColumn newColumn = new DataColumn("ClientHeader", typeof(string));
headerTable.Columns.Add(newColumn);
newColumn = new DataColumn("StandardHeader", typeof(string));
headerTable.Columns.Add(newColumn);
DataRow newRow = null;
foreach (string s in headerLine.Split(','))
{
newRow = headerTable.NewRow();
newRow[0] = s;
newRow[1] = "Property";
headerTable.Rows.Add(newRow);
}
testDataSet.Tables.Add(headerTable);
DataGridViewComboBoxColumn cbCol =
this.dataGridView1.Columns["standardColumn"] as DataGridViewComboBoxColumn;
cbCol.DataSource = this.standardList;
this.dataGridView1.AutoGenerateColumns = false;
this.dataGridView1.Columns[0].DataPropertyName = "ClientHeader";
this.dataGridView1.Columns[1].DataPropertyName = "StandardHeader";
this.dataGridView1.DataSource = testDataSet;
this.dataGridView1.DataMember = "ClientHeaders";
}
private void btnGetValue_Click(object sender, EventArgs e)
{
this.MakeHeaderDictionaries();
this.MappingForm.HeaderDictionary = this.clientHeaders;
this.MappingForm.DataFile = this.dataFile;
this.MappingForm.FormClosing += new FormClosingEventHandler(MappingForm_Closed);
this.MappingForm.Show();
}
void MappingForm_Closed(object sender, FormClosingEventArgs e)
{
this.docsDictionary = this.MappingForm.DocumentsDictionary;
this.ProcessMods();
this.testDataSet.Tables["StandardData"].WriteXml("TestData.xml", XmlWriteMode.WriteSchema);
}
}
There are no changes to MappingForm, at this time.
TestData.xml will be in the debug directory. When examining it you must remember that the code, as is, only corrects the 'Documentation' column.
I also found out why the FieldMappingDictionary gave you errors the first time, here is the corrected version:
public class FieldMappingDictionary : Dictionary<string, List<string>>
{
public void Add(string key, string value)
{
if (base.ContainsKey(key))
{
if (!base[key].Contains(value))
{
base[key].Add(value);
}
}
else
{
List<string> list = new List<string>();
list.Add(value);
base.Add(key, list);
}
}
}
Let me know what you think. Be gentle with me.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
If I had more than two brain cells to rub together, I would have written this:
void MappingForm_Closed(object sender, FormClosingEventArgs e)
{
this.docsDictionary = this.MappingForm.DocumentsDictionary;
this.ProcessMods();
this.testDataSet.Tables["ClientData"].WriteXml("ClientTestData.xml", XmlWriteMode.WriteSchema);
this.testDataSet.Tables["StandardData"].WriteXml("StandardTestData.xml", XmlWriteMode.WriteSchema);
}
This should make it easier to compare unmodified and modified data. You should also note that the column names have been modified in the StandardTestData.xml version.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Henry,
This is great! Very well organized and I like the idea of having the ability to contain the integrity of the original data set. I also like the idea of outputting to an xml file as well as comparing both the original data set to the standardized data set.
I did have to modify some of the code you sent over. I had to add <string> to List and <string, string> to the Dictionaries. Let me know if this is not correct and I will go back through and make the recommended changes.
I'm still having problems populating the dgv on form 1. Maybe it's that I have not added some functionality to it. On Form 1 I added a dgv and a button name dataGridView1 and btnGetValue. On Form 2 I added a dgv and a button named dgvDocumentation and btnOK. Am I forgetting anything? I have read through the code and it compiles but just can't pinpoint what's going on.
You’re the man Henry!!!
|
|
|
|
|
bwood2020 wrote: I'm still having problems populating the dgv on form 1. Maybe it's that I have not added some functionality to it. On Form 1 I added a dgv and a button name dataGridView1 and btnGetValue. On Form 2 I added a dgv and a button named dgvDocumentation and btnOK. Am I forgetting anything? I have read through the code and it compiles but just can't pinpoint what's going on.
That sounds right.
I'll go through my designer code to see if I've forgotten to tell you something obvious.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Er..................
I did tell you that I had added two dgv columns, in the designer, didn't I?
No, you say!
ahem:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.btnGetValue = new System.Windows.Forms.Button();
this.clientColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.standardColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.headersBindingSource = new System.Windows.Forms.BindingSource(this.components);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.headersBindingSource)).BeginInit();
this.SuspendLayout();
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.clientColumn,
this.standardColumn});
this.dataGridView1.Location = new System.Drawing.Point(12, 12);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(284, 171);
this.dataGridView1.TabIndex = 0;
this.btnGetValue.Location = new System.Drawing.Point(154, 236);
this.btnGetValue.Name = "btnGetValue";
this.btnGetValue.Size = new System.Drawing.Size(75, 23);
this.btnGetValue.TabIndex = 1;
this.btnGetValue.Text = "Value";
this.btnGetValue.UseVisualStyleBackColor = true;
this.btnGetValue.Click += new System.EventHandler(this.btnGetValue_Click);
this.clientColumn.HeaderText = "Client Header";
this.clientColumn.Name = "clientColumn";
this.standardColumn.HeaderText = "Standard Header";
this.standardColumn.Name = "standardColumn";
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 14F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(422, 288);
this.Controls.Add(this.btnGetValue);
this.Controls.Add(this.dataGridView1);
this.Name = "ListEditorForm";
this.Text = "List Editor";
this.Load += new System.EventHandler(this.ListEditorForm_Load);
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.headersBindingSource)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.Button btnGetValue;
private System.Windows.Forms.BindingSource headersBindingSource;
private System.Windows.Forms.DataGridViewTextBoxColumn clientColumn;
private System.Windows.Forms.DataGridViewComboBoxColumn standardColumn;
Here is the designer code for the first form. Just replace the code in your form1.designer.cs file with it.
I think I'll go for a lie down in a dark room now.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
|
|
|
|
|
Ha-ha, you have a very good sense of humor. It makes it more fun and adds to my dull and busy day. You are correct sir. You did have that. I am looking through Form 2 and I see I need to add something else to get this to work. One down and one to go. I will follow up with you tomorrow. Thanks again Henry and have a good night!
|
|
|
|
|
Hi Henry,
I was extremely busy yesterday but I was able to work on this demo for about an hour. As it turns out I am having difficulties getting the second form to work. I looked through the code again and saw that I was missing a combobox so I added that to the dgv; however this didn't fix the issue. Can you send the designer code for the second form when you get a chance please?
Thank you,
Brenton
|
|
|
|
|
Hi Henry,
Thank you for sending me the demo. Even though I was not able to get it to work, I was able to get my app working by dissecting the code you wrote. I'm sorry I caused you frustration and thank you again for helping me on this. I will close this out now and give you the rating you deserve.
Thanks again,
Brenton
|
|
|
|
|
Hello.
I have a application with a webclient. In that webclient I am loading a homepage with about 5 frames, but one of the frames are refreshing constantly each 30second.
That gives me problem when I want to use the source from another frame - because when I use IsBusy and it is refreshing the frame with constantly refreshing while I am navigating another frame, does the application think that frame is done navigating too, and then I of course get an error.
It happens very often, and stops the whole program.
So is there any way only to check one frame if it is done loading ?
Hope your guys can help me out.
|
|
|
|
|
hello,
i am using the WebBrowser Navigate to navigate to a webpage from my c# application.
i try to post data to a form which is in that page. (its my page , i control it)
first , what is the name of the field i need to put in the post string?
is it ID or NAME ?
second , i tried various methods but none filled the form textbox with the information i sent. what am i doing wrong?
here's the c# code
WebBrowser Web = new WebBrowser();
string postdata = "ctl00_pass=1234";
System.Text.Encoding a = System.Text.Encoding.UTF8;
byte[] SendBytes = a.GetBytes(postdata);
Web.Navigate(WebBase + WebAddress, WebTitle, SendBytes, "Content-Type: application/x-www-form-urlencoded");
.
and here's the website
&lt;form name="aspnetForm" method="post" action="default.aspx?key=5555" id="aspnetForm"&gt;
&lt;input name="ctl00$pass" type="text" id="ctl00_pass" /&gt;
</form>
.
tnx
|
|
|
|
|
Hi,
In my C# application, I need to convert EBCDIC data to ASCII. This EBCDIC data is stored as BLOB type in Teradata. This data also has packed decimals in it.
I tried the code i found on internet, which simply converts EBCDIC to ASCII. In that there a interger array of 256 characters only. But the characters which i need to convert,
char chrItem = Convert.ToChar(strEbcidic.Substring(i, 1));
returns number much higher then 256. So i get 'index out of bound of array exception'. The EBCDIC characters include 'ÁõÁõöôùô@@@@ðóùòùùðñ@ððððð' also.
Could any one please help me out here?
Thanks,
Deepa
|
|
|
|
|
I think the problem may be that your input is not EBCDIC - ebcdic is an 8-bit code so only has characters 000 to 255.
Wiki on EBCDIC[^]
No trees were harmed in the sending of this message; however, a significant number of electrons were slightly inconvenienced.
This message is made of fully recyclable Zeros and Ones
|
|
|
|
|
Hi,
Yes, none of these characters in the file are in the 255 codes of EBCDIC.
As i had mentioned earlier, the file from the BLOB, contains packed decimal also.
Are you sure its not EBCDIC, when i do .ToCharArray() i get like:
[0]: 22909 '好'
[1]: 8224 '†'
[2]: 8256 '⁀'
[3]: 8592 '←'
[4]: 879 'ͯ'
[5]: 12629 'ㅕ'
[6]: 16527 '䂏'
[7]: 16448 '䁀'
[8]: 16448 '䁀'
[9]: 16448 '䁀'
[10]: 16448 '䁀'
[11]: 16448 '䁀'
[12]: 16448 '䁀'
[13]: 65533 '�'
[14]: 49605 '쇅'
[15]: 16601 '䃙'
[16]: 16448 '䁀'
[17]: 16448 '䁀'
[18]: 16448 '䁀'
[19]: 16448 '䁀'
[20]: 16448 '䁀'
[21]: 16448 '䁀'
[22]: 16448 '䁀'
[23]: 62448 ''
[24]: 63216 ''
[25]: 63220 ''
[26]: 63473 ''
[27]: 63216 ''
[28]: 62451 ''
[29]: 61689 ''
[30]: 54769 '헱'
[31]: 16448 '䁀'
[32]: 16448 '䁀'
[33]: 16448 '䁀'
[34]: 16448 '䁀'
So their character codes are greater then 255.
How to resolve this?
|
|
|
|
|
The problem is that chars in .NET are Unicode, which is generally two bytes. Using a byte array instead of a char array might solve your problem.
|
|
|
|
|
I highly recommend using Jon Skeet's EBCDIC encoding library[^]
We have been using this for years. You basically just set up Encoding objects and pass them into Stream objects.
Granted, this is VB.NET code, but it should still make sense:
Dim inputEncoding As Encoding = EbcdicEncoding.GetEncoding("EBCDIC-US")
Dim outputEncoding = Encoding.ASCII
Dim inputReader As StreamReader
Dim outputWriter As StreamWriter
inputReader = New StreamReader(inputFile, inputEncoding)
outputWriter = New StreamWriter(outputFile, False, outputEncoding)
I don't claim to be a know it all, for I know that I am not...
I usually have an answer though.
|
|
|
|
|
how to install the Jon Skeet's EBCDIC encoding library[
|
|
|
|
|
Try This
#region public static byte[] ConvertAsciiToEbcdic(byte[] asciiData)
public static byte[] ConvertAsciiToEbcdic(byte[] asciiData)
{
// Create two different encodings.
Encoding ascii = Encoding.ASCII;
Encoding ebcdic = Encoding.GetEncoding("IBM037");
//Retutn Ebcdic Data
return Encoding.Convert(ascii, ebcdic, asciiData);
}
#endregion
#region public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData)
public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData)
{
// Create two different encodings.
Encoding ascii = Encoding.ASCII;
Encoding ebcdic = Encoding.GetEncoding("IBM037");
//Retutn Ascii Data
return Encoding.Convert(ebcdic, ascii, ebcdicData);
}
#endregion
|
|
|
|
|
Hi...
I am using c#.net and sql2005.and in my form i am taking datetime picker for date.in sql taken datatype as datetime. it takes date correctly but it cant take time correctly,taken 12:00 default for all records.
i want to add current date and time in database.
Suggest me something.
|
|
|
|
|
DateTime.Now retrieves the current date and time
I are troll
|
|
|
|
|