I need to push a second table in my main table.
I use the main table to format correct the text: I'm creating a class in java for generate Curriculum, so I need a main table to create a good template
I try to push a
Tbl element in a Tc (cell element) of main table, but Word gives me error about a wrong template. It ask me if I want open anyway the document: It show correctly the nested table, but I don't want that the error is displayed.
ObjectFactory factory = Context.getWmlObjectFactory();
Tbl mainTable = TblFactory.createTable(2, 2, cellWidthTwips );
List<Object> rows = table.getContent();
Tr row = (Tr) rows.get(0);
List<Object> cells = row.getContent();
Tc cell = (Tc) cells.get(0);
Tbl nestedTable = TblFactory.createTable(1, 5, widthTips/columns );
cell.getContent().add(nestedTable);
I tried also
Tbl nestedTable2 = factory.createTbl();
Where I wrong?
Assuming MainDocumentPart mdp:
int widthTwips = 4788;
Tbl mainTable = TblFactory.createTable(2, 2, widthTwips);
List<Object> rows = mainTable.getContent();
Tr row = (Tr) rows.get(0);
List<Object> cells = row.getContent();
Tc cell = (Tc) cells.get(0);
Tbl nestedTable = TblFactory.createTable(1, 2, 2000);
// You'll get an error in Word if you don't have an empty <p/> after the nested table.
// Since TblFactory.createTable automatically added an empty <p>, add the table before it
cell.getContent().add(0, nestedTable);
mdp.getContent().add(mainTable);
See the explanatory comment in the code snippet.
Related
I'm creating an excel file with many tabs. Each tab has a table and, manually, is very easy to create a graph from it. The tables contain the cell range and headings needed for the graphs, which varies from one to another. I've been searching to do this programmatically and found nothing. Do I have to create it from scratch or is there a simpler way of creating a graph form a table?
Thanks for your help
Additional info:
I'm not saying that the graphs cannot be create using the tables but I was looking for a way where the information from the table could be used for the graph. Anyway, I've realised that the tables are the same throughout the sheets.
Code from the method that generates the tabs and adds the tables
...
XSSFSheet sheet = workbook.createSheet(kind);
addTable(sheet, years, count++);
XSSFRow row;
XSSFCell cell;
for (String var : yearMapSorted.keySet()) {
List<Double> weights = yearMap.get(var);
row = sheet.createRow(rowNum++);
cell = row.createCell(0);
cell.setCellType(CellType.NUMERIC);
cell.setCellValue(weights.get(FIRST_YEAR));
row.createCell(1).setCellValue(weights.get(SECOND_YEAR));
row.createCell(2).setCellValue(var);
}
// add formula to calculate the sum of the columns
addTotalColumns(sheet);
addCalculatedColumns(sheet);
...
Method that adds the table
private void addTable(XSSFSheet sheet, List<Integer> years, Long count) {
String tableName = "Table_" + count;
XSSFRow row = sheet.createRow(0);
row.createCell(2).setCellValue("Variety");
row.createCell(3).setCellValue(years.get(FIRST_YEAR).toString());
row.createCell(4).setCellValue(years.get(SECOND_YEAR).toString());
XSSFTable table = sheet.createTable();
CTTable cttable = table.getCTTable();
cttable.setDisplayName(tableName);
cttable.setId(count);
cttable.setName(tableName);
cttable.setRef("C1:E11");
cttable.setTotalsRowShown(false);
CTTableStyleInfo styleInfo = cttable.addNewTableStyleInfo();
styleInfo.setName("TableStyleMedium2");
styleInfo.setShowColumnStripes(false);
styleInfo.setShowRowStripes(true);
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(3);
for (int i = 1; i <= 3; i++) {
CTTableColumn column = columns.addNewTableColumn();
column.setId(i);
column.setName("Column"+i);
}
}
How do I split the rows of the inner table. Problem description according to the image.
Here, I have table named PARENT_TABLE that has cell that contains two tables named HEADER_TABLE and CONTENT_TABLE
CONTENT_TABLE has a cell that contains INNER_TABLE. INNER_TABLE contains the dynamic rows/content whose height will be changed according to content.
So, If I make this table using one page it's working perfectly. But incase if I need to split the table in different pages it shows the error like image_2. Please help me out. As a result: The table should look like in the image_1 even if the page split into two or more pages.
Please checkout mentioned image to be more clear.
image_1
Attempt to read from field 'float com.itextpdf.text.pdf.ColumnText.maxY' on a null object reference
image_2
I just found out the solution. The issue occurs only in the case when trying to split the PDFPTable into two pages. I had used tableCell.setRowspan(2), so when trying to split the table above issue occurs.
SOLVED IT: I just made an empty cell in place of using tableCell.setRowspan(2).
private PdfPTable contentWithDateTitleAndDescription(String stringData1, String stringData2, String stringData3, String stringData4) throws IOException, BadElementException {
float relativeWidth[] = {2, 7};
PdfPTable table = new PdfPTable(relativeWidth);
table.setWidthPercentage(100);
PdfPCell cellA = new PdfPCell();
cellA.setBorder(Rectangle.NO_BORDER);
// dateCell.setRowspan(2);
cellA.setPaddingLeft(15);
cellA.setVerticalAlignment(Element.ALIGN_CENTER);
cellA.setPaddingTop(7);
Paragraph dateParagraph = new Paragraph(stringData1);
cellA.addElement(dateParagraph);
PdfPCell emptyCellB = new PdfPCell();
emptyCellB.setBorder(Rectangle.NO_BORDER);
PdfPCell cellC = new PdfPCell();
cellC.setBorder(Rectangle.NO_BORDER);
cellC.setVerticalAlignment(Element.ALIGN_LEFT);
Paragraph titleParagraph = new Paragraph(stringData2 + " / " + stringData3);
cellC.addElement(titleParagraph);
PdfPCell cellD = new PdfPCell();
cellD.setBorder(Rectangle.NO_BORDER);
cellD.setVerticalAlignment(Element.ALIGN_LEFT);
Paragraph descriptionParagraph = new Paragraph(stringData4);
cellD.addElement(descriptionParagraph);
cellD.setPaddingBottom(15);
table.addCell(cellA);
table.addCell(cellC);
table.addCell(emptyCellB);
table.addCell(cellD);
return table;
}
The following is the format I want to generate:
From my limited experience of the API I know how to make a list
ListFormat listFormat = builder.getListFormat();
listFormat.setList(document.getLists().add(ListTemplate.NUMBER_DEFAULT));
builder.writeln("Component Specification")
listFormat.setListLevelNumber(1);
builder.writeln("Raw Material Specification")
Now how do I transition from the list to the table below?
writing a new line adds numbers, even in the cells of the table.
If I set the listformat to null then the indentation is lost. I want to maintain the indentation of the list but also add the table below that list value
Anyway to do that?
#Furqan,
You need to set Table LeftIndent property for your requirements. Please check following sample code snippet.
I am Tilal Ahmad, developer evangelist at Aspose.
Document doc= new Document();
DocumentBuilder builder= new DocumentBuilder(doc);
ListFormat listFormat = builder.getListFormat();
listFormat.setList(doc.getLists().add(ListTemplate.NUMBER_DEFAULT));
builder.writeln("Component Specification");
builder.getListFormat().listIndent();
builder.getListFormat().getListLevel().setNumberStyle(NumberStyle.ARABIC);
builder.getListFormat().getListLevel().setNumberFormat("\u0000.\u0001");
builder.writeln("Raw Material Specification");
builder.getListFormat().removeNumbers();
Table table = new Table(doc);
// Add the table to the document.
doc.getFirstSection().getBody().appendChild(table);
Row row1 = new Row(doc);
row1.getRowFormat().setAllowBreakAcrossPages(true);
table.appendChild(row1);
// Create a cell and add it to the row
Cell cell1 = new Cell(doc);
cell1.getCellFormat().getShading()
.setBackgroundPatternColor(Color.LIGHT_GRAY);
cell1.getCellFormat().setWidth(50);
// Add a paragraph to the cell as well as a new run with some text.
cell1.appendChild(new Paragraph(doc));
cell1.getFirstParagraph().appendChild(new Run(doc, "Col1"));
// Add the cell to the row.
row1.appendChild(cell1);
// We would then repeat the process for the other cells and rows in the
// table.
// We can also speed things up by cloning existing cells and rows.
row1.appendChild(cell1.deepClone(false));
row1.getLastCell().appendChild(new Paragraph(doc));
row1.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Col2"));
row1.appendChild(cell1.deepClone(false));
row1.getLastCell().appendChild(new Paragraph(doc));
row1.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Col3"));
Row row = new Row(doc);
row.getRowFormat().setAllowBreakAcrossPages(true);
table.appendChild(row);
// Create a cell and add it to the row
Cell cell = new Cell(doc);
cell.getCellFormat().setWidth(50);
// Add a paragraph to the cell as well as a new run with some text.
cell.appendChild(new Paragraph(doc));
cell.getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 1 Text"));
// Add the cell to the row.
row.appendChild(cell);
row.appendChild(cell.deepClone(false));
row.getLastCell().appendChild(new Paragraph(doc));
row.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 2 Text"));
row.appendChild(cell.deepClone(false));
row.getLastCell().appendChild(new Paragraph(doc));
row.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 3 Text"));
// Add left indent to the table.
table.setLeftIndent(60);
doc.save("E:/Data/Test1.docx");
I am working with apose words java recently.
In my first page I have a table need to merge, which can grow any size, no fixed number of rows and at the end of my first page, I want to keep some content (for example contact details) to be fixed. (Note: I can't keep contact details in Footer or in foot note section because of some formatting I need to ensure which can't maintain in footer or foot note section)
On growing of table as many rows, My content is going down, But I want to fix it at the end of my first page. if table grows bigger in size, wanted to skip the content and render table in next page.
is there any solution/work around for this?
My expected results are like below....
Page 1 Start
dynamic Table row1
dynamic Table row2
dynamic Table row3
Contact Details ,wanted to fix at the end of my first page
Page 1 end
Page 2 Start
dynamic table row 4
dynamic table row 5
........
For your scenario, ideally the contact details should be set in a footer. It is possible, but very risky.
First create a new document, either in Aspose.Words or MS Word, it will be used as a template.
Add a blank table on top
Add contact details, after the blank table
Add a bookmark, after the contact details
Now, using Aspose.Words, you can check the location of the bookmark, every time you are adding a new row in the table. If bookmark is at page 1, add new row to the first table. If bookmark is at page 2, add new row to the second table. Below is the sample code that adds rows to the table, keeping the contact details fixed on page 1.
Template document: Google drive link
Java source code is given below.
public static void main(String[] args)
{
try
{
String template = Common.DATA_DIR + "Contact Template.docx";
String saveDocument = Common.DATA_DIR + "Contact with tables.docx";
String bookmarkNameContact = "ContactEnd";
// Load the template
com.aspose.words.Document wordDoc = new com.aspose.words.Document(template);
DocumentBuilder builder = new DocumentBuilder(wordDoc);
// Find the contacts bookmark
com.aspose.words.Bookmark bookmarkContact = wordDoc.getRange().getBookmarks().get(bookmarkNameContact);
// Set the table with null
com.aspose.words.Table table = null;
// Add some rows
for (int i = 0; i < 50; i++)
{
// If contacts bookmark is on 1st page, add new rows to first table
if (getBookmarkPage(wordDoc, bookmarkContact) == 1)
{
table = (com.aspose.words.Table) wordDoc.getChild(NodeType.TABLE, 0, true);
} else
{
// If the contacts bookmark is on second page, add rows to second table
table = (com.aspose.words.Table) wordDoc.getChild(NodeType.TABLE, 1, true);
// If there is no second table, create it
if (table == null)
{
table = createNewTable(wordDoc, bookmarkContact);
}
}
// Add rows dynamically to either first or second table
addRow(wordDoc, table, "some text " + i);
}
// Save the document
wordDoc.save(saveDocument);
} catch (Exception ex)
{
System.err.println(ex.getMessage());
}
}
private static com.aspose.words.Table createNewTable(com.aspose.words.Document wordDoc, com.aspose.words.Bookmark bookmarkContact) throws Exception
{
// Get the first table and clone it to create the second one
com.aspose.words.Table firstTable = (com.aspose.words.Table) wordDoc.getChild(NodeType.TABLE, 0, true);
com.aspose.words.Table table = (com.aspose.words.Table) firstTable.deepClone(true);
// Add the second table after the bookmark
bookmarkContact.getBookmarkEnd().getParentNode().getParentNode().appendChild(table);
// Delete all its rows
table.getRows().clear();
return table;
}
// Add a new row to the table
private static void addRow(com.aspose.words.Document wordDoc, com.aspose.words.Table table, String text)
{
// Create a new row
com.aspose.words.Row row = new com.aspose.words.Row(wordDoc);
row.getRowFormat().setAllowBreakAcrossPages(true);
// Add it to the table
table.appendChild(row);
// Add cells to the row
for (int iCell = 0; iCell < 4; iCell++)
{
// Create a new cell and set text inside it
com.aspose.words.Cell cell = new com.aspose.words.Cell(wordDoc);
cell.appendChild(new com.aspose.words.Paragraph(wordDoc));
cell.getFirstParagraph().appendChild(new Run(wordDoc, text));
cell.getFirstParagraph().getParagraphFormat().setSpaceAfter(0);
row.appendChild(cell);
}
}
private static int getBookmarkPage(com.aspose.words.Document wordDoc, com.aspose.words.Bookmark bookmarkContact) throws Exception
{
// Find the page number, where our contacts bookmark is
LayoutCollector collector = new LayoutCollector(wordDoc);
return collector.getStartPageIndex(bookmarkContact.getBookmarkEnd());
}
I work with Aspose as Developer Evangelist.
I'm generating Excel tables with Apache POI, but my generated tables lack the drop-down menu on each header that appear when I "format as table" in Excel itself.
I'd like to generate this:
But instead I get this:
I'm following this blog post, and my code looks like this:
XSSFTable table = sheet.createTable();
table.setDisplayName("Data");
CTTable ctTable = table.getCTTable();
ctTable.setDisplayName("Data");
ctTable.setId(1L);
ctTable.setName("DATA");
CTTableStyleInfo table_style = ctTable.addNewTableStyleInfo();
table_style.setName("TableStyleMedium9");
table_style.setShowColumnStripes(false);
table_style.setShowRowStripes(true);
Each column is then created like this:
CTTableColumn column = ctColumns.addNewTableColumn();
column.setName(headers.get(i));
column.setId(i + 1);
What am I missing?
Thanks to Alan Hay for the clue - the solution is to add an auto-filter, but this needs to be added as a CTAutoFilter for each individual column of the CTTable. The working solution looks like this:
CTTableColumns ctColumns = ctTable.addNewTableColumns();
CTAutoFilter autofilter = ctTable.addNewAutoFilter();
ctColumns.setCount(table_headers.size());
for(int i = 0; i < table_headers.size(); i++) {
CTTableColumn column = ctColumns.addNewTableColumn();
column.setName(table_headers.get(i));
column.setId(i + 1);
CTFilterColumn filter = autofilter.addNewFilterColumn();
filter.setColId(i + 1);
filter.setShowButton(true);
}
When auto-sizing columns, it's also necessary to add extra width for the drop down menu:
for(int i = 0; i < table_headers.size(); i++) {
sheet.autoSizeColumn(i);
// Include width of drop down button
sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 1000);
}
It is not exactly clear from the example you quoted whether applying the Table styling should create the filter dropdowns for you or not.
However you can explicitly call setAutoFilter() as below to have the filter dropdowns set.
e.g.
CellReference start = table.getStartCellReference();
CellReference end= table.getEndCellReference();
sheet.setAutoFilter(new CellRangeAddress(...);