2010-08-30 41 views
4

J'exporte une grille avec NPOI v1.2.3, et j'ai du mal à faire fonctionner la mise en forme des cellules.NPOI DataFormat

J'ai une classe qui exporte une liste d'objets dans un fichier XLS. Une ligne est créée pour chaque objet et une cellule est ajoutée pour chaque propriété configurée. Le format de données de cellule peut être défini sur un niveau par propriété.

J'ai lu que you shouldn't create a new style for each cell. Je ne peux pas coder en dur mes styles, puisque mon exportateur doit supporter n'importe quelle classe. Au lieu de cela, j'ai écrit un petit système de cache qui ne crée un nouveau CellStyle que s'il n'a pas déjà été créé pour le format de la cellule en cours.

Malheureusement, cela n'a toujours pas résolu le problème. La mise en forme n'est pas correctement appliquée dans le fichier XLS final. Dans mon cas de test, la plupart des cellules de la XLS utilisent le format "Date", même si seules quelques colonnes sont des dates. La première colonne utilise correctement un format personnalisé, cependant. Aucune cellule n'est définie sur du texte, même si cela devrait être la plupart d'entre elles.

Qu'est-ce que je fais mal?

code

La méthode « AddRecords » ci-dessous permet d'ajouter les lignes de données (lignes d'en-tête et pied de page sont ajoutés séparément). Le dernier bit de code est la méthode paresseuse de 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]; 
} 

Répondre

6

Il semble que le problème a quelque chose à voir avec la création de nouveaux formats qui correspondent à des formats intégrés. J'ai changé ma méthode de chargement paresseux pour utiliser le format intégré si disponible, et les formats de cellule dans mon XLS final sont tous corrects maintenant.

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