2013-08-16 3 views
10

OpenXML을 사용하여 Excel 파일을 생성하는 코드를 작성했습니다. 다음은 Excel에서 열을 생성하는 코드입니다.OpenXML : 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 속성에 대한 더 나은 해결책이 될 것입니다! 현재 2014 년 8 월입니다. –

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

AutoSize()의 charWidth 변수가 사용되지 않습니까? – Macke

1

나는 그것을 조사 할 시간이 없었어요,하지만 대신 주석과 a link를 떠나, 나는 내가 겉으로는이에 대한 몇 가지 연구를 수행 한 사람의 의견을 공유하고자합니다.

개인적으로는 현실에 맞게 the official formulas의 문제가 발생했습니다. 나는. 짧은 문자열에 너무 작은 셀이 있고 긴 문자열에 너무 큰 셀이 있고 무엇보다도 Excel에 표시된 값은 DocumentFormat.OpenXml.Spreadsheet.ColumnWidth- 속성에 삽입 한 값보다 비례하여 작습니다. 나의 빠른 해결책은 단지 최소한의 폭을 가졌다.

내가 관심 오전 XLSX 파일이 자동으로 생성하고 열 되 자마자 좋은 보일 것 때문에 결국이 작업을 수행했다 그래서이 들여다 :

어쨌든

, 여기에 코멘트입니다 조금 더 자세히 살펴보면 Excel에서 열의 크기를 정확하게 계산하는 데 몇 가지 문제가 있음을 알 수 있습니다.

  1. 필요 대신 당신이 MeasureCharacterRanges를 사용할 필요 MeasureString 사용하는, 5 개 픽셀 (각 테두리 1과 2를 추가하는 말 사양에도 불구하고 http://groups.google.com/group/microsoft.public.office.developer.com.add_ins/browse_thread/thread/2fc33557feb72ab4/adaddc50480b8cff?lnk=raot

  2. 를 볼 수 있다는 것을 의미 정확한 문자 크기를 사용하는 사이드 마진) Excel은 국경을 위해 9 - 1, 선행 공간을 위해 5 그리고 후미 공간을 위해 3을 사용하는 것으로 보인다 - 나는 접근성 앱을 사용하여 이것을 발견했다. 돋보기 및 자동 실제로 MeasureCharacterRanges 또는 MeasureString을 사용하지 않도록 사실 내가 기본 글꼴 메트릭에 내 계산을 내놓고 된 열

에 맞게 Excel을 사용 후 픽셀을 계산.사람은 글꼴 메트릭에서이 일에 관심이 있다면 :

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

{MaxDigitWidth}는 96 dpi로 에서 0..9 자리의 가장 가까운 픽셀 반올림 정수 {DesiredWidth가}이다 모든 문자 너비를 더한 합. 각 문자 너비는 96 dpi에서 가장 가까운 정수로 반올림 한 문자 너비입니다. 각 문자는 총계가 아닌 반올림 함을 유의하십시오.