WriteXML, ReadXML Issue with Table Name - c#

I have a program where I run a query and store data in a DataTable. I then allow the user to save that DataTable.WriteXML. The problem I have is that I want to read that saved file (XML file) into another DataTable with a different name - and it does not allow it! It gives me an error "Error while loading Results Table to File: Data Table: 'ImportTable' does not match to any DataTable in Source"
Now I believe this message is telling me that the XML contains a different table name than the DataTable I am trying to ReadXML into it. I have tried setting the TableName property to blank - but that does not make any difference.
So - my question is how do others get around this issue? I am using the standard DataTable.WriteXML(filename) - and DataTable.ReadXML method calls. AND due to some design issues - I do need to have the import DataTable named differently than the one used to export the data.
Is there a different way to write out and read in the data in the DataTable that will get around this issue?
Sample code - showing the issue
In the form load - create two tables - one named Export the other Import. Create a structure for Export - and populate it with 10 records.
private void Form_Main_Load(object sender, EventArgs e)
{
ExportTable = new DataTable("Export");
ImportTable = new DataTable("Import");
ExportTable.Columns.Add("ID", Type.GetType("System.Int32"));
ExportTable.Columns.Add("Name", Type.GetType("System.String"));
ExportTable.Columns.Add("Amount", Type.GetType("System.Int32"));
// Populate the first one
DataRow workRow;
for (int i = 0; i <= 9; i++)
{
workRow = ExportTable.NewRow();
workRow[0] = i;
workRow[1] = "CustName" + i.ToString();
workRow[2] = i;
ExportTable.Rows.Add(workRow);
}
}
Then create two buttons - one for exporting the data - the other for importing the data.
private void button_Export_Click(object sender, EventArgs e)
{
ExportTable.WriteXml("c:\\Temp\\TableOut.xml");
}
private void button_Import_Click(object sender, EventArgs e)
{
ImportTable.ReadXmlSchema("c:\\Temp\\TableOut.xml");
ImportTable.ReadXml("c:\\Temp\\TableOut.xml");
}
Run the program - export the data - then click on the Import button. When you do - you will get the error - "DataTable 'Import' does not match to any DataTable in source."
Now - I realize it is because the XML has the Export table name embedded in the XML. In my case I need to import that data into a DataTable with a different name - and I am wondering how (and if) others have dealt withi this in the past? Did you manually change the name in the XML? Did you temporarily change the datatable name? OR is there another better way around this issue of trying to use the READXML method of a DataTable?

Ok - I have been playing around with this - and have a solution. Not sure it is the best (and I would appreciate any comments as to how I might do this better).
Basically what I had to do was write the XML out to a string reader - change the table name for the schema and the record elements. Both the <> and tags.
Then when I read it in - I had to do the reverse - basically read the file into a string - then change all the table names back to what I needed them to be. Then I had to write the file out to disk (temporary file) - and then use the ReadXML method to read that temp file and then delete the file.
I am not sure why the ReadXML with a string reader did not work (it seems to be a valid parameter) - but I had found a few posts that stated there were issues with the READXML method and string readers - so I simply wrote it out to file and used READXML with the file name - and it worked fine.
I hope this helps others - even if it is not the 'best' solution - maybe someone else can improve on it.
Write XML
// Write XML
StringWriter sw = new StringWriter();
ResultDT.WriteXml(sw, XmlWriteMode.WriteSchema);
string OutputXML = sw.ToString();
// now replace the Table Name
OutputXML = OutputXML.Replace("<" + ResultDT.TableName + ">", "<" + "ExportTable" + ">");
OutputXML = OutputXML.Replace("</" + ResultDT.TableName + ">", "</" + "ExportTable" + ">");
OutputXML = OutputXML.Replace("MainDataTable=\"" + ResultDT.TableName + "\"", "MainDataTable=\"" + "ExportTable" + "\"");
OutputXML = OutputXML.Replace("name=\"" + ResultDT.TableName + "\"", "name=\"" + "ExportTable" + "\"");
System.IO.File.WriteAllText(fileName, OutputXML);
Read XML
// Read XML
InputXML = System.IO.File.ReadAllText(fileName);
// now replace the Table Name
InputXML = InputXML.Replace("<" + "ExportTable" + ">", "<" + ResultTable.TableName + ">");
InputXML = InputXML.Replace("</" + "ExportTable" + ">", "</" + ResultTable.TableName + ">");
InputXML = InputXML.Replace("MainDataTable=\"" + "ExportTable" + "\"", "MainDataTable=\"" + ResultTable.TableName + "\"");
InputXML = InputXML.Replace("name=\"" + "ExportTable" + "\"", "name=\"" + ResultTable.TableName + "\"");
string TempFileName = "TempDumpFile.idt";
System.IO.File.WriteAllText(TempFileName, InputXML);
ResultTable.ReadXmlSchema(TempFileName);
ResultTable.ReadXml(TempFileName);
System.IO.File.Delete(TempFileName);

Related

How to write array values to columns of same line C#

I have a loop, which writes the values of an array into a .csv file. It is appending each line, so it writes the values vertically, however, I would like it to write each value in a different column rather than by line, that way I can filter the content after running the program.
My initial thought was to save all the values in one variable and then just write the variable to the .csv file, but I believe this would fill all values into one cell instead of distributing them to different columns.
I need it to write all of the values of the array on each loop, and then move to the next line on the each time it loops if that makes sense.
string pathCleansed = #"myfilename.csv";
string[] createText = {
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress1,
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress2,
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].SubDivision,
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].City,
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].PostalCode,
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].MainDivision,
resCleansedMulti.TaxAreaResult[0].confidenceIndicator
};
File.AppendAllLines(pathCleansed, createText, System.Text.Encoding.UTF8);
These are the current results: current results
This is what I would like it to do: desired results
I have had good success with CsvHelper package. You can find more information about it here https://joshclose.github.io/CsvHelper/api/CsvHelper/CsvWriter/.
This helper implements IDisposable so be sure to dispose if it when you're done or wrap it in a using which is more preferred. You will have to provide a writer object to CsvHelper. In the past I've used MemoryStream and StreamWriter.
//Headers if you want
csvWriter.WriteField("StreetAddress1");
csvWriter.WriteField("StreetAddress2");
csvWriter.WriteField("subDivision");
csvWriter.WriteField("City");
csvWriter.WriteField("PostalCode");
csvWriter.WriteField("MainDivision");
csvWriter.WriteField("ConfidenceIndicator");
csvWriter.NextRecord();
//Your Loop Here
{
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress1);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress2);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].SubDivision);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].City);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].PostalCode);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].MainDivision);
csvWriter.WriteField(resCleansedMulti.TaxAreaResult[0].confidenceIndicator);
csvWriter.NextRecord();
}
Update: I was able to get the desired results by changing to code to:
string pathCleansed = #"myfilename.csv";
string[] createText = {
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress1 + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress2 + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].SubDivision + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].City + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].PostalCode + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].MainDivision + "," +
resCleansedMulti.TaxAreaResult[0].confidenceIndicator
};
File.AppendAllLines(pathCleansed, createText, System.Text.Encoding.UTF8);

FileInfo.GetFiles() and special characters (accents)

When I insert in DB a string that contains special character as a "à" or a "é" from a FileInfo.GetFiles() item, I get issues and SQL save splitted special char. Non-special chars are OK.
For instance, "à" becomes "a`", and "é" becomes "e´". Did anyone get this kind of trouble?
Here is the code
DirectoryInfo di = new DirectoryInfo(path);
foreach (FileInfo fi in di.GetFiles())
{
Logger.LogInfo("Info: " + fi.Name);
}
Basically, if string is "sàrl", log saved "Info: sa`rl"
When I breakpoint trough VS, I see the string with "à" but when I log it, char are splitted.
My SQL collation is Latin CI AS (SQL_Latin1_General_CP1_CI_AS) and DB already host string with special char without problem.
Thanks folks
EDIT
I have trouble when I insert the fi.Name into the final table too:
public bool InsertFile(string fileName, Societe company, string remark, PersonnelAM creator)
{
string commandText = (#"INSERT INTO [dbo].[TB_DOCSOCIETE_COM] " +
"([IdtSOC] " +
",[NomDOC] " +
",[RemDOC] " +
",[DateDOC] " +
",[IdtPER]) " +
"VALUES " +
"(#company" +
",#fileName" +
",#remark" +
",#date" +
",#creator) SELECT ##IDENTITY");
var identity = CreateCommand(commandText,
new SqlParameter("#fileName", DAOHelper.HandleNullValueAndMinDateTime<string>(fileName)),
new SqlParameter("#company", DAOHelper.HandleNullValueAndMinDateTime<int>(company.Id)),
new SqlParameter("#remark", DAOHelper.HandleNullValueAndMinDateTime<string>(remark)),
new SqlParameter("#date", DAOHelper.HandleNullValueAndMinDateTime<DateTime>(DateTime.Now)),
new SqlParameter("#creator", DAOHelper.HandleNullValueAndMinDateTime<int>(creator.id))
).ExecuteScalar();
return int.Parse(identity.ToString()) > 0;
}
I'm using NLog so data is varchar(8000) for message column and code that logs message is
public static bool LogInfo(Exception ex, string message = "")
{
try
{
GetLogger().Log(LogLevel.Info, ex, message);
}
#pragma warning disable 0168
catch (Exception exception)
#pragma warning restore 0168
{
return false;
}
return true;
}
EDIT 2 :
To be clear about DB, those 3 lines:
Logger.LogInfo("BL1 " + "sàrl is right saved");
Logger.LogInfo("BL2 " + fi.Name + " is not right saved");
Logger.LogInfo("BL3 " + "sàrl" + " - " + fi.Name + " is not right too!");
Gave me that result in DB:
BL1 sàrl is right saved
BL2 ENTERPRISE Sa`rl - file.pdf is not right saved
BL3 sàrl - ENTERPRISE Sa`rl - file.pdf is not right too!
So it doesn't come from DB, it is an issue about the string (encoding?)
varchar(8000)
Make the column NVARCHAR. This is not a collation issue. Collations determine the sort order and comparison rules, not the storage. Is true that for non-unicode columns (varchar) the collation is used as hint to determine the code page of the result. But code page will only get you so far, as obviously a 1 byte encoding code page cannot match the entire space of the file system naming, which is 2 bytes encoding Unicode based.
Use an Unicode column: NVARCHAR.
If you want to understand what are you experiencing, just run this:
declare #a nvarchar(4000) = NCHAR(0x00E0) + N'a' + NCHAR(0x0300)
select #a, cast(#a as varchar);
Unicode is full of wonderful surprises, like Combining characters. You can't distinguish them visually, but they sure show up when you look at the actual encoded bytes.

Writing and Reading excel files in C#

I am writing a program that takes data from a website via selenium web driver. I am trying to create football fixture for our projects.
I am so far, I accomplished to take date and time, team names and scores from the website. Also still trying writing on txt file, but it gets little messy while writing on txt file
How do I accomplish writing on excel file, and reading?
I want to write like that
Date-Time First-Team Second-Team Score Statistics
28/07 19:00 AM AVB 2-1 Shot 13123 Pass 65465 ...
28/07 20:00 BM BVB 2-2 Shot 13123 Pass 65465 ...
28/07 20:00 CM CVB 2-3 Shot 13123 Pass 65465 ...
And this is my part of my code :
StreamWriter file = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\Test" + "\\" + pathName + "\\" + subFile + "\\" + pathName + ".txt", false);
for (int k = 2; k > 1; k--)
{
//doing some stuff
}
Writing part:
for (int x = 0; x <dT.Count; x++)
{
file.Write(dateTime[x] + " " + firstTeam[x] + " "
+ secondTeam[x] + " " + firstHalf[x] + " " + secondHalf[x] + " ")
for (int i = 0; i < total_FS.Count(); i++)
{
int index = total_FS[i].Length;
if (total_FS[i][index-1].ToString() != " " && total_FS[i] != "-")
{
file.Write(total_FS[i]);
}
else
{
SpaceC++;
if (total_FS[i][index - 1].ToString() == " ")
file.Write(total_FS[i]);
}
if (SpaceC == 9)
{
file.Write("\n");
SpaceC = 0;
break;
}
}
}
There are few cool libraries that you can use to easy read and write excel files. You can reference them in your project and easily create/modify spreadsheets.
EPPlus
Very developer friendly and easy to use.
EPPlus - codeplex source
Simple tutorial
NOPI
NOPI - codeplex source
DocumentFormat.OpenXml 
It provides strongly typed classes for spreadsheet objects and seems to be fairly easy to work with.
DocumentFormat.OpenXml site
DocumentFormat.OpenXml tutorial
Open XML SDK 2.0 for Microsoft Office
Provides strongly typed classes / easy to work with.
Open XML SDK 2.0 - MSDN
ClosedXML - The easy way to OpenXML
ClosedXML makes it easier for developers to create (.xlsx, .xlsm, etc) files.
ClosedXML - repository hosted at GitHub
ClosedXML - codeplex source
SpreadsheetGear
*Paid - library to import / export Excel workbooks in ASP.NET
SpreadsheetGear site
Instead of creating XLS file, make a CSV text file that can be opened with Excel. Fields are comma separated and each line represents a record.
field11,field12
field21,field22
If a field contains inner commas, it needs to be wrapped in double quotation marks.
"field11(row1,column1)", field12
field21, field22
If a field contains double quotation marks, they need to be escaped. But you can use CsvHelper to do the job. Grab it from Nuget
PM> Install-Package CsvHelper
An example on how to use it.
using(var textWriter = new StreamWriter(#"C:\mypath\myfile.csv")
{
var writer = new CsvWriter(textWriter);
writer.Configuration.Delimiter = ",";
foreach (var item in list)
{
csv.WriteField("field11");
csv.WriteField("field12");
csv.NextRecord();
}
}
Full documentation can be found here.

Trying to update a text file

I'm trying to replace a certain line in a .txt file when I click the Update Button
This is what my program looks like
http://i.imgur.com/HKu4bGo.png
This is my code so far
string[] arrLine = File.ReadAllLines("Z:/Daniel/SortedAccounts.txt");
arrLine[accountComboBox.SelectedIndex] = "#1#" + firstNameInfoBox.Text + "#2#" + lastNameInfoBox.Text + "#3#" + emailInfoBox.Text + "#4#" + phoneNumberInfoBox.Text + "#5#EMAIL#6#";
File.WriteAllLines("Z:/Daniel/SortedAccounts.txt", arrLine);
This is what's inside SortedAccounts.txt
#1#Bob#2#Smith#3#Bob#Smith.com#4#5551234567#5#EMAIL#6#
#1#Dan#2#Lastyy#3#Daniel#Lastyy.com#4#5551234567#5#EMAIL#6#
The ComboBox is in the order as the Txt File.
So I get the same Index as the selected item in the ComboBox. And then I want to delete that line and then add a new line that same txt file with the updated information.
My code isn't doing this for some reason though and I can't figure it out
Try this out using List to easily remove an entry at a certain index. Don't forget to reload the combobox data source when the file is updated to avoid index mismatch etc..
List<string> arrLine = File.ReadAllLines("Z:/Daniel/SortedAccounts.txt").ToList();
arrLine.RemoveAt(accountComboBox.SelectedIndex);
string newLine = "#1#" + firstNameInfoBox.Text + "#2#" + lastNameInfoBox.Text + "#3#" + emailInfoBox.Text + "#4#" + phoneNumberInfoBox.Text + "#5#EMAIL#6#";
arrLine.Add(newLine);
File.WriteAllLines("Z:/Daniel/SortedAccounts.txt", arrLine);

Write tab separated csv file in c#

I am currently developing an application in C# where I need to write a tab separated CSV file from the data that it retrieves from a MySQL Database. The database retrieval works fine.
The problem that I am having is writing the file. Between each variable that I am writing I am using the \t which I thought put a tab into the csv, therefore when opening in excel each variable will be in its own cell.
However for some reason it is not doing this it just writes the whole line as one long string. Below is an example of the code that I am code that I have written:
while (reader.Read())
{
int bankID = reader.GetInt16("ban_bankID");
int userID = reader.GetInt16("ban_userID");
string bankUsername = reader.GetString("ban_username");
string accountName = reader.GetString("ban_accountName");
string accountType = reader.GetString("ban_accountType");
decimal overdraft = reader.GetDecimal("ban_overdraft");
char defaultAccount = reader.GetChar("ban_defaultAccount");
string line = bankID + "\t" + userID + "\t" + bankUsername + "\t" + accountName + "\t"
+ accountType + "\t" + overdraft + "\t" + defaultAccount + "\n";
tw.WriteLine(line);
Thanks for your help with this problem.
The format is correct, a CSV expects the file to be COMMA Separated. When saving a Tab delimited file, typically just a txt extension is used (or some people save as .tsv) etc.
If you look at the Save As options in excel the option is Text (Tab Delimited) .txt
If I open the output generated by your sample code (stubbing in the data) everything loads in to Excel 2007 as you would expect.
The problem is your encoding.
You don't show your TextWriter instantiation, but it should look something like this:
TextWriter tw = new Stream(filename, false, Encoding.ASCII);
You should use the Text Import Wizard: Data / From Text. From there you can specify your delimiter to a tab.

Categories