iText formatting tables - java

I'm generating a PDF document (for those who have seen his before, yes still) using the iText5 library. Compliments to Bruno Lowagie; I've found it to be a really great API!
However, part of my task is to format some phrases. I used a nested PdfPTable to format the data, but I'm getting bizarre spacing issues. Here is an example of the problem I'm facing:
As you can see, rows with only a couple of phrases in them tend to have huge gaps in between them. I can understand why this is happening; the rows above are stretching the table. Is there a way to only make the table as big as it needs to be, and no larger?
Code
Generating the prices collection
I'm creating the prices with this snippet:
Paragraph pricePara = new Paragraph();
pricePara.add(price);
pricePara.add(generateBreakLine());
pricePara.add(time);
pricePara.add(generateBreakLine());
allPrices.add(pricePara);
where generateBreakLine() returns an empty Paragraph object.
Adding them into the cell
I add them into the cell with the following snippet:
// 5 is just the amount of prices we can fit on one line.
PdfPTable pricesCellValue = new PdfPTable(elements.size() > 5 ? 5 : elements.size());
// Make it appear that the prices are just horizontal, as opposed to in a table.
pricesCellValue.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
// Cycle through each price. Add to cell. Add cell to the table.
for (com.lowagie.text.Element elem : elements) {
PdfPCell cell = new PdfPCell((Paragraph) elem);
cell.setBorder(PdfPCell.NO_BORDER);
cell.setPadding(2);
pricesCellValue.addCell(cell);
}
return pricesCellValue;
The above snippet, I believe, is where I can make sure the table is only as wide as it needs to be, as opposed to filling up all the space around it. How would I go about doing that?

Solved
Found a simple way of fixing it. In stead of changing the amount of columns based on the number of prices, I make sure the column number is always 5, and then append empty cells on:
if(elements.size() < 5)
{
int diff = 5 - elements.size();
for(int x = 0; x < diff; x++)
{
pricesCellValue.addCell(new Paragraph(" "));
}
}

Related

Aspose Cells for Java: get original CSV row

I am using Aspose to read a CSV file.
I do not beforehand know the number of cells for each row of the file, but I will need to know it for further processing.
Unfortunately, I see no way to find out the number of cells in a CSV row.
Imagine the following row in the CSV file. It contains 7 cells, 4 of which are empty:
1,2,,4,,,
Using
row.iterator();
Aspose will only return 3 cells, as it ignores all empty cells.
As an alternative, I now do the following:
Cell lastCell = row.getLastCell();
int count = 0;
do {
cell = row.getCellOrNull(count);
String cellValue = cell == null ? "" : cell.getStringValueWithoutFormat();
//do something with the cell value...
count++;
} while (cell == null || ! lastCell.equals(cell));
This works better, as it returns the first 4 cells.
However, it still ignores the last 3 cells .
Is there any way to get information about the missing cells?
(It would be sufficient for me if Aspose could return the original Row as a String - I could then count the number of commas and find out the number of cells this way)
You may use Worksheet.getCells().getMaxDisplayRange() method to get the maximum display range.
Please consider this CSV. If you open it in MS-Excel and check the last cell, you will find it is Q2
Book1.csv
2,,,,1,,,,,,,,,,,,,
,,3,,,,
Aspose.Cells returns the same via the following code.
TxtLoadOptions opts = new TxtLoadOptions(LoadFormat.CSV);
Workbook wb = new Workbook("Book1.csv", opts);
Worksheet ws = wb.getWorksheets().get(0);
Range rng = ws.getCells().getMaxDisplayRange();
System.out.println(rng);
Here is the console output of the code.
Console Output
Aspose.Cells.Range [ Sheet1!A1:Q2 ]
Note: I am working as Developer Evangelist at Aspose

Selenium - How to count the number of rows in a table dynamically?

In my html page there's a table with 10 rows; those rows will display based on filter (dynamically). Let's say, for example, without any filters by default 10 row will be returned.
after applying the filter, less than 10 rows will be returned, depending on the type of filter, so i want to get that dynamic count of table rows (after filter) using selenium web driver.
i tried with driver.findElements(By.xpath("abcd")).size() but this is giving default count 10; however, after applying the filter only 2 rows are appearing.
Please suggest how to get dynamic count (count=2 as appearing 2 rows in UI) .
To find the total number of elements on dynamic webpage we need to use driver.findElements().size() method. But sometimes it's not useful at all.
First get the size of all element matching with the row count. Once we have it then you can use dynamic xpath ie replace row and column number run time to get the data.
{
List<WebElement> rows_table = mytable.findElements(By.tagName("tr"));
//To calculate no of rows In table.
int rows_count = rows_table.size();
//Loop will execute till the last row of table.
for (int row=0; row<rows_count; row++){
//To locate columns(cells) of that specific row.
List<WebElement> Columns_row = rows_table.get(row).findElements(By.tagName("td"));
//To calculate no of columns(cells) In that specific row.
int columns_count = Columns_row.size();
System.out.println("Number of cells In Row "+row+" are "+columns_count);
//Loop will execute till the last cell of that specific row.
for (int column=0; column<columns_count; column++){
//To retrieve text from that specific cell.
String celtext = Columns_row.get(column).getText();
System.out.println("Cell Value Of row number "+row+" and column number "+column+" Is "+celtext);
}
System.out.println("--------------------------------------------------");
}
I'll prefix this with the fact that I'm not a Java dev but I use a lot of webdriver in other languages.
The best way to setup tests is to wait for the outcome of the action that your testing. Sometimes you can get away without doing waits, or timed waits, but then you go and run your tests on a slower grid box and everything falls in a heap.
Things like "div exists", "div has class", whatever your outcome may be. In your case, it sounds like you may not be able to test for a div to be rendered but you can probably use your size test as the outcome to wait for.
Selenium can use any ExpectedCondition or you can specify a function
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
int elementCount = driver.findElement(By.xpath("xxxx")).size();
if (elementCount == 2)
return true;
else
return false;
}
});
Code from https://sqa.stackexchange.com/a/8701

Need help regarding array formulas implementation in apache poi api

I got allocated updation of existing project. Previous developer used jcom api to export data to excel sheets. But jcom api don't work with 64 bit systems. I decided to change code and using apache poi api. I managed to done many methods. My problem is array formulas. I Need to implement array formulas using apache poi. Those formulas are posted below, any help will be more appreciable. Thanks in advance guys.
Formulas:
String formula1 = "SUM(R[-2]C/1.200)";//net income calculation from gross income
String formula2 = "SUM(R[-1]C-R[1]C)";
String formula3 = "SUM(R[-" + Integer.toString(listTypeTotals.size()+1) + "]C:R[-2]C)";
I tried to set that cell as formulatype and passing formula as string.
setCellFormulaStyle(sheet, 4, i+2, formula2);
public static void setCellFormulaStyle(HSSFSheet sheet,int row, int column,String value)
{
HSSFRow temprow = null;
temprow =getRow_CreateRow(sheet, row);
temprow.createCell(column).setCellFormula(value);
}
public static HSSFRow getRow_CreateRow(HSSFSheet sheet,int row)
{
HSSFRow excelrow=null;
excelrow = sheet.getRow(row);
if(excelrow==null)
{
excelrow =sheet.createRow(row);
return excelrow;
}else
return excelrow;
}
I am getting following exception
org.apache.poi.ss.formula.FormulaParseException: Specified named range 'R' does not exist in the current workbook.
at org.apache.poi.ss.formula.FormulaParser.parseNonRange(FormulaParser.java:569)
at org.apache.poi.ss.formula.FormulaParser.parseRangeable(FormulaParser.java:517)
at org.apache.poi.ss.formula.FormulaParser.parseRangeExpression(FormulaParser.java:268)
at org.apache.poi.ss.formula.FormulaParser.parseSimpleFactor(FormulaParser.java:1119)
at org.apache.poi.ss.formula.FormulaParser.percentFactor(FormulaParser.java:1079)
at org.apache.poi.ss.formula.FormulaParser.powerFactor(FormulaParser.java:1066)
at org.apache.poi.ss.formula.FormulaParser.Term(FormulaParser.java:1426)
at org.apache.poi.ss.formula.FormulaParser.additiveExpression(FormulaParser.java:1526)
at org.apache.poi.ss.formula.FormulaParser.concatExpression(FormulaParser.java:1510)
at org.apache.poi.ss.formula.FormulaParser.comparisonExpression(FormulaParser.java:1467)
at org.apache.poi.ss.formula.FormulaParser.Arguments(FormulaParser.java:1051)
at org.apache.poi.ss.formula.FormulaParser.function(FormulaParser.java:936)
at org.apache.poi.ss.formula.FormulaParser.parseNonRange(FormulaParser.java:558)
at org.apache.poi.ss.formula.FormulaParser.parseRangeable(FormulaParser.java:429)
at org.apache.poi.ss.formula.FormulaParser.parseRangeExpression(FormulaParser.java:268)
at org.apache.poi.ss.formula.FormulaParser.parseSimpleFactor(FormulaParser.java:1119)
at org.apache.poi.ss.formula.FormulaParser.percentFactor(FormulaParser.java:1079)
at org.apache.poi.ss.formula.FormulaParser.powerFactor(FormulaParser.java:1066)
at org.apache.poi.ss.formula.FormulaParser.Term(FormulaParser.java:1426)
at org.apache.poi.ss.formula.FormulaParser.additiveExpression(FormulaParser.java:1526)
at org.apache.poi.ss.formula.FormulaParser.concatExpression(FormulaParser.java:1510)
at org.apache.poi.ss.formula.FormulaParser.comparisonExpression(FormulaParser.java:1467)
at org.apache.poi.ss.formula.FormulaParser.unionExpression(FormulaParser.java:1447)
at org.apache.poi.ss.formula.FormulaParser.parse(FormulaParser.java:1568)
at org.apache.poi.ss.formula.FormulaParser.parse(FormulaParser.java:176)
at org.apache.poi.hssf.model.HSSFFormulaParser.parse(HSSFFormulaParser.java:72)
at org.apache.poi.hssf.usermodel.HSSFCell.setCellFormula(HSSFCell.java:594)`
I am not sure how you have use the formula yet. However if your problem is regarding the dynamic cell reference based on rows and Columns, perhaps I can help you.
For any cell, say "B5", at runtime,
cell.getReference();
will give you cell reference (like in example... it will return you "B5"
cell.getReference().toString().charAt(0);
will give you the Column Reference (will give you "B" if the current cell is B5). Now
cell.getRowIndex();
OR
cell.getReference().toString().charAt(1);
will give you Row Index. I have used that multiple times to update/create the Named ranges and formula on my workbook.
Small Changes to include handling address like AZ89
For the cases of AZ99 we can use for this we can use small hacks like:
String str = cell.getReference();
for(index = 0;index<str.length();index++){
if((int)str.charAt(index)<65){
break;
}
}
String Col = str.substring(0, index);
String Row = str.substring(index+1, str.length());

Writing to a particular cell location using Apache POI Excel

If I've got an list of parameters 'x,y,z' that aren't sorted, is there a straightforward way to write them to particular cells in an excel document created with POI, as though the first two parameters are X and Y coordinates?
For example, I have rows like:
10,4,100
Is it possible to write the value '100' in the cell at the 10th row, 4th column?
Looking at the documentation, it looks straightforward to iterate values into the next row, but I can't see any way of creating a fixed number of rows and columns and writing particular values to only certain cells.
Any advice or suggestions would be appreciated, thanks!
Sure, it's very easy, just remember that POI is 0 based not 1 based in addressing. Assuming you want to write to the 10th row, 4th column, you'd do something like
Row r = sheet.getRow(9); // 10-1
if (r == null) {
// First cell in the row, create
r = sheet.createRow(9);
}
Cell c = r.getCell(3); // 4-1
if (c == null) {
// New cell
c = r.createCell(3, Cell.CELL_TYPE_NUMERIC);
}
c.setCellValue(100);

Creating a dynamic 2D matrix in Java

I want a dynamic matrix, number rows and columns unkonw, filling it by clicking on a button. Bu there is more: I don't want to add entire rows, but just one cell at the time, one click = one cell added. Of course not randomly : 1st cell of 1st row, 2nd cell of 1st row... and then the same of the 2nd row and so one...
I know about UJMP, ArrayList, but it's not quite what I'm looking for. Please be accurate on your answer, thank you in advance.
Use this:
List<List<Integer>> dynamicMatrix = new ArrayList<List<Integer>>();
dynamicMatrix.add(new ArrayList<Integer>());
dynamicMatrix.add(new ArrayList<Integer>());
dynamicMatrix.add(new ArrayList<Integer>());
dynamicMatrix.get(0).add(6);
dynamicMatrix.get(0).add(7);
dynamicMatrix.get(0).add(8);
System.out.println(dynamicMatrix.get(0).get(0)); // 6
System.out.println(dynamicMatrix.get(0).get(1)); // 7
System.out.println(dynamicMatrix.get(0).get(2)); // 8

Categories