简体   繁体   English

使用 Npoi 导出 Excel

[英]Export Excel using Npoi

I am looking to export an excel sheet using NPOI library.我正在寻找使用 NPOI 库导出 excel 表。 Is there any way to insert the datatable into the sheet without losing the data format?有什么办法可以在不丢失数据格式的情况下将数据表插入到工作表中吗?

Previously, I used to use the Gembox Spreadsheet Library.以前,我曾经使用 Gembox 电子表格库。 This worked well for me.这对我来说效果很好。 The code for that looke like:那个看起来像的代码:

    public void ExportTest(DataSet ds)
    {

        SpreadsheetInfo.SetLicense("FREE-LIMITED-KEY");
        ExcelFile ef = new ExcelFile();
        var filename = DateTime.Now.ToString("yyyyMMdd") + "BSI_MEMBERAmendment" + ".xls";
        foreach (DataTable dt in ds.Tables)
        {
            ExcelWorksheet ws = ef.Worksheets.Add(dt.TableName);
            ws.InsertDataTable(dt,
           new InsertDataTableOptions(0, 0)
           {
               ColumnHeaders = true,
               StartRow = 0,

           });
        }

        ef.Save(this.Response, filename);

I had to stop using the Gembox library because I need to make excel files with more than 5 sheets.我不得不停止使用 Gembox 库,因为我需要制作超过 5 张纸的 excel 文件。 Gembox, unfortunately does not allow that on a free platform.不幸的是,Gembox 在免费平台上不允许这样做。 As such, I've switched to NPOI.因此,我已经切换到 NPOI。

Now that I'm using the NPOI library, I've change my code to:现在我正在使用 NPOI 库,我已将代码更改为:

  public void WriteExcelWithNPOI(String extension, DataSet dataSet)
    {


        HSSFWorkbook workbook = new HSSFWorkbook(); ;

       if (extension == "xls")
        {
            workbook = new HSSFWorkbook();
        }
        else
        {
            throw new Exception("This format is not supported");
        }

        foreach (DataTable dt in dataSet.Tables)
        {
            var sheet1 = workbook.CreateSheet(dt.TableName);
            // How can i insert the data's from dataTable in this sheet
        }

        using (var exportData = new MemoryStream())
        {
            Response.Clear();
            workbook.Write(exportData);
            if (extension == "xls") 
            {
                Response.ContentType = "application/vnd.ms-excel";
                Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "tpms_dict.xls"));
                Response.BinaryWrite(exportData.GetBuffer());
            }
            Response.End();
        }
    }

The problem that I'm encountering with using the NPOI library is, all the cells in the exported excel file is formatted as text.我在使用 NPOI 库时遇到的问题是,导出的 excel 文件中的所有单元格都被格式化为文本。 I'd like to retain the format that's used in the data table.我想保留数据表中使用的格式。 Looking for help.寻求帮助。 Thanks in advance!!!提前致谢!!!

To insert data from a data table, you could perhaps use this code in place of the comment " // How can i insert the data's from dataTable in this sheet ".要从数据表插入数据,您或许可以使用此代码代替注释“ // 如何在此工作表中插入来自 dataTable 的数据”。

// 1. make a header row
IRow row1 = sheet1.CreateRow(0);

for (int j = 0; j < dt.Columns.Count; j++)
{
    ICell cell = row1.CreateCell(j);
    string columnName = dt.Columns[j].ToString();
    cell.SetCellValue(columnName);
}

// 2. loop through data
for (int i = 0; i < dt.Rows.Count; i++)
{
    IRow row = sheet1.CreateRow(i + 1);
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        ICell cell = row.CreateCell(j);
        string columnName = dt.Columns[j].ToString();
        cell.SetCellValue(dt.Rows[i][columnName].ToString());
    }
}
// 3. Auto size columns
for (int i = 0; i < 5; i++)
{
    for (int j = 0; j < row1.LastCellNum; j++)
    {
        sheet1.AutoSizeColumn(j);
    }
}

For data types, you could use the function cell.SetCellType(CellType.[TYPE HERE]);对于数据类型,您可以使用函数cell.SetCellType(CellType.[TYPE HERE]); . . The type entered in the function SetCellType must match the data type in cell.SetCellValue() afterwards.之后在函数SetCellType输入的类型必须与cell.SetCellValue()中的数据类型匹配。

This will modify the data loop to look as follows:这将修改数据循环,如下所示:

// 2. loop through data
for (int i = 0; i < dt.Rows.Count; i++)
{
    IRow row = sheet1.CreateRow(i + 1);
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        ICell cell = row.CreateCell(j);
        string columnName = dt.Columns[j].ToString();
        // Set the cell type
        cell.SetCellType(GetCorrectCellType(dt.Rows[i][columnName].GetType()))
        // Set the cell value
        cell.SetCellValue(dt.Rows[i][columnName]);
    }
}

// Function to return the correct cell type
public int GetCorrectCellType(Type dataType) 
{
   if(dataType == typeof(string))
      return CellType.String;
   else if(dataType == typeof(int) || dataType == typeof(double))
      return CellType.Numeric;
   else if(dataType == typeof(bool))
      return CellType.Boolean;
   else
      return CellType.Unknown; // Not sure how to set Date Type --> Unknown
}

EDIT I found how set set Date values in a human readable format in this answer .编辑我发现如何在这个答案中以人类可读的格式设置日期值。

I know I am a little late here but I think it may help others, yes, there is a way to convert datatable directly to export excel without losing data format.我知道我在这里有点晚了,但我认为它可以帮助其他人,是的,有一种方法可以将数据表直接转换为导出 excel 而不会丢失数据格式。

I have developed an excel utility with the use of the NPOI package, which can我使用 NPOI 包开发了一个 excel 实用程序,它可以

  1. Simply takes your data table or the collection只需获取您的数据表或集合
  2. And Returns you excel while maintaining all the data table/list data type intact in the excel.并返回您的 excel,同时在 excel 中保持所有数据表/列表数据类型完整。

Github Code repo.: https://github.com/ansaridawood/.NET-Generic-Excel-Export-Sample/tree/master/GenericExcelExport/ExcelExport Github 代码仓库: https : //github.com/ansaridawood/.NET-Generic-Excel-Export-Sample/tree/master/GenericExcelExport/ExcelExport

Looking for a code explanation, you can find it here: https://www.codeproject.com/Articles/1241654/Export-to-Excel-using-NPOI-Csharp-and-WEB-API寻找代码解释,你可以在这里找到: https : //www.codeproject.com/Articles/1241654/Export-to-Excel-using-NPOI-Csharp-and-WEB-API

It uses NPOI DLL and it has 2 cs files to include and then you are good to go它使用 NPOI DLL 并包含 2 个 cs 文件,然后您就可以开始使用了

Below is the first file for reference AbstractDataExport.cs :以下是参考AbstractDataExport.cs的第一个文件:

using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

namespace GenericExcelExport.ExcelExport
{
    public interface IAbstractDataExport
    {
        HttpResponseMessage Export(List exportData, string fileName, string sheetName);
    }

    public abstract class AbstractDataExport : IAbstractDataExport
    {
        protected string _sheetName;
        protected string _fileName;
        protected List _headers;
        protected List _type;
        protected IWorkbook _workbook;
        protected ISheet _sheet;
        private const string DefaultSheetName = "Sheet1";

        public HttpResponseMessage Export
              (List exportData, string fileName, string sheetName = DefaultSheetName)
        {
            _fileName = fileName;
            _sheetName = sheetName;

            _workbook = new XSSFWorkbook(); //Creating New Excel object
            _sheet = _workbook.CreateSheet(_sheetName); //Creating New Excel Sheet object

            var headerStyle = _workbook.CreateCellStyle(); //Formatting
            var headerFont = _workbook.CreateFont();
            headerFont.IsBold = true;
            headerStyle.SetFont(headerFont);

            WriteData(exportData); //your list object to NPOI excel conversion happens here

            //Header
            var header = _sheet.CreateRow(0);
            for (var i = 0; i < _headers.Count; i++)
            {
                var cell = header.CreateCell(i);
                cell.SetCellValue(_headers[i]);
                cell.CellStyle = headerStyle;
            }

            for (var i = 0; i < _headers.Count; i++)
            {
                _sheet.AutoSizeColumn(i);
            }

            using (var memoryStream = new MemoryStream()) //creating memoryStream
            {
                _workbook.Write(memoryStream);
                var response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new ByteArrayContent(memoryStream.ToArray())
                };

                response.Content.Headers.ContentType = new MediaTypeHeaderValue
                       ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.Content.Headers.ContentDisposition = 
                       new ContentDispositionHeaderValue("attachment")
                {
                    FileName = $"{_fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
                };

                return response;
            }
        }

        //Generic Definition to handle all types of List
        public abstract void WriteData(List exportData);
    }
}

and this the second and final file AbstractDataExportBridge.cs :这是第二个也是最后一个文件AbstractDataExportBridge.cs

using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;

namespace GenericExcelExport.ExcelExport
{
    public class AbstractDataExportBridge : AbstractDataExport
    {
        public AbstractDataExportBridge()
        {
            _headers = new List<string>();
            _type = new List<string>();
        }

        public override void WriteData<T>(List<T> exportData)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));

            DataTable table = new DataTable();

            foreach (PropertyDescriptor prop in properties)
            {
                var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
                _type.Add(type.Name);
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? 
                                  prop.PropertyType);
                string name = Regex.Replace(prop.Name, "([A-Z])", " $1").Trim(); //space separated 
                                                                           //name by caps for header
                _headers.Add(name);
            }

            foreach (T item in exportData)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }

            IRow sheetRow = null;

            for (int i = 0; i < table.Rows.Count; i++)
            {
                sheetRow = _sheet.CreateRow(i + 1);
                for (int j = 0; j < table.Columns.Count; j++)
                {
                    ICell Row1 = sheetRow.CreateCell(j);

                    string type = _type[j].ToLower();
                    var currentCellValue = table.Rows[i][j];

                    if (currentCellValue != null && 
                        !string.IsNullOrEmpty(Convert.ToString(currentCellValue)))
                    {
                        if (type == "string")
                        {
                            Row1.SetCellValue(Convert.ToString(currentCellValue));
                        }
                        else if (type == "int32")
                        {
                            Row1.SetCellValue(Convert.ToInt32(currentCellValue));
                        }
                        else if (type == "double")
                        {
                            Row1.SetCellValue(Convert.ToDouble(currentCellValue));
                        }
                    }
                    else
                    {
                        Row1.SetCellValue(string.Empty);
                    }
                }
            }
        }
    }
}

For a detailed explanation, refer link provided in the beginning.有关详细说明,请参阅开头提供的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM