XSLFTable get size to see if it will fit in slide after insertion - apache-poi

I am working on a slide show where I insert N number of rows. There are two issues...
I don't know the number of rows, there is a max of 50 we will allow but even 50 will go out of the slide.
The text I will add to each column can also be somewhat long.
Right now, my current approach is allowing 15 rows, creating a new slide to add the next 15, and so on until I hit 50.
What I would prefer to do is get the size of the table and after I finish one row, I would like to check if it is overflowing out of the slide, and if it is, I'll remove it, make a new slide, and add it to the new table.
An alternative approach if possible, is keep the row height locked, and allow any extra text to kinda be hidden until the cell is selected (similar to an excel spreadsheet).

Using a similar approach here
Apache POI get Font Metrics
Solution:
stringList is repopulated for each row
int max = 0;
int j = 0;
for (String text : stringList) {
AttributedString attributedString = new AttributedString(text);
attributedString.addAttribute(
TextAttribute.FAMILY, "Avenir Book", 0, text.length());
attributedString.addAttribute(TextAttribute.SIZE, (float)14);
TextLayout layout = new TextLayout(attributedString.getIterator(), fontRenderContext);
Rectangle2D bounds = layout.getBounds();
max = Math.max(max, (int) Math.ceil((bounds.getWidth() * covertToEmu)
/ (table.getTblGrid().getGridColList().get(j).getW())));
j++
}
covertToEmu is just a number...bounds.getWidth() is in 72 dpi and table.getTblGrid().getGridColList().get(j).getW() (the width) is in EMU. 72 dpi is just the pixels in inches...which is 72 pixels per inch. An EMU per inch is 914400.
So convertToEmu is 914400 / 72 = 12700.
The max is the number of "rows" it takes...the rest is kinda hard coded, but I split the list of data I have into sublists and add it to each slide. I know 20 rows is a good fit so if it gets higher than that I create a new list, to add to a new slide.
Also worth noting I am using CTTable, which you can get from a method in XSLFTable.

Related

Increasing height merged cells Apache POI

I am using Apache POI SXSSF to generate xlsx document. The document uses Times New Roman sizes 9 and 11, and the default cell width and height have been changed. The question is how to calculate the height of the merged cells so that all the text fits (the height of the cell must be dynamically set according to the given text)? The server running the application does not have a display, and this code is running in the IBM Integration Bus.
The solution from How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java? is not suitable. The server running the application is missing a display and the string int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution(); returns an exception, and manually picking the ppi value is also not possible. If there is a display, everything works correctly.
And is there any way to use the "align center selection" function somehow?
I found that centering a selection gives a similar result as merging multiple cells horizontally, but I couldn't find an answer anywhere on how to use this in Apache POI. As a result, experimentally, I found out that in order to achieve this effect, you need to do the following things:
Create CellStyle; specify setWrapText(true) and setAlignment(HorizontalAlignment.CENTER_SELECTION) for it
Apply the style created in step 1 to all cells that need to be merged
Specify the value in the first cell
Code example:
Font font = wb.createFont(); // where wb - is SXSSFWorkbook object
font.setFontName("Times New Roman");
font.setFontHeightInPoints((short) 11);
CellStyle style = wb.createCellStyle();
style.setFont(font);
style.setWrapText(true);
style.setAlignment(HorizontalAlignment.CENTER_SELECTION);
for (int i = 0; i <= endCellNum - firstCellNum; i++){ // where endCellNum - number of last cell of selection and firstCellNum is number of first cell of selection
Cell cell = curRow.createCell(firstCellNum + i);
cell.setCellStyle(cs);
if (i == 0){
firstCell = cell;
}
}
firstCell.setCellValue(value);

Is there a way to change height of tkinter Treeview heading?

I got a problem with changing the height of the Treeview.heading. I have found some answers about the dimensions of Treeview.column, but when I access Treeview.heading in the documentation, there is not a single word about changing the height of the heading dynamically when the text doesn't fit (and wrapping it) or even just hard-coding height of the heading in pixels.
I don't have to split the text to two rows, but when I just keep it that long the whole table (as it has many entries) takes up the whole screen. I want to keep it smaller, therefore I need to split longer entries.
Here is how it looks like:
I can't find any documentation to verify this but it looks like the height of the heading is determined by the heading in the first column.
Reproducing the problem
col_list = ('Name', 'Three\nLine\nHeader', 'Two\nline')
tree = Treeview(parent, columns=col_list[1:])
ix = -1
for col in col_list:
ix += 1
tree.heading(f'#{ix}', text=col)
The fix
col_list = ('Name\n\n', 'Three\nLine\nHeader', 'Two\nline')
or, if you want to make it look prettier
col_list = ('\nName\n', 'Three\nLine\nHeader', 'Two\nline')
The only problem is I haven't figured out how to centre the heading on a two line header
Edit
The newlines work if it is the top level window but not if it is a dialog. Another way of doing this is to set the style. I've got no idea why this works.
style = ttk.Style()
style.configure('Treeview.Heading', foreground='black')
you can use font size to increase the header height for sometimes;
style = ttk.Style()
style.configure('Treeview.Heading', foreground='black', background='white', font=('Arial',25),)

Python Docx Table row height

So column width is done using cell width on all cells in one column ike this:
from docx import Document
from docx.shared import Cm
file = /path/to/file/
doc = Document(file)
table = doc.add_table(4,2)
for cell in table.columns[0].cells:
cell.width = Cm(1.85)
however, the row height is done using rows, but I can't remember how I did it last week.
Now I managed to find a way to reference the rows in a table, but can't seem to get back to that way. It is possible to change the height by using the add_row method, but you can't create a table with no rows, so the the top row will always be the default height, which about 1.6cms.
There is a way to access paragraphs without using add_paragraph, does anyone know how to access the rows without using the add_row method because it was that that I used to set row height in a table as a default.
I have tried this but it doesn't work:
row = table.rows
row.height = Cm(0.7)
but although this does not give an error, it also has no effect on the height.
table.rows is a collection, in particular a sequence, so you need to access each row separately:
for row in table.rows:
row.height = Cm(0.7)
Also check out row.height_rule for some related behaviors you have access to:
https://python-docx.readthedocs.io/en/latest/api/table.html#row-objects
When you assign to table.rows.height, it just adds a .height instance attribute that does nothing. It's one of the side-effects of a dynamic language like Python that you encounter a mysterious behavior like this. It goes away as you gain more experience though, at least it has for me :)
Some additional information:
The answer here is correct, but this will give a minimum row height. Using WD_ROW_HEIGHT_RULE.EXACTLY will fix the cell height to the set row height ignoring the contents of the cell, this can result in cropping of the text in an undesirable way.
para = table.cell(0,0).add_paragrph('some text')
SOLUTION:
add_paragraph actually adds a blank line above the text.
Use the following instead to avoid using add_paragraph:
table.cell(0,0).paragraphs[0].text = 'some text'
or using add_run can make it easier to also work with the text:
run = table.cell(0,0).paragraphs[0].add_run('some text')
run.bold = True

How to encircle Invalid data in Excel?

I want to show a circle around only invalid data.
i have done the complete steps shown in this link
But this circle shown is very big and covers the entire cell.
I want a small circle only covering the data not the entire cell's width.
Data validation is a built in Excel functionality. It checks whole cell value.
So it is not possible, using Data validation, to accomplish what your trying.
It MAY BE POSSIBLE using VBA, shapes, events and (hard) parsing character rendering. In your place, I would be glad with this very big circles!!! :)
I agree with #LS_dev. See this MS Article about changing data validation for printing. Try modifying it to loop through all your data validation and change the width and height.
You can probably do it with this part of the code by changing the width and height:
If Not c.Validation.Value Then
Set o = ActiveSheet.Shapes.AddShape(msoShapeOval, _
c.Left - 2, c.Top - 2, c.Width + 4, c.Height + 4)
o.Fill.Visible = msoFalse
o.Line.ForeColor.SchemeColor = 10
o.Line.Weight = 1.25

LWUIT Table Layout embedded TextAreas

my goal is to display a Table through parsing an XML file.
I'm using a SAX Parser and the content has multirows and I want
the table width to fit to the display. Of course Y_AXIS scrolling would be ok.
Right now, I'm using the HTMLTableModel of src/com/sun/lwuit/html/ and it's corresponding HTMLTable. For this I declared it's methods public so I can access them. This works fine so far. This allows me to declare tables without knowing their size prematurely.
To allow multirows, I'm embedding TextAreas in the Cells.
Now the problem: The HTMLTable t needs t.setScrollableY(true), or else not all rows are shown.
This causes the table to be a bit to large in X direction, so the right border isn't shown.
Also the bottom border isn't shown all the time.
The container in which the table is embedded has BorderLayout.Y_AXIS.
Things I tried:
t.setPreferredW(mainContainer.getLayoutWidth()); This does reduce the size of the table, but then the table doesn't show all it's rows, like without t.setScrollableY(true).
t.setLayout(new BoxLayout(BoxLayout.Y_AXIS)) this causes an java/lang/ClassCastException.
Any ideas? Thanks in advance.
Excerpt from my code:
} else if (qName.equalsIgnoreCase("td")) {
if (sb.length() > 0) {
String sbt = new String(sb);
sb.delete(0, sb.length());
TextArea c = new TextArea(sbt);
c.setEditable(false);
c.getStyle().setFont(smallFont);
table.addCell(c, false, null);
}
} else if (qName.equalsIgnoreCase("tr")) {
debugPrint("Row closed.");
table.commitRow();
} else if (qName.equalsIgnoreCase("table")) {
HTMLTable t = new HTMLTable(table);
//without scrollable Y not all table rows are shown
t.setScrollableY(true);
//t.setPreferredW(screenWidth);
//this is verboten.
t.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
mainContainer.addComponent(t);
tableBool = false;
You can't change the layout of the table from table layout otherwise it will not be a table.
It should be possible to get the table to fill the width of a parent BoxLayout_Y by assigning width percentages to table columns up to 100% e.g. for a 3 column table return assign 33, 33 & 44.
This can be achieved by subclassing table and overriding the method:
protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {
TableLayout.Constraint c = super.createCellConstraint(value, row, column);
c.setWidthPercentage(whateverYouWant);
return c;
}

Resources