从Excel粘贴到C#应用程序,保持完整的精度

我有一个Excel电子表格中的数据,如下所示:

  • 0.69491375
  • 0.31220394

单元格格式为百分比,并设置为显示两位小数。 所以他们出现在Excel中:

  • 69.49%
  • 31.22%

我有一个C#程序从Clipboardparsing这些数据。

 var dataObj = Clipboard.GetDataObject(); var format = DataFormats.CommaSeparatedValue; if (dataObj != null && dataObj.GetDataPresent(format)) { var csvData = dataObj.GetData(format); // do something } 

问题是, csvData包含Excel的显示值,即“69.49%”和“ csvData %”。 它不包含额外小数位的完整精度。

我曾尝试使用各种不同的DataFormats值,但数据只包含来自Excel的显示值,例如:

  • DataFormats.Dif
  • DataFormats.Rtf
  • DataFormats.UnicodeText
  • 等等

作为testing,我安装了LibreOffice Calc,并将Excel中的相同单元格复制/粘贴到Calc中。 Calc保留了原始数据的完整精度。

很显然,Excel将这些数据放在其他程序可以访问的地方。 我怎样才能从我的C#应用​​程序访问它?

编辑 – 下一步。

我已经下载了LibreOffice Calc源代码,并且会有一个捅过头来看看我是否可以find他们如何从Excel复制数据的完整上下文。

我还对从剪贴板返回的数据对象进行了一次GetFormats()调用,并获得了24种不同数据格式的列表,其中一些不在DataFormats枚举中。 这些格式包括Biff12Biff8Biff5Format129等其他格式,我不熟悉,所以我会调查这些,并作出回应,如果我做任何发现…

也不是一个完整的答案,但对问题的一些进一步的见解:

当您复制单个Excel单元格时,最终剪贴板中将包含一个完整的Excel工作簿,其中包含一个电子表格,该电子表格又包含一个单元格:

 var dataObject = Clipboard.GetDataObject(); var mstream = (MemoryStream)dataObject.GetData("XML Spreadsheet"); // Note: For some reason we need to ignore the last byte otherwise // an exception will occur... mstream.SetLength(mstream.Length - 1); var xml = XElement.Load(mstream); 

现在,当您将XElement的内容转储到控制台时,您可以看到您确实获得了完整的Excel工作簿。 此外,“XML电子表格”格式包含存储在单元格中的数字的内部表示。 所以我想你可以使用Linq-To-Xml或类似的方式来获取你需要的数据:

 XNamespace ssNs = "urn:schemas-microsoft-com:office:spreadsheet"; var numbers = xml.Descendants(ssNs + "Data"). Where(e => (string)e.Attribute(ssNs + "Type") == "Number"). Select(e => (double)e); 

我也尝试使用Excel数据读取器读取Biff格式,但所得到的DataSets总是空着…

BIFF格式是微软公开的规范。 (注意,我说规格不标准)。 阅读这个来了解正在发生的事情。

那么你看到的那些BIFF对应于一些Excel格式。 BIFF5是Excel 5.0和95中的XLS,BIFF8是Excel 97到2003中的XLS,BIFF12是Excel 2003中的XLSB,注意Excel 2007也可以生成它们(我猜也是Excel 2010)。 这里有一些文档,也可以在这里 (来自OpenOffice),可以帮助你理解那里的二进制文件…

无论如何,过去已经做了一些工作来parsingC ++,Java,VB中的这些文档,并在C#中使用它。 比如这个BIFF12 Reader , NExcel项目, ExcelLibrary等等。

特别是NExcel会让你传递一个可以从剪贴板数据创build的数据stream,然后查询NExcel获取数据。 如果你打算采用源代码,那么我认为ExcelLibrary更具可读性。

你可以得到像这样的stream:

 var dataobject = System.Windows.Forms.Clipboard.GetDataObject(); var stream = (System.IO.Stream)dataobject.GetData(format); 

和NExcel一起阅读stream将是这样的:

 var wb = getWorkbook(stream); var sheet = wb.Sheets[0]; var somedata = sheet.getCell(0, 0).Contents; 

我想从微软的实际Office库也可以工作。

我知道这不是全部的故事,请分享它是如何发展的。 如果我有机会会尝试。