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

C# Excel:从字符串转换为数字时丢失小数分隔符,c#,excel,casting,formatting,C#,Excel,Casting,Formatting,我正在尝试从几个文件中读取一些值,并将它们保存在具有不同分组的新.xlsx文件中。我设计了一个非常简单的设置,用空值测试不同的格式和行为。我总是在Excel中打开刚创建的文件以查看结果。到目前为止没有问题 然而,在我的测试用例中,我可以实现以下两种方法:A)按原样保存测试值(字符串)或B)强制Excel将它们视为具有给定格式的数字(良好),但丢失十进制分隔符(非常糟糕和奇怪) 我已经将问题追溯到下面代码片段的最后一行。自我分配的想法来自于SO的另一个帖子,但现在我找不到它 如果该行被注释掉,则结

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

然而,在我的测试用例中,我可以实现以下两种方法:A)按原样保存测试值(字符串)或B)强制Excel将它们视为具有给定格式的数字(良好),但丢失十进制分隔符(非常糟糕和奇怪)

我已经将问题追溯到下面代码片段的最后一行。自我分配的想法来自于SO的另一个帖子,但现在我找不到它

如果该行被注释掉,则结果与
字符串[,]中的内容一样
仅将其格式化为文本(Excel对此表示不满,并显示“数字格式化为文本”消息)。如果取消注释,这些数字将被视为数字,但会丢失十进制分隔符。另外,问题可能是我在捷克共和国,小数点分隔符是
,这可能会给Excel带来麻烦。此外,将值从start读入
double[,]内容
是错误的,因为我需要指示值是否不存在(单元格为空)。和
double?[,]内容
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
excelApp=new Excel.Application();
excelWorkBooks=excelApp.Workbooks;
excelWorkBook=excelWorkBooks.Add();
excelSheets=excelWorkBook.Sheets;
Excel工作表=Excel工作表[1]//当心!Excel是一个基于0的C语言,而不是一个基于0的C语言#
字符串[,]内容=新字符串[,]{{“1,23”,“2123123123”,“31415926535”},{“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

编辑:为了测试,我尝试将NumberFormat从
0,00E+00
更改为
0,0
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];
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互操作一样

这与Excel无关。您试图传递的字符串格式不正确。盎格鲁萨克逊国家的小数点是
。您的示例使用欧洲国家通常使用的
。我打赌您的语言环境不是法语、德语或希腊语。与其尝试硬编码分隔符,不如将数字作为数字传递。即,使用十进制或双精度数组,并将未格式化的值传递给Excel。它可以接受数字和文本,而不是使用interop。使用像Epplus这样的库可以轻松地生成有效的
xlsx
文件,甚至不用安装Excel。您可以用
sheet.LoadFromCollection(myNumbersCollection)
LoadFromDataTable
填充一张工作表。我来自捷克共和国,并且currentCulture说
cs CZ
。最让我困惑的是,它与自我分配不一样。而且你和大多数开发人员一样拥有美国地区?无论如何,不要使用字符串。Excel理解数字。正如我所说,最好的选择是使用Epplus,我希望在不屈服于每个单元格的基础上解决这个问题,因为我要写14页,每5列乘以4500行。关于速度,请咨询此:。然而,如果我必须以每个单元格为基础工作,我可以直接在Excel中这样做。Web可用性不是我关心的事情,因为它是用于内部使用的,几乎所有计算机都有Excel…互操作比直接生成文件慢得多。如果您关心性能,那么首先就不应该使用互操作。如果要生成报告,应使用eg Reporting Services或SSI。从何处加载数据?如果数据是从数据库加载的,例如作为DataTable,则可以简单地使用LoadFromDataTable 15次。还有一个
LoadFromDataReader
用于直接从快进读取器加载我从文件中拾取数据。它们是关于一些测量的。但是,这些数据需要排序,因为来自多个文件的数据需要合并和排序。
var file = new FileInfo("test.xlsx");
using (var pck = new ExcelPackage(file))
{
    var ws = pck.Workbook.Worksheets.Add("Rules");
    ws.LoadFromDataTable(myTable);
    pck.Save();
}