2010-08-30 90 views
4

我正在使用NPOI v1.2.3導出網格,並且無法使單元格格式化工作。NPOI DataFormat

我有一個類將對象列表導出到XLS文件。爲每個對象創建一行,併爲每個配置的屬性添加一個單元格。單元格數據格式可以在每個屬性級別上設置。我已閱讀you shouldn't create a new style for each cell。我不能硬編碼我的風格,因爲我的出口商需要支持任何類。相反,我寫了一個小緩存系統,它只創建一個新的CellStyle,如果還沒有爲當前單元格的格式創建的話。

不幸的是,這仍然沒有解決問題。格式不正確應用在最終的XLS文件中。在我的測試案例中,儘管只有幾列是日期,但XLS中的大多數單元格都使用「日期」格式。但是,第一列正確使用自定義格式。沒有單元格設置爲文本,即使這應該是大部分。

我在做什麼錯?

代碼

下面的「AddRecords」方法被用於添加數據行(頁眉和頁腳行被分開加入)。最後一段代碼是延遲加載CellStyles的方法。

private void AddRecords(Sheet sheet, IList<T> records) 
{ 
    foreach(var record in records) 
    { 
     // append row 
     var row = sheet.CreateRow (sheet.LastRowNum + 1); 

     // iterate through all configured columns 
     foreach (var column in GetColumns()) 
     { 
      // append cell 
      Cell cell = row.CreateCell (row.LastCellNum == -1 ? 0 : row.LastCellNum); 

      // get the property value of the column from the record 
      object value = GetCellValue (column, record); 

      // extension method that takes an object value and calls the appropriate type-specific SetCellValue overload 
      cell.SetCellValue (value); 

      // get format from the column definition ("m/d", "##.###", etc.), or use the default 
      string dataFormat = column.DataFormat ?? GetDefaultDataFormat (value); 

      // find/create cell style 
      cell.CellStyle = GetCellStyleForFormat(sheet.Workbook, dataFormat); 
     } 
    } 
} 

/// <summary> 
/// Returns a default format string based on the object type of value. 
/// 
/// http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/BuiltinFormats.html 
/// </summary> 
/// <param name="value"></param> 
/// <returns></returns> 
private string GetDefaultDataFormat(object value) 
{ 
    if(value == null) 
    { 
     return "General"; 
    } 

    if(value is DateTime) 
    { 
     return "m/d"; 
    } 

    if(value is bool) 
    { 
     return "[=0]\"Yes\";[=1]\"No\""; 
    } 

    if(value is byte || value is ushort || value is short || 
     value is uint || value is int || value is ulong || value is long) 
    { 
     return "0"; 
    } 

    if(value is float || value is double) 
    { 
     return "0.00"; 
    } 

    // strings and anything else should be text 
    return "text"; 
} 

private readonly Dictionary<string, CellStyle> _cellStyleCache = new Dictionary < string, CellStyle >(); 

private CellStyle GetCellStyleForFormat(Workbook workbook, string dataFormat) 
{ 
    if(!_cellStyleCache.ContainsKey (dataFormat)) 
    { 
     var newDataFormat = workbook.CreateDataFormat(); 
     var style = workbook.CreateCellStyle(); 
     style.DataFormat = newDataFormat.GetFormat (dataFormat); 

     _cellStyleCache[dataFormat] = style; 
    } 

    return _cellStyleCache[dataFormat]; 
} 

回答

6

看起來問題似乎與創建匹配內置格式的新格式有關。如果可用,我將延遲加載方法更改爲使用內置格式,現在我最終的XLS中的單元格格式都是正確的。

if(!_cellStyleCache.ContainsKey (dataFormat)) 
{ 
    var style = workbook.CreateCellStyle(); 

    // check if this is a built-in format 
    var builtinFormatId = HSSFDataFormat.GetBuiltinFormat (dataFormat); 

    if(builtinFormatId != - 1) 
    { 
     style.DataFormat = builtinFormatId; 
    } 
    else 
    { 
     // not a built-in format, so create a new one 
     var newDataFormat = workbook.CreateDataFormat(); 
     style.DataFormat = newDataFormat.GetFormat (dataFormat); 
    } 

    _cellStyleCache[dataFormat] = style; 
}