Excel:从字符串转换为数字时丢失小数点分隔符

时间:2017-02-13 14:50:33

标签: c# excel casting formatting

我正在尝试从多个文件中读取一些值,并将它们保存在具有不同分组的新.xlsx文件中。我设计了一个非常简单的设置来测试具有空值的不同格式和行为。我总是在Excel中打开刚刚创建的文件以查看结果。到目前为止没问题。

但是在我的测试用例中,我可以实现以下两种方法之一:A)保存测试值(字符串)或B)强制Excel将它们视为具有给定格式(好)的数字,但丢失小数分隔符(非常糟糕) & strange)。

我已将问题追溯到下面代码段中的最后一行。自我分配的想法来自SO的某处,但现在我无法找到它。

如果该行被注释掉,则结果与string[,] contents中的结果相同,只是它们被格式化为文本(并且Excel以“格式化为文本的数字”消息抱怨此行)。如果我取消注释,数字将被视为数字但会丢失小数分隔符。此问题可能是我在捷克共和国的事实,小数点分隔符是,,这可能会给Excel带来麻烦。此外,读取从开始到double[,] contents的值是不对的,因为我需要指示值是否不存在(空单元格)。而double?[,] contents崩溃了Excel ......

请你以前没有遇到过这种行为吗?我想1)能够指出缺失值和2)将单元格的内容格式化为数字,而不是文本。你能帮我解决这个问题吗?

excelApp = new Excel.Application();
excelWorkBooks = excelApp.Workbooks;
excelWorkBook = excelWorkBooks.Add();
excelSheets = excelWorkBook.Sheets;
excelWorkSheet = excelSheets[1];           //Beware! Excel is one-based as opposed to a zero-based C#

string[,] contents = new string[,] {  { "1,23", "2,123123123", "3,1415926535" }, { "2,15", null, "" } };

int contentsHeight = contents.GetLength(0);
int contentsWidth = contents.GetLength(1);

System.Globalization.CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
string numberFormat = string.Format("0" + currentCulture.NumberFormat.NumberDecimalSeparator + "00E+00");

for (int column = 0; column < contentsWidth; column++) {
    excelWorkSheet.Columns[column + 1].NumberFormat = numberFormat;
}

Excel.Range range = excelWorkSheet.Range[excelWorkSheet.Cells[1, 1], excelWorkSheet.Cells[contentsHeight, contentsWidth]];
range.Value = contents;
// range.Value = range.Value;  //Problematic place

编辑:为了测试,我尝试将NumberFormat从0,00E+00更改为0,00.0#,#,但没有成功。崩溃(小数点)或保留为文本。

1 个答案:

答案 0 :(得分:0)

在将数字写入单元格之前,无需将数字转换为文本。 Excel理解数字。另一个问题是代码试图将数组设置为整个范围的值,就像粘贴到Excel中一样。

可以直接使用简单的循环设置数字,甚至是空值,例如

double?[,] contents = new double?[,] { { 1.23, 2.123123123, 3.1415926535 }, 
                                       { 2.15, null, null } };
int contentsHeight = contents.GetLength(0);
int contentsWidth = contents.GetLength(1);
...
for(int i=0;i<= contentsHeight; i++)
    for (int j = 0; j <= contentsWidth; j++)
        excelWorkSheet.Cells[i+1,j+1].Value = contents[i,j];

不是通过Interop使用Excel,而是使用像EPPlus这样的包来直接生成xlsx文件而不安装Excel。这样即使在无法安装Excel的Web服务器上也可以生成真实的Excel文件。

此特定问题的代码类似:

var file = new FileInfo("test.xlsx");
using (var pck = new ExcelPackage(file))
{
    var ws = pck.Workbook.Worksheets.Add("Rules");
    for(int i=0;i<= contentsHeight; i++)
        for (int j = 0; j <= contentsWidth; j++)
            ws.Cells[i+1,j+1].Value = contents[i,j];
    pck.Save();
}

EPPlus有一些方便的方法可以轻松加载工作表,例如LoadFromDataTable或LoadFromCollection。如果数据来自DataTable,则创建工作表将非常简单:

var file = new FileInfo("test.xlsx");
using (var pck = new ExcelPackage(file))
{
    var ws = pck.Workbook.Worksheets.Add("Rules");
    ws.LoadFromDataTable(myTable);
    pck.Save();
}

LoadFromDataTable返回ExcelRange,它允许单元格格式化,就像Excel Interop一样。