View | Details | Raw Unified | Return to bug 56274
Collapse All | Expand All

(-)../../repository/SupportingLibraries/poi-3.10-wc/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFTable.java (-243 / +211 lines)
Lines 17-29 Link Here
17
17
18
package org.apache.poi.xssf.usermodel;
18
package org.apache.poi.xssf.usermodel;
19
19
20
import java.io.IOException;
21
import java.io.InputStream;
22
import java.io.OutputStream;
23
import java.util.Arrays;
24
import java.util.List;
25
import java.util.Vector;
26
27
import org.apache.poi.POIXMLDocumentPart;
20
import org.apache.poi.POIXMLDocumentPart;
28
import org.apache.poi.openxml4j.opc.PackagePart;
21
import org.apache.poi.openxml4j.opc.PackagePart;
29
import org.apache.poi.openxml4j.opc.PackageRelationship;
22
import org.apache.poi.openxml4j.opc.PackageRelationship;
Lines 34-306 Link Here
34
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
27
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
35
import org.openxmlformats.schemas.spreadsheetml.x2006.main.TableDocument;
28
import org.openxmlformats.schemas.spreadsheetml.x2006.main.TableDocument;
36
29
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.io.OutputStream;
33
import java.util.ArrayList;
34
import java.util.Arrays;
35
import java.util.List;
36
37
/**
37
/**
38
 * 
38
 * This class implements the Table Part (Open Office XML Part 4: chapter 3.5.1)
39
 * This class implements the Table Part (Open Office XML Part 4:
39
 * <p/>
40
 * chapter 3.5.1)
41
 * 
42
 * This implementation works under the assumption that a table contains mappings to a subtree of an XML.
40
 * This implementation works under the assumption that a table contains mappings to a subtree of an XML.
43
 * The root element of this subtree an occur multiple times (one for each row of the table). The child nodes
41
 * The root element of this subtree an occur multiple times (one for each row of the table). The child nodes
44
 * of the root element can be only attributes or element with maxOccurs=1 property set
42
 * of the root element can be only attributes or element with maxOccurs=1 property set
45
 * 
43
 *
46
 *
47
 * @author Roberto Manicardi
44
 * @author Roberto Manicardi
48
 */
45
 */
49
public class XSSFTable extends POIXMLDocumentPart {
46
public class XSSFTable extends POIXMLDocumentPart {
50
47
51
	private CTTable ctTable;
48
    private CTTable ctTable;
52
	private List<XSSFXmlColumnPr> xmlColumnPr;
49
    private List<XSSFXmlColumnPr> xmlColumnPr;
53
	private CellReference startCellReference;
50
    private CellReference startCellReference;
54
	private CellReference endCellReference;	
51
    private CellReference endCellReference;
55
	private String commonXPath; 
52
    private String commonXPath;
56
	
53
57
	
54
    public XSSFTable() {
58
	public XSSFTable() {
59
		super();
55
        ctTable = CTTable.Factory.newInstance();
60
		ctTable = CTTable.Factory.newInstance();
61
56
    }
62
	}
63
57
64
	public XSSFTable(PackagePart part, PackageRelationship rel)
58
    public XSSFTable(PackagePart part, PackageRelationship rel) throws IOException {
65
			throws IOException {
66
		super(part, rel);
59
        super(part, rel);
67
		readFrom(part.getInputStream());
60
        readFrom(part.getInputStream());
68
	}
61
    }
69
62
70
	public void readFrom(InputStream is) throws IOException {
63
    public void readFrom(InputStream is) throws IOException {
71
		try {
64
        try {
72
			TableDocument doc = TableDocument.Factory.parse(is);
65
            TableDocument doc = TableDocument.Factory.parse(is);
73
			ctTable = doc.getTable();
66
            ctTable = doc.getTable();
74
		} catch (XmlException e) {
67
        } catch (XmlException e) {
75
			throw new IOException(e.getLocalizedMessage());
68
            throw new IOException(e.getLocalizedMessage());
76
		}
69
        }
77
	}
70
    }
78
	
71
79
	public XSSFSheet getXSSFSheet(){
72
    public XSSFSheet getXSSFSheet() {
80
		return (XSSFSheet) getParent();
73
        return (XSSFSheet) getParent();
81
	}
74
    }
82
75
83
	public void writeTo(OutputStream out) throws IOException {
76
    public void writeTo(OutputStream out) throws IOException {
84
        updateHeaders();
77
        updateHeaders();
85
78
86
        TableDocument doc = TableDocument.Factory.newInstance();
79
        TableDocument doc = TableDocument.Factory.newInstance();
87
		doc.setTable(ctTable);
80
        doc.setTable(ctTable);
88
		doc.save(out, DEFAULT_XML_OPTIONS);
81
        doc.save(out, DEFAULT_XML_OPTIONS);
89
	}
82
    }
90
83
91
	@Override
84
    @Override
92
	protected void commit() throws IOException {
85
    protected void commit() throws IOException {
93
		PackagePart part = getPackagePart();
86
        PackagePart part = getPackagePart();
94
		OutputStream out = part.getOutputStream();
87
        OutputStream out = part.getOutputStream();
95
		writeTo(out);
88
        writeTo(out);
96
		out.close();
89
        out.close();
97
	}
90
    }
98
	
91
99
	public CTTable getCTTable(){
92
    public CTTable getCTTable() {
100
		return ctTable;
93
        return ctTable;
101
	}
94
    }
102
	
95
103
	/**
96
    /**
104
	 * Checks if this Table element contains even a single mapping to the map identified by id
97
     * Checks if this Table element contains even a single mapping to the map identified by id
98
     *
105
	 * @param id the XSSFMap ID
99
     * @param id the XSSFMap ID
106
	 * @return true if the Table element contain mappings
100
     * @return true if the Table element contain mappings
107
	 */
101
     */
108
	public boolean mapsTo(long id){
102
    public boolean mapsTo(long id) {
109
		boolean maps =false;
103
        for (XSSFXmlColumnPr pointer : getXmlColumnPrs()) {
110
		
111
		List<XSSFXmlColumnPr> pointers = getXmlColumnPrs();
112
		
113
		for(XSSFXmlColumnPr pointer: pointers){
114
			if(pointer.getMapId()==id){
104
            if (pointer.getMapId() == id) {
115
				maps=true;
105
                return true;
116
				break;
117
			}
106
            }
118
		}
107
        }
119
		
108
120
		return maps;
109
        return false;
121
	}
110
    }
122
111
123
	
112
    /**
124
	/**
125
	 * 
113
     * Calculates the xpath of the root element for the table. This will be the common part
126
	 * Calculates the xpath of the root element for the table. This will be the common part
114
     * of all the mapping's xpaths
127
	 * of all the mapping's xpaths
115
     *
128
	 * 
116
     * @return the xpath of the table's root element
129
	 * @return the xpath of the table's root element
117
     */
130
	 */
118
    public String getCommonXpath() {
131
	public String getCommonXpath() {
132
		
119
        if (commonXPath == null) {
133
		if(commonXPath == null){
134
		
120
            String[] commonTokens = {};
135
		String[] commonTokens ={};
136
		
121
137
		for(CTTableColumn column :ctTable.getTableColumns().getTableColumnList()){
122
            for (CTTableColumn column : ctTable.getTableColumns().getTableColumnList()) {
138
			if(column.getXmlColumnPr()!=null){
123
                if (column.getXmlColumnPr() != null) {
139
				String xpath = column.getXmlColumnPr().getXpath();
124
                    String xpath = column.getXmlColumnPr().getXpath();
140
				String[] tokens =  xpath.split("/");
125
                    String[] tokens = xpath.split("/");
141
				if(commonTokens.length==0){
126
                    if (commonTokens.length == 0) {
142
					commonTokens = tokens;
127
                        commonTokens = tokens;
143
					
128
                    } else {
144
				}else{
145
					int maxLenght = commonTokens.length>tokens.length? tokens.length:commonTokens.length;
129
                        int maxLength = commonTokens.length > tokens.length ? tokens.length : commonTokens.length;
146
					for(int i =0; i<maxLenght;i++){
130
                        for (int i = 0; i < maxLength; i++) {
147
						if(!commonTokens[i].equals(tokens[i])){
131
                            if (!commonTokens[i].equals(tokens[i])) {
148
						 List<String> subCommonTokens = Arrays.asList(commonTokens).subList(0, i);
132
                                List<String> subCommonTokens = Arrays.asList(commonTokens).subList(0, i);
149
						 
133
150
						 String[] container = {};
134
                                commonTokens = subCommonTokens.toArray(new String[subCommonTokens.size()]);
151
						 
152
						 commonTokens = subCommonTokens.toArray(container);
153
						 break;
135
                                break;
154
						 
136
                            }
155
						 
137
                        }
156
						}
138
                    }
157
					}
158
				}
159
				
139
                }
160
			}
140
            }
161
		}
141
162
		
163
		
142
            StringBuilder sb = new StringBuilder();
164
		commonXPath ="";
165
		
166
		for(int i = 1 ; i< commonTokens.length;i++){
143
            for (int i = 1; i < commonTokens.length; i++) {
167
			commonXPath +="/"+commonTokens[i];
144
                sb.append('/').append(commonTokens[i]);
168
		
169
		}
145
            }
146
            commonXPath = sb.toString();
170
		}
147
        }
171
		
148
172
		return commonXPath;
149
        return commonXPath;
173
	}
150
    }
174
151
175
	
152
    public List<XSSFXmlColumnPr> getXmlColumnPrs() {
176
	public List<XSSFXmlColumnPr> getXmlColumnPrs() {
177
		
153
        if (xmlColumnPr == null) {
178
		if(xmlColumnPr==null){
179
			xmlColumnPr = new Vector<XSSFXmlColumnPr>();
154
            xmlColumnPr = new ArrayList<XSSFXmlColumnPr>();
180
			for(CTTableColumn column:ctTable.getTableColumns().getTableColumnList()){
155
            for (CTTableColumn column : ctTable.getTableColumns().getTableColumnList()) {
181
				if(column.getXmlColumnPr()!=null){
156
                if (column.getXmlColumnPr() != null) {
182
					XSSFXmlColumnPr columnPr = new XSSFXmlColumnPr(this,column,column.getXmlColumnPr());
157
                    XSSFXmlColumnPr columnPr = new XSSFXmlColumnPr(this, column, column.getXmlColumnPr());
183
					xmlColumnPr.add(columnPr);
158
                    xmlColumnPr.add(columnPr);
184
				}
159
                }
185
			}
160
            }
186
		}
161
        }
187
		return xmlColumnPr;
162
        return xmlColumnPr;
188
	}
163
    }
189
	
164
190
	/**
165
    /**
191
	 * @return the name of the Table, if set
166
     * @return the name of the Table, if set
192
	 */
167
     */
193
	public String getName() {
168
    public String getName() {
194
	   return ctTable.getName();
169
        return ctTable.getName();
195
	}
170
    }
196
	
171
197
	/**
172
    /**
198
	 * Changes the name of the Table
173
     * Changes the name of the Table
199
	 */
174
     */
200
	public void setName(String name) {
175
    public void setName(String name) {
201
	   if(name == null) {
176
        if (name == null) {
202
	      ctTable.unsetName();
177
            ctTable.unsetName();
203
	      return;
178
            return;
204
	   }
179
        }
205
	   ctTable.setName(name);
180
        ctTable.setName(name);
206
	}
181
    }
207
182
208
   /**
183
    /**
209
    * @return the display name of the Table, if set
184
     * @return the display name of the Table, if set
210
    */
185
     */
211
   public String getDisplayName() {
186
    public String getDisplayName() {
212
      return ctTable.getDisplayName();
187
        return ctTable.getDisplayName();
213
   }
188
    }
214
189
215
   /**
190
    /**
216
    * Changes the display name of the Table
191
     * Changes the display name of the Table
217
    */
192
     */
218
   public void setDisplayName(String name) {
193
    public void setDisplayName(String name) {
219
      ctTable.setDisplayName(name);
194
        ctTable.setDisplayName(name);
220
   }
195
    }
221
196
222
	/**
197
    /**
223
	 * @return  the number of mapped table columns (see Open Office XML Part 4: chapter 3.5.1.4)
198
     * @return the number of mapped table columns (see Open Office XML Part 4: chapter 3.5.1.4)
224
	 */
199
     */
225
	public long getNumerOfMappedColumns(){
200
    public long getNumerOfMappedColumns() {
226
		return ctTable.getTableColumns().getCount();
201
        return ctTable.getTableColumns().getCount();
227
	}
202
    }
228
	
203
229
	
204
    /**
230
	/**
205
     * @return The reference for the cell in the top-left part of the table
231
	 * @return The reference for the cell in the top-left part of the table
206
     * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
232
	 * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref) 
233
	 *
207
     */
234
	 */
208
    public CellReference getStartCellReference() {
235
	public CellReference getStartCellReference() {
236
		
209
        if (startCellReference == null) {
237
		if(startCellReference==null){			
238
				String ref = ctTable.getRef();
210
            initCellReferences();
239
                if(ref != null) {
240
                    String[] boundaries = ref.split(":");
241
                    String from = boundaries[0];
242
                    startCellReference = new CellReference(from);
243
                }
211
        }
244
		}
212
        return startCellReference;
245
		return startCellReference;
213
    }
246
	}
214
247
	
215
    /**
248
	/**
216
     * @return The reference for the cell in the bottom-right part of the table
249
	 * @return The reference for the cell in the bottom-right part of the table
217
     * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
250
	 * (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
251
	 *
218
     */
252
	 */
219
    public CellReference getEndCellReference() {
253
	public CellReference getEndCellReference() {
254
		
220
        if (endCellReference == null) {
255
		if(endCellReference==null){
221
            initCellReferences();
222
        }
223
        return endCellReference;
224
    }
256
			
225
226
    private void initCellReferences() {
257
				String ref = ctTable.getRef();
227
        String ref = ctTable.getRef();
258
				String[] boundaries = ref.split(":");
228
        if (ref != null) {
259
				String from = boundaries[1];
229
            int indexOfColon = ref.indexOf(':');
260
				endCellReference = new CellReference(from);
230
            startCellReference = new CellReference(ref.substring(0, indexOfColon));
231
            endCellReference = new CellReference(ref.substring(indexOfColon + 1));
261
		}
232
        }
262
		return endCellReference;
233
    }
263
	}
234
264
	
265
	
235
    /**
266
	/**
267
	 *  @return the total number of rows in the selection. (Note: in this version autofiltering is ignored)
236
     * @return the total number of rows in the selection. (Note: in this version autofiltering is ignored)
268
	 *
237
     */
269
	 */
270
	public int getRowCount(){
238
    public int getRowCount() {
271
		
239
        CellReference from = getStartCellReference();
272
		
240
        CellReference to = getEndCellReference();
273
		CellReference from = getStartCellReference();
241
274
		CellReference to = getEndCellReference();
242
        int rowCount = -1;
275
		
276
		int rowCount = -1;
277
		if (from!=null && to!=null){
243
        if (from != null && to != null) {
278
		 rowCount = to.getRow()-from.getRow();
244
            rowCount = to.getRow() - from.getRow();
279
		}
245
        }
280
		return rowCount;
246
        return rowCount;
281
	}
247
    }
282
248
283
    /**
249
    /**
284
     * Synchronize table headers with cell values in the parent sheet.
250
     * Synchronize table headers with cell values in the parent sheet.
285
     * Headers <em>must</em> be in sync, otherwise Excel will display a
251
     * Headers <em>must</em> be in sync, otherwise Excel will display a
286
     * "Found unreadable content" message on startup.
252
     * "Found unreadable content" message on startup.
287
     */
253
     */
288
    public void updateHeaders(){
254
    public void updateHeaders() {
289
        XSSFSheet sheet = (XSSFSheet)getParent();
255
        XSSFSheet sheet = (XSSFSheet) getParent();
290
        CellReference ref = getStartCellReference();
256
        CellReference ref = getStartCellReference();
291
        if(ref == null) return;
257
        if (ref == null) return;
292
258
293
        int headerRow = ref.getRow();
259
        int headerRow = ref.getRow();
294
        int firstHeaderColumn = ref.getCol();
260
        int firstHeaderColumn = ref.getCol();
295
        XSSFRow row = sheet.getRow(headerRow);
261
        XSSFRow row = sheet.getRow(headerRow);
296
262
297
        if(row != null) for(CTTableColumn col : getCTTable().getTableColumns().getTableColumnList()){
263
        if (row != null) {
298
            int colIdx = (int)col.getId() - 1 + firstHeaderColumn;
264
            int cellnum = firstHeaderColumn;
299
            XSSFCell cell = row.getCell(colIdx);
265
            for (CTTableColumn col : getCTTable().getTableColumns().getTableColumnList()) {
266
                XSSFCell cell = row.getCell(cellnum);
300
            if(cell != null) {
267
                if (cell != null) {
301
                col.setName(cell.getStringCellValue());
268
                    col.setName(cell.getStringCellValue());
302
            }
269
                }
270
                cellnum++;
303
        }
271
            }
304
272
        }
305
    }
273
    }
306
}
274
}

Return to bug 56274