Thank you Dany,

your answer was very helpfull. Here is my code, extending ULCTable and UITable. I have change createTransferable to transfer selected rows only and toTransferValue to replace non-breaking space in formatted number (e.g. 1 000,00) which Excel treats as text.


ULCTransferTable.java
------------------------------------------------------------------------------
package cz.cosma.cis.base.application.util.transfertable;

import com.ulcjava.base.application.ULCTable;
import com.ulcjava.base.application.table.ITableModel;

public class ULCTransferTable extends ULCTable {
   public ULCTransferTable() {
       super();
   }
public ULCTransferTable(ITableModel model) {
       super(model);
   }

   protected String typeString() {
return "cz.cosma.cis.base.client.util.transfertable.UITransferTable";
   }
}
------------------------------------------------------------------------------

UITransferTable.java
------------------------------------------------------------------------------
package cz.cosma.cis.base.client.util.transfertable;

import com.ulcjava.base.client.UITable;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.table.TableCellRenderer;

import java.awt.Component;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;

public class UITransferTable extends UITable {
   protected void postInitializeState() {
       super.postInitializeState();

       getBasicTable().setTransferHandler(new UITransferHandler());
   }
public class UITransferHandler extends TransferHandler {
       protected Transferable createTransferable(JComponent component) {
           StringBuffer data = new StringBuffer();
           JTable table = (JTable)component;
           ListSelectionModel model = table.getSelectionModel();
for (int i = model.getMinSelectionIndex(); i <= model.getMaxSelectionIndex(); i++) {
               if (model.isSelectedIndex(i)) {
                   for (int j = 0; j < table.getColumnCount(); j++) {
                       if (j > 0) {
                           data.append('\t');
                       }
                       data.append(toTransferValue(table, i, j));
                   }
                   data.append('\n');
               }
           }

           return new StringSelection(data.toString());
       }

       private Object toTransferValue(JTable table, int row, int column) {
           TableCellRenderer renderer = table.getCellRenderer(row, column);
Component rendererComponent = table.prepareRenderer(renderer, row, column);
           if (rendererComponent instanceof JLabel) {
               JLabel rendererLabel = (JLabel)rendererComponent;
               return rendererLabel.getText().replace("\u00A0", " ");
           } else {
               return table.getValueAt(row, column);
           }
       }

       public int getSourceActions(JComponent c) {
           return COPY;
       }
   }
}
------------------------------------------------------------------------------

Regards
Vladimir Turek



Daniel Grob napsal(a):
Hi Vladimir,

In Swing, a transfer handler is responsible to provide the transfer data. The default implementation for JTable just uses table.getValueAt(row, column) to construct the transfer data, i.e. renderers are not considered. For more information you can find Swing's default implementation in the class javax.swing.plaf.basic.BasicTableUI.TableTransferHandler class.

In ULC you can write an extension to have custom transfer behavior. The code at the end of my mail shows such an extension that considers renderers.

Regards Dany


import com.ulcjava.base.application.AbstractApplication;
import com.ulcjava.base.application.ULCFrame;
import com.ulcjava.base.application.ULCTable;
import com.ulcjava.base.application.table.AbstractTableModel;
import com.ulcjava.base.application.table.ITableModel;
import com.ulcjava.base.client.UITable;
import com.ulcjava.base.development.DevelopmentRunner;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.TransferHandler;
import javax.swing.table.TableCellRenderer;

import java.awt.Component;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.util.Date;

public class TableToExcelSnippet extends AbstractApplication {
   public void start() {
       ULCFrame frame = new ULCFrame("Snippet");
       frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE);
frame.getContentPane().add(new ULCSnippetTable(new SnippetModel()));
       frame.pack();
       frame.setVisible(true);
   }

   public static void main(String[] args) {
       DevelopmentRunner.setApplicationClass(TableToExcelSnippet.class);
       DevelopmentRunner.main(args);
   }

   public static class ULCSnippetTable extends ULCTable {
       public ULCSnippetTable(ITableModel model) {
           super(model);
       }

       protected String typeString() {
           return UISnippetTable.class.getName();
       }
   }

   public static class UISnippetTable extends UITable {
       protected void postInitializeState() {
           super.postInitializeState();

getBasicTable().setTransferHandler(new SnippetTransferHandler());
       }
   }

   public static class SnippetTransferHandler extends TransferHandler {
       protected Transferable createTransferable(JComponent component) {
           StringBuffer data = new StringBuffer();
           JTable table = (JTable)component;
           for (int i = 0; i < table.getRowCount(); i++) {
               for (int j = 0; j < table.getColumnCount(); j++) {
                   if (j > 0) {
                       data.append('\t');
                   }
                   data.append(toTransferValue(table, i, j));
               }
               data.append('\n');
           }
                     return new StringSelection(data.toString());
       }

private Object toTransferValue(JTable table, int row, int column) { TableCellRenderer renderer = table.getCellRenderer(row, column); Component rendererComponent = table.prepareRenderer(renderer, row, column);
           if (rendererComponent instanceof JLabel) {
               JLabel rendererLabel = (JLabel)rendererComponent;
               return rendererLabel.getText();
           } else {
               return table.getValueAt(row, column);
           }
       }

       public int getSourceActions(JComponent c) {
           return COPY;
       }
   }

   public static class SnippetModel extends AbstractTableModel {
       public Object getValueAt(int row, int column) {
           switch (column) {
           case 1:
               return new Date();
           default:
               return "foo";
           }
       }

       public int getRowCount() {
           return 20;
       }

       public int getColumnCount() {
           return 5;
       }

       public Class getColumnClass(int columnIndex) {
           switch (columnIndex) {
           case 1:
               return Date.class;
           default:
               return Object.class;
           }
       }
   }
}


Vladimír Turek wrote:
Hello to all,

The problem I encounter when I try to copy lines from ULCTable to MS Excel with Ctrl+C and Ctrl+V, is that copied data into clipboard contains number and date format without accepting renderers in table columns. And Czech Excel shows pasting number and date as text, not as requested. I have table with many rows and need to copy lines only on client without any server roundtrip. I find out that a value for copy is acquiring in UITableModelAdapter's getValueAt(int rowIndex, int columnIndex) method.

Expected result:
 31.7.2003     2 848,00        do roku 2005
 31.5.2003     34 709,00       do roku 2005
 13.6.2003     450,00          do roku 2005

Actual result:
 Thu Jul 31 00:00:00 CEST 2003     2848.00         do roku 2005
 Sat May 31 00:00:00 CEST 2003     34709.00        do roku 2005
 Fri Jun 13 00:00:00 CEST 2003     450.0           do roku 2005


This is what I have in my code ...

private void updateTableLook() {
   ...
   for (int i = 0; i < _tableModel.getColumnCount(); i++) {
       ULCTableColumn column = _table.getColumnModel().getColumn(i);
              // column renderer's
       String typ = _tableModel.getColumnTyp(i);
       if (typ.equals("B")) {
           column.setCellRenderer(new BooleanRenderer());
       } else if (typ.equals("D")) {
           column.setCellRenderer(new DateRenderer());
       } else if (typ.equals("T")) {
           column.setCellRenderer(new DateTimeRenderer());
       } else if (typ.equals("N")) {
           column.setCellRenderer(new DecimalRenderer());
       } else if (typ.equals("I")) {
           column.setCellRenderer(new IntegerRenderer());
       } else if (typ.equals("L")) {
           column.setCellRenderer(new LongRenderer());
       }
      _table.repaint();
}
   public class DateRenderer extends DefaultTableCellRenderer {
   public DateRenderer() {
       setDataType(new ULCCzDateDataType());
   }
}

public class ULCCzDateDataType extends ULCDateDataType {
   public static final String DEFAULT_FORMAT = "d.M.yyyy";
      public ULCCzDateDataType(String format) {
       if (format != null && !format.equals("")) {
           super.setFormatString(format);
       } else {
           setFormatString(DEFAULT_FORMAT);                   }
   }
      public ULCCzDateDataType() {
       this(DEFAULT_FORMAT);
   }
          protected String typeString() {
       return "cz.cosma.cis.base.client.util.datatype.UICzDateDataType";
   }
}

public class UICzDateDataType extends com.ulcjava.base.client.datatype.UIDateDataType {
}


Extending UICzDateDataType's method convertToString(Object object, boolean forEditing) don't affect the result.
ULC 6.1.3 on Windows 2000, Java 1.5.0_04 and Czech version of Excel.


Thanks and regards,

Vladimir Turek
_______________________________________________
ULC-developer mailing list
[email protected]
http://lists.canoo.com/mailman/listinfo/ulc-developer


_______________________________________________
ULC-developer mailing list
[email protected]
http://lists.canoo.com/mailman/listinfo/ulc-developer

Reply via email to