2013-08-16 13 views
10

Ho scritto un codice per generare file Excel utilizzando OpenXML. Di seguito è riportato il codice che genera le colonne in Excel.OpenXML: larghezza colonna Dimensione automatica in Excel

Worksheet worksheet = new Worksheet(); 
      Columns columns = new Columns(); 
      int numCols = dt1.Columns.Count; 
      for (int col = 0; col < numCols; col++) 
      { 
        Column c = CreateColumnData((UInt32)col + 1, (UInt32)numCols + 1, 20.42578125D); 

       columns.Append(c); 
      } 
      worksheet.Append(columns); 

Inoltre, ho provato sotto la linea per creare colonne.

Column c = new Column() { Min = (UInt32Value)1U, Max = (UInt32Value)1U, Width = 25.42578125D, BestFit = true, CustomWidth = true}; 

Ho pensato che utilizzare BestFit avrebbe funzionato. Ma non imposta la dimensione automatica.

Per favore aiutatemi su questo.

Grazie,

risposta

7

La proprietà BestFit è una proprietà delle informazioni (forse per l'ottimizzazione da Excel). Hai ancora bisogno di fornire la larghezza per la colonna. Ciò significa che devi effettivamente calcolare la larghezza della colonna in base al contenuto della cella. Open XML SDK non lo fa automaticamente per te, quindi è meglio usare una libreria di terze parti per questo.

+1

Dovrebbe essere una soluzione migliore per questa proprietà BestFit !!! ora è agosto 2014 –

0

Ecco la possibile formula width = Tronca ([{numero di caratteri} * {Digit Larghezza massima} + {5 pixel imbottitura}]/{cifra massima larghezza} * 256)/256

10

Devi calcola te stesso purtroppo

Questo è quello che ho. Funziona per i miei dati che sono tabulari con qualche codice in più per occuparmi di alcuni stili che ho impostato. Non è perfetto, ma funziona per quello che mi serve.

private WorksheetPart mySheetPart; 
private void WriteToTable() 
{ 
     //Get your sheet data - write Rows and Cells 
     SheetData sheetData = GetSheetData(); 

     //get your columns (where your width is set) 
     Columns columns = AutoSize(sheetData); 

     //add to a WorksheetPart.WorkSheet 
     mySheetPart.Worksheet = new Worksheet(); 
     mySheetPart.Worksheet.Append(columns); 
     mySheetPart.Worksheet.Append(sheetData); 
} 

private Columns AutoSize(SheetData sheetData) 
{ 
     var maxColWidth = GetMaxCharacterWidth(sheetData); 

     Columns columns = new Columns(); 
     //this is the width of my font - yours may be different 
     double maxWidth = 7; 
     foreach (var item in maxColWidth) 
     { 
      //width = Truncate([{Number of Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256 
      double width = Math.Truncate((item.Value * maxWidth + 5)/maxWidth * 256)/256; 

      //pixels=Truncate(((256 * {width} + Truncate(128/{Maximum Digit Width}))/256)*{Maximum Digit Width}) 
      double pixels = Math.Truncate(((256 * width + Math.Truncate(128/maxWidth))/256) * maxWidth); 

      //character width=Truncate(({pixels}-5)/{Maximum Digit Width} * 100+0.5)/100 
      double charWidth = Math.Truncate((pixels - 5)/maxWidth * 100 + 0.5)/100; 

      Column col = new Column() { BestFit = true, Min = (UInt32)(item.Key + 1), Max = (UInt32)(item.Key + 1), CustomWidth = true, Width = (DoubleValue)width }; 
      columns.Append(col); 
     } 

     return columns; 
    } 


    private Dictionary<int, int> GetMaxCharacterWidth(SheetData sheetData) 
    { 
     //iterate over all cells getting a max char value for each column 
     Dictionary<int, int> maxColWidth = new Dictionary<int, int>(); 
     var rows = sheetData.Elements<Row>(); 
     UInt32[] numberStyles = new UInt32[] { 5, 6, 7, 8 }; //styles that will add extra chars 
     UInt32[] boldStyles = new UInt32[] { 1, 2, 3, 4, 6, 7, 8 }; //styles that will bold 
     foreach (var r in rows) 
     { 
      var cells = r.Elements<Cell>().ToArray(); 

      //using cell index as my column 
      for (int i = 0; i < cells.Length; i++) 
      { 
       var cell = cells[i]; 
       var cellValue = cell.CellValue == null ? string.Empty : cell.CellValue.InnerText; 
       var cellTextLength = cellValue.Length; 

       if (cell.StyleIndex != null && numberStyles.Contains(cell.StyleIndex)) 
       { 
        int thousandCount = (int)Math.Truncate((double)cellTextLength/4); 

        //add 3 for '.00' 
        cellTextLength += (3 + thousandCount); 
       } 

       if (cell.StyleIndex != null && boldStyles.Contains(cell.StyleIndex)) 
       { 
        //add an extra char for bold - not 100% acurate but good enough for what i need. 
        cellTextLength += 1; 
       } 

       if (maxColWidth.ContainsKey(i)) 
       { 
        var current = maxColWidth[i]; 
        if (cellTextLength > current) 
        { 
         maxColWidth[i] = cellTextLength; 
        } 
       } 
       else 
       { 
        maxColWidth.Add(i, cellTextLength); 
       } 
      } 
     } 

     return maxColWidth; 
    } 
+0

Non hai definito il tuo metodo "GetSheetData()". –

+0

aspetta un minuto, capisco cosa intendi, volevi solo scrivere la tua implementazione di impostare tutti i valori delle celle e poi continuare con l'impostazione delle larghezze delle colonne, il mio male. –

+2

la variabile charWidth in AutoSize() non viene utilizzata? – Macke

1

non ho avuto il tempo di guardare in esso, ma invece di lasciare un commento e a link, ho pensato di condividere un commento da qualcuno che ha apparentemente fatto qualche ricerca su questo.

Personalmente ho avuto problemi con the official formulas per adattarsi alla realtà. Cioè Le stringhe corte hanno celle troppo piccole, le stringhe più lunghe hanno celle troppo grandi e, soprattutto, il valore presentato in Excel era proporzionalmente più piccolo del valore che ho inserito nella proprietà WidthDocumentFormat.OpenXml.Spreadsheet.Column. La mia soluzione rapida era solo per avere una larghezza minima.

Ad ogni modo, ecco il commento:

ho dovuto fare questo, alla fine, perché i file XLSX Sono interessato a sono generati automaticamente e dovrebbe apparire bella, non appena vengono aperte così ho guardato in questo un po 'oltre e ho trovato ci sono un paio di problemi per il dimensionamento accurato delle colonne in Excel.

  1. necessità di utilizzare preciso dimensionamento dei caratteri, il che significa che invece di utilizzare MeasureString è necessario utilizzare MeasureCharacterRanges, vedi http://groups.google.com/group/microsoft.public.office.developer.com.add_ins/browse_thread/thread/2fc33557feb72ab4/adaddc50480b8cff?lnk=raot

  2. Nonostante le specifiche dicendo aggiungere 5 pixel (1 per il bordo e 2 per ogni margine laterale) Excel sembra utilizzare 9 - 1 per il bordo, 5 per lo spazio iniziale e 3 per lo spazio finale - Ho trovato questo solo utilizzando l'app di accessibilità. Magnifier e contando i pixel dopo l'utilizzo di Excel per auto adattarsi alle colonne

In realtà stavo basando i miei calcoli sulla metrica dei font sottostanti così io in realtà non utilizzare sia MeasureCharacterRanges o MeasureString.Se qualcuno è interessato a fare questo da metriche di font poi:

Width = Truncate({DesiredWidth} + 9/{MaxDigitWidth})/256

{MaxDigitWidth} è un intero arrotondato al pixel più vicino di una delle cifre 0..9 a 96 dpi {} è il DesiredWidth somma dell'aggiunta di tutte le larghezze dei caratteri insieme in cui ogni larghezza di carattere corrisponde alla larghezza del carattere a 96 dpi arrotondata all'intero più vicino. Si noti che ogni carattere è arrotondato non la somma complessiva

Problemi correlati