最近接了一个新需求,主要有三个功能:
1.导出1688店铺的订单
2.导出入住微供市场店铺的商品
3.给微供市场进行下订单
其中如何调用阿里的接口进行数据获取这里就不做介绍了,但是如果有同学需要这方面的帮助可以联系我。
这里主要讲述如何导出excel。
最先开始的思路就是通过接口获取到订单信息之后通过页面Response进行输出一个Excel.
新建一个aspx页面。然后写一个方法如下:
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="lst"></param>
/// <param name="loginId"></param>
private void ExportExcel(List<OrdersItemDetailInfo> lst, string loginId)
{
string name = string.Format("{0}{1}订单报表.xls", loginId, DateTime.Now.ToString("yyMMddHHmmss"));
HttpContext.Current.Response.Clear();
string styleText = @"<style type='text/css'> .text{ mso-number-format:'\@'; } </style> ";
HttpContext.Current.Response.Charset = "UTF-8";
HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;//注意编码
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(name, Encoding.UTF8).ToString());
HttpContext.Current.Response.ContentType = "application/ms-excel";
var sbHtml = new StringBuilder();
sbHtml.Append("<table border='1' cellspacing='0' cellpadding='0'>");
sbHtml.Append("<tr>");
var lstTitle = new List<string> { "订单编号", "订单状态", "买家id", "买家联系电话", "买家收货地址", "创建时间","付款时间","商品ID",
"分类编号","商品名称", "数量", "商品单价", "付款时分摊后的每笔子订单金额", "产品金额", "折扣价",
"产品打折单价", "明细单价","卖家公司名称","运单号码","物流编号","物流公司","收货人姓名","收货手机","收货电话","收货省","收货市","收货区","收货地址" };
foreach (var item in lstTitle)
{
sbHtml.AppendFormat("<td style='font-size: 14px;text-align:center;background-color: #DCE0E2; font-weight:bold;' height='25'>{0}</td>", item);
}
sbHtml.Append("</tr>");
if (lst != null && lst.Count > 0)
{
foreach (var item in lst)
{
sbHtml.Append("<tr>");
sbHtml.AppendFormat("<td class='text' style='font-size: 12px;height:20px;'>{0}</td>", item.id);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.statusDisPlay);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.buyerLoginId);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", string.Empty);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.toArea);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", Utility.ChangeDate(item.gmtCreate));
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", Utility.ChangeDate(item.gmtPayment));
sbHtml.AppendFormat("<td class='text' style='font-size: 12px;height:20px;'>{0}</td>", item.itemId.ToString());
sbHtml.AppendFormat("<td class='text' style='font-size: 12px;height:20px;'>{0}</td>", item.categoryId.ToString());
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.productName);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.quantity);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.price);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.actualPayFee);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.amount);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.discount);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.discountPrice);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.unitPrice);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.sellerCompanyName);
sbHtml.AppendFormat("<td class='text' style='font-size: 12px;height:20px;'>{0}</td>", item.logisticsBillNo);
sbHtml.AppendFormat("<td class='text' style='font-size: 12px;height:20px;'>{0}</td>", item.logisticsId);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.logisticsCompanyName);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverName);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverMobile);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverPhone);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverProvince);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverCity);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverCounty);
sbHtml.AppendFormat("<td style='font-size: 12px;height:20px;'>{0}</td>", item.receiverAddress);
sbHtml.Append("</tr>");
}
}
sbHtml.Append("</table>");
var charset = "<meta http-equiv=\"content-type\" content=\"application/vnd.ms-excel; charset=utf-8\"/>";
HttpContext.Current.Response.Write(charset + styleText + sbHtml.ToString());
HttpContext.Current.Response.End();
}
其中遇到了几个问题:
问题1:当列的值是一个long长整型的时候,打开excel的时候就会显示成科学计数法,如图产品编号就变成科学计数的方式显示了。
问题2:结果导出Excel 真实数据才几十KB.但是Excel文件却有好几百。原因就是输除了大量的html标签。下图是一个200行数据的文件,相差已经是258kb 和41kb的区别了,当2000行的时候差距更明显。
问题3:点击了导出按钮,跳转到导出页面,执行导出相关代码流程,客户端一直等待服务器响应结束,但是因为数据太多处理时间需要几分钟甚至十几分钟,这样就会出现响应超时。
问题1解决办法:导出的额时候给td加一个样式。
string styleText = @".text{ mso-number-format:'\@'; }
问题2解决办法:使用了一个第三方操作excel的类库 NPOI ,http://npoi.codeplex.com/releases 类库地址,有源码。
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="lst"></param>
/// <param name="loginId"></param>
private void ExportExcel(List<ProductExInfo> lst, string loginId)
{
string name = string.Format("{0}销售商品列表.xls", loginId);
var lstTitle = new List<string> { "产品编号", "状态", "标题", "业务类型", "SKU", "specId", "单品货号", "属性", "单价", "建议零售价", "可销售数量", "单位", "发货地址ID", "运费模板ID", "体积", "产品链接" };
NPOI.HSSF.UserModel.HSSFWorkbook book = new NPOI.HSSF.UserModel.HSSFWorkbook();//创建工作簿
NPOI.SS.UserModel.ISheet sheet = book.CreateSheet("销售商品列表");//创建sheet
NPOI.SS.UserModel.IRow row = sheet.CreateRow(0);//创建表头第一行
for (int i = 0; i < lstTitle.Count; i++)
{
row.CreateCell(i).SetCellValue(lstTitle[i]);//循环创建单元格并且赋值
}
for (int j = 0; j < lst.Count; j++)
{
NPOI.SS.UserModel.IRow rowt = sheet.CreateRow(j + 1);
var rcol = rowt.CreateCell(0);
rcol.SetCellType(NPOI.SS.UserModel.CellType.String);
rcol.SetCellValue(lst[j].productID.ToString());
var rco15 = rowt.CreateCell(15);
HSSFHyperlink link = new HSSFHyperlink(HyperlinkType.Url);//建一个HSSFHyperlink实体,指明链接类型为URL(这里是枚举,可以根据需求自行更改)
link.Address = string.Format(@"https://detail.1688.com/offer/{0}.html", lst[j].productID);//给HSSFHyperlink的地址赋值
rco15.Hyperlink = link;//将链接方式赋值给单元格的Hyperlink即可将链接附加到单元格上
rco15.SetCellValue("链接");
}
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
book.Write(ms);
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", name));
Response.BinaryWrite(ms.ToArray());
book = null;
ms.Close();
ms.Dispose();
Response.End();
}
}
使用NPOI 进行导出Excel 同时也解决了第一个问题。
问题3解决办法:只能通过异步的方式去做了。
大致思路就是通过接口查询出订单然后生成一个excel文件在本地然后提供下载链接。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
namespace Ali1688.Web
{
/// <summary>
/// 生成Excel类
/// </summary>
public static class ExportExcelManager
{
//全局静态变量用来保存当前执行的logs
public static List<string> ExportLogs = new List<string>();
/// <summary>
/// 导出单个店铺的订单
/// </summary>
/// <param name="dts"></param>
/// <param name="dte"></param>
/// <param name="memberId"></param>
/// <param name="refreshToken"></param>
/// <param name="accessToken"></param>
/// <param name="loginid"></param>
public static void Report(DateTime dts, DateTime dte, string memberId, string refreshToken, string accessToken, string loginId)
{
ExportLogs.Clear();
ExportLogs.Add("开始导出" + loginId + dts.ToString("yyyy-MM-dd") + "到" + dte.ToString("yyyy-MM-dd") + "的订单");
List<OrdersItemDetailInfo> lst = new List<OrdersItemDetailInfo>();
lst = GetOrdersItem(memberId, accessToken, dts, dte);
ExportLogs.Add("订单获取完成开始生成Excel...");
string name = loginId + dts.ToString("yyyy-MM-dd") + "到" + dte.ToString("yyyy-MM-dd");
ExportExcel(lst, name, false);
}
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="lst"></param>
/// <param name="loginId"></param>
private static void ExportExcel(List<OrdersItemDetailInfo> lst, string loginId, bool isBatch = true)
{
string name = string.Format("{0}订单报表{1}.xls", loginId, DateTime.Now.ToString("yyyyMMddHHmmss"));
var lstTitle = new List<string> { "订单编号", "订单状态", "买家id", "买家联系电话", "买家收货地址", "创建时间","付款时间","商品ID",
"分类编号","商品名称", "数量", "商品单价", "付款时分摊后的每笔子订单金额", "产品金额", "折扣价",
"产品打折单价", "明细单价","卖家公司名称","运单号码","物流编号","物流公司","收货人姓名","收货手机","收货电话","收货省","收货市","收货区","收货地址" };
NPOI.HSSF.UserModel.HSSFWorkbook book = new NPOI.HSSF.UserModel.HSSFWorkbook();
NPOI.SS.UserModel.ISheet sheet = book.CreateSheet("订单列表");
NPOI.SS.UserModel.IRow row = sheet.CreateRow(0);
for (int i = 0; i < lstTitle.Count; i++)
{
row.CreateCell(i).SetCellValue(lstTitle[i]);
}
ExportLogs.Add("共需要生成" + lst.Count + "条明细!");
for (int j = 0; j < lst.Count; j++)
{
NPOI.SS.UserModel.IRow rowt = sheet.CreateRow(j + 1);
//创建单元格
ExportLogs.Add("生成完成" + (j + 1) + " 条明细!");
}
ExportLogs.Add("所有明细生成完成,生成文件中。。。");
// 写入到客户端
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
book.Write(ms);
string path = System.AppDomain.CurrentDomain.BaseDirectory + (isBatch ? "/BatchReport/" : "/Report/") + name;
var dir = System.AppDomain.CurrentDomain.BaseDirectory + (isBatch ? "/BatchReport" : "/Report");
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
byte[] data = ms.ToArray();
fs.Write(data, 0, data.Length);
fs.Flush();
}
book = null;
}
ExportLogs.Add("生成Excel文件完成!请<a href='" + (isBatch ? "/BatchReport/" : "/Report/") + name + "'>点击下载</a>");
}
/// <summary>
/// 获取这个商铺的销售订单
/// </summary>
/// <param name="memberId"></param>
/// <param name="accessToken"></param>
/// <param name="dts"></param>
/// <param name="dte"></param>
/// <param name="pageIndex"></param>
/// <returns></returns>
private static List<OrdersItemDetailInfo> GetOrdersItem(string memberId, string accessToken, DateTime dts, DateTime dte)
{
//获取订单具体方法
throw new NotImplementedException();
}
}
}
调用代码:
Thread thread = new Thread(() => ExportExcelManager.Report(dts, dte, memberId, refreshToken, accessToken, loginId));
thread.Start();
最后来几张图片吧
1.主页面:
2.导出页面
3.导出成功
最后其实还有一个问题我没有解决掉,就是这个提示,其实是一个全局的静态变量。所以多个用户同时操作的时候会出现提示不准确。但是这个需求是我们内部的人员使用而且只是提示上面的不准确。
如果谁有好的提议可提出来我修改。