c#操作excel
最近想写个脚本来保存程序中的一些日志,最后选择用excel来保存,这里总结一下C#中使用office.excel的一些技巧吧!
首先在C#的工程中添加excel的dll。右键点击引用->添加新引用,然后找出Microsoft.Office.Interop. Excel的dll。
然后在using中添加:
1
2
3 1using System.Reflection;
2using Excel=Microsoft.Office.Interop. Excel;
3
(如果找不到就自行下载)
using System.Reflection是为了调用缺省方法Missing
接下来是具体的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 1Excel.Application excelApp = new Excel.Application(); //Excel应用程序变量,初始化
2 Excel.Workbook excelDoc; //Excel文档变量
3 object OsPath,FilePath;//表格文件的保存地址
4 string FileName;
5 FileName="1.xls";
6 OsPath =@"C:\Users\admin\Desktop\1.xls";//这里我定义了桌面的地址
7 FilePath=string.Format("{0}{1}",(string)OsPath,FileName);//为了自定义地址,加了一个地址拼接
8 Console.WriteLine(FilePath); //调试提示用的
9 object Nothing;
10 Nothing=Missing.Value;//给Nothing一个缺省的值
11 if (File.Exists((string)FilePath))
12 {
13
14 Console.WriteLine("已经有了1.xls这个文件,文件路径为: {0}", FilePath);
15 Console.WriteLine(FilePath);
16 // excelDoc = excelApp.Workbooks.Open(path); //打开原来文件
17 }
18 else {
19 Console.WriteLine("还没有1.xls这个文件",FilePath);
20 }
21 excelDoc = excelApp.Workbooks.Add(Nothing);//Add()中的值不定义的时候给个缺省值就好了
22 Excel.Worksheet ws = (Excel.Worksheet)excelDoc.Sheets[1];
23 Excel.Range i;//定义范围的变量
24 i = ws.get_Range("A1", "A2");//从“A1”到“A2”的位置
25 i.Value2 = "数据1";
26 //WdSaveFormat为Excel文档的保存格式
27 object format = Excel.XlFileFormat.xlWorkbookDefault;
28 //将excelDoc文档对象的内容保存为XLSX文档
29 excelDoc.SaveAs(FilePath, format, Nothing, Nothing, Nothing, Nothing, Excel.XlSaveAsAccessMode.xlExclusive, Nothing, Nothing, Nothing, Nothing, Nothing);
30 excelDoc.Close(Nothing, Nothing, Nothing);
31 //关闭excelApp组件对象
32 excelApp.Quit();
33 Console.WriteLine("创建完毕");
34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 1//引用Microsoft.Office.Interop.Excel.dll文件
2//添加using
3using Microsoft.Office.Interop.Excel;
4using Excel=Microsoft.Office.Interop.Excel;
5
6//设置程序运行语言
7System.Globalization.CultureInfo CurrentCI = System.Threading.Thread.CurrentThread.CurrentCulture;
8System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
9//创建Application
10Excel.Application xlApp = new Excel.Application();
11//设置是否显示警告窗体
12excelApp.DisplayAlerts = false;
13//设置是否显示Excel
14excelApp.Visible = false;
15//禁止刷新屏幕
16excelApp.ScreenUpdating = false;
17//根据路径path打开
18Excel.Workbook xlsWorkBook = excelApp.Workbooks.Open(path, System.Type.Missing, System.Type.Missing, System.Type.Missing,
19System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing,
20System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);
21//获取Worksheet对象
22Excel.Worksheet xlsWorkSheet = (Worksheet)xlsWorkBook.Worksheets["sales plan"];
23
24***获取最后一行、一列的两种方法***
25//获取已用的范围数据
26int rowsCount = xlsWorkSheet.UsedRange.Rows.Count;
27int colsCount = xlsWorkSheet.UsedRange.Columns.Count;
28int rowsCount = xlsWorkSheet.get_Range("A65536", "A65536").get_End(Microsoft.Office.Interop.Excel.XlDirection.xlUp).Row;
29int colsCount = xlsWorkSheet.get_Range("ZZ1", "ZZ1").get_End(Microsoft.Office.Interop.Excel.XlDirection.xlToLeft).Column;
30
31***将Excel数据存入二维数组***
32//rowsCount:最大行 colsCount:最大列
33Microsoft.Office.Interop.Excel.Range c1 = (Microsoft.Office.Interop.Excel.Range)xlsWorkSheet.Cells[1, 1];
34Microsoft.Office.Interop.Excel.Range c2 = (Microsoft.Office.Interop.Excel.Range)xlsWorkSheet.Cells[rowsCount, colsCount];
35Range rng = (Microsoft.Office.Interop.Excel.Range)xlsWorkSheet.get_Range(c1, c2);
36object[,] exceldata = (object[,])rng.get_Value(Microsoft.Office.Interop.Excel.XlRangeValueDataType.xlRangeValueDefault);
37
38//在第一列的左边插入一列
39Excel.Range xlsColumns = (Excel.Range)xlsWorkSheet.Columns[1, System.Type.Missing];
40xlsColumns.Insert(XlInsertShiftDirection.xlShiftToRight, Type.Missing);
41//xlsSheetTemplateMajor_Meisai.Cells.get_Range(xlsSheetTemplateMajor_Meisai.Cells[1, 1], xlsSheetTemplateMajor_Meisai.Cells[65535, 1]).Insert(Type.Missing, Type.Missing);
42 Excel.Range rng;
43 rng = worksheet.get_Range("A:A", "A:A");
44 rng.Insert(Excel.XlDirection.xlToRight, Excel.XlInsertFormatOrigin.xlFormatFromLeftOrAbove);
45Excel.Range rng = (Microsoft.Office.Interop.Excel.Range)xlsWorkSheet.Columns[12, Type.Missing];
46rng.Insert(XlInsertShiftDirection.xlShiftToRight, XlInsertFormatOrigin.xlFormatFromLeftOrAbove);
47
48
49//删除行
50Range deleteRng = (Range)xlsWorkSheetSapExcel.Rows[2, System.Type.Missing];
51deleteRng.Delete(Excel.XlDeleteShiftDirection.xlShiftUp);
52
53//删除一列数据
54((Microsoft.Office.Interop.Excel.Range)xlWorkSheet.Cells[1, 11]).Select();
55((Microsoft.Office.Interop.Excel.Range)xlWorkSheet.Cells[1, 11]).EntireColumn.Delete(0);
56((Excel.Range)xlsSheetShareMajor_Meisai.Cells[1, 3]).EntireColumn.Delete (0);
57
58//设置背景色为红色
59xlsWorkSheet.get_Range("A1", "A1").Interior.ColorIndex = 3;
60
61//设置Format属性 属性值可以通过在vba中录宏得到
62Microsoft.Office.Interop.Excel.Range range1 = xlsWorkSheetAdd.get_Range("J1", "J65535");
63range1.NumberFormat = "@";//文本格式
64range1 = xlsWorkSheetAdd.get_Range("L1", "L65535");
65range1.NumberFormat = "0.00";//保留两位小数
66Excel.Range rng = xlsSheetShareMajor_Meisai.Columns["I", System.Type.Missing] as Excel.Range;
67rng.NumberFormatLocal =@"yyyy/m/d";//设置日期格式
68
69
70//替换
71Range Drng = xlsWorkSheetTemplate.get_Range("D1", "D65535");
72Drng.Replace(" ", "", XlLookAt.xlPart, XlSearchOrder.xlByColumns, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);
73Drng.TextToColumns(Drng, Excel.XlTextParsingType.xlDelimited, Excel.XlTextQualifier.xlTextQualifierSingleQuote, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);
74
75//分列处理 设置为文本
76Range TextToColumnRng = xlsWorkSheet.get_Range("E1", "E65535");
77xlsWorkSheet.get_Range("E1", "E65535").TextToColumns(TextToColumnRng, Excel.XlTextParsingType.xlDelimited, Excel.XlTextQualifier.xlTextQualifierSingleQuote, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing, System.Type.Missing);
78
79//设置公式
80rng = xlMergeFileWorkSheet.get_Range("D2", "D" + rowcount);//设置列范围
81rng.Formula = @"=IF(RC[-3]=""H"",""Survivor"",""Donor"")";//设置公式 @的问题
82//rng.NumberFormat = "$0.00";//设置格式
83copyRng = xlsSheetTemplateMajor_Meisai.get_Range("N3", "N" + lastRowTemplate);
84copyRng.Formula = "=VLOOKUP(RC[-12],AR残!C[-13]:C[-11],2,0)";
85
86//通过行、列的索引获取值
87string f = Convert.ToString(xlsSheetShareMajor_Meisai.get_Range(xlsSheetShareMajor_Meisai.Cells[2, 1], xlsSheetShareMajor_Meisai.Cells[2,1]).Value2);
88
89//筛选
90//确定筛选范围
91D1_rng = D1_TemSheet.Cells.get_Range(D1_TemSheet.Cells[1, 1], D1_TemSheet.Cells[1, 50]);
92//执行筛选动作
93rng.AutoFilter(5, "S", Microsoft.Office.Interop.Excel.XlAutoFilterOperator.xlFilterValues, Type.Missing, true);
94rng.AutoFilter(6, "H", Microsoft.Office.Interop.Excel.XlAutoFilterOperator.xlOr, "F", true);
95D1_rng.AutoFilter(D1_Column + 2, "#N/A", Microsoft.Office.Interop.Excel.XlAutoFilterOperator.xlFilterValues,"#N/A",false);
96
97//复制粘贴
98D2_rng.Copy(Type.Missing);
99D2_TemSheet.Cells.get_Range(D2_TemSheet.Cells[2, (D2_Column + 1)], D2_TemSheet.Cells[2, (D2_Column + 1)]).PasteSpecial(Excel.XlPasteType.xlPasteValues, Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
100
101
102//Find查找
103rng = mySheet.get_Range("A1", "IV10").Find(arrLabel[j], Type.Missing,
104 Microsoft.Office.Interop.Excel.XlFindLookIn.xlValues, Microsoft.Office.Interop.Excel.XlLookAt.xlWhole,
105 Microsoft.Office.Interop.Excel.XlSearchOrder.xlByRows,
106 Microsoft.Office.Interop.Excel.XlSearchDirection.xlNext, false, Type.Missing, Type.Missing);
107
108//文字占满单元格
109range.EntireColumn.AutoFit();
110
111//另存
112xlsWorkBook.SaveAs(FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
113
114***关闭对象***
115System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsWorkSheet);
116System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsWorkBook);
117excelApp.Quit();
118Kill(excelApp);//调用方法关闭进程
119GC.Collect();
120
121/// <summary>
122/// 关闭Excel进程
123/// </summary>
124public class KeyMyExcelProcess
125{
126 [DllImport("User32.dll", CharSet = CharSet.Auto)]
127 public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
128 public static void Kill(Microsoft.Office.Interop.Excel.Application excel)
129 {
130 try
131 {
132 IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄,具体作用是得到这块内存入口
133 int k = 0;
134 GetWindowThreadProcessId(t, out k); //得到本进程唯一标志k
135 System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用
136 p.Kill(); //关闭进程k
137 }
138 catch (System.Exception ex)
139 {
140 throw ex;
141 }
142 }
143}
144
145
146//关闭打开的Excel方法
147 public void CloseExcel(Microsoft.Office.Interop.Excel.Application ExcelApplication, Microsoft.Office.Interop.Excel.Workbook ExcelWorkbook)
148{
149 ExcelWorkbook.Close(false, Type.Missing, Type.Missing);
150 ExcelWorkbook = null;
151 ExcelApplication.Quit();
152 GC.Collect();
153 KeyMyExcelProcess.Kill(ExcelApplication);
154}
155
**0. 导入命名空间: **
1 2 3 4 | using Microsoft.Office.Core; using Microsoft.Office.Interop.Excel; using System.IO; using System.Reflection; |
1 | 1 |
**1. 如何打开已有excel文档,或者创建一个新的excel文档 **
1 2 3 | Application app = new Application(); Workbooks wbks = app.Workbooks; _Workbook _wbk = wbks.Add(xxx); |
1 | 1 |
若打开已有excel,把“xxx”替换成该excel的文件路径;
**注:**若新建一个excel文档,“xxx”替换成true即可;不过这里新建的excel文档默认只有一个sheet。
** **
2. 取得、删除和添加sheet
1 | Sheets shs = _wbk.Sheets; |
1 | 1 |
2.1取得:
1 2 | //i是要取得的sheet的index _Worksheet _wsh = (_Worksheet)shs.get_Item(i) |
1 | 1 |
2.2 删除:
1 2 3 | //删除sheet必须的设置 app.DisplayAlerts = false; _wsh.Delete(); |
1 | 1 |
2.3 添加:
1 2 | /a(before),b(after):确定添加位置;c:数目;d:类型 app.Worksheets.Add(a,b,c,d); |
1 | 1 |
2.4 sheet的重命名
1 | _wsh.Name = "xxx"; |
1 | 1 |
**3. 删除行和列 **
3.1 删除行:
1 | ((Range)_wsh.Rows[3, Missing.Value]).Delete(XlDeleteShiftDirection.xlShiftUp); |
1 | 1 |
3.2 删除列:
1 2 3 4 | _wsh.get_Range( _wsh.Cells[1, 2], _wsh.Cells[_wsh.Rows.Count, 2]).Delete(XlDeleteShiftDirection.xlShiftToLeft ); |
1 | 1 |
**4. 添加行和列 **
4.1 添加行:
1 2 | ((Range)_wsh.Rows[11, Missing.Value]) .Insert(Missing.Value, XlInsertFormatOrigin.xlFormatFromLeftOrAbove); |
1 | 1 |
4.2 添加列:
1 2 3 | _wsh.get_Range( _wsh.Cells[1, 1], _wsh.Cells[_wsh.Rows.Count, 1]) .Insert(Missing.Value, XlInsertShiftDirection.xlShiftToRight); |
1 | 1 |
**5. 单元格操作 **
5.1 单元格的取得
1 2 | //获得单元格对象 _wsh.Cells[row, cell] |
1 | 1 |
5.2 设置公式
1 2 | //在对应的单元格输入公式即可 _wsh.Cells[row, cell] = "=Sum(A1/B1)"; |
1 | 1 |
5.3 合并单元格
1 | ((Range)_wsh.Rows[1, Missing.Value]).Merge(Missing.Value); |
1 | 1 |
5.4 设置行高和列宽
1 2 | ((Range)_wsh.Rows[3, Missing.Value]).RowHeight = 5; ((Range)_wsh.Rows[3, Missing.Value]).ColumnWidth = 5; |
1 | 1 |
5.5 设置单元格颜色 颜色共有56中,详情请参照附录的[颜色对照表]
1 | ((Range)_wsh.Rows[1, Missing.Value]).Interior.ColorIndex = 3; |
1 | 1 |
5.6 设置字号
1 | ((Range)_wsh.Cells[1, "B"]).Font.Size = 8; |
1 | 1 |
5.7 是否设置粗体
1 | ((Range)_wsh.Rows[1, Missing.Value]).Font.Bold = false; |
1 | 1 |
5.8 单元格/区域、水平垂直居中
1 | ((Range)_wsh.Cells[2, 1]).HorizontalAlignment = XlVAlign.xlVAlignCenter; |
1 | 1 |
5.9 设置区域边框
1 | ((Range)_wsh.Cells[3, 3]).Borders.LineStyle = 3; |
1 | 1 |
5.10 设置边框的上、下、左、右线条
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //左 _wsh.get_Range( _wsh.Cells[2, 1], _wsh.Cells[2, 2]) .Borders[XlBordersIndex.xlEdgeLeft].Weight = XlBorderWeight.xlThick;// //右 _wsh.get_Range( _wsh.Cells[2, 1], _wsh.Cells[2, 2]) .Borders[XlBordersIndex.xlEdgeRight].Weight = XlBorderWeight.xlThick;// //上 _wsh.get_Range( _wsh.Cells[2, 1], _wsh.Cells[2, 2]) .Borders[XlBordersIndex.xlEdgeTop].Weight = XlBorderWeight.xlThick;//下 //下 _wsh.get_Range( _wsh.Cells[2, 1], _wsh.Cells[2, 2]) .Borders[XlBordersIndex.xlEdgeBottom].Weight = XlBorderWeight.xlThick; |
1 | 1 |
**6. 指定区域的复制 **
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | _Worksheet _wsh = (_Worksheet)shs.get_Item(1);//复制选中区域的内容 Range range = _wsh.get_Range(_wsh.Cells[7, 1], _wsh.Cells[10, _wsh.Columns.Count]); range.Select(); range.Copy(Type.Missing); //选中粘贴的起始位置 Range test = ((Range)_wsh.Cells[11, 1]); test.Select(); //屏蔽掉Alert,默认确定粘贴 app.DisplayAlerts = false; test.Parse(Missing.Value, Missing.Value); |
1 | 1 |
**注:**Type.Missing和Missing.Value,在excel的操作中被视为某些参数的默认值,他们起到的作用很多时候是形式补足参数
7. excel文件的保存,及后续处理** **
7.1 文件保存
1 2 3 4 5 | //屏蔽掉系统跳出的Alert app.AlertBeforeOverwriting = false; //保存到指定目录 SaveAs(filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); |
1 | 1 |
**注:**这个地方只能采用该方法保存,不然在指定路径下保存文件外,在我的文档中也会生成一个对应的副本
7.2 后续处理:退出和释放
1 2 3 4 5 6 7 | //_wbk.Close(null, null, null); //wbks.Close(); app.Quit(); //释放掉多余的excel进程 System.Runtime.InteropServices.Marshal.ReleaseComObject(app); app = null; |
1 | 1 |
说明:在application关闭的过程中,通常我们有两种方案:
#直接退出app
#先关闭workbook,然后关闭workbooks,最后在退出app
鉴于这两种方式,或许本质上是一样的(这点需要证明),但是依据我们软件开发的原则:哪里需要哪里声明,哪里结束哪里释放回收。
既然在直接退出app的时候,我们不清楚workbook和workbooks具体在什么时间关闭,不如在结束的时候直接手动关闭,这样做可以做到资源的快速直接回收;
所以,建议采用先关闭workbook,然后关闭workbooks,最后在退出app。
**8. 关于单元格设置域和取得域里需要的数据 **
8.1 若单元格已经设置为下拉框
1 2 3 | //这里的“1,2,3”设置的就是下拉框的值 ((Range)_wsh.Cells[2, 1]) .Validation.Modify(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, Type.Missing, "1,2,3", Type.Missing); |
1 | 1 |
8.2 若单元格还没有设置为下拉框的形式
1 2 | ((Range)_wsh.Cells[2, 1]) .Validation.Add(XlDVType.xlValidateList, XlDVAlertStyle.xlValidAlertStop, Type.Missing,"1,2,3", Type.Missing); |
1 | 1 |
8.3 取得下拉框域的值
1 | string strValue = ((Range)_wsh.Cells[2, 1]).Validation.Formula1; |
1 | 1 |
**注:**若在excel模板中通过有效性设定了下拉框的值,strValue得到的将会是excel里的公式,需将其转换, 取得strValue后,可以根据其索引得到你需要的数值;
**9. 隐藏行和隐藏列 **
9.1 隐藏行
1 | _wsh.get_Range(_wsh.Cells[19, 1], _wsh.Cells[22, 1]).EntireRow.Hidden = true; |
1 | 1 |
9.2 隐藏列
1 2 | _wsh.get_Range(_wsh.Cells[1, 1], _wsh.Cells[_wsh.Rows.Count, 1]) .EntireColumn.Hidden = true; |
1 | 1 |