Using a list of strings, I am trying to match the string in a excel sheet and add the cell elements in the inner list. Adding the inner list in the outer list using a loop. Please refer the code below
public static List<ArrayList<String>> getKeywords(List<String> testCaseIdList, String fileName, String sheetName){
try {
ArrayList<String> listTestSteps = new ArrayList<String>();
List<ArrayList<String>> listTestCases = new ArrayList<ArrayList<String>>(0);
Sheet sheetKW = ReadExcelFile.readExcel(ST_KEYWORDS);
String columnValue = null;
int matchFlag, addListFlag = 0;
for(String testCaseId : testCaseIdList) {
Iterator<Row> rowIterator = sheetKW.rowIterator();
listTestSteps.clear();
while(rowIterator.hasNext()) {
Row rowNext = (Row) rowIterator.next();
Iterator<Cell> cellIterator = rowNext.cellIterator();
matchFlag = 0;
addListFlag = 0;
//listTestSteps.clear();
while(cellIterator.hasNext()) {
Cell nextCell = cellIterator.next();
columnValue = nextCell.getStringCellValue();
//System.out.println("Column value " +columnValue);
if((columnValue.equalsIgnoreCase(testCaseId)) && (columnValue != "" )) {
matchFlag = 1;
}
if(matchFlag == 1 && columnValue != "") {
listTestSteps.add(columnValue);
addListFlag = 1;
System.out.println("Add Value : "+columnValue);
}
}
if((listTestSteps.isEmpty() == false) && (addListFlag == 1)) {
System.out.println("Adding to the Main list");
listTestCases.add(listTestSteps);
//listTestCases.forEach(System.out::println);
}
}
}
//listTestSteps.forEach(System.out::println);
// Return ArrayList of ArrayLists
return listTestCases;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
I am getting the output as
[TC_0003, login, createUser, deleteUser]
[TC_0003, login, createUser, deleteUser]
Firstly added list listTestSteps is getting replaced by the last iteration list.
Expected output is
[[TC_0002, login, createUser, deleteUser, newUser], [TC_0003, login, createUser, deleteUser]]
Something is wrong for sure. Any help will be appreciated.
Using the
listTestSteps.clear();
instruction in the loop lets you use always the same list, so in every iteration you just empty and refill the same list and add it to the outer list. For this reason the outer list will at the end contain x entries pointing always at the same list, which is filled with the data you put there in last iteration.
So you just have to do
ArrayList<String> listTestSteps = new ArrayList<String>();
instead of clearing the list
The problem is you add the reference of listTestSteps to listTestCases and then in the next loop you clear the listTestSteps, but the cleared list is still referenced in listTestCases. So would suggest using the answer to Add an object to an ArrayList and modify it later to ensure that both lists are resolved properly.
Related
I have List which has names. I am providing name by using Scanner by using advance for loop and checking if the name is in the list it will update the client table else it will update . Category and client table both are in database .The problem is if my list has 4 names it should check if condition only and not go to the else statement till it check the 4 names , if name is not there than(which i give from scanner) should go to else condition needed a logic
String n = scann.nextLine();
List<String> li = new ArrayList<>();
li.add("abc");
li.add("def");
li.add("ghi");
li.add("jkl");
for (int i = 0; i < li.size(); i++) {
if (n.equals(li.get(i))) {
System.out.println("client table update");
} else {
System.out.println("category and client table update");
}
}
}
I kinda get the gist of what you are asking, but please be more precise.
From what i understand from your question is, you want to print either the first or the second thing, depending on wether your name is in the list or not. And in your case, both get printed.
That is because your prints are inside the for loop, thus printing 4 times and printing both options regardless, since your name cant be all 4 names at the same time.
Here is how i would solve this:
List<String> li = new ArrayList<>();
li.add("abc");
li.add("def");
li.add("ghi");
li.add("jkl");
boolean inList = false;
for (int i = 0; i < li.size(); i++) {
if (n.equals(li.get(i))) {
inList = true;
}
}
if (inList) {
System.out.println("client table update");
} else {
System.out.println("category and client table update");
}
You can simply use contains() to check whether the name exists in the list i.e.
if(li.contains(n)){
System.out.println("client table update");
}
else{
System.out.println("category and client table update");
}
String n = scann.nextLine();
List<String> li = new ArrayList<>();
li.add("abc");
li.add("def");
li.add("ghi");
li.add("jkl");
for (String data : li) {
if (li.contains(n)) {
System.out.println("client table update");
} else {
System.out.println("category and client table update");
}
}
I was trying to scrape the data of a website and to some extents I succeed in my goal. But, there is a problem that the web page I am trying to scrape have got multiple HTML tables in it. Now, when I execute my program it only retrieves the data of the first table in the CSV file and not retrieving the other tables. My java class code is as follows.
public static void parsingHTML() throws Exception {
//tbodyElements = doc.getElementsByTag("tbody");
for (int i = 1; i <= 1; i++) {
Elements table = doc.getElementsByTag("table");
if (table.isEmpty()) {
throw new Exception("Table is not found");
}
elements = table.get(0).getElementsByTag("tr");
for (Element trElement : elements) {
trElement2 = trElement.getElementsByTag("tr");
tdElements = trElement.getElementsByTag("td");
File fold = new File("C:\\convertedCSV9.csv");
fold.delete();
File fnew = new File("C:\\convertedCSV9.csv");
FileWriter sb = new FileWriter(fnew, true);
//StringBuilder sb = new StringBuilder(" ");
//String y = "<tr>";
for (Iterator<Element> it = tdElements.iterator(); it.hasNext();) {
//Element tdElement1 = it.next();
//final String content2 = tdElement1.text();
if (it.hasNext()) {
sb.append("\r\n");
}
for (Iterator<Element> it2 = trElement2.iterator(); it.hasNext();) {
Element tdElement2 = it.next();
final String content = tdElement2.text();
//stringjoiner.add(content);
//sb.append(formatData(content));
if (it2.hasNext()) {
sb.append(formatData(content));
sb.append(" , ");
}
if (!it.hasNext()) {
String content1 = content.replaceAll(",$", " ");
sb.append(formatData(content1));
//it2.next();
}
}
System.out.println(sb.toString());
sb.flush();
sb.close();
}
System.out.println(sampleList.add(tdElements));
}
}
}
What I analyze is that there is a loop which is only checking tr tds. So, after first table there is a style sheet on the HTML page. May be due to style sheet loop is breaking. I think that's the reason it is proceeding to the next table.
P.S: here's the link which I am trying to scrap
http://www.mufap.com.pk/nav_returns_performance.php?tab=01
What you do just at the beginning of your code will not work:
// loop just once, why
for (int i = 1; i <= 1; i++) {
Elements table = doc.getElementsByTag("table");
if (table.isEmpty()) {
throw new Exception("Table is not found");
}
elements = table.get(0).getElementsByTag("tr");
Here you loop just once, read all table elements and then process all tr elements for the first table you find. So even if you would loop more than once, you would always process the first table.
You will have to iterate all table elements, e.g.
for(Element table : doc.getElementsByTag("table")) {
for (Element trElement : table.getElementsByTag("tr")) {
// process "td"s and so on
}
}
Edit Since you're having troubles with the code above, here's a more thorough example. Note that I'm using Jsoup to read and parse the HTML (you didn't specify what you are using)
Document doc = Jsoup
.connect("http://www.mufap.com.pk/nav_returns_performance.php?tab=01")
.get();
for (Element table : doc.getElementsByTag("table")) {
for (Element trElement : table.getElementsByTag("tr")) {
// skip header "tr"s and process only data "tr"s
if (trElement.hasClass("tab-data1")) {
StringJoiner tdj = new StringJoiner(",");
for (Element tdElement : trElement.getElementsByTag("td")) {
tdj.add(tdElement.text());
}
System.out.println(tdj);
}
}
}
This will concat and print all data cells (those having the class tab-data1). You will still have to modify it to write to your CSV file though.
Note: in my tests this processes 21 tables, 243 trs and 2634 tds.
below is the code for reading the excel file using poi: which is working fine
public class ReadExcelDemo {
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("demo.xlsx"));
List sheetData = new ArrayList();
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
ArrayList<Form> vipList = new ArrayList<Form>();
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
List data = new ArrayList();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: System.out.print(cell.getNumericCellValue() + "\t");
break;
case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue() + "\t");
break;
}
}
}
}
Now if excel contains duplicate records I should be able to print a simple error message. How do I do that?
Example:
ID Firstname Lastname Address
1 Ron wills Paris
1 Ron wills London
Now i want to check the duplicates only for the 3 columns: ID,Firstname and Lastname together. If these columns together contain same data as shown in the above example then it needs to be considered duplicate.
I have a pojo class Form consisting of the id,firstname and lastname with getters
and setters. Each record read is written to the pojo class using the setter methods. Then I am getting the values using getters and adding them to the arraylist object. Now the list object contains all the records. How do I compare them?
Throw the data in a set and check contains before every new entry. If you use a HashSet it will be quite quick. You can just pretend everything is Strings for the compare.
Set data = new HashSet();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if(data.contains(cell.getStringCellValue())
trow new IllegalDataException()
data.add(cell.getStringCellValue();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: System.out.print(cell.getNumericCellValue() + "\t");
break;
case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue() + "\t");
break;
}
}
If you need to actually compare the whole row you can create a class with all the fields, and then just override the equals method. Then throw that in a set and compare.
public class ProcessAction extends DispatchAction {
String dupValue = null;
ArrayList<String> dupList = new ArrayList<String>();
private String validateDuplicateRecords(ProcessForm process) {
String errorMessage = null;
dupValue = process.getId.trim()+" "+process.getFirstname().trim()+" "+process.getLastanme().trim();
mLogger.debug("order id,ctn,item id: "+dupValue);
if (dupList.contains(dupValue)){
mLogger.debug("value not added");
errorMessage = "Duplicate Record Exists";
} else {
dupList.add(dupValue);
}
return errorMessage;
}
}
Don't forget to clear the duplicate arraylist. I my case after performing certain tasks like writing the arraylist to a file i am clearing the duplicate arraylist using:
dupList.clear();
If you don't do this then what happens is when you upload the same data once more even if the records are not duplicate it will say duplicate since the dupList arraylist contains the previous uploaded data.
Here's a tip. While you loop, add your id (value to check the duplication based on) in a hashmap. if the size of the map did not change, then it is a duplicated record because keys overwrite each other if they already exist. Here's an example from a code of mine:
switch(cellType)
{
case 0:
your_id = cell1.getNumericCellValue();
mapSize = map.size();
map.put(your_id, your_id);
mapSizeAfterPut = map.size();
if(mapSize == mapSizeAfterPut)
{
duplicatedRecordsList.add(index);
}
break;
case 1:
your_id = cell1.getStringCellValue();
mapSize = map.size();
map.put(your_id , your_id);
mapSizeAfterPut = map.size();
if(mapSize == mapSizeAfterPut)
{
duplicatedRecordsList.add(index);
}
break;
default:break;
}
All,
Good Morning!
I have an excel file with data listed as the following, I'm trying to parse down using POI
A
B
C
D1
D2
F
G1
G2
G3
M
S1
R
T
U
L
X
Y
Z
is it possible to generate an output like the following
A
A-->B
A-->B-->C
A-->B-->C-->D1
A-->B-->C-->D2
A-->B-->F
A-->B-->F-->G1
A-->B-->F-->G2
A-->B-->F-->G3
A-->B-->M
A-->B-->M-->S1
A-->R
A-->R-->T
A-->U
L
L-->X
L-->X-->Y
L-->X-->Y-->Z
I have been trying from quite some time but havent figured out the logic
Thanks
Solution in Java, using Apache POI:
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ParseTreeDemo
{
private static final int NUM_COLUMNS = 4;
public static void main(String[] args)
{
try
{
FileInputStream file = new FileInputStream(new File("Test.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
// Use a column marker to save the 'farthest' column so far
int currColMarker = -1;
List<String> list = new ArrayList<>();
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
for(int currCol = 0; currCol < NUM_COLUMNS; currCol++)
{
Cell cell = row.getCell(currCol);
if(cell == null)
continue;
if(cell.getCellType() == Cell.CELL_TYPE_STRING) {
if(currCol > currColMarker) {
// A farther column, simply append and
// update column marker
currColMarker = currCol;
list.add(cell.getStringCellValue());
}
else if (currCol == currColMarker) {
// At same level as column marker
// Remove old value at same level, before appending
list.remove(list.size() - 1);
list.add(cell.getStringCellValue());
}
else {
// At a 'nearer' column, remove those values beyond
// this level before appending
currColMarker = currCol;
list = list.subList(0, currCol);
list.add(cell.getStringCellValue());
}
}
}
// For displaying the current contents
StringBuilder sb = new StringBuilder();
for(String s : list) {
if(sb.length() != 0) {
sb.append("-->");
}
sb.append(s);
}
System.out.println(sb.toString());
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Output:
A
A-->B
A-->B-->C
A-->B-->C-->D1
A-->B-->C-->D2
A-->B-->F
A-->B-->F-->G1
A-->B-->F-->G2
A-->B-->F-->G3
A-->B-->M
A-->B-->M-->S1
A-->R
A-->R-->T
A-->U
L
L-->X
L-->X-->Y
L-->X-->Y-->Z
The idea:
Use a 'column marker' to keep track of the active column
If the new value is at a column, with a larger column value, append
If it has the same column value, remove the last value, and append
If it has a smaller column value, remove all current values beyond the new column value, before appending
Note: Test.xlsx contains the values as stated in the question.
If the listed data is in a variable called data, the following will work in Tcl:
proc merge {a b} {
set res {}
foreach ac [split $a {}] bc [split $b {}] {
if {![string is space $ac] && [string is space -strict $bc]} {
append res $ac
} else {
append res $bc
}
}
set res
}
set current {}
foreach line [split [string trim $data] \n] {
set current [merge $current [string trimright $line]]
puts [join $current -->]
}
I originally went with a pseudo-stack approach, but it seemed simpler to "merge" each new line with the accumulated line (current) such that non-blank text in the new line would overwrite text in the accumulated line, and that the accumulated line would be truncated if the new line was shorter (after trimming off trailing whitespace from it).
Once I had the merged line, I could take advantage of the fact that (most) strings in Tcl are also lists, and print it as a string formed by joining the words using "-->" tokens.
Documentation: append, foreach, if, proc, puts, set, split, string
I have imported my excel file but i want to check duplicate cells in excel sheet .
I want to check each cell read and duplicate cell display alert message in jsp page.
Iterator obj = new Itertor();
StringBuffer sb = new StringBuffer();
while(obj.hasNext()) {
Row myrow = (ROW) obj.next();
class obj1 = new class();
obj1.setname();
}
I don't really understand your data structure. Are you using Apache POI? How are you obtaining the values from excel?
To identify duplicates create a HashSet and start adding values to the set. Add method returns true if the value was added. False otherwise.
Iterator sheetInterator = new Itertor();
Set<Object> set = new HashSet();
while(sheetInterator.hasNext()) {
Row myrow = (Row) obj.next();
Iterator rowIterator = myrow.iterator();
while(rowIterator.hasNext()) {
Cell cell = (Cell) rowIterator.next();
String value = cell.getValue();
if(!set.add(value)){
// value has not been added to the set -> it is at least 2nd occurrence of this value
}
}
}