Your Computer Science Resource

HOW-TO: Save JTable to Excel Spreadsheet using Apache POI

Have you ever needed to save the contents of a JTable? One convenient way to save this data is to make it available as a Microsoft Excel spreadsheet. At first, this may not seem like an easy task, but with Apache’s POI API, we can do it without too much frustration.

Recently for a project, I had to save my JTable data to an Excel spreadsheet. Doing a quick search, I came across Apache’s POI API and wrote the following class to save my table data. Note that upon calling the constructor of this class, we automatically call the save() method which saves the data to a specified file (also given from the constructor). The data is read from the JTable, and column header names are taken from the JTable, as well. In this example, I’ve set formatting for strings and integers — you can add more to this to suit your needs. After saving the data to the file, the user will be asked if s/he would like to open the file (I’m pretty sure this would only work in Windows, though).

Usage

I used a custom designed NonEditableTableModel class (which is not shown here) extending the DefaultTableModel to update my JTable data (I did not want the client modifying the table data). You must modify this parameter if you wish to use your own table model, or even if you want to use the default table model. Otherwise, usage is quite simple: Pass in your table model and a string representing the file name / location, and the data will be saved to the specified file.

new ExcelSaver( myNonEditableTableModel, filePathAndName );
// save() is automatically called after the constructor

Excel Saver

Note: You will need Apache’s POI class files in order to use this class. Please download them, and add them to your project as a library.

import java.awt.Toolkit;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JOptionPane;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class ExcelSaver {

	private String filename = null;				// File name
	private FileOutputStream out = null;			// Output Stream
	private NonEditableTableModel tableModel = null;	// Table Model

	/**
	 * ExcelSaver Constructor
	 *
	 * @param tableModel
	 * @param filename
	 */

	public ExcelSaver( NonEditableTableModel tableModel, String filename ) {

		this.tableModel = tableModel;	// Table Model
		this.filename = filename;	// File name
		save();				// Call save() method

	} // end constructor

	/**
	 * This method returns the file name.
	 *
	 * @return String filename
	 */

	public String getFilename() {

		return filename;

	} // end method getFilename()

	/**
	 * This method returns the table
	 * model.
	 *
	 * @return NonEditableTableModel tableModel
	 */

	public NonEditableTableModel getTableModel() {

		return tableModel;

	} // end method getTableModel()

	/**
	 * This method saves the given file
	 * to an excel spreadsheet.
	 */

	@SuppressWarnings("deprecation")
	public void save() {

		/**
		 * Create a new file
		 */

		try {

			out = new FileOutputStream( filename );

		} catch (FileNotFoundException e) {

			JOptionPane.showMessageDialog( null, "Could not save file. Please try again.", "Error Saving File",
					JOptionPane.ERROR_MESSAGE);

		}

		/**
		 * Set up workbook
		 */

		HSSFWorkbook workbook = new HSSFWorkbook();				// New workbook
		HSSFSheet worksheet = workbook.createSheet();				// New worksheet
		HSSFRow row = null;							// Row
		HSSFCell column = null;							// Column

		/**
		 * Header Cell Style
		 */

		HSSFCellStyle headerCellStyle = workbook.createCellStyle();		// Header Cell Style
		HSSFFont headerFont = workbook.createFont();				// Header Font
		headerFont.setFontHeightInPoints( (short) 10 );				// Font Size
		headerFont.setBoldweight( HSSFFont.BOLDWEIGHT_BOLD );			// Bold Font
		headerCellStyle.setFont( headerFont );					// Set style

		headerCellStyle.setAlignment( HSSFCellStyle.ALIGN_CENTER );		// Center align

		/**
		 * String Cell Style
		 */

		HSSFCellStyle stringCellStyle = workbook.createCellStyle();		// Data Cell Style
		HSSFFont stringFont = workbook.createFont();				// Data Font
		stringFont.setFontHeightInPoints( (short) 10 );				// Font Size
		stringCellStyle.setFont(stringFont);					// Set style

		/**
		 * Integer Cell Style
		 */

		HSSFCellStyle integerCellStyle = workbook.createCellStyle();		// Data Cell Style
		HSSFDataFormat format = workbook.createDataFormat();			// Data Format
		HSSFFont integerFont = workbook.createFont();				// Data Font
		integerFont.setFontHeightInPoints( (short) 10 );			// Font Size
		integerCellStyle.setFont(integerFont);					// Set style
		integerCellStyle.setAlignment( HSSFCellStyle.ALIGN_RIGHT );		// Right align
		integerCellStyle.setDataFormat( format.getFormat("0") );		// Data Format

		/**
		 * Column Widths
		 */

		worksheet.setColumnWidth( (short) 0, (short) 10000 );
		worksheet.setColumnWidth( (short) 1, (short) 10000 );
		worksheet.setColumnWidth( (short) 2, (short) 3500 );

		/**
		 * Add headers to worksheet
		 */

		for ( short colNumber = 0; colNumber < getTableModel().getColumnCount(); colNumber++ ) {

			row = worksheet.createRow( 0 );

			column = row.createCell( colNumber );
			column.setCellStyle( headerCellStyle );
			column.setCellValue( getTableModel().getColumnName( colNumber ) );

		}

		/**
		 * Add data to worksheet
		 */

		int temp = 0; // Row value after the header row

		// Rows

		for ( int rowNumber = 0; rowNumber < getTableModel().getRowCount(); rowNumber++ ) {

			temp = rowNumber + 1; // Add one row to account for header

			row = worksheet.createRow( temp );

			// Columns

			for ( short colNumber = 0; colNumber < getTableModel().getColumnCount(); colNumber++ ) {

				column = row.createCell( colNumber );

				Class<?> dataClass = getTableModel().getValueAt( rowNumber, colNumber ).getClass();

				if ( dataClass.equals( String.class ) ) {

					column.setCellStyle( stringCellStyle );
					column.setCellValue( getTableModel().getValueAt( rowNumber, colNumber ).toString() );

				}

				else if ( dataClass.equals( Integer.class ) ) {

					column.setCellStyle( integerCellStyle );
					column.setCellValue( Double.parseDouble( getTableModel().getValueAt( rowNumber, colNumber ).toString() ) );

				}

				else {

					column.setCellValue( getTableModel().getValueAt( rowNumber, colNumber ).toString() );

				}

			} // end for loop (cols)

		} // end for loop (rows)

		/**
		 * Write workbook to output stream
		 */

		try {

			workbook.write(out);
			out.close();

		} catch (IOException e) {

			JOptionPane.showMessageDialog( null, "Could not save file. Please try again.", "Error Saving File",
					JOptionPane.ERROR_MESSAGE);

		} // end try

		/**
		 * Ask the user if he wants to open
		 * the spreadsheet.
		 */

		Toolkit.getDefaultToolkit().beep(); 

		int n = JOptionPane.showConfirmDialog( null, "<html><body>Successfully saved results to:<br><strong>" + getFilename() +
				"</strong><br>Would you like to open this spreadsheet now?</body></html>", "Successfully Saved Results",
				JOptionPane.YES_NO_OPTION);

		if ( n == 0 ) {

			try {

				Runtime.getRuntime().exec("rundll32 SHELL32.DLL,ShellExec_RunDLL " + getFilename() );

			} catch (IOException e) {

				e.printStackTrace();

			} // end try

		} else {

			return;

		} // end if

	} // end method save()

} // end class ExcelSaver

Note: I realize you can also save your data as a CSV file which may be an even better idea, but that’s not what this article is focused on (since these were not the requirements of my project). Enjoy! :)

Tags: , , , , ,

2 Responses to “HOW-TO: Save JTable to Excel Spreadsheet using Apache POI”

  1. Lidya Cota

    THANKS for this post!!!!!!

    This HOW_TO was very useful for me.

    Just there is a little bug in the code on line 141.

    The cellrow is being created for every column, the result is that at the end just the last column name is displayed.

    The fix for me, was just a condition.

    if ( colNumber == 0 ){
    row = worksheet.createRow( 0 );
    }

    Thank You!!!!

  2. Kurt

    Thanks for your comment! For some reason I didn’t experience this bug, but thanks for posting a fix :)

Leave a Reply