How to export table contents to csv using java? - java

Here I need to get the values from table instead of manual values like display name, age.
And I don't need to generate csv file in location. Instead, it should show me a popup that I can download the csv file. How to achieve this?
So far I tried this to export data to csv using java.
I used some manual values like display name, age. But I need the values to get from the table. For example
<table>
<td>
--datas--
</td>
</table>
Java Code:
import java.io.FileWriter;
import java.io.IOException;
public class test
{
public static void main(String [] args)
{
generateCsvFile("D:/test.csv");
}
private static void generateCsvFile(String sFileName)
{
try
{
FileWriter writer = new FileWriter(sFileName);
writer.append("DisplayName");
writer.append(',');
writer.append("Age");
writer.append('\n');
writer.append("Dinesh");
writer.append(',');
writer.append("23");
writer.append('\n');
writer.append("Kumar");
writer.append(',');
writer.append("29");
writer.append('\n');
//generate whatever data you want
writer.flush();
writer.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}

Suppose you have a jsp page with the table. While submitting the jsp page you can form the comma separated table value string from javascript by reading the table.
eg
//gets table
var table= document.getElementById('table1');
//gets rows of table
var rowLen = table.rows.length;
//loops through rows
for (i = 0; i < rowLen; i++){
var oCells = table.rows.item(i).cells;
var cellLen = oCells.length;
for(var j = 0; j < cellLen; j++){
/* get your cell info here */
/* var cellVal = oCells.item(j).innerHTML; */
}
}
and once you have the string of comma separated values, you can pass it to the action handling the submitted request.

I'm assuming you are generating your table dynamically and using httpSession, you can set the table in session like so:
HttpSession.setAttribute("Data", ArrayList<Object> data);
Then get the table from there when generating:
ArrayList<Object> data = this.context.getSession().getAttribute("Data");

Simple solution:
Use RegEx to extract only the inner part of the table (between the
<table></table> tags)
Use RegEx to remove all newlines between <tr></tr> and those tags
themselves (rows)
Use RegEx to replace "</td><td>" with ","
Use RegEx to remove remaining tags

Related

How do I read data from excel sheet and use data as an input for webpage using selenium ? I am able to read only 1 row at a time. Code displayed:

I have just started learning selenium and I am not able to automate the code only reads one at a time from excel.I need to make the code read from the excel automatically instead of changing the row count number in this line "for (int i= 1; i<=6; i++)."
How can I make it automatically read from the code below?
public static void main(String[] args) throws IOException, InterruptedException {
System.setProperty("driver location");
WebDriver driver = new FirefoxDriver();
driver.get("link");
FileInputStream file = new FileInputStream("xcel file location");
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet= workbook.getSheet("SO Reg");
int noOfRows = sheet.getLastRowNum(); // returns the row count
System.out.println("No. of Records in the Excel Sheet:" + noOfRows);
int cols=sheet.getRow(1).getLastCellNum();
System.out.println("No. of Records in the Excel Sheet:" + cols);
for (int i= 1; i<=6; i++)
{
String SO_Name = row.getCell(0).getStringCellValue();
String Contact_Person = row.getCell(1).getStringCellValue();
String Address_1 = row.getCell(2).getStringCellValue();
String Address_2 = row.getCell(3).getStringCellValue();
String City = row.getCell(4).getStringCellValue();
String State = row.getCell(5).getStringCellValue();
String ZipCode = row.getCell(6).getStringCellValue();
String Phone_Number = row.getCell(8).getStringCellValue();
String Username = row.getCell(9).getStringCellValue();
String Email = row.getCell(10).getStringCellValue();
String Re_Type_Email = row.getCell(11).getStringCellValue();
//Registration Process
driver.findElement(By.cssSelector("p.text-white:nth-child(4) > a:nth-child(1)")).click(); //create an account
Thread.sleep(5000);
//Enter Data information
driver.findElement(By.id("SOName")).sendKeys(SO_Name);
driver.findElement(By.xpath("//*[#id=\"ContactPerson\"]")).sendKeys(Contact_Person);
driver.findElement(By.xpath("//*[#id=\"AddressLine1\"]")).sendKeys(Address_1);
driver.findElement(By.xpath("//*[#id=\"AddressLine2\"]")).sendKeys(Address_2);
driver.findElement(By.id("City")).sendKeys(City);
driver.findElement(By.id("State")).sendKeys(State);
driver.findElement(By.id("ZipCode")).sendKeys(ZipCode);
driver.findElement(By.id("Phone")).sendKeys(Phone_Number);
driver.findElement(By.xpath("//*[#id=\"UserName\"]")).sendKeys(Username);
driver.findElement(By.xpath("//*[#id=\"Email\"]")).sendKeys(Email);
driver.findElement(By.xpath("//*[#id=\"RandText\"]")).sendKeys(Re_Type_Email);
driver.findElement(By.id("ConfirmBox")).click();
driver.findElement(By.xpath("/html/body/app-root/app-soregistration/div[2]/div/div/div/div/form[2]/div/div[12]/div/button[1]")).click();
driver.findElement(By.cssSelector(".btn-green-text-black")).click(); //finish button
driver.findElement(By.cssSelector("p.text-white:nth-child(4) > a:nth-child(1)")).click(); //create an account
Thread.sleep(5000);
}
}
}
}
}
Do you only want to process newly added rows in Excel? If so, you should also save your last stay.
First of all, you can simply keep it in an infinite loop. Like
while(true){...}
. You can also start your loop here by keeping the last line you read from Excel in a static variable.
For example:
for (int i= previusLastSavedRowNum; i<=getLastRowNum; i++) {...}
If there is no new record, you can wait for a while in the WHILE loop.
Of course, for a better solution, you can create a SpringBoot project and set up a structure that listens for changes in Excel. When Excel detects the change, you can call the Selenium code with a trigger.
Better way to handle it is to open the excel file as CSV.
You can read all the data into one String with:
String excelToString = new String(Files.readAllBytes(Paths.get(path_to_file)));
If you want to keep it as table you can parse this String into String [] [] table.

Create CSV file with columns and values from HashMap

Be gentle,
This is my first time using Apache Commons CSV 1.7.
I am creating a service to process some CSV inputs,
add some additional information from exterior sources,
then write out this CSV for ingestion into another system.
I store the information that I have gathered into a list of
HashMap<String, String> for each row of the final output csv.
The Hashmap contains the <ColumnName, Value for column>.
I have issues using the CSVPrinter to correctly assign the values of the HashMaps into the rows.
I can concatenate the values into a string with commas between the variables;
however,
this just inserts the whole string into the first column.
I cannot define or hardcode the headers since they are obtained from a config file and may change depending on which project uses the service.
Here is some of my code:
try (BufferedWriter writer = Files.newBufferedWriter(
Paths.get(OUTPUT + "/" + project + "/" + project + ".csv"));)
{
CSVPrinter csvPrinter = new CSVPrinter(writer,
CSVFormat.RFC4180.withFirstRecordAsHeader());
csvPrinter.printRecord(columnList);
for (HashMap<String, String> row : rowCollection)
{
//Need to map __record__ to column -> row.key, value -> row.value for whole map.
csvPrinter.printrecord(__record__);
}
csvPrinter.flush();
}
Thanks for your assistance.
You actually have multiple concerns with your technique;
How do you maintain column order?
How do you print the column names?
How do you print the column values?
Here are my suggestions.
Maintain column order.
Do not use HashMap,
because it is unordered.
Instead,
use LinkedHashMap which has a "predictable iteration order"
(i.e. maintains order).
Print column names.
Every row in your list contains the column names in the form of key values,
but you only print the column names as the first row of output.
The solution is to print the column names before you loop through the rows.
Get them from the first element of the list.
Print column values.
The "billal GHILAS" answer demonstrates a way to print the values of each row.
Here is some code:
try (BufferedWriter writer = Files.newBufferedWriter(
Paths.get(OUTPUT + "/" + project + "/" + project + ".csv"));)
{
CSVPrinter csvPrinter = new CSVPrinter(writer,
CSVFormat.RFC4180.withFirstRecordAsHeader());
// This assumes that the rowCollection will never be empty.
// An anonymous scope block just to limit the scope of the variable names.
{
HashMap<String, String> firstRow = rowCollection.get(0);
int valueIndex = 0;
String[] valueArray = new String[firstRow.size()];
for (String currentValue : firstRow.keySet())
{
valueArray[valueIndex++] = currentValue;
}
csvPrinter.printrecord(valueArray);
}
for (HashMap<String, String> row : rowCollection)
{
int valueIndex = 0;
String[] valueArray = new String[row.size()];
for (String currentValue : row.values())
{
valueArray[valueIndex++] = currentValue;
}
csvPrinter.printrecord(valueArray);
}
csvPrinter.flush();
}
for (HashMap<String,String> row : rowCollection) {
Object[] record = new Object[row.size()];
for (int i = 0; i < columnList.size(); i++) {
record[i] = row.get(columnList.get(i));
}
csvPrinter.printRecord(record);
}

Compare Two CSV Files and Fetch Data

I have two csv files. One Master CSV File around 500000 records. Another DailyCSV file has 50000 Records.
The DailyCSV files misses few columns which has to be fetched from Master CSV File.
For example
DailyCSV File
id,name,city,zip,occupation
1,Jhon,Florida,50069,Accountant
MasterCSV File
id,name,city,zip,occupation,company,exp,salary
1, Jhon, Florida, 50069, Accountant, AuditFirm, 3, $5000
What I have to do is, read both files, match the records with ID, if ID is present in the master file, then i have to fetch company, exp, salary and write it to a new csv file.
How to achieve this.??
What I have done Currently
while (true) {
line = bstream.readLine();
lineMaster = bstreamMaster.readLine();
if (line == null || lineMaster == null)
{
break;
}
else
{
while(lineMaster != null)
readlineSplit = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1);
String splitId = readlineSplit[4];
String[] readLineSplitMaster =lineMaster.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", -1);
String SplitIDMaster = readLineSplitMaster[13];
System.out.println(splitId + "|" + SplitIDMaster);
//System.out.println(splitId.equalsIgnoreCase(SplitIDMaster));
if (splitId.equalsIgnoreCase(SplitIDMaster)) {
String writeLine = readlineSplit[0] + "," + readlineSplit[1] + "," + readlineSplit[2] + "," + readlineSplit[3] + "," + readlineSplit[4] + "," + readlineSplit[5] + "," + readLineSplitMaster[15]+ "," + readLineSplitMaster[16] + "," + readLineSplitMaster[17];
System.out.println(writeLine);
pstream.print(writeLine + "\r\n");
}
}
}pstream.close();
fout.flush();
bstream.close();
bstreamMaster.close();
First of all, your current parsing approach will be painfully slow. Use a CSV parsing library dedicated for that to speed things up. With uniVocity-parsers you can process your 500K records in less than a second. This is how you can use it to solve your problem:
First let's define a few utility methods to read/write your files:
//opens the file for reading (using UTF-8 encoding)
private static Reader newReader(String pathToFile) {
try {
return new InputStreamReader(new FileInputStream(new File(pathToFile)), "UTF-8");
} catch (Exception e) {
throw new IllegalArgumentException("Unable to open file for reading at " + pathToFile, e);
}
}
//creates a file for writing (using UTF-8 encoding)
private static Writer newWriter(String pathToFile) {
try {
return new OutputStreamWriter(new FileOutputStream(new File(pathToFile)), "UTF-8");
} catch (Exception e) {
throw new IllegalArgumentException("Unable to open file for writing at " + pathToFile, e);
}
}
Then, we can start reading your daily CSV file, and generate a Map:
public static void main(String... args){
//First we parse the daily update file.
CsvParserSettings settings = new CsvParserSettings();
//here we tell the parser to read the CSV headers
settings.setHeaderExtractionEnabled(true);
//and to select ONLY the following columns.
//This ensures rows with a fixed size will be returned in case some records come with less or more columns than anticipated.
settings.selectFields("id", "name", "city", "zip", "occupation");
CsvParser parser = new CsvParser(settings);
//Here we parse all data into a list.
List<String[]> dailyRecords = parser.parseAll(newReader("/path/to/daily.csv"));
//And convert them to a map. ID's are the keys.
Map<String, String[]> mapOfDailyRecords = toMap(dailyRecords);
... //we'll get back here in a second.
This is the code to generate a Map from the list of daily records:
/* Converts a list of records to a map. Uses element at index 0 as the key */
private static Map<String, String[]> toMap(List<String[]> records) {
HashMap<String, String[]> map = new HashMap<String, String[]>();
for (String[] row : records) {
//column 0 will always have an ID.
map.put(row[0], row);
}
return map;
}
With the map of records, we can process your master file and generate the list of updates:
private static List<Object[]> processMasterFile(final Map<String, String[]> mapOfDailyRecords) {
//we'll put the updated data here
final List<Object[]> output = new ArrayList<Object[]>();
//configures the parser to process only the columns you are interested in.
CsvParserSettings settings = new CsvParserSettings();
settings.setHeaderExtractionEnabled(true);
settings.selectFields("id", "company", "exp", "salary");
//All parsed rows will be submitted to the following RowProcessor. This way the bigger Master file won't
//have all its rows stored in memory.
settings.setRowProcessor(new AbstractRowProcessor() {
#Override
public void rowProcessed(String[] row, ParsingContext context) {
// Incoming rows from MASTER will have the ID as index 0.
// If the daily update map contains the ID, we'll get the daily row
String[] dailyData = mapOfDailyRecords.get(row[0]);
if (dailyData != null) {
//We got a match. Let's join the data from the daily row with the master row.
Object[] mergedRow = new Object[8];
for (int i = 0; i < dailyData.length; i++) {
mergedRow[i] = dailyData[i];
}
for (int i = 1; i < row.length; i++) { //starts from 1 to skip the ID at index 0
mergedRow[i + dailyData.length - 1] = row[i];
}
output.add(mergedRow);
}
}
});
CsvParser parser = new CsvParser(settings);
//the parse() method will submit all rows to the RowProcessor defined above.
parser.parse(newReader("/path/to/master.csv"));
return output;
}
Finally, we can get the merged data and write everything to another file:
... // getting back to the main method here
//Now we process the master data and get a list of updates
List<Object[]> updatedData = processMasterFile(mapOfDailyRecords);
//And write the updated data to another file
CsvWriterSettings writerSettings = new CsvWriterSettings();
writerSettings.setHeaders("id", "name", "city", "zip", "occupation", "company", "exp", "salary");
writerSettings.setHeaderWritingEnabled(true);
CsvWriter writer = new CsvWriter(newWriter("/path/to/updates.csv"), writerSettings);
//Here we write everything, and get the job done.
writer.writeRowsAndClose(updatedData);
}
This should work like a charm. Hope it helps.
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).
I will approach the problem in a step by step manner.
First I will parse/read the master CSV file and keep its content into a hashmap, where the key will be each record's unique 'id' as for the value maybe you can store them in a hash or simply create a java class to store the information.
Example of hash:
{
'1' : { 'name': 'Jhon',
'City': 'Florida',
'zip' : 50069,
....
}
}
Next, read your comparer csv file. For each row, read the 'id' and check if the key exists on the hashmap you have created earlier.
if it exists, then from the hashmap access the information you need and write to a new CSV file.
Also, you might want to consider using a 3rd party CSV parser to make this task easier.
If you have maven maybe you can follow this example I found on net. Otherwise you can just google for apache 'csv parser' example on the internet.
http://examples.javacodegeeks.com/core-java/apache/commons/csv-commons/writeread-csv-files-with-apache-commons-csv-example/

using Jsoup to extract a table inside several divs

I am trying to use jsoup so as to have access to a table embedded inside multiple div's of an html page.The table is under the outer division with id "content-top". I will give the inner divs leading to the table: content-top -> center -> middle-right-col -> result .
Under the div result; is table round. This is the table that i want to access and whose rows I need to traverse and print out the data contained in them. Below is the java code I have been trying to use but yielding no results :
Document doc = Jsoup.connect("http://www.calculator.com/#").data("express", "sin(x)").data("calculate","submit").post();
// give the application time to calculate result before retrieving result from results table
try {
Thread.sleep(10000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
Elements content = doc.select("div#result") ;
Element tables = content.get(0) ;
Elements table_rows = tables.select("tr") ;
Iterator iterRows = table_rows.iterator();
while (iterRows.hasNext()) {
Element tr = (Element)iterRows.next();
Elements table_data = tr.select("td");
Iterator iterData = table_data.iterator();
int tdCount = 0;
String f_x_value = null;
String result = null;
// process new line
while (iterData.hasNext()) {
Element td = (Element)iterData.next();
switch (tdCount++) {
case 1:
f_x_value = td.text();
f_x_value = td.select("a").text();
break;
case 2:
result = td.text();
result = td.select("a").text();
break;
}
}
System.out.println(f_x_value + " " + result ) ;
}
The above code crashes and hardly does what I want it to do. PLEASE CAN ANYONE PLEASE HELP ME !!!
public static String do_conversion (String str)
{
char c;
String output = "{";
for(int i = 0; i < str.length(); i++)
{
c = str.charAt(i);
if(c=='e')
output += "{mathrm{e}}";
else if(c=='(')
output += '{';
else if(c==')')
output += '}';
else if(c=='+')
output += "{cplus}";
else if(c=='-')
output += "{cminus}";
else if(c=='*')
output += "{cdot}";
else if(c=='/')
output += "{cdivide}";
else output += c; // else copy the character normally
}
output += ", mathrm{d}x}";
return output;
}
#Syam S
The page doesnt directly give you a table in a div with id as "result". It uses an ajax class to a php file and get the process done. So what you need to do here is to first build a json like
{"expression":"sin(x)","intVar":"x","upperBound":"","lowerBound":"","simplifyExpressions":false,"latex":"\\displaystyle\\int\\limits^{}_{}{\\sin\\left(x\\right)\\, \\mathrm{d}x}"}
The expression key hold the expression that you want to evaluate, the latex is a mathjax expression and then post it to int.php. This expects two arguments namely q which is the above json and v which seems to a constant value 1380119311. I didnt understand what this is.
Now this will return a response like
<html>
<head></head>
<body>
<table class="round">
<tbody>
<tr class="">
<th>$f(x) =$</th>
<td>$\sin\left(x\right)$</td>
</tr>
<tr class="sep odd">
<th>$\displaystyle\int{f(x)}\, \mathrm{d}x =$</th>
<td>$-\cos\left(x\right)$</td>
</tr>
</tbody>
</table>
<!-- Finished in 155 ms -->
<p id="share"> <img src="layout/32x32xshare.png.pagespeed.ic.i3iroHP5fI.png" width="32" height="32" /> <a id="share-link" href="http://www.integral-calculator.com/#expr=sin%28x%29" onclick="window.prompt("To copy this link to the clipboard, press Ctrl+C, Enter.", $("share-link").href); return false;">Direct link to this calculation (for sharing)</a> </p>
</body>
</html>
The table in this expression gives you the result and the site uses mathjax to display it like
A sample program would be
import java.io.IOException;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class JsoupParser6 {
public static void main(String[] args) {
try {
// Integral
String url = "http://www.integral-calculator.com/int.php";
String q = "{\"expression\":\"sin(4x) * e^(-x)\",\"intVar\":\"x\",\"upperBound\":\"\",\"lowerBound\":\"\",\"simplifyExpressions\":false,\"latex\":\"\\\\displaystyle\\\\int\\\\limits^{}_{}{\\\\sin\\\\left(4x\\\\right){\\\\cdot}{\\\\mathrm{e}}^{-x}\\\\, \\\\mathrm{d}x}\"}";
Document integralDoc = Jsoup.connect(url).data("q", q).data("v", "1380119311").post();
System.out.println(integralDoc);
System.out.println("\n*******************************\n");
//Differential
url = "http://www.derivative-calculator.net/diff.php";
q = "{\"expression\":\"sin(x)\",\"diffVar\":\"x\",\"diffOrder\":1,\"simplifyExpressions\":false,\"showSteps\":false,\"latex\":\"\\\\dfrac{\\\\mathrm{d}}{\\\\mathrm{d}x}\\\\left(\\\\sin\\\\left(x\\\\right)\\\\right)\"}";
Document differentialDoc = Jsoup.connect(url).data("q", q).data("v", "1380119305").post();
System.out.println(differentialDoc);
System.out.println("\n*******************************\n");
//Calculus
url = "http://calculus-calculator.com/calculation/integrate.php";
Document calculusDoc = Jsoup.connect(url).data("expression", "sin(x)").data("intvar", "x").post();
String outStr = StringEscapeUtils.unescapeJava(calculusDoc.toString());
Document formattedOutPut = Jsoup.parse(outStr);
formattedOutPut.body().html(formattedOutPut.select("div.isteps").toString());
System.out.println(formattedOutPut);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Update based on comment.
The unescape works perfectly well. In MathJax you could right click and view the command. So if you go to your site http://calculus-calculator.com/ and try the sin(x) equation there and right click the result and view TexCommand like
The you could see the commands are exactly the ones which we get after unsescape. The demo site is not rendering it. May be a limitation of the demo site, thats all.

Storing MySQL query results in an ArrayList using Java

The following java code takes in a POST request from a JSP file and passes back the out ArrayList as output. The problem I'm having is figuring out how to read the output into the Arraylist properly, so they I can grab each element from the Arraylist and display it in my JSP.
How can I read in the column names as the first array of strings, and then each row of data as the following arrays of strings, so that I have one giant array list that contains the entire results of the query in an organized manner, and will allow me to read the results onto my JSP page?
EDIT:
So the only problem I'm having now is that when executing a command like SELECT * FROM table; it only shows the column names. But when I execute a command like SELECT columnName FROM table; it displays the column perfectly. The code below has been updated to reflect where I am at now.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.sql.*;
import java.util.ArrayList;
#SuppressWarnings("serial")
public class databaseServlet extends HttpServlet {
private Connection conn;
private Statement statement;
public void init(ServletConfig config) throws ServletException {
try {
Class.forName(config.getInitParameter("databaseDriver"));
conn = DriverManager.getConnection(
config.getInitParameter("databaseName"),
config.getInitParameter("username"),
config.getInitParameter("password"));
statement = conn.createStatement();
}
catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ArrayList<String[]> out = new ArrayList<String[]>();
ArrayList<String> columns = new ArrayList<String>();
String query = request.getParameter("query");
if (query.toString().toLowerCase().contains("select")) {
//SELECT Queries
//try {
ResultSet resultSet = statement.executeQuery(query.toString());
ResultSetMetaData metaData = resultSet.getMetaData();
int numberOfColumns = metaData.getColumnCount();
for(int i = 1; i<= numberOfColumns; i++){
columns.add(metaData.getColumnName(i));
}
while (resultSet.next()){
String[] row = new String[numberOfColumns];
for (int i = 0; i < numberOfColumns; i++){
row[i] = (String) resultSet.getObject(i+1);
}
out.add(row);
}
//}
//catch (Exception f) {
//f.printStackTrace();
//}
}
else if (query.toString().toLowerCase().contains("delete") || query.toLowerCase().contains("insert")) {
//DELETE and INSERT commands
//try {
conn.prepareStatement(query.toString()).executeUpdate(query.toString());
columns.add("\t\t Database has been updated!");
//}
//catch (Exception l){
//l.printStackTrace();
//}
}
else {
//Not a valid response
columns.add("\t\t Not a valid command or query!");
}
request.setAttribute("query", query);
request.setAttribute("resultSize", out.size());
request.setAttribute("queryResults", out);
request.setAttribute("queryColumns", columns);
RequestDispatcher dispatcher = request.getRequestDispatcher("/dbServlet.jsp");
dispatcher.forward(request, response);
}
}
Here is my .JSP file, and right now it is only printing [] with nothing in it when I execute a command. I know that commands are working because of previous tests, but the array is not displaying properly.
<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- dbServlet.html -->
<html xmlns = "http://www.w3.org/1999/xhtml">
<%# page import="java.util.ArrayList" %>
<head>
<title>MySQL Servlet</title>
<style type="text/css">
body{background-color: green;}
</style>
</head>
<body>
<h1>This is the MySQL Servlet</h1>
<form action = "/database/database" method = "post">
<p>
<label>Enter your query and click the button to invoke a MySQL Servlet
<textarea name = "query" cols="20" rows="5"></textarea>
<input type = "submit" value = "Run MySQL Servlet" />
<input type = "reset" value = "Clear Command" />
</label>
</p>
</form>
<hr>
<TABLE id="results">
<%
ArrayList<String> columns = (ArrayList<String>)request.getAttribute("queryColumns");
ArrayList<String[]> results = (ArrayList<String[]>)request.getAttribute("queryResults");
out.println("<TR>");
if(columns != null && !columns.isEmpty()){
for(String columnName: columns ){
out.println("<TD>"+columnName+"</TD>");
}
}
out.println("</TR>");
//print data
if(results != null && !results.isEmpty()){
for(String[] rowData: results){
out.println("<TR>");
for(String data: rowData){
out.println("<TD>"+data+"</TD>");
}
out.println("</TR>");
}
}
%>
</TABLE>
<%= request.getAttribute("query") %>
<%= request.getAttribute("resultSize") %>
</body>
</html>
Define one list for columns as well.
ArrayList<String[]> results= new ArrayList<String[]>();
ArrayList<String> columns= new ArrayList<String>();
Populate the list of columns as:
for(int i = 1; i<= numberOfColumns; i++){
columns.add(metaData.getColumnName(i));
}
Populate the list of with results row as:
while (resultSet.next()){
String[] row = new String[numberOfColumns];
for (int i = 1; i <= numberOfColumns; i++){
row[i] = (String) resultSet.getObject(i);
}
results.add(row);
}
in the end:
request.setAttribute("queryResults", results);
request.setAttribute("queryColumns", columns);
First of all, why are you adding a toString call on a String type variable?
Now, as for your issue, I would rather create a Class, for the tables in database, with the columns as attributes. And for each row, create an instance of that class from the columns, and add it to the ArrayList.
So, your ArrayList declaration might be like this: -
List<TargetTable> records = new ArrayList<TargetTable>();
And then: -
while (res.next()) {
records.add(new TargetTable(res.getString(1), res.getString(2), ...));
}
I hope you know the number of columns in your table.
ArrayList is not the best data structure for this purpose.
You can use
Table<Integer, String, Object>
which is available in google guava library. It is really easy to use as well
U can have two arraylists as,
ArrayList<String> columnNames = new ArrayList<String>();
ArrayList<String> out = new ArrayList<String>();
Iterate through ResultSetMetadata and add the columns to the columnNames ArrayList.
Then add the columnNames to out :
out.add(columNames);
Then Create a VO class with all the column names in the table you are accessing. create all the getters and setters for the class names.
Then iterate through the Resultset,
set all the values from the result set into that VO class.
add this VO class to the out arrayList.
ResultVO vo ;
while (resultSet.next()){
vo = new ResultVO();
vo.setColumnName1(resultSet.getString(1));
vo.setColumnName2(resultSet.getString(2));
out.add(vo);
}

Categories