Adding headers to an excel file using Java - java

I have a problem with adding headers to the newly created .xlsx file
I would like to see the first header = 'UserName' and the second header = 'Password'. Can anyone help me on how to do this?
XSSFWorkbook new_workbook = new XSSFWorkbook(); // create a blank workbook object
XSSFSheet sheet = new_workbook.createSheet("EMP_DETAILS"); // create a worksheet with caption score_details
// Define the SQL query
String sql = "SELECT login, password FROM \"Permissions\"";
ResultSet rs = stmt.executeQuery(sql);
// Create Map for Excel Data
Map<String, Object[]> excel_data = new HashMap<String, Object[]>();
int row_counter = 0;
//Extract data from result set
while(rs.next()){
row_counter = row_counter+1;
String login = rs.getString("login");
String password = rs.getString("password");
excel_data.put(Integer.toString(row_counter), new Object[] {login, password});
}
rs.close();
// Load data into logical worksheet
Set<String> keyset = excel_data.keySet();
int rownum = 0;
for(String key : keyset){ // loop through the data and add them to the cell
Row row = sheet.createRow(rownum++);
Object [] objArr = excel_data.get(key);
int cellnum = 0;
for(Object obj : objArr){
Cell cell = row.createCell(cellnum++);
if(obj instanceof Double)
cell.setCellValue((Double)obj);
else
cell.setCellValue((String)obj);
}
}
FileOutputStream output_file = new FileOutputStream(new File("File.xlsx")); // create XLSX file
new_workbook.write(output_file); // write excel document to output stream
output_file.close(); // close the file

My $0.02... don't create an Excel file for something this simple. Instead create a CSV file. The first line you write will be
UserName, Password
for the headers and the lines after that will just be your data for each column separated by a comma. Once the file is written, you can easily open it in Excel and save it as an Excel file.
This method is way simpler and easier than trying to actually write an Excel file.
If you don't want to do that, you just need to create a row before you start looping through your keyset as you would any other row and write the strings for headers.

You can use following code after this line ResultSet rs = stmt.executeQuery(sql);:
ResultSetMetaData rsmd=rs.getMetaData();
Then to fetch column headers; use below:
String columnName1 = rsmd.getColumnName(1); // will fetch you "UserName"
String columnName2 = rsmd.getColumnName(2); // will fetch you "Password"

Related

Fetching Data From xlsx sheet, not showing last three rows in jtable

I am trying to fetching data from excel sheet(.xlsx) file. when I use to print fetched data using
System.out.println(sheet.getRow(i).getCell(c).getStringCellValue()); I see the all the rows from excel sheet is fetched. But when I add this data in jtable it misses last three rows and shows following error:
Cannot invoke "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" because the return value of "org.apache.poi.xssf.usermodel.XSSFSheet.getRow(int)" is null
enter code here
JFileChooser fileChooser = new JFileChooser("D:");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
selectedFile = fileChooser.getSelectedFile();
FileName = selectedFile.getName();
String FilePath = selectedFile.getPath();
System.out.println(FileName);
System.out.println(FilePath);
File excelfile = new File(FileName);
try{
FileInputStream fis = new FileInputStream(selectedFile);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
int totalrows = sheet.getPhysicalNumberOfRows();
for (int i = 0; i <=totalrows; )
{
dmodel.addRow(new Object[]{"" });
System.out.println(sheet.getRow(i).getCell(0).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(0).getStringCellValue();
jTable1.setValueAt(name , i, 0); // this line does not work
i++ ;
}
JOptionPane.showMessageDialog(null, "All rows are fetched Successfully" );
}catch(Exception fx)
{
System.out.println(fx.getMessage());
// System.out.println(fx.getCause());
}
System.out.println(sheet.getRow(r).getCell(c).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(c).getStringCellValue();
jTable1.setValueAt(name , i, 0); // this line does not work
Don't know if this will solve your problem, but the above code is not how you use System.out.println(...) to debug your logic.
To verify the data you use:
//System.out.println(sheet.getRow(r).getCell(c).getStringCellValue()); // this line work
String name = sheet.getRow(i).getCell(c).getStringCellValue();
System.out.println( name );
jTable1.setValueAt(name , i, 0); // this line does not work
Don't attempt to read the data twice. By assigning the data to a variable you are debugging the data in the variable. Don't repeat the nested methods multiple times.
Maybe the class expects you to only read the data once, so the second read gives the null value. The simple change above will prevent this.

In java eclipse, i retrieved data from the database and pasted in the already present excel. The data already present is getting deleted

In java eclipse, I ran a query to retrieve data from the database and pasted in the already present excel sheet (exceldatabase16) in the C drive. Already present excel -exceldatabase16 contains column names in the first row. And the data pasted into the exceldatabase16 is pasted from row 6 and column F. Still the row 1 data is getting deleted.
public static void retrieveData1( Connection connection) throws SQLException, IOException
{
Statement stmt = null;
ResultSet rs = null;
stmt = connection.createStatement();
rs = stmt.executeQuery("SELECT * FROM countries where region_id='3' ");
// getColumnNames(rs);
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet spreadsheet = workbook.createSheet("countriesdetails");
XSSFRow row = spreadsheet.createRow(5);
XSSFCell cell;
cell = row.createCell(5);
cell.setCellValue("country id");
cell = row.createCell(6);
cell.setCellValue("country name");
cell = row.createCell(7);
cell.setCellValue("region");
int i = 6;
while(rs.next()) {
row = spreadsheet.createRow(i);
cell = row.createCell(5);
cell.setCellValue(rs.getString(1));
cell = row.createCell(6);
cell.setCellValue(rs.getString(2));
cell = row.createCell(7);
cell.setCellValue(rs.getInt(3));
i++;
}
FileOutputStream out = new FileOutputStream(new File("C:\\Users\\lenovo\\workspace\\ApachePoi\\exceldatabase16.xlsx"));
workbook.write(out);
out.close();
workbook.close();
System.out.println("exceldatabase.xlsx written successfully");
}
It looks like you are overwriting your existing file with a new one whenever you run this program.
According to the XSSF documentation, there is a method signature of the XSSFWorkbook creation which can open an existing file instead of making a new one.
Try something along the lines of:
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("C:\\Users\\lenovo\\workspace\\ApachePoi\\exceldatabase16.xlsx"));

Read Excel dynamically and store it in map

My requirement is to read the excel dynamically and store the contents in Map. The headers should be key and the respective column should be value so that when I pass the key, I can get the cell value.
My Excel sheet contains multiple rows and columns which can be changed dynamically. My intention is to write a common function in java to read an excel and store the contents in map. The Key should be column headers and the value should be respective cell value of the header. So while retrieving when I pass the header key, I should receive the respective cell value. My plan is to pass the row number and the key in a method so that it can retrieve the respective cell value related to the row as well as the key
static Map<String> excelMap = new LinkedHashMap<String>();
public static String readWriteExcel(String sheetName) throws EncryptedDocumentException, InvalidFormatException, IOException, JSONException
{
File file = new File("File Path");
FileInputStream inputStream = new FileInputStream( file );
Workbook workbook = WorkbookFactory.create( inputStream );
Sheet sheet = workbook.getSheet( sheetName );
int rowNumber =0;
int rowCount = sheet.getLastRowNum();
for(int i=1;i<=rowCount;i++){
Row row = sheet.getRow(0);
for(int j=0;j<row.getLastCellNum();j++) {
String key=row.getCell(j).getStringCellValue();
String value=sheet.getRow(rowNumber+1).getCell(j).getStringCellValue();
excelMap.put(key, value);
}
}
}
By looking at the code, i am assuming the issues: Multiple rows present in the sheet, but you are getting data of first row only.
Solution :
First of all, you need to store all rows data in a List of Map. where list index corresponds to the row number. Also You are not incrementing the rowNumber variable anywhere. Its always 0.
Why not directly use the variable i to get a particular row from sheet?
I think this should work.
static List<Map<String, String>> excelData = new ArrayList<HashMap<String, String>>();
public static String readWriteExcel(String sheetName) throws EncryptedDocumentException, InvalidFormatException, IOException, JSONException
{
File file = new File("File Path");
FileInputStream inputStream = new FileInputStream( file );
Workbook workbook = WorkbookFactory.create( inputStream );
Sheet sheet = workbook.getSheet( "sheetName" );
int rowCount = sheet.getLastRowNum();
for(int i=1;i<=rowCount;i++){
Row row = sheet.getRow(0);
Map<String,String> rowData = new HashMap<>();
for(int j=0;j<row.getLastCellNum();j++) {
String key=row.getCell(j).getStringCellValue();
String value=sheet.getRow(i).getCell(j).getStringCellValue();
rowData.put(key, value);
}
excelData.add(rowData);
}
}
Since you want to map multiple rows you have to store multiple rows.
One way is storing a map consisting column->list containing values for each row.
Another way is storing a map consisting column+row number->value.
Sample code for second method:
static Map<String, String> excelMap = new LinkedHashMap<String, String>();
...
// storing values
excelMap.put(key + "_" + i, value); // i is row index
...
// getting values
public static String getCellValue(String cellName, int rowIndex) {
return excelMap.get(cellName + "_" + rowIndex);
}

Issue in using the data that is being fetched from Excel sheet

I've the following code where fetching of data from excel sheet is done and then this data is added to list as below:
List<HashMap<String,String>> mydata = new ArrayList<>();
try
{
FileInputStream fs = new FileInputStream(filepath);
XSSFWorkbook workbook = new XSSFWorkbook(fs);
XSSFSheet sheet = workbook.getSheet(sheetName);
Row HeaderRow = sheet.getRow(0);
for(int i=1;i<sheet.getPhysicalNumberOfRows();i++)
{
Row currentRow = sheet.getRow(i);
HashMap<String,String> currentHash = new HashMap<String,String>();
for(int j=0;j<currentRow.getPhysicalNumberOfCells();j++)
{
Cell currentCell = currentRow.getCell(j);
switch (currentCell.getCellType())
{
case Cell.CELL_TYPE_STRING:
currentHash.put(HeaderRow.getCell(j).getStringCellValue(), currentCell.getStringCellValue());
break;
}
}
mydata.add(currentHash);
I've another class where we are making use Properties class and setting the property :
public List<HashMap<String,String>> datamap;
public static Properties prop;
public void read_Data_FromExcel(String arg1) throws Throwable {
datamap = DataHelper.data("C:/FINALORDER/ORDERING_Tools/ordering-tools/src/test/resources/Test451.xlsx","Sheet1");
prop=new Properties();
int index = Integer.parseInt(arg1)-2;
FileInputStream fs = new FileInputStream("C:\\FINALORDER\\ORDERING_Tools\\ordering-tools\\src\\test\\resources\\Test451.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(fs);
XSSFSheet sheet = workbook.getSheet("Sheet1");
Row HeaderRow = sheet.getRow(0);
for(int i=0;i<HeaderRow.getPhysicalNumberOfCells();i++) {
prop.setProperty(HeaderRow.getCell(i).toString(), datamap.get(index).get(HeaderRow.getCell(i).toString()));
Using the above code i m fetching the data from excel and then inputting that data into the fields present in the screen like below:
try {
String remark=ExcelSteps.prop.getProperty("Remark");
mosdpOrderSummaryEditPage.tbx_remarks.type(remark);
}catch(Exception e) {
}
The issue is if there are many fields like remark,name,address,id then i have to fetch them one by one using the above code as for remark which is sort of redundant work and increasing code unnecessarily , is there a way by which i can reduce the code or make any generic method.
You can create separate column and get those through
ExcelSteps.prop.getProperty("Here you should pass the column data");
By this code will automatically get remark,name,address,id field names dynamically.
:)

Parse a JDBC ResultSet into a CSV in-memory String

I am executing a query which is returning a ResultSet object. I want to convert this ResultSet into a CSV String in memory.
The reason I want to do this is that once I have the CSV String, I want to invoke a REST API endpoint and pass it this CSV data.
Are there any existing libraries or utilities I can use to convert from a ResultSet into an in memory String? I.e. not into a file..
StringWriter output = new StringWriter();
CsvWriterSettings settings = new CsvWriterSettings(); // many options here, check the documentation
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
String[] headers = new String[columns];
for(int i = 1; i <= columns; i++){
headers[i - 1] = md.getColumnLabel(i);
}
//if an input value is null, you may want print "NULL"
settings.setNullValue("NULL");
// if an input value is not null, but is empty (e.g. ""), the writer can be configured to print "NULL" as well
settings.setEmptyValue("NULL");
// Sets the file headers (used for finer selection of fields, these values won't be written automatically)
settings.setHeaders(headers);
// Creates a writer with the above settings;
CsvWriter writer = new CsvWriter(output, settings);
// Writes the headers specified in the settings
writer.writeHeaders();
Object[] row = new Object[columns];
while(rs.next()){
for(int i = 1; i <= columns; i++){
row[i - 1] = rs.getObject(i);
}
writer.writeRow(row);
}
writer.close();
String yourString = output.toString();

Categories

Resources