Вставить из Excel в приложение C #, сохраняя полную точность - PullRequest
7 голосов
/ 23 декабря 2011

У меня есть данные в электронной таблице Excel с такими значениями:

  • 0.69491375
  • 0.31220394

Ячейки отформатированы в процентах и ​​установленыотображать два десятичных знака.Поэтому в Excel они выглядят так:

  • 69,49%
  • 31,22%

У меня есть программа на C #, которая анализирует эти данные с Clipboard.

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%» и «31,22%».Он не содержит полной точности дополнительных десятичных разрядов.

Я пытался использовать различные значения DataFormats, но данные содержат только отображаемое значение из Excel, например:

  • DataFormats.Dif
  • DataFormats.Rtf
  • DataFormats.UnicodeText
  • и т. Д.

В качестве теста я установил LibreOffice Calcи скопируйте / вставьте те же ячейки из Excel в Calc.Calc сохраняет полную точность необработанных данных.

Столь ясно, что Excel помещает эти данные куда-нибудь, к чему могут обращаться другие программы.Как я могу получить к нему доступ из своего приложения на C #?

Редактировать - Следующие шаги.

Я скачал исходный код LibreOffice Calc и поищу, чтобы посмотретьесли я смогу узнать, как они получают полный контекст скопированных данных из Excel.

Я также сделал GetFormats() вызов объекта данных, возвращенного из буфера обмена, и получил список из 24 различных форматов данных,некоторые из которых отсутствуют в перечислении DataFormats.К ним относятся форматы, такие как Biff12, Biff8, Biff5, Format129, среди прочих незнакомых мне форматов, поэтому я буду исследовать их и отвечать, если сделаю какие-либо открытия ...

Ответы [ 2 ]

6 голосов
/ 03 января 2012

Также не полный ответ, но некоторые дополнительные сведения о проблеме:

Когда вы копируете одну ячейку 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 Spreadsheet» содержит внутреннее представление чисел, хранящихся в ячейке. Поэтому я думаю, что вы можете использовать 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 Data Reader , однако результирующие наборы данных всегда выходили пустыми ...

3 голосов
/ 25 декабря 2011

Форматы BIFF являются открытой спецификацией Microsoft.(Обратите внимание, что я говорю, спецификация не стандартная).Прочитайте this , чтобы получить представление о том, что происходит.

Тогда те BIFF, которые вы видите, соответствуют некоторым форматам Excel.BIFF5 - это XLS из Excel 5.0 и 95, BIFF8 - это XLS из Excel 97 - 2003, BIFF12 - это XLSB из Excel 2003, обратите внимание, что Excel 2007 также может их создавать (я полагаю, Excel 2010 тоже).Существует некоторая документация здесь , а также здесь (из OpenOffice), которая может помочь вам разобраться в бинарном файле ...

В любом случае, есть некоторые работыбыло сделано в прошлом для анализа этих документов в C ++, Java, VB и на ваш вкус в C #.Например, это BIFF12 Reader , проект NExcel и ExcelLibrary для цитирования нескольких.

В частности NExcel позволит вам передать потоккоторый вы можете создать из данных буфера обмена и затем запросить NExcel, чтобы получить данные.Если вы собираетесь взять исходный код, то я думаю, что ExcelLibrary гораздо более читабелен.

Вы можете получить поток следующим образом:

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

И читать из потока поток с NExcel будетчто-то вроде этого:

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

Полагаю, что настоящие библиотеки Office от Microsoft тоже подойдут.

Я знаю, что это не вся история, пожалуйста, поделитесь, как идут дела.Попробую, если у меня будет шанс.

...