7

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

1 に答える 1

8

問題は、組み込みの形式と一致する新しい形式の作成に関係しているようです。可能であれば組み込み形式を使用するように遅延読み込み方法を変更しました。これで、最終的な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;
}
于 2010-08-30T19:54:53.900 に答える