How to add rows to an existing table using Docx4J - java

I have an existing Workbook with a Sheet that has a table ('table' refers to the Insert Table feature of the Excel UI with column headers and filter arrows, etc). I am having trouble determining which classes to use to edit existing rows of the table or inserting new rows into the table.
I have been successful (thanks in no small part to JasonPlutext) with writing new cell contents to existing cells as well as creating entirely new cells/rows. I'd rather not have to write the header row and all the data rows first and them make it into a table using the API, but I would like to know if anybody know how it should be done. In the past, I could just create the table with the number of rows I knew I would need but in this case the rows quantity is dynamic. I was hoping I could just reference a tablePart and then there would be some method for inserting into a List object.
Any guidance is appreciated.
EDIT:
So as a concrete example, let's say I have a workbook and sheet with an existing table of 2 columns with 2 rows (including the header) starting at A1. I can open the underlying xl>tables>table1.xml and see this:
<table xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="xr xr3" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision" xmlns:xr3="http://schemas.microsoft.com/office/spreadsheetml/2016/revision3" id="5" xr:uid="{FAABA541-34FC-423B-94F5-DDD8D784132E}" name="SummarySFTP" displayName="SummarySFTP" ref="A1:B2" totalsRowShown="0" headerRowDxfId="46" headerRowBorderDxfId="45" tableBorderDxfId="44">
<autoFilter ref="A1:B2" xr:uid="{93499C15-75FB-4436-A9B9-0C1FCBD787F4}">
<filterColumn colId="0" hiddenButton="0"/>
<filterColumn colId="1" hiddenButton="0"/>
</autoFilter>
<tableColumns count="2">
<tableColumn id="1" xr3:uid="{D4DA50CD-C581-4286-9B64-42B02B6646B6}" name="Status"/>
<tableColumn id="2" xr3:uid="{9D4F40B3-B530-42E1-92E9-86D5632CA191}" name="Quantity" dataDxfId="43"/>
</tableColumns>
<tableStyleInfo showFirstColumn="0" showLastColumn="0" showRowStripes="1" showColumnStripes="0"/>
</table>
I can see my two columns, and the ref attribute of the root tag as well as the autoFilter block's ref attribute. What I want to do is add a new row such that the area of the table would be A1:B3.

Inspecting an xlsx file containing a table in the docx4j webapp, it looks fairly straightforward.
It generates code for the contents of the table part like:
CTTable table = smlObjectFactory.createCTTable();
JAXBElement<org.xlsx4j.sml.CTTable> tableWrapped = smlObjectFactory.createTable(table);
// Create object for autoFilter
CTAutoFilter autofilter = smlObjectFactory.createCTAutoFilter();
table.setAutoFilter(autofilter);
autofilter.setRef( "A2:B4");
// Create object for tableColumns
CTTableColumns tablecolumns = smlObjectFactory.createCTTableColumns();
table.setTableColumns(tablecolumns);
tablecolumns.setCount( new Long(2) );
// Create object for tableColumn
CTTableColumn tablecolumn = smlObjectFactory.createCTTableColumn();
tablecolumns.getTableColumn().add( tablecolumn);
tablecolumn.setTotalsRowFunction(org.xlsx4j.sml.STTotalsRowFunction.NONE);
tablecolumn.setName( "Column1");
tablecolumn.setId( 1 );
// Create object for tableColumn
CTTableColumn tablecolumn2 = smlObjectFactory.createCTTableColumn();
tablecolumns.getTableColumn().add( tablecolumn2);
tablecolumn2.setTotalsRowFunction(org.xlsx4j.sml.STTotalsRowFunction.NONE);
tablecolumn2.setName( "Column2");
tablecolumn2.setId( 2 );
// Create object for tableStyleInfo
CTTableStyleInfo tablestyleinfo = smlObjectFactory.createCTTableStyleInfo();
table.setTableStyleInfo(tablestyleinfo);
tablestyleinfo.setName( "TableStyleMedium2");
table.setTableType(org.xlsx4j.sml.STTableType.WORKSHEET);
table.setHeaderRowCount( new Long(1) );
table.setTotalsRowCount( new Long(0) );
table.setName( "Table1");
table.setId( 1 );
table.setRef( "A2:B4");
table.setDisplayName( "Table1");
Once you know the row quantity, you can see you need to write it in 2 places, using setRef and autofilter.setRef

Related

How can i create a single database table in java data from 4 excel sheets?

In my project I have uploaded the excel sheets and I retrieve by using java, after receiving excel files i just want to create a database table.
These excel sheets contains mark list (each excel sheet contain single subject mark list) like student name, internal,external,result.
if it is one excel sheet then i can easily create a table in db. But i have to create a table from 4 sheets.
i just tried to list the each excel files using for loop and get the data from one by one but its not my solution.
STUDENT NAME CIA ESE TOTAL
AJAY G 46 31 77
AJITH V 41 27 68
AJITH KUMAR 40 26 66
And My Java code is here :
String dirs[] = file.list();
for(String i:dirs) {
// here i can get the file one by one
fis = new FileInputStream(fullpath+"/"+i);
wb = WorkbookFactory.create(fis);
System.out.println(wb.getNumberOfSheets());
sh = wb.getSheet("Sheet1");
int noOfRows = sh.getLastRowNum();
int noOfCols = sh.getRow(7).getLastCellNum();
System.out.println("Rows : "+ noOfRows);
System.out.println("Cols : "+ noOfCols);
}
The above is my excel sheet data and all sheets like the same with different subject (Subject name is the file name so i can take it).
What I expect is to create a single table in db like :
Table name : StudentResult
Stuname | Subject1 | Sub1CIA | Sub1ESE | Subject2 | Sub2CIA | Sub2ESE ...
and so on (get remaining excel sheet column like this.)
Assuming each of the sheets contain the column heading, collect the column headings from all the sheets and make a unique set of them. Then you can use this set to create the database table dynamically executing a DDL using JDBC.
If you want to create the table after the for loop, then declare a Set variable above for- loop and keep adding the column headings from each Sheet to it. Once the control is out of for loop you will have the set with column headings. Here is the pseudo code for this
// Declare a set here
Set<String> dbColumns = new HashSet<String>();
String dirs[] = file.list();
for(String i:dirs) {
// For each sheet
// Get the heading row ( may be col 1 depending on the work sheet)
// Get the cells from this row
// Add the values to the dbColumns set
}
// Now dbColumns contains the list for columns to be created
// Iterate through this set and form the DDL Statement
// Execute the DDL using jdbc

Java Apache Poi Write Excel

I working in an application in Java to write to an excel. I am using apache poi libraries. I have a requirement to create pivot table. I am able to create pivot table and sum the columns using below code.
CellReference topLeft = new CellReference(0, 0);
CellReference bottomRight = new CellReference(10, 3);
AreaReference aref = new AreaReference(topLeft, bottomRight);
CellReference pos = new CellReference(0, 0);
XSSFSheet pivotSheet = workbook.createSheet("PivotSheet");
XSSFPivotTable pivotTable = pivotSheet.createPivotTable(aref,pos,dataSheet)
pivotOrgWiseSheet.setDisplayGridlines(true);
pivotTable.addRowLabel(0);
pivotTable.addRowLabel(1);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 2, "Sum of column3");
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 3, "Sum of column4");
But the above code generate excel like
But I am not sure why the keyword "values" comes in 2nd column header and also is it possible to change the value "Row Label" to custom text like "Category"
I want it something like below.
I am not sure how to remove the keyword "Values", but I guess to change the header to custom string, we have to get the value and set it out ?
In Excel there is a setting Field Headers on the Analyze or Options tab, in the Show group. This switches between showing and hiding field headers.
See Change the layout of columns, rows, and subtotals.
The corresponding setting in org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableDefinition is setShowHeaders.
So
...
pivotTable.getCTPivotTableDefinition().setShowHeaders(false);
...
should hiding field headers in your pivot table.
But your picture of the wanted result looks more as if the data headers are visible but the RowHeaderCaption was changed and first row containing the DataCaption is hidden. That would be:
...
//pivotTable.getCTPivotTableDefinition().setShowHeaders(false);
pivotTable.getCTPivotTableDefinition().setRowHeaderCaption("Category");
pivotTable.getCTPivotTableDefinition().setDataCaption("Changed Data Caption");
CellUtil.getRow(pos.getRow(), pivotSheet).setZeroHeight(true);
...

Insert new row into LibreOffice writer table using UNO

I have recently tried to code a small java file which will insert a row into an already existing table in a .odt document. The table itself has 4 rows and 3 column, but I would like to implement a check which will expand that table if the content to be inserted is larger than 4. However, every time I try to get the table's rows, it returns a null pointer. I am not that familiar with UNO api, but as far as i read through the documentation, the class XColumnsAndRowRange should be used in this situation. My code is as follows:
XTextTablesSupplier xTablesSupplier = (XTextTablesSupplier) UnoRuntime.queryInterface(XTextTablesSupplier.class, xTextDocument);
XNameAccess xNamedTables = xTablesSupplier.getTextTables();
try {
Object table = xNamedTables.getByName(tblName);
XTextTable xTable = (XTextTable) UnoRuntime.queryInterface(XTextTable.class, table);
XCellRange xCellRange = (XCellRange) UnoRuntime.queryInterface(XCellRange.class, table);
if(flag){
XColumnRowRange xCollumnAndRowRange =(XColumnRowRange)
UnoRuntime.queryInterface(XColumnRowRange.class, xCellRange);
XTableRows rows = xCollumnAndRowRange.getRows();
System.out.println("Testing if this works");
rows.insertByIndex(4, size-4);
}
I am not sure if I am missing something here or if I should be using a different function.
As Lyrl suggested, this works:
XTableRows rows = xTable.getRows();
Apparently XColumnRowRange is only used for spreadsheets.
Note: With Basic or Python you would not have this problem, because those languages do not need queryInterface. The code would simply be:
table = tables.getByName(tblName)
rows = table.getRows()

table not getting created in docx using docx4j library

I'm trying to create a table and add it to MainDocumentPart using docx4j library as below but its corrupting the document and it's not opening ( im using MS Word 2010 with docx format )
// creating docx
WordprocessingMLPackage wordPackage = WordprocessingMLPackage.createPackage();
// creating a table
// use ObjectFactory for creating the table, table row and table cell
ObjectFactory factory = Context.getWmlObjectFactory();
// create the table
Tbl table = factory.createTbl();
// create a row
R row = factory.createR();
// create a cell
Tc cell = factory.createTc();
// add the content to cell
cell.getContent().add(wordPackage.getMainDocumentPart().createParagraphOfText("table cell data added"));
// add the cell to row
row.getContent().add(cell);
// add the row to table
table.getContent().add(row);
// adding the table to main document part
wordPackage.getMainDocumentPart().addObject(table);
wordPackage.save(new File("D:\\Programs\\test\\Doc222.docx"));
R is not a row; it is a run.
To generate your table, the easiest way is to create a suitable docx in Microsoft Word (or LibreOffice/OpenOffice or whatever), and upload it to the docx4j demo webapp.

JMesa: pre-sorting a table

I am creating a multiple column JMesa table. I want to pre-sort the table on a specified column. How can I achieve this?
You have to call addSort() on SortSet, then associate the SortSet with the TableModel. Sample code:
SortSet mySortSet = new SortSet() {};
mySortSet.addSort("your column property here", Order.ASC);
Limit limit = TableModelUtils.getLimit("table model id here", request, itemsList);
limit.setSortSet(mySortSet);
model.setLimit(limit);

Categories