16,721
社区成员




[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
Excel(以及 ms office)有很多功能,例如可以自动使用用户的声卡读出Excel 上的文字,这样你在用户打开一个报表时可以用你的程序自动查找报告的标题行,然后写一行简单的 app.Speek(....) 语句来读出报告的标题。你也可以使用 Office 通用的功能来打印、转换为 PDF、HTML,等等,使用你的代码来调用 Excel 和 Office 所具有的各种方法。using excel = Microsoft.Office.Interop.Excel;
为了方便避免名称空间冲突(因为可能不同的组件都有Application等等同名的元素),我在这里使用了别名 excel。
首先要在内存中创建一个 Excel 进程影像(获得跟COM 进程对象的“桥梁”),你可以这样写var app = new excel.Application();
app.DisplayAlerts = false;
ExcelApps.Add(app);
要打开一个工作簿文件,假设名字叫做 11.xslx,可以写app.Workbooks.Open(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data", "11.xlsx"));
app.Visible = true; //你也可以在后台打开它,让它不可见。我这里让 excel 窗口可见。
excel.Workbook wb = app.Workbooks[1];
要访问某个工作表(假设名为 sheet3)的单个单元,可以这样写excel.Worksheet sht = wb.Sheets["sheet3"];
object v = sht.Range["a2"].Value2; //使用 excel 相对坐标方式来访问单元
v = sht.Range["计算C列有数据的行数"].Value2; //使用excel命名单元方式来访问单元
Debug.Assert(v is double); //读取出来的v,值可以是数字、字符,等等
要重新运行工作表上所有的计算公式,可以写excel.Range cs = null;
try
{
cs = sheet.Cells.SpecialCells(excel.XlCellType.xlCellTypeFormulas);
}
catch
{
}
if (cs != null)
foreach (excel.Range c in cs)
try
{
c.FormulaR1C1 = c.FormulaR1C1;
}
catch { }
如果你要读写大量数据,切忌打一个一个单元去读写,应该使用二维数组整体一次性地读写。例如sht = wb.Sheets["sheet1"];
object[,] datas = sht.Range["c22", "f23"].Value2; //注意,excel vb 返回的二维数组的下标是从 1 开始的
Debug.Assert(datas[1, 1] is double);
Debug.Assert(datas[2, 3] is string);
Debug.Assert(datas[1, 2] == null);
datas[1, 1] = new Random().Next();
datas[2, 4] = DateTime.Now.ToShortTimeString();
sht.Range["c22", "f23"].Value2 = datas;
var endCell = sht.Range["c22"].End[excel.XlDirection.xlDown];
这里就把sheet1工作表上的一个2行4列的区域里边的数据,一次性读取到二维数组中。然后验证其单元的值的类型(c22单元为数字,e23但愿为字符串,d22为空)。然后把数据一次性地写入excel工作表。
再强一次,不要一个单元一个单元地去读写数据。要使用二维数组,一次读写大块数据区域。
可以捕获单元格的更改(用户录入)事件,例如sht.Change += Sht_Change;
private void Sht_Change(excel.Range Target)
{
if(Target.Row==1 || Target.Column == 2 || Target...........)
{
}
}
要关闭工作簿,这样写 app.DisplayAlerts = false;
wb.Close();
要杀掉刚刚打开的 Excel进程(但是不误杀其它Excel进程),应该这样写app.Quit();
IntPtr intptr = new IntPtr(app.Hwnd);
var ps = Process.GetProcessesByName("EXCEL").ToList();
int id;
GetWindowThreadProcessId(intptr, out id);
var p = Process.GetProcessById(id);
if (p != null)
p.Kill();
我上面举得例子,只有 Excel 的一丁点皮毛,甚至连皮毛都不算。Excel功能非常强大。你可以买一本管理人员、统计人员使用的Excel书籍看看,就知道 Excel 有多少种功能。而每一种功能都可以通过 c#、vb.net 实时地控制!