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.
Related
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);
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);
I am exporting a csv file and getting the date field and phone number field masked as shown in the image below. The problem occurs only when I open the exported file in Microsoft Excel not on other platforms
What I want to do is remove the mask and show the birth date and number properly as: birth date: "12/11/2016" and number as "123456789".
Note: birth date is datetime AND cell_phone or mobile number is string
The code I used to create this is as follows:
foreach (EmployeeDataExportObject item1 in _obj_distinct_company)
{
sb.Append(string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21}"
, item1.client_id
, item1.employee_number
, item1.employee_status_type
, item1.first_name.Replace(",", "")
, item1.middle_name.Replace(",", "")
, item1.last_name.Replace(",", "")
, '"' + item1.ssn.ToString() + '"'
, '"' + birth_date.ToString("MM-dd-yyyy") + '"' //problem is on this part
, Address.Replace(",", "")
, item1.address2.Replace(",", "")
, item1.city
, item1.state
, item1.zip_code
, item1.country
, '"' + item1.cell_phone.ToString().Replace("-", "").Replace("(", "").Replace(")", "").Replace(".", "").Replace(" ", "") + '"' //problem is on this part
, item1.pay_rate1
, item1.pay_rate_amount1.ToString("0.00")
, item1.pay_rate2
, item1.pay_rate_amount2.ToString("0.00")
, item1.employee_status_type
, item1.termination_reason.Replace(",", " ")
, item1.termination_date.ToString("MM-dd-yyyy"))
+ Environment.NewLine);
}
_fileName = item.company_name;
if (!Directory.Exists(paychex_folder))
Directory.CreateDirectory(paychex_folder);
filepath = paychex_folder + _fileName + ".csv";
File.WriteAllText(filepath, sb.ToString());
}
What do you mean by masked, can you attach a screenshot of the excel file?
If a column with a date in is not wide enough, the value is shown as ###### - is this the problem you are having?
It's actually easier to create an XLSX file using a library like EPPLus. XSLX files are zipped XML files which can be generated without having Excel installed. With EPPlus you can fill a sheet with data from a DataTable or collection with a simple call to LoadFromDatatable or LoadFromCollection, eg:
FileInfo targetFile = new FileInfo(targetFile);
using (var excelFile = new ExcelPackage(targetFile))
{
var sheet = excelFile.Workbook.Worksheets.Add("Sheet1");
sheet.LoadFromCollection(_obj_distinct_company, PrintHeaders: true);
excelFile.Save();
}
EPPlus takes care to serialize dates in the decimal format (OA Date) expected by Excel.
LoadFromCollection returns an ExcelRange object which you can use to further format rows and columns, or create a named table, eg:
var range1=sheet.LoadFromCollection(_obj_distinct_company, PrintHeaders: true);
var table = sheet.Tables.Add(range, "Companies");
table.TableStyle = TableStyles.Light2;
I'm currently pooping out, I am having trouble displaying lines from a text document. What I mean is whenever I press enter it displays a new line of the text document.
Thanks
This is I guess some code, this is referenced to a text document and received a definition, from here it receives it and gets it ready to display but I just need it to read from say result one line at a time every time I press enter
First line wont work this is the first line ->>>>
var result = GetLinesWithWord(i1, #"" + Path + "/dict2.txt");
// Display the results.
foreach (var line1 in result)
{
//word maxlength
const int MaxLength = 82;
var name1 = line1;
if (name1.Length > MaxLength)
name1 = name1.Substring(0, MaxLength);
Console.WriteLine(name1 + "\r");
string boc1 = name1;
string foc1 = i1;
System.IO.File.AppendAllText (#"" + Path + "/" + n + ".txt", foc1 + "\n" + boc1 + "\n");
If I understand you correctly (especcialy your comment to #MairajAhmad) you want to dump the text file line by line, waiting for the user to press a key after each line.
Look at the post here. I think, that is what you need. It's basically a call to Console.ReadKey(true). The mentioned post listen's for the escape key, but it should still illustrate what to do.
A label printer is controled by sending a string of raw ASCII characters (which formats a label). Like this:
string s = "\x02L\r" + "D11\r" + "ySWR\r" + "421100001100096" + date + "\r" + "421100002150096" + time + "\r" + "421100001200160" + price + "\r" + "E\r";
RawPrinterHelper.SendStringToPrinter(printerName, s);
This hardcoded variant works well.
Now I want to put the control string to a .txt file and read it during runtime. Like this:
string printstr;
TextReader tr = new StreamReader("print.txt");
printstr = tr.ReadLine();
tr.Close();
But in this case printer prints nothing.
It seems, that StreamReader adds something else to this string
(If I put the read string to a MessageBox.Show(printstr); everything looks OK. Though, this way we can not see control characters added).
What could be a solution to this problem?
Your code calls tr.ReadLine() once, but it looks like you have multiple lines in that string.
Looks like a Zebra label printer, I've had the displeasure. The first thing you need to fix is the way you generate the print.txt file. You'll need to write one line for each section of the command string that's terminated with \r. For example, your command string should be written like this:
printFile.WriteLine("\x02L");
printFile.WriteLine("D11");
printFile.WriteLine("ySWR");
printFile.WriteLine("421100001100096" + date);
printFile.WriteLine("421100002150096" + time);
printFile.WriteLine("421100001200160" + price);
printFile.WriteLine("E");
printFile.WriteLine();
Now you can use ReadLine() when you read the label from print.txt. You'll need to read multiple lines to get the complete label. I added a blank line at the end, you could use that when you read the file to detect that you got all the lines that creates the label. Don't forget to append "\r" again when you send it to the printer.
It could be that the StreamReader is reading it in an Unicode format. By the way, you are reading in only just one line...you need to iterate the lines instead...Your best bet would be to do it this way:
string printstr;
TextReader tr = new StreamReader("print.txt",System.Text.Encoding.ASCII);
printstr = tr.ReadToEnd();
tr.Close();
Or read it as a binary file and read the whole chunk into a series of bytes instead, error checking is omitted.
System.IO.BinaryReader br = new System.IO.BinaryReader(new StreamReader("print.txt", System.Text.Encoding.ASCII));
byte[] data = br.ReadBytes(br.BaseStream.Length);
br.Close();
Edit:
After rem's comment I thought it best to include this additional snippet here...this follows on from the previous snippet where the variable data is referenced...
string sData = System.Text.Encoding.ASCII.GetString(data);
Hope this helps,
Best regards,
Tom.