前言:
最近收到任务是公司需要一份新报表,挂到公司内部的网页上,供使用者查询,然而这份报表所要呈现的资料并无法直接以Sql语法捞出,虽然这部分不排除是我Sql功力不足,但无论如何,问题来了还是得解决,只好另闢蹊径,想把要用的资料捞出来后再自行整理成使用者需要的样式。
问题:
这次的主要问题简而言之就是从SQL获取「库存资料」及「异动资料」,从这两个去整理出目前库存的库龄,最一开始我想到的解法便是:当使用者选完它要的搜寻条件后,按下查询会在网页上出现「库存资料」及「异动资料」的表格,当使用者按下【下载成Excel】的按钮后,再把他们整理成三个Sheet,依序为「库存资料」「异动资料」及「库龄报表」
解决方法:
这个问题并不难解决,只要把NPOI这个套件拿来使用就好(也顺手介绍一下NPOI的一些基本使用方法) //NPOI要使用的工作簿,工作表,列,储存格都需要先被「创造」后才能使用 HSSFWorkbook hssfworkbook = new HSSFWorkbook(); //建立活页簿 ISheet ws2 = hssfworkbook.CreateSheet("异动明细"); //建立sheet ISheet ws3 = hssfworkbook.CreateSheet("库存资料"); ISheet ws1 = hssfworkbook.CreateSheet("库存统计表");
创立好各个工作表(Sheet)后就可以开始把内容写入工作表内,而相信眼尖的朋友也已经发现刚刚说要先创造列,却没提到栏,那栏要创造吗?让我们看一下以下的程式码。ws1.CreateRow(0);//第一列被创造 ws1.GetRow(0).CreateCell(0).SetCellValue("厂别");//获取第一列,并创造第一列的第一个储存格 //(即第一栏,excel的A1储存格),并赋值。 ws1.GetRow(0).GetCell(0).CellStyle = headerStyle;
因为报表要好看,所以多了ws1.GetRow(0).GetCell(0).CellStyle = headerStyle;
这行来设置储存格的样式
至于headerStyle要怎么设置就要在前面先设好它的内容,方式个人觉得有点像Css的方式ICellStyle headerStyle = hssfworkbook.CreateCellStyle(); IFont headerfont = hssfworkbook.CreateFont(); headerStyle.Alignment = HorizontalAlignment.Center; //水平置中 headerStyle.VerticalAlignment = VerticalAlignment.Center; //垂直置中 headerfont.FontName = "微软正黑体"; headerfont.FontHeightInPoints = 12; headerfont.Boldweight = (short)FontBoldWeight.Bold;//粗体 headerfont.Color = NPOI.HSSF.Util.HSSFColor.White.Index; headerStyle.FillPattern = FillPattern.SolidForeground; headerStyle.FillForegroundColor = IndexedColors.Black.Index; headerStyle.SetFont(headerfont);
这些应该就是NPOI的基本介绍了,至于怎么把资料填入就是各种for迴圈跟if判断就不再赘述了!
下载下来就可以得到想要的报表了~(虽然我码了几乎整张图)
延伸问题
然而这样的做法却被嫌弃「不够直观」,「我要在网页上直接看到结果,我不要你的过程」等等,相信未来需要使用类似功能的人也会遇到类似的问题,希望先在网页端就看一下这次捞取出的资料长甚么样子,再决定要不要下载,然而C# asp.net却没有可以对资料进行计算整理然后再贴到网页的方法(也可能是我不会),苦思许久后,我决定直接複製,然后贴上,把刚刚要下载成excel的方法再做一次,但这次不下载,而是做完之后,直接像是上传了一个档案然后读取,在把它们一行一行填入table内,然后再利用Css美化我的表格。
解决方法
`
HSSFSheet worksheet = (HSSFSheet)hssfworkbook.GetSheetAt(0);
int rowCount = worksheet.LastRowNum; int colCount = worksheet.GetRow(0).LastCellNum; StringWriter sw = new StringWriter(); HtmlTextWriter hw = new HtmlTextWriter(sw); hw.Write("<style type='text/css'>"); hw.Write("table { border-collapse: collapse; width: 100%; }"); hw.Write("th ,td { text-align: left; padding: 12px; font-size:175%;}"); hw.Write("</style>"); hw.RenderBeginTag(HtmlTextWriterTag.Table); hw.RenderBeginTag(HtmlTextWriterTag.Tr); for (int j = 0; j < colCount; j++) { hw.RenderBeginTag(HtmlTextWriterTag.Th); hw.Write(worksheet.GetRow(0).GetCell(j).ToString()); hw.RenderEndTag(); } hw.RenderEndTag(); for (int i = 1; i <= rowCount; i++) { bool isSubtotal = i == clint_A + 1 || i == clint_H || i == clint_R; bool isTotal = i == clint_R + 1; string cssClass = ""; if (isSubtotal) { cssClass = "subtotal"; } else if (isTotal) { cssClass = "total"; } hw.RenderBeginTag(HtmlTextWriterTag.Tr); for (int j = 0; j < colCount; j++) { if (worksheet.GetRow(i).GetCell(j) != null) { if (isSubtotal) { if (j != 0) { hw.AddAttribute("class", cssClass); hw.RenderBeginTag(HtmlTextWriterTag.Th); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } else { hw.AddAttribute("class", cssClass); hw.AddStyleAttribute("font-size", "200%"); hw.AddAttribute("colspan", "2"); hw.RenderBeginTag(HtmlTextWriterTag.Th); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } }else if (isTotal) { if (j != 0) { hw.AddAttribute("class", cssClass); hw.RenderBeginTag(HtmlTextWriterTag.Th); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } else { hw.AddAttribute("class", cssClass); hw.AddStyleAttribute("font-size", "200%"); hw.AddAttribute("colspan", "2"); hw.RenderBeginTag(HtmlTextWriterTag.Th); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } } else { hw.RenderBeginTag(HtmlTextWriterTag.Td); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } } else { if (!isTotal && !isSubtotal) { hw.RenderBeginTag(HtmlTextWriterTag.Td); worksheet.GetRow(i).CreateCell(j).SetCellValue(""); hw.Write(worksheet.GetRow(i).GetCell(j).ToString()); hw.RenderEndTag(); } } } hw.RenderEndTag(); } string total_num = worksheet.GetRow(clint_R + 1).GetCell(2).ToString(); lblTotal.Text = total_num; hw.RenderEndTag(); hssfworkbook.Close(); Label1.Text = sw.ToString();
`
就像是这样,把东西都做完后呢!再插入Label
这样就可以完成我要的样子了
如下图,一样打码处理
因为前两家工厂没有被选到,所以只有一列,列出工厂名字,但完全没有对应的客户,故以灰色显示
第三家工厂有被使用者选到,所以会有很多列,每一列都是C厂配上C1客户,C2客户等等已次类推
最下面的黑色则为所有有被选到的工厂的总计。
后记:
进公司三个多月从巨集要用的VB到SQL再到C# asp.net都是从0开始,边做边查边学,英文奇差的我也因此看了很多英文的网站,但这次后来的延伸问题是真的没查到,大部分都只查到怎么转成Excel(没错就是用NPOI),但这我已经会了呀~没有办法的情况下只能自己多绕几条路用本文的方法来解决,特别发文,一来是为了避免自己忘记,二来也为了未来有跟我一样的初心者,三来更是为了记录自己的成长,所以就记录了下来,我也明白这样的方法感觉有点绕,但至少解决了目前的问题,也希望如果有大神路过此文,能指点我更棒的方法,先说声感恩了!