using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Reflection; using System.IO; using System.Diagnostics; using System.Collections; using System.Runtime.InteropServices; using Microsoft.Office.Interop.Excel; using Infragistics.Win.UltraWinGrid; using System.Windows.Forms; namespace Core.StlMes.Client.Plan.Order { /**/ /// /// 功能说明: 为套用模板输出Excel定制,并对数据进行分页 /// public class ExcelHelper { protected string templetFile = null; protected string outputFile = null; protected object missing = Missing.Value; /// /// 构造函数,需指定模板文件和输出文件完整路径 /// /// Excel模板文件路径 /// 输出Excel文件路径 public ExcelHelper(string templetFilePath, string outputFilePath) { if (templetFilePath == null) throw new Exception(" Excel模板文件路径不能为空! "); if (!File.Exists(templetFilePath)) throw new Exception(" 指定路径的Excel模板文件不存在! "); this.templetFile = templetFilePath; this.outputFile = outputFilePath; if (CheckPath() == false) throw new Exception(" 输出Excel文件路径不能为空! "); } /// /// 获取Cells单元格的值 /// /// 第x行,Excel的起始列为1 /// 第y列,Excel的起始行为1 /// object public string GetCell_Value(int x, int y,Microsoft.Office.Interop.Excel.Worksheet sheet) { if (sheet == null) { return ""; } object[] Parameters_Cells = new object[2] { x, y }; //第x行,第y列 object m_objCells = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, Parameters_Cells); if (m_objCells == null) { return ""; } object m_objCellsValue = sheet.GetType().InvokeMember("Value", BindingFlags.GetProperty, null, m_objCells, new object[0]); if (m_objCellsValue == null) { return ""; } System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objCells); GC.GetTotalMemory(true); return m_objCellsValue.ToString(); } /// /// 获取WorkSheet数量 /// /// 记录总行数 /// 每WorkSheet行数 private int GetSheetCount(int rowCount, int rows) { int n = rowCount % rows; // 余数 if (n == 0) return rowCount / rows; else return Convert.ToInt32(rowCount / rows) + 1; } /// /// 将二维数组数据写入Excel文件(套用模板并分页) /// /// 二维数组 /// 每个WorkSheet写入多少行数据 /// 行索引-从1开始 /// 列索引-从1开始 /// WorkSheet前缀名,比如:前缀名为“Sheet”,那么WorkSheet名称依次为“Sheet-1,Sheet-2” public bool ArrayToExcel(object[,] arr, int rows, int top, int left, string sheetPrefixName) { int rowCount = arr.GetLength(0); // 二维数组行数(一维长度) int colCount = arr.GetLength(1); // 二维数据列数(二维长度) int sheetCount = this.GetSheetCount(rowCount, rows); // WorkSheet个数 if (sheetPrefixName == null || sheetPrefixName.Trim() == "") sheetPrefixName = " Sheet "; // 创建一个Application对象并使其可见 Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); app.Visible = false; try { // 打开模板文件,得到WorkBook对象 Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks._Open(templetFile, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); // 得到WorkSheet对象 Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets.get_Item(1); // 复制sheetCount-1个WorkSheet对象 for (int i = 1; i < sheetCount; i++) { ((Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets.get_Item(i)).Copy(missing, workBook.Worksheets[i]); } #region 将二维数组数据写入Excel //将二维数组数据写入Excel for (int i = 1; i <= sheetCount; i++) { int startRow = (i - 1) * rows; // 记录起始行索引 int endRow = i * rows; // 记录结束行索引 // 若是最后一个WorkSheet,那么记录结束行索引为源DataTable行数 if (i == sheetCount) endRow = rowCount; // 获取要写入数据的WorkSheet对象,并重命名 Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets.get_Item(i); sheet.Name = sheetPrefixName + " - " + i.ToString(); //设定输出部分的样式 Microsoft.Office.Interop.Excel.Range excelRange = sheet.get_Range(SeqToXlsCol[left] + (top + startRow - (i - 1) * rows), SeqToXlsCol[left + colCount - 1] + (top + endRow - 1 - (i - 1) * rows)); //excelRange.NumberFormatLocal = "@"; excelRange.Borders.LineStyle = 1; excelRange.Font.Size = 9; excelRange.Font.Name = "Arial"; List param = new List(); for (int row = 0; row < rowCount; row++) { for (int col = 0; col < colCount; col++) { if (arr[row, col].ToString().Length > 500) { ValuesPoint value = new ValuesPoint(); value.Values = arr[row, col]; value.Row = row; value.Col = col; arr[row, col] = ""; param.Add(value); } } } //string _BeginPoint = SeqToXlsCol[left] + (top + startRow - (i - 1) * rows); //string _EndPoint = SeqToXlsCol[left + colCount - 1] + (top + endRow - 1 - (i - 1) * rows); //SetRangeArray_Value(app, sheet, _BeginPoint, _EndPoint, arr); //设定header 居中粗体 //sheet.get_Range(IFCF.SeqToXlsCol[left] + top + ":" + IFCF.SeqToXlsCol[left + colCount - 1] + top).Font.Bold = true; //sheet.get_Range(IFCF.SeqToXlsCol[left] + top + ":" + IFCF.SeqToXlsCol[left + colCount - 1] + top).HorizontalAlignment = XlHAlign.xlHAlignCenter; // 将二维数组中的数据写入WorkSheet sheet.get_Range(SeqToXlsCol[left] + (top + startRow - (i - 1) * rows), SeqToXlsCol[left + colCount - 1] + (top + endRow - 1 - (i - 1) * rows)).Value2 = arr; for (int cout = 0; cout < param.Count; cout++) { int row = param[cout].Row; int col = param[cout].Col; sheet.Cells[top + row-startRow, left + col] = param[cout].Values; } //for (int j = 0; j < endRow - startRow; j++) //{ // for (int k = 0; k < colCount; k++) // { // sheet.Cells[top + j, left + k] = arr[startRow + j, k]; // } //} //自动调整列宽 //sheet.Cells.EntireColumn.AutoFit(); } #endregion // 输出Excel文件并退出 //保存Excel的时候,不弹出是否保存的窗口直接进行保存 app.DisplayAlerts = false; workBook._SaveAs(outputFile, missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, missing, missing, missing, missing); workBook.Close(null, null, null); app.Workbooks.Close(); app.Application.Quit(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); ExcelProecssKill(app); workSheet = null; workBook = null; app = null; GC.Collect(); } catch (Exception ex) { ExcelProecssKill(app); Debug.WriteLine(ex.Message); MessageBox.Show(ex.Message); return false; } finally { ExcelProecssKill(app); } return true; } /// /// 将二维数组数据写入Excel文件(套用模板并分页) /// /// 二维数组 /// 行索引-从1开始 /// 列索引-从1开始 /// WorkSheet前缀名,比如:前缀名为“Sheet”,那么WorkSheet名称依次为“Sheet-1,Sheet-2” public bool ArrayToExcel(object[,] arr, int top, int left, string sheetPrefixName) { int rowCount = arr.GetLength(0); // 二维数组行数(一维长度) int colCount = arr.GetLength(1); // 二维数据列数(二维长度) if (sheetPrefixName == null || sheetPrefixName.Trim() == "") sheetPrefixName = " Sheet "; // 创建一个Application对象并使其可见 Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); app.Visible = false; try { // 打开模板文件,得到WorkBook对象 Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks._Open(templetFile, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); // 得到WorkSheet对象 Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets.get_Item(1); #region 将二维数组数据写入Excel //将二维数组数据写入Excel //for (int i = 1; i <= sheetCount; i++) //{ //int startRow = (i - 1) * rows; // 记录起始行索引 //int endRow = i * rows; // 记录结束行索引 //// 若是最后一个WorkSheet,那么记录结束行索引为源DataTable行数 //if (i == sheetCount) // endRow = rowCount; // 获取要写入数据的WorkSheet对象,并重命名 Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets.get_Item(1); sheet.Name = sheetPrefixName + " - 1"; //设定输出部分的样式 Microsoft.Office.Interop.Excel.Range excelRange = sheet.get_Range(SeqToXlsCol[left] + top, SeqToXlsCol[left + colCount - 1] + (top + rowCount - 1)); //excelRange.NumberFormatLocal = "@"; excelRange.Borders.LineStyle = 1; excelRange.Font.Size = 9; excelRange.Font.Name = "Arial"; List param = new List(); for (int row = 0; row < rowCount; row++) { for (int col = 0; col < colCount; col++) { if (arr[row, col].ToString().Length > 500) { ValuesPoint value = new ValuesPoint(); value.Values = arr[row, col]; value.Row = row; value.Col = col; arr[row, col] = ""; param.Add(value); } } } //string _BeginPoint = SeqToXlsCol[left] + (top + startRow - (i - 1) * rows); //string _EndPoint = SeqToXlsCol[left + colCount - 1] + (top + endRow - 1 - (i - 1) * rows); //SetRangeArray_Value(app, sheet, _BeginPoint, _EndPoint, arr); //设定header 居中粗体 //sheet.get_Range(IFCF.SeqToXlsCol[left] + top + ":" + IFCF.SeqToXlsCol[left + colCount - 1] + top).Font.Bold = true; //sheet.get_Range(IFCF.SeqToXlsCol[left] + top + ":" + IFCF.SeqToXlsCol[left + colCount - 1] + top).HorizontalAlignment = XlHAlign.xlHAlignCenter; // 将二维数组中的数据写入WorkSheet sheet.get_Range(SeqToXlsCol[left] + top, SeqToXlsCol[left + colCount - 1] + (top + rowCount - 1)).Value2 = arr; for (int cout = 0; cout < param.Count; cout++) { int row = param[cout].Row; int col = param[cout].Col; sheet.Cells[top + row, left + col] = param[cout].Values; } //for (int j = 0; j < endRow - startRow; j++) //{ // for (int k = 0; k < colCount; k++) // { // sheet.Cells[top + j, left + k] = arr[startRow + j, k]; // } //} //自动调整列宽 //sheet.Cells.EntireColumn.AutoFit(); #endregion // 输出Excel文件并退出 //保存Excel的时候,不弹出是否保存的窗口直接进行保存 app.DisplayAlerts = false; workBook._SaveAs(outputFile, missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, missing, missing, missing, missing); workBook.Close(null, null, null); app.Workbooks.Close(); app.Application.Quit(); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(workSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(workBook); System.Runtime.InteropServices.Marshal.ReleaseComObject(app); ExcelProecssKill(app); workSheet = null; workBook = null; app = null; GC.Collect(); } catch (Exception ex) { ExcelProecssKill(app); Debug.WriteLine(ex.Message); MessageBox.Show(ex.Message); return false; } finally { ExcelProecssKill(app); } return true; } [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); /// /// 对Excel的进程进行处理 /// /// public static void ExcelProecssKill(Microsoft.Office.Interop.Excel.Application excel) { try { if (excel != null) { IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄,具体作用是得到这块内存入口 int k = 0; GetWindowThreadProcessId(t, out k); //得到本进程唯一标志k System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用 p.Kill(); //关闭进程k } } catch (System.Exception ex) { Debug.WriteLine(ex.Message); } } /// /// 验证输出文件的路径,如果没有就新 /// /// true or false private bool CheckPath() { try { string tempPath = outputFile.Substring(0, outputFile.LastIndexOf("\\")); if (Directory.Exists(tempPath) == false) { Directory.CreateDirectory(tempPath); } if (File.Exists(outputFile) == true) { File.Delete(outputFile); //File.Move(outputFile, outputFile + "_" + DateTime.Now.ToString("yyyyMMddHHmmss")); } return true; } catch (System.Exception ex) { Debug.WriteLine(ex.Message); return false; } } /// /// 读取Grid数据,并按模板格式排列成二维数组 /// /// grid表格 /// 模板表头行索引-从1开始 /// 模板表头列索引-从1开始 /// 二维数组 public string[,] setModelArr(UltraGrid grid, int top, int left) { int count = 0; //模板表头列数 string[,] arr = null; DateTime beforeTime; DateTime afterTime; // 创建一个Application对象并使其可见 beforeTime = DateTime.Now; Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); //new Excel.ApplicationClass(); app.Visible = true; afterTime = DateTime.Now; try { // 打开模板文件,得到WorkBook对象 Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks._Open(templetFile, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); // 得到WorkSheet对象 Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets.get_Item(1); ArrayList headGourp = new ArrayList(); for (int k = left; k < workSheet.Columns.Count; k++) { string head = GetCell_Value(top, k, workSheet); headGourp.Add(head); if (head.Equals("")) { count = k - left; break; } } arr = new string[grid.Rows.Count, count]; //读取grid数据到二维数组中 for (int k = left, j = 0; k < count + left; k++, j++) { string head = headGourp[j].ToString(); //string head = GetCell_Value(top, k, workSheet); int rows = 0; for (int i = 0; i < grid.DisplayLayout.Bands[0].Columns.Count; i++) { string gridhead = grid.DisplayLayout.Bands[0].Columns[i].Header.Caption; if (head.Equals(gridhead)) { foreach (UltraGridRow uRow in grid.Rows) { arr[rows, k - 1] = uRow.Cells[i].Value.ToString(); rows++; } break; } } } app.Workbooks.Close(); app.Application.Quit(); app.Quit(); } catch (Exception ex) { ExcelProecssKill(app); Debug.WriteLine(ex.Message); return arr; } finally { ExcelProecssKill(app); } return arr; } /// /// 读取DataTable数据,并按模板格式排列成二维数组 /// /// DataTable /// 模板表头行索引-从1开始 /// 模板表头列索引-从1开始 /// 二维数组 public string[,] setModelArr(System.Data.DataTable dt, int top, int left) { int count = 0; //模板表头列数 string[,] arr = null; DateTime beforeTime; DateTime afterTime; // 创建一个Application对象并使其可见 beforeTime = DateTime.Now; Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); //new Excel.ApplicationClass(); app.Visible = true; afterTime = DateTime.Now; try { // 打开模板文件,得到WorkBook对象 Microsoft.Office.Interop.Excel.Workbook workBook = app.Workbooks._Open(templetFile, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); // 得到WorkSheet对象 Microsoft.Office.Interop.Excel.Worksheet workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets.get_Item(1); ArrayList headGourp = new ArrayList(); for (int k = left; k < workSheet.Columns.Count; k++) { string head = GetCell_Value(top, k, workSheet); headGourp.Add(head); if (head.Equals("")) { count = k - left; break; } } arr = new string[dt.Rows.Count, count]; //读取DataTable数据到二维数组中 for (int k = left, j = 0; k < count + left; k++, j++) { string head = headGourp[j].ToString(); //string head = GetCell_Value(top, k, workSheet); int rows = 0; for (int i = 0; i < dt.Columns.Count; i++) { string dthead = dt.Columns[i].Caption; if (head.Equals(dthead)) { foreach (DataRow dr in dt.Rows) { arr[rows, k - 1] = dr[i].ToString(); rows++; } break; } } } app.Workbooks.Close(); app.Application.Quit(); app.Quit(); } catch (Exception ex) { ExcelProecssKill(app); Debug.WriteLine(ex.Message); return arr; } finally { ExcelProecssKill(app); } return arr; } /// /// 列标号,Excel最大列数是256 /// public static string[] SeqToXlsCol = new string[] {"", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD", "CE", "CF", "CG", "CH", "CI", "CJ", "CK", "CL", "CM", "CN", "CO", "CP", "CQ", "CR", "CS", "CT", "CU", "CV", "CW", "CX", "CY", "CZ", "DA", "DB", "DC", "DD", "DE", "DF", "DG", "DH", "DI", "DJ", "DK", "DL", "DM", "DN", "DO", "DP", "DQ", "DR", "DS", "DT", "DU", "DV", "DW", "DX", "DY", "DZ", "EA", "EB", "EC", "ED", "EE", "EF", "EG", "EH", "EI", "EJ", "EK", "EL", "EM", "EN", "EO", "EP", "EQ", "ER", "ES", "ET", "EU", "EV", "EW", "EX", "EY", "EZ", "FA", "FB", "FC", "FD", "FE", "FF", "FG", "FH", "FI", "FJ", "FK", "FL", "FM", "FN", "FO", "FP", "FQ", "FR", "FS", "FT", "FU", "FV", "FW", "FX", "FY", "FZ", "GA", "GB", "GC", "GD", "GE", "GF", "GG", "GH", "GI", "GJ", "GK", "GL", "GM", "GN", "GO", "GP", "GQ", "GR", "GS", "GT", "GU", "GV", "GW", "GX", "GY", "GZ", "HA", "HB", "HC", "HD", "HE", "HF", "HG", "HH", "HI", "HJ", "HK", "HL", "HM", "HN", "HO", "HP", "HQ", "HR", "HS", "HT", "HU", "HV", "HW", "HX", "HY", "HZ", "IA", "IB", "IC", "ID", "IE", "IF", "IG", "IH", "II", "IJ", "IK", "IL", "IM", "IN", "IO", "IP", "IQ", "IR", "IS", "IT", "IU", "IV" }; /// /// 将二维数组 写入 excel /// /// 起始位置 如"A1" /// 终止位置 如"B5" /// 写入的二维数组的值,可以是各种数据类型 /// bool,是否正确写入 public bool SetRangeArray_Value(object m_objApp,object m_objSheet,string _BeginPoint, string _EndPoint, object[,] _Array_Value) { if (m_objApp == null) { return false; } if (m_objSheet == null) { return false; } try { //得到range数组 //object[] Parameters_rangeArray = new object[] { "A1", "B5" }; object[] Parameters_rangeArray = new object[] { _BeginPoint, _EndPoint }; object m_objRangeArray = m_objSheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, m_objSheet, Parameters_rangeArray); if (m_objRangeArray == null) { Console.WriteLine("出错啦: range == null,请检查range的设置。"); } //************************ //得到写入值 Object[] ParametersArray_WriteValue = new Object[1]; ParametersArray_WriteValue[0] = _Array_Value; //赋值:数值类型=int //****************** m_objRangeArray.GetType().InvokeMember("Value2", BindingFlags.SetProperty, null, m_objRangeArray, ParametersArray_WriteValue); System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objRangeArray); GC.GetTotalMemory(true); return true; } catch (Exception ex) { MessageBox.Show("写入错误!错误原因:" + ex.Message); return false; } } /// /// 退出excel.exe的编辑模式 Edit Mode /// //public void SetApp_Exit_EditMode() //{ // if (m_objApp == null) { return; } // if (m_objSheet == null) { return; } // while (true) // { // try // { // this.Cursor = System.Windows.Forms.Cursors.WaitCursor; // bool bAppReady = (bool)m_objApp.GetType().InvokeMember("Ready", BindingFlags.GetProperty, null, m_objApp, null); // this.Cursor = System.Windows.Forms.Cursors.Arrow; // break; //如果excel.exe退出了编辑模式则退出循环 // } // catch // { // myWin32API.SetForegroundWindow(this.appSubWinHandle); // myWin32API.SetFocus(this.appSubWinHandle); // //System.Threading.Thread.Sleep(100); // System.Windows.Forms.SendKeys.SendWait("{ESC}"); //发送ESC键 // //System.Windows.Forms.SendKeys.Send("{ESC}"); //发送ESC键 // //System.Threading.Thread.Sleep(100); // } // } //} } class ValuesPoint { private object values; public object Values { get { return values; } set { values = value; } } private int row; public int Row { get { return row; } set { row = value; } } private int col; public int Col { get { return col; } set { col = value; } } } }