I am using apache POI to read an excel document. To say the least, it is able to serve my purpose as of now. But one thing where I am getting struck is extracting the value of cell as HTML.
I have one cell wherein user will enter some string and apply some formatting(like bullets/numbers/bold/italic) etc.
SO when I read it the content should be in HTML format and not a plain string format as given by POI.
I have almost gone through the entire POI API but not able to find anyone. I want to remain the formatting of just one particular column and not the entire excel. By column I mean, the text which is entered in that column. I want that text as HTML text.
Explored and used Apache Tika also. However as I understand it can only get me the text but not the formatting of the text.
Please someone guide me. I am running out of options.
Suppose I wrote My name is Angel and Demon in Excel.
The output I should get in Java is My name is <b>Angel</b> and <i>Demon</i>
I've paste this as unicode to cell A1 of xls file:
<html><p>This is a test. Will this text be <b>bold</b> or <i>italic</i></p></html>
This html line produce this:
This is a test. Will this text be bold or italic
My code:
public class ExcelWithHtml {
// <html><p>This is a test. Will this text be <b>bold</b> or
// <i>italic</i></p></html>
public static void main(String[] args) throws FileNotFoundException,
IOException {
new ExcelWithHtml()
.readFirstCellOfXSSF("/Users/rcacheira/testeHtml.xlsx");
}
boolean inBold = false;
boolean inItalic = false;
public void readFirstCellOfXSSF(String filePathName)
throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(filePathName);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet sheet = wb.getSheetAt(0);
String cellHtml = getHtmlFormatedCellValueFromSheet(sheet, "A1");
System.out.println(cellHtml);
fis.close();
}
public String getHtmlFormatedCellValueFromSheet(XSSFSheet sheet,
String cellName) {
CellReference cellReference = new CellReference(cellName);
XSSFRow row = sheet.getRow(cellReference.getRow());
XSSFCell cell = row.getCell(cellReference.getCol());
XSSFRichTextString cellText = cell.getRichStringCellValue();
String htmlCode = "";
// htmlCode = "<html>";
for (int i = 0; i < cellText.numFormattingRuns(); i++) {
try {
htmlCode += getFormatFromFont(cellText.getFontAtIndex(i));
} catch (NullPointerException ex) {
}
try {
htmlCode += getFormatFromFont(cellText
.getFontOfFormattingRun(i));
} catch (NullPointerException ex) {
}
int indexStart = cellText.getIndexOfFormattingRun(i);
int indexEnd = indexStart + cellText.getLengthOfFormattingRun(i);
htmlCode += cellText.getString().substring(indexStart, indexEnd);
}
if (inItalic) {
htmlCode += "</i>";
inItalic = false;
}
if (inBold) {
htmlCode += "</b>";
inBold = false;
}
// htmlCode += "</html>";
return htmlCode;
}
private String getFormatFromFont(XSSFFont font) {
String formatHtmlCode = "";
if (font.getItalic() && !inItalic) {
formatHtmlCode += "<i>";
inItalic = true;
} else if (!font.getItalic() && inItalic) {
formatHtmlCode += "</i>";
inItalic = false;
}
if (font.getBold() && !inBold) {
formatHtmlCode += "<b>";
inBold = true;
} else if (!font.getBold() && inBold) {
formatHtmlCode += "</b>";
inBold = false;
}
return formatHtmlCode;
}
}
My output:
This is a test. Will this text be <b>bold</b> or <i>italic</i>
I think it is what you want, i'm only show you the possibilities, i'm not using the best code practices, i'm just programming fast to produce an output.
Related
I want to write data into excel(.xlsx file) using Apache poi. but getting some error while writing a data. I have followed this video " How to read/write data from Excel file using Apache POI API in Selenium || Latest POI Version", I m able to read data but while writing I m getting this error " Cannot invoke "org.apache.poi.xssf.usermodel.XSSFCell.getStringCellValue()" because the return value of "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" is null ", basically nullpointerexception.
enter code here
String resourceGroupNameElement = driver.findElement(By.xpath(FrameworkValidator_Constants.Constants.RESOURCE_GROUP_NAME_XPATH)).getText();
String expectedResult = reader.getCellData("RG",6,2);
if( resourceGroupNameElement== expectedResult) {
String status= "pass";
System.out.println(status);
}
else {
String status="fail";
System.out.println(status);
}
//reader.setCellData("RG", "STATUS/PASS/FAIL", 2, status);
System.out.println(status);
reader.setCellData("RG","ACTUAL RESULT" , 2, resourceGroupNameElement);
Assert.assertEquals(resourceGroupNameElement, expectedResult);
#######
It is showing error in this section
public String setCellData(String sheetName, String colName, int rowNum, String data) {
try {
fis = new FileInputStream(path);
workbook = new XSSFWorkbook(fis);
if (rowNum <= 0)
return "";
int index = workbook.getSheetIndex(sheetName);
int colNum = -1;
if (index == -1)
return "";
sheet = workbook.getSheetAt(index);
row = sheet.getRow(0);
for (int i = 0; i < row.getLastCellNum(); i++) {
// System.out.println(row.getCell(i).getStringCellValue().trim());
if (row.getCell(i).getStringCellValue().trim().equals(colName))
colNum = i;
}
if (colNum == -1)
return "";
sheet.autoSizeColumn(colNum);
row = sheet.getRow(rowNum - 1);
if (row == null)
row = sheet.createRow(rowNum - 1);
cell = row.getCell(colNum);
if (cell == null)
cell = row.createCell(colNum);
// cell style
// CellStyle cs = workbook.createCellStyle();
// cs.setWrapText(true);
// cell.setCellStyle(cs);
cell.setCellValue(data);
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
fileOut.close();
} catch (Exception e) {
e.printStackTrace();
return "";
}
return "";
}
so can anybody tell me where I m going wrong.
Have a look at the HOWTO and examples.
You will notice that there are calls for creating a row or creating a cell. Unless you do so, the row/cell does not exist and your getCell() function will return null.
Changing for loop condition part i.e. i < row.getLastCellNum(); to i < row.getLastCellNum()-1; can resolve this issue.
getLastCellNum() returns index plus one and once the counter will reach to end value, getCell(i) can point to the null value as per your code.
I'm using Apache POI to save data to an excel file. Basic data is being saved fine, but I need to also use formula's.
Its adding the formula in, but its not being evaluated until I refresh the cell (clicking into and pressing enter)
The code I'm using to create the cells. Removed code that's not relevant
public void writeExcel(ClassManager cm) throws FileNotFoundException, IOException {
setupRows();
workbook.setForceFormulaRecalculation(true);
FileOutputStream outputStream = new FileOutputStream(fileLocation);
workbook.write(outputStream);
workbook.close();
}
public void setupRows() {
setupRow15();
}
public void setupRow15() {
int start = 2;
Row row = sheet.createRow(16);
// Create 1st Cell
Cell cell = row.createCell(0);
cell.setCellValue("templateId = ");
for (int i = 0; i < classes.size(); i++) {
// Get class
Classes c = classes.get(i);
// Create cell
cell = row.createCell(start);
// Set contents
cell.setCellFormula("IF(C3=\"\",\"\",CONCAT($A17,$B17,C" + (start + 1) + ",$B17,$A$16))");
start++;
}
}
It's resulting in the formula
Solved it by running after setting all formulas
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
for (Row r : sheet) {
for (Cell c : r) {
evaluator.evaluateFormulaCell(c);
}
}
I have an Excel file which has a macro and I would like to automate the process. I have Java code which fills the Excel columns and I have written the VBScript to run the macro in the Excel.
My Java code is (I pass the Excel fileName which has the macro)
public void excelupdate(String fileName) {
FileInputStream file = null;
FileOutputStream out = null;
try {
file = new FileInputStream(new File(fileName));
HSSFWorkbook yourworkbook = new HSSFWorkbook(file);
HSSFSheet sheet1 = null;
for (int i = 0; i < yourworkbook.getNumberOfSheets(); i++) {
if (yourworkbook.getSheetName(i).contains("Sheet-Macro")) {
sheet1 = yourworkbook.getSheetAt(i);
}
}
Cell cell = null;
int rowValue = 10;
for (int i = 0; i < list.size() - 1; i++) {
cell = sheet1.getRow(rowValue).getCell(2);
cell.setCellValue(list.get(i));
rowValue++;
}
Cell cell1 = null;
int rowValue1 = 10;
for (int j = 0; j < Input1list.size() - 1; j++) {
cell1 = sheet1.getRow(rowValue1).getCell(3);
cell1.setCellValue(Input1list.get(j));
rowValue1++;
}
Cell cell2 = null;
int rowValue2 = 22;
for (int k = 0; k < Input2list.size() - 1; k++) {
cell2 = sheet1.getRow(rowValue2).getCell(4);
cell2.setCellValue(Input2list.get(k));
rowValue2++;
}
out = new FileOutputStream(("C:\\Users\\Desktop\\EXCEL.xls"));
yourworkbook.write(out);
out.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (file != null) {
try {
file.close();
} catch (Exception e) {
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
}
}
The Java code runs on Apache Poi to fill in the columns and moves the Excel file to a particular directory and then I have the below VBScript to run the macro:
Dim objXL
Set objXL = CreateObject("Excel.Application")
Set objWorkbook = objXL.Workbooks.Open("F:\testmacro\testmacro\EXCEL.xls")
objWorkbook.Sheets("AD stages").Cells(6, 4) = "F:\set1\set.txt"
objXL.Application.DisplayAlerts = False
objXL.ActiveWorkbook.Save
objXL.Application.Run "macro_cal"
objXL.ActiveWorkbook.Save
objXL.ActiveWorkbook.Close
objXL.Application.DisplayAlerts = True
objXL.Application.Quit
WScript.Echo "ExCEL file updated successfully"
WScript.Quit
Set objXL = Nothing
I call the above VBscript from the java as below,
File file = new File(excelFilename);
file.setExecutable(true);
file.setReadable(true);
file.setWritable(true);
Runtime runtime = Runtime.getRuntime();
try {
String sample="cmd /c start "+vbScript+" "+"\"" +excelFilename + "\"" + " "+"\"" +outFile + "\"";
System.out.println(sample);
Process process1 = runtime.exec(sample);
} catch (IOException e) {
logger.error(e);
}
But the problem is, once the Java populates the Excel columns and save the file, the file becomes protected and hence the VBScript is throwing an error stating it can't open/run the macro in protected Excel.
Any advice?
Thanks to #AxelRitcher, the solution is "Please read about Error message in Microsoft Office: "Office has detected a problem with this file". So seems as if the location F:\testmacro\testmacro is not a trusted location for Excel files having macros in it."
I am doing Bulk Upload Task in Alfresco.
Before this i created custom action to call java code, i also successfully read data from excel sheet, and i found node reference of target document as well as source Document. Using that node reference i am also able to create new multiple Documents.
Now My requirement is, I want to replace Excel Data in that newly created Document. I tried to replace it, But It replacing the String only in First line of document, and it also deleting Rest of the existing contents inside newly created document. I have written Below code for this.
In below code i am first simply trying to replace some hard coded data to the Document.
But My requirement is i want to replace the data inside document which i already read from excel file.
Java Code:
public class MoveReplacedActionExecuter extends ActionExecuterAbstractBase {
InputStream is;
Cell cell = null;
public static final String NAME = "move-replaced";
private FileFolderService fileFolderService;
private NodeService nodeService;
private ContentService contentService;
private SearchService searchService;
#Override
protected void addParameterDefinitions(List < ParameterDefinition > paramList) {
}
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
try {
ContentReader contentReader = contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
is = contentReader.getContentInputStream();
} catch (NullPointerException ne) {
System.out.println("Null Pointer Exception" + ne);
}
try {
Workbook workbook = new XSSFWorkbook(is);
Sheet firstSheet = workbook.getSheetAt(0);
Iterator < Row > iterator = firstSheet.rowIterator();
while (iterator.hasNext()) {
ArrayList < String > al = new ArrayList < > ();
System.out.println("");
Row nextRow = iterator.next();
Iterator < Cell > cellIterator = nextRow.cellIterator();
while (cellIterator.hasNext()) {
cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.print("\t" + cell.getStringCellValue());
al.add(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.print("\t" + cell.getBooleanCellValue());
al.add(String.valueOf(cell.getBooleanCellValue()));
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print("\t" + cell.getNumericCellValue());
al.add(String.valueOf(cell.getNumericCellValue()));
break;
}
}
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
String query = "PATH:\"/app:company_home/cm:Dipak/cm:OfferLetterTemplate.doc\"";
SearchParameters sp = new SearchParameters();
StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
sp.addStore(storeRef);
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery(query);
ResultSet resultSet = searchService.query(sp);
System.out.println("Result Set" + resultSet.length());
NodeRef sourceNodeRef = null;
for (ResultSetRow row: resultSet) {
NodeRef currentNodeRef = row.getNodeRef();
sourceNodeRef = currentNodeRef;
System.out.println(currentNodeRef.toString());
}
NodeRef n = new NodeRef("workspace://SpacesStore/78342318-37b8-4b42-aadc-bb0ed5d413d9");
try {
org.alfresco.service.cmr.model.FileInfo fi = fileFolderService.copy(sourceNodeRef, n, "JustCreated" + Math.random() + ".doc");
NodeRef newNode = fi.getNodeRef();
QName TYPE_AUTHORTY = QName.createQName("sunpharma.hr.model", "hrdoctype");
nodeService.setType(newNode, TYPE_AUTHORTY);
ContentReader contentReader1 = contentService.getReader(newNode, ContentModel.PROP_CONTENT);
InputStream is2 = contentReader1.getContentInputStream();
POIFSFileSystem fs = new POIFSFileSystem(is2);
HWPFDocument doc = new HWPFDocument(fs);
doc = replaceText1(doc, "Company", "Datamatics");
ContentWriter writerDoc = contentService.getWriter(newNode, ContentModel.PROP_CONTENT, true);
writerDoc.putContent(doc.getDocumentText());
} catch (FileExistsException | FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static HWPFDocument replaceText1(HWPFDocument doc, String findText, String replaceText) {
System.out.println("In the method replacetext" + replaceText);
Range r1 = doc.getRange();
System.out.println("Range of Doc : " + r1);
for (int i = 0; i < r1.numSections(); ++i) {
Section s = r1.getSection(i);
for (int x = 0; x < s.numParagraphs(); x++) {
Paragraph p = s.getParagraph(x);
for (int z = 0; z < p.numCharacterRuns(); z++) {
CharacterRun run = p.getCharacterRun(z);
String text = run.text();
if (text.contains(findText)) {
run.replaceText(findText, replaceText);
} else {
System.out.println("NO text found");
}
}
}
}
return doc;
}
public void setFileFolderService(FileFolderService fileFolderService) {
this.fileFolderService = fileFolderService;
}
public void setNodeService(NodeService nodeService) {
this.nodeService = nodeService;
}
public void setContentService(ContentService contentService) {
this.contentService = contentService;
}
public void setSearchService(SearchService searchService) {
this.searchService = searchService;
}
}
Its not possible to take direct file stream object in alfresco.
so i created one file at local drive, in background i performed all replacement operations. and after that i read all data using file input stream object. and later i used file that stream with node.
and it gave me my desired output. :)
i had created script which get element from excel , .
Here is my script
public void readExcel() throws BiffException, IOException {
String script = "return rlSerial;";
WebDriver driver;
String baseUrl;
System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.Jdk14Logger");
driver = new FirefoxDriver();
baseUrl = "http://website.com/";
String SiteWindow = driver.getWindowHandle();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
String FilePath = "D:\\TestData.xls";
FileInputStream fs = new FileInputStream(FilePath);
Workbook wb = Workbook.getWorkbook(fs);
// TO get the access to the sheet
Sheet sh = wb.getSheet(0);
// To get the number of rows present in sheet
int totalNoOfRows = sh.getRows();
int totalNoOfCol=sh.getColumns();
sh.getColumns();
for (int row =1; row < totalNoOfRows; row++)
{
for (int col = 0; col < totalNoOfCol; col++){
if (col == 0)
{
System.out.println("Check for Elink "+sh.getCell(col,row).getContents());
}
if (col == 1) {
driver.get(baseUrl +sh.getCell(col,row).getContents());
}
if (col ==2 ) {
driver.findElement(By.xpath(sh.getCell(col,row).getContents())).click();
for (String PromoWindow : driver.getWindowHandles()) {
driver.switchTo().window(PromoWindow); // switch focus of WebDriver to the next found window handle (that's your newly opened window)
}
}
if (col ==3 ) {
String exSerial = (String) ((JavascriptExecutor)driver).executeScript(script);
System.out.println("Actual rlSerial = "+ exSerial + "\t" +"Excpected rlSerial = "+sh.getCell(col,row).getContents());
Assert.assertEquals(exSerial ,sh.getCell(col,row).getContents());
System.out.println("Pass");
driver.close();
driver.switchTo().window(SiteWindow);
}
}
}
}
public static void main(String args[]) throws BiffException, IOException {
runTest DT = new runTest();
DT.readExcel();
}
}
If my test cases pass i want to write Pass on next column and if fail then "Fail".
How to achieve this , what to need to be done !!!
To Achieve this first you have to create a new cell in the given row and then set value as "pass" and "fail" to this cell. Use the following code:
sheet.getRow(rowNumber).createCell(columnNumber).setCellValue("pass");
EDIT:
In your code you are using Assert.assertEquals(actual, expected) function which is used with TestNg Annotations, but you are not using TestNG annotations here, So better way is simply compare your actual and expected strings by using equals() or equalsIgnoreCase() method and set your column pass or fail based on that, Here is the solution you want:
if (col ==3 ) {
String exSerial = (String) ((JavascriptExecutor)driver).executeScript(script);
System.out.println("Actual rlSerial = "+ exSerial + "\t" +"Excpected rlSerial = "+sh.getCell(col,row).getContents());
//Assert.assertEquals(exSerial ,sh.getCell(col,row).getContents());
if(exSerial.equals(sh.getCell(col,row).getContents())){
sh.getRow(row).createCell(totalNoOfCol).setCellValue("Pass");
System.out.println("Pass");
}
else{
sh.getRow(row).createCell(totalNoOfCol).setCellValue("Fail");
System.out.println("Fail");
}
driver.close();
driver.switchTo().window(SiteWindow);
}
And save your worksheet after the end of for loop like that:
FileOutputStream outFile =new FileOutputStream(new File(FilePath ));
wb.write(outFile);
outFile.close();