getTableLevel() method of org.apache.poi.hwpf.usermodel.Paragraph - java

I am trying to modify the existing code which converts MS word documents to text using apache POI. I am new to this Apache POI API. There is GetTableLevel() method of org.apache.poi.hwpf.usermodel.Paragraph class which returns some integer value.
For some table, this method returns value 1 and for some other tables it returns 0. I am not able to understand this behaviour.
I looked at JavaDoc of this API here but there is no description about the return values of this method.
Can anyone please tell me what are the possible return values of this method?
Here is code snippet which calls the GetTableLevel() method :
for (int x = 0; x < lenParagraph; x++) {
Paragraph paragraph = range.getParagraph(x);
int tableLevel = paragraph.getTableLevel();
Please enlighten !!!

paragraph.getTableLevel() returns the nesting level (aka "table depth") of a table. For paragraphs which are not part of a table this call always yields 0 - and in addition paragraph.isInTable() will return false.
A return value of 1 indicates an ordinary (top level) table. All values n>1 represent a table which is nested n-1 times within another (parent) table.
For more details see [MS-DOC, Section 2.4.3].

try the source at http://kickjava.com/src/org/apache/poi/hwpf/usermodel/Paragraph.java.htm

Related

Apache Poi cell not returning the correct value

I have a excel file with a cell that generates the number 3.69 (based on calculations from proceeding numbers)
However when pulling that number in java using
if (brightCell.getNumericCellValue()) > 0 )
{
double brightness = brightCell.getNumericCellValue();
return brightness;
}
I've also tried:
if (Double.parseDouble(brightCell.getStringCellValue()) > 0 )
{
double brightness = Double.parseDouble(brightCell.getStringCellValue());
return brightness;
}
brightCell is instantiated with :
brightCell = spreadsheet.getRow(new CellReference(brightString).getRow()).getCell(new CellReference(brightString).getCol());
brightString is String brightString = "BV29"
But with both solutions, brightness receives the value, 3.2133....
So thanks to #Igor I managed to figure it out but it led to more issues.
So the solution was creating an evaluator
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluator.setIgnoreMissingWorkbooks(true); //if you need it
when you finish setting the required cells and want to evaluate.
evaluator.EvaluateAll();
The problem for me is I'm doing this multiple times and my 1st resut is correct but upon the second iteration it becomes skewed, and more skewed.
What I'm doing is setting various cells (via java) then before I retrieve the value for a cell (that contains a formula) I run EvaluateAll. Now, I'm not sure if I should be evaluating after EVERY change or after I make all my changes to the excel sheet (via java).
I can't evaluate a specific cell at a time because there's over 38 sheets with multitudes of formulas. So EvaluateAll is the best option for me
EDIT 26/10/2018*
So the issue was not clearing the cache after making inputs. The solution was after each input as specified in the javaDoc that:
Should be called whenever there are changes to input cells in the evaluated workbook.
Failure to call this method after changing cell values will cause incorrect behaviour
of the evaluate~ methods of this class
therefore after making an input on a cell you should call evaluator.clearAllCachedResultValues();

How to keep track of inserted page numbers or get a row reference when a page number is changing in .docx file using Apache POI

I am creating a Java application in which I am interacting with document file .docx. I am using Apache POI to generate it and modify into it.
The existing file is having tables like:
Tables that are created initially.
I have to add the rows in the first table so that the output is something like: The way the 2 tables should be shown
So this is like I am allowing table 1 to occupy the space till it can go in document page, it is followed by another table. This type of table is needed because after that I am removing its inside borders and it shows something like: how it should be shown with inside borders removed.
I am adding the blank rows using this piece of code..
for (int i = 0; i < itemCount; i++) {
oldRow = table.getRow(i);
newRow = table.insertNewTableRow(i + 1);
for (int j = 0; j < oldRow.getTableCells().size(); j++) {
cell = newRow.createCell();
CTTcPr ctTcPr = cell.getCTTc().addNewTcPr();
ctTcPr.addNewTcBorders().addNewTop().setVal(STBorder.NIL);
ctTcPr.addNewTcBorders().addNewBottom().setVal(STBorder.NIL);
CTTblWidth cellWidth = ctTcPr.addNewTcW();
cellWidth.setType(oldRow.getCell(j).getCTTc().getTcPr().getTcW().getType());
// sets type of width
BigInteger width = oldRow.getCell(j).getCTTc().getTcPr().getTcW().getW();
cellWidth.setW(width); // sets width
if (oldRow.getCell(j).getCTTc().getTcPr().getGridSpan() != null) {
ctTcPr.setGridSpan(oldRow.getCell(j).
getCTTc().getTcPr().getGridSpan()); // sets grid span if any
}
}
}
In few of the lines in starting, I am adding value as something like:
paragraph = row.getCell(0).getParagraphArray(0);
if (paragraph == null) {
paragraph = row.getCell(0).addParagraph();
}
run = setRunAndParagraph(paragraph);
run.setText(itemNames[i]);
All this works nicely, this code was helped by a great coder here who helped me to solve earlier issue.
Now, when I am inserting the rows, I can manually count that for A4 size page, this many rows will be there in table 1, and can iterate likewise. But, the issue is, some item names are wider than column length and as word wrap is on, row for that particular item takes height twice as normal. So, I can get number of rows but not exactly decide how many lines occupied by the items.
The rows appended are for better look and application specific so I thought of an approach that may work:
I am adding page numbers in footer, after inserting a blank row, I am checking whether total page numbers of a document changed or not, if yes that means the code stops there. And as there's 1 excess row I am removing it.
But the issue here arise is I am not able to get page number. I tried
document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
But that always shows 1 even if total pages becomes 2. I searched for an approach stating to check form-feed but I think I am having tables here so I don't know it will be helpful approach or not. So I went for adding page number in the page as a field but that also gave 1 every time. Then I tried to do it with footer and this is how I am writing the page number.
XWPFHeaderFooterPolicy p = document.createHeaderFooterPolicy();
XWPFFooter f = p.createFooter(XWPFHeaderFooterPolicy.DEFAULT);
paragraph = f.createParagraph();
//paragraph.createRun().setText("Page: ");
paragraph.createRun();
paragraph.getCTP().addNewFldSimple().setInstr("PAGE \\* MERGEFORMAT");
Now I don't know how to get value of this field, I tried getText() on footer but it did not gave the number. I read that fields are related to paragraph so I tried to get the paragraph from the footer and tried to call getText() but the output is nothing. So can someone help me with this scenario? Right now I am getting the response like this: some part of second table going in next page.
I tried to implement solution I found, but I could not get it resolved yet. so if someone can help me in this scenario like how to fetch this page numbers from the field inserted in the document, it would be really great. I tried to provide more details so that if there's a better approach than this then also someone can suggest the same. Thank you.. :)

XPages - Lotus Domino Java - getDocumentByKey

In a Java class in my XPages application, I'm trying to get a handle on a Notes Document in a Notes View. The Notes View contains several Notes Documents. To get the Notes Document I want, I use 2 keys. This produces an error. If I use just one key, the first Notes Document in the Notes View is returned. The Notes View contains two sorted columns. The first column contains the empLang value, the second column contains the templateType value. Here is my code:
String empLang = "en";
String templateType = "C";
Database dbCurr = session.getCurrentDatabase();
String viewName = "vieAdminTemplates" + empLang;
View tview = dbCurr.getView(viewName);
Vector viewKey = new Vector();
viewKey.addElement(empLang);
viewKey.addElement(templateType); // this line causes the code to fail
Document templateDoc = tview.getDocumentByKey(viewKey);
What could be the cause of this problem?
A couple of ideas
1) You could concatenate the key into a single column since you said that worked. Something like 'en~C'
2) You could use the database.search method where you include a string of formula language that isolates the document you want. It returns a collection, and then you pull the document from there.
getDocumentByKey works with multiple columns. There's a known problem with doubles, but you're not hitting that there. One thing that stands out is the second column is just a single letter. That could be considered as a Char instead of a String, either when you do addElement or by the view.
I'd recommend debugging out what data type they are. viewKey.get(1).getClass().getName() I think gives you the class it's stored as. Doing the same for the View Column value.
When you say it causes the code to fail, how does it fail? Does it just not return anything or throw an error?
My next step would be to try testing it where the View and the Vector contain more than one character, e.g. "CC", to help check if there's an underlying issue with Java getDocumentByKey and single characters.
I'm very sorry. The problem here is that the view name in the code is incorrect. There is a view "vieAdminTemplates" but it does not have a second column containing the value "C". With the correct view, the code works fine. Thanks for taking the time to respond to my question.

Redefine Named Excel Range then Save using Apache POI

Using Apache POI, I'm able to find a named range:
XSSFName[] ranges = new XSSFName[workbook.getNumberOfNames()];
for (int i = 0; i < _wb.getNumberOfNames(); i++)
ranges[i] = workbook.getNameAt(i);
With that, I'm able to cell an AreaReference:
AreaReference area = new AreaReference(ranges[0].getRefersToFormula());
And then finally I can get all the cells within that range:
CellReference[] cells = area.getAllReferencedCells();
That all works just fine. Burt I have a use case where I have to redefine the area that the range covers. Is there a way to do that? I notice that the range.getRefersToFormula() method return a String, something like MySheet!$A$1:$B$8. There is a range.setRefersToFormula(String formula), but I've got to believe there's a way other than resorting to writing an excel range formula parser on my own. Is there no way to generate an AreaReference with a set to Cell references of something more type-safe? Do I actually have to generate a String to represent the new range? I would think there would be API somewhere to help me with this but I can't seem to find it.
Update
I found some API, but it doesn't seem to work, at least it doesn't save properly. Here's what I did.
AreaReference newArea = new AreaReference(firstCell, lastCell);
ranges[0].setRefersToFormula(newArea.formatAsString())
It seems to set the formula correctly, but when I stream the workbook back out to disk, the range is completely wrong.
you can update the existing Reference and set it as per your requirement.
Suppose the reference contains TestSheet!$A$1:$B$8and you want to change it to MySheet!$B$5:$C$12
For any cell, say "B5", at runtime,
cell.getReference();
will give you cell reference (like in example... it will return you "B5")
char startCellColRef = cell.getReference().toString().charAt(0);
will give you the Column Reference (will give you "B" if the current cell is B5). Now
int startCellRowRef = cell.getReference().toString().charAt(1);
will give you Row Index (will give you "5" if the current cell is B5).
By the same way you can get your start and end cell references (say B5 and C12).
Now comes how can I update the existing references. Just update its value with newly created reference string
Name reference = wb.getName("NameReferenceInExcelSheet");
referenceString = sheetName+"!$"+startCellColRef+"$"+startCellRowRef+":$"+endCellColRef+"$"+endCellRowRef;
reference.setRefersToFormula(referenceString);

How would I construct a really simple java maths expression to be used with KNIME

Im currently using a program called KNIME, which is used for analysing data. For some of my data, I want each row in a column to be averaged with the value in the previous row. The 'java snippet' option requires a 'global value declaration' and a 'method body'. The column name is 'new acc'.
I understand to use this program more efficiently I'll probably need to learn simple java (and its on my to do), but just for this evening I would like a quick check on some of the data used.
Any help is really appreciated - ive attached an image of the layout.
Thanks!
If you aren't required to use the Java Snippet, I'd recommend the Math Formula node.
There's a Moving Average Node which might be suitable for the task.
What about putting
double acc = Double.NaN;
to the global area, and something like this to the method body:
if (Double.isNaN(acc)) {
acc = $z$;
return $z$;
} else {
double avg = (acc + $z$) / 2;
acc = $z$;
return avg;
}
As a partial answer to the one from Sylvansight, it should be noted that the Java Snippet node is executed on a per row basis, so it's not even possible to use the Java Snippet node to access the values in the previous or subsequent rows.
Math formula node fits better your problem, but if you want to use **java snippet node (simple) ** just put the formula in the return (using normal java sintax). return 1+9;

Categories

Resources