📜 ⬆️ ⬇️

Copy / paste functionality between Swing's JTables and Excel

From the translator : this translation is just a sample of the pen. I would be very grateful for all the comments. I hope for your help in bringing this article to the literary form. Here is a small list of what I want to fix in this article:


Many business applications are developed using Java. Most of them display data as tables using Swing JTable. It would be very convenient to be able to copy and paste data from this application into Microsoft Excel and back. This way, users can take advantage of all the power of this omnipresent program.

This Java tip will help you understand the principle of the Excel-generated string, placed on the system clipboard, that will allow you to achieve copy / paste functionality when interacting JTable and Excel. As you will see later, this advice is complete and allows you to achieve the desired result literally adding one line of code.

All you need to achieve this goal is to copy the ExcelAdapter.java file described below, compile it and take care of the availability of the resulting class for your application. Once you do this, your JTable is ready to "talk" with Excel. We will show which line you need to add to provide copy / paste functionality with Excel. Of course, an example of a simple application provided with this functionality will also be given.
')

Adapter class


Below is the code of the adapter class, called ExcelAdapter.java, which is designed to solve this problem:

import java.awt.*;
import java.awt. event .*;
import javax.swing.*;
import java.awt.datatransfer.*;
import java.util.*;

/**
* ExcelAdapter enables Copy-Paste Clipboard functionality on JTables. The
* clipboard data format used by the adapter is compatible with the clipboard
* format used by Excel. This provides for clipboard interoperability between
* enabled JTables and Excel.
*/
public class ExcelAdapter implements ActionListener {
private String rowstring, value ;
private Clipboard system;
private StringSelection stsel;
private JTable jTable1;

/**
* The Excel Adapter is constructed with a JTable on which it enables
* Copy-Paste and acts as a Clipboard listener.
*/
public ExcelAdapter(JTable myJTable) {
jTable1 = myJTable;
KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,
ActionEvent.CTRL_MASK, false );
// Identifying the copy KeyStroke user can modify this
// to copy on some other Key combination.
KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,
ActionEvent.CTRL_MASK, false );
// Identifying the Paste KeyStroke user can modify this
// to copy on some other Key combination.
jTable1.registerKeyboardAction( this , "Copy" , copy,
JComponent.WHEN_FOCUSED);
jTable1.registerKeyboardAction( this , "Paste" , paste,
JComponent.WHEN_FOCUSED);
system = Toolkit.getDefaultToolkit().getSystemClipboard();
}

/**
* Public Accessor methods for the Table on which this adapter acts.
*/
public JTable getJTable() {
return jTable1;
}

public void setJTable(JTable jTable1) {
this .jTable1 = jTable1;
}

/**
* This method is activated on the Keystrokes we are listening to in this
* implementation. Here it listens for Copy and Paste ActionCommands.
* Selections comprising non-adjacent cells result in invalid selection and
* then copy action cannot be performed. Paste is done by aligning the upper
* left corner of the selection with the 1st element in the current
* selection of the JTable.
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().compareTo( "Copy" ) == 0) {
StringBuffer sbf = new StringBuffer();
// Check to ensure we have selected only a contiguous block of
// cells
int numcols = jTable1.getSelectedColumnCount();
int numrows = jTable1.getSelectedRowCount();
int [] rowsselected = jTable1.getSelectedRows();
int [] colsselected = jTable1.getSelectedColumns();
if (!((numrows - 1 == rowsselected[rowsselected.length - 1]
- rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1]
- colsselected[0] && numcols == colsselected.length))) {
JOptionPane.showMessageDialog( null , "Invalid Copy Selection" ,
"Invalid Copy Selection" , JOptionPane.ERROR_MESSAGE);
return ;
}
for ( int i = 0; i < numrows; i++) {
for ( int j = 0; j < numcols; j++) {
sbf.append(jTable1.getValueAt(rowsselected[i],
colsselected[j]));
if (j < numcols - 1)
sbf.append( "\t" );
}
sbf.append( "\n" );
}
stsel = new StringSelection(sbf.toString());
system = Toolkit.getDefaultToolkit().getSystemClipboard();
system.setContents(stsel, stsel);
}
if (e.getActionCommand().compareTo( "Paste" ) == 0) {
System. out .println( "Trying to Paste" );
int startRow = (jTable1.getSelectedRows())[0];
int startCol = (jTable1.getSelectedColumns())[0];
try {
String trstring = ( String ) (system.getContents( this )
.getTransferData(DataFlavor.stringFlavor));
System. out .println( "String is:" + trstring);
StringTokenizer st1 = new StringTokenizer(trstring, "\n" );
for ( int i = 0; st1.hasMoreTokens(); i++) {
rowstring = st1.nextToken();
StringTokenizer st2 = new StringTokenizer(rowstring, "\t" );
for ( int j = 0; st2.hasMoreTokens(); j++) {
value = ( String ) st2.nextToken();
if (startRow + i < jTable1.getRowCount()
&& startCol + j < jTable1.getColumnCount())
jTable1.setValueAt( value , startRow + i, startCol
+ j);
System. out .println( "Putting " + value + "at row="
+ startRow + i + "column=" + startCol + j);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
* This source code was highlighted with Source Code Highlighter .
import java.awt.*;
import java.awt. event .*;
import javax.swing.*;
import java.awt.datatransfer.*;
import java.util.*;

/**
* ExcelAdapter enables Copy-Paste Clipboard functionality on JTables. The
* clipboard data format used by the adapter is compatible with the clipboard
* format used by Excel. This provides for clipboard interoperability between
* enabled JTables and Excel.
*/
public class ExcelAdapter implements ActionListener {
private String rowstring, value ;
private Clipboard system;
private StringSelection stsel;
private JTable jTable1;

/**
* The Excel Adapter is constructed with a JTable on which it enables
* Copy-Paste and acts as a Clipboard listener.
*/
public ExcelAdapter(JTable myJTable) {
jTable1 = myJTable;
KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,
ActionEvent.CTRL_MASK, false );
// Identifying the copy KeyStroke user can modify this
// to copy on some other Key combination.
KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,
ActionEvent.CTRL_MASK, false );
// Identifying the Paste KeyStroke user can modify this
// to copy on some other Key combination.
jTable1.registerKeyboardAction( this , "Copy" , copy,
JComponent.WHEN_FOCUSED);
jTable1.registerKeyboardAction( this , "Paste" , paste,
JComponent.WHEN_FOCUSED);
system = Toolkit.getDefaultToolkit().getSystemClipboard();
}

/**
* Public Accessor methods for the Table on which this adapter acts.
*/
public JTable getJTable() {
return jTable1;
}

public void setJTable(JTable jTable1) {
this .jTable1 = jTable1;
}

/**
* This method is activated on the Keystrokes we are listening to in this
* implementation. Here it listens for Copy and Paste ActionCommands.
* Selections comprising non-adjacent cells result in invalid selection and
* then copy action cannot be performed. Paste is done by aligning the upper
* left corner of the selection with the 1st element in the current
* selection of the JTable.
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().compareTo( "Copy" ) == 0) {
StringBuffer sbf = new StringBuffer();
// Check to ensure we have selected only a contiguous block of
// cells
int numcols = jTable1.getSelectedColumnCount();
int numrows = jTable1.getSelectedRowCount();
int [] rowsselected = jTable1.getSelectedRows();
int [] colsselected = jTable1.getSelectedColumns();
if (!((numrows - 1 == rowsselected[rowsselected.length - 1]
- rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1]
- colsselected[0] && numcols == colsselected.length))) {
JOptionPane.showMessageDialog( null , "Invalid Copy Selection" ,
"Invalid Copy Selection" , JOptionPane.ERROR_MESSAGE);
return ;
}
for ( int i = 0; i < numrows; i++) {
for ( int j = 0; j < numcols; j++) {
sbf.append(jTable1.getValueAt(rowsselected[i],
colsselected[j]));
if (j < numcols - 1)
sbf.append( "\t" );
}
sbf.append( "\n" );
}
stsel = new StringSelection(sbf.toString());
system = Toolkit.getDefaultToolkit().getSystemClipboard();
system.setContents(stsel, stsel);
}
if (e.getActionCommand().compareTo( "Paste" ) == 0) {
System. out .println( "Trying to Paste" );
int startRow = (jTable1.getSelectedRows())[0];
int startCol = (jTable1.getSelectedColumns())[0];
try {
String trstring = ( String ) (system.getContents( this )
.getTransferData(DataFlavor.stringFlavor));
System. out .println( "String is:" + trstring);
StringTokenizer st1 = new StringTokenizer(trstring, "\n" );
for ( int i = 0; st1.hasMoreTokens(); i++) {
rowstring = st1.nextToken();
StringTokenizer st2 = new StringTokenizer(rowstring, "\t" );
for ( int j = 0; st2.hasMoreTokens(); j++) {
value = ( String ) st2.nextToken();
if (startRow + i < jTable1.getRowCount()
&& startCol + j < jTable1.getColumnCount())
jTable1.setValueAt( value , startRow + i, startCol
+ j);
System. out .println( "Putting " + value + "at row="
+ startRow + i + "column=" + startCol + j);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
* This source code was highlighted with Source Code Highlighter .
import java.awt.*;
import java.awt. event .*;
import javax.swing.*;
import java.awt.datatransfer.*;
import java.util.*;

/**
* ExcelAdapter enables Copy-Paste Clipboard functionality on JTables. The
* clipboard data format used by the adapter is compatible with the clipboard
* format used by Excel. This provides for clipboard interoperability between
* enabled JTables and Excel.
*/
public class ExcelAdapter implements ActionListener {
private String rowstring, value ;
private Clipboard system;
private StringSelection stsel;
private JTable jTable1;

/**
* The Excel Adapter is constructed with a JTable on which it enables
* Copy-Paste and acts as a Clipboard listener.
*/
public ExcelAdapter(JTable myJTable) {
jTable1 = myJTable;
KeyStroke copy = KeyStroke.getKeyStroke(KeyEvent.VK_C,
ActionEvent.CTRL_MASK, false );
// Identifying the copy KeyStroke user can modify this
// to copy on some other Key combination.
KeyStroke paste = KeyStroke.getKeyStroke(KeyEvent.VK_V,
ActionEvent.CTRL_MASK, false );
// Identifying the Paste KeyStroke user can modify this
// to copy on some other Key combination.
jTable1.registerKeyboardAction( this , "Copy" , copy,
JComponent.WHEN_FOCUSED);
jTable1.registerKeyboardAction( this , "Paste" , paste,
JComponent.WHEN_FOCUSED);
system = Toolkit.getDefaultToolkit().getSystemClipboard();
}

/**
* Public Accessor methods for the Table on which this adapter acts.
*/
public JTable getJTable() {
return jTable1;
}

public void setJTable(JTable jTable1) {
this .jTable1 = jTable1;
}

/**
* This method is activated on the Keystrokes we are listening to in this
* implementation. Here it listens for Copy and Paste ActionCommands.
* Selections comprising non-adjacent cells result in invalid selection and
* then copy action cannot be performed. Paste is done by aligning the upper
* left corner of the selection with the 1st element in the current
* selection of the JTable.
*/
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().compareTo( "Copy" ) == 0) {
StringBuffer sbf = new StringBuffer();
// Check to ensure we have selected only a contiguous block of
// cells
int numcols = jTable1.getSelectedColumnCount();
int numrows = jTable1.getSelectedRowCount();
int [] rowsselected = jTable1.getSelectedRows();
int [] colsselected = jTable1.getSelectedColumns();
if (!((numrows - 1 == rowsselected[rowsselected.length - 1]
- rowsselected[0] && numrows == rowsselected.length) && (numcols - 1 == colsselected[colsselected.length - 1]
- colsselected[0] && numcols == colsselected.length))) {
JOptionPane.showMessageDialog( null , "Invalid Copy Selection" ,
"Invalid Copy Selection" , JOptionPane.ERROR_MESSAGE);
return ;
}
for ( int i = 0; i < numrows; i++) {
for ( int j = 0; j < numcols; j++) {
sbf.append(jTable1.getValueAt(rowsselected[i],
colsselected[j]));
if (j < numcols - 1)
sbf.append( "\t" );
}
sbf.append( "\n" );
}
stsel = new StringSelection(sbf.toString());
system = Toolkit.getDefaultToolkit().getSystemClipboard();
system.setContents(stsel, stsel);
}
if (e.getActionCommand().compareTo( "Paste" ) == 0) {
System. out .println( "Trying to Paste" );
int startRow = (jTable1.getSelectedRows())[0];
int startCol = (jTable1.getSelectedColumns())[0];
try {
String trstring = ( String ) (system.getContents( this )
.getTransferData(DataFlavor.stringFlavor));
System. out .println( "String is:" + trstring);
StringTokenizer st1 = new StringTokenizer(trstring, "\n" );
for ( int i = 0; st1.hasMoreTokens(); i++) {
rowstring = st1.nextToken();
StringTokenizer st2 = new StringTokenizer(rowstring, "\t" );
for ( int j = 0; st2.hasMoreTokens(); j++) {
value = ( String ) st2.nextToken();
if (startRow + i < jTable1.getRowCount()
&& startCol + j < jTable1.getColumnCount())
jTable1.setValueAt( value , startRow + i, startCol
+ j);
System. out .println( "Putting " + value + "at row="
+ startRow + i + "column=" + startCol + j);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
* This source code was highlighted with Source Code Highlighter .

Simple application


Below is the code for a simple application Frame1.java, which, using ExcelAdapter, makes the JTable Excel-compatible.

import java.awt.*;
import javax.swing.*;

public class Frame1 extends Frame {

BorderLayout borderLayout1 = new BorderLayout();
JTable jTable1;
Object[][] data = new Object[4][4];
Object header[] = { "Jan" , "Feb" , "Mar" , "Apr" };

public static void main( String args[]) {
Frame1 myframe = new Frame1();
myframe.setSize( new Dimension(250, 250));
myframe.setVisible( true );
}

public Frame1() {
super();
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}

private void jbInit() throws Exception {
for ( int i = 0; i < 4; i++)
for ( int j = 0; j < 4; j++)
data[i][j] = new Integer(i * 10 + j);
System. out .println( "Header length=" + header[1]);
jTable1 = new JTable(data, header);
jTable1.setCellSelectionEnabled( true );
this .setTitle( "Excel Lent JTABLE" );
jTable1.setBackground(Color.pink);
this .setLayout(borderLayout1);
this .setSize( new Dimension(400, 300));
this .setBackground(Color.white);
this .add(jTable1, BorderLayout.CENTER);
// This is the line that does all the magic!
ExcelAdapter myAd = new ExcelAdapter(jTable1);
}
}
* This source code was highlighted with Source Code Highlighter .
import java.awt.*;
import javax.swing.*;

public class Frame1 extends Frame {

BorderLayout borderLayout1 = new BorderLayout();
JTable jTable1;
Object[][] data = new Object[4][4];
Object header[] = { "Jan" , "Feb" , "Mar" , "Apr" };

public static void main( String args[]) {
Frame1 myframe = new Frame1();
myframe.setSize( new Dimension(250, 250));
myframe.setVisible( true );
}

public Frame1() {
super();
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}

private void jbInit() throws Exception {
for ( int i = 0; i < 4; i++)
for ( int j = 0; j < 4; j++)
data[i][j] = new Integer(i * 10 + j);
System. out .println( "Header length=" + header[1]);
jTable1 = new JTable(data, header);
jTable1.setCellSelectionEnabled( true );
this .setTitle( "Excel Lent JTABLE" );
jTable1.setBackground(Color.pink);
this .setLayout(borderLayout1);
this .setSize( new Dimension(400, 300));
this .setBackground(Color.white);
this .add(jTable1, BorderLayout.CENTER);
// This is the line that does all the magic!
ExcelAdapter myAd = new ExcelAdapter(jTable1);
}
}
* This source code was highlighted with Source Code Highlighter .
import java.awt.*;
import javax.swing.*;

public class Frame1 extends Frame {

BorderLayout borderLayout1 = new BorderLayout();
JTable jTable1;
Object[][] data = new Object[4][4];
Object header[] = { "Jan" , "Feb" , "Mar" , "Apr" };

public static void main( String args[]) {
Frame1 myframe = new Frame1();
myframe.setSize( new Dimension(250, 250));
myframe.setVisible( true );
}

public Frame1() {
super();
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}

private void jbInit() throws Exception {
for ( int i = 0; i < 4; i++)
for ( int j = 0; j < 4; j++)
data[i][j] = new Integer(i * 10 + j);
System. out .println( "Header length=" + header[1]);
jTable1 = new JTable(data, header);
jTable1.setCellSelectionEnabled( true );
this .setTitle( "Excel Lent JTABLE" );
jTable1.setBackground(Color.pink);
this .setLayout(borderLayout1);
this .setSize( new Dimension(400, 300));
this .setBackground(Color.white);
this .add(jTable1, BorderLayout.CENTER);
// This is the line that does all the magic!
ExcelAdapter myAd = new ExcelAdapter(jTable1);
}
}
* This source code was highlighted with Source Code Highlighter .


The format of the data placed in the Excel clipboard


The format of the data placed in the Excel clipboard is very simple. Excel shares data that is on the same line using tabs, and data that is on different lines is divided into newline characters (usually the "\ n" character). Thus, when you copy a set of cells, Excel puts a string formed according to the rules described above on the clipboard. Using this information, you can implement Copy / Paste functionality in any application written in any language that allows you to work with the clipboard.

The authors


Ashok Banerjee and Jignesh Mehta work for Oracle Corporation.

Source: https://habr.com/ru/post/36612/


All Articles