Apache POI là một thư viện nguồn mở phổ biến được sử dụng để đọc, viết và thao tác với các tệp MS Office và Open Office bằng cách sử dụng mã Java. Thư viện là một trong nhiều sản phẩm mã nguồn mở được duy trì bởi Apache Software Foundation (ASF) đã đóng góp cho cộng đồng Java. Thư viện chứa các lớp và phương pháp để giải mã các định dạng tệp dựa trên các tiêu chuẩn Open Office XML và Microsoft OLE2. Mặc dù thư viện có khả năng thao tác với các tệp Word, bảng tính Excel và PowerPoint, nhưng bài viết này chủ yếu tập trung vào các tài liệu bảng tính, chỉ để trình bày ngắn gọn.
Tìm hiểu JAVA và Bắt đầu Dùng thử Miễn phí ngay hôm nay!
Thư viện Apache POI
Thật thú vị, trong cái tên Apache POI, POI là viết tắt của “Poor Obfuscation Exhibition” và mục tiêu của thư viện là cung cấp các API Java để thao tác các định dạng tệp khác nhau dựa trên các tiêu chuẩn Office Open XML (OOXML) và định dạng Tài liệu tổng hợp OLE 2 của Microsoft (OLE2). Nói tóm lại, điều này cho phép một người đọc và ghi các tệp MS Excel, MS Word và MS PowerPoint bằng cách sử dụng mã Java. Hầu hết các tệp Microsoft Office — chẳng hạn như định dạng tệp dựa trên API tuần tự hóa XLS, DOC, PPT và MFC — đều dựa trên tiêu chuẩn OLE2. Về cơ bản, OLE là một kỹ thuật độc quyền được phát triển của Microsoft và cung cấp định dạng để liên kết các đối tượng và nhúng các đối tượng trong tài liệu vùng chứa. Định dạng đầu tiên được gọi là định dạng OLE1.0 trong đó đối tượng được liên kết và dữ liệu đối tượng nhúng được trình bày dưới dạng chuỗi byte trong tài liệu vùng chứa. Phiên bản thứ hai, định dạng OLE2.0, sử dụng Công nghệ tệp tổng hợp OLE (MS-CFB) trong đó đối tượng được liên kết hoặc dữ liệu đối tượng nhúng được chứa trong bộ lưu trữ này dưới dạng đối tượng Luồng tệp tổng hợp OLE. Tham khảo Định dạng OLE1.0 và OLE2.0 để biết thêm chi tiết về điều này. Thư viện Apache POI cung cấp các API thư viện cho hệ thống tệp OLE2 được gọi là POIFS và Thuộc tính tài liệu OLE2 được gọi là HPSF.
Các thành phần POI của Apache
Thư viện Apache POI cung cấp các lớp và phương pháp để làm việc với Tài liệu tổng hợp OLE2 của MS Office. Dưới đây là tổng quan ngắn gọn về những cái thường được sử dụng nhất:
- POIFS đối với Tài liệu OLE2:POIFS là viết tắt của Hệ thống tệp triển khai giải mã kém . Đây là phần tử POI cơ bản được triển khai trong thư viện để chuyển Tài liệu tổng hợp OLE2. Nó hỗ trợ chức năng đọc và ghi cho định dạng Microsoft Office nhị phân không phải XML. Tất cả các API của thư viện POI đều được xây dựng dựa trên điều này.
- HSSF và XSSF:HSSF là viết tắt của Định dạng bảng tính kinh khủng . Nó là một cổng triển khai Java cho định dạng tệp Excel 97 hoặc cho các tệp .xls. XSSF là viết tắt của Định dạng bảng tính XML và nó là một cổng cho định dạng tệp OOXML hoặc định dạng tệp .xlsx.
- HWPF và XWPF:HWPF là viết tắt của Định dạng bộ xử lý văn bản khủng khiếp . Đây là một cổng chỉ đọc giới hạn cho định dạng tệp Word 6 hoặc Word 95 cũ hơn. XWPF là viết tắt của Định dạng bộ xử lý văn bản XML . Nó là một cổng triển khai Java cho định dạng tệp Word 2007 .docx. Cả hai cách triển khai đều hỗ trợ chức năng hạn chế.
- HSLF và XSLF:HSLF là viết tắt của Định dạng bố cục trang trình bày kinh khủng . XSLF là viết tắt của Định dạng bố cục trang trình bày XML . Cả hai đều cung cấp khả năng đọc, ghi, tạo và sửa đổi bản trình bày PowerPoint trong khi HSLF hỗ trợ định dạng PowerPoint 97 và XSLF hỗ trợ các phiên bản mới hơn.
- HPSF :HPSF là viết tắt của Định dạng Tập hợp Thuộc tính Kinh khủng . Nó đặc biệt được sử dụng để làm việc với các thuộc tính tài liệu như đặt tiêu đề, danh mục, tác giả, ngày sửa đổi, v.v. của tài liệu
- HDGF và XDGF:HDGF là viết tắt của Định dạng sơ đồ kinh khủng . Thành phần này chứa các lớp để làm việc với định dạng tệp nhị phân Visio. Nó cung cấp các API cấp thấp, chỉ đọc để truy cập vào Tài liệu Visio và các tệp VSD. XDGF là viết tắt của Định dạng sơ đồ XML . Nó dành cho định dạng tệp Visio XML hoặc các tệp VSDX.
- HPBF :HPBF là viết tắt của Định dạng nhà xuất bản kinh khủng . Đây là một cổng Java hạn chế để hoạt động với định dạng tệp MS Publisher.
Các từ viết tắt nghe có vẻ hài hước vì các hệ thống tệp này được cho là đã bị đóng và Microsoft đã cố gắng hết sức để làm xáo trộn mã để chúng không chỉ khó hiểu mà còn khó dịch ngược. Tuy nhiên, các nhà phát triển tại Apache đã hack nó một cách dễ dàng và đảo ngược thiết kế thành công. Có lẽ, như một dấu hiệu của sự vui mừng hoặc lên án hoàn toàn đối với hệ thống khép kín, họ đã đặt tên cho chúng một cách hài hước như vậy.
Làm việc với các tệp HSSF và XSSF
Các thành phần HSSF và XSSF của thư viện Apache cung cấp ba mô hình truy cập tài liệu bảng tính theo Tài liệu HSSF và XSSF. Đó là:
- Cấu trúc cấp thấp cho các nhu cầu đặc biệt
- API mô hình sự kiện để truy cập chỉ đọc vào tài liệu Excel
- Các API mô hình chung để tạo, đọc và sửa đổi các tệp Excel
Các API mô hình sự kiện hạn chế chỉ có thể được sử dụng để đọc dữ liệu bảng tính. Các API này nằm trong org.apache.poi.hssf.eventusermodel gói và org.apache.poi.xssf.eventusermodel gói, trong đó gói đầu tiên được sử dụng để đọc dữ liệu từ .xls định dạng tệp và định dạng thứ hai được sử dụng để đọc dữ liệu từ .xlsx định dạng tệp.
Mô hình usermodel linh hoạt hơn và dễ sử dụng hơn nhiều; nó có thể đọc, viết, tạo và sửa đổi tài liệu bảng tính Excel. Tuy nhiên, nó có dung lượng bộ nhớ cao hơn nhiều so với mô hình sự kiện cấp thấp.
Ngoài ra, việc truy cập và thao tác định dạng tệp dựa trên OOXML mới hơn với XSSF có dung lượng bộ nhớ cao hơn nhiều so với các tệp nhị phân được hỗ trợ HSSF cũ.
Từ POI 3.5 trở đi, mô hình HSSF và XSSF đã được đưa vào mô hình SS, thay vì được tinh chỉnh để hoạt động cho cả hai mô hình. Nó là một sự thay đổi về tên gọi hơn là một sự thay đổi thực sự. Theo một cách nào đó, chúng ta có thể nói rằng SS =HSSF + XSSF.
Di chuyển dữ liệu bảng cơ sở dữ liệu sang bảng tính Excel
Ở đây, chúng tôi sẽ tạo một chương trình tiện ích đơn giản để di chuyển một số dữ liệu cơ sở dữ liệu vào trang tính Excel. Điều này cũng có thể được tinh chỉnh để hoạt động với các cách khác, chẳng hạn như di chuyển dữ liệu Excel sang bảng cơ sở dữ liệu. Đây là một bài tập cho người đọc. Chương trình rất đơn giản và dễ hiểu. Truy cập Tài liệu Apache POI để biết thông tin chi tiết về bất kỳ lớp hoặc phương pháp nào. Để thử ví dụ sau, những gì chúng tôi đã sử dụng như sau:
- JDK 8
- MS Excel 2007
- IDEA Intellij IDE
- Apache POI 3.17
- Trận thắng Apache 10.14
Truy cập các tài liệu thích hợp và các tệp trợ giúp để thiết lập dự án. Đây là nội dung của tệp Maven pom.xml mà chúng tôi đã sử dụng.
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mano.examples</groupId> <artifactId>apache-poi-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>apache-poi-demo</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <artifactId> maven-compiler-plugin </artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact /org.apache.maven.plugins/maven-compiler-plugin --> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </dependency> <!-- https://mvnrepository.com/artifact/ org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <!-- https://mvnrepository.com/artifact/ org.apache.poi/poi-ooxml --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <!-- https://mvnrepository.com/artifact/ org.apache.derby/derby --> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derby</artifactId> <version>10.14.1.0</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/ org.apache.derby/derbyclient --> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derbyclient</artifactId> <version>10.14.1.0</version> </dependency> </dependencies> </project>
Liệt kê 1: pom.xml
Một bảng cơ sở dữ liệu được tạo với một số bản ghi giả trước khi chạy chương trình tiện ích. Đây là mã của tệp đó.
package com.mano.examples; import java.sql.*; public class DummyDatabase { public static void createDummyDatabase() throws SQLException { Connection con=DriverManager.getConnection ("jdbc:derby:D:/temp/dummy;create=true"); Statement stmt=con.createStatement(); stmt.executeUpdate("drop table semester2"); stmt.executeUpdate("CREATE TABLE semester2(STUDENT_ID int, CARCH INT, DCE INT, WEBTECH INT, JAVA INT, SAD_MIS INT, PRIMARY KEY(STUDENT_ID))"); // Insert 2 rows stmt.executeUpdate("insert into semester2 values (23567932,56,78,97,58,85)"); stmt.executeUpdate("insert into semester2 values (47250001,96,34,75,68,12)"); stmt.executeUpdate("insert into semester2 values (99568955,45,68,69,78,29)"); stmt.executeUpdate("insert into semester2 values (89376473,75,23,56,89,47)"); stmt.executeUpdate("insert into semester2 values (29917740,85,78,55,15,48)"); stmt.executeUpdate("insert into semester2 values (85776649,23,56,78,25,69)"); stmt.executeUpdate("insert into semester2 values (38846455,68,95,78,53,48)"); stmt.executeUpdate("insert into semester2 values (40028826,63,56,48,59,75)"); stmt.executeUpdate("insert into semester2 values (83947759,85,54,69,36,89)"); stmt.executeUpdate("insert into semester2 values (92884775,78,59,25,48,69)"); stmt.executeUpdate("insert into semester2 values (24947389,12,10,14,54,68)"); stmt.executeUpdate("insert into semester2 values (77399465,44,33,26,88,77)"); // Query ResultSet rs = stmt.executeQuery ("SELECT * FROM semester2"); // Print out query result while (rs.next()) { System.out.printf ("%dt%dt%dt%dt%dt%dn", rs.getLong("STUDENT_ID"), rs.getInt("CARCH"), rs.getInt("DCE"), rs.getInt("WEBTECH"), rs.getInt("JAVA"), rs.getInt("SAD_MIS")); } stmt.close(); con.close(); } }
Liệt kê 2: DummyDatabase.java.
Đây là chương trình tiện ích mà chúng ta đang nói đến. Mã được viết rất vội vàng và cấu trúc không được thanh lịch cho lắm. Tuy nhiên, nó hoạt động. Cơ cấu lại hoặc điều chỉnh nó khi bạn cho là phù hợp.
package com.mano.examples; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.sql.*; public class SSFile { private static String[] header={"STUDENT_ID", "CARCH", "DCE", "WEBTECH", "JAVA", "SAD_MIS", "TOTAL", "AVERAGE"}; public static void databaseToExcel(File file) throws IOException, SQLException { Workbook workbook = null; if (file.getName().endsWith(".xls")) workbook = new HSSFWorkbook(); else if (file.getName().endsWith(".xlsx")) workbook = new XSSFWorkbook(); else { System.out.println("Invalid filename!"); return; } Sheet sheet = workbook.createSheet(); Connection con = DriverManager.getConnection ("jdbc:derby:D:/temp/dummy;create=true"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM semester2"); Row rr = sheet.createRow(0); for(int i=0;i<header.length;i++){ createHeaderCell(rr, (short) i, header[i]); } int i = 1; while (rs.next()) { rr = sheet.createRow(i++); for(int j=0;j<header.length-2;j++){ createDataCell(rr, (short) j, rs.getLong(header[j])); } } rr = sheet.getRow(1); Cell total = rr.createCell(6); total.setCellType(CellType.FORMULA); total.setCellFormula("SUM(B2:F2)"); Cell avg = rr.createCell(7); avg.setCellType(CellType.FORMULA); avg.setCellFormula("AVERAGE(B2:F2)"); FileOutputStream outFile = new FileOutputStream(file); workbook.write(outFile); outFile.flush(); outFile.close(); stmt.close(); con.close(); } private static void createHeaderCell(Row row, short col, String cellValue) { Cell c = row.createCell(col); c.setCellValue(cellValue); } private static void createDataCell(Row row, short col, Number cellValue) { Cell c = row.createCell(col); c.setCellType(CellType.NUMERIC); c.setCellValue(cellValue.doubleValue()); } }
Liệt kê 3: SSFile.java
Đây là bảng điều khiển mà từ đó chương trình tiện ích được gọi.
package com.mano.examples; import java.io.File; import java.io.IOException; import java.sql.SQLException; public class App { public static void main( String[] args ) throws IOException,SQLException{ // DummyDatabase.createDummyDatabase(); SSFile.databaseToExcel(new File("d://temp//test1.xls")); } }
Danh sách 4 :App.java
Trước khi chạy…
Đảm bảo rằng test1.xls hoặc test1.xlsx tệp không tồn tại trong d:// temp thư mục trước khi chạy chương trình vì chương trình không ghi đè cũng như không kiểm tra tệp có cùng tên trong thư mục nơi tệp được cho là sẽ được tạo. Đảm bảo điều này mỗi khi chương trình được chạy; nếu không, mã đưa ra một thông báo lỗi khó chịu. Tuy nhiên, bạn có thể chỉnh sửa mã để kiểm tra.
Kết luận
Có một giải pháp thay thế khác để làm việc với bảng tính, như Tài liệu Apache POI gợi ý thông qua bộ tuần tự Cocoon, mặc dù nó vẫn sử dụng HSSF gián tiếp. Cocoon có thể tuần tự hóa bất kỳ nguồn dữ liệu XML nào bằng cách áp dụng biểu định kiểu và chỉ định trình tuần tự. Mô hình HSSF và XSSF khá mạnh mẽ và cung cấp một số lớp và phương pháp để xử lý các khía cạnh khác nhau của tài liệu Excel. Bài viết này đã cố gắng cung cấp một cái nhìn sơ lược về những gì chúng ta có thể làm với Apache POI. Chúng ta thường cần viết một chương trình tiện ích để làm cầu nối giữa hệ thống đóng và mở. Apache POI chắc chắn có thể phục vụ mục đích của chúng tôi như một trong những loại này.
Tài liệu tham khảo
- Apache POI - Java API cho Microsoft Documents
- POI-HSSF và POI-XSSF - Java API để truy cập các tệp định dạng Microsoft Excel