1. 程式人生 > >匯入EXCEL報錯:"外部表不是預期的格式錯誤"、檔案格式和副檔名不匹配,檔案可能已損壞或不安全的解決方法

匯入EXCEL報錯:"外部表不是預期的格式錯誤"、檔案格式和副檔名不匹配,檔案可能已損壞或不安全的解決方法

開發環境:C# + EXCEL2003 + VS2008

問題:

當使用如下程式碼從gridview匯出資料到excel後,無法從excel取出資料,具體如下:

1、原使用的程式碼:

        protected void ExcelOut_Click(object sender, EventArgs e)
        {
            Response.Clear(); //清除緩衝區流中的所有內容輸出
            Response.Buffer = true; //
            Response.Charset = "";    //設定輸出流的http字符集
            //儲存附件用"attachment;filename=bang.xls";線上開啟用"online;filename=bang.xls"
            //可以是.doc、.xls、.txt、.htm、
            Response.AppendHeader("Content-Disposition", "attachment;filename=bang.xls");
            Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");//設定輸出流為簡體中文

            //設定輸出檔案型別為excel檔案。儲存為word時,應為"application/ms-word" 
            //可以為application/ms-excel、application/ms-word、application/ms-txt、application/ms-html、或其他瀏覽器可直接支援文件  
            Response.ContentType = "application/vnd.ms-excel";

            this.EnableViewState = false;   //關閉儲存檢視狀態 
            System.Globalization.CultureInfo myCItrad = new System.Globalization.CultureInfo("ZH-CN", true);//區域設定
            System.IO.StringWriter oStringWriter = new System.IO.StringWriter(myCItrad);
 
            System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter);
            DepartList.RenderControl(oHtmlTextWriter); //將DataGrid(dgBang)中的內容輸出到oHtmlTextWriter
            Response.Write(oStringWriter.ToString());
            Response.End();//將當前所有緩衝的輸出傳送到客戶端,並停止該頁執行
       }
使用這段程式碼確實可以匯出資料,並以excel的格式儲存在使用者的客戶端電腦裡,但當使用到這些匯出的excel檔案時就出問題了,下面程式碼是使用這些excel檔案的:

前臺頁面需要一個控制元件配合:

<asp:FileUpload ID="ExcelIn" runat="server" Width="250px" CssClass="inputcss" 
                                            Height="16px" ></asp:FileUpload>  <font face="宋體"></font>

        protected void ExcelInButton_Click(object sender, EventArgs e)
        {
            string strFilePath = "";
            string serverPath = "";
            //通過控制元件來獲取使用者待上傳的excel檔名,這個excel檔案其實是上面程式產生的檔案
            strFilePath = ExcelIn.PostedFile.FileName;
            // strFilePath = strFilePath.Substring(strFilePath.LastIndexOf("."));
            // 獲取系統時間生成附件名
            //strFilePath = DateTime.Now.ToFileTime().ToString() + strFilePath;
            // 將附件儲存到伺服器上
            ExcelIn.PostedFile.SaveAs(("D:") + "\\空調標杆附件\\" + strFilePath);
            serverPath = "D:\\空調標杆附件\\" + strFilePath;

            string strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + serverPath + ";Extended Properties='Excel 8.0;HDR=YES;IMEX=1'";
            OleDbConnection ExcelConn = new OleDbConnection(strCon);
            try
            {
                string strCom = "SELECT * FROM [Sheet1$]";
                <span style="background-color: rgb(255, 102, 102);">ExcelConn.Open();</span>
                OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom, ExcelConn);
                DataSet ds = new DataSet();
                myCommand.Fill(ds, "[Sheet1$]");<pre>                //由於excel列名“當月效益”和gridview中“當月效益”指定的資料來源"效益"不一樣,無法匹配資料來源,因此要把excel中列名改為“效益”
                ds.Tables[0].Columns["當月效益"].ColumnName = "效益";
                DepartList.DataSource = ds;
                DepartList.DataBind();
                ExcelConn.Close();
            }
            catch (MembershipCreateUserException ex)
            {
                ExcelConn.Close();
                Response.Write("<script>alert('匯入內容:" + ex.Message + "')</script>");
            }
        }

當程式執行到下面程式時,會報錯,錯誤程式碼為:"外部表不是預期的格式錯誤"。

ExcelConn.Open();

分析:

當我們用2003以上版本的excel開啟這些excel檔案時,會出現:檔案格式和副檔名不匹配,檔案可能已損壞或不安全。


這說明我們用

 ExcelOut_Click(object sender, EventArgs e)
來生成excel檔案的方法不是很好,我在網上查閱了大量資料,按照各種方法也沒有解決這個問題,然後我用另外一種方法從gridview匯出資料到excel,結果成功了,不再出現:“檔案格式和副檔名不匹配,檔案可能已損壞或不安全”這個錯誤。程式碼如下:
       /// <summary>
        /// 將資料從gridview匯入到本地excel,檔案儲存在D:\\除錯檔案\\中,檔名為當時的時間
        /// </summary>
        /// <param name="FileName"></param>
        private void SaveFile(String FileName)
        {
            try
            {

                string fileNameString = "D:\\除錯檔案\\" + FileName;

                //驗證strFileName是否為空或值無效   
                if (fileNameString.Trim() == " ")
                { return; }
                //定義表格內資料的行數和列數   
                int rowscount = DepartList.Rows.Count;
                int colscount = DepartList.Columns.Count;
                //行數必須大於0   
                if (rowscount <= 0)
                {
                    System.Web.HttpContext.Current.Response.Write("沒有資料可供儲存");
                    return;
                }

                //列數必須大於0   
                if (colscount <= 0)
                {
                    System.Web.HttpContext.Current.Response.Write("沒有資料可供儲存");
                    return;
                }

                //行數不可以大於65536   
                if (rowscount > 65536)
                {
                    System.Web.HttpContext.Current.Response.Write("資料記錄數太多(最多不能超過65536條)");
                    return;
                }

                //列數不可以大於255   
                if (colscount > 255)
                {
                    System.Web.HttpContext.Current.Response.Write("資料記錄行數太多,不能儲存");
                    return;
                }



                Microsoft.Office.Interop.Excel.Application objExcel = null;
                Microsoft.Office.Interop.Excel.Workbook objWorkbook = null;
                Microsoft.Office.Interop.Excel.Worksheet objsheet = null;

                try
                {
                    //申明物件   
                    objExcel = new Microsoft.Office.Interop.Excel.Application();
                    objWorkbook = objExcel.Workbooks.Add(true);
                    objsheet = (Microsoft.Office.Interop.Excel.Worksheet)objWorkbook.ActiveSheet;
                    //設定EXCEL不可見   
                    objExcel.Visible = false;

                    //設定列寬
                    //objExcel.Range objRng = objsheet.get_Range(objsheet.Cells[1, 1], objsheet.Cells[1, 1]);


                    //向Excel中寫入表格的表頭   
                    int displayColumnsCount = 1;
                    for (int i = 0; i <= DepartList.Columns.Count - 1; i++)
                    {
                        if (DepartList.Columns[i].Visible == true)
                        {
                            objExcel.Cells[1, displayColumnsCount] = DepartList.Columns[i].HeaderText.Trim();
                            displayColumnsCount++;
                        }
                    }
                    //向Excel中逐行逐列寫入表格中的資料   
                    for (int row = 0; row <= DepartList.Rows.Count - 1; row++)
                    {
                        displayColumnsCount = 1;
                        for (int col = 0; col < 2; col++)
                        {
                            if (DepartList.Columns[col].Visible == true)
                            {
                                try
                                {
                                    if (DepartList.Rows[row].Cells[col].Text != null)
                                    {
                                        objExcel.Cells[row + 2, displayColumnsCount] = DepartList.Rows[row].Cells[col].Text.ToString();
                                    }
                                    else
                                    {
                                        objExcel.Cells[row + 2, displayColumnsCount] = "";
                                    }
                                    displayColumnsCount++;
                                }
                                catch (Exception ex)
                                {
                                    System.Web.HttpContext.Current.Response.Write(ex.Message);
                                }

                            }
                        }
                    }

                    //儲存檔案   
                    objWorkbook.SaveAs(fileNameString, true, null, null, null,
                            null, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlShared, true, true, true,
                            true, true);
                    objExcel.Quit();

                }
                catch (Exception error)
                {
                    System.Web.HttpContext.Current.Response.Write(error.Message);
                    return;
                }
            }
            catch (Exception ex)
            {
                System.Web.HttpContext.Current.Response.Write(ex.Message);
            }
        }
上面的函式只能實現從gridview匯出資料到excel,要使得使用者可以下載生成的檔案,那得用到另一個函式:
        /// 下載伺服器上已有檔案
        /// </summary>
        /// <param name="fileName">儲存到客戶端時的檔名</param>
        /// <param name="filePath">下載檔案在伺服器上所在物理路徑全名</param>
        public static void DownloadFile(String fileName, String filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            System.Web.HttpContext.Current.Response.Clear();
            System.Web.HttpContext.Current.Response.ClearContent();
            System.Web.HttpContext.Current.Response.ClearHeaders();
            System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
            System.Web.HttpContext.Current.Response.AddHeader("Content-Length", fileInfo.Length.ToString());
            System.Web.HttpContext.Current.Response.AddHeader("Content-Transfer-Encoding", "binary");
            System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream";
            System.Web.HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
            System.Web.HttpContext.Current.Response.WriteFile(fileInfo.FullName);
            System.Web.HttpContext.Current.Response.Flush();
            System.Web.HttpContext.Current.Response.End();
        }

使用方法如下:
       protected void ExcelOut_Click(object sender, EventArgs e)
        {
            string FileName = DateTime.Now.ToFileTime().ToString() + ".xls";
            string FilePath = "D:\\除錯檔案\\" + FileName;
            SaveFile(FileName);
            DownloadFile(FileName, FilePath);

        }