|
有一客戶需求: 1、要從SQL Server數(shù)據(jù)庫導(dǎo)出并生成Excel ; 2、用戶下載對應(yīng)的Excel并填寫上傳再導(dǎo)入到SQL server。 費了將近六個小時,故一定要把過程寫下來,希望看到此文的朋友少走些不必要的彎路。 首先,想到的是直接導(dǎo)出到客戶端,代碼如下: public static void DataSetToExcel(DataSet oDS, HttpResponse Response, string fileName)![]() {![]() if (oDS == null || oDS.Tables[0] == null || oDS.Tables[0].Rows.Count == 0) { return; } Response.Clear(); //Encoding pageEncode = Encoding.GetEncoding(PageEncode); HttpContext.Current.Response.Charset = "gb2312"; //Response.ContentType = "application/vnd-excel";//"application/vnd.ms-excel"; //Response.ContentType = "application/x-octet-stream";//"application/vnd.ms-excel"; Response.ContentType = "text/csv";//"application/vnd.ms-excel"; Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + ".cvs"); System.IO.StringWriter oSW = new System.IO.StringWriter(); HtmlTextWriter oHW = new HtmlTextWriter(oSW); DataGrid dg = new DataGrid(); dg.DataSource = oDS.Tables[0]; dg.DataBind(); dg.RenderControl(oHW); Response.Write(oSW.ToString()); Response.Flush(); Response.Close(); }
這樣生成是生成了! 客戶也可以用Excel直接打開并編輯,問題來了! 上傳時出錯,仔細看看生成的Excel.xls, 用記事本打開,內(nèi)容大致如下: <table cellspacing="0" rules="all" border="1" style="border-collapse:collapse;"> <tr> <td>品名</td><td>最高價格</td><td>最低價格</td><td>平均價格</td><td>計量單位</td><td>備注</td> </tr><tr> <td>青菜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>南瓜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>瓠子</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>冬春筍</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>雪里蕻</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>櫻桃蘿卜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>佛手瓜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>白菜鼎</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>蒜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>食用菌</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr><tr> <td>黃瓜</td><td> </td><td> </td><td> </td><td>元/公斤</td><td> </td> </tr> </table> 原來,就是純粹的html格式,披了件Excel的外衣。這樣用戶傳上來的文件當(dāng)然不是標(biāo)準(zhǔn)的Excel格式了! 于是, 想到直接生成xml格式的Excel文檔,方法如下 : ![]() /**//// <summary> /// 執(zhí)行導(dǎo)出 /// </summary> /// <param name="ds">要導(dǎo)出的DataSet</param> /// <param name="strExcelFileName">要導(dǎo)出的文件名</param> public static void ExportToExcel(DataSet source, string fileName)![]() {![]() 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=\"Bottom\"/>\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.0000\"/>\r\n </Style>\r\n " + "<Style ss:ID=\"Integer\">\r\n <NumberFormat " + "ss:Format=\"0\"/>\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>";![]() int rowCount = 0; int sheetCount = 1;![]() /**//* <xml version> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font/> <Interior/> <NumberFormat/> <Protection/> </Style> <Style ss:ID="BoldColumn"> <Font x:Family="Swiss" ss:Bold="1"/> </Style> <Style ss:ID="StringLiteral"> <NumberFormat ss:Format="@"/> </Style> <Style ss:ID="Decimal"> <NumberFormat ss:Format="0.0000"/> </Style> <Style ss:ID="Integer"> <NumberFormat ss:Format="0"/> </Style> <Style ss:ID="DateLiteral"> <NumberFormat ss:Format="mm/dd/yyyy;@"/> </Style> </Styles> <Worksheet ss:Name="Sheet1"> </Worksheet> </Workbook> */ excelDoc.Write(startExcelXML); excelDoc.Write("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">"); excelDoc.Write("<Table>"); excelDoc.Write("<Row>"); for (int x = 0; x < source.Tables[0].Columns.Count; x++)![]() { excelDoc.Write("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">"); excelDoc.Write(source.Tables[0].Columns[x].ColumnName); excelDoc.Write("</Data></Cell>"); } excelDoc.Write("</Row>"); foreach (DataRow x in source.Tables[0].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 < source.Tables[0].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": //Excel has a specific Date Format of YYYY-MM-DD followed by ![]() //the letter 'T' then hh:mm:sss.lll Example 2005-01-31T24:01:21.000![]() //The Following Code puts the date stored in XMLDate ![]() //to the format above![]() DateTime XMLDate = (DateTime)x[y]; string XMLDatetoString = ""; //Excel Converted Date![]() 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()) + ":" + (XMLDate.Second < 10 ? "0" + XMLDate.Second.ToString() : XMLDate.Second.ToString()) + ".000"; 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(); }
可惜, 生成的倒是XML格式了,但還是上傳格式不正確,考慮到客戶端可能是Excel2007/2003-97等等,決定放棄保存Excel到客戶端的方式。 第三種嘗試方案:用cvs保存,將第一種方法改為: Response.ContentType = "text/csv";//"application/vnd.ms-excel"; Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + ".cvs");
生成格式大致如下: "品名","最高價格","最低價格","平均價格","計量單位","備注" "青菜","","","","元/公斤","" "南瓜","","","","元/公斤","" "瓠子","","","","元/公斤","" "冬春筍","","","","元/公斤","" "雪里蕻","","","","元/公斤","" "櫻桃蘿卜","","","","元/公斤","" "佛手瓜","","","","元/公斤","" "白菜鼎","","","","元/公斤","" "蒜","","","","元/公斤","" "食用菌","","","","元/公斤","" "黃瓜","","","","元/公斤",""
導(dǎo)入到SQL Server時有多種方法: 給出簡要代碼: public static DataTable GetDataFromCSV(string filePath,int beginColumn)![]() { int intColCount = 0; bool blnFlag = true; DataTable mydt = new DataTable("myTableName");![]() DataColumn mydc; DataRow mydr;![]() string strline; string[] aryline;![]() System.IO.StreamReader mysr = new System.IO.StreamReader(filePath,System.Text.Encoding.UTF8); int FlagFirst =1; while ((strline = mysr.ReadLine()) != null)![]() { //if (beginColumn == FlagFirst) { FlagFirst++; continue; } strline = strline.Replace("\n", ""); strline = strline.Replace("\r", ""); strline = strline.Replace("\t", ""); //aryline = strline.Split(new char[] { '|' });![]() aryline = strline.Split(new char[] { ',' });![]() if (blnFlag)![]() { blnFlag = false; intColCount = aryline.Length; for (int i = 0; i < aryline.Length; i++)![]() { mydc = new DataColumn(aryline[i]); mydt.Columns.Add(mydc); } }![]() mydr = mydt.NewRow(); for (int i = 0; i < intColCount; i++)![]() { mydr[i] = aryline[i]; } mydt.Rows.Add(mydr); FlagFirst++; } mysr.Close(); mysr.Dispose(); return mydt; }也有人給出方案,直接從cvs中讀取 public static string PreFilePath=@"c:\Excel\"; public static string strconn = @"Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq="+PreFilePath+";Extensions=asc,csv,tab,txt;"; public static DataSet GetDataSetFromCSV( string filename)![]() { OdbcConnection objconn = new OdbcConnection(strconn); DataSet dscsv = new DataSet(); try![]() { string strsql = "select * from " + filename; //filename, for example: 1.csv OdbcDataAdapter odbccsvdataadapter = new OdbcDataAdapter(strsql, objconn);![]() odbccsvdataadapter.Fill(dscsv); return dscsv; } catch (Exception ex)![]() { throw ex; } }嘗試失?。。?/p> Code Project 上有篇文章, A Fast CSV Reader也可以試試。 雖然也可以湊合用, 但總覺得CVS出錯的可能性更大。 到此,決定放棄客戶端生成的方式,請看下篇 DataSet導(dǎo)出到Excel比較完整的解決方案(二)--服務(wù)器端生成文件(downmoon) 邀月注:本文版權(quán)由邀月和博客園共同所有,轉(zhuǎn)載請注明出處。
助人等于自助! 3w@live.cn |
|
|