最近在用c#的asp.net,需要批量導出數據。原本用的是stringbuilder逐個填充,但是隻能做到html強制格式轉換為xls,這不是真正的excel表格,所以在網上找了datatable快速填充到excel的方法。

使用該方法後,發現下載了以後的表格沒有辦法用exce軟件l打開,而且電腦的所有的excel文件都打不開了,重啓後才可以,花了一天時間才找到問題所在。

如下圖所示,打開表格,什麼都不顯示,表格名字也不對。

導出 convertToExcelData 空數據不進入_Office

有的人遇到這種情況,可能是視圖裏面選擇了隱藏,需要取消隱藏,但是我並沒有隱藏數據,而且這幾個按鈕點擊了就變暗,並沒有反應

導出 convertToExcelData 空數據不進入_Interop_02

我覺得是我的代碼有問題,就仔細檢查了,最後終於發現問題所在了

以下是我的方法

protected void ExportExcel(System.Data.DataTable dt)
        {
            if (dt == null || dt.Rows.Count == 0) return;
            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
            //Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.ApplicationClass();
            if (xlApp == null)
            {
                return;
            }

            System.Globalization.CultureInfo CurrentCI = System.Threading.Thread.CurrentThread.CurrentCulture;
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
            Microsoft.Office.Interop.Excel.Workbook workbook =
                workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
            Microsoft.Office.Interop.Excel.Worksheet worksheet =
                (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];
            Microsoft.Office.Interop.Excel.Range range, range2, range3, range4, range5, range6, range7;
            long totalCount = dt.Rows.Count;
            //long rowRead = 0;
            //float percent = 0;
            xlApp.ScreenUpdating = false;  //屏幕不跟新,加快速度             
            int colCount = dt.Columns.Count;//列總數
            int rowCount = dt.Rows.Count;//行總數
            object[,] objData = new object[rowCount + 1, colCount];//標題
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;
                range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, i + 1];
                range.Interior.ColorIndex = 15;
                range.Font.Bold = true;
            }
            //獲取實際數據
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
            {
                for (int colIndex = 0; colIndex < colCount; colIndex++)
                {
                    objData[rowIndex, colIndex] = dt.Rows[rowIndex][colIndex].ToString();
                }
            }
            for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
            {
                objData2[rowIndex, 0] = dt.Rows[rowIndex][3].ToString();
                objData3[rowIndex, 0] = dt.Rows[rowIndex][14].ToString();
                objData4[rowIndex, 0] = dt.Rows[rowIndex][46].ToString();
                objData5[rowIndex, 0] = dt.Rows[rowIndex][49].ToString();
                objData6[rowIndex, 0] = dt.Rows[rowIndex][52].ToString();
            }
            range = (Range)worksheet.Range[xlApp.Cells[2, 1], xlApp.Cells[rowCount + 1, colCount]];
            range.NumberFormatLocal = "@";//寫入到表中的數據格式以文本形式存在
            range.Value2 = objData;

            worksheet.Cells.Columns.AutoFit();
            xlApp.Visible = true;
            //11.保存表格到根目錄下指定名稱的文件中
            string pathname = "~/Upload" + "/" + "Pks_data" + "/" + (string)Session[AppSetting.SESSION_USERNAME] +
                              DateTime.Now.Date.ToString("yyyyMMdd") + ".xlsx";
            string filePath = Server.MapPath(pathname);//路徑
            if (System.IO.File.Exists(Path.GetFullPath(filePath)))
            {
                File.Delete(Path.GetFullPath(filePath));
            }
            xlApp.ActiveWorkbook.SaveAs(filePath);
            xlApp.Quit();
            xlApp = null;
            GC.Collect();
            DownloadFile(pathname);
        }

        public void DownloadFile(string fileRpath)
        {
            string filepath = Server.MapPath(fileRpath);
            Response.ClearHeaders();
            Response.Clear();
            Response.Expires = 0;
            Response.Buffer = true;
            Response.AddHeader("Accept-Language", "zh-tw");
            string name = System.IO.Path.GetFileName(filepath);
            System.IO.FileStream files = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            byte[] byteFile = null;
            if (files.Length == 0)
            {
                byteFile = new byte[1];
            }
            else
            {
                byteFile = new byte[files.Length];
            }
            files.Read(byteFile, 0, (int)byteFile.Length);
            files.Close();

            Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(name, System.Text.Encoding.UTF8));
            Response.ContentType = "application/octet-stream;charset=gbk";
            Response.BinaryWrite(byteFile);
            Response.Flush();
            Response.End();

        }

 用了這個方法以後,的確比用stringbuilder快很多,而且可以導出正確格式的xlsx,但是打不開,後來發現問題出在這

//xlApp.ScreenUpdating = false;  //屏幕不跟新,加快速度

把這一行註釋了以後,就正常了,雖然我也不是很明白原理....


 

因為只會調用方法,但是不明白方法中每個語句的含義和用法,所以會有很多問題,希望自己能慢慢解決吧

2019-04-21