public class OpenXmlHelper
{
#region 导入
/// <summary>
/// 按照给定的地址读取Excel转换成DataTable
/// </summary>
/// <param name="path">路径</param>
/// <param name="page">页码</param>
/// <param name="pagesize">页行数</param>
/// <param name="sheetName">Excel的Sheet名;默认第一个Sheet</param>
/// <param name="index">列头行;默认第一列</param>
/// <returns></returns>
/// OpenXml只支持Excel2007版后的.xlsx
public static DataTable Read(string path, int page = 0, int pagesize = 0, string sheetName = null, int index = 1)
{
try
{
DataTable dt = new DataTable();
if (!path.ToLower().Trim().EndsWith(".xlsx"))
{
throw new Exception("OpenXml组件只支持Office Excel2007版后的.xlsx格式文件");
}
using (SpreadsheetDocument document = SpreadsheetDocument.Open(path, false))
{
//打开Stream
IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>();
if (!string.IsNullOrEmpty(sheetName))
{
sheets = sheets.Where(s => s.Name.ToString().ToLower() == sheetName.ToLower());
if (sheets.Count() == 0)
{
throw new Exception("没有找到该Sheet");
}
}
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);
//获取Excel中共享数据
SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//获得Excel中得数据行
foreach (Row row in rows)
{
if (row.RowIndex == index)//Excel的列名列
{
GetDataColumn(row, stringTable, ref dt);
break;
}
}
if (page != 0 && pagesize != 0)
{
rows = rows.Skip((pagesize * (page-1))+1).Take(pagesize);
foreach (Row row in rows)
{
if (row.RowIndex != index)
{
GetDataRow(row, stringTable, ref dt, document.WorkbookPart);//Excel中行数大于列头的都作为数据列处理
}
}
}
else
{
foreach (Row row in rows)
{
if (row.RowIndex != index) {
GetDataRow(row, stringTable, ref dt, document.WorkbookPart);//Excel中行数大于列头的都作为数据列处理
}
}
}
return dt;
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Excel数据列总行数(不包括列头)
/// </summary>
/// <param name="path"></param>
/// <param name="sheetName"></param>
/// <param name="index"></param>
/// <returns></returns>
public static int GetExcelCount(string path, string sheetName = null, int index = 1)
{
try
{
DataTable dt = new DataTable();
if (!path.ToLower().Trim().EndsWith(".xlsx"))
{
throw new Exception("OpenXml组件只支持Office Excel2007版后的.xlsx格式文件");
}
using (SpreadsheetDocument document = SpreadsheetDocument.Open(path, false))
{
//打开Stream
IEnumerable<Sheet> sheets = document.WorkbookPart.Workbook.Descendants<Sheet>();
if (!string.IsNullOrEmpty(sheetName))
{
sheets = sheets.Where(s => s.Name.ToString().ToLower() == sheetName.ToLower());
if (sheets.Count() == 0)
{
throw new Exception("没有找到该Sheet");
}
}
WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id);
//获取Excel中共享数据
SharedStringTable stringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
IEnumerable<Row> rows = worksheetPart.Worksheet.Descendants<Row>();//获得Excel中得数据行
return rows.Count() - 1;
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 获取Excel原始列下标
/// </summary>
/// <param name="str">原始列名</param>
/// <returns></returns>
private static int GetIndexNumber(string value)
{
if (string.IsNullOrEmpty(value))
{
return -1;
}
char[] chars = value.ToLower().ToCharArray();
int index = 0;
for (int i = 0; i < chars.Length; i++)
{
index += ((int)chars[i] - (int)'a' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
}
return index - 1;
}
/// <summary>
/// 构建DataTable的列
/// </summary>
/// <param name="row">OpenXML定义的Row对象</param>
/// <param name="stringTablePart"></param>
/// <param name="dt">须要返回的DataTable对象</param>
/// <returns></returns>
private static void GetDataColumn(Row row, SharedStringTable stringTable, ref DataTable dt)
{
DataColumn col = new DataColumn();
Dictionary<string, int> columnCount = new Dictionary<string, int>();
foreach (Cell cell in row)
{
string cellVal = GetValue(cell, stringTable);
col = new DataColumn(cellVal);
if (IsContainsColumn(dt, col.ColumnName))
{
if (!columnCount.ContainsKey(col.ColumnName))
columnCount.Add(col.ColumnName, 0);
col.ColumnName = col.ColumnName + (columnCount[col.ColumnName]++);
}
dt.Columns.Add(col);
}
}
/// <summary>
/// 构建DataTable的每一行数据,并返回该Datatable
/// </summary>
/// <param name="row">OpenXML的行</param>
/// <param name="stringTablePart"></param>
/// <param name="dt">DataTable</param>
private static void GetDataRow(Row row, SharedStringTable stringTable, ref DataTable dt, WorkbookPart workbookPart)
{
//读取数据
DataRow dr = dt.NewRow();
int number = 0;
foreach (Cell cell in row)
{
//获取Excel列头
var column = Regex.Replace(cell.CellReference.Value, "[0-9]", "");
//列头转换成下标
var index = GetIndexNumber(column);
if (index < 0)
{
continue;
}
string cellVal = GetValue(cell, stringTable);
if (!string.IsNullOrEmpty(cellVal))
{
if (cell.DataType != null && (cell.DataType.Value == CellValues.SharedString || cell.DataType.Value == CellValues.String || cell.DataType.Value == CellValues.Number))
{
if (index < dt.Columns.Count)
{
switch (cell.DataType.Value)
{
case CellValues.Boolean:
dr[index] = Convert.ToBoolean(GetValue(cell, stringTable));
break;
case CellValues.Date:
dr[index] = Convert.ToDateTime(GetValue(cell, stringTable));
break;
default:
dr[index] = Convert.ToString(GetValue(cell, stringTable));
break;
}
}
}
else
{
//日期格式
if (workbookPart.WorkbookStylesPart!=null/*cell.StyleIndex != null*/)
{
var styleSheet = workbookPart.WorkbookStylesPart.Stylesheet;
if (styleSheet!= null) {
CellFormat cellFormat = (CellFormat)styleSheet.CellFormats.ChildElements[(int)cell.StyleIndex.Value];
int formatId = (int)cellFormat.NumberFormatId.Value;
if (formatId == 177)
{
dr[index] = DateTime.FromOADate(double.Parse(GetValue(cell, stringTable)));
}
//双精度浮点格式
else
{
dr[index] = double.Parse(GetValue(cell, stringTable));
}
}
}
else
{
dr[index] = GetValue(cell, stringTable);
}
}
}
else
{
dr[index] = cellVal;
}
if (!string.IsNullOrEmpty(cellVal))
{
number++;
}
}
if (number != 0)
{
dt.Rows.Add(dr);
}
}
/// <summary>
/// 获取单位格的值
/// </summary>
/// <param name="cell"></param>
/// <param name="stringTablePart"></param>
/// <returns></returns>
private static string GetValue(Cell cell, SharedStringTable stringTable)
{
//因为Excel的数据存储在SharedStringTable中,须要获取数据在SharedStringTable 中的索引
string value = string.Empty;
try
{
if (cell.ChildElements.Count == 0)
return value;
value = double.Parse(cell.CellValue.InnerText).ToString();
if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
{
value = stringTable.ChildElements[Int32.Parse(value)].InnerText;
}
}
catch (Exception)
{
value = string.Empty;
}
return value;
}
/// <summary>
/// 判断网格是否存在列
/// </summary>
/// <param name="dt">网格</param>
/// <param name="columnName">列名</param>
/// <returns></returns>
private static bool IsContainsColumn(DataTable dt, string columnName)
{
if (dt == null || columnName == null)
{
return false;
}
return dt.Columns.Contains(columnName);
}
#endregion
#region 导出
/// <summary>
/// 获取Excel原始Colum名称
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
static string GetLetter(int index)
{
if (index < 0)
{
throw new Exception($"参数{nameof(index)}异常");
}
List<string> chars = new List<string>();
do
{
if (chars.Count > 0) index--;
chars.Insert(0, ((char)(index % 26 + (int)'A')).ToString());
index = (int)((index - index % 26) / 26);
} while (index > 0);
return String.Join(string.Empty, chars.ToArray());
}
/// <summary>
/// 添加WorkSheet
/// </summary>
private static WorksheetPart InsertWorksheet(WorkbookPart workbookPart, string sheetName)
{
//创建新的WorksheetPart
WorksheetPart newWorksheetPart = workbookPart.AddNewPart<WorksheetPart>();
newWorksheetPart.Worksheet = new Worksheet(new SheetData());
newWorksheetPart.Worksheet.Save();
//在末尾追加一个Sheets
Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
string relationshipId = workbookPart.GetIdOfPart(newWorksheetPart);
Sheet sheet = new Sheet() { Id = relationshipId, SheetId = 1, Name = sheetName };
//添加Sheet
sheets.Append(sheet);
workbookPart.Workbook.Save();
return newWorksheetPart;
}
/// <summary>
/// DataTable导出Excel到MemoryStream;
///Return File(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "test.xlsx");
///MVC模式下返回文件流结果,参数一为流,参数二为文件类型,参数三为文件名
/// </summary>
/// <param name="dtSource">数据源</param>
/// <param name="sheetName">Sheet名称</param>
/// <returns></returns>
public static MemoryStream ToExcelIntoMemoryStream(DataTable dtSource, string sheetName = "Sheet0")
{
try
{
var memoryStream = new MemoryStream();
using (var document = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))
{
var workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
//创建新的SharedStringTablePart
SharedStringTablePart shareStringPart = document.WorkbookPart.AddNewPart<SharedStringTablePart>();
// 添加一个WorkSheet
WorksheetPart worksheetPart = InsertWorksheet(workbookPart, sheetName);
// 添加SharedStringTable
shareStringPart.SharedStringTable = new SharedStringTable();
int rowIndex = 1;
int cellIndex = 0;
Worksheet worksheet = worksheetPart.Worksheet;
SheetData sheetData = worksheet.GetFirstChild<SheetData>();
//Excel表头列
SetSheetDataHeadRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
//Excel数据列
SetSheetDataRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
shareStringPart.SharedStringTable.Save();
worksheet.Save();
worksheetPart.Worksheet.Save();
}
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// DataTable固定路径导出Excel,单个Sheet生成
/// 指定路径
/// </summary>
/// <param name="excelFilePath">存储路径</param>
/// <param name="table">数据</param>
/// <param name="sheetName">Sheet名称</param>
public static void ToExcelFixUrl(string excelFilePath, DataTable dtSource, string sheetName = "Sheet0")
{
try
{
using (var document = SpreadsheetDocument.Create(excelFilePath, SpreadsheetDocumentType.Workbook))
{
var workbookPart = document.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
//创建新的SharedStringTablePart
SharedStringTablePart shareStringPart = document.WorkbookPart.AddNewPart<SharedStringTablePart>();
// 添加WorkSheet
WorksheetPart worksheetPart = InsertWorksheet(workbookPart, sheetName);
// 添加SharedStringTable
shareStringPart.SharedStringTable = new SharedStringTable();
int rowIndex = 1;
int cellIndex = 0;
Worksheet worksheet = worksheetPart.Worksheet;
SheetData sheetData = worksheet.GetFirstChild<SheetData>();
//Excel表头列
SetSheetDataHeadRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
//Excel数据列
SetSheetDataRow(dtSource, ref shareStringPart, ref sheetData, ref rowIndex, ref cellIndex);
shareStringPart.SharedStringTable.Save();
worksheet.Save();
worksheetPart.Worksheet.Save();
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 将DataTable的ColumnsName转换为Excel表头Row
/// </summary>
/// <param name="dtSource">数据</param>
/// <param name="shareStringPart"></param>
/// <param name="sheetData"></param>
/// <param name="rowIndex">行下标</param>
/// <param name="cellIndex">单元格下标/param>
private static void SetSheetDataHeadRow(DataTable dtSource, ref SharedStringTablePart shareStringPart, ref SheetData sheetData, ref int rowIndex, ref int cellIndex)
{
{
Row row = new Row() { RowIndex = Convert.ToUInt32(rowIndex) };
sheetData.Append(row);
for (int c = 0; c < dtSource.Columns.Count; c++)
{
string cellReference = GetLetter(c) + rowIndex;
//SharedStringTable里,取数据也是根据SharedStringTable来取
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(Convert.ToString(dtSource.Columns[c]))));
Cell refCell = null;
foreach (Cell cell in row.Elements<Cell>())
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
Cell newCell = new Cell() { CellReference = cellReference };
row.InsertBefore(newCell, refCell);
newCell.CellValue = new CellValue(cellIndex++.ToString());
newCell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
if (c == dtSource.Columns.Count - 1)
{
rowIndex++;
}
}
}
}
/// <summary>
/// 将DataTable的ColumnsData转换为数据Row
/// </summary>
/// <param name="dtSource">数据</param>
/// <param name="shareStringPart"></param>
/// <param name="sheetData"></param>
/// <param name="rowIndex">行下标</param>
/// <param name="cellIndex">单元格下标/param>
private static void SetSheetDataRow(DataTable dtSource, ref SharedStringTablePart shareStringPart, ref SheetData sheetData, ref int rowIndex, ref int cellIndex)
{
{
//Excel的数据列生成
for (int r = 0; r < dtSource.Rows.Count; r++)
{
Row dataRow = new Row() { RowIndex = Convert.ToUInt32(rowIndex) };
sheetData.Append(dataRow);
for (int c = 0; c < dtSource.Columns.Count; c++)
{
string cellReference = GetLetter(c) + rowIndex;
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(Convert.ToString(dtSource.Rows[r][c]))));
Cell refCell = null;
foreach (Cell cell in dataRow.Elements<Cell>())
{
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
{
refCell = cell;
break;
}
}
Cell newCell = new Cell() { CellReference = cellReference };
dataRow.InsertBefore(newCell, refCell);
newCell.CellValue = new CellValue(cellIndex++.ToString());
newCell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
}
rowIndex++;
}
}
}
#endregion
/// <summary>
/// list模型转换为DataTable
/// </summary>
/// <typeparam name="T">模型</typeparam>
/// <param name="list">数据集合</param>
/// <returns></returns>
public static DataTable ToDataTable<T>(List<T> list)
{
if (list == null || list.Count <= 0)
{
throw new Exception("参数异常");
}
DataTable dt = new DataTable();
if (list.Count <= 0 || list == null)
{
return dt;
}
//添加列名
{
var type = list.First().GetType();
PropertyInfo[] PropertyList = type.GetProperties();
foreach (PropertyInfo item in PropertyList)
{
DataColumn dc = new DataColumn();
string name = item.Name;
dc.ColumnName = name;//反射类字段添加列名
dt.Columns.Add(dc);
}
}
//添加数据列
foreach (var model in list)
{
var type = model.GetType();
PropertyInfo[] PropertyList = type.GetProperties();
DataRow dr = dt.NewRow();
foreach (PropertyInfo item in PropertyList)
{
string name = item.Name;
string value = Convert.ToString(item.GetValue(model, null));
dr[name] = value;
}
dt.Rows.Add(dr);
}
return dt;
}
}