在網上搜索到的一般是這種通用的方法,這個方法速度太慢了,代碼如下
private void ExportExcel(string fileName, DataGridView myDGV)
{
string saveFileName = "";
SaveFileDialog saveDialog = new SaveFileDialog();
saveDialog.DefaultExt = "xls";
saveDialog.Filter = "Excel文件|*.xls";
saveDialog.FileName = fileName;
saveDialog.ShowDialog();
saveFileName = saveDialog.FileName;
if (saveFileName.IndexOf(":") < 0) return; //被點了取消
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
MessageBox.Show("無法創建Excel對象,可能您的機子未安裝Excel");
return;
}
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];//取得sheet1
//寫入標題
for (int i = 0; i < myDGV.ColumnCount; i++)
{
worksheet.Cells[1, i + 1] = myDGV.Columns[i].HeaderText;
}
//寫入數值
for (int r = 0; r < myDGV.Rows.Count; r++)
{
for (int i = 0; i < myDGV.ColumnCount; i++)
{
worksheet.Cells[r + 2, i + 1] = myDGV.Rows[r].Cells[i].Value;
}
System.Windows.Forms.Application.DoEvents();
}
worksheet.Columns.EntireColumn.AutoFit();//列寬自適應
if (saveFileName != "")
{
try
{
workbook.Saved = true;
workbook.SaveCopyAs(saveFileName);
}
catch (Exception ex)
{
MessageBox.Show("導出文件時出錯,文件可能正被打開!\n" + ex.Message);
}
}
xlApp.Quit();
GC.Collect();//強行銷毀
MessageBox.Show("文件: " + fileName + ".xls 保存成功", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
最近研究了半天,使用NOPI的方法真是的太快了,秒存的感覺
主要代碼如下:
/// <summary>
/// 由DataGridView導出Excel
/// </summary>
/// <param name="grid"></param>
/// <param name="sheetName"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ExportToExcel(DataGridView grid, string sheetName = "result", string filePath = null)
{
if (grid.Rows.Count <= 0) return null;
if (string.IsNullOrEmpty(filePath))
{
filePath = GetSaveFilePath();
}
if (string.IsNullOrEmpty(filePath)) return null;
bool isCompatible = GetIsCompatible(filePath);
IWorkbook workbook = CreateWorkbook(isCompatible);
ICellStyle cellStyle = GetCellStyle(workbook);
ISheet sheet = workbook.CreateSheet(sheetName);
IRow headerRow = sheet.CreateRow(0);
for (int i = 0; i < grid.Columns.Count; i++)
{
ICell cell = headerRow.CreateCell(i);
cell.SetCellValue(grid.Columns[i].Name);
cell.CellStyle = cellStyle;
}
int rowIndex = 1;
foreach (DataGridViewRow row in grid.Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);
for (int n = 0; n < grid.Columns.Count; n++)
{
dataRow.CreateCell(n).SetCellValue((row.Cells[n].Value ?? "").ToString());
}
rowIndex++;
}
AutoColumnWidth(sheet, headerRow.LastCellNum - 1);
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
workbook.Write(fs);
fs.Dispose();
sheet = null;
headerRow = null;
workbook = null;
MessageBox.Show("文件: " + filePath + ".xls 保存成功", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return filePath;
}
下面是我整理的通用EXCEL的幫助類,非常的實用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Windows.Forms;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections;
namespace _009_TPS.MyClass.Class
{
public static class ExcelHelper
{
#region 私有方法
/// <summary>
/// 獲取要保存的文件名稱(含完整路徑)
/// </summary>
/// <returns></returns>
public static string GetSaveFilePath()
{
SaveFileDialog saveFileDig = new SaveFileDialog();
saveFileDig.Filter = "Excel Office97-2003(*.xls)|*.xls|Excel Office2007及以上(*.xlsx)|*.xlsx";
saveFileDig.FilterIndex = 0;
saveFileDig.OverwritePrompt = true;
string dir = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);//獲取當前系統桌面路徑
saveFileDig.InitialDirectory = dir;
string filePath = null;
if (saveFileDig.ShowDialog() == DialogResult.OK)
{
filePath = saveFileDig.FileName;
}
return filePath;
}
/// <summary>
/// 打開文件對話框,並返回文件的路徑
/// </summary>
/// <returns></returns>
public static string GetOpenFilePath()
{
//創建對話框的對象
OpenFileDialog ofd = new OpenFileDialog();
//設置對話框的標題
ofd.Title = "請選擇要打開的文件";
//設置對話框可以多選
ofd.Multiselect = true;
//設置對話框的初始目錄
ofd.InitialDirectory = @"C:\Users\Administrator\Desktop";
//設置對話框打開文件的類型
ofd.Filter = "Excel文件(.xls)|*.xls|Excel文件(.xlsx)|*.xlsx";
//展示對話框
ofd.ShowDialog();
//獲得在打開對話框中選中的文件的路徑
string filePath = ofd.FileName;//全路徑
return filePath;
}
/// <summary>
/// 判斷Excel文件是否為兼容模式(.xls)
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static bool GetIsCompatible(string filePath)
{
return filePath.EndsWith(".xls", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// 創建工作薄
/// </summary>
/// <param name="isCompatible">true就是.xls</param>
/// <returns></returns>
public static IWorkbook CreateWorkbook(bool isCompatible)
{
if (isCompatible)
{
return new HSSFWorkbook();
}
else
{
return new XSSFWorkbook();
}
}
/// <summary>
/// 創建工作薄(依據文件流)
/// </summary>
/// <param name="isCompatible"></param>
/// <param name="stream"></param>
/// <returns></returns>
public static IWorkbook CreateWorkbook(bool isCompatible, Stream stream)
{
if (isCompatible)
{
return new HSSFWorkbook(stream);
}
else
{
return new XSSFWorkbook(stream);
}
}
#region 傳入一個文件路徑,返回一個IWorkbook對象
/// <summary>
/// 傳入一個文件路徑,返回一個IWorkbook對象
/// </summary>
/// <param name="filepath"></param>
/// <returns></returns>
public static IWorkbook CreateWorkbook(string filepath)
{
IWorkbook workbook = null;
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fs = File.Open(filepath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
//把xls文件讀入workbook變量里,之后就可以關閉了
workbook = ExcelHelper.CreateWorkbook(isCompatible, fs);
fs.Close();
}
return workbook;
}
#endregion
#region 打開一個excel文件,設置單元格的值,再保存文件
/// <summary>
/// 打開一個excel文件,設置單元格的值,再保存文件
/// </summary>
/// <param name="ExcelPath"></param>
/// <param name="sheetname"></param>
/// <param name="column"></param>
/// <param name="row"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool SetCellValue(String ExcelPath, String sheetname, int column, int row, String value)
{
bool returnb = false;
try
{
IWorkbook wk = null;
bool isCompatible = ExcelHelper.GetIsCompatible(ExcelPath);
using (FileStream fs = File.Open(ExcelPath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
//把xls文件讀入workbook變量里,之后就可以關閉了
wk = ExcelHelper.CreateWorkbook(isCompatible, fs);
fs.Close();
}
//把xls文件讀入workbook變量里,之后就可以關閉了
//ISheet sheet = wk.GetSheet(sheetname);
ISheet sheet = wk.GetSheetAt(0);
ICell cell = sheet.GetRow(row).GetCell(column);
cell.SetCellValue(value);
using (FileStream fileStream = File.Open(ExcelPath,
FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
wk.Write(fileStream);
fileStream.Close();
}
returnb = true;
}
catch (Exception)
{
returnb = false;
throw;
}
return returnb;
}
#endregion
#region 打開一個文件,讀取excel文件某個單元格的值(多少行,多少列)
/// <summary>
/// 打開一個文件,讀取excel文件某個單元格的值(多少行,多少列)
/// </summary>
/// <param name="ExcelPath"></param>
/// <param name="sheetname"></param>
/// <param name="column"></param>
/// <param name="row"></param>
/// <returns></returns>
public static String GetCellValue(string ExcelPath, String sheetname, int column, int row)
{
String returnStr = null;
try
{
IWorkbook wk = null;
bool isCompatible = ExcelHelper.GetIsCompatible(ExcelPath);
using (FileStream fs = File.Open(ExcelPath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
//把xls文件讀入workbook變量里,之后就可以關閉了
wk = ExcelHelper.CreateWorkbook(isCompatible, fs);
fs.Close();
}
//把xls文件讀入workbook變量里,之后就可以關閉了
//ISheet sheet = wk.GetSheet(sheetname);
ISheet sheet = wk.GetSheetAt(0);
ICell cell = sheet.GetRow(row).GetCell(column);
returnStr = cell.ToString();
}
catch (Exception)
{
returnStr = "Exception";
throw;
}
return returnStr;
}
#endregion
#region 打開一個文件,刪除多少以后的數據(是刪除,不是清空數據)
/// <summary>
/// 打開一個文件,刪除多少以后的數據(是刪除,不是清空數據)
/// </summary>
/// <param name="fileMatchPath"></param>
/// <param name="rowIndex">從多少行后開始刪除</param>
public static void DelRowsData(string fileMatchPath, int startRowIndex)
{
IWorkbook wk = null;
bool isCompatible = ExcelHelper.GetIsCompatible(fileMatchPath);
using (FileStream fs = File.Open(fileMatchPath, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
//把xls文件讀入workbook變量里,之后就可以關閉了
wk = ExcelHelper.CreateWorkbook(isCompatible, fs);
fs.Close();
}
ISheet sheet = wk.GetSheetAt(0);
for (int i = startRowIndex; i <= sheet.LastRowNum; i++)
{
if (sheet.GetRow(i) == null)
{
i++;
continue;
}
sheet.RemoveRow(sheet.GetRow(i));
}
//轉為字節數組
MemoryStream stream = new MemoryStream();
wk.Write(stream);
var buf = stream.ToArray();
//保存為Excel文件 這種方式能保存.xls和.xlsx文件
using (FileStream fs = new FileStream(fileMatchPath, FileMode.Create, FileAccess.Write))
{
fs.Write(buf, 0, buf.Length);
fs.Flush();
}
}
#endregion
/// <summary>
/// 創建表格頭單元格
/// </summary>
/// <param name="sheet"></param>
/// <returns></returns>
private static ICellStyle GetCellStyle(IWorkbook workbook)
{
ICellStyle style = workbook.CreateCellStyle();
style.FillPattern = FillPattern.SolidForeground;
style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
return style;
}
/// <summary>
/// 遍歷打印二維數組
/// </summary>
/// <param name="array"></param>
public static void PrintTwoArrayTest(object[,] array)
{
Console.WriteLine("============測試打印二維數組==============");
int row = array.GetLength(0);
int column = array.GetLength(1);
for (int r = 0; r < row; r++)
{
for (int c = 0; c < column; c++)
{
if (array[r, c] != null)
{
string value = array[r, c].ToString();
Console.Write($"{value} |");
}
}
Console.WriteLine();
}
}
/// <summary>
/// 傳入2個二維數組,進行條件匹配替換,返回替換后的一個二維數組
/// </summary>
/// <param name="refArray">參考的數組</param>
/// <param name="matchArray">帶替換的數組</param>
/// <param name="refColumn01">參考列1</param>
/// <param name="refColumn02">參考列2</param>
/// <param name="refColTarget01">被復制的值的列1</param>
/// <param name="matchColumn01">帶替換的參考列1</param>
/// <param name="matchColumn02">帶替換的參考列2</param>
/// <param name="matchColTarget01">帶粘貼的值的列1</param>
/// <returns></returns>
public static string[,] GetMatchArray(string[,] refArray, string[,] matchArray, int refColumn01, int refColumn02, int refColTarget01, int matchColumn01, int matchColumn02, int matchColTarget01)
{
Console.WriteLine("============遍歷2個二維數,匹配替換==============");
int row = refArray.GetLength(0);
int column = matchArray.GetLength(1);
int row02 = matchArray.GetLength(0);
int iMatch = 0;
for (int r = 0; r < row; r++)
{
string value01 = refArray[r, refColumn01];//第1列的數據
string value02 = refArray[r, refColumn02];//第2列的數據
if (value01 != null && value02 != null)
{
if (value01.Length > 0 | value02.Length > 0)
{
for (int r02 = 0; r02 < row02; r02++)
{
string match01 = matchArray[r02, matchColumn01];//第1列的數據
string match02 = matchArray[r02, matchColumn02];//第2列的數據
if (value01 == match01 && value02 == match02)
{
matchArray[r02, matchColTarget01] = refArray[r, refColTarget01];
iMatch++;
Console.WriteLine($"匹配了{iMatch}次");
}
}
}
}
}
return matchArray;
}
/// <summary>
/// 傳入2個數組,根據相同條件匹配,吧ref的目標寫入match中
/// </summary>
/// <param name="refArray">參考的數組</param>
/// <param name="matchArray">帶替換的數組</param>
/// <param name="refColumn01"></param>
/// <param name="refColTarget01"></param>
/// <param name="matchColumn01"></param>
/// <param name="matchColTarget01"></param>
/// <returns></returns>
public static string[,] GetMatchArray(string[,] refArray, string[,] matchArray, int refColumn01, int refColTarget01, int matchColumn01, int matchColTarget01)
{
Console.WriteLine("============遍歷2個二維數,匹配替換==============");
int row = refArray.GetLength(0);
int column = matchArray.GetLength(1);
int row02 = matchArray.GetLength(0);
int iMatch = 0;
for (int r = 0; r < row; r++)
{
string value01 = string.Empty;
value01 = refArray[r, refColumn01];//遍歷第一個數組第1列的數據
//value01 = value01.Trim();
if (value01 != null)
{
if (value01.Length > 0)
{
for (int r02 = 0; r02 < row02; r02++)
{
string match01 = string.Empty;
match01 = matchArray[r02, matchColumn01];//遍歷第一個數組第1列的數據
//match01 = match01.Trim();
if (value01 == match01)
{
matchArray[r02, matchColTarget01] = refArray[r, refColTarget01];
iMatch++;
Console.WriteLine($"匹配了{iMatch}次");
}
}
}
}
}
return matchArray;
}
/// <summary>
/// 遍歷一個數組,如果第二列的數值大於等於第一列的數值,替換字符串
/// </summary>
/// <param name="matchArray"></param>
/// <param name="refColumn01"></param>
/// <param name="refColumn02"></param>
/// <param name="sValue"></param>
/// <returns></returns>
public static string[,] GetMatchArray(string[,] matchArray, int refColumn01, int refColumn02, string sValue)
{
Console.WriteLine("============遍歷2個二維數,匹配替換==============");
int row = matchArray.GetLength(0);
int column = matchArray.GetLength(1);
int iMatch = 0;
for (int r = 0; r < row; r++)
{
string value01 = matchArray[r, refColumn01];//第1列的數據
string value02 = matchArray[r, refColumn02];//第2列的數據
try
{
int i01 = Convert.ToInt32(value01);
int i02 = Convert.ToInt32(value02);
if (i01 >= i02)
{
matchArray[r, refColumn02] = sValue + $"(數量:{value02})";
}
}
catch
{
}
}
return matchArray;
}
#region 打開excel文件,獲取某一行的數據
/// <summary>
/// 打開excel文件,獲取某一行的數據
/// </summary>
/// <param name="filepath">文件全路徑</param>
/// <param name="iRow">哪一行的數據</param>
/// <param name="sheet_Number">哪一個sheet表</param>
/// <returns></returns>
public static ArrayList GetRowData(string filepath, int sheet_Number, int iRow)
{
ArrayList arrayList = new ArrayList();
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1);
IRow currentRow = sheet.GetRow(iRow - 1);
for (int c = 0; c < currentRow.LastCellNum; c++)
{
//獲取每個單元格(r行c列的數據)
ICell cell = currentRow.GetCell(c);
//獲取單元格的內容
string value = string.Empty;
if (cell != null)
{
value = cell.ToString(); //如果單元格為空,這里會報錯的
arrayList.Add(value);
}
}
return arrayList;
}
}
#endregion
/// <summary>
/// 打開excel文件,根據某一行的數據,根據字符串內容,返回這個字符串所在的列的索引
/// </summary>
/// <param name="filepath"></param>
/// <param name="iRow"></param>
/// <param name="sheet_Number">從1開始的</param>
/// <param name="s1">注意字符串的順序</param>
/// <param name="s2"></param>
/// <param name="s3"></param>
/// <returns></returnss
public static ArrayList GetDataIndexs(string filepath, int sheet_Number, int iRow, string s1, string s2, string s3)
{
ArrayList arrayList = new ArrayList();
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1);
IRow currentRow = sheet.GetRow(iRow - 1);
for (int c = 0; c < currentRow.LastCellNum; c++)
{
//獲取每個單元格(r行c列的數據)
ICell cell = currentRow.GetCell(c);
//獲取單元格的內容
string value = string.Empty;
if (cell != null)
{
value = cell.ToString(); //如果單元格為空,這里會報錯的
if (value == s1 | value == s2 || value == s3)
{
arrayList.Add(c);
}
}
}
Console.WriteLine("==========測試打印索引值============");
foreach (var a in arrayList)
{
Console.WriteLine($"{a} |");
}
return arrayList;
}
}
/// <summary>
/// 打開excel文件,根據某一行的字符串,然后這個字符串所在列的索引
/// </summary>
/// <param name="filepath"></param>
/// <param name="sheet_Number"></param>
/// <param name="iRow"></param>
/// <param name="sValue"></param>
/// <returns></returns>
public static int GetDataIndex(string filepath, int sheet_Number, int iRow, string sValue)
{
int i = 0;
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1);
IRow currentRow = sheet.GetRow(iRow - 1);
for (int c = 0; c < currentRow.LastCellNum; c++)
{
//獲取每個單元格(r行c列的數據)
ICell cell = currentRow.GetCell(c);
//獲取單元格的內容
string value = string.Empty;
if (cell != null)
{
value = cell.ToString(); //如果單元格為空,這里會報錯的
if (value == sValue)
{
i = c;
}
}
}
}
return i;
}
/// <summary>
/// 打開一個文件,把第幾行的數據取出來,返回一個字典 單元格的值:列的索引
/// </summary>
/// <param name="filepath"></param>
/// <param name="sheet_Number">第幾張工作表(從1開始)</param>
/// <param name="iRow">第幾行(從1開始)</param>
/// <returns></returns>
public static Dictionary<string, int> GetDataDictionary(string filepath, int sheet_Number, int iRow)
{
Dictionary<string, int> DataDict = new Dictionary<string, int>();
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1);
IRow currentRow = sheet.GetRow(iRow - 1);
for (int c = 0; c < currentRow.LastCellNum; c++)
{
//獲取每個單元格(r行c列的數據)
ICell cell = currentRow.GetCell(c);
//獲取單元格的內容
string value = string.Empty;
if (cell != null)
{
value = cell.ToString(); //如果單元格為空,這里會報錯的
if (!DataDict.ContainsKey(value))
{
if (value == "*預計交貨日期" | value == "預計交貨日期")
{
value = "*預計交貨日期";
}
DataDict.Add(value, c);
}
else
{
if (filepath.Contains("銷售訂單")) //銷售訂單模板的第二個備注填寫收貨地址
{
if (value == "備注") //如果有兩個備注
{
//DataDict.Add("采購員", c);
DataDict.Add("收貨地址", c);
}
}
}
}
}
//Console.WriteLine("================開始遍歷字典===============");
//foreach (KeyValuePair<string, int> kv in DataDict)//通過KeyValuePair遍歷元素
//{
// Console.WriteLine($"Key:{kv.Key},Value:{kv.Value}");
//}
return DataDict;
}
}
/// <summary>
/// 打開一個文件,根據第幾張表第幾行的中的兩個字符,返回值:一個字典
/// </summary>
/// <param name="filepath"></param>
/// <param name="sheet_Number"></param>
/// <param name="strColumnKey"></param>
/// <param name="strColumnValue"></param>
/// <returns></returns>
public static Dictionary<string, string> GetDataDictionary(string filepath, int sheet_Number, int iRow, string strColumnKey, string strColumnValue)
{
Dictionary<string, int> dic = GetDataDictionary(filepath, 1, iRow);
int iColumnKey = dic[strColumnKey];
int iColumnValue = dic[strColumnValue];
Dictionary<string, string> DataDict = new Dictionary<string, string>();
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1);
for (int i = 0; i <= sheet.LastRowNum; i++)
{
IRow rowdata = sheet.GetRow(i);
ICell cellKey = rowdata.GetCell(iColumnKey);
ICell cellValue = rowdata.GetCell(iColumnValue);
if (cellKey != null && cellValue != null)
{
if (!DataDict.ContainsKey(cellKey.ToString()))
{
string strCellKey = cellKey.ToString();
string strCellValue = cellValue.ToString();
DataDict.Add(strCellKey, strCellValue);
}
}
}
return DataDict;
}
}
#region 根據一個文件,獲取一個Excel文件的最大行數和列數(不成熟不建議用)
/// <summary>
/// 根據一個文件,獲取一個Excel文件的最大行數和列數(不成熟不建議用)
/// </summary>
/// <param name="filepath">excel表格保存的地址,包括"文件名.xls</param>
/// <param name="sheet_number">代表將要讀取的sheet表的索引位置</param>
/// <returns>行數Array[0],列數Array[2]</returns>
public static Array GetRowCountAndColumnCount(string filepath, int sheet_number)
{
int rowMaxCount = 0;
int columnMaxCount = 0;
FileStream readStream = null;
try
{
if (!string.IsNullOrEmpty(filepath) && sheet_number > 0)
{
readStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
bool isCompatible = GetIsCompatible(filepath);
IWorkbook workbook = CreateWorkbook(isCompatible, readStream);
ISheet sheet = workbook.GetSheetAt(sheet_number - 1);
if (sheet != null)
{
rowMaxCount = sheet.LastRowNum + 1; //有效行數(NPOI讀取的有效行數不包括列頭,所以需要加1)
for (int c = 0; c <= sheet.LastRowNum; c++)
{
IRow row = sheet.GetRow(c);
#pragma warning disable CS1525 // 表達式項“=”無效
if (row != null && row.LastCellNum > -1)
#pragma warning restore CS1525 // 表達式項“=”無效
{
columnMaxCount = row.LastCellNum;
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
if (readStream != null)
{
readStream.Close();
}
}
int[] array = new int[2];
array[1] = rowMaxCount;
array[2] = columnMaxCount;
return array;
}
#endregion
/// <summary>
/// Excel轉化為二維數組
/// </summary>
/// <param name="filepath">文件全路徑</param>
/// <param name="arrayRowNnmber">數組的行數</param>
/// <param name="arrayColumnNumber">數組的列數</param>
/// <param name="sheet_Number">要遍歷的sheet索引</param>
/// <returns>返回一個二維素組</returns>
public static string[,] ToTwoArray(string filepath, int arrayRowNnmber, int arrayColumnNumber, int sheet_Number)
{
string[,] array = new string[arrayRowNnmber, arrayColumnNumber];
bool isCompatible = ExcelHelper.GetIsCompatible(filepath);
using (FileStream fsRead = File.OpenRead(filepath))
{
IWorkbook workbook = ExcelHelper.CreateWorkbook(isCompatible, fsRead);
ISheet sheet = workbook.GetSheetAt(sheet_Number - 1); //獲取第一個工作表(sheet)
int rowCount = sheet.LastRowNum;
if (!isCompatible)//如果是xlsx格式的,行數要-2
{
rowCount = rowCount - 2;
}
for (int r = 0; r <= rowCount; r++)
{
IRow currentRow = sheet.GetRow(r); //讀取當前行數據
Console.Write($"第{r}行有{currentRow.LastCellNum}列有數據:--->");
for (int c = 0; c < currentRow.LastCellNum; c++)
{
//獲取每個單元格(r行c列的數據)
ICell cell = currentRow.GetCell(c);
//獲取單元格的內容
string value = string.Empty;
if (cell != null)
{
value = cell.ToString(); //如果單元格為空,這里會報錯的
}
Console.Write($"{value} |");
array[r, c] = value;
}
Console.WriteLine();
}
return array;
}
}
/// <summary>
/// 從工作表中生成DataTable
/// </summary>
/// <param name="sheet"></param>
/// <param name="headerRowIndex"></param>
/// <returns></returns>
private static DataTable GetDataTableFromSheet(ISheet sheet, int headerRowIndex)
{
DataTable table = new DataTable();
IRow headerRow = sheet.GetRow(headerRowIndex);
int cellCount = headerRow.LastCellNum;
for (int i = headerRow.FirstCellNum; i < cellCount; i++)
{
if (headerRow.GetCell(i) == null || headerRow.GetCell(i).StringCellValue.Trim() == "")
{
// 如果遇到第一個空列,則不再繼續向后讀取
cellCount = i + 1;
break;
}
DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
table.Columns.Add(column);
}
for (int i = (headerRowIndex + 1); i <= sheet.LastRowNum; i++)
{
IRow row = sheet.GetRow(i);
if (row != null && !string.IsNullOrEmpty(row.Cells[0].StringCellValue))
{
DataRow dataRow = table.NewRow();
for (int j = row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) != null)
{
dataRow[j] = row.GetCell(j).ToString();
}
}
table.Rows.Add(dataRow);
}
}
return table;
}
#endregion
#region 公共導出方法
/// <summary>
/// 由DataSet導出Excel
/// </summary>
/// <param name="sourceTable">要導出數據的DataTable</param>
/// <returns>Excel工作表</returns>
public static string ExportToExcel(DataSet sourceDs, string filePath = null)
{
if (string.IsNullOrEmpty(filePath))
{
filePath = GetSaveFilePath();
}
if (string.IsNullOrEmpty(filePath)) return null;
bool isCompatible = GetIsCompatible(filePath);
IWorkbook workbook = CreateWorkbook(isCompatible);
ICellStyle cellStyle = GetCellStyle(workbook);
for (int i = 0; i < sourceDs.Tables.Count; i++)
{
DataTable table = sourceDs.Tables[i];
string sheetName = "result" + i.ToString();
ISheet sheet = workbook.CreateSheet(sheetName);
IRow headerRow = sheet.CreateRow(0);
// handling header.
foreach (DataColumn column in table.Columns)
{
ICell cell = headerRow.CreateCell(column.Ordinal);
cell.SetCellValue(column.ColumnName);
cell.CellStyle = cellStyle;
}
// handling value.
int rowIndex = 1;
foreach (DataRow row in table.Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);
foreach (DataColumn column in table.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue((row[column] ?? "").ToString());
}
rowIndex++;
}
}
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
workbook.Write(fs);
fs.Dispose();
workbook = null;
return filePath;
}
/// <summary>
/// 獲取sheet表名
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static string[] GetSheetName(string filePath)
{
int sheetNumber = 0;
var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);
if (filePath.IndexOf(".xlsx") > 0)
{
//2007版本
var xssfworkbook = new XSSFWorkbook(file);
sheetNumber = xssfworkbook.NumberOfSheets;
string[] sheetNames = new string[sheetNumber];
for (int i = 0; i < sheetNumber; i++)
{
sheetNames[i] = xssfworkbook.GetSheetName(i);
}
return sheetNames;
}
else if (filePath.IndexOf(".xls") > 0)
{
//2003版本
var hssfworkbook = new HSSFWorkbook(file);
sheetNumber = hssfworkbook.NumberOfSheets;
string[] sheetNames = new string[sheetNumber];
for (int i = 0; i < sheetNumber; i++)
{
sheetNames[i] = hssfworkbook.GetSheetName(i);
}
return sheetNames;
}
return null;
}
/// <summary>
/// 根據表名獲取表
/// </summary>
/// <param name="filePath"></param>
/// <param name="sheetName"></param>
/// <returns></returns>
public static DataTable ExcelToDataTable(string filePath, string sheetName)
{
string outMsg = "";
var dt = new DataTable();
string fileType = Path.GetExtension(filePath).ToLower();
try
{
ISheet sheet = null;
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
if (fileType == ".xlsx")
{
//2007版
XSSFWorkbook workbook = new XSSFWorkbook(fs);
sheet = workbook.GetSheet(sheetName);
if (sheet != null)
{
dt = GetSheetDataTable(sheet, out outMsg);
}
}
else if (fileType == ".xls")
{
//2003版
HSSFWorkbook workbook = new HSSFWorkbook(fs);
sheet = workbook.GetSheet(sheetName);
if (sheet != null)
{
dt = GetSheetDataTable(sheet, out outMsg);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return dt;
}
private static int sheetCellNumMax = 12;
/// <summary>
/// 獲取sheet表對應的DataTable
/// </summary>
/// <param name="sheet">Excel工作表</param>
/// <param name="strMsg"></param>
/// <returns></returns>
private static DataTable GetSheetDataTable(ISheet sheet, out string strMsg)
{
strMsg = "";
DataTable dt = new DataTable();
string sheetName = sheet.SheetName;
int startIndex = 0;// sheet.FirstRowNum;
int lastIndex = sheet.LastRowNum;
//最大列數
int cellCount = 0;
IRow maxRow = sheet.GetRow(0);
for (int i = startIndex; i <= lastIndex; i++)
{
IRow row = sheet.GetRow(i);
if (row != null && cellCount < row.LastCellNum)
{
cellCount = row.LastCellNum;
maxRow = row;
}
}
//列名設置
try
{
//maxRow.LastCellNum = 12 // L
for (int i = 0; i < sheetCellNumMax; i++)//maxRow.FirstCellNum
{
dt.Columns.Add(Convert.ToChar(((int)'A') + i).ToString());
//DataColumn column = new DataColumn("Column" + (i + 1).ToString());
//dt.Columns.Add(column);
}
}
catch
{
strMsg = "工作表" + sheetName + "中無數據";
return null;
}
//數據填充
for (int i = startIndex; i <= lastIndex; i++)
{
IRow row = sheet.GetRow(i);
DataRow drNew = dt.NewRow();
if (row != null)
{
for (int j = row.FirstCellNum; j < row.LastCellNum; ++j)
{
if (row.GetCell(j) != null)
{
ICell cell = row.GetCell(j);
switch (cell.CellType)
{
case CellType.Blank:
drNew[j] = "";
break;
case CellType.Numeric:
short format = cell.CellStyle.DataFormat;
//對時間格式(2015.12.5、2015/12/5、2015-12-5等)的處理
if (format == 14 || format == 31 || format == 57 || format == 58)
drNew[j] = cell.DateCellValue;
else
drNew[j] = cell.NumericCellValue;
if (cell.CellStyle.DataFormat == 177 || cell.CellStyle.DataFormat == 178 || cell.CellStyle.DataFormat == 188)
drNew[j] = cell.NumericCellValue.ToString("#0.00");
break;
case CellType.String:
drNew[j] = cell.StringCellValue;
break;
case CellType.Formula:
try
{
drNew[j] = cell.NumericCellValue;
if (cell.CellStyle.DataFormat == 177 || cell.CellStyle.DataFormat == 178 || cell.CellStyle.DataFormat == 188)
drNew[j] = cell.NumericCellValue.ToString("#0.00");
}
catch
{
try
{
drNew[j] = cell.StringCellValue;
}
catch { }
}
break;
default:
drNew[j] = cell.StringCellValue;
break;
}
}
}
}
dt.Rows.Add(drNew);
}
return dt;
}
/// <summary>
/// 由DataTable導出Excel
/// </summary>
/// <param name="sourceTable">要導出數據的DataTable</param>
/// <returns>Excel工作表</returns>
public static string ExportToExcel(DataTable sourceTable, string sheetName = "result", string filePath = null)
{
if (sourceTable.Rows.Count <= 0) return null;
if (string.IsNullOrEmpty(filePath))
{
filePath = GetSaveFilePath();
}
if (string.IsNullOrEmpty(filePath)) return null;
bool isCompatible = GetIsCompatible(filePath);
IWorkbook workbook = CreateWorkbook(isCompatible);
ICellStyle cellStyle = GetCellStyle(workbook);
ISheet sheet = workbook.CreateSheet(sheetName);
IRow headerRow = sheet.CreateRow(0);
// handling header.
foreach (DataColumn column in sourceTable.Columns)
{
ICell headerCell = headerRow.CreateCell(column.Ordinal);
headerCell.SetCellValue(column.ColumnName);
headerCell.CellStyle = cellStyle;
}
// handling value.
int rowIndex = 1;
foreach (DataRow row in sourceTable.Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);
foreach (DataColumn column in sourceTable.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue((row[column] ?? "").ToString());
}
rowIndex++;
}
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
workbook.Write(fs);
fs.Dispose();
sheet = null;
headerRow = null;
workbook = null;
return filePath;
}
/// <summary>
/// 由List導出Excel
/// </summary>
/// <typeparam name="T">類型</typeparam>
/// <param name="data">在導出的List</param>
/// <param name="sheetName">sheet名稱</param>
/// <returns></returns>
public static string ExportToExcel<T>(List<T> data, IList<KeyValuePair<string, string>> headerNameList, string sheetName = "result", string filePath = null) where T : class
{
if (data.Count <= 0) return null;
if (string.IsNullOrEmpty(filePath))
{
filePath = GetSaveFilePath();
}
if (string.IsNullOrEmpty(filePath)) return null;
bool isCompatible = GetIsCompatible(filePath);
IWorkbook workbook = CreateWorkbook(isCompatible);
ICellStyle cellStyle = GetCellStyle(workbook);
ISheet sheet = workbook.CreateSheet(sheetName);
IRow headerRow = sheet.CreateRow(0);
for (int i = 0; i < headerNameList.Count; i++)
{
ICell cell = headerRow.CreateCell(i);
cell.SetCellValue(headerNameList[i].Value);
cell.CellStyle = cellStyle;
}
Type t = typeof(T);
int rowIndex = 1;
foreach (T item in data)
{
IRow dataRow = sheet.CreateRow(rowIndex);
for (int n = 0; n < headerNameList.Count; n++)
{
object pValue = t.GetProperty(headerNameList[n].Key).GetValue(item, null);
dataRow.CreateCell(n).SetCellValue((pValue ?? "").ToString());
}
rowIndex++;
}
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
workbook.Write(fs);
fs.Dispose();
sheet = null;
headerRow = null;
workbook = null;
return filePath;
}
/// <summary>
/// 由DataGridView導出Excel
/// </summary>
/// <param name="grid"></param>
/// <param name="sheetName"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static string ExportToExcel(DataGridView grid, string sheetName = "result", string filePath = null)
{
if (grid.Rows.Count <= 0) return null;
if (string.IsNullOrEmpty(filePath))
{
filePath = GetSaveFilePath();
}
if (string.IsNullOrEmpty(filePath)) return null;
bool isCompatible = GetIsCompatible(filePath);
IWorkbook workbook = CreateWorkbook(isCompatible);
ICellStyle cellStyle = GetCellStyle(workbook);
ISheet sheet = workbook.CreateSheet(sheetName);
IRow headerRow = sheet.CreateRow(0);
for (int i = 0; i < grid.Columns.Count; i++)
{
ICell cell = headerRow.CreateCell(i);
cell.SetCellValue(grid.Columns[i].Name);
cell.CellStyle = cellStyle;
}
int rowIndex = 1;
foreach (DataGridViewRow row in grid.Rows)
{
IRow dataRow = sheet.CreateRow(rowIndex);
for (int n = 0; n < grid.Columns.Count; n++)
{
dataRow.CreateCell(n).SetCellValue((row.Cells[n].Value ?? "").ToString());
}
rowIndex++;
}
AutoColumnWidth(sheet, headerRow.LastCellNum - 1);
FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
workbook.Write(fs);
fs.Dispose();
sheet = null;
headerRow = null;
workbook = null;
MessageBox.Show("文件: " + filePath + ".xls 保存成功", "信息提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return filePath;
}
#endregion
/// <summary>
/// 自適應列寬
/// </summary>
/// <param name="sheet"></param>
/// <param name="cols"></param>
public static void AutoColumnWidth(ISheet sheet, int cols)//獲取當前列的寬度,然后對比本列的長度,取最大值
{
for (int col = 0; col <= cols; col++)
{
sheet.AutoSizeColumn(col);//自適應寬度,但是其實還是比實際文本要寬
int columnWidth = sheet.GetColumnWidth(col) / 256;//獲取當前列寬度
for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++)
{
IRow row;
//當前行未被使用過
if (sheet.GetRow(rowIndex) == null)
{
row = sheet.CreateRow(rowIndex);
}
else
{
row = sheet.GetRow(rowIndex);
}
if (row.GetCell(col) != null)
{
ICell cell = row.GetCell(col);
int contextLength = Encoding.UTF8.GetBytes(cell.ToString()).Length;//獲取當前單元格的內容寬度
columnWidth = columnWidth < contextLength ? contextLength : columnWidth;
}
}
sheet.SetColumnWidth(col, columnWidth * 256);//需要注意的是列的寬度為 列寬*256,所以獲得的寬度需要處以256得到真實的寬度,同樣再設置的時候需要再乘上256才能得到正確的值
}
}
#region 公共導入方法
/// <summary>
/// 由Excel導入DataTable
/// </summary>
/// <param name="excelFileStream">Excel文件流</param>
/// <param name="sheetName">Excel工作表名稱</param>
/// <param name="headerRowIndex">Excel表頭行索引</param>
/// <param name="isCompatible">是否為兼容模式</param>
/// <returns>DataTable</returns>
public static DataTable ImportFromExcel(Stream excelFileStream, string sheetName, int headerRowIndex, bool isCompatible)
{
IWorkbook workbook = CreateWorkbook(isCompatible, excelFileStream);
ISheet sheet = null;
int sheetIndex = -1;
if (int.TryParse(sheetName, out sheetIndex))
{
sheet = workbook.GetSheetAt(sheetIndex);
}
else
{
sheet = workbook.GetSheet(sheetName);
}
DataTable table = GetDataTableFromSheet(sheet, headerRowIndex);
excelFileStream.Close();
workbook = null;
sheet = null;
return table;
}
/// <summary>
/// 由Excel導入DataTable
/// </summary>
/// <param name="excelFilePath">Excel文件路徑,為物理路徑。</param>
/// <param name="sheetName">Excel工作表名稱</param>
/// <param name="headerRowIndex">Excel表頭行索引</param>
/// <returns>DataTable</returns>
public static DataTable ImportFromExcel(string excelFilePath, string sheetName, int headerRowIndex)
{
using (FileStream stream = System.IO.File.OpenRead(excelFilePath))
{
bool isCompatible = GetIsCompatible(excelFilePath);
return ImportFromExcel(stream, sheetName, headerRowIndex, isCompatible);
}
}
/// <summary>
/// 由Excel導入DataSet,如果有多個工作表,則導入多個DataTable
/// </summary>
/// <param name="excelFileStream">Excel文件流</param>
/// <param name="headerRowIndex">Excel表頭行索引</param>
/// <param name="isCompatible">是否為兼容模式</param>
/// <returns>DataSet</returns>
public static DataSet ImportFromExcel(Stream excelFileStream, int headerRowIndex, bool isCompatible)
{
DataSet ds = new DataSet();
IWorkbook workbook = CreateWorkbook(isCompatible, excelFileStream);
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
ISheet sheet = workbook.GetSheetAt(i);
DataTable table = GetDataTableFromSheet(sheet, headerRowIndex);
ds.Tables.Add(table);
}
excelFileStream.Close();
workbook = null;
return ds;
}
/// <summary>
/// 由Excel導入DataSet,如果有多個工作表,則導入多個DataTable
/// </summary>
/// <param name="excelFilePath">Excel文件路徑,為物理路徑。</param>
/// <param name="headerRowIndex">Excel表頭行索引</param>
/// <returns>DataSet</returns>
public static DataSet ImportFromExcel(string excelFilePath, int headerRowIndex)
{
using (FileStream stream = System.IO.File.OpenRead(excelFilePath))
{
bool isCompatible = GetIsCompatible(excelFilePath);
return ImportFromExcel(stream, headerRowIndex, isCompatible);
}
}
#endregion
#region 公共轉換方法
/// <summary>
/// 將Excel的列索引轉換為列名,列索引從0開始,列名從A開始。如第0列為A,第1列為B...
/// </summary>
/// <param name="index">列索引</param>
/// <returns>列名,如第0列為A,第1列為B...</returns>
public static string ConvertColumnIndexToColumnName(int index)
{
index = index + 1;
int system = 26;
char[] digArray = new char[100];
int i = 0;
while (index > 0)
{
int mod = index % system;
if (mod == 0) mod = system;
digArray[i++] = (char)(mod - 1 + 'A');
index = (index - 1) / 26;
}
StringBuilder sb = new StringBuilder(i);
for (int j = i - 1; j >= 0; j--)
{
sb.Append(digArray[j]);
}
return sb.ToString();
}
/// <summary>
/// 轉化日期
/// </summary>
/// <param name="date">日期</param>
/// <returns></returns>
public static DateTime ConvertDate(object date)
{
string dtStr = (date ?? "").ToString();
DateTime dt = new DateTime();
if (DateTime.TryParse(dtStr, out dt))
{
return dt;
}
try
{
string spStr = "";
if (dtStr.Contains("-"))
{
spStr = "-";
}
else if (dtStr.Contains("/"))
{
spStr = "/";
}
string[] time = dtStr.Split(spStr.ToCharArray());
int year = Convert.ToInt32(time[2]);
int month = Convert.ToInt32(time[0]);
int day = Convert.ToInt32(time[1]);
string years = Convert.ToString(year);
string months = Convert.ToString(month);
string days = Convert.ToString(day);
if (months.Length == 4)
{
dt = Convert.ToDateTime(date);
}
else
{
string rq = "";
if (years.Length == 1)
{
years = "0" + years;
}
if (months.Length == 1)
{
months = "0" + months;
}
if (days.Length == 1)
{
days = "0" + days;
}
rq = "20" + years + "-" + months + "-" + days;
dt = Convert.ToDateTime(rq);
}
}
catch
{
throw new Exception("日期格式不正確,轉換日期失敗!");
}
return dt;
}
/// <summary>
/// 轉化數字
/// </summary>
/// <param name="d">數字字符串</param>
/// <returns></returns>
public static decimal ConvertDecimal(object d)
{
string dStr = (d ?? "").ToString();
decimal result = 0;
if (decimal.TryParse(dStr, out result))
{
return result;
}
else
{
throw new Exception("數字格式不正確,轉換數字失敗!");
}
}
#endregion
}
}
C#使用NPOI需要的引用
