
me.chyxion.xls.css.support.TextApplier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of table-to-xls Show documentation
Show all versions of table-to-xls Show documentation
Convert HTML Table To Excel
The newest version!
package me.chyxion.xls.css.support;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import java.util.Map;
import org.slf4j.Logger;
import java.util.HashMap;
import java.util.regex.Pattern;
import org.slf4j.LoggerFactory;
import me.chyxion.xls.css.CssUtils;
import me.chyxion.xls.css.CssApplier;
import org.apache.poi.ss.usermodel.Font;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
/**
* supports:
* color: name | #rgb | #rrggbb | rgb(r, g, b)
* text-decoration: underline;
* font-style: italic | oblique;
* font-weight: bold | bolder | 700 | 800 | 900;
* font-size: length; length unit will be ignored,
* [xx-small|x-small|small|medium|large|x-large|xx-large] will be ignored.
* font:[[ font-style || font-variant || font-weight ]? font-size [/line-height]? font-family]
* | caption | icon | menu | message-box | small-caption | status-bar;
* [font-variant, line-height, caption, icon, menu, message-box, small-caption, status-bar] will be ignored.
*
* @author Shaun Chyxion
* @date Oct 24, 2014 5:21:30 PM
*/
@Slf4j
public class TextApplier implements CssApplier {
private static final String TEXT_DECORATION = "text-decoration";
private static final String UNDERLINE = "underline";
/**
* {@inheritDoc}
*/
@Override
public Map parse(final Map style) {
log.debug("Parse font style.");
val mapRtn = new HashMap(8);
// color
val color = CssUtils.processColor(style.get(COLOR));
if (StringUtils.isNotBlank(color)) {
log.debug("Text color [{}] found.", color);
mapRtn.put(COLOR, color);
}
// font
parseFontAttr(style, mapRtn);
// text text-decoration
if (UNDERLINE.equals(style.get(TEXT_DECORATION))) {
mapRtn.put(TEXT_DECORATION, UNDERLINE);
}
return mapRtn;
}
/**
* {@inheritDoc}
*/
@Override
public void apply(final XSSFCell cell,
final XSSFCellStyle cellStyle,
final Map style) {
XSSFFont font = null;
if (ITALIC.equals(style.get(FONT_STYLE))) {
font = createFontIfNull(cell, font);
font.setItalic(true);
}
val fontSize = CssUtils.getInt(style.get(FONT_SIZE));
if (fontSize > 0) {
font = createFontIfNull(cell, font);
font.setFontHeightInPoints((short) fontSize);
}
if (BOLD.equals(style.get(FONT_WEIGHT))) {
font = createFontIfNull(cell, font);
font.setBold(true);
}
val fontFamily = style.get(FONT_FAMILY);
if (StringUtils.isNotBlank(fontFamily)) {
font = createFontIfNull(cell, font);
font.setFontName(fontFamily);
}
val color = CssUtils.parseColor(style.get(COLOR));
if (color != null) {
if (!CssUtils.isBlack(color)) {
font = createFontIfNull(cell, font);
font.setColor(color);
}
else {
val removedColor = style.remove(COLOR);
log.info("Text color [{}] is black or familiar to black, ignore.", removedColor);
}
}
// text-decoration
val textDecoration = style.get(TEXT_DECORATION);
if (UNDERLINE.equals(textDecoration)) {
font = createFontIfNull(cell, font);
font.setUnderline(Font.U_SINGLE);
}
if (font != null) {
cellStyle.setFont(font);
}
}
// --
// private methods
private Map parseFontAttr(Map style, Map mapRtn) {
// font
val font = style.get(FONT);
if (StringUtils.isNotBlank(font) &&
!ArrayUtils.contains(new String[] {
"small-caps", "caption",
"icon", "menu", "message-box",
"small-caption", "status-bar"
}, font)) {
log.debug("Parse font attr [{}].", font);
val ignoreStyles = new String[] {
"normal",
// font weight normal
"[1-3]00"
};
val sbFont = new StringBuffer(
font.replaceAll("^|\\s*" + StringUtils.join(ignoreStyles, "|") + "\\s+|$", " "));
log.debug("Font attr [{}] after process ignore.", sbFont);
// style
val matcherStyle = Pattern.compile("(?:^|\\s+)(italic|oblique)(?:\\s+|$)")
.matcher(sbFont.toString());
if (matcherStyle.find()) {
sbFont.setLength(0);
if (log.isDebugEnabled()) {
log.debug("Font style [{}] found.", matcherStyle.group(1));
}
mapRtn.put(FONT_STYLE, ITALIC);
matcherStyle.appendReplacement(sbFont, " ");
matcherStyle.appendTail(sbFont);
}
// weight
val matcherWeight = Pattern.compile("(?:^|\\s+)(bold(?:er)?|[7-9]00)(?:\\s+|$)")
.matcher(sbFont.toString());
if (matcherWeight.find()) {
sbFont.setLength(0);
if (log.isDebugEnabled()) {
log.debug("Font weight [{}](bold) found.", matcherWeight.group(1));
}
mapRtn.put(FONT_WEIGHT, BOLD);
matcherWeight.appendReplacement(sbFont, " ");
matcherWeight.appendTail(sbFont);
}
// size xx-small | x-small | small | medium | large | x-large | xx-large | 18px [/2]
val matcherSize = Pattern.compile(
// before blank or start
new StringBuilder("(?:^|\\s+)")
// font size
.append("(xx-small|x-small|small|medium|large|x-large|xx-large|")
.append("(?:")
.append(PATTERN_LENGTH)
.append("))")
// line height
.append("(?:\\s*\\/\\s*(")
.append(PATTERN_LENGTH)
.append("))?")
// after blank or end
.append("(?:\\s+|$)")
.toString())
.matcher(sbFont.toString());
if (matcherSize.find()) {
sbFont.setLength(0);
log.debug("Font size[/line-height] [{}] found.", matcherSize.group());
String fontSize = matcherSize.group(1);
if (StringUtils.isNotBlank(fontSize)) {
fontSize = StringUtils.deleteWhitespace(fontSize);
log.debug("Font size [{}].", fontSize);
if (fontSize.matches(PATTERN_LENGTH)) {
mapRtn.put(FONT_SIZE, fontSize);
}
else {
log.info("Font size [{}] not supported, ignore.", fontSize);
}
}
val lineHeight = matcherSize.group(2);
if (StringUtils.isNotBlank(lineHeight)) {
log.warn("Line height [{}] not supported, ignore.", lineHeight);
}
matcherSize.appendReplacement(sbFont, " ");
matcherSize.appendTail(sbFont);
}
// font family
if (sbFont.length() > 0) {
log.debug("Font families [{}].", sbFont);
// trim & remove '"
String fontFamily = sbFont.toString()
.split("\\s*,\\s*")[0].trim().replaceAll("'|\"", "");
log.debug("Use first font family [{}].", fontFamily);
mapRtn.put(FONT_FAMILY, fontFamily);
}
}
val fontStyle = style.get(FONT_STYLE);
if (ArrayUtils.contains(new String[] {ITALIC, "oblique"}, fontStyle)) {
log.debug("Font italic [{}] found.", fontStyle);
mapRtn.put(FONT_STYLE, ITALIC);
}
val fontWeight = style.get(FONT_WEIGHT);
if (StringUtils.isNotBlank(fontWeight) &&
Pattern.matches("^bold(?:er)?|[7-9]00$", fontWeight)) {
log.debug("Font weight [{}](bold) found.", fontWeight);
mapRtn.put(FONT_WEIGHT, BOLD);
}
val fontSize = style.get(FONT_SIZE);
if (CssUtils.isNum(fontSize)) {
log.debug("Font size [{}] found.", fontSize);
mapRtn.put(FONT_SIZE, fontSize);
}
val fontFamily = style.get(FONT_FAMILY);
if (StringUtils.isNotBlank(fontFamily)) {
log.debug("Font family [{}] found.", fontFamily);
mapRtn.put(FONT_FAMILY, fontFamily);
}
return mapRtn;
}
XSSFFont createFontIfNull(final XSSFCell cell, final XSSFFont font) {
if (font != null) {
return font;
}
return cell.getSheet().getWorkbook().createFont();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy