ArrayList导出excel问题,为何占用巨大大内存,有无解决方法?

时间:2021-09-01 20:26:45
/// <summary>
/// 将ArrayList转换成excel文件
/// </summary>
/// <param name="arr"></param>
/// <param name="strFileName"></param>
private void ArrayListToExcel(ArrayList  arr, string strFileName)
{
Excel.Application excel=new Excel.ApplicationClass();
Excel.Workbooks workbooks = excel.Workbooks; 
Excel._Workbook workbook1=excel.Workbooks.Add(XlWBATemplate.xlWBATWorksheet); 
Sheets sheets = workbook1.Worksheets; 
_Worksheet worksheet = (_Worksheet) sheets.get_Item(1);  

//循环读取生成新表格 
excel.Application.Workbooks.Add(true);             

//生成EXCEL的格式设定 
excel.Cells.Font.Bold = false; 
//excel.Cells.FillRight();

excel.Cells.Font.Size = "9";
excel.Cells.NumberFormatLocal = "@";
      
//将列名赋值给单元格 
excel.Cells[1,1] ="客户号";
excel.Cells[1,2] ="姓名";
excel.Cells[1,3] ="性别";
excel.Cells[1,4] ="手机号码";
excel.Cells[1,5] ="单位地址";
excel.Cells[1,6] ="单位邮编";
excel.Cells[1,7] ="家庭地址";
excel.Cells[1,8] ="家庭邮编";

//将数据放入excel
int rowIndex=1;

foreach (Detail objDetail in arr )
{
rowIndex++; 
excel.Cells[rowIndex,1] = objDetail.custno.ToString();
excel.Cells[rowIndex,2] = objDetail.name.ToString();
excel.Cells[rowIndex,3] = objDetail.sex.ToString();
excel.Cells[rowIndex,4] = objDetail.mobile.ToString();
excel.Cells[rowIndex,5] = objDetail.deptaddress.ToString();
excel.Cells[rowIndex,6] = objDetail.deptcode.ToString();
excel.Cells[rowIndex,7] = objDetail.homeaddress.ToString();
excel.Cells[rowIndex,8] = objDetail.homecode.ToString();
}

//不可见,即后台处理 
excel.Visible=false;

//友好界面提示 
Excel.XlSaveAsAccessMode lhx=Excel.XlSaveAsAccessMode.xlShared;  
object Nothing=System.Reflection.Missing.Value; 
string strDownLoadDir = System.Configuration.ConfigurationSettings.AppSettings["downloadDir"];
string url= @strDownLoadDir +strFileName+".xls";
excel.ActiveWorkbook.SaveAs( url,Nothing,Nothing,Nothing,Nothing,Nothing,lhx,Nothing,Nothing,Nothing,Nothing,Nothing);     
excel.Workbooks.Close();
excel.Quit(); 
System.Runtime.InteropServices.Marshal.ReleaseComObject(excel); 
excel=null; 
GC.Collect();

}


这是我的代码,运行起来后,cpu占用很大,有没有改进的方法?

8 个解决方案

#1


你这是用COM的方式,是有点消耗资源。主要还是你的代码有问题

workbooks.Close(false, Nothing, Nothing);
excel.Workbooks.Close();
excel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);

workbooks=null;
excel=null;

GC.Collect();

#2


excel占用的内存没有被释放掉。

最好的方法是直接生成XML文件,因为从office 2003开始,excel可以读xml文件了。

#3


private void exportToExcelReportFile(DataTable ds, string fileName, string rptName)
    {
        string filesPath = "";
        System.IO.StreamWriter excelDoc;
        excelDoc = new System.IO.StreamWriter(fileName);
        const string startExcelXML = "<xml version>\r\n<Workbook " +
              "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
              " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
              "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
              "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
              "office:spreadsheet\">\r\n <Styles>\r\n " +
              "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
              "<Alignment ss:Vertical=\"Center\"/>\r\n <Borders/>" +
              "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
              "\r\n <Protection/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
              "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
              " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
              "ss:ID=\"Decimal\">\r\n <NumberFormat " +
              "ss:Format=\"0.00\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
              "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
              "ss:ID=\"DateTimeLiteral\">\r\n <NumberFormat " +
              "ss:Format=\"mm/dd/yyyy hh:mm AM/PM\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
              "ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n " +
              "</Styles>\r\n ";
        const string endExcelXML = "</Workbook>";
        string rptNames = "";
        int rowCount = 0;
        int sheetCount = 1;
        excelDoc.Write(startExcelXML);
        excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
        excelDoc.Write("<Table>");


        //Add Sql Where Infomation
        excelDoc.Write("<Row>");
        excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
        excelDoc.Write(oneAndEightTitleInfo);
        excelDoc.Write("</Data></Cell>");
        excelDoc.Write("</Row>");


        excelDoc.Write("<Row>");
        for (int x = 0; x < ds.Columns.Count; x++)
        {
            excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
            excelDoc.Write(ds.Columns[x].ColumnName);
            excelDoc.Write("</Data></Cell>");
        }
        excelDoc.Write("</Row>");
        rptNames = rptNames + ".xml";
        filesPath = Request.PhysicalApplicationPath + directoryPath + rptName;
        foreach (DataRow x in ds.Rows)
        {
            rowCount++;
            //if the number of rows is > 64000 create a new page to continue output
            if (rowCount == 64000)
            {
                rowCount = 0;
                sheetCount++;
                excelDoc.Write("</Table>");
                excelDoc.Write(" </Worksheet>");
                excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
                excelDoc.Write("<Table>");
            }
            excelDoc.Write("<Row>"); //ID=" + rowCount + "
            for (int y = 0; y < ds.Columns.Count; y++)
            {
                System.Type rowType;
                rowType = x[y].GetType();
                switch (rowType.ToString())
                {
                    case "System.String":
                        string XMLstring = x[y].ToString();
                        XMLstring = XMLstring.Trim();
                        XMLstring = XMLstring.Replace("&", "&");
                        XMLstring = XMLstring.Replace(">", ">");
                        XMLstring = XMLstring.Replace("<", "<");
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                       "<Data ss:Type=\"String\">");
                        excelDoc.Write(XMLstring);
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.DateTime":
                        DateTime XMLDate = (DateTime)x[y];
                        string XMLDatetoString = "";
                        XMLDatetoString = XMLDate.Year.ToString() + "-" +
                             (XMLDate.Month < 10 ? "0" + XMLDate.Month.ToString() : XMLDate.Month.ToString()) + "-" + (XMLDate.Day < 10 ? "0" +
                             XMLDate.Day.ToString() : XMLDate.Day.ToString()) + "T" +
                             (XMLDate.Hour < 10 ? "0" + XMLDate.Hour.ToString() : XMLDate.Hour.ToString()) + ":" +
                             (XMLDate.Minute < 10 ? "0" + XMLDate.Minute.ToString() : XMLDate.Minute.ToString());
                        if (XMLDate.Hour > 0 | XMLDate.Minute > 0)
                        {
                            excelDoc.Write("<Cell ss:StyleID=\"DateTimeLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                        }
                        else
                        {
                            excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                        }
                        excelDoc.Write(XMLDatetoString);
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Boolean":
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                    "<Data ss:Type=\"String\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                    case "System.Byte":
                        excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                "<Data ss:Type=\"Number\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Decimal":
                    case "System.Double":
                        excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                              "<Data ss:Type=\"Number\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.DBNull":
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                              "<Data ss:Type=\"String\">");
                        excelDoc.Write("");
                        excelDoc.Write("</Data></Cell>");
                        break;
                    default:
                        throw (new Exception(rowType.ToString() + " not handled."));
                }
            }
            excelDoc.Write("</Row>");
        }
        excelDoc.Write("</Table>");
        excelDoc.Write(" </Worksheet>");
        excelDoc.Write(endExcelXML);
        excelDoc.Close();
    }

#4


也可以创建了excel文件后,用数据库连接的方式往里面灌数据。用OleDb连接。我往excel文件读写数据都是这么做的。

#5


对了,Sheet就是表名,不过写的时候是$Sheet或者是Sheet$,记不清楚了。

#6


感觉慢的原因是频繁的拆箱,使用ArrayList的效率本身就不高.楼住看是否可以用数组.
com组件的编程,可以直接用数组填充一个sheet的Range.

#7


为什么存成那样?
Csv不是更好?

#8


up。学习

#1


你这是用COM的方式,是有点消耗资源。主要还是你的代码有问题

workbooks.Close(false, Nothing, Nothing);
excel.Workbooks.Close();
excel.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);

workbooks=null;
excel=null;

GC.Collect();

#2


excel占用的内存没有被释放掉。

最好的方法是直接生成XML文件,因为从office 2003开始,excel可以读xml文件了。

#3


private void exportToExcelReportFile(DataTable ds, string fileName, string rptName)
    {
        string filesPath = "";
        System.IO.StreamWriter excelDoc;
        excelDoc = new System.IO.StreamWriter(fileName);
        const string startExcelXML = "<xml version>\r\n<Workbook " +
              "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n" +
              " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
              "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
              "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:" +
              "office:spreadsheet\">\r\n <Styles>\r\n " +
              "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
              "<Alignment ss:Vertical=\"Center\"/>\r\n <Borders/>" +
              "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
              "\r\n <Protection/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
              "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
              " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
              "ss:ID=\"Decimal\">\r\n <NumberFormat " +
              "ss:Format=\"0.00\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"Integer\">\r\n <NumberFormat " +
              "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
              "ss:ID=\"DateTimeLiteral\">\r\n <NumberFormat " +
              "ss:Format=\"mm/dd/yyyy hh:mm AM/PM\"/>\r\n </Style>\r\n " +
              "<Style ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
              "ss:Format=\"mm/dd/yyyy;@\"/>\r\n </Style>\r\n " +
              "</Styles>\r\n ";
        const string endExcelXML = "</Workbook>";
        string rptNames = "";
        int rowCount = 0;
        int sheetCount = 1;
        excelDoc.Write(startExcelXML);
        excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
        excelDoc.Write("<Table>");


        //Add Sql Where Infomation
        excelDoc.Write("<Row>");
        excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
        excelDoc.Write(oneAndEightTitleInfo);
        excelDoc.Write("</Data></Cell>");
        excelDoc.Write("</Row>");


        excelDoc.Write("<Row>");
        for (int x = 0; x < ds.Columns.Count; x++)
        {
            excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
            excelDoc.Write(ds.Columns[x].ColumnName);
            excelDoc.Write("</Data></Cell>");
        }
        excelDoc.Write("</Row>");
        rptNames = rptNames + ".xml";
        filesPath = Request.PhysicalApplicationPath + directoryPath + rptName;
        foreach (DataRow x in ds.Rows)
        {
            rowCount++;
            //if the number of rows is > 64000 create a new page to continue output
            if (rowCount == 64000)
            {
                rowCount = 0;
                sheetCount++;
                excelDoc.Write("</Table>");
                excelDoc.Write(" </Worksheet>");
                excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
                excelDoc.Write("<Table>");
            }
            excelDoc.Write("<Row>"); //ID=" + rowCount + "
            for (int y = 0; y < ds.Columns.Count; y++)
            {
                System.Type rowType;
                rowType = x[y].GetType();
                switch (rowType.ToString())
                {
                    case "System.String":
                        string XMLstring = x[y].ToString();
                        XMLstring = XMLstring.Trim();
                        XMLstring = XMLstring.Replace("&", "&");
                        XMLstring = XMLstring.Replace(">", ">");
                        XMLstring = XMLstring.Replace("<", "<");
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                       "<Data ss:Type=\"String\">");
                        excelDoc.Write(XMLstring);
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.DateTime":
                        DateTime XMLDate = (DateTime)x[y];
                        string XMLDatetoString = "";
                        XMLDatetoString = XMLDate.Year.ToString() + "-" +
                             (XMLDate.Month < 10 ? "0" + XMLDate.Month.ToString() : XMLDate.Month.ToString()) + "-" + (XMLDate.Day < 10 ? "0" +
                             XMLDate.Day.ToString() : XMLDate.Day.ToString()) + "T" +
                             (XMLDate.Hour < 10 ? "0" + XMLDate.Hour.ToString() : XMLDate.Hour.ToString()) + ":" +
                             (XMLDate.Minute < 10 ? "0" + XMLDate.Minute.ToString() : XMLDate.Minute.ToString());
                        if (XMLDate.Hour > 0 | XMLDate.Minute > 0)
                        {
                            excelDoc.Write("<Cell ss:StyleID=\"DateTimeLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                        }
                        else
                        {
                            excelDoc.Write("<Cell ss:StyleID=\"DateLiteral\">" +
                                         "<Data ss:Type=\"DateTime\">");
                        }
                        excelDoc.Write(XMLDatetoString);
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Boolean":
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                                    "<Data ss:Type=\"String\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                    case "System.Byte":
                        excelDoc.Write("<Cell ss:StyleID=\"Integer\">" +
                                "<Data ss:Type=\"Number\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.Decimal":
                    case "System.Double":
                        excelDoc.Write("<Cell ss:StyleID=\"Decimal\">" +
                              "<Data ss:Type=\"Number\">");
                        excelDoc.Write(x[y].ToString());
                        excelDoc.Write("</Data></Cell>");
                        break;
                    case "System.DBNull":
                        excelDoc.Write("<Cell ss:StyleID=\"StringLiteral\">" +
                              "<Data ss:Type=\"String\">");
                        excelDoc.Write("");
                        excelDoc.Write("</Data></Cell>");
                        break;
                    default:
                        throw (new Exception(rowType.ToString() + " not handled."));
                }
            }
            excelDoc.Write("</Row>");
        }
        excelDoc.Write("</Table>");
        excelDoc.Write(" </Worksheet>");
        excelDoc.Write(endExcelXML);
        excelDoc.Close();
    }

#4


也可以创建了excel文件后,用数据库连接的方式往里面灌数据。用OleDb连接。我往excel文件读写数据都是这么做的。

#5


对了,Sheet就是表名,不过写的时候是$Sheet或者是Sheet$,记不清楚了。

#6


感觉慢的原因是频繁的拆箱,使用ArrayList的效率本身就不高.楼住看是否可以用数组.
com组件的编程,可以直接用数组填充一个sheet的Range.

#7


为什么存成那样?
Csv不是更好?

#8


up。学习