實現用戶自定義Excel模板

需求背景: 在Excel的實際使用過程當中,動態生成報表、導出報表等都是最終用戶經常使用的功能,使用常規的方式針對模板中具體的每一個單元格編程,動態的插入數據庫中數據到Excel報表模板的每個單元格,就能夠實現動態報表功能。可是不少時候用戶報表的樣式不是一成不變的,如某公司2015年的產品報表但願在2014年的產品報表基礎上,進行一些報表文本顏色、數據顯示位置等方面的調整,2014年報表模板中「合計」數據原來位於單元格:A50,調整後,2015年報表模板中的「合計」數據單元格位於:A80。因爲生成報表的程序代碼是針對報表模板中的每個具體的單元格編程的,模板中數據項所在單元格的位置發生了改變,就須要同步修改填充數據的程序代碼,原來給A50單元格填充數據的代碼須要修改成操做A80單元格。如果每次Excel模板的調整都須要開發人員從新修改代碼來實現的話,那就是一項永遠不會完成的工做了。數據庫

編輯Excel模板:定義名稱

定義名稱:Excel中有一個特別好的工具就是「定義名稱」,顧名思義,就是爲一個單元格或者區域定義一個名稱,這樣的話,咱們在以後的程序控制時能夠很方便的用所定義的名稱進行代碼編寫。編程

下面以給一個區域定義名稱爲例介紹一下Excel定義名稱的操做步驟:工具

  1. 在本地磁盤上打開一個Excel文件模板,選中須要填充數據的單元格區域,如B4:F13,以下圖所示;

5.4

  1. 在選中的單元格區域上,「右擊→定義名稱」(或者點擊Office工具欄上的「公式→定義名稱「),在名稱輸入框中輸入該區域的名稱,如命名爲「report」,點擊「肯定」按鈕便可。以下圖所示。

5.5

5.6

  1. 如果須要刪除、修改定義好的單元格區域,可點擊Office工具欄上的「公式→名稱管理器「來對名稱進行管理,以下圖所示。

5.7

PageOffice操做Excel模板中定義了名稱的單元格和區域

在PageOffice開發平臺下,爲了更好的在Excel模板中動態的、靈活的填充數據,專門開發了相應的程序接口,提供了完美解決上述問題的方法——openCellByDefinedName()和openTableByDefinedName()。在代碼實現過程當中,經過靈活的運用這兩個方法,便可完美的實如今不修改代碼的狀況下,知足最終用戶自定義修改Excel模板的需求。spa

1、openCellByDefinedName和openTableByDefinedName的定義說明code

這兩個方法用來實現操做用戶自定義Excel模板中的。其中openCellByDefinedName()方法用來打開Excel中具備指定名稱的單元格,並返回 Cell 對象。openTableByDefinedName()方法用來打開具備指定名稱的單元格區域(通常爲連續的多個單元格,在PageOffice的概念裏稱這塊區域爲一個Table),並返回 Table 對象。對象

Java方法:blog

openCellByDefinedName(String definedName);
    openTableByDefinedName(String definedName, int rowCount, int colCount, boolean autoIncrease);

ASP.NET方法:接口

public Cell OpenCellByDefinedName(
	    string DefinedName
    )
    public Table OpenTableByDefinedName(
	    string DefinedName,
	    int RowCount,
    	int ColCount,
	    bool AutoIncrease
    )

2、編寫代碼給Excel模板中的表格填充數據開發

Java部分代碼以下:文檔

Workbook workBook = new Workbook();
	Sheet sheet = workBook.openSheet("Sheet1");
	//定義Table對象,參數「report」就是Excel模板中定義的單元格區域的名稱
	Table table = sheet.openTableByDefinedName("report", 10, 5, false);
	//給區域中的單元格賦值
    table.getDataFields().get(0).setValue("輪胎");
    table.getDataFields().get(1).setValue("100");
    table.getDataFields().get(2).setValue("120");
    table.getDataFields().get(3).setValue("500");
    table.getDataFields().get(4).setValue("120%");
    table.nextRow(); //若是循環填充數據的話,執行下一行
   	table.close();
    
    //定義單元格對象,參數「year」就是Excel模板中定義的單元格的名稱
    Cell cellYear = sheet.openCellByDefinedName("year");
    Calendar c=new GregorianCalendar();
	int year=c.get(Calendar.YEAR);//獲取年份 
    cellYear.setValue(year + "年");
    Cell cellName = sheet.openCellByDefinedName("name");
    cellName.setValue("張三");
	
	poCtrl1.setWriter(workBook);
    ……

ASP.NET部分代碼以下:

PageOffice.ExcelWriter.Workbook wk = new PageOffice.ExcelWriter.Workbook();
    PageOffice.ExcelWriter.Sheet sheet = wk.OpenSheet("Sheet1");
    //定義Table對象,參數「report」就是Excel模板中定義的單元格區域的名稱
    PageOffice.ExcelWriter.Table table = sheet.OpenTableByDefinedName("report", 10, 5, false);
    //給區域中的單元格賦值
    table.DataFields[0].Value = "輪胎";
    table.DataFields[1].Value = "100";
    table.DataFields[2].Value = "120";
    table.DataFields[3].Value = "500";
    table.DataFields[4].Value = "120%";
    table.NextRow();//若是循環填充數據的話,執行下一行
    table.Close();
    
    //定義單元格對象,參數「year」就是Excel模板中定義的單元格的名稱
    PageOffice.ExcelWriter.Cell cellYear = sheet.OpenCellByDefinedName("year");
    cellYear.Value="2015年";
    PageOffice.ExcelWriter.Cell cellName = sheet.OpenCellByDefinedName("name");
    cellName.Value = "張三";
    
    PageOfficeCtrl1.SetWriter(wk);// 注意不要忘記此代碼,若是缺乏此句代碼,不會賦值成功。
    ……

在填充數據的代碼不作任何修改的狀況下,打開兩個不一樣的Excel模板並填充數據的效果:

  1. 打開模板一併填充數據,實現的效果如圖所示

5.8

  1. 打開模板二並填充數據,實現的效果如圖10所示:

5.9

能夠看出在不需修改代碼的狀況下,用戶能夠根據實際需求自行定義Excel模板。只要Excel模板中有代碼中所涉及到的定義名稱(如「report」、「year」、「name」),那麼不管定義了該名稱的單元格區域的位置、大小怎麼變化,程序都會自動在變化後的位置填充數據。而若是程序代碼中涉及到的定義名稱在Excel模板中不存在的話,那麼對該對象的全部操做將被自動忽略,打開的Excel文檔中也不會再顯示相應的信息。

優點總結

openCellByDefinedName()和openTableByDefinedName()方法相比於openCell()和openTable()方法的具體優點在於:

  1. 能夠避免同一個Excel工做薄中有多個表格時,上面的表格數據行增加後與下面的表格數據出現互相覆蓋的問題。
    假如在一個Excel模板的同一個工做薄中,使用openTable(rangeAddress)方法打開兩個不一樣的Table,分別爲Table1(數據填充範圍:第4-7行,行數:4行)、Table2(數據填充範圍:第13-16行)。而要動態填充到Table1裏的實際數據行數爲12行,超過了指定的單元格區域行數,且Table1設置了默認自動擴展單元格行數到實際大小,而且給新的單元格數據行應用 RangeAddress 指定的單元格區域的格式,那麼數據填充完後,Table1的實際填充範圍應該是第4-15行;然而因爲Table2的起始填充位置是不變的,仍是從第13行開始填充,這樣一來,Table2填充的數據就會覆蓋Table1第13-15行的數據,即發生數據重疊覆蓋的現象。

5.1

5.2

而若是使用openTableByDefinedName()來分別打開這兩個Table,且設置表格也會按實際數據行數自動擴展,當Table1自動擴展後數據行數爲12行,填充範圍爲第4-15行時,Table2的起始位置將再也不是固定不變的,Table2的起始位置由原來的第13行變成了第21行,填充範圍爲第21-24行。這樣一來,先後兩個Table的數據就不會發生重疊覆蓋的現象了,填充數據後的效果如圖3所示。

5.3

  1. 當Excel模板數據內容不變,樣式(數據的位置、大小等)改變時, openCell()和openTable()必需要修改其方法中的參數,即操做的單元格和Table對象,不然顯示或提交的數據時就可能發生錯亂;而openCellByDefinedName()和openTableByDefinedName()方法只要提早在模板中定義好要填充數據的單元格區域的名稱,那麼不管數據的位置、大小怎麼變化,都不需修改代碼就能將數據準確填充到相應的位置,並準確獲取到提交的數據。

  2. 還能夠實現用戶可根據實際狀況和實際需求自行便捷、簡單地定義Excel模板,而無需每次更改模板時都要聯繫程序的開發者更改代碼。PageOffice開發平臺以其更好的靈活性和適應性,充分的知足了最終用戶對系統功能的要求,極大的減小了程序開發者對系統後期的維護量。

詳細請參考PageOffice開發包中Samples4示例: 2、3三、給Excel模板中定義了名稱的一塊區域賦值(專業版、企業版)

相關文章
相關標籤/搜索