Menu

Java: Sử dụng thư viện POI để đọc và ghi dữ liệu với excel


English version
Ngay khi đọc tiêu đề bài viết, bạn cũng dễ dàng đoán được ý đồ của bài này rồi đúng không? Thao tác nhập và xuất dữ liệu từ file excel là một thao tác rất thường xuyên trong công việc của chúng ta. Vậy, làm thế nào chúng ta có thể nhập và xuất những dữ liệu mà ta mong muốn. Bài này sẽ giúp bạn trả lời câu hỏi trên.

Apache POI Project

Nhiệm vụ của Apache POI là để tạo ra và duy trì các Java API để làm việc trên các định dạng file khác nhau dựa trên tiêu chuẩn Office Open XML (OOXML) và định dạng OLE 2 của Microsoft (OLE2). Hay nói một cách đơn giản là bạn đọc và ghi các tệp excel trong các chương trình Java. Ngoài ra, bạn cũng có thể đọc và ghi dữ liệu với các tài liệu MS Word và MS PowerPoint. Bạn có thể xem chi tiết tại đây và tải các tệp tin thư viện tại đây.

Đọc và ghi dữ liệu excel

Trước khi làm việc với tệp dữ liệu excel ta cần phải hiểu cấu trúc của nó rồi mới tính đến chuyện đọc và ghi dữ liệu. Tất nhiên, nếu chúng ta được học tin học căn bản ở phổ thông hoặc đại học thì ta cũng đã biết cấu trúc của một tệp excel rồi đúng không? Nó gồm các phần sau đây (các thông số cụ thể xem tại đây):
  1. Workbook: cái tên này có vẻ lạ nhỉ? Không đâu, nó chính là tệp tin excel của chúng ta đấy. Từ này thay vì gọi là tệp excel ta hay gọi nó là workbook nhé.
  2. Worksheet: một cách ngắn gọn thì ta gọi nó là sheet. Một workbook thì có nhiều worksheet (số lượng thì tùy theo phiên bản nhé), các worksheet có tên (không trùng nhau) và nhãn (được đánh số từ 0 đến hết).
  3. Row: trong mỗi worksheet có nhiều Row. Các row này được đánh số từ 0 đến hết.
  4. Cell: mỗi Row lại được chia thành các Cell. Cell sẽ chứa các dữ liệu mà chúng ta cần đọc hoặc ghi. Cell là đơn vị nhỏ nhất chúng ta cần quan tâm.
Tóm lại là muốn đọc hay ghi dữ liệu excel ta cần xác định được Cell cần ghi hoặc cần đọc.

Đọc dữ liệu

Đầu tiên, ta hãy làm việc dễ dàng trước nhé. Giả sử, ta có một tệp tin excel chứa thông tin của các sinh viên trong lớp. Bạn tải về tại đây và mở workbook lên xem. Ta thấy có tất cả là năm cột gồm các thông tin: Mã SV (kiểu String), Họ tên (kiểu String), Ngày sinh (kiểu Date), Giới tính (kiểu Integer (1 là Nam và 0 là Nữ)) và Địa chỉ (kiểu String) đúng không nào. Bây giờ, ta sẽ cùng đọc dư liệu từ workbook trên vào chương trình nhé. Hãy xem đoạn code dưới đây:

Với đoạn code như trên, chúng ta sẽ tập trung vào phương thức readStudent từ dòng 37 đến dòng 103. Mình sẽ giải thích một vài đoạn mà ta cần chú ý:
  • Dòng 42: thư viện POI chỉ cho phép tạo workbook từ đối tượng của lớp InputStream cho nên chúng ta phải tạo một InputStream từ file dữ liệu. Điều này cũng hoàn toàn dễ hiểu, vì chúng ta làm trên desktop thì mới có khái niệm file, còn trong môi trường mạng thì rõ ràng chỉ có khái niệm luồng thôi đúng không?
  • Dòng 44: cho phép tạo một workbook từ luồng đầu vào.
  • Dòng 49: cho phép ta lấy sheet đầu tiên trong workbook. Ở đây, mình biết trước dữ liệu của mình đặt trong sheet đầu tiên.
  • Dòng 55-85: mình sẽ lấy từng dòng trong sheet đầu tiên, mỗi dòng mình sẽ đọc từ cell của nó. Bạn cũng lưu ý, dữ liệu trên các cột là phải thống nhất nhé. Nếu trên cùng một cột mà chỗ dữ liệu kiểu chữ, chỗ kiểu số hoặc kiểu Date là chương trình ném ra ngoại lệ đấy. Vì thế, bạn nên làm sạch dữ liệu trước khi đọc.
Lúc này, quay lại lớp Test để chạy thử, rõ ràng là chúng ta đọc được danh sách của tất cả các sinh viên vào chương trình rồi đúng không? Nếu bước này thành công thì ta thừa thắng xông lên để chuyển sang bước tiếp theo là ghi dữ liệu vừa đọc xuống một workbook khác nhé (dữ liệu này được đảo ngược lại).

Ghi dữ liệu

Ngược lại với bước đọc dữ liệu, chúng ta sẽ lần lượt làm các bước sau: i) tạo workbook, ii) tạo worksheet, ii) tạo row và cuối cùng iv) tạo cell. Đoạn code sau đây thực hiện việc ghi dữ liệu xuống một workbook.

Chúng ta xem xét phương thức writeStudent từ dòng 37 đến dòng 128. Mình sẽ nhấn mạnh một số dòng code sau:
  • Dòng 44: tạo một workbook trong bộ nhớ.
  • Dòng 49: tạo một worksheet có tên là Students. Đây cũng chính là sheet đầu tiên của workbook này.
  • Dòng 54: tạo một dòng trong worksheet ở trên. Dòng này được dùng làm dòng tiêu đề, thực chất việc dòng tiêu đề hay không là không quan trong. Tại mỗi dòng ta tạo các cell và ghi dữ liệu với phương thức setCellValue, phương thức này chấp nhận mọi giá trị nguyên thủy và giá trị kiểu Date nên bạn cứ an tâm ghi dữ liệu của mình vào.
  • Dòng 78 đến 108: ta lần lượt ghi thông tin của Student vào các cell tương ứng.
Bây giờ, ta quay lại lớp Test và chạy thử. Rõ ràng, dữ liệu mà bạn đọc từ đầu vào sẽ được ghi ra file đầu ra đúng không? (Nếu dùng eclipse thì bạn refresh lại cấu trúc thư mục nhé).

Tổng kết

  • Việc ghi và đọc dữ liệu từ file excel là một việc rất hay xảy ra, nhất là khi chuyển đổi dữ liệu giữa các hệ thống khác nhau. Chính vì vậy, bài viết này cung cấp cho bạn một cách làm ở mức tối thiểu nhất.
  • Thức tế, bài viết này chỉ sử dụng thư viện Apache POI ở mức sơ sài nhất. Tuy nhiên, mình cũng mong muốn nhận được sự góp ý để áp dụng vào những trường hợp thực tế hơn.
  • Bạn có thể tải mã nguồn tại đây.

10 nhận xét:

  1. Em chào anh,
    Em đang làm 1 module ứng dụng, lọc lấy dữ liệu trong file Excel như này. Sau đó dùng gửi tới người dùng ,theo Template HTML + Image (Image là logo, header file ).
    Em dùng thư viện Velocity, không biết hiểu vì sao mà khi chỉ dùng Template HTML thì mail gửi tớ người nhận đọc được luôn. nhưng khi kết hợp thêm Image thì nó lại thành 2 file đính kèm riêng biệt.
    Em làm theo hướng dẫn này:
    http://sengopal.github.io/blog/blog/java-mail-using-velocity-templates.html
    Mong anh chỉ giúp ạ!

    Trả lờiXóa
    Trả lời
    1. Mình không rõ hai file đính kèm là file html và file ảnh đúng không? Điều này là đương nhiên vì mình thấy các email gửi cho mình đều như thế cả. Mình dùng các chương trình đọc email như Thunderbird, Outlook hoặc Webmail để đọc vẫn hiển thị nội dung file html cùng với anh mà. Bạn xem lại cài đặt hiển thị xem có cho phép hiển thị ảnh hay không?
      Một cách làm nữa là thay vì gửi cả anh ta sẽ tả anh lên đâu đó, rồi trong file html ta dụng thẻ img với đường dẫn đến nơi lưu trữ là được rồi.
      Cảm ơn bạn đã ghé thăm blog của mình

      Xóa
  2. Cảm ơn bạn rất nhiều !
    Hy vọng bạn sẽ chia sẽ thêm nhiều bài viết hữu ích khác :)

    Trả lờiXóa
  3. Cảm ơn bạn rất nhiều !
    Hy vọng bạn sẽ có thêm nhiều bài viết hữu ích khác giúp đỡ mọi người :)

    Trả lờiXóa
    Trả lời
    1. Cảm ơn bạn đã ghé thăm. Hãy cho mình biết ý kiến của bạn về blog và những chủ để mà bạn quan tâm để mình có thể trình bày và viết các bài hay hơn trong tương lai.

      Xóa
  4. Hi anh...
    em có 1 file excel định nghĩa 1 loạt các item cần sử dụng... Em cần đọc file excel này và generate nó ra một file java interface định nghĩa các item này, các phương thức getter, setter. Anh có thể nói qua hướng đi như thế nào cho em được không(use POI)...
    Thanks
    TungHD,

    Trả lờiXóa
    Trả lời
    1. Chào Tùng,
      Rất vui vì bạn đã ghé thăm blog của mình. Về câu hỏi của bạn mình xin trả lời như sau:
      1. Bạn cần phải biết chính xác định dạng file excel của mình. POI sẽ đọc lần lượt từ workbook >> Worksheet >> Row >> Cell. Chính vì vậy, bạn nên tổ chức các thông tin này một cách dễ đọc nhất nhé.
      2. Sau khi đọc được nội dung của file excel thì việc sinh ra các Java Interface hoàn toàn dễ dàng thôi. Bạn có thể sử dụng các ngôn ngữ template như (Velocity (http://velocity.apache.org/) hoặc FreeMaker(http://www.freemarker.org/index.html), ...) để sinh ra các lớp (hoặc giao diện) Java cần thiết.
      Chúc bạn thành công và hãy ủng hộ blog của mình nhiều hơn nữa nhé!

      Xóa
  5. Bạn ơi mình đọc ngày tháng năm sinh sử dụng Apache poi 4.1.0 báo lỗi. Bạn hướng dẫn cho mình nhé

    Trả lờiXóa