Recently (nobody noticed it happening before, if it did) some "ID"-type values are being converted by Excel to dates. There is some logic to which values are being converted, as you can see here, where the user added a column to show what the underlying values really are, and how they should be represented (raw, no conversion):
So because there's a "-" after "01" Excel is thinking that "01-" should be January, an assuming the final two characters represent the year.
In Item codes that contain no dash, they are left alone. How can I prevent Excel from being "helpful" in this way and converting these values to dates?
UPDATE
In response to Scott Craner's comment, this is the code I have to write out that value:
using (var memberItemCodeCell = priceComplianceWorksheet.Cells[rowToPopulate, DETAIL_MEMBERITEMCODE_COL])
{
memberItemCodeCell.Style.Font.Size = DATA_FONT_SIZE;
memberItemCodeCell.Value = _memberItemCode;
memberItemCodeCell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
}
...and when I try to figure out how to format the value as Text or General by typing "for" after the cells name, I see these options:
So what do I need to use - FormatedText (sic) or ConditionalFormatting, and how specifically do I set those up to format the column as Text or General, and which if any of these two are preferred?
I generally when preparing the table to put data, I define data type so Excel don't try to find the kind of data.
In this case I would use Text data type. Example:
I think you want to change the number format to text.
The text format is specified with the NumberFormat property using the "at" character.
memberItemCodeCell.Style.Font.Size = DATA_FONT_SIZE;
memberItemCodeCell.NumberFormat = "#";
memberItemCodeCell.Value = _memberItemCode;
memberItemCodeCell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
Also, for what it's worth, take a look at articles / questions regarding the difference between Value and Value2. It's good to understand the difference and use the proper one. In your case, I doubt it matters.
What ended up working for me was using this technique to assign the proper data type to the value in the cell (with the call to ConvertValueToAppropriateTypeAndAssign()) and then formatting as necessary after the fact:
public static readonly string NUMBER_FORMAT_CURRENCY = "$#,##0.00;($#,##0.00)";
public static readonly string NUMBER_FORMAT_THOUSANDS = "#,##0";
public static readonly string PERCENTAGE_FORMAT = "0.00%;[Red]-0.00%";
public static readonly string NUMBER_FORMAT_TEXT = "#";
public static readonly string NUMBER_FORMAT_DOUBLE = "0.00";
. . .
using (var percentageCell = priceComplianceWorksheet.Cells[rowToPopulate, SUMMARY_PERCENTAGE_COL])
{
ConvertValueToAppropriateTypeAndAssign(percentageCell, totalPercentage);
percentageCell.Style.Numberformat.Format = PERCENTAGE_FORMAT;
}
. . .
// Adapted from https://stackoverflow.com/questions/26483496/is-it-possible-to-ignore-excel-warnings-when-generating-spreadsheets-using-epplu
public static void ConvertValueToAppropriateTypeAndAssign(this ExcelRangeBase range, object value)
{
string strVal = value.ToString();
if (!String.IsNullOrEmpty(strVal))
{
decimal decVal;
double dVal;
int iVal;
if (decimal.TryParse(strVal, out decVal))
range.Value = decVal;
if (double.TryParse(strVal, out dVal))
range.Value = dVal;
else if (Int32.TryParse(strVal, out iVal))
range.Value = iVal;
else
range.Value = strVal;
}
else
range.Value = null;
}
I have to parse (C#) a .CSV file, with a variable "width" and 2 lines of header information (the fist one being name and the second one being the unit).
The data looks like:
Example1.CSV:
"timestamp","NAME_1","NAME_2","NAME_3","NAME_4"
"ms","unit_1","unit_2","unit_3","unit_4"
0.01,1.23,4.56,7.89,0.12
0.02,1.23,4.66,7.89,0.11
0.03,1.23,4.76,7.89,0.11
0.04,56.23,4.86,7.89,0.12
Example2.CSV:
"timestamp","NAME_1","NAME_2","NAME_3","NAME_4","NAME_5",...,"NAME_N"
"ms","unit_1","unit_2","unit_3","unit_4","unit_5",...,"unit_N"
0.01,1.23,4.56,7.89,0.12,0.13,...,0.27
0.02,1.23,4.66,7.89,0.12,0.13,...,0.22
0.03,1.23,4.76,7.89,0.11,0.13,...,0.24
0.04,56.23,4.86,7.89,0.12,0.13,...,0.29
With N being the "width" of the table (value can be up to 128 and larger). I'm planning to use Filehelpers.
I thought of using [FieldOptional()] - but that gets very unhandy, especially when the "width" is variable...
My current attempt looks like
[IgnoreFirst(2)]
[DelimitedRecord(",")]
public sealed class LogData
{
public Double ts;
public Double Field1;
[FieldNullValue(0.0)]
[FieldOptional()]
public Double Field2;
[FieldNullValue(0.0)]
[FieldOptional()]
public Double Field3;
// and so on
}
Any help on "how to solve the variable width"-Problem in a more elegant manner is appreciated - Thank you very much in advance!
Ben
If you are planning to convert the file into DataTable, there is a better option
Please use CsvEngine of FileHelpers library. See the code snippet below:
using (MemoryStream stream = new MemoryStream(_fileContent)) //file content can be file as byte array
{
TextReader reader = new StreamReader(stream);
string path = "C:\\Sample.csv";
CsvEngine csvEngine = new CsvEngine("Model", ',', path);
var dataTable = csvEngine.ReadStreamAsDT(reader);
//Do whatever with dataTable
}
Here the sample file can be csv file or text file contains the header of the csv file you want to process. The columns of the DataTable will be named according to the header of the sample file
Cheers
You can use optional array field. I think you need to be using FileHelpers 2.9.9.
[IgnoreFirst(2)]
[DelimitedRecord(",")]
public class LogData
{
public Double TimeStamp;
[FieldNullValue(0.0)]
[FieldOptional, FieldArrayLength(0, 100)]
public Double[] ManyFields;
}
Here's a working example.
class Program
{
static String content =
#"""timestamp"",""NAME_1"",""NAME_2"",""NAME_3"",""NAME_4""
""ms"",""unit_1"",""unit_2"",""unit_3"",""unit_4""
0.01,1.23,4.56,7.89,0.12
0.02,1.23,4.66,7.89,0.11
0.03,1.23,4.76,7.89,0.11
0.04,56.23,4.86,7.89,0.12";
private static void Main()
{
var engine = new FileHelperEngine<LogData>();
var records = engine.ReadString(content);
Assert.AreEqual(0.01, records[0].TimeStamp);
Assert.AreEqual(1.23, records[0].ManyFields[0]);
Assert.AreEqual(4.56, records[0].ManyFields[1]);
Assert.AreEqual(7.89, records[0].ManyFields[2]);
Assert.AreEqual(0.12, records[0].ManyFields[3]);
}
}
I need to take an input from the user, turn all the chars to their decimal value and display the as one string without spaces, then turn it into a string and display it, and afterwards take the number string and turn back to the original string.
A."Hello World" - string
B."72101108108111 87111114108100" - string
C."7210110810811187111114108100" (Processed and displayed) - int
D."72101108108111 87111114108100" - string
E."Hello World" - string
I got to this stage :
string input = Console.ReadLine();
byte[] array = Encoding.ASCII.GetBytes(input);
It's not much but its my first try at creating a program.
here is a example using decimal. but you could also use System.Numerics.BigInteger with its ToString and Parse functions for bigger numbers
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
using System;
namespace big_number
{
class Program
{
static void Main(string[] args)
{
decimal d = 0;
begining:
try {d = Convert.ToDecimal(Console.ReadLine()); }//<------ HERE IT IS!!!
catch (Exception EX)// look up what exceptions you want to catch
{
Console.WriteLine("try again\r\n\n" + EX.Message);//display error (if you want)
d = 0;//just incase
goto begining; // do not run this code outside of debugger you may get caught in inifinite loop
}
//and back again
string s = "" + d;
Console.WriteLine(s);//we could just pass d
Console.ReadLine();
}
}
}
I am using the .Split(',') method on a string that I know has values delimited by commas and I want those values to be separated and put into a string[] object. This works great for strings like this:
78,969.82,GW440,.
But the values start to look different when that second value goes over 1000, like the one found in this example:
79,"1,013.42",GW450,....
These values are coming from a spreadsheet control where I use the controls built in ExportToCsv(...) method and that explains why a formatted version of the actual numerical value.
Question
Is there a way I can get the .Split(',') method to ignore commas inside of quotes? I don't actually want the value "1,013.42" to be split up as "1 and 013.42".
Any ideas? Thanks!
Update
I really would like to do this without incorporating a 3rd party tool as my use case really doesn't involve many other cases besides this one and even though it is part of my work's solution, having a tool like that incorporated doesn't really benefit anyone at the moment. I was hoping there was something quick to solve this particular use case that I was missing, but now that it is the weekend, I'll see if I can't give one more update to this question on Monday with the solution I eventually come up with. Thank you everyone for you assistance so far, I'll will assess each answer further on Monday.
This is a fairly straight forward CSV Reader implementation we use in a few projects here. Easy to use and handles those cases you are talking about.
First the CSV Class
public static class Csv
{
public static string Escape(string s)
{
if (s.Contains(QUOTE))
s = s.Replace(QUOTE, ESCAPED_QUOTE);
if (s.IndexOfAny(CHARACTERS_THAT_MUST_BE_QUOTED) > -1)
s = QUOTE + s + QUOTE;
return s;
}
public static string Unescape(string s)
{
if (s.StartsWith(QUOTE) && s.EndsWith(QUOTE))
{
s = s.Substring(1, s.Length - 2);
if (s.Contains(ESCAPED_QUOTE))
s = s.Replace(ESCAPED_QUOTE, QUOTE);
}
return s;
}
private const string QUOTE = "\"";
private const string ESCAPED_QUOTE = "\"\"";
private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}
Then a pretty nice Reader implementation - If you need it. You should be able to do what you need with just the CSV class above.
public sealed class CsvReader : System.IDisposable
{
public CsvReader(string fileName)
: this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
}
public CsvReader(Stream stream)
{
__reader = new StreamReader(stream);
}
public System.Collections.IEnumerable RowEnumerator
{
get
{
if (null == __reader)
throw new System.ApplicationException("I can't start reading without CSV input.");
__rowno = 0;
string sLine;
string sNextLine;
while (null != (sLine = __reader.ReadLine()))
{
while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
sLine += "\n" + sNextLine;
__rowno++;
string[] values = rexCsvSplitter.Split(sLine);
for (int i = 0; i < values.Length; i++)
values[i] = Csv.Unescape(values[i]);
yield return values;
}
__reader.Close();
}
}
public long RowIndex { get { return __rowno; } }
public void Dispose()
{
if (null != __reader) __reader.Dispose();
}
//============================================
private long __rowno = 0;
private TextReader __reader;
private static Regex rexCsvSplitter = new Regex(#",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))");
private static Regex rexRunOnLine = new Regex(#"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$");
}
Then you can use it like this.
var reader = new CsvReader(new FileStream(file, FileMode.Open));
Note: This would open an existing CSV file, but can be modified fairly easily to take a string[] like you need.
Since you're reading a CSV file, the best course of action would be to use an existing CSV reader. There's more to CSV than just commas between quotes. Finding all of the cases you need to handle would be more work than it's worth.
Here's a CSV reader question on SO.
You should probably read this article: Regular Expression for Comma Based Splitting Ignoring Commas inside Quotes
Although it is for Java, but the regular expression is the same.
I have the following code:
class Program
{
static void Main(string[] args)
{
string linie;
foreach (string elem in Directory.GetFiles(#"C:\Users\A\Desktop\FIles", "*.txt"))
{
Console.WriteLine(elem);
StreamReader reader = new StreamReader(elem);
{
while (!reader.EndOfStream)
{
linie=reader.ReadLine();
Console.WriteLine(linie);
}
}
reader.Close();
}
Console.ReadKey();
Console.WriteLine(DateTime.ParseExact("5/10/2005", "m/d/yyyy", null).Day);
}
}
What i need is to select only the Date from a file.
For example if i have the string "the date is 20/2/2012" in a .txt file, i need to substract only 20/2/2012 and to compare it with the current date.
If you want an easy lazy solution, you can always add a : and Split on it. (You could split on white spaces but then I would have to count for the index and I don't want to do this).
string dateFromFile = "The date is : 20/2/2012";
string[] dateString = dateFromFile.Split(':');
string myDate = dateString[1];
Ok I looked at my answer and decided I was too lazy...
string dateFromFile = "The date is 20/2/2012";
string[] dateString = dateFromFile.Split(' ');
string myDate = dateString[3];
It splits the string everytime it sees the sepcified character and returns a String[].
In the second example (where I split on white space, the array would look like this)
dateString[0] = "The"
dateString[1] = "date"
dateString[2] = "is"
dateString[3] = "20/2/2012"