I'm having some issues with autosizing cells. After my program populates and formats each accordingly, it autosizes the cells to make it look visually acceptable. The issue is, when the cell is formatted as percentage, it auto-sizes the cell without taking in consideration the fact that there's a '%' character, so we end up getting #### on the cells until you expand the cell. Is there a way to autosize it WHILE taking in consideration that extra '%' character?
EDIT:
So this is what happens, the left VAR has been autosized correctly for whatever reasons, but the VAR on the right hasn't.
EDIT2:
I noticed that this ONLY happens when the cell value is 0.00% So all the values in the column for VAR that has #### were 0s and some of the values in the left column for VAR were non-zeros.
While this may not be an ideal solution, one possibility is to grab the size of the string you are inserting into the cell (ie. "50.00%" = size of 6), and set the cell width based manually based on that.
I'm afraid this is not supported in Apache POI, as it disregards the custom cell formatting when trying to calculate column width (it only takes font characteristics and rotation into consideration, but no DataFormat).
As a workaround you can try to write your custom autoSizeColumn method as a modification of the one currently implemented, i.e.:
public void autoSizeColumn(Sheet sheet, int column, int plusMinusChars) {
double width = SheetUtil.getColumnWidth(sheet, column, false);
if (width != -1) {
width += plusMinusChars;
width *= 256;
int maxColumnWidth = 255*256; // The maximum column width for an individual cell is 255 characters
if (width > maxColumnWidth) {
width = maxColumnWidth;
}
sheet.setColumnWidth(column, (int)(width));
}
}
Then you can call it with an extra '%' character to be printed out:
//4th column autosized + 1 character in width to accomodate for '%'
autoSizeColumn(sheet, 3, 1);
Related
I'm trying to set the colunm width with setColumnWidth(rowindex, width) using POI,problem is the width is in double and the function above only accept Int
I tried using autosizecolumn but its still living underpopulated space in the column, problem i think is the font mismatch between excel and java
code
RowTotal = NewSheet.createRow(0);
cell1 = RowTotal.createCell(0);
cell1.setCellValue("Row Name/Label");
cell1 = RowTotal.createCell(1);
cell1.setCellValue("Sum of premium payable");
cell1 = RowTotal.createCell(2);
cell1.setCellValue("Sum of arrears payable");
NewSheet.setColumnWidth(0, 3755.84);
NewSheet.setColumnWidth(1, 5519.68);;
NewSheet.setColumnWidth(2, 5207.36);
You cannot pass double value to setColumnWidth as well as to autosizecolumn because both the methods of Apache POI accepts int value as parameters.
Methods of Apache POI:
1. autoSizeColumn(int column)
Adjusts the column width to fit the contents.
2. setColumnWidth(int columnIndex, int width)
Set the width (in units of 1/256th of a character width)
you can refer to https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFSheet.html
for more details.
Use:
NewSheet.getColumnHelper().setColWidth(0, 3755.84);
NewSheet.getColumnHelper().setCustomWidth(0, true);
I'm not sure if the second line is necessary but if you manually change the width of a column in excel, it will automatically set CustomWidth = true. So I just add it to be safe.
I have a JTable with an AbstractTabelModel displayed. I tried to create a void method in my project that sets the width of each column to the length of the longest value in the column. Here is the method that I am using right now, where "accountWindow" is the JTable:
public void setColumnWidths(){
accountWindow.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
for (int i = 0; i < accountWindow.getColumnCount(); i++){
int greatestStringLength = 2;
for (int z = 0; z < accountWindow.getRowCount(); z++){
if (accountWindow.getValueAt(z, i).toString().length() > greatestStringLength){
System.out.println("Width SET");
greatestStringLength = accountWindow.getValueAt(z, i).toString().length();
accountWindow.getColumnModel().getColumn(i).setPreferredWidth(greatestStringLength);
}
//System.out.println(accountWindow.getValueAt(z, i).toString());
//System.out.println("Greatest Value: " + greatestValueWidth);
}
}
}
The method is called correctly in my Controller class (MVC), but it is setting the width of each column to essentially 0. Method is called after the table is updated and the fireTableData() method is called and account information is displayed. I have added the JTable to a scroll pane. Any comments or suggestions would be appreciated.
The width needs to be specified in pixels not characters in the String.
if (accountWindow.getValueAt(z, i).toString().length() > greatestStringLength){
Looks to me like you are just getting the number of characters in the String, not the width it takes to render the String. That is 20 characters will NOT render in 20 pixels. The width of the String will vary for different Fonts.
Check out Table Column Adjuster for the solution on how to determine the rendered width. It gives a simple usage and a custom class that you can use which has more features.
Both solutions will actually invoke the renderer used by the table to determine the maximum width.
I have a function which I've been using for a good while in java which calculates cell widths for a pdftable from a given array of string values.
It works very well, and I recently wrote a version of the function in c# and it doesn't give the expected result (i.e text is wrapped to multiple lines) - both java and c# code shown below any help much appreciated
This is the Java version;
float[] CalculateCellWidths(String[] CellHeaders, Font CellFont)
{
float[] CellWidths = new float[CellHeaders.length];
for (int i = 0; i < CellHeaders.length; i++)
{
CellWidths[i] = CellFont.getCalculatedBaseFont(true).getWidthPoint(CellHeaders[i], CellFont.getCalculatedSize());
}
return CellWidths;
}
This is the C# version;
float[] CalculateCellWidths(String[] CellHeaders, iTextSharp.text.Font CellFont)
{
float[] CellWidths = new float[CellHeaders.Length];
for (int i = 0; i < CellHeaders.Length; i++)
{
CellWidths[i] = CellFont.GetCalculatedBaseFont(true).GetWidthPoint(CellHeaders[i], CellFont.CalculatedSize);
}
return CellWidths;
}
I see from your comment that the problem has been solved, but that you don't know why, so here's a small explanation about LockWidth.
There are two ways to define the width of a table. Either the table takes a percentage of the available width. This is a relative width that depends on page size and page margins. Historically, this percentage is 80% and the table is centered. You can change this width percentage with the setWidthPercentage() method. If you use a method to set the widths of the invidual columns, those widths will be treated as relative widths, for instance { 10, 10, 20 } means that you have a table with 3 columns where the first two columns take a quarter of the available width and the third column takes half.
You can also set the absolute width of a table. You can set the total width with the setTotalWidth() method. You can also define the absolute widths of the columns. However, these absolute widths are ignored in favor of the default width percentage as long as you don't "lock" the width. This is what happens if you use setLockedWidth(true) (Java) or table.LockedWidth = true (C#).
Based on your comment, I think the problem was caused by locking the width of the columns so that absolute values were used instead of relative values.
What is the recommended way of printing a text document as a pdf using absolute positioning ?
I am having a table that I have to print. I am also having the data type lengths and starting positions of the columns.
Since the existing table was a character based, there was no problem in its positioning. But even after using a monotype font (Courier, 10) I am not able to properly position the data and last column(s) of each row erroneously skip to the next line.
In order to present my data as close as the character one, I divided the page into different columns(based on its page size) and then add the contents at the desired place. I am adding chunks of data into the paragraph.
paragraph.add(new Chunk(new VerticalPositionMark(), columnNo*ptUnit, false));
I have tried to tweak the page size, font size and margin lengths, but the data is not properly displayed. Have you encountered any such problems ? please do share your thoughts.
Have you tried ColumnText
When i want to write a paragraph and I do know the amount of lines...I do a cycle incrementing (even it says incrementing and is minus is because the pdf is from "south" to "north" (0 - height) the y in a proportion of the fontsize, something like this
//_valueArray is my string[]
//fontSize is the value of the Size of the font...
//1.5 it's just a magic number :) that give me the space line that i need
//cbLocal is the PdfContentByte of the pdf
for (i = 0; i < _valueArray.Length; i++)
{
var p = new Phrase(_valueArray[i], font);
ColumnText.ShowTextAligned(cbLocal, align, p, x, y, 0);
if (i + 1 != _valueArray.Length)
{
y = y - (fontSize*1.5f);
}
}
The basic question:
While changing the width of a TableColumn the method SwingUtilities.layoutCompoundLabel(..) sets the parameter Rectangle textR to an old value (or 'the value before').
How could I get the current (real) Rectangle value?
Some background information and bugfixes:
I use the MatchingTextHighlighter.java from the SwingLabs-Demos (the example is SearchDemo.java)
It is a very nice start to mark just the found characters in a JXTable cell. But I have some issues with the position of the Highlighter if I change the alignment of the cell-content from LEFT to:
table.getColumnExt( 1 ).setCellRenderer( new DefaultTableRenderer( null, SwingConstants.RIGHT ) );
or
table.getColumnExt( 1 ).setCellRenderer( new DefaultTableRenderer( null, SwingConstants.CENTER ) );
Three bugs occur if characters are highlighted:
Situation: The text of the JLabel is fully visible.
The problem: The wider the column gets (resized using the columnheader), the more the highlighter will drift to the right (awaaay from the matched characters).
Situation: The text of the JLabel is partially visible (painted with ellipsis ...), but the highlighted string is fully visible.
The Problem: The highlighter position is wrong from one pixel to one character while resizing the column width.
Situation: The text of the JLabel and the highlighted string are partially visible (the highlighter should be on the ellipsis)
The Problem: The highlighter on the ellipsis has a wrong width (from no pixel to correct width) while resizing the column width.
This is the only bug that's also visible in a left-aligned column (the highlighter has always the correct width but is jumping to the right sometimes).
The first bug can be fixed by commenting out textR.x in 2 lines (starting at line 327 in MatchingTextHighlighter.java):
if (start == 0) {
// start highlight from the start of the field
highlightx = /* textR.x + */ xOffset;
} else {
// Calculate the width of the unhighlighted text to get the
// start of the highlighted region.
String strToStart = text.substring(0, start);
highlightx = /* textR.x + */ fm.stringWidth(strToStart) + xOffset;
}
Two smaller problems emerge:
One is that the highlighter starts one pixel more left if the matched area begins at the first Label-character. The second is a highlighter-one-pixel-jumping in the center-aligned column, if the width of the column is resized using the columnheader.
Both (plus a RightToLeft-Error) could be fixed with these changes (starting at line 397 in MatchingTextHighlighter.java):
return textR.x;//respect the icon and start the highlight at the beginning of the text not at 0
} else if (horizAlignment == SwingConstants.RIGHT
|| (horizAlignment == SwingConstants.TRAILING && leftToRight) //fix for rtol: ! deleted
|| (horizAlignment == SwingConstants.LEADING && !leftToRight)) //fix for rtol: ! added
{
return viewR.width - textR.width;
} else if (horizAlignment == SwingConstants.CENTER) {
return Math.round((viewR.width - textR.width) / 2f) - 1; //round a float to prevent a one-pixel-jumping Highlighter
The third bug can be partially fixed by (changing line 48 in XMatchingTextHighlighter.java):
int end = /* myTextR.x + */ fm.stringWidth(text) + offset;
Now the highlighter starts always at the first pixel of the ellipsis, fix! :-)
But the widths keeps changing while resizing the column, error! :-(
After debugging the second and (the remaining half of) the third bug in MatchingTextHighlighter.java, I think the call to the utility method
String clippedText = SwingUtilities.layoutCompoundLabel(.....)
sets the parameter textR to an old value. While resizing the column, the calculated width of the text-rectangle seems to be "one event behind". And because of this, the position of the Highlighter is wrong.
Does anyone has an idea to get this fixed?
Thanks for reading all this...