前一篇文章介紹了Excel中的菜單系統,在創建完菜單和工具欄之後,就要著手進行功能的開發了。不論您采用何種方式來開發Excel應用程序,了解Excel對象模型尤其重要,這些對象是您與Excel進行交互的基石。據不完全統計,Excel的對象模型中有270多個對象及超過5000多個屬性和方法。通過這些對象及方法,您可以充分利用Excel來定制化您的插件。
Excel的所有對象,事件,方法和屬性在這裡不可能全部介紹完。本文簡要介紹一下Excel的整體文檔對象模型,以及一些比較重要的,平常開發中需要頻繁接觸到的對象,屬性,事件及方法,如Application,Range對象等,使您對Excel的整個結構有一個簡單的了解。後面在編程中遇到問題了,您可以快速定位知道需要設置或者調用哪個對象及其方法,然後根據關鍵字到Google或者MSDN上方便查找。本文大部分內容參照MSDN上的這篇文章Understanding the Excel Object Model from a .NET Developer's Perspective 如果您對英文沒有問題,建議您直接去MSDN看原文。
一 Excel 對象模型簡介
在與Excel進行交互之前,了解Excel對象模型的整體結構非常重要,這使得我們對Excel有一種更整體全面的了解。下圖是Excel的對象模型的整個層級結構。
根據這個圖,我們打開一個Excel,可以有一種非常直觀形象的了解。
圖中可以看到,Excel對象模型基本模擬了UI界面:
一個Excel應用程序就是一個Application,全局的對象比如菜單,工具條都屬於Application對象。
相關文章:
淺談Excel開發(1) Excel開發概述:http://www.bianceng.cn/Programming/net/201312/39219.htm
一個Application可以包含很多個Workbook(Workbooks)。具體而言就是,我們可以同時打開很多個工作簿(Workbooks),但某一時候只有一個工作簿(Workbook)處於編輯狀態,這個工作簿叫做活動工作簿(ActiveWorkbook);
一個Workbook可以包含很多個Worksheet(Worksheets)。具體而言就是,一個工作簿可以包含很多工作表(Worksheets),某一時刻只有一個工作表(Worksheet)處於編輯狀態,這個工作表稱之為活動工作表(ActiveWorksheet)。
一個Workbook還可以包含很多Shapes對象。工作表中還可以包含一些圖表,標記,注釋,控件等,這些都是浮在Sheet頁上的,這些統稱為Shapes,其中我們接觸的最多的是圖表(Charts)。
一個WorkSheet可以包含很多個Range對象。具體而言,一個工作表裡面有很多個單元格,單元格范圍用Range表示,Range可以使一個單元格,也可以使多個單元格。單元格都是嵌入到Sheet頁中的。
更詳細地Excel的對象模型圖,如下,圖中灰色的部分存在於office.dll中所有Office應用程序中都存在的對象。
以上是Excel文檔對象模型的大概全部的對象模型。其中最重要的幾個對象為Application,Workbook,Worksheet 和Range對象。下面就簡單介紹下這些對象中的一些屬性,方法及事件。
二 Application對象
Application是根對象,代表著Excel應用程序本身,一切Excel中的其他對象都有它直接或者間接創建。 您可以回想到前面我們在Shared Add-in項目中創建Excel菜單和工具條時接觸到的對象。我們首先是在Connect方法中保存了 application對象,然後在該對象上創建了MenuBar和Toolbar。Application對象有一些熟悉,事件和方法,在我們編程中經常會用到,現在就稍微講一下:
2.1 Application中控制Excel狀態和顯示的方法和屬性
Application中控制Excel狀態和顯示的方法和屬性有很多,表一中列出了常用的幾個屬性。有一個屬性是需要重新啟用後才可以生效的。
上面列出的屬性中,最可能用到的是ScreenUpdating屬性,正確使用該屬性能夠大幅提高應用程序的性能。默認的,該屬性為true,即每一次修改就會刷新整個界面,這會使得應用程序變慢,尤其是在往單元格填充大量數據的時候。所以一般的做法是,在填充數據之前保存ScreenUpdating屬性,然後將ScreenUpdating屬性設置為false,禁止屏幕刷新,然後填充數據,最後將之前保存的ScreenUpdating屬性賦值回來。下面的代碼演示了這一做法:
Boolean oldScreenUpdate = this.Application.ScreenUpdating; try { this.Application.ScreenUpdating = false; //to fill in a large range that time comsuming } finally { this.Application.ScreenUpdating = oldScreenUpdate; }
2.2 Application中返回的對象
從Application對象中可以獲取很多有用的對象。如ActiveCell返回當前活動的單元格;ActiveChart,返回當前選中的活動的圖表;ActiveSheet、ActiveWindows分別返回活動的Sheet頁和窗口;Selection屬性返回當前選中的對象,可能是Range,Worksheet或者是一個窗體;Workbooks,Sheets,Charts返回當前Excel中所有工作簿,工作表,圖表的集合。
通常,我們接觸最多的是Application對象的Workbooks屬性,該對象是當前Excel打開的所有的工作簿文件。一個Workbook就是一個.xls或者.xlsx文件。下面簡單講解Workbooks對象。
創建一個新的workbook對象 通過Applicaition的Workbooks對象的Add方法可以創建一個新的工作簿。
// Create a new workbook object
Excel.Workbook wb = this.Application.Workbooks.Add(Type.Missing);
關閉所有的workbook對象 通過調用close對象可以關閉所有的工作簿。
// Close all workbooks
this.Application.Workbooks.Close();
打開一個Excel文件 通過Open方法可以打開一個本地的Excel文件,Open方法有很多定制化參數,如果不需要制定的話,傳入Type.Missing即可。
// Open an exist workbook Excel.Workbook wbOpenExistFile = this.Application.Workbooks.Open( "C:\\YourPath\\Yourworkbook.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
打開文本文件,數據庫文件,XML文件
這些操作可以通過OpenText,OpenDatabase,OpenXml方法來實現,方法參數可能需要您詳細指定。
返回指定的工作簿文件
有時候我們可能需要從當前的工作簿文件中,找到指定的工作簿文件進行操作。一般的我們可以通過Workbooks屬性通過索引器傳入index來返回,或者通過工作簿名稱來返回。需要注意的是,工作簿沒有保存前,不需要後綴,保存後需要帶上後綴來進行訪問,代碼如下:
//Get an exist workbook form current workbooks Excel.Workbook wbFind = this.Application.Workbooks[1]; // Before Book1 is saved: wbFind = this.Application.Workbooks["Book1"]; // After Book1 is saved: wbFind = this.Application.Workbooks["Book1.xls"];
2.3 Application中的方法
Application對象提供了一些方法,包括單元格的重新計算,撤銷操作等。
Calculate方法:該方法強制所有打開的工作簿,特定的工作簿,或者指定的Range對象進行重新計算。
// Cell calculate this.Application.Calculate(); // Or... this.Application.Calculate(); // Or... this.Application.get_Range("A1", "B12").Calculate();
Quit方法:如果要退出Excel,則可以調用Quit方法,如果DisplayAlerts設置為false,則不會彈出提示用戶保存的對話框。
Undo:撤銷用戶界面上的最後一次操作,該撤銷操作對代碼執行的操作不起作用,並且只能撤銷最後一次操作哦。
2.4 Application中文件操作方法
DefaultFilePath 獲取或者設置Excel默認加載和保存文件的路徑
DefaultSaveFormat 獲取或者設置Excel默認保存的文件格式,該格式是XlFileFormat枚舉類型的對象。
RecentFiles 最近使用文件屬性,返回一系列最近使用的文件名
FileDialog 屬性,該屬性返回一個FileDialog對象,他能夠處理四種類型的文件操作,包括:選擇文件並打開,選擇文件路徑並保存當前工作簿,選擇目錄和選擇文件名。使用Dialog窗體,我們可以利用Office提供的各種文件處理能力。其文件類型通過指定FileDialog類型來實現,該類型是一個msoFileDialogType枚舉,包含msoFileDialogFilePicker,msoFileDialogFolderPicker,msoFileDialogOpen和msoFileDialogSaveAs四個枚舉值。FileDialog對象存在於Microsoft.Office.Core命名空間中。FileDialog的Show方法彈出一個對話框,如果返回-1表示擁護點擊了OK按鈕,如果是0表示擁護按下了Cancel按鈕,如果使用msoFileDialogOpen或者msoFileDialogSaveAs枚舉值,FileDialog的Execute方法會執行打開或者保存文件的操作。SelectedItems屬性包含了一些列的字符串,它表示選中的一些列文件名稱。下面代碼演示了如何使用。
//using FileDialog to open an exist file Office.FileDialog dlg = this.Application.get_FileDialog( Office.MsoFileDialogType.msoFileDialogOpen); dlg.Filters.Clear(); dlg.Filters.Add("Excel Files", "*.xls;*.xlw", Type.Missing); dlg.Filters.Add("All Files", "*.*", Type.Missing); if (dlg.Show() != 0) dlg.Execute();
2.5 Application中其他一些有用的對象
Application中還有一些其他有用的對象,如WorksheetFunction,該對象包括了一系列靜態或者共享方法,這些方法都是對Excel內置函數的包裝。
WorksheetFunction 下面演示了WorksheetFunction的用法:
Excel.Worksheet ws = (Excel.Worksheet)this.Application.ActiveSheet; Excel.Range rng = ws.get_Range("RandomNumbers", Type.Missing); System.Random rnd = new System.Random(); for (int i = 1; i <= 20; i++) ws.Cells[i, 2] = rnd.Next(100); rng.Sort(rng, Excel.XlSortOrder.xlAscending, Type.Missing, Type.Missing, Excel.XlSortOrder.xlAscending, Type.Missing, Excel.XlSortOrder.xlAscending, Excel.XlYesNoGuess.xlNo, Type.Missing, Type.Missing, Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin, Excel.XlSortDataOption.xlSortNormal, Excel.XlSortDataOption.xlSortNormal, Excel.XlSortDataOption.xlSortNormal); Excel.WorksheetFunction wsf = this.Application.WorksheetFunction; ws.get_Range("Min", Type.Missing).Value2 = wsf.Min(rng, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Windows對象 Application的Windows對象提供了對Excel窗體進行打開,關閉重新排列的方法。可以調用該對象的Arrange方法來對所有的窗體進行重新排列,我們需要指定XlArrangeStyle枚舉:
// Arrange the windows this.Application.Windows.Arrange( Excel.XlArrangeStyle.xlArrangeStyleTiled, Type.Missing, Type.Missing, Type.Missing);
Name對象 該對象對應了Excel中的名稱管理器,這些名稱對應了一些Range對象,這在繪制圖表,以及一些對函數公式長度有限制的地方很有用處,Application對象的Name屬性返回了Excel中有所名字對象的集合。要創建命名Range對象,調用Names的Add方法即可。
//Add a name range Excel.Name nm = this.Application.Names.Add( "NewName", @"='Other Application Members'!$A$6", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
後面使用該名稱即可找到該名稱代表的Range對象:
// Retrive a name Range this.Application.get_Range("NewName", Type.Missing).Value2 = "Hello, World!";
2.6 Application對象中的事件
Application對象除了上面講解的一些有用的方法和屬性之外,還有一些事件。這些事件大致分為Sheet行為相關的事件、Window行為相關事件Workbook管理相關的事件。下面簡要介紹這些事件的作用。
Sheet相關事件:
SheetActive事件:當任意Sheet頁變為活動工作表時觸發。
SheetClculate事件:當任意Sheet重新計算時觸發,其參數包含了被重新計算的Object對象
SheetChange事件:當工作步中,單元格的值發生改變時觸發,參數中包含了發生變化的Range對象。
SheetFollowHyperlink事件:當用戶點擊工作簿中的超鏈接時觸發。參數中包含了包含超鏈接的Object對象,以及一個Hyperlink對象包含了需要跳轉到的對象。
SheetSelectionChange事件:當工作簿中的選擇區域發生變化時觸發。
以上application上的事件在Workbook類上也存在。application上的事件對所有的工作簿都有效,而Workbook上的這些事件僅對該Workbook有效。
Windows行為相關事件:
WindowsActivate事件:當任意一個窗體被激活時觸發。
WindowsResize事件:當窗體大小發生改變時觸發。
Workbook行為相關事件:
NewWorkbook事件:當新的工作簿(workbook)被創建時觸發。方法中包含新創建的Workbook類型的變量。
WorkbookBeforeClose事件:在工作簿被關閉時觸發,方法中傳遞了被關閉工作簿的對象,以及一個表示是否處理的Boolean型值。
WorkbookBeforeSave事件:在工作簿保存時觸發的事件。
WorkbookNewSheet事件:在工作簿中創建新的工作表時觸發的事件。
WorkbookOpen事件:在工作簿被打開始觸發的事件。
三 Workbook對象
Workbook對象也有很多屬性和方法,下面僅介紹一些比較常用的方法和屬性。
Workbook屬性
Name,FullName,Path:Name返回文件的名稱,不好含路徑;FullName返回包含路徑的文件名稱;Path返回文件所在的文件夾。
Password:設置或者返回與該工作簿相關的密碼。如果文檔由密碼保護,則HasPassword屬性返回True,通過Password屬性可以獲取到密碼,密碼顯示為“*****”。
PrecisionAsDisplayed:如果為True,則Excel進行數值計算時,精度按照顯示的精度來進行。如果為false(默認值),則Excel將會按照所有可用的精度進行計算。
ReadOnly:只讀屬性,如果為True,則標為只讀。即不能對文檔進行修改。
Saved:獲取或者設置保存工作簿的狀態。如果用戶對工作表的內容或者結構進行過修改,則該屬性為True。在試圖退出或者關閉Excel時,如果Application.DisplayAlerts為False時,會彈出提示框提示用戶是否保存。但是如果將Saved屬性設置為False,則Excel會認為您已經保存過,所以不會彈出提示框。
文檔屬性
Excel文檔允許用戶將一些信息保存到文件屬性中。Excel提供了一些列內置的屬性,我們也可以添加自己的屬性。
Workbook類的BuiltInDocumentProperties屬性可以獲取和設置那只的屬性,CustomDocumentProperties可以獲取和設置自定義屬性。屬性以鍵值對表示,我們可以使用屬性的關鍵字或者Index來獲取屬性。下面的代碼演示了獲取所有的內置和自定義的屬性,DumpPropertyCollection方法用來打印屬性。
//Display the document property private void DisplayDocumentProperties() { Office.DocumentProperty prp = null; Office.DocumentProperties prps = (Office.DocumentProperties) this.Application.ActiveWorkbook.BuiltinDocumentProperties; Excel.Range rng = this.Application. get_Range("DocumentProperties", Type.Missing); int i = 0; try { this.Application.ScreenUpdating = false; try { // Set the Revision Number property: prp = prps["Revision Number"]; prp.Value = Convert.ToInt32(prp.Value) + 1; // Dump contents of the collection: i = DumpPropertyCollection(prps, rng, i); } catch (Exception ex) { MessageBox.Show(ex.Message, this.Application.Name); } // Work with custom properties: try { prps = (Office.DocumentProperties) this.Application.ActiveWorkbook.CustomDocumentProperties; DumpPropertyCollection(prps, rng, i); } catch (Exception ex) { MessageBox.Show(ex.Message, this.Application.Name); } // Add a custom property: try { // Delete the property, if it exists. prp = prps["Project Name"]; prp.Delete(); } catch { // Do nothing if you get an exception. } try { // Add a new property. prp = prps.Add("Project Name", false, Office.MsoDocProperties.msoPropertyTypeString, "White Papers", Type.Missing); } catch (Exception ex) { MessageBox.Show(ex.Message, this.Application.Name); } } finally { this.Application.ScreenUpdating = true; } } private int DumpPropertyCollection( Office.DocumentProperties prps, Excel.Range rng, int i) { foreach (Office.DocumentProperty prp in prps) { rng.get_Offset(i, 0).Value2 = prp.Name; try { if (prp.Value != null) { rng.get_Offset(i, 1).Value2 = prp.Value.ToString(); } } catch { // Do nothing at all. } i += 1; } return i; }
一般地,我們可以將一些和文檔相關的信息或者臨時數據保存到自定義信息中。
文檔樣式
在Excel開發中,我們經常要對單元格進行格式化,這時,我們可能需要自定義一些樣式,然後給其命名,然後下次直接按照名稱賦給樣式即可。
我們可以通過Workbook的Styles屬性來對這些文檔樣式進行添加,修改和刪除。下面代碼演示了如何創建或者修改一個樣式:
// Apply Style private void ApplyStyle() { const String STYLE_NAME = "PropertyBorder"; // Get the range containing all the document properties. Excel.Range rng = GetDocPropRange(); Excel.Style sty; try { sty = this.Application.ActiveWorkbook.Styles[STYLE_NAME]; } catch { sty = this.Application.ActiveWorkbook.Styles.Add(STYLE_NAME, Type.Missing); } sty.Font.Name = "Verdana"; sty.Font.Size = 12; sty.Font.Color = ColorTranslator.ToOle(Color.Blue); sty.Interior.Color = ColorTranslator.ToOle(Color.LightGray); sty.Interior.Pattern = Excel.XlPattern.xlPatternSolid; rng.Style = STYLE_NAME; rng.Columns.AutoFit(); }
工作表對象
Workbook的Sheets屬性返回該工作簿包含的所有工作表對象。這些對象可以是工作表也可以是Chart對象,下面的代碼列出了當前工作簿中的所有對象。
// Show all the workSheet name in the active workbook private void ListSheets() { int i = 0; Excel.Range rng = this.Application.get_Range("Sheets", Type.Missing); foreach (Excel.Worksheet sh in this.Application.ActiveWorkbook.Sheets) { rng.get_Offset(i, 0).Value2 = sh.Name; i = i + 1; } }
WorkSheet有一些很有用的屬性和方法:
Visible屬性:該屬性控制工作表的可見性:Visibility屬性是一個XlSheetVisibility枚舉類型,之分別為XlSheetHidden,XlSheetVeryHidden,XlSheetVisible。使用XlSheetHidden,允許用戶通過Excel界面來顯示工作表。而XlSheetVeryHidden,則需要使用代碼來顯示工作表。一般的,我們可以將一些臨時數據存放到VeryHidden的工作表中,然後使用名字管理器或者直接地址來引用。下面代碼展示了如何設置WorkSheet的Visible屬性。
// Hide Worksheet private void HideTheSheet() { ((Excel.Worksheet)this.Application.ActiveWorkbook.Sheets[1]).Visible = Excel.XlSheetVisibility.xlSheetVeryHidden; }
Add方法:Add方法允許我們創建新的工作表。
Excel.Worksheet sh = this.Application.Sheets.Add( Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Copy方法:Copy方法允許我們對工作表進行整體拷貝。拷貝的時候,可以指定新工作表的位置,是位於某一個指定的工作表之前還是之後。下面的代碼,將工作表1種的內容拷貝到第三個工作表之後的新建的工作表中。
//Copy Worksheet
((Excel.Worksheet) this.Application.ActiveWorkbook.Sheets[1]).
Copy(Type.Missing, this.Application.ActiveWorkbook.Sheets[3]);
Delete方法:該方法用於從工作簿中刪除指定的工作表。
FillAcrossSheets方法用於拷貝某個Sheet中的Range對象到該工作簿中的其他工作表中。可以指定一個區間,然後指定拷貝的方式,是拷貝數據,樣式,還是所有的都拷貝。下面的代碼演示拷貝名為Data的Range的數據及樣式到該工作簿中的所有其他工作表中。
// Fill across sheet method
this.Application.ActiveWorkbook.Sheets.FillAcrossSheets(
this.Application.get_Range("Data", Type.Missing),
Excel.XlFillWith.xlFillWithAll);
Move方法:Move方法和Copy方法類似。他將Sheet移動到某一個Sheet之前或者之後。下面的代碼將第一個Sheet也移動到最後。
// move Worksheet
Excel.Sheets shts = this.Application.ActiveWorkbook.Sheets;
((Excel.Worksheet)shts[1]).Move(Type.Missing, shts[shts.Count]);
PrintOut方法:該方法用於打印指定的對象,方法接受眾多參數,包括,需要打印的頁數,打印的份數,打印之前是否預覽,打印機名稱,是否打印到文件中,是否校對,指定打印的文件名稱等。下面的例子展示了打印方法,該方法指定了紙打印第一頁,打印兩份,打印之前預覽,並采用默認的打印機打印。
// print out method
((Excel.Worksheet)this.Application.ActiveWorkbook.Sheets[1]).
PrintOut(1, 1, 2, true, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
PrintPreview方法:打印預覽方法。
Select方法:該方法將特定的對象選中。他會是的之前選中的對象失去選中狀態。如果不想失去或者改變用戶之前的選中的對象,而僅僅指向把該對象獲得焦點,那麼可以使用Active方法。
Workbook類的方法
Workbook代表一個工作簿,他也提供了很多方法,其中一些方法用來處理一些非常特殊的場景。和前面介紹其他對象一樣,這裡僅介紹我們在開發中會經常使用到的屬性和方法。
Active方法,該方法用來激活一個工作簿,並將該工作簿中的第一個工作表選中。
// Active a workbook
((Excel._Workbook)this.Application.Workbooks[1]).Activate();
Close方法用來關閉一個工作簿,可以指定是否在關閉之前保存修改,如果該工作簿是新建的,沒有保存過,您可以指定一個文件名。下面的代碼演示了保存一個工作簿並放棄修改。
// Close a workbook without save changes
this.Application.Workbooks[1].Close(false,Type.Missing, Type.Missing);
Protect和Unprotect方法:該方法用來保護和解除保護一個工作表不被用戶添加或者修改,一般在自定義模板中用的比較多。方法可以指定密碼,以及指定是否保存文檔的結構,比如是否允許用戶自由移動裡面的工作表;指定是否工作簿的窗口需要保護。對工作簿進行保護並不能阻止用戶編輯工作表裡面的內容。 要保護工作表裡面的內容,您需要對工作表Worksheets進行保護。使用Unprotect方法傳遞密碼可以解除保護。下面的代碼演示了如何對一個工作簿進行保護。
// Protect a workbook use password
this.Application.Workbooks[1].Protect("your password", Type.Missing, Type.Missing);
Save方法,該方法用來對工作簿進行保存。如果是新建的工作簿,之前沒有進行過保存,那麼您應該調用SaveAs方法,傳入方法路徑加名稱。如果沒有保存過,調用Save方法的話,Excel會以創建時默認的工作簿名稱以及在用戶文檔目錄下保存文件。
// Save all open workbooks.
foreach (Excel.Workbook wb in this.Application.Workbooks)
{
wb.Save();
}
SaveAs方法,該方法比Save方法更復雜,能夠允許保存指定的工作簿,能夠設置工作簿的名稱,文件格式,讀寫模式等。下面的代碼演示了保存當前的工作表到一個特定的目錄,格式為xml。需要注意的是,在調用SaveAs方法的時候,可能需要將Application.DisplayAlerts屬性設置為false,因為在另存為某些其他格式的時候,可能會彈出交互界面需要進行一些其他的設置。比如說,將工作簿保存為XML格式的時候,Excel會提醒你會不會將工作簿中的VBA保存到XML格式中去。如果將Application.DisplayAlerts屬性設置為false,則不會彈出提示框。
// Save as the active workbook
this.Application.ActiveWorkbook.SaveAs("C:\\MyWorkbook.xml",
Excel.XlFileFormat.xlXMLSpreadsheet, Type.Missing,
Type.Missing, Type.Missing, Type.Missing,
Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing);
SaveCopyAs方法,該方法拷貝並保存某個文件的一個副本,部隊當前在內存中打開的工作表產生影響。通常在我們需要對文件進行備份的時候很有用。但是需要注意的是,在保存或者拷貝的時候,如果沒有設置Application.DisplayAlerts為false的時候,當Excel彈出保存提示框的時候,如果您點擊取消,那麼代碼會拋出運行時異常。
// save a copy of the activeworkbooks
this.Application.ActiveWorkbook.SaveCopyAs("C:\\Test.xls");
四 Worksheet類
雖然Worksheet類也提供了大量的屬性方法和事件,但是大部分的屬性和方法和Application和Workbook類現相似,這部分重點介紹Worksheet中之前的對象中沒有講到過的,且經常會用到的屬性和方法。
沒有Sheet類
雖然Workbook對象有一個Sheets集合類,但是並不存在一個所謂的Sheet類,Sheets集合中的類要不是Worksheet元素,要麼是Chart對象。可以認為Worksheet和Chart對象是Sheet類對象的實例,雖然公共的對象中並沒有看到有Sheet類。
文檔保護
通常Excel會對工作簿或者工作表提供一些保護特性,以不允許用戶修改工作表中的隊形。一旦我們開啟了對工作表進行保護,除非進行取消保護,否則用戶不能編輯或者修改工作表。在用戶界面上,您可以通過菜單審閱-> 保護工作表菜單開啟,我們可以設置保護密碼。默認情況下,會對所有的工作表中的單元格進行保護。如果您要對特定范圍的單元格進行保護,可能需要使用 審閱->允許用戶編輯區域實現。
在代碼中,我們可以通過調用Worksheet的Protect方法來實現,該方法有很多參數進行配置。其方法簽名如下:
// Worksheet protect method signature WorksheetObject.Protect(Password, DrawingObjects, Contents, Scenarios, UserInterfaceOnly, AllowFormattingCells, AllowFormattingColumns, AllowFormattingRows, AllowInsertingColumns, AllowInsertingRows, AllowInsertingHyperlinks, AllowDeletingColumns, AllowDeletingRows, AllowSorting, AllowFiltering, AllowUsingPivotTables);
Password參數,指定大小寫敏感的保護密碼,如果不設置,那麼任何人都可以接觸保護。
DrawingObject參數,如果為true,則保護工作表內的圖形對象,默認為false。
Contents參數,如果為True則保護工作表中的所有單元格,默認為True,一般地,不需要進行修改。
Scenarios參數,如果為True,則保護工作表內的方案,默認為True。
UserInterfaceOnly,如果為True,則允許從代碼中修改保護,而不是從用戶界面上。默認值為False,即不能通過代碼或者用戶界面來對受保護的工作表進行修改。通常該修改只能對當前的會話有效。如果想要每一次都能對工作表進行操作,那麼在每一次打開工作表的時候都需要通過代碼進行設置。
AllowFormattingCells參數,指定對工作表中對象的格式化權限。通常默認情況下,這些屬性都是False。
下面是一個使用Protect方法對工作表進行保護的例子,該方法設置了保護密碼,並僅允許對數據進行排序:
((Excel.Worksheet)this.Application.Sheets[1]).Protect( "MyPassword", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing);
要取消保護,直接調用unprotect方法即可。
Object屬性
Worksheet對象還有幾個返回Object類型的屬性。
Comments:在Excel中,我們可以在單元格中添加注釋。我們可以通過Range對象的AddComment方法來實現:
下面的代碼演示了如果注釋存在,刪除,然後添加注釋。後面演示了如何通過代碼演示和現實所有注釋:
Excel.Range rng = this.Application.get_Range("Date", Type.Missing); if (rng.Comment != null) { rng.Comment.Delete(); } rng.AddComment("Comment added " + DateTime.Now); // Display all the comments: ShowOrHideComments(true);
Worksheet類提供了Comments屬性,該屬性返回一個Comments對象,該對象是一個集合,您可以便利該集合中的對象,Comment類提供的屬性很少,用的最多的是Visible屬性,用來顯示或者隱藏注釋;在一個就是Delete屬性,用來刪除注釋,最後Text屬性可以用來添加或者修改現有的注釋。
添加完成注釋之後,我們可能希望在工作表中顯示注釋。下面就是在當前活動工作表中顯示或者隱藏注釋的代碼。
private void ShowOrHideComments(bool show) { // Show or hide all the comments: Excel.Worksheet ws = (Excel.Worksheet)this.Application.Sheets["Worksheet Class"]; for (int i = 1; i <= ws.Comments.Count; i++) { ws.Comments[i].Visible = show; } }
五 Range對象
Range對象是在Excel開發中用的最多的隊形,在我們對Excel進行操作之前,我們需要獲取我們要進行操作的對象。幾乎我們對工作表中的內容操作都會涉及到Range對象。Range對象是對工作表中內容的一種抽象,他可以表示一個單元格,一行數據,一列數據,一個選擇的單元格區間,或者在不同工作表中的一系列對象。下圖是Range的簡要對象模型圖:
下面就從三個方面介紹Range對象
在代碼中使用Range對象
在代碼中對Range對象進行操作
l通過Range對象來完成一些功能
對選中對象進行操作
雖然可以對當前選中的對象進行各種屬性和行為的修改,但是最好避免這樣做。Excel中的選中對象代表用戶的選擇。如果我們再代碼中進行修改的話,會導致用戶對當前選中的對象失去控制。首要准則是,只有當你試圖更改用戶的選擇區域時,才去調用Range對象的Select方法。作為一個開發者,我們不應該因為該方法比較簡單就去使用它。如果我們只想對這些用戶選中的范圍進行操作的話,通常有其他更好的選擇。避免調用Select方法不僅能夠使得我們的代碼運行的更快,而且也能讓用戶更高興使用我們的產品。
下面的代碼用來清除用戶當前單元格中的內容。
// clear select content
this.Application.ActiveCell.CurrentRegion.Select();
((Excel.Range)this.Application.Selection).ClearContents();
上面的代碼會使得用戶當前的選擇區域丟失。如果之前只有一個單元格被選中,那麼在運行上面的代碼之後,整個連續的單元格都回被選中了。除非我們的目的就是這樣,要選擇整個Range返回內的單元格,一個更好的方法可能是:
this.Application.ActiveCell.CurrentRegion.ClearContents();
之前的代碼通常是使用宏錄制獲得的,一般情況下,宏錄制其會錄制好用戶的選擇,然後對用戶的選擇進行修改。當我們對單個單元格或者多個單元格進行操作的時候,一般應該使用Range對象來表示我們操作的對象,而不是通過修改選中的對象來進行操作。如果確實需要修改用戶的選擇對象,可以使用Range.Select 方法。
在代碼中引用Range對象
在開發中,Range對象的使用范圍非常廣泛和靈活。有時候Range對象表示單個的對象,有時候也表示一個集合。即使一個Range對象只表示一個對象,它也有Item和Count屬性,所以我們要注意在有些情況下該如何更好地使用Range對象。
Application 的ActiveCell屬性,該屬性返回一個Range對象,表示當前活動的單元格:
Excel.Worksheet ws = (Excel.Worksheet)this.Application.Worksheets[1];
Excel.Range rng1, rng2;
rng1 = this.Application.ActiveCell;
通過其他對象的get_Range方法傳入地址獲取。
rng = ws.get_Range("A1", Type.Missing);
rng = ws.get_Range("A1:B12", Type.Missing);
通過Worksheet的Cells屬性,傳入行列號獲取:
rng = (Excel.Range)ws.Cells[1, 1];
指定Range對象的區域邊界; 可以通過range對象的Cells,Rows和Columns屬性來返回另外一個Range對象。
rng = ws.get_Range("A1", "C5");
rng = ws.get_Range("A1", "C5").Cells;
rng = ws.get_Range("A1", "C5").Rows;
rng = ws.get_Range("A1", "C5").Columns;
通過名稱管理器引用Range對象
rng = this.Application.get_Range("SomeRangeName", Type.Missing);
通過引用行或者列來獲取Range對象
rng = (Excel.Range)ws.Rows[1, Type.Missing];
rng = (Excel.Range)ws.Rows["1:3", Type.Missing];
rng = (Excel.Range)ws.Columns[3, Type.Missing];
通過對兩個Range對象的求並集,返回新的Range對象
// C# rng = this.Application.get_Range("A1:D4, F2:G5", Type.Missing); // You can also use the Application object's Union // method to retrieve the intersection of two ranges, but this // is far more effort in C#: rng1 = this.Application.get_Range("A1", "D4"); rng2 = this.Application.get_Range("F2", "G5"); // Note that the Union method requires you to supply thirty // parameters: rng = this.Application.Union(rng1, rng2, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
通過對兩個Range對象的求交集,返回新的Range對象
rng = this.Application.get_Range("A1:D16 B2:F14", Type.Missing); // You can also use the Application object's Intersect // method to retrieve the intersection of two ranges. Note // that the Intersect method requires you to pass 30 parameters: rng1 = this.Application.get_Range("A1", "D16"); rng2 = this.Application.get_Range("B2", "F14"); rng = this.Application.Intersect(rng1, rng2, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
通過對原始Range對象的取偏移,獲取新的Range對象。對原始Range對象取便宜實用Offset函數實現
rng = (Excel.Range)ws.Cells[1, 1]; for (int i = 1; i <= 5; i++) { rng.get_Offset(i, 0).Value2 = i.ToString(); }
通過Range對象的End屬性,傳入XlDirection參數,可以獲取四個方向的邊界的Range對象
Excel.Range rngLeft, rngRight, rngUp, rngDown; rng = (Excel.Range)this.Application.Selection; // Note that the Range.End property is parameterized, so // C# developers cannot retrieve it. You must call the // get_End method, instead: // E3 rngRight = rng.get_End(Excel.XlDirection.xlToRight); // A3 rngLeft = rng.get_End(Excel.XlDirection.xlToLeft); // C1 rngUp = rng.get_End(Excel.XlDirection.xlUp); // C5 rngDown = rng.get_End(Excel.XlDirection.xlDown);
通過EntireRow和EntireColumn屬性來獲取包含某一個特定Range對象的行和列的Range對象
操作Range對象
獲得了Range對象之後,我們就可以對Range對象進行各種操作了。
自動填充 Range對象的AutoFill方法是的我們可以自動填充某一個區域。大多數的自動填充用於填充連續遞增或者遞減的值。我們可以設置遞增的類型及方式。這些都通過XlAutoFillType 枚舉類型來實現 (xlFillDays, xlFillFormats, xlFillSeries, xlFillWeekdays, xlGrowthTrend, xlFillCopy, xlFillDefault, xlFillMonths, xlFillValues, xlFillYears, or xlLinearTrend)。如果不設置自動填充類型,則默認為XlFillDefault,Excel會判斷區域的數據類型采用默認的自動填充方式填充。下面的代碼演示了如何自動填充區域。
private void AutoFill() { Excel.Range rng = this.Application.get_Range("B1", Type.Missing); rng.AutoFill(this.Application.get_Range("B1:B5", Type.Missing), Excel.XlAutoFillType.xlFillDays); rng = this.Application.get_Range("C1", Type.Missing); rng.AutoFill(this.Application.get_Range("C1:C5", Type.Missing), Excel.XlAutoFillType.xlFillMonths); rng = this.Application.get_Range("D1", Type.Missing); rng.AutoFill(this.Application.get_Range("D1:D5", Type.Missing), Excel.XlAutoFillType.xlFillYears); rng = this.Application.get_Range("E1:E2", Type.Missing); rng.AutoFill(this.Application.get_Range("E1:E5", Type.Missing), Excel.XlAutoFillType.xlFillSeries); }
對Range對象的查找 Range對象的查找方法允許我們在Range范圍內查找特定的字符串。這個功能我們可以通過Range.Find方法實現。
Find方法有很多個參數,下面的代碼演示了如何使用Find方法:
private void DemoFind() { Excel.Range rng = this.Application. get_Range("Fruits", Type.Missing); Excel.Range rngFound; // Keep track of the first range you find. Excel.Range rngFoundFirst = null; // You should specify all these parameters // every time you call this method, since they // can be overriden in the user interface. rngFound = rng.Find("apples", Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, Type.Missing, Type.Missing); while (rngFound != null) { if (rngFoundFirst == null) { rngFoundFirst = rngFound; } else if (GetAddress(rngFound) == GetAddress(rngFoundFirst)) { break; } rngFound.Font.Color = ColorTranslator.ToOle(Color.Red); rngFound.Font.Bold = true; rngFound = rng.FindNext(rngFound); } }
對Range對象排序 和Find方法一樣,Range對象的Sort方法也有很多參數來幫助我們完成自定義排序
下面的代碼演示了自定義排序:
private void DemoSort() { Excel.Range rng = this.Application. get_Range("Fruits", Type.Missing); rng.Sort(rng.Columns[1, Type.Missing], Excel.XlSortOrder.xlAscending, rng.Columns[2, Type.Missing], Type.Missing, Excel.XlSortOrder.xlAscending, Type.Missing, Excel.XlSortOrder.xlAscending, Excel.XlYesNoGuess.xlNo, Type.Missing, Type.Missing, Excel.XlSortOrientation.xlSortColumns, Excel.XlSortMethod.xlPinYin, Excel.XlSortDataOption.xlSortNormal, Excel.XlSortDataOption.xlSortNormal, Excel.XlSortDataOption.xlSortNormal); }
六 結語
要進行Excel開發,繞不開對Excel中對象模型的理解, 本文簡要介紹了Excel中的對象模型,介紹了這些對象中比較重要的幾個對象,Application,Workbook,Worksheet,Range對象,這些對象不論在何種Excel開發方式中,只要需要對Excel進行交互,都會使用的到,本文介紹了這四個對象中的一些常用的屬性,方法及事件。他們之間有很多對象都有相同的屬性方法或者事件,這篇文章主要是想讓大家對Excel對象模型有一個簡單的認識,具體全部的對象模型,大家可以直接到MSDN或者Google上面去查找,下一篇文章將會介紹Excel中比較核心的功能:自定義函數。
希望本文對大家理解Excel對象模型有所幫助。
作者: yangecnu(yangecnu's Blog on 博客園)
出處:http://www.cnblogs.com/yangecnu/