2011-12-23 10 views
7

ho dati in un foglio di calcolo di Excel con i valori in questo modo:incolla da Excel in C# app, conservando la piena precisione

  • 0,69491375
  • 0,31220394

Le celle sono formattate come percentuale, e impostato per visualizzare due posizioni decimali. In modo che appaiano in Excel come:

  • 69,49%
  • 31.22%

Ho un programma C# che analizza questi dati fuori dal Clipboard.

var dataObj = Clipboard.GetDataObject(); 
var format = DataFormats.CommaSeparatedValue; 

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

Il problema è che csvData contiene i valori visualizzati da Excel, ossia '69 .49% 'e '31 .22%'. Non contiene la precisione completa dei posti decimali aggiuntivi.

Ho provato utilizzando le varie DataFormats valori diversi, ma i dati sempre e solo contiene il valore visualizzato da Excel, ad esempio:

  • DataFormats.Dif
  • DataFormats.Rtf
  • DataFormats.UnicodeText
  • ecc

Come test, ho installato LibreOffice C alc e copia/incolla le stesse celle da Excel in Calc. Calc conserva la precisione completa dei dati grezzi.

Così chiaramente Excel inserisce questi dati da qualche parte a cui possono accedere altri programmi. Come posso accedervi dalla mia applicazione C#?

Modifica - Passaggi successivi.

Ho scaricato il codice sorgente di LibreOffice Calc e cercherò di vedere se riesco a scoprire come ottenere il contesto completo dei dati copiati da Excel.

Ho anche effettuato una chiamata GetFormats() sull'oggetto dati restituito dagli Appunti e ottenuto un elenco di 24 formati di dati diversi, alcuni dei quali non presenti nell'enum DataFormats. Questi includono formati come Biff12, Biff8, Biff5, Format129 tra gli altri formati che sono sconosciuti a me, quindi mi indagare su questi e rispondere se faccio qualche scoperta ...

+0

Ho appena provato ad incollare i dati in 10 diversi programmi, e mi hanno dato tutti i dati formattati "69.00% \ r \ n" proprio come lo vedo io Appunti.GetData –

+0

Sì, hai ragione. Stavo pensando, Excel ha i suoi appunti interni dove memorizza tutti i dati di formattazione e precisione, che non vengono messi negli appunti generali? E Calc ha qualche aggancio negli appunti interni di Excel, che la maggior parte delle app non avrebbe e non è facile da ottenere? Ho paura della risposta a questo. :-) – Lyall

+1

se Calc utilizza un hook excel, non riesco a vedere un motivo per cui non è possibile utilizzare lo stesso hook ... – Adam

risposta

6

Inoltre non una risposta completa sia, ma alcuni ulteriori approfondimenti il ​​problema:

Quando si copia una singola cella di Excel allora che cosa finirà negli appunti è una cartella di lavoro completa di Excel che contiene un singolo foglio di calcolo che, in sua volta contiene una singola cella:

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); 

Ora, quando si dump il contenuto del XElement alla console si può vedere che, invece, si ottiene una completa cartella di lavoro Excel. Anche il formato "XML Spreadsheet" contiene la rappresentazione interna dei numeri memorizzati nella cella. Quindi credo che si potrebbe usare LINQ to XML o simile per recuperare i dati necessari:

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); 

Ho anche cercato di leggere i formati di Biff utilizzando il Excel Data Reader tuttavia i set di dati risultanti sempre uscito vuoto ..

+0

Ho finito per usare questo approccio, grazie per l'intuizione. Interessante che l'enumerazione DataFormats non contenga "XML Spreadsheet" ma funziona piuttosto bene con un po 'di analisi dell'XML. – Lyall

3

I formati BIFF sono una specifica aperta da Microsoft. (Nota, che dico specifica non standard). Dai una lettura a this per avere un'idea di cosa sta succedendo.

Quindi quei BIFF che vedi corrispondono ai formati Excel. BIFF5 è XLS da Excel 5.0 e 95, BIFF8 è XLS da Excel 97 a 2003, BIFF12 è XLSB da Excel 2003, si noti che Excel 2007 può anche produrli (credo anche Excel 2010). C'è della documentazione here e anche here (da OpenOffice) che può aiutarti a capire il codice binario lì ...

In ogni caso, in passato è stato fatto qualche lavoro per analizzare questi documenti in C++, Java, VB e per i vostri gusti in C#. Ad esempio questo BIFF12 Reader, il progetto NExcel e ExcelLibrary per citarne alcuni.

In particolare, NExcel consente di passare un flusso che è possibile creare dai dati degli appunti e quindi eseguire una query su NExcel per ottenere i dati. Se hai intenzione di prendere il codice sorgente, penso che ExcelLibrary sia molto più leggibile.

È possibile ottenere il flusso in questo modo:

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

E leggere formare il flusso con Nexcel sarebbe qualcosa di simile:

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

immagino le librerie di Office reali da Microsoft avrebbe funzionato troppo .

So che non è tutta la storia, per favore condividi come va. Lo proverò se avrò la possibilità.

Problemi correlati