2011-12-23 20 views
7

tengo los datos en una hoja de cálculo de Excel con los valores de la siguiente manera:pegar de Excel en C# aplicación, conservando la precisión completa

  • 0,69491375
  • 0,31220394

Las células tienen el formato de porcentaje, y configurado para mostrar dos lugares decimales. Por lo que aparecerá en Excel como:

  • 69,49%
  • 31,22%

Tengo un programa de C# que analiza estos datos de la Clipboard.

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

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

El problema es que csvData contiene los valores de indicación de Excel, es decir '69 0,49% 'y '31 0,22%'. No contiene la precisión completa de los lugares decimales adicionales.

He intentado usar los diversos valores diferentes DataFormats, pero los datos solamente siempre contiene el valor de la pantalla de Excel, por ejemplo:

  • DataFormats.Dif
  • DataFormats.Rtf
  • DataFormats.UnicodeText
  • etc.

Como prueba, instalé LibreOffice C alc y copie/pegue las mismas celdas de Excel en Calc. Calc conserva la precisión total de los datos brutos.

Así que, claramente, Excel pone esta información en algún lugar al que otros programas pueden acceder. ¿Cómo puedo acceder desde mi aplicación C#?

Editar - Próximos pasos.

he descargado el código fuente de LibreOffice Calc y tendrá un empuje alrededor para ver si puedo averiguar cómo consiguen el contexto completo de los datos copiados de Excel.

También hice una llamada GetFormats() en el objeto de datos devuelto desde el portapapeles y obtuve una lista de 24 formatos de datos diferentes, algunos de los cuales no están en la enumeración DataFormats. Estos incluyen formatos como Biff12, Biff8, Biff5, Format129 entre otros formatos que no son familiares para mí, así que voy a investigar estas y responder si hago ningún descubrimiento ...

+0

Acabo de intentar pegar los datos en como 10 programas diferentes, y todos me han dado los datos formateados "69.00% \ r \ n" tal como lo veo Clipboard.GetData –

+0

Sí, tienes razón. Estaba pensando, ¿tiene Excel su propio portapapeles interno donde almacena todos los datos de formato y precisión, que no se colocan en el portapapeles general? ¿Tiene Calc algún gancho en el portapapeles interno de Excel, que la mayoría de las aplicaciones no tendrían y no es fácil de obtener? Temo la respuesta a esto. :-) – Lyall

+1

si Calc usa un gancho excel, no veo una razón por la que no pueda usar ese mismo gancho ... – Adam

Respuesta

6

Además, no es una respuesta completa o bien, pero algunas ideas más en el problema:

Al copiar una sola celda de Excel a continuación, lo que va a terminar en el portapapeles es un completo libro de Excel que contiene una sola hoja de cálculo que a su a su vez contiene una sola célula:

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

Ahora, al volcar el contenido de la XElement a la consola se puede ver que de hecho obtener un completo libro de Excel. Además, el formato "Hoja de cálculo XML" contiene la representación interna de los números almacenados en la celda. Así que supongo que se podría utilizar LINQ to XML o similares a buscar los datos que necesita:

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

También he tratado de leer los formatos de Biff utilizando el Excel Data Reader sin embargo, los conjuntos de datos resultantes siempre salieron vacío ..

+0

Terminé usando este enfoque, gracias por la información. Es interesante que DataFormats enum no contenga "XML Spreadsheet", pero funciona bastante bien con un poco de análisis del XML. – Lyall

3

Los formatos BIFF son una especificación abierta por Microsoft. (Tenga en cuenta que digo especificación no estándar). Dale una lectura al this para tener una idea de lo que está pasando.

Luego esos BIFF que ve corresponden a algunos formatos de Excel. BIFF5 es XLS de Excel 5.0 y 95, BIFF8 es XLS de Excel 97 a 2003, BIFF12 es XLSB de Excel 2003, tenga en cuenta que Excel 2007 también puede producirlos (creo que Excel 2010 también). Existe alguna documentación here y también here (de OpenOffice) que puede ayudarlo a encontrarle sentido al binario allí ...

De todos modos, se ha hecho un trabajo en el pasado para analizar estos documentos en C++, Java, VB y para su gusto en C#. Por ejemplo, este BIFF12 Reader, el proyecto NExcel y ExcelLibrary para citar algunos.

En particular, NExcel le permitirá pasar una secuencia que puede crear a partir de los datos del portapapeles y luego consultar NExcel para obtener los datos. Si va a tomar el código fuente, entonces creo que ExcelLibrary es mucho más legible.

Usted puede obtener la corriente de la siguiente manera:

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

Y leer formar la corriente con Nexcel sería algo como esto:

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

supongo que las bibliotecas reales de oficina de Microsoft trabajarían demasiado .

Sé que esto no es todo, por favor comparta cómo le va. Lo intentaré si tengo la oportunidad.

Cuestiones relacionadas