com.github.developframework.excel.styles.CellStyleKey Maven / Gradle / Ivy
package com.github.developframework.excel.styles;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author qiushui on 2023-05-19.
*/
public class CellStyleKey implements ItemKey {
@SuppressWarnings("unchecked")
private static final Class extends ItemKey>[] ITEM_KEY_CLASSES = new Class[]{
AlignmentKey.class,
BorderKey.class,
ConfigKey.class,
DataFormatKey.class,
FontKey.class,
ForegroundKey.class
};
private final List itemKeys = new LinkedList<>();
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
for (ItemKey itemKey : itemKeys) {
itemKey.configureCellStyle(workbook, cellStyle);
}
}
@Override
public String toString() {
return itemKeys
.stream()
.sorted(Comparator.comparing(ik -> ik.getClass().getSimpleName()))
.map(ItemKey::toString)
.filter(s -> !s.endsWith("{}"))
.collect(Collectors.joining(" "));
}
public static boolean isCellStyleKey(String key) {
return key.isEmpty() || key.matches("^(\\s*\\w+\\s*\\{(.+?)*}\\s*)+$");
}
public static CellStyleKey parse(String key) {
final CellStyleKey cellStyleKey = new CellStyleKey();
final Map, Map> itemKeyMetadataMap = disassembleItemKey(key);
for (Class extends ItemKey> itemKeyClass : ITEM_KEY_CLASSES) {
final Map properties = itemKeyMetadataMap.getOrDefault(itemKeyClass, Collections.emptyMap());
try {
cellStyleKey.itemKeys.add(
itemKeyClass.getConstructor(Map.class).newInstance(properties)
);
} catch (Exception e) {
e.printStackTrace();
}
}
return cellStyleKey;
}
private static Map, Map> disassembleItemKey(String key) {
final char[] charArray = key.toCharArray();
final StringBuilder itemKeyNameBuilder = new StringBuilder();
final StringBuilder propertiesBuilder = new StringBuilder();
final Map, Map> map = new HashMap<>();
boolean inner = false;
boolean quote = false;
Class extends ItemKey> itemKeyClass = null;
for (char c : charArray) {
switch (c) {
case ' ':
case '\t':
case '\n': {
if (quote) {
propertiesBuilder.append(c);
} else {
continue;
}
}
break;
case '\'': {
quote = !quote;
propertiesBuilder.append(c);
}
break;
case '{': {
if (inner) {
throw new IllegalArgumentException("item key is valid");
}
inner = true;
itemKeyClass = determineItemKey(itemKeyNameBuilder.toString());
itemKeyNameBuilder.setLength(0);
}
break;
case '}': {
if (!inner) {
throw new IllegalArgumentException("item key is valid");
}
inner = false;
map.put(itemKeyClass, disassembleProperties(propertiesBuilder.toString()));
itemKeyClass = null;
propertiesBuilder.setLength(0);
}
break;
default: {
if (inner) {
propertiesBuilder.append(c);
} else {
itemKeyNameBuilder.append(c);
}
}
break;
}
}
return map;
}
private static Map disassembleProperties(String properties) {
final Map map = new HashMap<>();
final String[] parts = properties.split(";");
for (String part : parts) {
if (part.isEmpty()) {
continue;
}
final int i = part.indexOf(":");
if (i == -1) {
map.put(part, "true");
} else {
map.put(part.substring(0, i), StringUtils.strip(part.substring(i + 1), "'"));
}
}
return map;
}
private static Class extends ItemKey> determineItemKey(String itemKeyName) {
for (Class extends ItemKey> itemKeyClass : ITEM_KEY_CLASSES) {
final String[] prefixArray = itemKeyClass.getAnnotation(ItemKeySign.class).value();
for (String prefix : prefixArray) {
if (itemKeyName.equals(prefix)) {
return itemKeyClass;
}
}
}
throw new IllegalArgumentException("unknown item key \"" + itemKeyName + "\"");
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ItemKeySign {
String[] value();
}
// font {size: 16; bold; italic; family: 宋体; color: #ffaaee}
@Getter
@ItemKeySign({"font", "f"})
protected static class FontKey extends AbstractItemKey {
private short size;
private CompositeColor color;
private String family;
private boolean italic;
private boolean bold;
public FontKey(Map properties) {
super(properties);
if (properties.containsKey("size")) {
size = Short.parseShort(properties.get("size"));
}
if (properties.containsKey("color")) {
color = new CompositeColor(properties.get("color"));
}
if (properties.containsKey("family")) {
family = properties.get("family");
}
if (properties.containsKey("italic")) {
italic = Boolean.parseBoolean(properties.get("italic"));
}
if (properties.containsKey("bold")) {
bold = Boolean.parseBoolean(properties.get("bold"));
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
final Font font = workbook.createFont();
if (family != null) {
font.setFontName(family);
}
if (size != 0) {
font.setFontHeightInPoints(size);
}
font.setItalic(italic);
font.setBold(bold);
if(color != null) {
color.configureFontColor(workbook, font);
}
cellStyle.setFont(font);
}
@Override
public String toString() {
List list = new LinkedList<>();
if (size != 0) {
list.add("size: " + size);
}
if (color != null) {
list.add("color: " + color);
}
if (family != null) {
list.add("family: '" + family + "'");
}
if (italic) {
list.add("italic");
}
if (bold) {
list.add("bold");
}
return String.format("font {%s}", StringUtils.join(list, "; "));
}
}
// align {vertical: right; horizontal: center}
@Getter
@ItemKeySign({"align", "a"})
protected static class AlignmentKey extends AbstractItemKey {
private HorizontalAlignment horizontalAlignment = HorizontalAlignment.CENTER;
private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER;
public AlignmentKey(Map properties) {
super(properties);
if (properties.containsKey("v")) {
verticalAlignment = VerticalAlignment.valueOf(properties.get("v").toUpperCase());
}
if (properties.containsKey("vertical")) {
verticalAlignment = VerticalAlignment.valueOf(properties.get("vertical").toUpperCase());
}
if (properties.containsKey("h")) {
horizontalAlignment = HorizontalAlignment.valueOf(properties.get("h").toUpperCase());
}
if (properties.containsKey("horizontal")) {
horizontalAlignment = HorizontalAlignment.valueOf(properties.get("horizontal").toUpperCase());
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
cellStyle.setAlignment(horizontalAlignment);
cellStyle.setVerticalAlignment(verticalAlignment);
}
@Override
public String toString() {
List list = new LinkedList<>();
if (verticalAlignment != VerticalAlignment.CENTER) {
list.add("vertical: " + verticalAlignment);
}
if (horizontalAlignment != HorizontalAlignment.CENTER) {
list.add("horizontal: " + horizontalAlignment);
}
return String.format("align {%s}", StringUtils.join(list, "; "));
}
}
// foreground {color: #aa1199; type: SOLID_FOREGROUND}
@Getter
@ItemKeySign({"foreground", "fg"})
protected static class ForegroundKey extends AbstractItemKey {
private CompositeColor color;
private FillPatternType type = FillPatternType.SOLID_FOREGROUND;
public ForegroundKey(Map properties) {
super(properties);
if (properties.containsKey("color")) {
color = new CompositeColor(properties.get("color"));
}
if (properties.containsKey("type")) {
type = FillPatternType.valueOf(properties.get("type").toUpperCase());
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
if(color != null) {
color.configureForegroundColor(workbook, cellStyle);
cellStyle.setFillPattern(type);
}
}
@Override
public String toString() {
List list = new LinkedList<>();
if (color != null) {
list.add("color: " + color);
}
if (type != FillPatternType.SOLID_FOREGROUND) {
list.add("type: " + type);
}
return String.format("foreground {%s}", StringUtils.join(list, "; "));
}
}
// border {style: thin; color: #bbaadd;}
@Getter
@ItemKeySign({"border", "b"})
protected static class BorderKey extends AbstractItemKey {
private BorderStyle style = BorderStyle.THIN;
private CompositeColor color;
public BorderKey(Map properties) {
super(properties);
if (properties.containsKey("color")) {
color = new CompositeColor(properties.get("color"));
}
if (properties.containsKey("style")) {
style = BorderStyle.valueOf(properties.get("style").toUpperCase());
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
cellStyle.setBorderTop(style);
cellStyle.setBorderRight(style);
cellStyle.setBorderBottom(style);
cellStyle.setBorderLeft(style);
if(color != null) {
color.configureBorderColor(workbook, cellStyle);
}
}
@Override
public String toString() {
List list = new LinkedList<>();
if (style != BorderStyle.THIN) {
list.add("style: " + style);
}
if (color != null) {
list.add("color: " + color);
}
return String.format("border {%s}", StringUtils.join(list, "; "));
}
}
// dataFormat {format: 0.00%}
@Getter
@ItemKeySign({"dataFormat", "df"})
protected static class DataFormatKey extends AbstractItemKey {
private String format = "@";
public DataFormatKey(Map properties) {
super(properties);
if (properties.containsKey("format")) {
format = properties.get("format");
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
cellStyle.setDataFormat(workbook.createDataFormat().getFormat(format));
}
@Override
public String toString() {
List list = new LinkedList<>();
if (!format.equals("@")) {
list.add("format: '" + format + "'");
}
return String.format("dataFormat {%s}", StringUtils.join(list, "; "));
}
}
// config {wrapText}
@Getter
@ItemKeySign({"config", "c"})
protected static class ConfigKey extends AbstractItemKey {
private boolean wrapText;
public ConfigKey(Map properties) {
super(properties);
if (properties.containsKey("wrapText")) {
wrapText = Boolean.parseBoolean(properties.get("wrapText"));
}
}
@Override
public void configureCellStyle(Workbook workbook, CellStyle cellStyle) {
cellStyle.setWrapText(wrapText);
}
@Override
public String toString() {
List list = new LinkedList<>();
if (wrapText) {
list.add("wrapText");
}
return String.format("config {%s}", StringUtils.join(list, "; "));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy