Java - Use odfdom library to create ods file

之前曾經提到利用JODconverter來進行xls檔案轉換至ods檔案,而在這邊主要是說明,如何利

odfdom library來讀取ods template file並且做基本的處理,同時也會提到style的用法,如

粗體、縮排等設定,如此一來即可建構出一基本的ods試算表。

使用的版本為:odfdom-java-0.8.7.jar

首先,載入一自訂的資料檔,如下:

資工系,男,21,小彬
經濟系,女,19,小花
建築系,男,23,小勇
國貿系,男,21,小金
中文系,女,20,小琪
歷史系,男,18,小強
財金系,女,24,小雯
畜產系,男,23,小維
哲學系,男,25,小茂
外文系,女,20,小琳

  1. private List<Student> studentList;
  2. public static void main(String[] args) {
  3. // TODO Auto-generated method stub
  4. new SimpleOds("menu.txt");
  5. }
  6. public SimpleOds(String file){
  7. loadStudentMenu(new File(file));
  8. OutputOdsReport();
  9. }
  10. public void loadStudentMenu(File f){
  11. studentList = new ArrayList<Student>();
  12. Random rmd = new Random();
  13. try (BufferedReader br = new BufferedReader(new FileReader(f))){
  14. String data = null;
  15. System.out.println("學生名單如下:");
  16. while((data = br.readLine()) != null){
  17. Student p = new Student(data);
  18. p.setScore(rmd.nextInt(100));
  19. System.out.println(p);
  20. studentList.add(p);
  21. }
  22. } catch (FileNotFoundException e) {
  23. // TODO Auto-generated catch block
  24. System.out.println("指定檔案不存在!!");
  25. } catch(IOException e){
  26. System.out.println("IOException");
  27. }
  28. }

這邊做的事情很單純,載入一txt檔案,並將各欄位的資料組成一Student Bean List。

緊接著,初始化讀入Ods樣板檔及相關建立ods file變數


  1. SimpleDateFormat date_convert = new SimpleDateFormat("yyyyMMddHHmmss");
  2. String inputFileName;
  3. String outputFileName;
  4. OdfSpreadsheetDocument outputDocument; //workbook
  5. OdfContentDom contentDom; // the document object model for content.xml
  6. OdfOfficeAutomaticStyles contentAutoStyles;
  7. public void OutputOdsReport(){
  8. inputFileName = "students.ods";
  9. outputFileName = "student_"+date_convert.format(
  10. new java.sql.Date(System.currentTimeMillis()))+".ods";
  11. setupOutputDocument(inputFileName);
  12. if (outputDocument != null) {
  13. processInputDocument();
  14. saveOutputDocument();
  15. }
  16. }
  17. public void setupOutputDocument(String inputFile) {
  18. try {
  19. //Creates an empty spreadsheet document.
  20. outputDocument = OdfSpreadsheetDocument.loadDocument(inputFile);
  21. contentDom = outputDocument.getContentDom();
  22. contentAutoStyles = contentDom.getOrCreateAutomaticStyles();
  23. } catch (Exception e) {
  24. System.err.println("Unable to create output file.");
  25. System.err.println(e.getMessage());
  26. outputDocument = null;
  27. }
  28. }

outputDocument => 猶如Excel的workbook,可以取得特定的sheet及輸出一新的ods

contentAutoStyles => 取得當下cell的style element,此style element跟style設定有關,如

粗體、縮排、文字顏色...等,簡單來說每一個cell都會有一個style name,如果cell的style name

一樣的話,若該style name被設定也將影響到另一cell本身。

再來則是做set value to cell的動作,如下:
  1. public void processInputDocument(){
  2. OdfTable sheet = outputDocument.getTableList().get(0); //取sheet1
  3. int startRow = 3;
  4. int indent = 0;
  5. boolean isBold = false;
  6. String color = null;
  7. for(int i = 0 ; i < studentList.size() ; i++){
  8. Student bean = studentList.get(i);
  9. indent = (bean.getSex().equals("女")) ? 2 : 1;
  10. isBold = (bean.getAge() > 20) ? true : false;
  11. color = (bean.getScore() <= 60) ? "#FF0000" : null;
  12. setValue(bean.getUnit(), startRow, 0, sheet, 0, false, "center", "center", null);
  13. setValue(bean.getSex(), startRow, 1, sheet, indent, false, "left", "center", null);
  14. setValue(bean.getAge(), startRow, 2, sheet, 0, isBold, "center", "center", null);
  15. setValue(bean.getName(), startRow, 3, sheet, 0, false, "center", "center", null);
  16. setValue(bean.getScore(),startRow, 4, sheet, 0, false, "center", "center", color);
  17. startRow++;
  18. }
  19. }
  20. public void setValue(Object value, int row, int col, OdfTable sheet, Integer indentation, Boolean isBOLD, String va,String ha, String color) {
  21. row-=1;
  22. OdfTableCell cell = sheet.getCellByPosition(col, row);
  23. cell.setCellBackgroundColor(Color.WHITE);
  24. String styleName = cell.getStyleName();
  25. OdfStyle styleElement = contentAutoStyles.getStyle(styleName, OdfStyleFamily.TableCell);
  26. //水平排列
  27. if(va != null){
  28. cell.setHorizontalAlignment(va);
  29. }
  30. //垂直排列
  31. if(ha != null){
  32. cell.setVerticalAlignment(ha);
  33. }
  34. //粗體
  35. if(isBOLD != null && isBOLD.booleanValue()){
  36. setFontWeight(styleElement, "bold");
  37. }else{
  38. setFontWeight(styleElement, "");
  39. }
  40. //縮排
  41. if(indentation != null){
  42. setIndentation(styleElement, String.valueOf(0.353*indentation)+" cm");
  43. }
  44. //文字顏色
  45. if(color != null){
  46. setTextColor(styleElement, color);
  47. }else{
  48. setTextColor(styleElement, "#000000");
  49. }
  50. //set value
  51. if(value instanceof java.lang.String || value instanceof java.lang.Integer){
  52. cell.setStringValue(String.valueOf(value));
  53. }else if(value instanceof java.lang.Double){
  54. cell.setDoubleValue(Double.parseDouble(""+value));
  55. }
  56. //System.out.println(isBOLD.booleanValue()+","+row+","+","+col+","+styleElement);
  57. }

上面的設定值得注意的地方是,cell.setCellBackgroundColor(Color.WHITE);主要的目的

是針對各個cell產生其各自的style name(相當於ID),避免如該欄的各cell如果style name都

一樣的話,改變其一的設定會影響到其它欄,猶如牽一髮而動全身。

setValue method的各參數將指定該cell的一些設定,如下:

  1. //粗體
  2. void setFontWeight(OdfStyleBase style, String value) {
  3. style.setProperty(OdfTextProperties.FontWeight, value);
  4. style.setProperty(OdfTextProperties.FontWeightAsian, value);
  5. style.setProperty(OdfTextProperties.FontWeightComplex, value);
  6. }
  7. //縮排
  8. void setIndentation(OdfStyleBase style, String value) {
  9. style.setProperty(OdfParagraphProperties.MarginLeft, value);
  10. }
  11. //文字顏色
  12. void setTextColor(OdfStyleBase style, String value) {
  13. style.setProperty(OdfTextProperties.Color, value);
  14. }

最後,則是做輸出檔案的動作
  1. public void saveOutputDocument(){
  2. try {
  3. outputDocument.save(outputFileName);
  4. } catch (Exception e) {
  5. System.err.println("Unable to save document.");
  6. System.err.println(e.getMessage());
  7. } finally{
  8. if(outputDocument != null)outputDocument.close();
  9. }
  10. }

留言