2013-08-16 2 views
10

Я написал код для создания файла Excel с использованием OpenXML. Ниже приведен код, который генерирует столбцы в Excel.OpenXML: ширина столбца Auto Size в 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); 

Кроме того, я попытался использовать строку ниже для создания столбцов.

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

Я думал, используя BestFit, он должен работать. Но он не устанавливает автоматический размер.

Пожалуйста, помогите мне в этом.

Спасибо,

ответ

7

Свойства BestFit является свойством информации (возможно, для оптимизации с помощью Excel). Вам все равно нужно предоставить ширину для столбца. Это означает, что вы должны фактически рассчитать ширину столбца в зависимости от содержимого ячейки. Open XML SDK не делает это автоматически для вас, поэтому лучше использовать для этого стороннюю библиотеку.

+1

Если это будет лучшее решение для этого имущества BestFit !!! now is Aug 2014 –

0

Здесь можно формула ширина = усечения ([{Количество символов} * {Максимальная цифра Ширина} + {5 пикселей обивка}]/{Максимальная цифра Ширина} * 256)/256

10

Вы должны рассчитать его, к сожалению,

Это то, что у меня есть. Он работает для моих данных, которые являются табличными с некоторым дополнительным кодом, чтобы позаботиться о некоторых стилях, которые я установил. Он не идеален никоим образом, но работает для того, в чем я нуждаюсь.

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

Вы не определили свой метод GetSheetData(). –

+0

Подождите минуту, я понимаю, что вы имеете в виду, вы просто хотели написать собственную реализацию установки всех значений ячеек, а затем продолжить настройку ширины столбцов, что плохо. –

+2

переменная charWidth в AutoSize() не используется? – Macke

1

У меня не было времени, чтобы посмотреть на него, но вместо того, чтобы просто оставить комментарий и a link, я думал, что я разделю комментарий от кого-то, кто, казалось бы, сделал некоторые исследования по этому вопросу.

У меня лично возникли проблемы с получением the official formulas в соответствии с реальностью. То есть Короткие строки получили слишком маленькие ячейки, более длинные строки получили слишком большие ячейки и, самое главное, значение, представленное в Excel, было пропорционально меньше значения, которое я вставил в DocumentFormat.OpenXml.Spreadsheet.ColumnWidth -property. Моим быстрым решением было просто иметь минимальную ширину.

Во всяком случае, вот комментарий:

Я должен был сделать это в конце концов, так как XLSX файлы Я заинтересован в сгенерированы автоматически и должны хорошо выглядеть, как только они открыты, так что я посмотрел на это немного дальше и обнаружил, что есть несколько проблем для точной калибровки столбцов в Excel.

  1. Необходимости использовать точные проклейки характера, что означает, что вместо того, чтобы использовать MeasureString вам нужно использовать MeasureCharacterRanges см http://groups.google.com/group/microsoft.public.office.developer.com.add_ins/browse_thread/thread/2fc33557feb72ab4/adaddc50480b8cff?lnk=raot

  2. Несмотря спецификации говоря, чтобы добавить 5 пикселей (1 для границы и 2 для каждого боковое поле) Excel, по-видимому, использует 9 - 1 для границы, 5 для ведущего пространства и 3 для конечного пространства - я нашел это только с помощью приложения доступности. Лупа и подсчета пикселей после использования Excel для автоматического подходят столбцы

На самом деле я основывал свои расчеты на базовых метрик шрифта, так что я на самом деле не использовать либо MeasureCharacterRanges или MeasureString.Если кто-то заинтересован в этом из метрик шрифта, то:

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

{MaxDigitWidth} представляет собой целое число округляется до ближайшего пикселя любого из 0..9 цифр 96 точек на дюйм {DesiredWidth} является сумма суммирования всех ширин символов, где каждая ширина символа равна ширине символа с 96 dpi, округленной до ближайшего целого. Обратите внимание, что каждый символ округлен не общей суммой

Смежные вопросы