NPOI DataFormat

Estou exportando uma grade com o NPOI v1.2.3 e estou tendo problemas para fazer com que a formatação de célula funcione.

Eu tenho uma classe que exporta uma lista de objetos para um arquivo XLS. Uma linha é criada para cada objeto e uma célula é adicionada para cada propriedade configurada. O formato dos dados da célula pode ser definido em um nível por propriedade.

Eu li issovocê não deve criar um novo estilo para cada célula. Não consigo codificar meus estilos, pois meu exportador precisa oferecer suporte a qualquer classe. Em vez disso, escrevi um pequeno sistema de cache que só cria um novo CellStyle se ainda não tiver sido criado para o formato da célula atual.

Infelizmente, isso ainda não resolveu o problema. A formatação não é aplicada corretamente no arquivo XLS final. No meu caso de teste, a maioria das células no XLS está usando o formato "Data", mesmo que apenas algumas colunas sejam datas. A primeira coluna usa corretamente um formato personalizado, no entanto. Nenhuma célula está definida como texto, mesmo que deva ser a maioria delas.

O que estou fazendo errado?

Código

O método "AddRecords" abaixo é usado para adicionar as linhas de dados (as linhas de cabeçalho e rodapé são adicionadas separadamente). O último bit de código é o método que carrega CellStyles preguiçosamente.

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

questionAnswers(1)

yourAnswerToTheQuestion