I am trying to substitute the null value of VCID and VCIDBACKUP for "Dont Have". Here is my code:
if (controladorExcel == false) {
WritableWorkbook workbookVazio = Workbook.createWorkbook(file);
WritableSheet sheet1 = workbookVazio.createSheet("First Sheet", 0);
TableModel model = table.getModel();
for (int i = 0; i < model.getColumnCount(); i++) {
Label column = new Label(i, 0, model.getColumnName(i));
sheet1.addCell(column);
System.out.println(column.getContents());
}
int j = 0;
for (int i = 0; i < model.getRowCount(); i++) {
for (j = 0; j < model.getColumnCount(); j++) {
System.out.println(model.getRowCount());
System.out.println(model.getColumnCount());
if(model.getValueAt(i, j) == null){ //At this point I verify if the value is null
model.setValueAt("Nao possui", i, j);
}
Label row = new Label(j, i + 1, //I got NULL POINTER here
model.getValueAt(i, j).toString());
System.out.println(row.getContents());
sheet1.addCell(row);
}
}
workbookVazio.write();
workbookVazio.close();
Here is the code of my AbstractTableModel:
public class MacroTableModel extends AbstractTableModel {
private String[] colunas;
private List<Macro> linhas;
public MacroTableModel(List<Macro> lista){
this.colunas = new String[]{"VPN Name", "VCID", "VCID BACKUP"};
this.linhas = new ArrayList<Macro>(lista);
}
public String getColumnName(int index) {
return colunas[index];
}
public int getRowCount(){
return linhas.size();
}
public int getColumnCount(){
return colunas.length;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
Macro macro = new Macro();
switch(columnIndex){
case 0:
macro.setVpnName(aValue.toString());
break;
case 1:
macro.setVcid(aValue.toString());
break;
case 2:
macro.setVcid_BackUp(aValue.toString());
break;
}
fireTableCellUpdated(rowIndex,columnIndex);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Macro macro = linhas.get(rowIndex);
switch(columnIndex){
case 0:
return macro.getVpnName();
case 1:
return macro.getVcid();
case 2:
return macro.getVcid_BackUp();
}
return null;
}
public void setColunas(String[] colunas) {
this.colunas = colunas;
}
public String getColunas(int i) {
return colunas[i];
}
}
When I debug the setValueAt method I get the correct value, but I still get the same error.
I might forgot some implementation in my AbstractModel class, I dont know exactly. Can someone help, please ?
The following two lines
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
Macro macro = new Macro();
should be replaced by
public void setValueAt(Object aValue, int rowIndex, int columnIndex){
Macro macro = linhas.get(rowIndex);
Otherwise, you're modifying a new Macro that is not even part of the model, and this new Macro becomes eligible to GC right after the setValueAt() method returns. You want to change the value of the Macro that is in the model, at this row index.
That said, I find it a bit strange to modify the model when exporting it to Excel. Why doesn't the model do the substitution by itself:
public Object getValueAt(int rowIndex, int columnIndex) {
Macro macro = linhas.get(rowIndex);
switch(columnIndex){
case 0:
return valueOrDontHave(macro.getVpnName());
break;
case 1:
return valueOrDontHave(macro.getVcid());
case 2:
return valueOrDontHave(macro.getVcid_BackUp());
}
return null;
}
private valueOrDontHave(Object value) {
return value == null ? ""Nao possui" : value;
}
Related
sorry but I still don't get this thing from my database dont change to check box. it just show as true or false
try {
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT * FROM tblpdareenlist");
DefaultTableModel model = (DefaultTableModel) viewRecordTable.getModel();
int x = 0;
String b, c, d, e, f, g, h, i;
Boolean a;
while (rs.next()) {
a = rs.getBoolean("colAttend");
b = rs.getString("colNr");
c = rs.getString("colRank");
d = rs.getString("colFName");
e = rs.getString("colMName");
f = rs.getString("colLName");
g = rs.getString("colSN");
h = rs.getString("colUnit");
i = rs.getString("colETE");
model.insertRow(x, new Object[]{a,b,c,d,e,f,g,h,i});
x++;
}
} catch (Exception e) {
JOptionPane.showMessageDialog(rootPane, "Syntax Error\n" + e);
}
The JTable will display a check box for a column if the table model's getColumnClass method returns Boolean.class for that column[1]. You are using the DefaultTableModel which only returns Object.class for any column. This model is just a very simple model, not the best for a real system, more for testing or very simple data.
The best is to implement your own TableModel returning the correct class for given column, e.g. extending the AbstractTableModel.
For testing only you can just extend the DefaultTableModel and override the getColumnClass method:
var model = new DefaultTableModel(0, 3) {
#Override
public Class<?> getColumnClass(int col) {
if (col == 0) return Boolean.class;
else return super.getColumnClass(col);
}
};
var table = new JTable(model);
model.insertRow(0, List.of(false, "false", 0).toArray());
model.insertRow(1, List.of(true, "true", 1).toArray());
JOptionPane.showMessageDialog(null, table);
Again, on the long run, for a real project, you will get stuck very soon with that solution - much better to implement a dedicated TableModel. A very simple (incomplete) example:
public static void main(String[] args) {
var model = new MyTableModel();
var table = new JTable(model);
model.add(new MyData(false, "false", 0));
model.add(new MyData(true, "true", 1));
JOptionPane.showMessageDialog(null, table);
}
static final int FLAG = 0;
static final int NAME = 1;
static final int VALUE = 2;
private static class MyTableModel extends AbstractTableModel {
private final List<MyData> list = new ArrayList<>();
void add(MyData data) {
list.add(data);
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public Object getValueAt(int row, int col) {
var data = list.get(row);
switch(col) {
case FLAG: return data.flag;
case NAME: return data.name;
case VALUE: return data.value;
}
throw new IllegalArgumentException("column " + col);
}
#Override
public Class<?> getColumnClass(int col) {
switch(col) {
case FLAG: return Boolean.class;
case NAME: return String.class;
case VALUE: return Integer.class;
}
throw new IllegalArgumentException("column " + col);
}
}
private static class MyData {
final boolean flag;
final String name;
final int value;
MyData(boolean flag, String name, int value) {
this.flag = flag;
this.name = name;
this.value = value;
}
}
[1] JTable Tutorial
For some reason this was removed.
This question is CLOSED and i won't be reading it as i have moved onwards and implemented more methods working. So no need putting snarky comments here, i won't read them.
Ok, so this might be quite the simple question, but here goes. I am setting up a JTable for editing and i want column 1 to have a comboBox editor. I looked up how to do it and followed the instructions which lead me to the code under, however it doesn't seem to actually update into the display. What am I misssing here? Thank you in advance.
//MainWindow class
public class MainWindow extends JFrame{
GridBagConstraints gbc;
JTable gridDisplay;
private AbstractTableModel tableModel;
JLabel statusBar;
MainWindow()
{
super("LayoutEditor");
setLayout(new BorderLayout());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
gridDisplay = new JTable();
tableModel = new MyTableModel();
gridDisplay.setAutoCreateRowSorter(true);
gridDisplay.setColumnSelectionAllowed(true);
gridDisplay.setCellSelectionEnabled(true);
gridDisplay.setModel(tableModel);
TableColumn tc = gridDisplay.getColumnModel().getColumn(0);
JComboBox<String> cb = new JComboBox<String>();
cb.addItem("JLabel");
cb.addItem("JButton");
cb.addItem("JTextField");
cb.addItem("JTextArea");
cb.addItem("JCheckBox");
cb.addItem("JList");
cb.addItem("JComboBox");
cb.addItem("JSpinnerList");
cb.addItem("JSpinnerNumber");
cb.setSelectedIndex(0);
tc.setCellEditor(new DefaultCellEditor(cb));
MyDataModel temp= new MyDataModel();
MyTableModel table = (MyTableModel)gridDisplay.getModel();
table.append(temp);
JScrollPane gridScroll = new JScrollPane(gridDisplay);
mainPanel.add(toolBox, BorderLayout.NORTH);
mainPanel.add(gridScroll, BorderLayout.CENTER);
add(mb, BorderLayout.NORTH);
add(mainPanel, BorderLayout.CENTER);
setSize(1280,720);
setVisible(true);
}
]
//myTableModel class
public class MyTableModel extends AbstractTableModel {
ArrayList<MyDataModel> data;
String[] names;
MyTableModel()
{
names = new String[]{"Type","Variable name","Text","Row","Column","Rows","Columns","Fill","Anchor"};
data = new ArrayList<MyDataModel>();
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return names.length;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
switch (columnIndex)
{
case 0:
data.get(rowIndex).setType(aValue.toString());
case 1:
data.get(rowIndex).setName(aValue.toString());
case 2:
data.get(rowIndex).setText(aValue.toString());
case 3:
data.get(rowIndex).setRow((int)aValue);
case 4:
data.get(rowIndex).setColumn((int)aValue);
case 5:
data.get(rowIndex).setRows((int)aValue);
case 6:
data.get(rowIndex).setColumns((int)aValue);
case 7:
data.get(rowIndex).setFill((int)aValue);
case 8:
data.get(rowIndex).setAnchor((int)aValue);
}
fireTableCellUpdated(rowIndex, columnIndex);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex){
case 0:
return data.get(rowIndex).getType();
case 1:
return data.get(rowIndex).getName();
case 2:
return data.get(rowIndex).getText();
case 3:
return data.get(rowIndex).getRow();
case 4:
return data.get(rowIndex).getColumn();
case 5:
return data.get(rowIndex).getRows();
case 6:
return data.get(rowIndex).getColumns();
case 7:
return data.get(rowIndex).getFill();
case 8:
return data.get(rowIndex).getAnchor();
}
return null;
}
public void append(MyDataModel item)
{
data.add(item);
}
#Override
public String getColumnName(int column) {
return names[column];
}
}
//MyDataModel Class
public class MyDataModel {
String type, name, text;
int row, column, rows, columns, fill, anchor;
MyDataModel()
{
type = new String("");
name = new String("");
text = new String("");
row = 0;
column = 0;
rows = 0;
columns = 0;
fill = 0;
anchor = 0;
}
public MyDataModel(MyDataModel test) {
type = test.getType();
name = test.getName();
text = test.getText();
row = test.getRow();
column = test.getColumn();
rows = test.getRows();
columns = test.getColumns();
fill = test.getFill();
anchor = test.getAnchor();
}
public int getAnchor() {
return anchor;
}
public void setAnchor(int anchor) {
this.anchor = anchor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getColumns() {
return columns;
}
public void setColumns(int columns) {
this.columns = columns;
}
public int getFill() {
return fill;
}
public void setFill(int fill) {
this.fill = fill;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
it doesn't seem to actually update into the display.
The value you select from the combo box is not being saved in the TableModel.
Your TableModel needs to implement the setValueAt(...) method.
See the section from the Swing tutorial on Create a Table Model for a simple implementation. It also shows you what fireXXX(...) method to invoke so the table is notified of the change in data.
You're missing a bit from your model including setValueAt(...), isCellEditable(...), and you forgot to call fireTableRowsInserted(...) inside of your append method.
e.g.,
public void append(MyDataModel item) {
data.add(item);
// !! don't forget this!!
int firstRow = getRowCount() - 1;
int lastRow = firstRow;
fireTableRowsInserted(firstRow, lastRow);
}
#Override
public String getColumnName(int column) {
return names[column];
}
#Override //!!
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0; // allow editing of first column
}
#Override //!!
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
MyDataModel row = data.get(rowIndex);
row.setType(aValue.toString());
fireTableCellUpdated(rowIndex, columnIndex);
return;
}
super.setValueAt(aValue, rowIndex, columnIndex);
}
You will want to re-read the JTable tutorial because you're skipping a lot of key concepts.
And I forgot -- you also need to override public boolean isCellEditable(int row, int col) and have it return true, at least for the JComboBox column, else you'll never see combo boxes since it is an editor.
I add items to a model that is linked to a table. When I select an item in this table, things happen depending on what item it is. For now I just have a System.out telling me the items name.
If I have two items called 'A' and 'B', when I select either their respective name is written to the console as expected, however, if I sort them by name, so that 'B' is placed in the row over 'A', the sorting never happened internally but only visually. So if I now select 'A', the console prints out 'B', and vice versa.
The sorter is declared in the mainclass, itemList is a JTable itemList.setAutoCreateRowSorter(true);
Apparently I must have failed to include some default method that's needed for this sorterfunctionality. "default methods" is declared towards the end in the code-snippet, from and after the method 'getColumnName'.
class ItemModel extends AbstractTableModel
{
ArrayList<MCItem> items = new ArrayList<MCItem>();
private int currentMaxRows = 0;
private String[] columnNames = {"Item", "Total Units", "In Sorter"};
private Class[] types = {String.class, Integer.class, Integer.class};
private Object[][] data = new Object[currentMaxRows][getColumnCount()];
public ArrayList<MCItem> getItems()
{
return items;
}
public void readdItems(Main m, ArrayList<MCItem> tempItems)
{
for(MCItem mci : tempItems)
{
mci.setMain(m);
addRow(mci);
}
}
public void emptyMe()
{
currentMaxRows = 0;
items.clear();
data = new Object[currentMaxRows][getColumnCount()];
fireTableDataChanged();
}
public boolean isDuplicate(String s)
{
for(MCItem ci : items)
if(ci.getName().equalsIgnoreCase(s))
return true;
return false;
}
public void updateItem(String id)
{
try
{
int foundRow = -1;
for(int i = 0;i < currentMaxRows;i++)
if(getValueAt(i, 0).toString().equalsIgnoreCase(id))
{
foundRow = i;
break;
}
for(MCItem ii : items)
if(ii.getName().equalsIgnoreCase(id))
{
setItem(foundRow, ii);
fireTableDataChanged();
return;
}
}
catch(NullPointerException e){}
}
public void addRow(MCItem item)
{
//check if we need to expand the dataArray
if(currentMaxRows == items.size())
{
if(currentMaxRows == 0)
data = new Object[++currentMaxRows][getColumnCount()];
else
{
Object[][] tempArr = data;
data = new Object[++currentMaxRows][getColumnCount()];
for(int x = 0; x < tempArr.length; x++)
for(int y = 0; y < getColumnCount(); y++)
data[x][y] = tempArr[x][y];
}
}
setItem(items.size(), item);
items.add(item);
fireTableDataChanged();
}
public void changeItem(int row, String name)
{
String originalName = (String) data[row][0];
data[row][0] = name;
for(MCItem ii : items)
if(ii.getName().toString().equalsIgnoreCase(originalName))
{
ii.setName(name);
return;
}
fireTableDataChanged();
}
public void removeItem(String id)
{
for(MCItem ii : items)
if(ii.getName().toString().equalsIgnoreCase(id))
{
items.remove(ii);
redoList();
return;
}
fireTableDataChanged();
}
private void redoList()
{
ArrayList<MCItem> tempArr = (ArrayList<MCItem>) items.clone();
emptyMe();
for(MCItem ii : tempArr)
addRow(ii);
}
private void setItem(int row, MCItem item)
{
int counter = 0;
data[row][counter++] = item.getName();
data[row][counter++] = item.getCount();
data[row][counter++] = item.getSorterCount();
fireTableDataChanged();
}
MCItem getMCItem(String name)
{
for(MCItem i : items)
if(i.getName().equals(name))
return i;
return null;
}
public String getColumnName(int col)
{
return columnNames[col].toString();
}
public int getRowCount()
{
return data.length;
}
public int getColumnCount()
{
return columnNames.length;
}
public Object getValueAt(int row, int col)
{
return data[row][col];
}
public Class getColumnClass(int columnIndex)
{
return this.types[columnIndex];
}
public boolean isCellEditable(int row, int col)
{
return false;
}
public void setValueAt(Object value, int row, int col)
{
data[row][col] = value;
fireTableCellUpdated(row, col);
}
}
* Answer *
The issue was never the tablemodel, but the JTable itself. When I want to present information based on the item selected, I called
currentMCItem = model.getMCItem(model.getValueAt(itemList.getSelectedRow(), 0).toString());
which returned the index in the JTable correctly, however when sorting all the indexes gets messed up and it's only the view that changes, so I had to redo that line to
currentMCItem = model.getMCItem(model.getValueAt(itemList.convertRowIndexToModel(itemList.getSelectedRow()), 0).toString());
So, the key is to call JTable.convertRowIndexToModel(SELECTED INDEX IN TABLE) in order to get the correct index, and use that as if it was the selectedRow.
You have a set of convert methods in JTable that you need to use. For example, convertColumnIndexToModel takes a view index and gives you back a corresponding column index in the model. Convert them and then get the values.
How can I print three different tables side by side or add them together in one printing? since the following code prints separately and in different pages.
I have little knowledge with the printing aspect of JTable's.
I am using NetBeans 8.0.
Or could I instead import the data to an excel file and print it from there? Is that plausible?
edit: All three tables must be together, side by side when it print, regardless if its portrait or landscape. Even better if all the tables or joined and is represented by multiple columns instead of three separate tables.
PrinterJob job = PrinterJob.getPrinterJob();
PrintRequestAttributeSet asset = new HashPrintRequestAttributeSet();
PageFormat pf = job.pageDialog(asset);
job.setPrintable(new recording_system(), pf);
boolean ok = job.printDialog(asset);
if (ok) {
try {
jTstudents.print(JTable.PrintMode.NORMAL);
jTscores.print(JTable.PrintMode.NORMAL);
jTresults.print(JTable.PrintMode.NORMAL);
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
The tables look like this
Implement a TableModel class that combines all models.
TableModel model = new ParallelTableModel(jTStudents.getModel(),
jTScores.getModel(),
TResults.getModel());
JTable totalTable = new JTable(model);
Copy table header.
And then totalTable.getPrintable for printing.
/**
* Table Model composed from side-by-side table models.
*/
public class ParalleTableModel extends AbstractTableModel {
private final TableModel[] models;
public ParalleTableModel(TableModel... models) {
this.models = models;
}
#Override
public int getRowCount() {
return models[0].getRowCount();
}
#Override
public int getColumnCount() {
int count = 0;
for (TableModel model : models) {
count += model.getColumnCount();
}
return count;
}
#Override
public String getColumnName(int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getColumnName(columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getColumnClass(columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.isCellEditable(rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
return model.getValueAt(rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
int count = 0;
for (TableModel model : models) {
int n = model.getColumnCount();
if (columnIndex < count) {
model.setValueAt(aValue, rowIndex, columnIndex - count);
}
count += n;
}
throw new IndexOutOfBoundsException();
}
}
I'm trying to read a csv file and get it setup to convert into another format to save some time at work, but the JTable i'm loading it into throws an exception when a row has a length less than the expected column. Is there a method to create an empty cell if row length < column length?
here is the table model:
private class CSVTableModel extends AbstractTableModel{
private ArrayList<String[]> list;
private String[] columns;
public CSVTableModel() {
this.list = p.getData();
this.columns = p.getHeaders();
}
#Override
public String getColumnName(int col) {
return columns[col];
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public int getColumnCount() {
return columns.length;
}
#Override
public Object getValueAt(int row, int col) {
return list.get(row)[col];
}
#Override
public void setValueAt(Object value, int row, int col) {
list.get(row)[col] = (String) value;
this.fireTableCellUpdated(row, col);
}
}
So you can see with the getValueAt(int row, int col) method it will cause an error if the col exceeds the String[].length.
I literally solved it after posting. Rubber duck debugging.
#Override
public Object getValueAt(int row, int col) {
if ( col < list.get(row).length ) {
return list.get(row)[col];
} else {
return "";
}
}
added a condition and works fine now. Should've seen it before.