不幸的是,Excel在生成CSV文件时对程序员不是很友好,因为它存储了屏幕上显示的数字。因此,CSV中数字的外观取决于区域设置和用户的品味。
因此,我最终可能看起来像
2 123
3'322
1,233.44
2123,45
等
现在我必须在程序中处理这样的CSV文件。
除告诉用户如何构建他们的CSV文件外 - 是否有任何智能或规范的解决方案如何处理这个问题?切换到另一种数据格式也是一种选择 - 但是哪一种?它必须由Excel本机支持,并且应该易于处理(所以我想避免使用xlsx)。
答案 0 :(得分:2)
我对客户端有同样的问题,我已经写了一个导出到csv宏,明确告诉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
答案 1 :(得分:0)
到目前为止,除了自己导出文件之外,我还没有找到更好的解决方案(CsvWriter
是一个自定义类,但直截了当 - CsvWriter.WriteItems
需要一个可枚举的字符串,引用它们必要的,并在csv文件中构建一行代码):
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 ();
}
}
}