I am doing a project in java swing in which I have to use a JTable.
By default jtable can validate the inputs (float,int) by turning into red when wrong input is given.
But I want to validate the empty cell left in the table at the time of save button click.
Here is my code:
public boolean validCheck() {
if (jTable.getCellEditor() != null) {
jTable.getCellEditor().stopCellEditing();
}
for (int i = 0; i < jTable3.getRowCount(); i++) {
for (int j = 0; j < jTable3.getColumnCount(); j++) {
String val = jTable3.getValueAt(row, col).toString();
if (val.trim().length() == 0) {
return false;(joptionpane.showmessagedialog(null,"field empty");)
}
}
}
return true;
}
This code is checking all the rows in the table and displaying the field empty message. I need to check only filled rows(rows which have data) not all the rows in the jtable.
Any suggestions would be helpful.
You need to change your logic to first look if a row had data at all. Then (and only then), take a second pass to validate that all columns in that row are filled.
Related
Currently I am going through a situation. There are three rows in a the body of the table. I have to perform some action on each row if row matches with a text. For this I am getting the size for the the rows and using for loop and checking the condition. When condition are met, I have to perform some action by which the row is getting removed from the webtable which is as per my expectations. Further, I am getting org.openqa.selenium.StaleElementReferenceException: here "totalOrders.get(i).click();" when the loop try to perform action in next row here
here is some part of my code:
By loading = By.xpath("//div[#class='loading-wrap']");
By orders = By.xpath("//tbody/tr"); //this retruns 3 row
public void invoiceAllStockOrder() {
eu.waitForInvisibilityOfElementLocated(loading, 10);
List<WebElement> totalOrders = eu.getElements(orders);
int rowSize =totalOrders.size();
if(rowSize == 0) {
System.out.println("No order");
}
else {
for (int i = 0; i < totalOrders.size(); i++) {
eu.waitForInvisibilityOfElementLocated(loading, 10);
totalOrders.get(i).click();//getting stale element exception here when i = 1 but there are still 2 rows left
selectInstockOrders();
invoiceOrder();
}
}
}
If the page has Javascript which automatically updates the DOM,
you should assume a StaleElementException will occur.
Can you try with the below code, I hope this will work for you
public boolean retryingFindClick(By by) {
boolean result = false;
int attempts = 0;
while(attempts < 2) {
try {
driver.findElement(by).click();
result = true;
break;
} catch(StaleElementException e) {
}
attempts++;
}
return result;
}
This will attempt to find and click the element. If the DOM changes
between the find and click, it will try again.
I am using the APACHE POI library to read an excel file in xlsx format.
My problem is that I want to remove the last row from each sheet of this excel, I found a way to find the last row to remove, but it returns an int. The method sheet.removeRow(Row var1); would solve my problem.
Well, having the row number that I want to delete and a method to delete that row. I just need to convert the lastRow (int) in a Row type so I can use the sheet.removeRow method.
To do that I used the following code: Row a = sheet.getRow(lastRow) this method should return a Row with that index. But instead it returns NULL.
Any idea what I'm doing wrong or how to convert the line number I want to remove into a Row type?
Appreciate your help!
Here is an excerpt of the code that read my excel file
public static List<Measure> excelToMeasures(InputStream is, ProjectMeasureFile projectMeasureFile) throws IOException {
List<Measure> measures = new ArrayList<>();
try (Workbook workbook = new XSSFWorkbook(is)) {
for (int i = 0; i < 3; i++) {
Sheet sheet = workbook.getSheetAt(i);
int lastRow = sheet.getPhysicalNumberOfRows() -1;
removeRow(sheet, lastRow);
int rowNumber = 0;
for (Row row : sheet) {
// skip header
if (rowNumber == 0) {
rowNumber++;
continue;
}
Iterator<Cell> cellIterator = row.iterator();
List<Cell> cellObject = new ArrayList<>();
while (cellIterator.hasNext()) {
cellObject.add(cellIterator.next());
}
if (cellObject.size() > 0) {
Measure measure = new Measure();
measure.setArea(sheet.getSheetName());
measure.setCode(convertStringCell(cellObject.get(0)));
measure.setBehavior(convertStringCell(cellObject.get(1)));
measure.setHumanDependencyFactor(convertNumericCell(cellObject.get(2)));
Double measureType = convertToPercentage(measure.getHumanDependencyFactor());
measure.setHumanDependencyFactor(measureType);
measure.setMeasurementResults(convertNumericCell(cellObject.get(3)));
Double value = convertToPercentage(measure.getMeasurementResults());
measure.setMeasurementResults(value);
measure.setProjectMeasureFile(projectMeasureFile);
measures.add(measure);
}
rowNumber++;
}
}
} catch (Exception e) {
log.error("An error occurred when trying to parse the file.");
e.printStackTrace();
}
return measures;
}
And here is the method for removing a row:
public static void removeRow(Sheet sheet, int rowIndex) {
int lastRowNum = sheet.getPhysicalNumberOfRows() -1;
if (rowIndex == lastRowNum) {
Row removingRow = sheet.getRow(rowIndex);
sheet.getRow(rowIndex);
Row a = sheet.getRow(rowIndex);
if (removingRow != null) {
System.out.println(sheet.getRow(lastRowNum).getCell(0).toString());
sheet.removeRow(removingRow);
}
}
}
At first to title of your question: Sheet.getRow will return NULL by design. It returns NULL if the row behind the row index is not stored in sheet. So you always need to check for NULL after Sheet.getRow. Same is for Row.getCell which returns NULL by design for cells which are not stored in the row.
And Sheet.getPhysicalNumberOfRows is not the correct way to get the last row in sheet.
A Excel sheet only physically contains rows having cells stored in them. Rows which are completely empty are not physically stored. So if a sheet only contains data in rows 1, 2, 5, 6 and 7, then Sheet.getPhysicalNumberOfRows will return 5 but last row is 7.
There is Sheet.getLastRowNum to get the last row number (0-based) in sheet. So that would return 6 in the example above and sheet.getRow(6) would get the last row and not NULL.
But there is another problem to consider. In Excel rows might not be totally empty but only contains cells which are blank. Blank cells might be stored because they have cell formats or they had content before. Sheet.getLastRowNum gets the last stored row, even if this row only contains blank cells. So you need to check whether the row behind Sheet.getLastRowNum contains only blank cells by iterating over the cells and check for CellType.BLANK if you need the last filled row.
The following method gets the last filled row in a sheet. It returns NULL if no filled row was found.
Row getLastFilledRow(Sheet sheet) {
int lastStoredRowNum = sheet.getLastRowNum();
for (int r = lastStoredRowNum; r >= 0; r--) {
Row row = sheet.getRow(r);
if (row != null) {
for (Cell cell : row) {
if (cell.getCellType() != CellType.BLANK) return row;
}
}
}
return null;
}
a question about removing unused rows in jtable i am using DefualtTableModel my table already has some data & when i update it leave some columns empty to update theme later so they are null column.. i want to remove theme with a push button before saving data.. i actually tried this code:
private void btn_ClearActionPerformed(java.awt.event.ActionEvent evt) {
table.setAutoCreateRowSorter(true);
TableRowSorter sorter = (TableRowSorter) table.getRowSorter();
sorter.setRowFilter(new RowFilterImpl());
}
i also tried this:
private void btn_ClearActionPerformed(java.awt.event.ActionEvent evt) {
table.setAutoCreateRowSorter(true);
TableRowSorter sorter = (TableRowSorter) table.getRowSorter();
sorter.setRowFilter(new RowFilter<TableModel, Integer>() {
#Override
public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) {
boolean included = true;
Object cellValue = entry.getModel().getValueAt(entry.getIdentifier(), 0);
if (cellValue == null || cellValue.toString().trim().isEmpty()) {
included = false;
}
return included;
}
});
}
the code above is working but i don't like it becuase it resizes rows after filtering so i want to do something with model.remove(); using if conditions.. and i want to specify columns for example column 7 & 12 and want to remove only empty rows in specified columns..
ok i tried this code:
for (int i = model.getRowCount() - 1; i >= 0; i--)
{
Object col1 = model.getValueAt( i,model.getColumnCount() - 6);
Object col2 = model.getValueAt( i,model.getColumnCount() - 11);
if (col1 == null || col2 == null)
model.removeRow(i);
}
i faced same problem and i found this code below cuasing that problem so i removed it ... i also found that it counts how many time you selected or clicked on a row and then resizes it as many you clicked!
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
int lastRow = -1;
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
if (lastRow != -1) {
table.setRowHeight(lastRow, table.getRowHeight());
}
int row = table.getSelectedRow();
table.setRowHeight(row, 23);
lastRow = row;
}
}
});
any idea guys?
thanx in advance
Create a loop to remove the data from the model.
Maybe something like:
for (int i = model.getRowCount() - 1; i >= 0; i--)
{
if (column?? == null && column?? == null)
model.removeRow(i);
}
added the problem above in table.setRowHeight();
Well, that should have been part of the original question. How do we know you have custom logic doing something strange???
In the future post a proper SSCCE that demonstrates the problem so we don't have to guess what you are doing.
i get the same problem it resizes rows
Then remove the listener:
remove the listener
delete the rows
add the listener
I want to move datas from grid-table4 to grid-table3. The problem is grid-table4 can only hold one raw of data and when the function calls data from grid-table4 moves to 3, but I can not add any item into the grid-table4.
function reset() {
var RowList;
RowList = $('#grid-table4').getRowData();
var Row;
for (Row in RowList) {
$('#grid-table3').addRowData(Row, RowList[Row]);
}
$('#grid-table4').clearGridData();
}
It seems that you don't set any unique id values for the rows in the grids (rowid). It seems that only the data itself have an interest for you. In the case I would recommend you to generate new unique id vale for grid-table3 with respect of $.jgrid.randId().
function reset() {
var $gridSrc = $("#grid-table4"), $gridDest = $("#grid-table3"), i, data;
data = $gridSrc.jqGrid("getRowData");
if (data != null && data.length > 0) {
for (i = 0; i < data.length; i++) {
$gridDest.jqGrid("addRowData", $.jgrid.randId(), data[i]);
}
$gridSrc.jqGrid("clearGridData");
}
}
I have a JTable which has 2 columns
column 0 username
column 1 password.
for the password column it will be encrypted to SHA256.
Basically what I want to achieve is it will update all the rows in my password column to SHA256 that I have edited after my button is pressed.
so..
I have a RowData class, this will store the text being edited and the position of the text
being edited(rows,columns).
public class RowData {
int rows = 0, columns = 0;
String text = " ";
public RowData(String text,int rows, int columns) {
setEditedRows(rows);
setEditedColumns(columns);
setEditedText(text);
}
public int getEditedRows() {
return rows;
}
public int getEditedColumns() {
return columns;
}
public String getEditedText() {
return text;
}
public void setEditedRows(int rows) {
this.rows = rows;
}
public void setEditedColumns(int columns) {
this.columns = columns;
}
public void setEditedText(String text) {
this.text = text;
}
}
I wrote a TableModelListener.. I have an List to store the text and the rows and columns
after the table has changed
table.getModel().addTableModelListener(new TableModelListener() {
#Override
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel) e.getSource();
//System.out.println(model.getValueAt(row, column));
if(column == 1) {
String data = (String) model.getValueAt(row, column);
System.out.println(data);
dataList.add(new RowData(data,row,column));
}
}
});
In my button I loop through the list and retrieve the rows, and columns and text
and set the password to SHA256 to the JTable.
updateBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (table.getCellEditor() != null) {
table.getCellEditor().stopCellEditing();
for(int i = 0; i < dataList.size(); i++) {
String text = dataList.get(i).getEditedText();
int rows = dataList.get(i).getEditedRows();
int columns = dataList.get(i).getEditedColumns();
//System.out.println(dataList.get(i).getEditedText() + " " + dataList.get(i).getEditedRows() + dataList.get(i).getEditedColumns());
table.setValueAt(convertPassword.convertToSHA256(text), rows ,columns);
}
}
}
});
The result I get is I will keep printing the password endlessly in my console.
So I think that my logic is wrong and needed to be corrected.
table.setValueAt(convertPassword.convertToSHA256(text), rows ,columns);
When you change the TableModel the TableModelListener will be invoked again. The TableModelListener is invoked whether you change the data by using the JTable or by updating the TableModel directly.
The solution would be to remove the TableModelListener when you click on your button, at the start of your ActionListener. You would then need to add the TableModelListener back to the TableModel at the end of the code in case the user make further changes.
Another solution is to have 3 columns in the TableModel, username, password and sha256Password. Then you can use the JTable to display only the first two columns. See the removeColumn() method of JTable. Then your conversion code would update the TableModel using:
table.getModel().setValueAt(value, row, 2);
Now the code in your TableModel will be invoked, but because you check for updates to column 1, nothing will happen when you update column 2.
Then when you save the data you save the data from the TableModel.
Edit:
I must click into another cell before I can press my button to edit.
You need to stop the cell editing. See Table Stop Editing for a couple of solutions.