首页 > 其他分享 >DataTable的行列转换及多表头HTML表格转Excel

DataTable的行列转换及多表头HTML表格转Excel

时间:2023-02-27 21:02:49浏览次数:54  
标签:string Excel System listCells HTML 表头 ._ using public


需要解决的问题:

1、根据数据库中多个不同字段名称的以行形式表现的数据转为以列形式展现的数据;

2、HTML多表头数据展示,做到数据“一个萝卜一个坑”,并求出多条数据的合计数据。

3、将HTML表格转为EXCEL。

先看效果图:

DataTable的行列转换及多表头HTML表格转Excel_数据转换

图1 HTML页面表格


DataTable的行列转换及多表头HTML表格转Excel_html_02

图2 导出为Excel文档


DataTable的行列转换及多表头HTML表格转Excel_数据库_03

图3 数据行不同,表头列数也不相同


DataTable的行列转换及多表头HTML表格转Excel_数据转换_04

  

图4  行数据记录不同时,表格的表头也变得不同(对比图1),各相关行数据需要一一对应。


HTML表格的结构:

<table id="TableStatics" align="center">
<tbody>

<tr>

<td rowspan="2">

工单编号

</td>

<td rowspan="2">

生产数量

</td>

<td colspan="7" class="Ocv">

OCV1

</td>

<td colspan="6" class="Ocv">

OCV2

</td>

<td colspan="7" class="Ocv">

OCV3

</td>

<td colspan="9" class="Ocv">

OCV4

</td>

</tr>

<tr>

<td nowrap="">

A

</td>

<td nowrap="">

A1

</td>

<td nowrap="">

电压B

</td>

<td nowrap="">

电压C

</td>

<td nowrap="">

内阻D

</td>

<td nowrap="">

扫描异常

</td>

<td nowrap="">

数码A

</td>

<td nowrap="">

A

</td>

<td nowrap="">

C

</td>

<td nowrap="">

D1

</td>

<td nowrap="">

D3

</td>

<td nowrap="">

N2

</td>

<td nowrap="">

扫描异常

</td>

<td nowrap="">

A

</td>

<td nowrap="">

C

</td>

....

<td nowrap="">

扫描异常

</td>

</tr>

<!-- 数据行开始 -->

<tr>

<td>

20170221

</td>

<td>

100000

</td>

<td>

18

</td>

...

</tr>

<tr.....>

</tbody>

</table>

//ExcelCellInfo.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace LEBLL.ExcelOutput
{
/// <summary>
/// Excel单元格信息
/// </summary>
public class ExcelCellInfo
{
/// <summary>
/// 起始位置:X方向
/// </summary>
public int StartX = 1;

/// <summary>
/// 起始位置:Y方向
/// </summary>
public int StartY = 1;

/// <summary>
/// 单元格横向格数(占几列)
/// </summary>
public int ColSpan = 1;

/// <summary>
/// 单元格竖向格数(占几行)
/// </summary>
public int RowSpan = 1;

/// <summary>
/// 单元格内容
/// </summary>
public string Content = string.Empty;
}
}//ExcelGenerator.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using HtmlAgilityPack;

namespace LEBLL.ExcelOutput
{
public class ExcelGenerator
{
private string excelFileName = "Excel";
private int sheetCount = 1;
ExcelTableInfo excelTableInfo;
HtmlNode htmlNodeTable;
public string TableID = "TableStatics";

/// <summary>
///
/// </summary>
/// <param name="tableHTML">表格的HTML代码</param>
public ExcelGenerator(string tableHTML)
{
//Excel文件名
this.excelFileName = "电池批次统计";
//Excel文件的sheet数量
this.sheetCount = 1;

excelTableInfo = new ExcelTableInfo();
excelTableInfo.TableName = "电池批次统计信息";
excelTableInfo.SheetIndex = 1;
excelTableInfo.StartX = 1;
excelTableInfo.StartY = 1;

HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(tableHTML);
htmlNodeTable = htmlDoc.DocumentNode.SelectSingleNode("//table[@id='"+ TableID + "']");
excelTableInfo.HtmlNodeOfTable = htmlNodeTable;
}

public string Save(string fileDirectory)
{
ExcelWriter excelWriter = new ExcelWriter(this.sheetCount);
List<ExcelCellInfo> cells = this.ConvertToCells(excelTableInfo.StartX, excelTableInfo.StartY + 1, htmlNodeTable);
if (null != cells && cells.Count > 0)
{
excelWriter.Write(excelTableInfo.TableName, excelTableInfo.SheetIndex, cells);
}

string filePhysicalPath = System.Web.HttpContext.Current.Server.MapPath(fileDirectory);
string excelName = Utility.GetUniqueFileName(filePhysicalPath, this.excelFileName + ".xls");

excelWriter.Save(filePhysicalPath, excelName);

return excelName;
}

private List<ExcelCellInfo> ConvertToCells(int pnStartX, int pnStartY, HtmlNode htmlNodeOfTable)
{
HtmlNodeCollection trNodes = htmlNodeOfTable.SelectNodes("tr");
List<ExcelCellInfo> listCells = new List<ExcelCellInfo>();
for (int y = 0; y < trNodes.Count; y++)
{
HtmlNodeCollection tdNodes = trNodes[y].SelectNodes("td");
for (int x = 0; x < tdNodes.Count; x++)
{
ExcelCellInfo newCell = new ExcelCellInfo();
newCell.StartY = pnStartY + y;
newCell.StartX = pnStartX + this.HorizontalDeduction(tdNodes[x]);
newCell.ColSpan = tdNodes[x].GetAttributeValue("colspan", 1);
newCell.RowSpan = tdNodes[x].GetAttributeValue("rowspan", 1);
string content = tdNodes[x].InnerText.Trim();
newCell.Content = ((x == 0) ? "'" + content : content);

listCells.Add(newCell);
}
}

this.VerticalDeduction(listCells);

return listCells;
}

/// <summary>
/// 第一次colspan推演,即横向
/// </summary>
/// <param name="htmlNodeOfTd"></param>
/// <returns></returns>
private int HorizontalDeduction(HtmlNode htmlNodeOfTd)
{
HtmlNode htmlNodPreSibling = htmlNodeOfTd.PreviousSibling;
while (htmlNodPreSibling != null && htmlNodPreSibling.Name != htmlNodeOfTd.Name)
{
htmlNodPreSibling = htmlNodPreSibling.PreviousSibling;
}

if (htmlNodPreSibling != null)
{
int colSpan = htmlNodPreSibling.GetAttributeValue("colspan", 1);
return HorizontalDeduction(htmlNodPreSibling) + colSpan;
}

return 0;
}

/// <summary>
/// 第二次推演,即纵向
/// </summary>
/// <param name="listCells"></param>
private void VerticalDeduction(List<ExcelCellInfo> listCells)
{
for (int i = 0; i < listCells.Count; i++)
{
ExcelCellInfo currentCell = listCells[i];

bool bActedPush = false;

do
{
int comparedIndex = -1;
for (int j = i - 1; j >= 0; j--)
{
if (listCells[j].StartX == currentCell.StartX)
{
comparedIndex = j;
break;
}
}

if (comparedIndex >= 0)
{
if (listCells[comparedIndex].RowSpan > (currentCell.StartY - listCells[comparedIndex].StartY))
{
currentCell.StartX += listCells[comparedIndex].ColSpan;

bActedPush = true;

for (int k = i + 1; k < listCells.Count; k++)
{
if (listCells[k].StartY == currentCell.StartY)
{
listCells[k].StartX += listCells[comparedIndex].ColSpan;
}
}
}
else
{
bActedPush = false;
}
}
else
{
bActedPush = false;
}
}
while (bActedPush);
}
}
}
}
//Utility.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;

namespace LEBLL.ExcelOutput
{
public class Utility
{
/// <summary>
/// 在指定目录以指定文件名为基础,取得系列文件名。
/// 如果已存在指定文件,则生成: path\fileName_(当前数字+1).后缀名。
/// </summary>
/// <param name="path">指定目录</param>
/// <param name="fileName">指定文件名</param>
/// <returns>生成: path\fileName_(当前数字+1).后缀名</returns>
public static string GetUniqueFileName(string path, string fileName)
{
string file = fileName;
string ext = null;
int n = 1;
int lastDotIndex = 0;
lastDotIndex = fileName.LastIndexOf(".");
if (lastDotIndex == -1) {
ext = "";
} else {
ext = file.Substring(lastDotIndex);
file = file.Substring(0, lastDotIndex);
}
string fileOrg = file;
while (System.IO.File.Exists(path + "\\" + file + ext)) {
file = fileOrg + "_" + n;
n = n + 1;
}
return file + ext;
}

/// <summary>
/// 下载文件
/// </summary>
/// <param name="path"></param>
/// <param name="fileName"></param>
/// <param name="fileContentType"></param>
public static void DownLoadFile(string path, string fileName, string fileContentType)
{
string absolutePath = System.Web.HttpContext.Current.Server.MapPath(path);
FileInfo fi = new FileInfo(absolutePath + "\\" + fileName);
HttpResponse contextResponse = HttpContext.Current.Response;
contextResponse.Clear();
contextResponse.Buffer = true;
contextResponse.Charset = "UTF-8";
contextResponse.AppendHeader("Content-Disposition", String.Format("attachment;filename={0}", fileName)); //定义输出文件和文件名
contextResponse.AppendHeader("Content-Length", fi.Length.ToString());
contextResponse.ContentEncoding = Encoding.UTF8;
contextResponse.ContentType = fileContentType;

contextResponse.WriteFile(fi.FullName);
contextResponse.Flush();
contextResponse.End();
}
}
}
//ExcelTableInfo.cs
using System;
using System.Collections.Generic;
using System.Text;
using HtmlAgilityPack;

namespace LEBLL.ExcelOutput
{
public class ExcelTableInfo
{
public string TableName = string.Empty;
public int SheetIndex = 1;
public int StartX = 1;
public int StartY = 1;
public HtmlNode HtmlNodeOfTable = null;
}
}

// ExcelWriter.cs
using System;
using System.Collections.Generic;
using System.Text;
using HtmlAgilityPack;
using Microsoft.Office.Interop.Excel;
using System.Reflection;
using System.Drawing;

namespace LEBLL.ExcelOutput
{
public class ExcelWriter
{
private Application _excelApp = null;
private Workbook _excelWorkbook = null;
private object _missingV = Missing.Value;

public ExcelWriter(int sheetCount)
{
this._excelApp = new Application();
this._excelApp.SheetsInNewWorkbook = sheetCount;
this._excelWorkbook = this._excelApp.Workbooks.Add(this._missingV);
}

public void Write(string tableName,int pnAtWhickSheet, List<ExcelCellInfo> listCells)
{
Worksheet currentSheet = this._excelWorkbook.Sheets[pnAtWhickSheet] as Worksheet;

foreach (ExcelCellInfo ec in listCells)
{
currentSheet.Cells[ec.StartY, ec.StartX] = ec.Content;
currentSheet.Range[currentSheet.Cells[ec.StartY, ec.StartX], currentSheet.Cells[ec.StartY + ec.RowSpan - 1, ec.StartX + ec.ColSpan - 1]].Merge(this._missingV);
}

//表区域边框颜色
Range rangeTable = currentSheet.Range[currentSheet.Cells[listCells[0].StartY, listCells[0].StartX], currentSheet.Cells[listCells[listCells.Count - 1].StartY + listCells[listCells.Count - 1].RowSpan - 1, listCells[listCells.Count - 1].StartX + listCells[listCells.Count - 1].ColSpan - 1]];
rangeTable.Borders.Color = ColorTranslator.ToOle(Color.Black);

//表名称
currentSheet.Cells[listCells[0].StartY - 1, listCells[0].StartX] = tableName;
Range rangeTableTitle = currentSheet.Range[currentSheet.Cells[listCells[0].StartY - 1, listCells[0].StartX], currentSheet.Cells[listCells[0].StartY - 1, listCells[listCells.Count - 1].StartX + listCells[listCells.Count - 1].ColSpan - 1]];
rangeTableTitle.Merge(this._missingV);
rangeTableTitle.Font.Bold = true;
rangeTableTitle.HorizontalAlignment = XlVAlign.xlVAlignCenter;
}

/// <summary>
/// 保存Excel到指定目录下的指定文件中
/// </summary>
/// <param name="filePhysicalPath">指定目录</param>
/// <param name="excelFileName">Excel文件名</param>
public void Save(string filePhysicalPath, string excelFileName)
{
try
{
this._excelWorkbook.RefreshAll();
this._excelWorkbook.SaveAs(filePhysicalPath + "\\" + excelFileName, this._missingV, this._missingV, this._missingV, this._missingV, this._missingV, XlSaveAsAccessMode.xlNoChange, this._missingV, this._missingV, this._missingV, this._missingV, this._missingV);
}
catch (Exception ex)
{
}
finally
{
this._excelWorkbook.Close(false, this._missingV, this._missingV);
this._excelApp.Quit();
this._excelApp = null;
GC.Collect();
}
}
}
}

//调用时:
private void BuildTable()
{
SetDefaultStartEndTime();
TableExporter tableExporter = new TableExporter();
tableExporter.TableID = tableID;
string htmlTable = tableExporter.BuildTable(this.OrderNo, this.StartTime, this.EndTime);
PanelTable.Html = htmlTable;
TextField_TableHtml.Text = Server.HtmlEncode(htmlTable);

string resultTimeCost = string.Format("{0},总耗时:{1}。", "产生数据", tableExporter.TimeCost);
Label_TimeCost.Text = resultTimeCost;
}

protected void ExportExcel(object sender, EventArgs e)
{
string directory = "~/ExcelFile";
// 表格的HTML代码
string tableHTML = Server.HtmlDecode(TextField_TableHtml.Text);
ExcelGenerator excelGenerator = new ExcelGenerator(tableHTML);
excelGenerator.TableID = tableID;
string excelName = excelGenerator.Save(directory);

if (excelName != null)
{
Utility.DownLoadFile(directory, excelName, "application/ms-excel");
}
}

(写作中,未完待续)

标签:string,Excel,System,listCells,HTML,表头,._,using,public
From: https://blog.51cto.com/JohnsonJu/6089172

相关文章

  • html5和css3基础学习笔记
    网页简介一个页面包括结构、表现、行为三个部分。结构:HTML用于描述页面的结构。表现:CSS用于控制页面中元素的样式。行为:JavaScript用于响应用户操作。......
  • 多文件夹下Excel指定列的提取合并
    一、前言大家好,我是崔艳飞,工作中经常遇到,从多个文件夹下的Excel中,提取指定列,再合并成新的Excel。几个文件夹还能应付,但要是有成百上千个文件夹,你就要哭了,本文针对此问题,实......
  • 通过html页面方式访问www.iximo.com的方式(原创)
    因为通过它的开发openapi问题太多,限制也很多,所以今天准备改写原来的方式,但调试的过程中经常出一些问题,后来通过firefox的firebug的方式找到一些原因,所以大家在开发页面过程......
  • Excel CountIF 统计个数
    Tips:统计数据源中值的个数。函数:countif(数据源,条件表达式)数据源:可以是单列或单行,也可以是二维表条件表达式:运算符(>,>=,=,<>等),连接符(&),值(或单元格)或其他函数示例:COUNTIF......
  • 通过EXCEL/WPS文件,拼接SQL,刷数据库数据
    WPS如何把日期变成文本格式?【快捷选择同一列多条记录】同一列,鼠标左键标记A,SHIFT+鼠标左键标记B,等于选择A-B的之间的数据【向下填充】在第一行输入数据,选择同一列A-B......
  • #甘特图# DHTMLXGantt 组件笔记
    配置配置缩放单位gantt.config.scale,示例gantt.config.scale=[{unit:"day",step:1,format:"%d%M"}]需要注意的是,当显示比较小的刻度如天、小时甚至时分钟......
  • JAVA读取Excel文件
    工具类 /***同步无模型读取(默认读取sheet0,从第2行开始读)**@paramfilePath文件路径*@returnList<Map<Integer,String>>*/......
  • java 读 excel 表格(xlsx) 用到的 poi-5.2.3 相关的 jar
    今天第一次用java读取xlsx表格中的数据,到网上下载了一个poi5.2.3(发布日期:2022-9-16),这是目前的最新版本。下载后,解压缩。看了一下文件夹中有很多的jar,目前只需要......
  • html测试
    <!DOCTYPEhtml><html><head>   <title>2.26</title>   <metacharset="utf-8">   <metaname="viewport"content="width=device-width,initial-scale......
  • HTML 中 script 标签的属性和加载顺序
    script标签默认是阻塞加载的,也就是先下载src内容,然后执行src内容,然后再往后读文档head中的script按顺序加载执行,然后再加载body的元素。把script移动到文档最后......