首页 > 解决方案 > NPOI 在 MemoryStream 中写入 0 个字节

问题描述

我需要将报告保存到MemoryStream,所以我执行以下操作:

byte[] result = new byte[0];

using (var stream = new MemoryStream())
{
    XlsxReport.BuildTaskReport(stream);
    result = stream.ToArray();
}

在我的XlsxReport班级下面:

public sealed class XlsxReport
{
    public const string FontName = "Times New Roman";
    private const int FontSize = 14;

    private readonly IWorkbook workbook;
    // Fonts
    private readonly IFont boldFont;
    private readonly IFont defaultFont;
    // Styles
    private readonly ICellStyle cbStyle;
    private readonly ICellStyle simpleStyle;
    private readonly ICellStyle cdStyle;
    private readonly ICellStyle ldStyle;
    // Sheet
    private readonly ISheet sheet;
    private readonly int rows, columns;

    private XlsxReport(int rows, int columns)
    {
        this.rows = rows;
        this.columns = columns;
        workbook = new XSSFWorkbook();
        // Prepare fonts
        boldFont = workbook.CreateFont();
        defaultFont = workbook.CreateFont();
        boldFont.FontHeightInPoints = FontSize;
        defaultFont.FontHeightInPoints = FontSize;
        boldFont.FontName = FontName;
        defaultFont.FontName = FontName;
        boldFont.Boldweight = (short)FontBoldWeight.Bold;
        // Prepare styles
        cbStyle = CreateCellStyle(boldFont);
        simpleStyle = CreateCellStyle(defaultFont, HorizontalAlignment.Justify);
        cdStyle = CreateCellStyle(defaultFont, HorizontalAlignment.Center, VerticalAlignment.Center, true, false);
        ldStyle = CreateCellStyle(defaultFont, HorizontalAlignment.Left, VerticalAlignment.Center, true, false);
        // Initialize a sheet
        sheet = workbook.CreateSheet(Headers.Page + " 1");
        CreateSheet(sheet, rows, columns, cdStyle);
    }

    private ICellStyle CreateCellStyle(IFont font, HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center, 
        VerticalAlignment verticalAlignment = VerticalAlignment.Center, bool hasBorder = true, bool wrapText = true)
    {
        var style = workbook.CreateCellStyle();
        style.SetFont(font);
        style.Alignment = horizontalAlignment;
        style.VerticalAlignment = verticalAlignment;
        style.WrapText = wrapText;

        if (hasBorder)
        {
            SetBorder(style);
        }

        return style;
    }

    private void BuildMainHeader()
    {
        // Prepare styles
        var titleStyle = CreateCellStyle(boldFont, HorizontalAlignment.Center, VerticalAlignment.Center, false, false);
        var stampStyle = CreateCellStyle(defaultFont, HorizontalAlignment.Center, VerticalAlignment.Center, false, false);
        // Create a title
        GetCell(sheet.GetRow(0), 0, Headers.Report, titleStyle);
        // Create a timestamp
        GetCell(sheet.GetRow(2), 0, DateTime.Today.ToDateStr(), stampStyle);
        // Set regions
        var titleRegion = new CellRangeAddress(0, 0, 0, columns - 1);
        var stampRegion = new CellRangeAddress(2, 2, 0, columns - 1);
        sheet.AddMergedRegion(titleRegion);
        sheet.AddMergedRegion(stampRegion);
    }

    private void SetBorder(ICellStyle style)
    {
        style.BorderTop = BorderStyle.Medium;
        style.BorderBottom = BorderStyle.Medium;
        style.BorderLeft = BorderStyle.Medium;
        style.BorderRight = BorderStyle.Medium;
    }

    private ICell GetCell(IRow row, int index, string value, ICellStyle style)
    {
        var cell = row.GetCell(index);
        cell.SetCellValue(value);
        cell.CellStyle = style;
        cell.SetCellType(CellType.String);
        return cell;
    }

    private void SetBorder(CellRangeAddress region, ISheet sheet, IWorkbook wb)
    {
        RegionUtil.SetBorderBottom(2, region, sheet, wb);
        RegionUtil.SetBorderTop(2, region, sheet, wb);
        RegionUtil.SetBorderLeft(2, region, sheet, wb);
        RegionUtil.SetBorderRight(2, region, sheet, wb);
    }

    private void CreateSheet(ISheet sheet, int rows, int columns, ICellStyle style)
    {
        for (int i = 0; i < rows; ++i)
        {
            var row = sheet.CreateRow(i);

            for (int j = 0; j < columns; ++j)
            {
                var cell = row.CreateCell(j);

                if (i > 3) { cell.CellStyle = style; }
            }
        }
    }

    private void AutoSizeColumns()
    {
        for (int i = 0; i < columns; ++i)
        {
            sheet.AutoSizeColumn(i);
        }
    }

    public static void BuildTaskReport(Stream stream)
    {
        var report = new XlsxReport(5 + Count * 6, 6);
        report.BuildMainHeader();
        var sheet = report.sheet;
        // Set cell regions
        var head = report.sheet.GetRow(4);
        report.GetCell(head, 0, Headers.OrderNumber, report.cbStyle);
        report.GetCell(head, 1, Headers.TaskName, report.cbStyle);
        report.GetCell(head, 2, Headers.DateCreate, report.cbStyle);
        report.GetCell(head, 3, Headers.DateEnd, report.cbStyle);
        report.GetCell(head, 4, Headers.Priority, report.cbStyle);
        report.GetCell(head, 5, Headers.Status, report.cbStyle);
        ////////////////////////////////////////////////////////
        // Many lines to fill rows
        ////////////////////////////////////////////////////////
        // Resize columns
        report.AutoSizeColumns();
        // Save changes
        report.workbook.Write(stream);
        stream.Flush();
    }
}

但是在usingblock my之后result仍然是 0 字节。我已经在调试器中检查了我的报告生成器:IWorkbook包含一个工作表并且工作表包含行,一切看起来都正确,似乎没有任何例外。
有什么问题?在我将代码移至XlsxReport课堂之前,它可以工作。

标签: c#npoi

解决方案


我今天遇到了同样的问题。问题是我将 SharpZipLib 库从 0.86.* 更新到 1.0.*。它停止工作,或者至少应用程序开始将 0 个字节放入流中。当我将此库降级回 0.86.* 时,一切都开始按预期重新工作。


推荐阅读