Формат данных NPOI

Я экспортирую сетку с помощью NPOI v1.2.3, и у меня возникают проблемы с форматированием ячеек.

У меня есть класс, который экспортирует список объектов в файл XLS. Для каждого объекта создается строка, а для каждого настроенного свойства добавляется ячейка. Формат данных ячейки может быть установлен на уровне каждого свойства.

Я читал, что вам не следует не создавать новый стиль для каждой ячейки. Я не могу жестко закодировать свои стили, так как мой экспортер должен поддерживать любой класс. Вместо этого я написал небольшую систему кэширования, которая создает новый 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];
}

person MikeWyatt    schedule 30.08.2010    source источник


Ответы (1)


Похоже, проблема как-то связана с созданием новых форматов, соответствующих встроенным форматам. Я изменил свой метод ленивой загрузки, чтобы использовать встроенный формат, если он доступен, и теперь все форматы ячеек в моем окончательном 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;
}
person MikeWyatt    schedule 30.08.2010