Search code examples
javaexceldocx4j

How to add rows to an existing table using Docx4J


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.


Solution

  • 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