由Excel生成的CSV文件中的数字

不幸的是,当Excel生成CSV文件时,它并不是非常适合程序员,因为它存储了屏幕上显示的数字。 CSV中数字的外观如何取决于区域设置和用户的喜好。

结果,我可能会看起来像数字

2 123 3'322 1,233.44 2123,45 

等等

现在我必须在我的程序中处理这样的CSV文件。

除了告诉用户如何构build他们的CSV文件 – 是否有任何聪明或规范的解决scheme如何处理这个问题? 切换到另一种数据格式也是一种select – 但哪一个? 它必须由Excel本地支持,它应该很容易处理(所以我想避免xlsx)。

我有一个客户端相同的问题,我已经写了一个导出到csvmacros,明确告诉excel格式的每一列,这里是一个代码的例子

 Public Sub Export_To_CSV() 'Give excel the sheet with data to be exported to CSV Sheets("Sheet1").Activate 'Declare your string array to be filled - currently set to 5 columns Dim csvread(1 To 5) As String Dim i As Integer i = 1 Dim ObjFso Dim StrFileName Dim ObjFile 'Name the export csv - This will generate it in the folder you have the excel you are working with in and then names it CSVexport-Day-Month.csv StrFileName = Application.ThisWorkbook.Path & "\CSVExport-" & Day(Date) & "-" & Month(Date) & ".csv" Set ObjFso = CreateObject("Scripting.FileSystemObject") 'Creating a file for writing data Set ObjFile = ObjFso.CreateTextFile(StrFileName) 'takes the headers from row 1 - set by i if different csvread(1) = Range("A" & i).Value csvread(2) = Range("B" & i).Value csvread(3) = Range("C" & i).Value csvread(4) = Range("D" & i).Value csvread(5) = Range("E" & i).Value 'Writes the Headers ObjFile.WriteLine (csvread(1) & "," & csvread(2) & "," & csvread(3) & "," & csvread(4) & "," & csvread(5)) i = i + 1 'Do until loop can be altered to meet your parameters Do Until Range("A" & i).Value = 0 Or i = 1000 'format your data however you require csvread(15) = Format(Range("A" & i).Value, "###0.00") csvread(15) = Format(Range("B" & i).Value, "###0.00") csvread(15) = Format(Range("C" & i).Value, "###0.00") csvread(15) = Format(Range("D" & i).Value, "###0.00") csvread(15) = Format(Range("E" & i).Value, "###0.00") 'write the line to the file ObjFile.WriteLine (csvread(1) & "," & csvread(2) & "," & csvread(3) & "," & csvread(4) & "," & csvread(5)) i = i + 1 Loop ObjFile.Close p = MsgBox("Exported", vbOKOnly) End Sub 

到目前为止,除了自己导出文件外,我还没有find任何更好的解决scheme( CsvWriter是一个自定义类,但是很简单 – CsvWriter.WriteItems接受一个string的枚举,必要时引用它们,并在csv中构build一行文件在他们之外):

 public static class CsvExporter { public static void ExportWorksheet ( CsvWriter csvWriter, Excel.Worksheet worksheet, Action<int,int> reportProgressCallback = null ) { foreach (var row in WorksheetToStrings (worksheet, reportProgressCallback)) csvWriter.WriteItems (row); } public static IEnumerable<IEnumerable<string>> WorksheetToStrings ( Excel.Worksheet worksheet, Action<int,int> reportProgressCallback = null ) { var usedRange = worksheet.UsedRange; return RangeToStrings (usedRange, reportProgressCallback); } public static IEnumerable<IEnumerable<string>> RangeToStrings ( Excel.Range range, Action<int,int> reportProgressCallback = null ) { if (reportProgressCallback == null) reportProgressCallback = (line, total) => { }; int rowsTotal = range.Rows.Count; int currentRow = 0; foreach (var row in range.Rows) { ++currentRow; reportProgressCallback (currentRow, rowsTotal); var rowValues = (row as Excel.Range).Value2 as object; foreach ( var convertedRow in convertToEnumerableOfEnumerablesOfStrings (rowValues) ) yield return convertedRow; } } private static IEnumerable<IEnumerable<string>> convertToEnumerableOfEnumerablesOfStrings ( object values ) { return convertToEnumerableOfEnumerablesOfObjects (values) .Select ( r => r.Select ( c => convertSingleValueToString (c) ) ); } private static IEnumerable<IEnumerable<object>> convertToEnumerableOfEnumerablesOfObjects ( object values ) { var ary = values as object [,]; if (ary != null) return convertTwoDimAryToEnumerableOfEnumerablesOfObjects (ary); var obj = values as object; if (obj != null) return Enumerable.Repeat<IEnumerable<object>> ( Enumerable.Repeat<object> (obj, 1), 1 ); return Enumerable.Empty<IEnumerable<object>> (); } private static IEnumerable<IEnumerable<object>> convertTwoDimAryToEnumerableOfEnumerablesOfObjects ( object [,] ary ) { var firstUpperBound = ary.GetUpperBound (0); var secondUpperBound = ary.GetUpperBound (1); return Enumerable.Range (1, firstUpperBound).Select ( i => Enumerable.Range (1, secondUpperBound).Select (j => ary [i, j]) ); } private static string convertSingleValueToString (object value) { if ( value == null ) { return string.Empty; } else if (value is string) { return value as string; } else if (value is long) { return ((long) value).ToString (CultureInfo.InvariantCulture); } else if (value is double) { return ( (double) value ).ToString (CultureInfo.InvariantCulture); } else if (value is bool) { return (bool) value ? "TRUE" : "FALSE"; } else { return value.ToString (); } } }