C#封裝的VSTO Excel操作類(20180903更新)

来源:https://www.cnblogs.com/tchivs/archive/2018/09/03/9578635.html
-Advertisement-
Play Games

自己在用的Excel操作類,因為經常在工作中要操作Excel文件,可是使用vba實現起來實在是不方便,而且編寫也很困難,拼接一個字元串都看的眼花。 這個時候C#出現了,發現使用C#來操作Excel非常方便,比VBA不知道高到哪裡去了,而且直接就可以上手,所以我就把常用的一些操作封裝成了一個類,編譯成 ...


自己在用的Excel操作類,因為經常在工作中要操作Excel文件,可是使用vba實現起來實在是不方便,而且編寫也很困難,拼接一個字元串都看的眼花。

這個時候C#出現了,發現使用C#來操作Excel非常方便,比VBA不知道高到哪裡去了,而且直接就可以上手,所以我就把常用的一些操作封裝成了一個類,編譯成DLL方便在各個項目中調用。

其實使用第三方控制項也可以實現相應的功能,而且某些控制項也是使用Visual Studio Tools for Office (VSTO)中同樣風格的介面,直接就可以上手,不過好用的都是要付費的。這裡不做討論。

 

首先要添加程式集引用:Microsoft.Office.Interop.Excel,因為我們使用的是OFFICE2016,所以選擇15.0.0.0版本。

 

只要繼承Excel這個抽象類並實現handler方法即可。

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Diagnostics;
  4 using System.Runtime.InteropServices;
  5 using Microsoft.Office.Interop.Excel;
  6 using System.IO;
  7 using static System.IO.File;
  8 
  9 namespace ExcelHelper
 10 {
 11     /*
 12      2018-08-17 13:43:53
 13      [email protected]
 14          */
 15     /// <summary>
 16     /// Excel抽象類,封裝了常用的方法,只需要實現Hanlder方法即可。
 17     /// </summary>
 18     public abstract class Excel
 19     {
 20         /// <summary>
 21         /// 實例化Excel對象
 22         /// </summary>
 23         /// <param name="debugMode">設置Debug模式(Excel可見性,屏幕刷新,不提示警告窗體)</param>
 24         protected Excel(bool debugMode = true)
 25         {
 26             try
 27             {
 28                 ExcelApp = GetExcelApplication();
 29                 DebugMode = debugMode;
 30             }
 31             catch (InvalidCastException)
 32             {
 33                 throw new COMException("對不起,沒有獲取到本機安裝的Excel對象,請嘗試修複或者安裝Office2016後使用本軟體!");
 34             }
 35         }
 36 
 37         /// <summary>
 38         /// 顯示Excel視窗
 39         /// </summary>
 40         public void Show()
 41         {
 42             if (!ExcelApp.Visible)
 43             {
 44                 ExcelApp.Visible = true;
 45             }
 46         }
 47 
 48         /// <summary>
 49         /// 獲取Excel對象,如果不存在則打開
 50         /// </summary>
 51         /// <returns>返回一個Excel對象</returns>
 52         public Application GetExcelApplication()
 53         {
 54             Application application;
 55             try
 56             {
 57                 application = (Application)Marshal.GetActiveObject("Excel.Application");//嘗試取得正在運行的Excel對象
 58                 Debug.WriteLine("Get Running Excel");
 59             }
 60             //沒有打開Excel則會報錯
 61             catch (COMException)
 62             {
 63                 application = CreateExcelApplication();//打開Excel
 64                 Debug.WriteLine("Create new Excel");
 65             }
 66             Debug.WriteLine(application.Version);//列印Excel版本
 67             return application;
 68         }
 69 
 70         /// <summary>
 71         /// 創建一個Excel對象
 72         /// </summary>
 73         /// <param name="visible">是否顯示Excel,預設為True</param>
 74         /// <param name="caption">標題欄</param>
 75         /// <returns>返回創建好的Excel對象</returns>
 76         public Application CreateExcelApplication(bool visible = true, string caption = "New Application")
 77         {
 78             var application = new Application
 79             {
 80                 Visible = visible,
 81                 Caption = caption
 82             };
 83             return application;
 84         }
 85 
 86         /// <summary>
 87         /// 退出Excel
 88         /// </summary>
 89         public void Exit()
 90         {
 91             if (ExcelApp.Workbooks.Count > 0)
 92             {
 93                 ExcelApp.DisplayAlerts = false;
 94                 ExcelApp.Workbooks.Close(); //關閉所有工作簿
 95             }
 96             ExcelApp.Quit(); //退出Excel
 97             ExcelApp.DisplayAlerts = true;
 98         }
 99         /// <summary>
100         /// 殺死Excel進程
101         /// </summary>
102         public void Kill()
103         {
104             if (ExcelApp.Workbooks.Count > 0)
105             {
106                 ExcelApp.DisplayAlerts = false;
107                 ExcelApp.Workbooks.Close(); //關閉所有工作簿
108             }
109             ExcelApp.Quit();
110             GC.Collect();
111             KeyMyExcelProcess.Kill(ExcelApp);
112         }
113         /// <summary>
114         /// Excel實例對象
115         /// </summary>
116         public Application ExcelApp { get; }
117 
118         /// <summary>
119         /// 獲取workbook對象
120         /// </summary>
121         /// <param name="name">工作簿全名</param>
122         /// <returns></returns>
123         public Workbook GetWorkbook(string name)
124         {
125             var wbk = ExcelApp.Workbooks[name];
126             return wbk;
127         }
128 
129         /// <summary>
130         /// 獲取workbook對象
131         /// </summary>
132         /// <param name="index">索引</param>
133         /// <returns></returns>
134         public Workbook GetWorkbook(int index)
135         {
136             var wbk = ExcelApp.Workbooks[index];
137             return wbk;
138         }
139 
140         /// <summary>
141         /// 獲取workbook活動對象
142         /// </summary>
143         /// <returns></returns>
144         public Workbook GetWorkbook()
145         {
146             var wbk = ExcelApp.ActiveWorkbook;
147             return wbk;
148         }
149 
150         /// <summary>
151         /// 打開工作簿
152         /// </summary>
153         /// <param name="path"></param>
154         /// <returns></returns>
155         public Workbook OpenFromFile(string path)
156         {
157             var workbook = ExcelApp.Workbooks.Open(path);
158             return workbook;
159         }
160 
161         /// <summary>
162         /// 添加工作簿
163         /// </summary>
164         /// <returns></returns>
165         public Workbook AddWorkbook()
166         {
167             var workbook = ExcelApp.Workbooks.Add();
168             return workbook;
169         }
170 
171         /// <summary>
172         /// 保存工作簿
173         /// </summary>
174         /// <param name="workbook"></param>
175         /// <param name="path"></param>
176         public void SaveWorkbook(Workbook workbook, string path)
177         {
178             workbook.SaveAs(path);
179         }
180 
181         /// <summary>
182         /// 關閉工作簿
183         /// </summary>
184         /// <param name="workbook"></param>
185         public void CloseWorkbook(Workbook workbook)
186         {
187             workbook.Close(false, Type.Missing, Type.Missing);
188         }
189 
190         /// <summary>
191         /// 打開或者查找表
192         /// </summary>
193         /// <param name="path"></param>
194         /// <param name="filename"></param>
195         /// <returns></returns>
196         public Workbook OpenAndFindWorkbook(string path, string filename)
197         {
198             var pathFull = Path.Combine(path, filename);
199             string fileName;
200             if (!Exists(pathFull))
201             {
202                 pathFull = Directory.GetFiles(path, filename)[0];
203                 fileName = Path.GetFileName(pathFull);
204             }
205             else
206             {
207                 fileName = Path.GetFileName(filename);
208             }
209 
210 
211             Workbook res = null;
212             //遍歷所有已打開的工作簿
213             foreach (Workbook ws in ExcelApp.Workbooks)
214             {
215                 if (ws.Name != fileName) continue;
216                 res = GetWorkbook(fileName); //OpenFromFile(umts_path).Worksheets[1];
217                 break;
218             }
219 
220             //如果沒有找到就直接打開文件
221             return res ?? (OpenFromFile(pathFull));
222         }
223 
224         /// <summary>
225         /// 打開或者查找表
226         /// </summary>
227         /// <param name="filename">文件名全路徑</param>
228         /// <returns></returns>
229         public Workbook OpenAndFindWorkbook(string filename)
230         {
231             var pathFull = filename;
232             string fileName;
233             var path = Path.GetDirectoryName(filename);
234             if (!Exists(pathFull))
235             {
236                 pathFull = Directory.GetFiles(path ?? throw new InvalidOperationException(), filename)[0];
237                 fileName = Path.GetFileName(pathFull);
238             }
239             else
240             {
241                 fileName = Path.GetFileName(filename);
242             }
243 
244 
245             Workbook res = null;
246             //遍歷所有已打開的工作簿
247             foreach (Workbook ws in ExcelApp.Workbooks)
248             {
249                 if (ws.Name != fileName) continue;
250                 res = GetWorkbook(fileName); //OpenFromFile(umts_path).Worksheets[1];
251                 break;
252             }
253 
254             //如果沒有找到就直接打開文件
255             return res ?? (OpenFromFile(pathFull));
256         }
257 
258         /// <summary>
259         /// 複製列到另一張表
260         /// </summary>
261         /// <param name="sourceWorksheet">源表</param>
262         /// <param name="sourceRows">源列</param>
263         /// <param name="sourceStart">起始位置</param>
264         /// <param name="newWorksheet">目的表</param>
265         /// <param name="newRows">目的列</param>
266         /// <param name="newStart">目的位置</param>
267         public void CopyRow2OtherSheet(Worksheet sourceWorksheet, string[] sourceRows, int sourceStart,
268             Worksheet newWorksheet, string[] newRows, int newStart)
269         {
270             int intrngEnd = GetEndRow(sourceWorksheet);
271             if (newRows != null && (sourceRows != null && sourceRows.Length == newRows.Length))
272             {
273                 for (int i = 0; i < sourceRows.Length; i++)
274                 {
275                     var rg = sourceRows[i] + sourceStart + ":" + sourceRows[i] + intrngEnd;
276                     sourceWorksheet.Range[rg]
277                         .Copy(newWorksheet.Range[newRows[i] + newStart]);
278                     //  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;
279                 }
280             }
281             else
282             {
283                 Console.WriteLine("Error source_rows length not is new_rows length!");
284             }
285         }
286 
287         /// <summary>
288         /// 複製列到另一張表
289         /// </summary>
290         /// <param name="sourceWorksheet">源表</param>
291         /// <param name="sourceRows">源列</param>
292         /// <param name="sourceStart">起始位置</param>
293         /// <param name="newWorksheet">目的表</param>
294         /// <param name="newRows">目的列</param>
295         /// <param name="newStart">目的位置</param>
296         public void CopyRow2OtherSheet(Worksheet sourceWorksheet, int[] sourceRows, int sourceStart, Worksheet newWorksheet,
297             int[] newRows, int newStart)
298         {
299             int intrngEnd = GetEndRow(sourceWorksheet);
300             if (sourceRows.Length == newRows.Length)
301             {
302                 for (int i = 0; i < sourceRows.Length; i++)
303                 {
304                     newWorksheet.Cells[65536, newRows[i]].End[XlDirection.xlUp].Offset(sourceStart, 0).Resize(intrngEnd, sourceStart)
305                         .Value = sourceWorksheet.Cells[newStart, sourceRows[i]].Resize(intrngEnd, newRows[i]).Value;
306                 }
307             }
308             else
309             {
310                 Console.WriteLine("Error source_rows length not is new_rows length!");
311             }
312         }
313 
314         /// <summary>
315         /// 複製表頭到另一個sheet中
316         /// </summary>
317         /// <param name="sourceWorksheet">表頭所在的sheet</param>
318         /// <param name="newWorksheet">要複製到的sheet</param>
319         /// <param name="start">起始位置</param>
320         public void CopyHeader(Worksheet sourceWorksheet, Worksheet newWorksheet, int start = 1)
321         {
322             if (sourceWorksheet.Rows != null)
323                 sourceWorksheet.Rows[start].Copy(newWorksheet.Cells[1, 1]); //把數據表的表頭複製到新表中
324         }
325 
326         /// <summary>
327         /// 設置特定列的數據
328         /// </summary>
329         /// <param name="worksheet">源表</param>
330         /// <param name="row">要設置的列號</param>
331         /// <param name="len">長度</param>
332         /// <param name="value">要設的值</param>
333         /// ///
334         public void SetSheetRow(Worksheet worksheet, int row, int len, string value)
335         {
336             //int intrngEnd = this.GetEndRow(worksheet);//取特定列最後一列的長度
337             worksheet.Cells[65536, row].End[XlDirection.xlUp].Offset(1, 0).Resize(len, 1).Value = value;
338         }
339 
340         /// <summary>
341         /// 取有效列的最後一列的長度
342         /// </summary>
343         /// <param name="worksheet"></param>
344         /// <returns></returns>
345         public int GetEndRow(Worksheet worksheet)
346         {
347             int res = worksheet.UsedRange.Rows.Count;
348             return res;
349         }
350 
351         /// <summary>
352         /// 插入圖片
353         /// </summary>
354         /// <param name="path">圖片路徑</param>
355         /// <param name="worksheet">要插入的表</param>
356         /// <param name="range">要插入的range</param>
357         public void AddPic(string path, Worksheet worksheet, Range range)
358         {
359             this.AddPic(path, worksheet, range, range.Width, range.Height);
360         }
361 
362         /// <summary>
363         /// 插入圖片
364         /// </summary>
365         /// <param name="path">圖片路徑</param>
366         /// <param name="worksheet">要插入的表</param>
367         /// <param name="range">要插入的range</param>
368         /// <param name="width">圖片的寬度</param>
369         /// <param name="height">圖片的高度</param>
370         public void AddPic(string path, Worksheet worksheet, Range range, int width, int height)
371         {
372             worksheet.Shapes.AddPicture(path, Microsoft.Office.Core.MsoTriState.msoCTrue,
373                     Microsoft.Office.Core.MsoTriState.msoCTrue, range.Left, range.Top, width, height).Placement =
374                 XlPlacement.xlMoveAndSize;
375         }
376 
377         /// <summary>
378         /// 批量插入圖片
379         /// </summary>
380         /// <param name="pngdic">單元格範圍-圖片名</param>
381         /// <param name="imgBase">圖片根目錄</param>
382         /// <param name="worksheet">要插入圖片的worksheet</param>
383         /// <returns>返回處理好的圖片日誌</returns>
384         public string InsertMultipleImages(Dictionary<string, string> pngdic, string imgBase, Worksheet worksheet)
385         {
386             string msg = null;
387             foreach (var s in pngdic)
388             {
389                 string imgPath = Path.Combine(imgBase, s.Value);
390                 if (!Exists(imgPath))
391                 {
392                     continue;
393                 }
394 
395                 Range range = worksheet.Range[s.Key];
396                 AddPic(imgPath, worksheet, range);
397                 msg = s.Value + "\t" + s.Key + "\t\t\t" + range.Left.ToString() + "\t" + range.Top.ToString() + "\n";
398             }
399 
400             return msg;
401         }
402 
403         /// <summary>
404         /// 主要實現這個方法
405         /// </summary>
406         /// <param name="path">要打開的文件路徑</param>
407         public abstract void Handler(string path = null);
408         /// <summary>
409         /// 開啟或者關閉屏幕刷新
410         /// </summary>
411         public bool ScreenUpdating
412         {
413             get => ExcelApp.ScreenUpdating;
414             set => ExcelApp.ScreenUpdating = value;
415         }
416         /// <summary>
417         /// Excel可見性
418         /// </summary>
419         public bool Visible
420         {
421             get => ExcelApp.Visible;
422             set => ExcelApp.Visible = value;
423         }
424         /// <summary>
425         /// 是否顯示警告窗體
426         /// </summary>
427         public bool DisplayAlerts
428         {
429             get => ExcelApp.DisplayAlerts;
430             set => ExcelApp.DisplayAlerts = value;
431         }
432         private bool	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 順序 自上而下,依次執行 分支 分支的基本語法 if 條件表達式: 語句1 語句2 語句3 ...... 條件表達式就是計算結果必須為布爾值的表達式 表達式後面的冒號不能少 註意if後面的出現的語句,如果屬於if語句塊,則必須同一個鎖緊等級 條件表達式結果為True執行if後面的縮進的語句塊 雙向分 ...
  • 前言 IO完成埠(IO completion ports)在多核電腦的並行非同步IO請求方面提供了一種高效的線程模型。當進程創建一個IO完成埠時,系統創建一個相關聯的隊列,其唯一目的是服務與那些請求。IO完成埠通常和預先分配的線程池配合,相比於一個一個創建線程,這使其更快更高效。IOCP在進程 ...
  • 一、環境及優點介紹: 開發環境:vs2017(.Net Framework 4.5) 資料庫:MySQL(選擇原因是占用資源少) ORM:SqlSuger(是由園中大神孫凱旋寫的,向大神致敬!膜拜!博客園,官網) 前端:LayUI(扁平化設計,個人體驗(看著舒服、用著方便 模塊化開發)向團隊致敬) ...
  • 1、C#語言簡介 C#電腦語言 是一門高級電腦語言 他的開發模式更接近人類和社會的思維模式,有助於提高開發效率 C#歷史 1998年COOL這個項目是C#語言的前身,由微軟 Anders Hejlsberg 和他的團隊在 .Net 框架開發期間開發的 2001年正式發佈 C#含義 C#是C語言和 ...
  • netcore項目引用dll包,分如下三種: 1、引用網路包 從nuget獲取,然後引入,使用命令:dotnet add package 包名 然後:dotnet restore 2、引用同解決方案的類庫包 在項目文件.csproj添加項目引用: <ItemGroup> <PackageRefere ...
  • 下載文件: 代碼: 後端代碼: public IActionResult DownloadFile() { var FilePath = @"./files/deparment.xlsx"; var stream = System.IO.File.OpenRead(FilePath); return ...
  • 在ASP.NET Core上利用MassTransit來集成使用RabbitMQ真的很簡單,代碼也很簡潔。近期因為項目需要,我便在這基礎上再次進行了封裝,抽成了公共方法,使得使用RabbitMQ的調用變得更方便簡潔。那麼,就讓咱們來瞧瞧其魅力所在吧。 ...
  • 一、添加覆選框 ArrayList arr = new ArrayList(); public string checkboxName = "選擇"; void StandLibWin_Load(object sender, EventArgs e) { DataGridViewCheckBoxCo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...