到目前为止,除了自己导出文件之外,我还没有找到任何更好的解决方案(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 ();
}
}
}