【背景】
之前写的,用于抓取Amazon的Hot Deal的数据。
【AmazonHotDeal 代码分享】
1.截图:
2.完整项目代码下载:
3.代码分享:
(1)frmAmazonHotDeal.cs
/* * [Function] * Amazon Hot Deal search * * [Date] * 2013-06-16 * * [Author] * Crifan Li * * [Contact] * https://www.crifan.com/contact_me * */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Web; using System.Net; using Sgml; using System.Xml; using System.IO; using Excel = Microsoft.Office.Interop.Excel; using Microsoft.Office.Interop.Excel; namespace AmazonHotDeal { public partial class frmAmazonHotDeal : Form { category mainCategory; List<category.categoryItem> mainCategoryList; public crifanLib crifanLib; public struct amazonProductInfo { public string category; public string productId; public string title; public bool isTop100; //http://www.amazon.com/gp/bestsellers/hi/ref=pd_dp_ts_hi_1 public string listPrice; public string salePrice; public string savingPrice; public string savingPercentage; //public string comm; public string rating; public string reviews; }; public frmAmazonHotDeal() { //!!! for load embedded dll: (1) register resovle handler AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); InitializeComponent(); crifanLib = new crifanLib(); } //for load embedded dll System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", ""); dllName = dllName.Replace(".", "_"); if (dllName.EndsWith("_resources")) return null; System.Resources.ResourceManager rm = new System.Resources.ResourceManager(GetType().Namespace + ".Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly()); byte[] bytes = (byte[])rm.GetObject(dllName); return System.Reflection.Assembly.Load(bytes); } void initProductInfoGridView() { dgvProductInfo.ColumnCount = 10; dgvProductInfo.RowHeadersWidth = 60; dgvProductInfo.RowHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; dgvProductInfo.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing; dgvProductInfo.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; dgvProductInfo.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCellsExceptHeaders; //(1)Category dgvProductInfo.Columns[0].HeaderText = "Category"; //dgvProductInfo.Columns[0].Width = 250; //(2)Product ID dgvProductInfo.Columns[1].HeaderText = "Product ID"; //dgvProductInfo.Columns[1].Width = 200; //(3)Title dgvProductInfo.Columns[2].HeaderText = "Title"; //dgvProductInfo.Columns[2].Width = 200; //(4)Is Top 100 dgvProductInfo.Columns[3].HeaderText = "Is Top 100"; //dgvProductInfo.Columns[3].Width = 100; //(5)List Price dgvProductInfo.Columns[4].HeaderText = "List Price"; //dgvProductInfo.Columns[4].Width = 110; //(6)Sale Price dgvProductInfo.Columns[5].HeaderText = "Sale Price"; //dgvProductInfo.Columns[4].Width = 110; //(7)Savings dgvProductInfo.Columns[6].HeaderText = "Savings"; //dgvProductInfo.Columns[4].Width = 110; //(8)Savings % dgvProductInfo.Columns[7].HeaderText = "Savings %"; //dgvProductInfo.Columns[4].Width = 110; //(9)Rating dgvProductInfo.Columns[8].HeaderText = "Rating"; //dgvProductInfo.Columns[4].Width = 110; //(10)Reviews dgvProductInfo.Columns[9].HeaderText = "Reviews"; //dgvProductInfo.Columns[4].Width = 110; } private void frmAmazonHotDeal_Load(object sender, EventArgs e) { initProductInfoGridView(); mainCategory = new category(); mainCategoryList = mainCategory.getMainCategoryList(); //foreach (category.categoryItem singleMainCategory in mainCategoryList) //{ // cmbMainCatetory.Items.Add(singleMainCategory); //} cmbMainCatetory.DataSource = mainCategoryList; cmbMainCatetory.DisplayMember = "name"; cmbMainCatetory.SelectedIndex = -1; } private void cmbMainCatetory_SelectedIndexChanged(object sender, EventArgs e) { if (cmbMainCatetory.SelectedIndex >= 0) { //category.categoryItem selectedMainCategory = (category.categoryItem)cmbMainCatetory.Items[cmbMainCatetory.SelectedIndex]; category.categoryItem selectedMainCategory = (category.categoryItem)cmbMainCatetory.SelectedItem; List<category.categoryItem> subCategoryList = selectedMainCategory.subCategoryList; cmbSubCategory.DataSource = subCategoryList; cmbSubCategory.DisplayMember = "name"; cmbSubCategory.SelectedIndex = -1; //foreach (category.categoryItem singleSubCategory in subCategoryList) //{ // cmbSubCategory.Items.Add(singleSubCategory); //} } else { cmbSubCategory.DataSource = null; cmbSubCategory.DisplayMember = null; //cmbSubCategory.Items.Clear(); } } category.categoryItem getCurrentSelectedCategory() { category.categoryItem curSelectedCategory = new category.categoryItem(); if (cmbSubCategory.SelectedIndex >= 0) { //has selected some sub category curSelectedCategory = (category.categoryItem)cmbSubCategory.SelectedItem; } else { if (cmbMainCatetory.SelectedIndex >= 0) { //not select any sub category //so use the corresponding main category curSelectedCategory = (category.categoryItem)cmbMainCatetory.SelectedItem; } } return curSelectedCategory; } XmlDocument htmlToXmlDoc(string html) { // setup SgmlReader Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader(); sgmlReader.DocType = "HTML"; sgmlReader.WhitespaceHandling = WhitespaceHandling.All; sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower; //sgmlReader.InputStream = reader; sgmlReader.InputStream = new StringReader(html); // create document XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; doc.XmlResolver = null; doc.Load(sgmlReader); return doc; } //draw the row index void drawRowHeaderNumer(DataGridView dgvValue) { for (int index = 0; (index <= (dgvValue.Rows.Count - 1)); index++) { int number = index + 1; dgvValue.Rows[index].HeaderCell.Value = String.Format("{0}", number); } } void saveEachProduct(amazonProductInfo productInfo) { dgvProductInfo.Rows.Add( productInfo.category, productInfo.productId, productInfo.title, productInfo.isTop100?"yes":"no", productInfo.listPrice, productInfo.salePrice, productInfo.savingPrice, productInfo.savingPercentage, productInfo.rating, productInfo.reviews); drawRowHeaderNumer(dgvProductInfo); } //void processEachProductNode(category.categoryItem curSelCategory, XmlNode singleProductNode) void processEachProductNode(string categoryName, XmlNode singleProductNode) { amazonProductInfo productInfo = new amazonProductInfo(); //category name //productInfo.category = curSelCategory.Name; productInfo.category = categoryName; //product id productInfo.productId = "N/A"; //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 /* <div class="zg_itemImage_normal"><a href="http://www.amazon.com/Hamilton-Beach-25475-Breakfast-Sandwich/dp/B00BTIUYOO/ref=zg_bsnr_appliances_1/191-0874592-3518518 "><img src="http://ecx.images-amazon.com/images/I/41E3PVWxhML._SL160_SL160_.jpg" alt="Hamilton Beach 25475 Breakfast Sandwich Maker, Gray" title="Hamilton Beach 25475 Breakfast Sandwich Maker, Gray" onload="if (typeof uet == 'function') { uet('af'); }"/></a></div> */ //XmlNode itemImageNode = singleProductNode.SelectSingleNode(".//div[@class='zg_itemImage_normal']/a[@href]"); //special //http://www.amazon.com/gp/new-releases/appliances/3741521/ref=zg_bsnr_nav_la_1_la //7th item, contain nothing, only contain pic //<img src="http://ecx.images-amazon.com/images/I/41P-wTTZgFL._SL160_SL160_.jpg"/></a></div></div><div class="zg_itemRightDiv_normal"><div class="zg_rankLine"><span class="zg_rankNumber">7.</span><span class="zg_rankMeta"></span></div><div class="zg_itemPriceBlock_normal"> //now html change to //<div class="zg_image"> //<div class="zg_itemImageImmersion"> // <a href="http://www.amazon.com/Creative-Options-700-769-Shoulder-Organizers/dp/B00CB38TUC/ref=zg_bsnr_12896361_1/181-1310935-2535815"> // <div class="valign_wrapper" style="padding:10px 0 10px 0"> // <img src="http://ecx.images-amazon.com/images/I/51E3EHv1h2L._SL160_SL150_.jpg" alt="Creative Options 700-769 Soft Sided S..." title="Creative Options 700-769 Soft Sided S..." onload="if (typeof uet == 'function') { uet('af'); }" /> // </div></a> //</div> //</div> XmlNode itemImageNode = singleProductNode.SelectSingleNode(".//div[@class='zg_itemImageImmersion']/a[@href]"); string productUrl = itemImageNode.Attributes["href"].Value; //"\n\n\n\n\n\n\nhttp://www.amazon.com/Creative-Options-700-769-Shoulder-Organizers/dp/B00CB38TUC/ref=zg_bsnr_12896361_1/190-5936290-7962445\n" productUrl = HttpUtility.HtmlDecode(productUrl.Trim()); //"http://www.amazon.com/Creative-Options-700-769-Shoulder-Organizers/dp/B00CB38TUC/ref=zg_bsnr_12896361_1/190-5936290-7962445" //http://www.amazon.com/Hamilton-Beach-25475-Breakfast-Sandwich/dp/B00BTIUYOO/ref=zg_bsnr_appliances_1/191-0874592-3518518 string productId = ""; if (crifanLib.extractSingleStr(@"/([A-Z\d]+)/ref=", productUrl, out productId)) { productInfo.productId = productId; } else { //MessageBox.Show("Can not find product id from " + productUrl); } //title productInfo.title = "N/A"; //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 //<div class="zg_title"><a href="http://www.amazon.com/Hamilton-Beach-25475-Breakfast-Sandwich/dp/B00BTIUYOO/ref=zg_bsnr_appliances_1/191-0874592-3518518">Hamilton Beach 25475 Breakfast Sandwich Maker, Gray</a></div> XmlNode zgTitleNode = singleProductNode.SelectSingleNode(".//div[@class='zg_title']"); if (zgTitleNode != null) { productInfo.title = zgTitleNode.InnerText.Trim(); } else { //special //http://www.amazon.com/gp/new-releases/appliances/3741521/ref=zg_bsnr_nav_la_1_la //7th item, contain nothing, only contain pic } //is top 100 //has top 100: //http://www.amazon.com/gp/bestsellers/hi/ref=pd_dp_ts_hi_1 //<span class="zg_rankMeta"><span class="zg_arrowSprite zg_arrowUp"></span>2007 days in the top 100</span> //normal no top 100: //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 //<span class="zg_rankMeta"></span> XmlNode hasArrowSpriteNode = singleProductNode.SelectSingleNode(".//span[@class='zg_rankMeta']/span[@class]"); if (hasArrowSpriteNode != null) { productInfo.isTop100 = true; } else { productInfo.isTop100 = false; } //List Price, price, saving price and percentage productInfo.listPrice = "N/A"; productInfo.salePrice = "N/A"; productInfo.savingPrice = "N/A"; productInfo.savingPercentage = "N/A"; //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 //<p class="priceBlock"><strong>List Price: </strong> <span class="listprice">$65.00</span> </p><p class="priceBlock"><strong>Price: </strong> <span class="price"><b>$34.95</b></span> </p><p class="priceBlock"><strong>You Save: </strong> <span class="price">$30.05 (46%)</span></p> //XmlNode listPriceNode = singleProductNode.SelectSingleNode(".//p[@class='priceBlock']/span[@class='listprice']"); //now html change to: //<div class="zg_itemPriceBlock_compact"> //<div class="zg_price"> // <span class="listprice"></span> // <strong class="price">$24.99</strong> // <br /> //</div> //<div class="zg_usedPrice"> // <a href="http://www.amazon.com/gp/offer-listing/B00CB38TUC/ref=zg_bsnr_12896361_price/181-1310935-2535815?ie=UTF8&condition=new">3 new</a> from // <span class="price">$17.91</span> //</div> //</div> XmlNode listPriceNode = singleProductNode.SelectSingleNode(".//div[@class='zg_price']/strong[@class='price']"); if (listPriceNode != null) { productInfo.listPrice = listPriceNode.InnerText; } //XmlNodeList priceNodeList = singleProductNode.SelectNodes(".//p[@class='priceBlock']/span[@class='price']"); //if (priceNodeList.Count > 0) //{ // foreach (XmlNode curPriceNode in priceNodeList) // { // XmlNode parentNode = curPriceNode.ParentNode; // if (parentNode.InnerXml.Contains("Price: ")) // { // //<p class="priceBlock"><strong>Price: </strong> <span class="price"><b>$29.00</b></span> // productInfo.salePrice = curPriceNode.InnerText;//$29.00 // } // else if (parentNode.InnerXml.Contains("You Save:")) // { // //<p class="priceBlock"><strong>You Save: </strong> <span class="price">$30.05 (46%)</span></p> // string savingTxt = curPriceNode.InnerText; // string[] priceAndPercent = savingTxt.Split(' '); // productInfo.savingPrice = priceAndPercent[0]; // if (priceAndPercent.Length > 1) // { // productInfo.savingPercentage = priceAndPercent[1].Replace("(", "").Replace(")", ""); ; // } // else // { // //some only contain price, no saving percentage // //"<strong>You Save: </strong> <span class=\"price\">$0.04</span>" // } // } // else // { // //tmp omit : // //12 used & new from $25.00 // //in // //<p class="priceBlock"><a href="http://www.amazon.com/gp/offer-listing/B00ARQVM5O/ref=zg_bsnr_appliances_price/191-0874592-3518518?ie=UTF8&condition=all">12 used & new</a> from <span class="price">$25.00</span> // //from http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 // } // } //} XmlNode usedPriceNode = singleProductNode.SelectSingleNode(".//div[@class='zg_usedPrice']/span[@class='price']"); if (usedPriceNode != null) { productInfo.salePrice = usedPriceNode.InnerText; } //rating and reviews productInfo.rating = "N/A"; productInfo.reviews = "N/A"; //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 //<span class="crAvgStars" style="white-space:no-wrap;"><span class="asinReviewsSummary acr-popover" name="B00BTIUYOO" ref="zg_bsnr_appliances_cm_cr_acr_pop_" > <a ......" ><span class="swSprite s_star_4_0 " title="4.0 out of 5 stars" ><span>4.0 out of 5 stars</span></span> </a> <span class="histogramButton" style="margin-left:-3px">......</span></span>(<a href="http://........ie=UTF8&showViewpoints=1" >14</a>)</span> XmlNode avgStarsNode = singleProductNode.SelectSingleNode(".//span[@class='crAvgStars']"); if (avgStarsNode != null) { //rating string productRating = ""; //<span class="swSprite s_star_4_0 " title="4.0 out of 5 stars" > if (crifanLib.extractSingleStr(@"<span class=""swSprite.+?"" title=""([\d\.]+) out of 5 stars""", avgStarsNode.InnerXml, out productRating)) { productInfo.rating = productRating; } else { MessageBox.Show("Can not find rating from" + avgStarsNode.InnerXml); } //reviews XmlNode reviewsANode = avgStarsNode.SelectSingleNode("./a[@href]"); if (reviewsANode != null) { productInfo.reviews = reviewsANode.InnerText; } } saveEachProduct(productInfo); } //void processSinglePageCategoryHtml(category.categoryItem curSelCategory, string singlePageHtml) void processSinglePageCategoryHtml(string singlePageHtml) { string decodedHtml = HttpUtility.HtmlDecode(singlePageHtml); XmlDocument xmlDoc = htmlToXmlDoc(decodedHtml); //find title==category first //<h1 id="zg_listTitle">Hot New Releases in <span class="category">Appliances</span></h1> XmlNode listTitleNode = xmlDoc.SelectSingleNode("//h1[@id='zg_listTitle']/span[@class='category']"); string categoryName = listTitleNode.InnerText; //find products info //<div class="zg_itemRow"> //XmlNodeList zgItemRowNodeList = xmlDoc.SelectNodes("//div[@class='zg_itemRow']"); //now html change to: //<div class="zg_itemWrapper" style="height:300px"> XmlNodeList zgItemRowNodeList = xmlDoc.SelectNodes("//div[@class='zg_itemWrapper']"); foreach (XmlNode singleProductNode in zgItemRowNodeList) { //processEachProductNode(curSelCategory, singleProductNode); processEachProductNode(categoryName, singleProductNode); } } //void processSubCategoryHtml(category.categoryItem curSelCategory, string subCategoryHtml) void processSubCategoryHtml(string subCategoryHtml) { //string decodedHtml = HttpUtility.HtmlDecode(subCategoryHtml); ////<div class="zg_itemRow"> //XmlDocument xmlDoc = htmlToXmlDoc(decodedHtml); //XmlNodeList zgItemRowNodeList = xmlDoc.SelectNodes("//div[@class='zg_itemRow']"); ////find title==category first ////<h1 id="zg_listTitle">Hot New Releases in <span class="category">Appliances</span></h1> //XmlNode listTitleNode = xmlDoc.SelectSingleNode("//h1[@id='zg_listTitle']/span[@class='category']"); //string categoryName = listTitleNode.InnerText; //foreach (XmlNode singleProductNode in zgItemRowNodeList) //{ // //processEachProductNode(curSelCategory, singleProductNode); // processEachProductNode(categoryName, singleProductNode); //} processSinglePageCategoryHtml(subCategoryHtml); //check if still has more page //normal: //http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_nav_0 //has more page: //<div id='zg_paginationWrapper'> //<ol class="zg_pagination"> //<li class="zg_page zg_selected" id="zg_page1"> // <a page="1" ajaxUrl="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_1/191-0874592-3518518?ie=UTF8&pg=1&ajax=1" href="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_1/191-0874592-3518518?ie=UTF8&pg=1">1-20</a></li><li class="zg_page " id="zg_page2"> //... //<li class="zg_page " id="zg_page5"> // <a page="5" ajaxUrl="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_5/191-0874592-3518518?ie=UTF8&pg=5&ajax=1" href="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_5/191-0874592-3518518?ie=UTF8&pg=5">81-100</a></li> //</ol> //</div> //speical: //http://www.amazon.com/gp/new-releases/appliances/3741261/ref=zg_bsnr_nav_la_1_la //no more page: //<div id='zg_paginationWrapper'> //<ol class="zg_pagination"> //<li class="zg_page zg_selected" id="zg_page1"> // <a page="1" ajaxUrl="http://www.amazon.com/gp/new-releases/appliances/3741261/ref=zg_bsnr_3741261_pg_1?ie=UTF8&pg=1&ajax=1" href="http://www.amazon.com/gp/new-releases/appliances/3741261/ref=zg_bsnr_3741261_pg_1?ie=UTF8&pg=1">1-5</a></li> //</ol> //</div> //<ol class="zg_pagination"> //<li class="zg_page " id="zg_page2"><a page="2" ajaxUrl="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_2/191-0874592-3518518?ie=UTF8&pg=2&ajax=1" href="http://www.amazon.com/gp/new-releases/appliances/ref=zg_bsnr_appliances_pg_2/191-0874592-3518518?ie=UTF8&pg=2">21-40</a></li> XmlDocument xmlDoc = htmlToXmlDoc(HttpUtility.HtmlDecode(subCategoryHtml)); XmlNodeList pageNodeList = xmlDoc.SelectNodes("//ol[@class='zg_pagination']/li[@class]"); if (pageNodeList.Count > 1) { //more than 1 page for (int pageIdx = 1; pageIdx < pageNodeList.Count; pageIdx++) { XmlNode curPageNode = pageNodeList[pageIdx]; XmlNode ajaxUrlNode = curPageNode.SelectSingleNode(".//a[@href]"); string pageUrl = ajaxUrlNode.Attributes["href"].Value; string singlePageHtml = crifanLib.getUrlRespHtml(pageUrl); //processSinglePageCategoryHtml(curSelCategory, singlePageHtml); processSinglePageCategoryHtml(singlePageHtml); } } } void clearSearchResult() { dgvProductInfo.Rows.Clear(); } private void btnSearch_Click(object sender, EventArgs e) { category.categoryItem curSelCategory = getCurrentSelectedCategory(); if ((curSelCategory.Url != null) && (curSelCategory.Url != "")) { clearSearchResult(); string subCatRespHtml = crifanLib.getUrlRespHtml(curSelCategory.Url); //processSubCategoryHtml(curSelCategory, subCatRespHtml); processSubCategoryHtml(subCatRespHtml); } } private void btnClearAll_Click(object sender, EventArgs e) { dgvProductInfo.Rows.Clear(); } private string getSaveFolder() { string saveFolderPath = ""; //string saveFolderPath = System.Environment.CurrentDirectory; //fbdSaveFolder.SelectedPath = System.Environment.CurrentDirectory; DialogResult saveFolderResult = fbdSaveFolder.ShowDialog(); if (saveFolderResult == System.Windows.Forms.DialogResult.OK) { saveFolderPath = fbdSaveFolder.SelectedPath; } else if (saveFolderResult == System.Windows.Forms.DialogResult.Cancel) { saveFolderPath = ""; } return saveFolderPath; } private void openFolderAndSelectFile(string fullFilename) { System.Diagnostics.Process.Start("Explorer.exe", "/select," + fullFilename); } private void btnExportToCsv_Click(object sender, EventArgs e) { string saveFolderPath = getSaveFolder(); if ((saveFolderPath == null) || (saveFolderPath == "")) { return; } //settings //string delimiter = "|"; string delimiter = ","; string outputFilename = txbExportFilename.Text + ".csv"; string fullFilename = Path.Combine(saveFolderPath, outputFilename); StreamWriter csvStreamWriter = new StreamWriter(fullFilename, false, System.Text.Encoding.UTF8); //output header data string strHeader = ""; for (int i = 0; i < dgvProductInfo.Columns.Count; i++) { strHeader += dgvProductInfo.Columns[i].HeaderText + delimiter; } csvStreamWriter.WriteLine(strHeader); //output rows data for (int j = 0; j < dgvProductInfo.Rows.Count; j++) { string strRowValue = ""; for (int k = 0; k < dgvProductInfo.Columns.Count; k++) { strRowValue += dgvProductInfo.Rows[j].Cells[k].Value + delimiter; } csvStreamWriter.WriteLine(strRowValue); } csvStreamWriter.Close(); //after save file openFolderAndSelectFile(fullFilename); } private void btnExportToExcel_Click(object sender, EventArgs e) { string saveFolderPath = getSaveFolder(); if ((saveFolderPath == null) || (saveFolderPath == "")) { return; } Excel.Application xlApp = new Excel.Application(); Excel.Workbook xlWorkBook; Excel.Worksheet xlWorkSheet; object misValue = System.Reflection.Missing.Value; xlApp = new Excel.ApplicationClass(); xlWorkBook = xlApp.Workbooks.Add(misValue); xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); int i = 0; int j = 0; //save header for (i = 0; i <= dgvProductInfo.ColumnCount - 1; i++) { xlWorkSheet.Cells[0 + 1, i + 1] = dgvProductInfo.Columns[i].HeaderText; } //save cells for (i = 0; i <= dgvProductInfo.RowCount - 1; i++) { for (j = 0; j <= dgvProductInfo.ColumnCount - 1; j++) { DataGridViewCell cell = dgvProductInfo[j, i]; xlWorkSheet.Cells[i + 2, j + 1] = cell.Value; } } //formatting //header to bold Range headerRow = xlWorkSheet.get_Range("1:1", System.Type.Missing); headerRow.Font.Bold = true; string outputFilename = txbExportFilename.Text + ".xls"; string fullFilename = Path.Combine(saveFolderPath, outputFilename); //xlWorkBook.SaveAs(fullFilename, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue); xlWorkBook.SaveAs(fullFilename, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, XlSaveConflictResolution.xlLocalSessionChanges, misValue, misValue, misValue, misValue); //auto adjust column width (according to content) Range allColumn = xlWorkSheet.Columns; allColumn.AutoFit(); xlWorkBook.Close(true, misValue, misValue); xlApp.Quit(); releaseObject(xlWorkSheet); releaseObject(xlWorkBook); releaseObject(xlApp); openFolderAndSelectFile(fullFilename); } private void releaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; MessageBox.Show("Exception Occured while releasing object " + ex.ToString()); } finally { GC.Collect(); } } } }
【总结】