2011-10-10 37 views
9

He pasado muchas horas tratando de determinar una fórmula para convertir píxeles .NET a un ancho de columna Excel utilizando el formato OpenXML. Estoy usando EPPlus para generar documentos xmls. Estoy tratando de determinar el ancho de una columna que será de tamaño automático. Estoy obteniendo el número de píxeles midiendo la cadena y luego tratando de convertir eso al ancho de la columna para OpenXML, que se mide en caracteres, creo.Fórmula para convertir píxeles .NET al ancho de Excel en formato OpenXML

He leído la documentación de Microsoft sobre la forma de convertir y trató la fórmula sugieren, pero no es ni siquiera cerca de ser preciso:

http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx

Aquí está mi código utilizando la fórmula:

public double GetCharacterWidth(string Text, Font f, Graphics g) 
    { 
     float MaxDigitWidth = g.MeasureString("0", f).Width; 
     float Pixels = g.MeasureString(Text, f).Width; 

     return ((Pixels - 5)/MaxDigitWidth * 100 + 0.5)/100; 
    } 

¿Alguna idea?

+0

Si se trata de una columna de tamaño automático, ¿por qué no utilizar el atributo de mejor ajuste como se especifica en el MSDN vinculado? – PeteT

+0

Ya lo intenté. Si configura BestFit en True y luego abre la hoja de cálculo, las columnas no tienen el tamaño adecuado. –

+0

Pixel-to-EMU is (pixel * 12700). No esperaría que el ancho de las columnas sea en píxeles. Prueba EMU. –

Respuesta

16

En primer lugar tenemos que establecer cómo Excel realiza la conversión (a medida que cambiamos manualmente el tamaño dentro de la aplicación Excel):

//Use 7d to promote to double, otherwise int will truncate. 
ExcelWidth = (Pixels - 12)/7d + 1;//From pixels to inches. 

Advertencia: Las fórmulas no funcionan para 0 Ancho (cero) o Píxeles.
Para esos escenarios, use una declaración "if" para verificar si es cero y devolver cero.

Me dio un vuelco también. En lugar de tratar de calcular los píxeles por ancho, miré la diferencia en píxeles entre cada número entero de ancho y encontré que siempre era 7. La excepción fue de 0 a 1 ancho; donde había 12 píxeles por ancho 1.00. A partir de ahí, pude llegar a las fórmulas anteriores, easy-peasy.

Ahora esos números se mantienen en el mundo de Excel, pero si está configurando anchos de columna directamente en el documento de OpenXml, es una historia ligeramente diferente. He aquí por qué: En la documentación se vincula a este que se dice acerca de los 5 píxeles:

Hay 4 píxeles de desplazamiento de margen (dos a cada lado), más 1 de relleno de píxeles de las líneas de división.

Ahora todo lo que significa es que Excel asume que ha tenido en cuenta estos 5 píxeles en el ancho que está proporcionando. Cuando abre su documento en Excel y cambia el tamaño de las columnas, verá que el ancho es de 5 píxeles menos de lo que lo configuró.

Para ajustar para ello se puede actualizar las fórmulas de la siguiente manera:

//Use 7d to promote to double, otherwise int will truncate. 
OpenXmlWidth = (Pixels - 12 + 5)/7d + 1;//From pixels to inches. 

Esto responde el título de tu pregunta:
"Fórmula para convertir píxeles .NET a la anchura de Excel en formato OpenXML"

Si desea saber cómo calcular una aproximación del ancho de la columna para ajustar automáticamente una columna en función del contenido (y la fuente) de una sola celda, esa es una pregunta completamente diferente. Las fórmulas proporcionadas por el enlace de Microsoft que proporcionó no funcionarán. Escriba 10 períodos en una celda y 10 mayúsculas en otra columna. Verá que el ajuste automático le da 41 píxeles y 129 píxeles, respectivamente. Las fórmulas proporcionadas por ms no tienen en cuenta el ancho de los caracteres individuales. En otras palabras; te enviaron a una loca búsqueda.

La única forma de ajustar automáticamente una columna es escanear todas las filas de la columna y calcular el ancho del texto en función de los caracteres y la fuente utilizados. Utilizarías algo como lo que encontré here. Luego tome el valor máximo de eso y el pad con 5. Evitaría este enfoque cuando procese hojas de cálculo en un entorno web, ya que podría exportar cientos de miles de filas con decenas de columnas; ya se entiende. El mejor enfoque es establecer un ancho de mejor estimación para sus columnas y capacitar a sus usuarios sobre cómo ajustar automáticamente desde Excel.

Sinceramente,
"El hombre común"


Editar - 10/26/2011:

Porque me siento generoso, aquí está un ejemplo de cómo obtener una anchura aproximada de para su columna. Preferiría evitar hacer esto para todas las filas en una columna, así que basémonos en nuestro ancho (de forma predeterminada) en el valor de la celda del encabezado. A continuación se muestra cómo puede hacerlo utilizando el ejemplo al que me he vinculado anteriormente. Nota: Estas son aproximaciones, pero lo suficientemente cerca.

using System.Drawing; 
using System.Windows.Forms;//Add Reference. Test on webserver first. 
Font font = new Font("Calibri", 11.0f, FontStyle.Regular); 
string header = "Hello There World!"; 
int pxBaseline = TextRenderer.MeasureText("__", font).Width; 
int pxHeader = TextRenderer.MeasureText("_" + header + "_"), font).Width; 
int pxColumnWidth = pxHeader - pxBaseline + 5;//Pad with 5 for Excel. 

Advertencia: si utiliza este código en el mismo lugar que está utilizando OpenXml, entonces puede que tenga que quitar el "uso" de System.Drawing y totalmente calificar "Fuente" y "FontStyle" como System.Drawing.Font y System.Drawing.FontStyle. De lo contrario, su compilador puede confundir estas clases como pertenecientes a DocumentFormat.OpenXml.Spreadsheet.

+0

Encontré la primera fórmula que sugirió que fuera la más precisa, aunque todavía no lo suficientemente precisa. Tengo que modificarlo un poco para hacer una "mejor suposición" como dijiste. –

+0

¿Has visto el código que publiqué en la parte inferior debajo de mi edición? Lo uso y funciona perfecto para mis necesidades (dar o tomar algunos píxeles, pero no lo suficiente para mostrar signos de libra o texto de clip). Probablemente modifique mi código para escanear el encabezado y las primeras 20 filas para el ancho máximo (ya que eso es lo que el usuario verá primero cuando abra por primera vez el documento). En cuanto a la primera fórmula, es perfectamente precisa en el cálculo de píxeles en OpenXML-Width que dará el mismo número exacto de píxeles al abrir el documento de Excel (recuerde establecer el mismo nombre de fuente, negrita y tamaño). Gracias por los puntos! – MikeTeeVee

Cuestiones relacionadas