简体   繁体   中英

How to read decimal and dates from Excel with C# and ADO.NET

I am trying to read an Excel file in my ASP.NET application using the following piece of code (ADO.NET):

// Create OleDbCommand object and select data from worksheet Sheet1    
String query = String.Format("Select * From [{0}$]", sheetName);
OleDbCommand cmd = new OleDbCommand(query, oledbConn);

// Create new OleDbDataAdapter
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;

//Fills Data to DataTable
oleda.Fill(dt);

The problem is that values in the data table are represented

1) For decimals either with a comma (3,14) or with a dot (3.14)

2) For dates with either the format 'DD/MM/YYYY' or'MM/DD/YYYY'

For the same Excel file depending on the locale settings server has.

Is there any way to read the data in a specific locale in order to get the correct values from the Excel file?

In the case of the column with decimals, use the following to parse them: ( Decimal.Parse )

string decimal1 = "3,14";
string decimal2 = "3.14";

decimal d1 = decimal.Parse(decimal1, new NumberFormatInfo { NumberDecimalSeparator = "," });
decimal d2 = decimal.Parse(decimal2);

Note that with a , you need to use a custom NumberFormatInfo for it to parse right.

Then for your DateTime column:

string date1 = "14/03/2018";
string date2 = "03/14/2018";

DateTime dt1 = DateTime.ParseExact(date1, "dd/MM/yyyy", CultureInfo.InvariantCulture);
DateTime dt2 = DateTime.ParseExact(date2, "MM/dd/yyyy", CultureInfo.InvariantCulture);

Here you will want to specify the differnt formats for your dates.


EDIT:

To be more general about parsing an unknown DateTime format, you could try iterating through all the formats for your CultureInfo or multiple CultureInfo if you know there might be more than one. An example is below of how you could do this:

string dateTimeString = @"03/14/2018";

string[] possibleStandardFormats = new CultureInfo("en-US")
                                     .DateTimeFormat.GetAllDateTimePatterns();

DateTime? result = null;
foreach (string format in possibleStandardFormats) {
    if (DateTime.TryParse(dateTimeString, out DateTime dateTime)) {
        // this format could work
        result = dateTime;
        break;
    }
}

if (result == null) {
    // no luck with any format
    // try one last parse
    if (DateTime.TryParse(dateTimeString, out DateTime dateTime)) {
        // finally worked
        result = dateTime;
    }
    else {
        // no luck
    }
}

Here it may be more effective to try the general DateTime.TryParse first (shown at the end of this example), as it could save you the iterations through the other formats. Up to you how you want to handle this, but this example should handle the majority of the cases.

EDIT 2:

In order to get the standard DateTime formats, you can use the CurrentCulture which will help with your dates. In my previous edit, I hard coded new CultureInfo("en-US") , but the below is a bit more general.

string[] possibleStandardFormats = new CultureInfo(CultureInfo.CurrentCulture.Name)
                                            .DateTimeFormat.GetAllDateTimePatterns();

EDIT 3: To expound a bit more on the previous parsing of decimals, first check if the string has a comma and then parse it according to the method I have listed above.

string decimal1 = "3,14";

if (decimal1.Contains(",")) {
    decimal d1 = decimal.Parse(decimal1, new NumberFormatInfo { NumberDecimalSeparator = "," });
}
else {
    decimal d1 = decimal.Parse(decimal1);
}

EDIT 4:

To incorporate culture into parsing decimals, you can try the Convert.ToDecimal method. One of its parameters takes a CultureInfo where you can pass in your current culture as CultureInfo.CurrentCulture . For example below, I am using de-de (German) since that is a valid culture for 1.234,14

string decimal1 = "1.234,14";
string decimal2 = "1,234.14";

decimal d1 = Convert.ToDecimal(decimal1, new CultureInfo("de-de"));
decimal d2 = Convert.ToDecimal(decimal2, CultureInfo.CurrentCulture);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM