自己在用的Excel操作类,因为经常在工作中要操作Excel文件,可是使用vba实现起来实在是不方便,而且编写也很困难,拼接一个字符串都看的眼花。

这个时候C#出现了,发现使用C#来操作Excel非常方便,比VBA不知道高到哪里去了,而且直接就可以上手,所以我就把常用的一些操作封装成了一个类,编译成DLL方便在各个项目中调用,或者作为excel加载项,写的不好的轻喷,毕竟我是门外汉一个。

其实使用第三方控件也可以实现相应的功能,而且某些控件也是使用Visual Studio Tools for Office (VSTO)中同样风格的接口,直接就可以上手,不过好用的都是要付费的。这里不做讨论。

Visual Studio里面请安装好office开发组件

首先要添加程序集引用:Microsoft.Office.Interop.Excel,因为我们使用的是OFFICE2016,所以选择15.0.0.0版本。

只要继承Excel这个抽象类并实现handler方法即可。

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop.Excel;
using System.IO;
using static System.IO.File; namespace ExcelHelper
{
/*
2018-08-17 13:43:53
luoc@zhiweicl.com
*/
/// <summary>
/// Excel抽象类,封装了常用的方法,只需要实现Hanlder方法即可。
/// </summary>
public abstract class Excel
{
/// <summary>
/// 实例化Excel对象
/// </summary>
/// <param name="debugMode">设置Debug模式(Excel可见性,屏幕刷新,不提示警告窗体)</param>
protected Excel(bool debugMode = true)
{
try
{
ExcelApp = GetExcelApplication();
DebugMode = debugMode;
}
catch (InvalidCastException)
{
throw new COMException("对不起,没有获取到本机安装的Excel对象,请尝试修复或者安装Office2016后使用本软件!");
}
} /// <summary>
/// 显示Excel窗口
/// </summary>
public void Show()
{
if (!ExcelApp.Visible)
{
ExcelApp.Visible = true;
}
} /// <summary>
/// 获取Excel对象,如果不存在则打开
/// </summary>
/// <returns>返回一个Excel对象</returns>
public Application GetExcelApplication()
{
Application application;
try
{
application = (Application)Marshal.GetActiveObject("Excel.Application");//尝试取得正在运行的Excel对象
Debug.WriteLine("Get Running Excel");
}
//没有打开Excel则会报错
catch (COMException)
{
application = CreateExcelApplication();//打开Excel
Debug.WriteLine("Create new Excel");
}
Debug.WriteLine(application.Version);//打印Excel版本
return application;
} /// <summary>
/// 创建一个Excel对象
/// </summary>
/// <param name="visible">是否显示Excel,默认为True</param>
/// <param name="caption">标题栏</param>
/// <returns>返回创建好的Excel对象</returns>
public Application CreateExcelApplication(bool visible = true, string caption = "New Application")
{
var application = new Application
{
Visible = visible,
Caption = caption
};
return application;
} /// <summary>
/// 退出Excel
/// </summary>
public void Exit()
{
if (ExcelApp.Workbooks.Count > )
{
ExcelApp.DisplayAlerts = false;
ExcelApp.Workbooks.Close(); //关闭所有工作簿
}
ExcelApp.Quit(); //退出Excel
ExcelApp.DisplayAlerts = true;
}
/// <summary>
/// 杀死Excel进程
/// </summary>
public void Kill()
{
if (ExcelApp.Workbooks.Count > )
{
ExcelApp.DisplayAlerts = false;
ExcelApp.Workbooks.Close(); //关闭所有工作簿
}
ExcelApp.Quit();
GC.Collect();
KeyMyExcelProcess.Kill(ExcelApp);
}
/// <summary>
/// Excel实例对象
/// </summary>
public Application ExcelApp { get; } /// <summary>
/// 获取workbook对象
/// </summary>
/// <param name="name">工作簿全名</param>
/// <returns></returns>
public Workbook GetWorkbook(string name)
{
var wbk = ExcelApp.Workbooks[name];
return wbk;
} /// <summary>
/// 获取workbook对象
/// </summary>
/// <param name="index">索引</param>
/// <returns></returns>
public Workbook GetWorkbook(int index)
{
var wbk = ExcelApp.Workbooks[index];
return wbk;
} /// <summary>
/// 获取workbook活动对象
/// </summary>
/// <returns></returns>
public Workbook GetWorkbook()
{
var wbk = ExcelApp.ActiveWorkbook;
return wbk;
} /// <summary>
/// 打开工作簿
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public Workbook OpenFromFile(string path)
{
var workbook = ExcelApp.Workbooks.Open(path);
return workbook;
} /// <summary>
/// 添加工作簿
/// </summary>
/// <returns></returns>
public Workbook AddWorkbook()
{
var workbook = ExcelApp.Workbooks.Add();
return workbook;
} /// <summary>
/// 保存工作簿
/// </summary>
/// <param name="workbook"></param>
/// <param name="path"></param>
public void SaveWorkbook(Workbook workbook, string path)
{
workbook.SaveAs(path);
} /// <summary>
/// 关闭工作簿
/// </summary>
/// <param name="workbook"></param>
public void CloseWorkbook(Workbook workbook)
{
workbook.Close(false, Type.Missing, Type.Missing);
} /// <summary>
/// 打开或者查找表
/// </summary>
/// <param name="path"></param>
/// <param name="filename"></param>
/// <returns></returns>
public Workbook OpenAndFindWorkbook(string path, string filename)
{
var pathFull = Path.Combine(path, filename);
string fileName;
if (!Exists(pathFull))
{
pathFull = Directory.GetFiles(path, filename)[];
fileName = Path.GetFileName(pathFull);
}
else
{
fileName = Path.GetFileName(filename);
} Workbook res = null;
//遍历所有已打开的工作簿
foreach (Workbook ws in ExcelApp.Workbooks)
{
if (ws.Name != fileName) continue;
res = GetWorkbook(fileName); //OpenFromFile(umts_path).Worksheets[1];
break;
} //如果没有找到就直接打开文件
return res ?? (OpenFromFile(pathFull));
} /// <summary>
/// 打开或者查找表
/// </summary>
/// <param name="filename">文件名全路径</param>
/// <returns></returns>
public Workbook OpenAndFindWorkbook(string filename)
{
var pathFull = filename;
string fileName;
var path = Path.GetDirectoryName(filename);
if (!Exists(pathFull))
{
pathFull = Directory.GetFiles(path ?? throw new InvalidOperationException(), filename)[];
fileName = Path.GetFileName(pathFull);
}
else
{
fileName = Path.GetFileName(filename);
} Workbook res = null;
//遍历所有已打开的工作簿
foreach (Workbook ws in ExcelApp.Workbooks)
{
if (ws.Name != fileName) continue;
res = GetWorkbook(fileName); //OpenFromFile(umts_path).Worksheets[1];
break;
} //如果没有找到就直接打开文件
return res ?? (OpenFromFile(pathFull));
} /// <summary>
/// 复制列到另一张表
/// </summary>
/// <param name="sourceWorksheet">源表</param>
/// <param name="sourceRows">源列</param>
/// <param name="sourceStart">起始位置</param>
/// <param name="newWorksheet">目的表</param>
/// <param name="newRows">目的列</param>
/// <param name="newStart">目的位置</param>
public void CopyRow2OtherSheet(Worksheet sourceWorksheet, string[] sourceRows, int sourceStart,
Worksheet newWorksheet, string[] newRows, int newStart)
{
int intrngEnd = GetEndRow(sourceWorksheet);
if (newRows != null && (sourceRows != null && sourceRows.Length == newRows.Length))
{
for (int i = ; i < sourceRows.Length; i++)
{
var rg = sourceRows[i] + sourceStart + ":" + sourceRows[i] + intrngEnd;
sourceWorksheet.Range[rg]
.Copy(newWorksheet.Range[newRows[i] + newStart]);
// new_worksheet.Cells[65536, new_rows[i]].End[XlDirection.xlUp].Offset(1, 0).Resize(intrngEnd, 1).Value = source_worksheet.Cells[2, source_rows[i]].Resize(intrngEnd, new_rows[i]).Value;
}
}
else
{
Console.WriteLine("Error source_rows length not is new_rows length!");
}
} /// <summary>
/// 复制列到另一张表
/// </summary>
/// <param name="sourceWorksheet">源表</param>
/// <param name="sourceRows">源列</param>
/// <param name="sourceStart">起始位置</param>
/// <param name="newWorksheet">目的表</param>
/// <param name="newRows">目的列</param>
/// <param name="newStart">目的位置</param>
public void CopyRow2OtherSheet(Worksheet sourceWorksheet, int[] sourceRows, int sourceStart, Worksheet newWorksheet,
int[] newRows, int newStart)
{
int intrngEnd = GetEndRow(sourceWorksheet);
if (sourceRows.Length == newRows.Length)
{
for (int i = ; i < sourceRows.Length; i++)
{
newWorksheet.Cells[, newRows[i]].End[XlDirection.xlUp].Offset(sourceStart, ).Resize(intrngEnd, sourceStart)
.Value = sourceWorksheet.Cells[newStart, sourceRows[i]].Resize(intrngEnd, newRows[i]).Value;
}
}
else
{
Console.WriteLine("Error source_rows length not is new_rows length!");
}
} /// <summary>
/// 复制表头到另一个sheet中
/// </summary>
/// <param name="sourceWorksheet">表头所在的sheet</param>
/// <param name="newWorksheet">要复制到的sheet</param>
/// <param name="start">起始位置</param>
public void CopyHeader(Worksheet sourceWorksheet, Worksheet newWorksheet, int start = )
{
if (sourceWorksheet.Rows != null)
sourceWorksheet.Rows[start].Copy(newWorksheet.Cells[, ]); //把数据表的表头复制到新表中
} /// <summary>
/// 设置特定列的数据
/// </summary>
/// <param name="worksheet">源表</param>
/// <param name="row">要设置的列号</param>
/// <param name="len">长度</param>
/// <param name="value">要设的值</param>
/// ///
public void SetSheetRow(Worksheet worksheet, int row, int len, string value)
{
//int intrngEnd = this.GetEndRow(worksheet);//取特定列最后一列的长度
worksheet.Cells[, row].End[XlDirection.xlUp].Offset(, ).Resize(len, ).Value = value;
} /// <summary>
/// 取有效列的最后一列的长度
/// </summary>
/// <param name="worksheet"></param>
/// <returns></returns>
public int GetEndRow(Worksheet worksheet)
{
int res = worksheet.UsedRange.Rows.Count;
return res;
} /// <summary>
/// 插入图片
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="worksheet">要插入的表</param>
/// <param name="range">要插入的range</param>
public void AddPic(string path, Worksheet worksheet, Range range)
{
this.AddPic(path, worksheet, range, range.Width, range.Height);
} /// <summary>
/// 插入图片
/// </summary>
/// <param name="path">图片路径</param>
/// <param name="worksheet">要插入的表</param>
/// <param name="range">要插入的range</param>
/// <param name="width">图片的宽度</param>
/// <param name="height">图片的高度</param>
public void AddPic(string path, Worksheet worksheet, Range range, int width, int height)
{
worksheet.Shapes.AddPicture(path, Microsoft.Office.Core.MsoTriState.msoCTrue,
Microsoft.Office.Core.MsoTriState.msoCTrue, range.Left, range.Top, width, height).Placement =
XlPlacement.xlMoveAndSize;
} /// <summary>
/// 批量插入图片
/// </summary>
/// <param name="pngdic">单元格范围-图片名</param>
/// <param name="imgBase">图片根目录</param>
/// <param name="worksheet">要插入图片的worksheet</param>
/// <returns>返回处理好的图片日志</returns>
public string InsertMultipleImages(Dictionary<string, string> pngdic, string imgBase, Worksheet worksheet)
{
string msg = null;
foreach (var s in pngdic)
{
string imgPath = Path.Combine(imgBase, s.Value);
if (!Exists(imgPath))
{
continue;
} Range range = worksheet.Range[s.Key];
AddPic(imgPath, worksheet, range);
msg = s.Value + "\t" + s.Key + "\t\t\t" + range.Left.ToString() + "\t" + range.Top.ToString() + "\n";
} return msg;
} /// <summary>
/// 主要实现这个方法
/// </summary>
/// <param name="path">要打开的文件路径</param>
public abstract void Handler(string path = null);
/// <summary>
/// 开启或者关闭屏幕刷新
/// </summary>
public bool ScreenUpdating
{
get => ExcelApp.ScreenUpdating;
set => ExcelApp.ScreenUpdating = value;
}
/// <summary>
/// Excel可见性
/// </summary>
public bool Visible
{
get => ExcelApp.Visible;
set => ExcelApp.Visible = value;
}
/// <summary>
/// 是否显示警告窗体
/// </summary>
public bool DisplayAlerts
{
get => ExcelApp.DisplayAlerts;
set => ExcelApp.DisplayAlerts = value;
}
private bool _debugMode;
/// <summary>
/// 设置DEBUG模式
/// </summary>
public bool DebugMode
{
get => _debugMode;
set
{
_debugMode = value;
//设置是否显示警告窗体
DisplayAlerts = value;
//设置是否显示Excel
Visible = value;
//禁止刷新屏幕
ScreenUpdating = value;
}
}
}
/// <summary>
/// 关闭Excel进程
/// </summary>
public class KeyMyExcelProcess
{
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int id);
public static void Kill(Application excel)
{
try
{
IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄,具体作用是得到这块内存入口
GetWindowThreadProcessId(t, out var k); //得到本进程唯一标志k
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用
p.Kill(); //关闭进程k
}
catch (Exception e)
{
Console.WriteLine(e.Message);
} }
}
}

最后放上github的地址

https://github.com/tchivs/ExcelLib

C#封装的VSTO Excel操作类的更多相关文章

  1. C#EXCEL 操作类--C#ExcelHelper操作类

    主要功能如下1.导出Excel文件,自动返回可下载的文件流 2.导出Excel文件,转换为可读模式3.导出Excel文件,并自定义文件名4.将数据导出至Excel文件5.将指定的集合数据导出至Exce ...

  2. Excel 操作类

    转载:http://www.cnblogs.com/fellowcheng/archive/2010/08/21/1805158.html ExcelHelper(Excel2007) Code hi ...

  3. C#常用工具类——Excel操作类

    /// 常用工具类——Excel操作类 /// <para> ------------------------------------------------</para> / ...

  4. C# Excel操作类

    /// 常用工具类——Excel操作类 /// <para> ------------------------------------------------</para> / ...

  5. c# 封装的文件夹操作类之复制文件夹

    c#  封装的文件夹操作类之复制文件夹 一.复制文件夹原理: 1.递归遍历文件夹 2.复制文件 二.FolderHelper.cs /// <summary> /// 文件夹操作类 /// ...

  6. C#常用工具类——Excel操作类(ZT)

    本文转载于: http://www.cnblogs.com/zfanlong1314/p/3916047.html /// 常用工具类——Excel操作类 /// <para> ----- ...

  7. 封装php redis缓存操作类

    封装php redis缓存操作类,集成了连接redis并判断连接是否成功,redis数据库选择,检测redis键是否存在,获取值,写入值,设置生存时间和删除清空操作. php redis类代码: &l ...

  8. C#自定义Excel操作类

    C#自定义Excel操作类,可以用于将DataTable导出到Excel文件,从Excel文件读取数据. using System; using System.IO; using System.Dat ...

  9. C# Excel操作类 ExcelHelper

    实现C#与Excel文件的交互操作,实现以下功能: 1.DataTable 导出到 Excel文件 2.Model数据实体导出到 Excel文件[List<Model>] 3.导出数据到模 ...

随机推荐

  1. 学习动态性能表(14)--v$parameter&v$system_parameter

    学习动态性能表 第14篇--V$PARAMETER&V$SYSTEM_PARAMETER  2007.6.11 这两个视图列出的各参数项名称以及参数值.V$PARAMETER显示执行查询的se ...

  2. vijos1369:难解的问题

    描述 在你的帮助下,蔚蓝来到了埃及.在金字塔里,蔚蓝看到了一个问题,传说,能回答出这个问题的人就能受到埃及法老的祝福,可是蔚蓝日夜奋战,还是想不出来,你能帮帮他么?(XXX: 胡扯,教主怎么可能想不出 ...

  3. boot asio 非阻塞同步编程---非阻塞的accept和receive。

    boot asio 非阻塞同步编程---非阻塞的accept和receive. 客户端编程: #include<boost/timer.hpp> #include <iostream ...

  4. Errors occurred during the build. Errors occurred during the build. Errors running builder 'JavaScript Validator' on XXX

    选择项目--右键Properties--Builders--如果有则取消第一项“JavaScript Validator”的勾. http://blog.csdn.net/error_case/art ...

  5. [JAVA反序列化DEMO]利用RMI进行反序列化一键启动工具

    功能: 命令行启动jar包,用户自定义启动RMI端口.默认内置Apache Commons Collections.只需一键启动即可测试java反序列化漏洞. 启动服务: [root@sevck_v3 ...

  6. redmine2.3环境搭建

    1. 安装redmine bitnami-redmine-2.3.0-0-windows-installer.exe安装到C:\BitNami\redmine-2.3.0-0目录下. 其中redmin ...

  7. RegisterUserFunc为测试对象添加新方法或重写已有方法

    QTP中为了提高扩展性,提供了一个为测试对象添加一个新的自定义方法,或者重写测试对象已有的方法的函数RegisterUserFunc,在此给大家分享一下. RegisterUserFunc:为测试对象 ...

  8. Solaris与Windows Active Directory集成

    通过Solaris与Active Directory的集成,Solaris可以使用Windows 2003 R2/ 2008 Active Directory来进行用户登录验证.以下是简要配置过程. ...

  9. 如何判断python的数据类型,用type函数

    用 type 函数 In [29]:  type(dataset) Out[29]: list 查询list的行数 In [38]: len(dataset) In [39]: Out[38]: 36 ...

  10. docker 笔记(6)网络

    docker network ls   默认docker安装时会创建3个网络 none网络 one 网络就是什么都没有的网络.挂在这个网络下的容器除了 lo,没有其他任何网卡.容器创建时,可以通过 - ...