I am still new to java. I am having a bit problems with the java syntax.
My Program should do the following procedure:
1) It takes a csv file as an input.
2) It takes an excel file as an input.
3) It should iterate over the first columns of the two files where the dates are written.
4) Update the excel file by adding the information from the csv sheet and save its changes.
I have a https://onedrive.live.com/?cid=24b4fceb4f4e4098&id=24B4FCEB4F4E4098%213018&authkey=%21AKKzaZsJ5pkd5NE
where I have the two input examples and how the result excel sheet should look like.
Two Input files:
export-csv-input.csv
export-excel-input.xlsx
The updated excel file should look like:
export-excel-output.xlsx
My Java Code yet:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CsvToExcelConverter {
public static final String SAMPLE_XLSX_FILE_PATH =
"C:/Users/blawand/Desktop/CSV_to_Excel/export-excel-test.xlsx";
public static final String SAMPLE_CSV_FILE_PATH =
"C:/Users/blawand/Desktop/CSV_to_Excel/export-csv-test.csv";
public static List<String> dates_csv = new ArrayList<>();
public static List<String> dates_excel = new ArrayList<>();
public static void main(String[] args) throws IOException,
InvalidFormatException {
try (Reader reader =
Files.newBufferedReader(Paths.get(SAMPLE_CSV_FILE_PATH));
CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT);)
{
for (CSVRecord csvRecord : csvParser) {
// Accessing Values by Column Index
String name = csvRecord.get(0);
dates_csv.add(name);
}
dates_csv.remove(0);
}
FileInputStream fsIP = new FileInputStream(new
File(SAMPLE_XLSX_FILE_PATH));
/*
* ==================================================================
Iterating over all the
* rows and columns in a Sheet (Multiple ways)
* ==================================================================
*/
// Getting the Sheet at index zero
XSSFWorkbook workbook = new XSSFWorkbook(fsIP);
XSSFSheet sheet = workbook.getSheetAt(0);
// Get the Cell at index 2 from the above row
// Cell cell1 = sheet.getRow(1).getCell(0);
// for (int i = 0; i < dates_excel.size(); i++) {
// XSSFRow rowtest = sheet.createRow((short) i + 1);
// rowtest.createCell(0).setCellValue(dates_csv.get(i));
//
// }
// cell1.setCellValue(dates_csv.get(0));
// Create a DataFormatter to format and get each cell's value as
String
DataFormatter dataFormatter = new DataFormatter();
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++)
{
Row row = sheet.getRow(rowIndex);
if (row != null) {
Cell cell = row.getCell(0); // getColumn(0)
if (cell != null) {
// Found column and there is value in the cell.
// String cellValueMaybeNull = cell.getStringCellValue();
String cellValueMaybeNull =
dataFormatter.formatCellValue(cell);
// String to number set
dates_excel.add(cellValueMaybeNull);
}
}
}
System.out.println(dates_csv);
System.out.println(dates_csv.size());
System.out.println(dates_excel);
System.out.println(dates_excel.size());
while (dates_excel == dates_excel) {
System.out.println("Yes");
break;
}
fsIP.close();
FileOutputStream output_file = new FileOutputStream(new
File(SAMPLE_XLSX_FILE_PATH));
workbook.write(output_file);
output_file.close();
}
}
I read already the two files but i am having problems with updating the excel file and adding the project names to the correct dates. And if the same date has been written two or more times in the csv sheet.
Which information would you like also to know?
I would be thankful for every help or advice!
I have an example for you, mostly explained by code comments. Nevertheless, the code basically does the following:
Takes file paths of the xlsx and csv file in the constructor.
When updating, it first reads the content of the csv file into a Map with a LocalDate as key and a List<String> as values.
Then it goes through the rows of the workbook skipping the header row and comparing the dates in column one with the keys of the Map<LocalDate, List<String>>. If the map contains that key, it starts checking the cells in that row for present values and keeps them in a list in order to not write them later.
Then it starts writing the values into the cells of the row with the key date.
I hope this helps.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class CsvXlsxUpdater {
private static final DateTimeFormatter DATE_TIME_FORMATTER_CSV = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private Path csvFilePath;
private Path xlsxFilePath;
private XSSFWorkbook workbook;
private XSSFSheet sheet;
private Map<LocalDate, List<String>> csvContent = new TreeMap<LocalDate, List<String>>();
private ZoneId zoneId = ZoneId.systemDefault();
public CsvXlsxUpdater(String pathToCsvFile, String pathToXlsxFile) {
csvFilePath = Paths.get(pathToCsvFile);
xlsxFilePath = Paths.get(pathToXlsxFile);
}
/**
* Reads the content of the csv file into the corresponding class variable,
* which is a {#link TreeMap} that has a {#link LocalDate} as key and a
* {#link List<String>} as values.
*/
private void readCsvContent() {
List<String> csvLines;
try {
csvLines = Files.readAllLines(csvFilePath);
for (int i = 1; i < csvLines.size(); i++) {
String line = csvLines.get(i);
String[] splitValues = line.split(",");
if (splitValues.length > 1) {
List<String> lineValues = Arrays.asList(splitValues);
List<String> projects = getProjectValuesFrom(lineValues);
LocalDate localDate = LocalDate.parse(lineValues.get(0), DATE_TIME_FORMATTER_CSV);
if (csvContent.containsKey(localDate)) {
projects.forEach((String project) -> {
List<String> csvProjects = csvContent.get(localDate);
if (!csvProjects.contains(project)) {
csvProjects.add(project);
}
});
} else {
csvContent.put(localDate, projects);
}
} else {
LocalDate localDate = LocalDate.parse(splitValues[0], DATE_TIME_FORMATTER_CSV);
csvContent.put(localDate, new ArrayList<String>());
}
}
} catch (IOException e) {
System.err.println("CANNOT FIND OR READ CSV FILE: " + e.getMessage());
e.printStackTrace();
} catch (UnsupportedOperationException e) {
System.err.println("UNSUPPORTED OPERATION: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Gets the corresponding {#link LocalDate} from a given (and deprecated)
* {#link Date}
*
* #param date the deprecated {#link Date} object
* #return the corresponding {#link LocalDate}
*/
private LocalDate parseLocalDateFrom(Date date) {
Instant instantDate = date.toInstant();
return instantDate.atZone(zoneId).toLocalDate();
}
/**
* Takes a list of read values from the csv file and returns a list containing
* all the values of the given list <strong>except from the first
* element</strong>, which is a {#link String} representation of a date and
* should be treated differently in this context.
*
* #param values the original list of {#link String}s
* #return another list without the first element of the given list
*/
private List<String> getProjectValuesFrom(List<String> values) {
List<String> projectValues = new ArrayList<String>();
for (int i = 1; i < values.size(); i++) {
String value = values.get(i);
if (!value.equals("")) {
projectValues.add(value);
}
}
return projectValues;
}
/**
* Updates the workbook with the values read from the csv file
*/
public void updateWorkbook() {
readCsvContent();
try {
FileInputStream fis = new FileInputStream(xlsxFilePath.toAbsolutePath().toString());
workbook = new XSSFWorkbook(fis);
sheet = workbook.getSheetAt(0);
// iterate over the rows
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
XSSFRow row = (XSSFRow) rowIterator.next();
if (row.getRowNum() == 0) {
// skip this or set updated headers
} else {
// check if the csvContent contains the value of cell(0)
LocalDate dateKey = parseLocalDateFrom(row.getCell(0).getDateCellValue());
if (csvContent.containsKey(dateKey)) {
// if yes, get list-value of the key
List<String> values = csvContent.get(dateKey);
// check if there are values
if (values != null) {
if (values.size() > 0) {
// if there are, then go checking the cell values
List<String> projectsInXlsx = new ArrayList<String>();
Iterator<Cell> cellIterator = row.cellIterator();
int lastColumnIndex = 1;
// go through all cells with a value except from the first one
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
// skip the first column as it contains the date
if (cell.getColumnIndex() != 0) {
lastColumnIndex = cell.getColumnIndex();
System.out.println("Accessing cell in column " + lastColumnIndex);
// if there is a cell with a value
if (cell.getStringCellValue() != null) {
if (!cell.getStringCellValue().equals("")) {
// check if the value in the cell is also in the csv values
if (values.contains(cell.getStringCellValue())) {
projectsInXlsx.add(cell.getStringCellValue());
lastColumnIndex++;
}
}
}
}
}
// now go through the values of the csv file
int offset = 0; // cell column offset for more than one entry per date
for (String value : values) {
if (!projectsInXlsx.contains(value)) {
// create a cell after the last one with a value
row.createCell(lastColumnIndex + offset).setCellValue(value);
offset++;
}
}
}
}
}
}
}
fis.close();
FileOutputStream fileOutputStream = new FileOutputStream(xlsxFilePath.toAbsolutePath().toString());
workbook.write(fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In a main method, you would just have to call the constructor, pass the file paths as Strings and then call the updateWorkbook() method, because it internally reads the csv first.
Example:
public class CsvXlsxMain {
private static final String CSV_FILE_PATH = "S:\\ome\\example\\path\\to\\csv-input.csv";
private static final String XLSX_FILE_PATH = "S:\\ome\\example\\path\\to\\excel-input.xlsx";
public static void main(String[] args) {
CsvXlsxUpdater cxu = new CsvXlsxUpdater(CSV_FILE_PATH, XLSX_FILE_PATH);
cxu.updateWorkbook();
}
}
Please keep in mind that this CODE IS NOT FULLY TESTED, there may be problems with alternating resources in future
If you need, go testing it with various xlsx and csv inputs that fit your requirements.
I haven't used any library to parse the csv file!
I hope this helps you a little…
Related
I am using Apache POI to edit an existing file. This file contains multiple formulas that use the numbers that will be inputted through Apache. And this is where I run into problems, when a number is inputted and that cell is being used in a formula, the file gets corrupted and the formula disappears.
Here the formulas for the 0 are C7+D7, C8+D8, etc.
Here the formulas for the 0 became normal 0, the formulas got lost.
Here is the code I used to write to the excel file:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class write {
public static void main(String[] args) {
String excelFilePath = "C:\\Users\\jose_\\IdeaProjects\\writeExcel\\src\\JavaBooks.xlsx";
try {
FileInputStream inputStream = new FileInputStream(new File(excelFilePath));
Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);
/*Cell cell2Update = sheet.getRow(1).getCell(3); // This updates a specific cell: row 0 cell 3
cell2Update.setCellValue(49);*/
Object[][] bookData = {
{2, 17},
{3, 27},
{4, 33},
{5, 44},
};
// int rowCount = sheet.getLastRowNum(); // Gets the last entry
int rowCount = 5;
for (Object[] aBook : bookData) {
Row row = sheet.createRow(++rowCount);
int columnCount = 1;
int lote = 1;
Cell cell = row.createCell(columnCount);
//cell.setCellValue(rowCount); // This sets the index for each entry
cell.setCellValue(lote);
for (Object field : aBook) {
cell = row.createCell(++columnCount);
if (field instanceof String) {
cell.setCellValue((String) field);
} else if (field instanceof Integer) {
cell.setCellValue((Integer) field);
}
}
}
inputStream.close();
FileOutputStream outputStream = new FileOutputStream("C:\\Users\\jose_\\IdeaProjects\\writeExcel\\src\\JavaBooks.xlsx");
workbook.write(outputStream);
workbook.close();
outputStream.close();
} catch (IOException | EncryptedDocumentException ex) {
ex.printStackTrace();
}
}
}
Is there a way to work around this or do I need to set all the formulas again through Apache POI?
You get the error because using code line Row row = sheet.createRow(++rowCount); you always create new empty rows and so you remove all cells in those rows. So you are also removing the cells containing the formulas. Doing so you are damaging the calculation chain. That's what the Excel GUI tells you with the messages.
You should not do this. Instead you always should try to get the rows first using Sheet.getRow. Only if that returns null then you need to create the row.
...
//Row row = sheet.createRow(++rowCount);
Row row = sheet.getRow(rowCount); if (row == null) row = sheet.createRow(rowCount); rowCount++;
...
Additional please read Recalculation of Formulas. So after changing cells referenced in formulas, do always either workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); or delegate re-calculation to Excel using workbook.setForceFormulaRecalculation(true);.
Need help! I am trying to code a simple function that could return the data from an excel source.
I am trying to create a list of Maps of data from excel file but the list that I am getting has the same values. All value are the same.
Here is my code:
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ExcelReaderFinal {
public static void main(String[] args) throws IOException {
String path = "C:\\Users\\username\\Downloads\\TestFile.xlsx";
FileInputStream fis = new FileInputStream(path);
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
int lastRow = sheet.getLastRowNum()-5;
int lastColumn = 3;
Map<String, Object> dataMap = new HashMap<String, Object>();
ArrayList<Map<String, Object>> dataList = new ArrayList<>();
for(int j=0; j<=lastRow; j++){
for(int i=0; i<=lastColumn; i++) {
Row row = sheet.getRow(4);
Cell keyCell = row.getCell(i);
Row val = sheet.getRow(5+j);
Cell valueCell = val.getCell(i);
String value = valueCell.getStringCellValue().trim();
String key = keyCell.getStringCellValue().trim();
dataMap.put(key, value);
}
dataList.add(dataMap);
}
System.out.println(dataList);
}
}
my actual output is like this:
[{Negative Val=0, Account Number=121312C, Positive Val=20,000,000.00, Banko=RCBC}, {Negative Val=0, Account Number=121312C, Positive Val=20,000,000.00, Banko=RCBC}, {Negative Val=0, Account Number=121312C, Positive Val=20,000,000.00, Banko=RCBC}]
but my expected output is like this:
And here is my excel file source:
In Summary:
I want to get all the data in excel file in list format
that list should be sorted based on the arrangement of columns from excel.
Thank you so much!!
I am a beginner in Java coding and would like to know how to read the following excel sheet data using Java.
Also, I have tried the below code -
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class ReadingFromExcelSheet {
public static void main(String[] args) throws EncryptedDocumentException, InvalidFormatException, IOException {
FileInputStream ip = new FileInputStream("C:\\Users\\Sanjana Rajeev\\Desktop\\Murali_YoutubeLinks.xlsx");
Workbook wb = WorkbookFactory.create(ip);
Sheet sheet = wb.getSheet("MySheet1");
int i,j;
int rowcount =3,cellcount=2;
for ( i=0;i<=rowcount;i++){
for (j=0;j<cellcount;j++){
Row row = sheet.getRow(i);
Cell cell = row.getCell(j);
String cellval = cell.getStringCellValue();
System.out.println(cellval + "\t\t" );
}
}
ip.close();
}
}
And i am getting the below shown output :
Topics
YouTube Links
Java Execution
Java and JDK dowload
Eclipse download
Create a Workspace/Project/Package/Class files
https://youtu.be/Pvcv-V69Vc0
Java Execution
Java and JDK dowload
Eclipse download
Create a Workspace/Project/Package/Class files
Datatypes
Variables
String Concatenation
https://youtu.be/Gx0ubuYwTjg
Global Variables (Static & NonStatic)
Local Variables
Memory Allocation
I am getting the values of the cell but not in their proper order as like the excel sheet. Can anyone please help?
Try this approach
public static void main(String[] args) throws EncryptedDocumentException, InvalidFormatException, IOException {
FileInputStream ip = new FileInputStream("C:\\Users\\Sanjana Rajeev\\Desktop\\Murali_YoutubeLinks.xlsx");
Workbook wb = WorkbookFactory.create(ip);
Sheet sheet = wb.getSheet("MySheet1");
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
//iterate over the columns of the current row
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
String cellValue = dataFormatter.formatCellValue(cell);
System.out.print(cellValue + "\t");
}
//append empty line
System.out.println();
}
ip.close();
}
Does this improve the formatting?
for ( i=0;i<=rowcount;i++)
{
Row row = sheet.getRow(i);
for (j=0;j<cellcount;j++)
{
Cell cell = row.getCell(j);
String cellval = cell.getStringCellValue();
System.out.print(cellval + "\t\t" );
}
System.out.println();
}
The situation is as follows;
I have a simple program which uses the Apache Poi Library to add one row of data at the end of the an exisiting xlsx file. See below
File file = new File(input);
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
XSSFRow row = sheet.createRow(sheet.getLastRowNum() + 1);
After this I will iterate over the row and set the CellValues. But the problem is that on the second line of the code, as shown above, I get an out of memory error. Is there a way to add a row of data to the existing xlsx file without having to read the file fully?
(not enough reputation to add this as a comment)
Have you tried using SXSSFWorkbook instead of XSSFWorkbook?
You can try XSSF and SAX (Event API).
If getting the XSSFWorkbook fails because of out-of-memory error and the need is to read and write the workbook, then neither SXSSF nor SAX parser will help. The one is only for writing. The other is only for reading.
Both approaches in follow needs knowledge about the *.xlsx file format which is Office Open XML. In general a *.xlsx file is a ZIP archive containing XML files and other files in a special directory structure. So one can unzip the *.xlsx file using a ZIP software to have a look at the XML files. The file format was first standardized by Ecma. So for further recherches I prefer Ecma Markup Language Reference. For example Row.
The ReadAndWriteTest.xlsx used in both examples must have at least one worksheet and the first worksheet must have at least one row.
One approach could be using the DOM methods of XMLBeans. My favorite reference for this is grepcode.
Example:
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.model.SharedStringsTable;
import java.io.File;
import java.io.OutputStream;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
import org.apache.xmlbeans.XmlOptions;
import javax.xml.namespace.QName;
import java.util.Map;
import java.util.HashMap;
import java.util.regex.Pattern;
class DOMReadAndWriteTest {
public static void main(String[] args) {
try {
File file = new File("ReadAndWriteTest.xlsx");
//we only open the OPCPackage, we don't create a Workbook
OPCPackage opcpackage = OPCPackage.open(file);
//if there are strings in the SheetData, we need the SharedStringsTable
PackagePart sharedstringstablepart = opcpackage.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")).get(0);
SharedStringsTable sharedstringstable = new SharedStringsTable();
sharedstringstable.readFrom(sharedstringstablepart.getInputStream());
//get the PackagePart of the first sheet
PackagePart sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0);
//get the worksheet from the first sheet's XML
//if it even fails while parsing this, then this approach is not usable
WorksheetDocument worksheetdocument = WorksheetDocument.Factory.parse(sheetpart.getInputStream());
CTWorksheet worksheet = worksheetdocument.getWorksheet();
CTSheetData sheetdata = worksheet.getSheetData();
//put some data in 10 new rows"
for (int i = 0; i < 10; i++) {
int rowsCount = sheetdata.sizeOfRowArray();
CTCell ctcell= sheetdata.addNewRow().addNewC();
CTRst ctstr = CTRst.Factory.newInstance();
ctstr.setT("new Row " + (rowsCount + 1));
int sRef = sharedstringstable.addEntry(ctstr);
ctcell.setT(STCellType.S);
ctcell.setV(Integer.toString(sRef));
ctcell=sheetdata.getRowArray(rowsCount).addNewC();
ctcell.setV(""+rowsCount+"."+(i+1)+""+((i+2>9)?0:i+2));
}
//write the SharedStringsTable
OutputStream out = sharedstringstablepart.getOutputStream();
sharedstringstable.writeTo(out);
out.close();
//create XmlOptions for saving the worksheet
XmlOptions xmlOptions = new XmlOptions();
xmlOptions.setSaveOuter();
xmlOptions.setUseDefaultNamespace();
xmlOptions.setSaveAggressiveNamespaces();
xmlOptions.setCharacterEncoding("UTF-8");
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTWorksheet.type.getName().getNamespaceURI(), "worksheet"));
Map<String, String> map = new HashMap<String, String>();
map.put(STRelationshipId.type.getName().getNamespaceURI(), "r");
xmlOptions.setSaveSuggestedPrefixes(map);
//save the worksheet
out = sheetpart.getOutputStream();
worksheet.save(out, xmlOptions);
out.close();
opcpackage.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
This code writes 10 new Rows in sheet1 of ReadAndWriteTest.xlsx without opening the whole workbook. But it must at least opening and parsing the sheet1 and the SharedStringsTable. If even this fails, then this approach is not usable.
Another approach could be using StAX. This API can read and write XML event driven. And it uses streaming.
Example:
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.XMLEvent;
import javax.xml.namespace.QName;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
class StaxReadAndWriteTest {
public static void main(String[] args) {
try {
File file = new File("ReadAndWriteTest.xlsx");
OPCPackage opcpackage = OPCPackage.open(file);
//if there are strings in the sheet data, we need the SharedStringsTable
//if it even fails while parsing this SharedStringsTable, then this approach is not usable
//then we must stream this XML event driven also.
PackagePart sharedstringstablepart = opcpackage.getPartsByName(Pattern.compile("/xl/sharedStrings.xml")).get(0);
SharedStringsTable sharedstringstable = new SharedStringsTable();
sharedstringstable.readFrom(sharedstringstablepart.getInputStream());
PackagePart sheetpart = opcpackage.getPartsByName(Pattern.compile("/xl/worksheets/sheet1.xml")).get(0);
XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(sheetpart.getInputStream());
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(sheetpart.getOutputStream());
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
int rowsCount = 0;
while(reader.hasNext()){ //loop over all XML in sheet1.xml
XMLEvent event = (XMLEvent)reader.next();
writer.add(event); //by default write each readed event
if(event.isStartElement()){
StartElement startElement = (StartElement)event;
QName startElementName = startElement.getName();
if(startElementName.getLocalPart().equalsIgnoreCase("row")) { //start element of row
boolean rowStart = true;
rowsCount++;
do {
event = (XMLEvent)reader.next(); //find this row's end
writer.add(event); //by default write each readed event
if(event.isEndElement()){
EndElement endElement = (EndElement)event;
QName endElementName = endElement.getName();
if(endElementName.getLocalPart().equalsIgnoreCase("row")) { //end element of row
rowStart = false;
//we assume that there is nothing else (character data) between end element of row and next element
XMLEvent nextElement = (XMLEvent)reader.peek();
QName nextElementName = null;
if (nextElement.isStartElement()) nextElementName = ((StartElement)nextElement).getName();
else if (nextElement.isEndElement()) nextElementName = ((EndElement)nextElement).getName();
if(!nextElementName.getLocalPart().equalsIgnoreCase("row")) { //next is not start element of row
//we have the last row, so we write new rows now
for (int i = 0; i < 10; i++) {
StartElement newRowStart = eventFactory.createStartElement(new QName("row"), null, null);
writer.add(newRowStart);
//start cell A
Attribute attribute = eventFactory.createAttribute("t", "s");
List attributeList = Arrays.asList(attribute);
StartElement newCellStart = eventFactory.createStartElement(new QName("c"), attributeList.iterator(), null);
writer.add(newCellStart);
CTRst ctstr = CTRst.Factory.newInstance();
ctstr.setT("new Row " + (rowsCount +1));
int sRef = sharedstringstable.addEntry(ctstr);
StartElement newCellValue = eventFactory.createStartElement(new QName("v"), null, null);
writer.add(newCellValue);
Characters value = eventFactory.createCharacters(Integer.toString(sRef));
writer.add(value);
EndElement newCellValueEnd = eventFactory.createEndElement(new QName("v"), null);
writer.add(newCellValueEnd);
EndElement newCellEnd = eventFactory.createEndElement(new QName("c"), null);
writer.add(newCellEnd);
//end cell A
//start cell B
newCellStart = eventFactory.createStartElement(new QName("c"), null, null);
writer.add(newCellStart);
newCellValue = eventFactory.createStartElement(new QName("v"), null, null);
writer.add(newCellValue);
value = eventFactory.createCharacters(""+rowsCount+"."+(i+1)+""+((i+2>9)?0:i+2));
writer.add(value);
newCellValueEnd = eventFactory.createEndElement(new QName("v"), null);
writer.add(newCellValueEnd);
newCellEnd = eventFactory.createEndElement(new QName("c"), null);
writer.add(newCellEnd);
//end cell B
EndElement newRowEnd = eventFactory.createEndElement(new QName("row"), null);
writer.add(newRowEnd);
rowsCount++;
}
}
}
}
} while (rowStart);
}
}
}
writer.flush();
//write the SharedStringsTable
OutputStream out = sharedstringstablepart.getOutputStream();
sharedstringstable.writeTo(out);
out.close();
opcpackage.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
This code also writes 10 new Rows in sheet1 of ReadAndWriteTest.xlsx without opening the whole workbook. But it must at least opening and parsing the SharedStringsTable. If even this fails, then this approach is also not usable. But of course even the SharedStringsTable could be streamed using StAX. But as you see in example with generating the rows and cells, this is much more complicated. So using the SharedStringsTable makes things easier in this example.
I need java code to read data for specific column from excel sheet. – (lo number, line, voucher no, stloc , quantity ,activity.)
These set of values for a particular column will be used for sql query (jdbc-odbc connection done).
The output for the query will be matched with a column in this sheet (this part ll be done later)
Kindly help.
sample excel sheet
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package excelfilereading;
/**
*
* #author vkantiya
*/
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
public class Main {
#SuppressWarnings("unchecked")
public static void main(String[] args) throws Exception {
//
// An excel file name. You can create a file name with a full
// path information.
//
String filename = "FirstExcel.xls";
// Create an ArrayList to store the data read from excel sheet.
//
List sheetData = new ArrayList();
FileInputStream fis = null;
try {
//
// Create a FileInputStream that will be use to read the
// excel file.
//
fis = new FileInputStream(filename);
//
// Create an excel workbook from the file system.
//
HSSFWorkbook workbook = new HSSFWorkbook(fis);
//
// Get the first sheet on the workbook.
//
HSSFSheet sheet = workbook.getSheetAt(0);
//
// When we have a sheet object in hand we can iterator on
// each sheet's rows and on each row's cells. We store the
// data read on an ArrayList so that we can printed the
// content of the excel to the console.
//
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
List data = new ArrayList();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
data.add(cell);
}
sheetData.add(data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
fis.close();
}
}
showExelData(sheetData);
}
private static void showExelData(List sheetData) {
//
// Iterates the data and print it out to the console.
//
for (int i = 0; i < sheetData.size(); i++) {
List list = (List) sheetData.get(i);
for (int j = 0; j < list.size(); j++) {
HSSFCell cell = (HSSFCell) list.get(j);
System.out.print(
cell.getRichStringCellValue().getString());
if (j < list.size() - 1) {
System.out.print(", ");
}
}
System.out.println("");
}
}
}
Have a look at Apache POI - the Java API for Microsoft Documents.
It covers
Excel (SS=HSSF+XSSF)
Word (HWPF+XWPF)
PowerPoint (HSLF+XSLF)
OpenXML4J (OOXML)
OLE2 Filesystem (POIFS)
OLE2 Document Props (HPSF)
Outlook (HSMF)
Visio (HDGF) TNEF (HMEF)
Publisher (HPBF)