it-swarm.com.de

OpenXML: Automatische Spaltenbreite in Excel

Ich habe einen Code geschrieben, um eine Excel-Datei mit OpenXML zu generieren. Nachfolgend finden Sie den Code, der die Spalten in Excel generiert.

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

Ich habe auch unterhalb der Zeile versucht, Spalten zu erstellen.

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

Ich dachte, mit BestFit sollte es funktionieren. Die automatische Größe wird jedoch nicht festgelegt.

12
Mittal Patel

Die BestFit-Eigenschaft ist eine Informationseigenschaft (möglicherweise zur Optimierung durch Excel). Sie müssen weiterhin die Breite für die Spalte angeben. Das bedeutet, dass Sie die Spaltenbreite abhängig vom Zellinhalt tatsächlich berechnen müssen. Open XML SDK führt dies nicht automatisch für Sie aus. Daher ist es besser, dass Sie eine Bibliothek eines Drittanbieters verwenden.

7
Vincent Tan

Du musst es dir leider selbst berechnen

Das ist was ich habe. Es funktioniert für meine Daten, die tabellarisch sind, mit zusätzlichem Code, um sich um einige von mir eingestellte Stile zu kümmern. Es ist auf keinen Fall perfekt, funktioniert aber für das, was ich brauche.

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

Ich hatte nicht die Zeit, mir das anzuschauen, aber anstatt nur einen Kommentar zu hinterlassen und einen Link , dachte ich, ich würde einen Kommentar von jemandem teilen, der anscheinend etwas dazu recherchiert hat.

Ich persönlich hatte Probleme damit, die offiziellen Formeln der Realität anzupassen. Das heißt Kurze Zeichenfolgen wurden zu kleinen Zellen, längere Zeichenketten zu großen Zellen und vor allem war der in Excel dargestellte Wert proportional kleiner als der Wert, den ich in die Width-Eigenschaft von DocumentFormat.OpenXml.Spreadsheet.Column eingefügt habe. Meine schnelle Lösung war nur eine minimale Breite.

Wie auch immer, hier ist der Kommentar:

Ich musste dies am Ende tun, da die xlsx-Dateien, an denen ich interessiert bin, automatisch generiert werden und "Nice" aussehen sollten, sobald sie geöffnet sind. Deshalb habe ich mir das etwas genauer angesehen und festgestellt, dass es einige Probleme gibt, die Spalten genau zu dimensionieren Excel.

  1. Verwenden Sie eine genaue Zeichengröße, dh, Sie müssen anstelle von MeasureString MeasureCharacterRanges verwenden. Weitere Informationen finden Sie unter http://groups.google.com/group/Microsoft.public.office.developer.com.add_ins/browse_thread/. thread/2fc33557feb72ab4/adaddc50480b8cff? lnk = raot

  2. Trotz der Angabe, dass 5 Pixel hinzugefügt werden sollen (1 für den Rand und 2 für jeden Seitenrand), scheint Excel 9 - 1 für den Rand, 5 für den führenden und 3 für den nachfolgenden Raum zu verwenden - ich habe dies nur über die Barrierefreiheit gefunden App. Vergrößern und Zählen der Pixel nach der Verwendung von Excel zum automatischen Anpassen der Spalten

Tatsächlich habe ich meine Berechnungen auf zugrunde liegenden Schriftartmetriken basiert, daher verwende ich weder MeasureCharacterRanges noch MeasureString. Wenn sich jemand aus Font-Metriken daran interessiert, dann:

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

{MaxDigitWidth} ist eine Ganzzahl, die auf das nächste Pixel einer der 0,9-Ziffern bei 96 dpi gerundet wird. {DesiredWidth} ist die Summe der Addition aller Zeichenbreiten, wobei jede Zeichenbreite der Zeichenbreite entspricht bei 96 dpi auf die nächste ganze Zahl gerundet. Beachten Sie, dass jedes Zeichen gerundet wird und nicht die Gesamtsumme

1
Aske B.

Hier ist die mögliche Formel Width = Truncate ([{Anzahl Zeichen} * {Maximale Ziffernbreite} + {5 Pixelauffüllung}]/{Maximale Digitbreite * * 256)/256

0
Cyclion