Проблема использования WPS Spreadsheets
заключается в том, что они утверждают, что они наиболее совместимы с Excel
, но иногда они полностью терпят неудачу. На этот раз они неверно истолковывают все настройки логического шрифта (жирный, курсив, зачеркнутый), если они явно установлены в true.
Office Open XML
предоставляет логические элементы, имеющие атрибут val
. Пример: <b val="true"/>
или <b val="false"/>
или также <b val="1"/>
или <b val="0"/>
. Но для набора жирного шрифта будет достаточно <b/>
. А для того, чтобы не устанавливать жирный шрифт, просто не было бы элемента b
.
Apache poi
всегда устанавливает <b val="true"/>
для жирного шрифта и <b val="false"/>
для не жирного. Но WPS Spreadsheets
теперь, похоже, неправильно истолковывает <b val="true"/>
. Ожидается только <b/>
.
Следующий код является наиболее совместимым кодом для создания строк расширенного текста для Excel
. Он поддерживает Office Open XML (*.xlsx)
, а также BIFF (*.xls)
и исправляет только <Boolean val="true"/>
до <Boolean/>
.
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBooleanProperty;
class CreateExcelRichText {
static RichTextString createRichTextString(Workbook workbook, String[] textParts, Font[] fonts) {
CreationHelper creationHelper = workbook.getCreationHelper();
RichTextString richTextString = creationHelper.createRichTextString(String.join("", textParts));
int start = 0;
int end = 0;
for (int tp = 0; tp < textParts.length; tp ++) {
Font font = null;
if (tp < fonts.length) font = fonts[tp];
end += textParts[tp].length();
if (font != null) richTextString.applyFont(start, end, font);
start += textParts[tp].length();
}
if (richTextString instanceof XSSFRichTextString) {
//unset val="true" for boolean objects
XSSFRichTextString xSSFRichTextString = (XSSFRichTextString)richTextString;
String[] boolenanObjectsToUnset = new String[]{"b", "i", "strike"};
for (String boolenanObjectToUnset : boolenanObjectsToUnset) {
XmlObject[] xmlObjects = xSSFRichTextString.getCTRst().selectPath(
"declare namespace main='http://schemas.openxmlformats.org/spreadsheetml/2006/main' " +
".//main:" + boolenanObjectToUnset);
for (XmlObject xmlObject : xmlObjects) {
CTBooleanProperty booleanProperty = (CTBooleanProperty)xmlObject;
if (booleanProperty.getVal()) booleanProperty.unsetVal();
}
}
}
return richTextString;
}
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
//Workbook workbook = new HSSFWorkbook();
Font font = workbook.createFont();
Font fontBoldItalic = workbook.createFont();
fontBoldItalic.setBold(true);
fontBoldItalic.setItalic(true);
Font fontItalic = workbook.createFont();
fontItalic.setItalic(true);
Font fontStrikeout = workbook.createFont();
fontStrikeout.setStrikeout(true);
String[] textParts = new String[]{"This is ", "Sample ", "content. ", "This is crossed out."};
Font[] fonts = new Font[]{font, fontBoldItalic, fontItalic, fontStrikeout};
RichTextString richTextString = createRichTextString(workbook, textParts, fonts);
Sheet sheet = workbook.createSheet();
sheet.createRow(0).createCell(0).setCellValue(richTextString);
String fileName = (workbook instanceof XSSFWorkbook)?"Excel.xlsx":"Excel.xls";
FileOutputStream out = new FileOutputStream(fileName);
workbook.write(out);
out.close();
workbook.close();
}
}