2011-10-10 10 views
9

Ho trascorso molte ore a cercare di determinare una formula per convertire i pixel .NET in una larghezza di colonna di Excel utilizzando il formato OpenXML. Sto usando EPPlus per generare documenti xmls. Sto provando a determinare la larghezza di una colonna che deve essere dimensionata automaticamente. Sto ottenendo il numero di pixel misurando la stringa e poi provando a convertirla nella larghezza della colonna per OpenXML, che viene misurata in caratteri che penso.Formula per convertire i pixel .NET in larghezza Excel in formato OpenXML

Ho letto la documentazione di Microsoft su come convertire e provato la formula essi suggeriscono, ma non è neppure vicino ad essere preciso:

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

Ecco il mio codice utilizzando la loro formula:

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

Qualche idea?

+0

Se è una colonna che deve essere dimensionata automaticamente, perché non utilizzare l'attributo best fit come specificato nel MSDN collegato? – PeteT

+0

L'ho già provato. Se si imposta BestFit su True e quindi si apre il foglio di calcolo, le colonne non vengono ridimensionate in modo appropriato. –

+0

Pixel-to-EMU è (pixel * 12700). Non mi aspetterei che le larghezze delle colonne siano espresse in pixel. Prova EMU. –

risposta

16

In primo luogo abbiamo bisogno di stabilire come Excel esegue la conversione (come si cambia manualmente le dimensioni all'interno dell'applicazione Excel):

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

Caveat: Le formule non funzionano per 0 (zero) Larghezza o pixel.
Per tali scenari, utilizzare un'istruzione "if" per verificare se zero e restituire zero.

Anche a me ha gettato un cappio. Invece di cercare di capire Pixel per larghezza, ho osservato la differenza di pixel tra ogni numero intero di larghezza e ho trovato che era sempre 7. L'eccezione era 0 a 1 larghezza; dove c'erano 12 pixel per larghezza 1.00. Da lì sono riuscito a trovare le formule sopra, facile-pisello.

Ora questi numeri si fermano nel mondo di Excel, ma se si impostano le larghezze delle colonne direttamente nel documento OpenXml, si tratta di una storia leggermente diversa. Ecco perché: nella documentazione a cui fai il link dice i 5 pixel:

Ci sono 4 pixel di margine di riempimento (due su ciascun lato), più 1 pixel di riempimento per le linee della griglia.

Ora tutto questo significa è Excel sta assumendo hai presi in questi 5 pixel nelle larghezze che si sta fornendo. Quando apri il documento in Excel e ridimensiona le colonne, vedrai che la larghezza è 5 pixel inferiore a quella impostata.

Per regolare per questo è possibile aggiornare le formule come segue:

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

questo risponde il titolo della tua domanda:
"Formula per convertire pixel NET di larghezza Excel in formato OpenXML"

Se vuoi sapere come calcolare un'approssimazione della larghezza della colonna per adattare automaticamente una colonna in base al contenuto (e al carattere) di una singola cella, allora questa è una domanda completamente diversa. Le formule fornite dal collegamento Microsoft che hai fornito non funzioneranno. Digita 10 periodi in una cella e 10 maiuscole-M in un'altra colonna. Vedrai che l'adattamento automatico ti dà rispettivamente 41 pixel e 129 pixel. Le formule fornite da ms non tengono conto della larghezza dei singoli caratteri. In altre parole; ti hanno mandato a caccia di selvaggina d'oca.

L'unico modo per eseguire l'adattamento automatico di una colonna consiste nell'esaminare ogni riga della colonna e calcolare la larghezza del testo in base ai caratteri e al carattere utilizzati. Dovresti usare qualcosa di simile a quello che ho trovato here. Quindi prendi il valore massimo di quello e il pad con 5. Eviterei questo approccio quando elabori i fogli di calcolo in un ambiente web perché potresti esportare centinaia di migliaia di righe con decine di colonne: ti viene l'idea. L'approccio migliore consiste nell'impostare una larghezza di best-guess per le colonne e addestrare gli utenti su come adattarsi automaticamente da Excel.

Cordiali saluti,
"The Common Man"


Modifica - 10/26/2011:

Perché mi sento generoso, ecco un esempio di come ottenere un per la larghezza approssimativa di per la colonna. Preferirei evitare di farlo per tutte le righe in una colonna, quindi basiamo semplicemente la larghezza (per impostazione predefinita) sul valore nella cella dell'intestazione. Di seguito è riportato come è possibile farlo utilizzando l'esempio che ho collegato in precedenza. Nota: sono approssimazioni, ma abbastanza vicine.

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. 

Caveat: Se si utilizza questo codice nello stesso luogo che si sta utilizzando OpenXml, allora potrebbe essere necessario rimuovere il "tramite" per System.Drawing e completamente qualificare "Carattere" e "FontStyle" come System.Drawing.Font e System.Drawing.FontStyle. Altrimenti il ​​compilatore potrebbe scambiare queste classi come appartenenti a DocumentFormat.OpenXml.Spreadsheet.

+0

Ho trovato la prima formula che hai suggerito di essere la più accurata, anche se non ancora abbastanza accurata. Devo modificarlo un po 'per fare una "ipotesi migliore" come hai detto tu. –

+0

Hai visto il codice che ho pubblicato in fondo sotto la mia modifica? Lo uso e funziona perfettamente per le mie esigenze (dare o prendere alcuni pixel ma non abbastanza per mostrare segni di sterlina o testo di clip). Probabilmente modificherò il mio codice per analizzare l'intestazione e le prime 20 righe per la larghezza massima (poiché è ciò che l'utente vedrà per la prima volta quando aprirà il documento). Per quanto riguarda la prima formula, è perfettamente preciso nel calcolare Pixel in OpenXML-Width che produrrà lo stesso numero esatto di pixel quando si apre il documento Excel (ricordarsi di impostare lo stesso Nome, Grassetto e Dimensione del Font). Grazie per i punti! – MikeTeeVee

Problemi correlati