package org.apache.poi.xssf.usermodel; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import org.apache.poi.ss.usermodel.TableStyle; import org.apache.poi.util.DocumentHelper; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.model.StylesTable; import org.apache.xmlbeans.XmlOptions; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxfs; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyle; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; /** * Table style names defined in the OOXML spec. * The actual styling is defined in presetTableStyles.xml */ public enum XSSFBuiltinTableStyle { /***/ TableStyleDark1, /***/ TableStyleDark2, /***/ TableStyleDark3, /***/ TableStyleDark4, /***/ TableStyleDark5, /***/ TableStyleDark6, /***/ TableStyleDark7, /***/ TableStyleDark8, /***/ TableStyleDark9, /***/ TableStyleDark10, /***/ TableStyleDark11, /***/ TableStyleLight1, /***/ TableStyleLight2, /***/ TableStyleLight3, /***/ TableStyleLight4, /***/ TableStyleLight5, /***/ TableStyleLight6, /***/ TableStyleLight7, /***/ TableStyleLight8, /***/ TableStyleLight9, /***/ TableStyleLight10, /***/ TableStyleLight11, /***/ TableStyleLight12, /***/ TableStyleLight13, /***/ TableStyleLight14, /***/ TableStyleLight15, /***/ TableStyleLight16, /***/ TableStyleLight17, /***/ TableStyleLight18, /***/ TableStyleLight19, /***/ TableStyleLight20, /***/ TableStyleLight21, /***/ TableStyleMedium1, /***/ TableStyleMedium2, /***/ TableStyleMedium3, /***/ TableStyleMedium4, /***/ TableStyleMedium5, /***/ TableStyleMedium6, /***/ TableStyleMedium7, /***/ TableStyleMedium8, /***/ TableStyleMedium9, /***/ TableStyleMedium10, /***/ TableStyleMedium11, /***/ TableStyleMedium12, /***/ TableStyleMedium13, /***/ TableStyleMedium14, /***/ TableStyleMedium15, /***/ TableStyleMedium16, /***/ TableStyleMedium17, /***/ TableStyleMedium18, /***/ TableStyleMedium19, /***/ TableStyleMedium20, /***/ TableStyleMedium21, /***/ TableStyleMedium22, /***/ TableStyleMedium23, /***/ TableStyleMedium24, /***/ TableStyleMedium25, /***/ TableStyleMedium26, /***/ TableStyleMedium27, /***/ TableStyleMedium28, /***/ PivotStyleMedium1, /***/ PivotStyleMedium2, /***/ PivotStyleMedium3, /***/ PivotStyleMedium4, /***/ PivotStyleMedium5, /***/ PivotStyleMedium6, /***/ PivotStyleMedium7, /***/ PivotStyleMedium8, /***/ PivotStyleMedium9, /***/ PivotStyleMedium10, /***/ PivotStyleMedium11, /***/ PivotStyleMedium12, /***/ PivotStyleMedium13, /***/ PivotStyleMedium14, /***/ PivotStyleMedium15, /***/ PivotStyleMedium16, /***/ PivotStyleMedium17, /***/ PivotStyleMedium18, /***/ PivotStyleMedium19, /***/ PivotStyleMedium20, /***/ PivotStyleMedium21, /***/ PivotStyleMedium22, /***/ PivotStyleMedium23, /***/ PivotStyleMedium24, /***/ PivotStyleMedium25, /***/ PivotStyleMedium26, /***/ PivotStyleMedium27, /***/ PivotStyleMedium28, /***/ PivotStyleLight1, /***/ PivotStyleLight2, /***/ PivotStyleLight3, /***/ PivotStyleLight4, /***/ PivotStyleLight5, /***/ PivotStyleLight6, /***/ PivotStyleLight7, /***/ PivotStyleLight8, /***/ PivotStyleLight9, /***/ PivotStyleLight10, /***/ PivotStyleLight11, /***/ PivotStyleLight12, /***/ PivotStyleLight13, /***/ PivotStyleLight14, /***/ PivotStyleLight15, /***/ PivotStyleLight16, /***/ PivotStyleLight17, /***/ PivotStyleLight18, /***/ PivotStyleLight19, /***/ PivotStyleLight20, /***/ PivotStyleLight21, /***/ PivotStyleLight22, /***/ PivotStyleLight23, /***/ PivotStyleLight24, /***/ PivotStyleLight25, /***/ PivotStyleLight26, /***/ PivotStyleLight27, /***/ PivotStyleLight28, /***/ PivotStyleDark1, /***/ PivotStyleDark2, /***/ PivotStyleDark3, /***/ PivotStyleDark4, /***/ PivotStyleDark5, /***/ PivotStyleDark6, /***/ PivotStyleDark7, /***/ PivotStyleDark8, /***/ PivotStyleDark9, /***/ PivotStyleDark10, /***/ PivotStyleDark11, /***/ PivotStyleDark12, /***/ PivotStyleDark13, /***/ PivotStyleDark14, /***/ PivotStyleDark15, /***/ PivotStyleDark16, /***/ PivotStyleDark17, /***/ PivotStyleDark18, /***/ PivotStyleDark19, /***/ PivotStyleDark20, /***/ PivotStyleDark21, /***/ PivotStyleDark22, /***/ PivotStyleDark23, /***/ PivotStyleDark24, /***/ PivotStyleDark25, /***/ PivotStyleDark26, /***/ PivotStyleDark27, /***/ PivotStyleDark28, ; private static final Map styleMap = new HashMap(60); private XSSFBuiltinTableStyle() { } /** * @return built-in {@link TableStyle} definition */ public TableStyle getStyle() { init(); return styleMap.get(this); } /** * NOTE: only checks by name, not definition. * @param style * @return true if the style represents a built-in style, false if it is null or a custom style */ public static boolean isBuiltinStyle(TableStyle style) { if (style == null) return false; try { XSSFBuiltinTableStyle.valueOf(style.getName()); return true; } catch (IllegalArgumentException e) { return false; } } /** * Only init once - thus the synchronized. Lazy, after creating instances, * and only when a style is actually needed, to avoid overhead for uses * that don't need the actual style definitions. *

* Public so clients can initialize the map on startup rather than lazily * during evaluation if desired. */ public static final synchronized void init() { if (! styleMap.isEmpty()) return; /* * initialize map. Every built-in has this format: * * * ... * ... * * * ... * * */ try { final InputStream is = XSSFBuiltinTableStyle.class.getResourceAsStream("presetTableStyles.xml"); try { final Document doc = DocumentHelper.readDocument(is); final NodeList styleNodes = doc.getDocumentElement().getChildNodes(); for (int i=0; i < styleNodes.getLength(); i++) { final Node node = styleNodes.item(i); if (node.getNodeType() != Node.ELEMENT_NODE) continue; // only care about elements final Element tag = (Element) node; String styleName = tag.getTagName(); Node dxfsNode = tag.getElementsByTagName("dxfs").item(0); Node tableStyleNode = tag.getElementsByTagName("tableStyles").item(0); // hack because I can't figure out how to get XMLBeans to parse a sub-element in a standalone manner // - build a fake styles.xml file with just this built-in StylesTable styles = new StylesTable(); styles.readFrom(new ByteArrayInputStream(styleXML(dxfsNode, tableStyleNode).getBytes(Charset.forName("UTF-8")))); styleMap.put(XSSFBuiltinTableStyle.valueOf(styleName), styles.getExplicitTableStyle(styleName)); } } finally { IOUtils.closeQuietly(is); } } catch (Exception e) { throw new RuntimeException(e); } } private static String styleXML(Node dxfsNode, Node tableStyleNode) { DOMImplementationLS lsImpl = (DOMImplementationLS)dxfsNode.getOwnerDocument().getImplementation().getFeature("LS", "3.0"); LSSerializer lsSerializer = lsImpl.createLSSerializer(); lsSerializer.getDomConfig().setParameter("xml-declaration", false); StringBuilder sb = new StringBuilder(); sb.append("\n") .append("\n"); sb.append(lsSerializer.writeToString(dxfsNode)); sb.append(lsSerializer.writeToString(tableStyleNode)); sb.append(""); return sb.toString(); } }