Apache Poi for Word - Создание собственного стиля с TextAlignment - PullRequest
0 голосов
/ 16 апреля 2020
    private static void applyTextAlign(XWPFStyle style, TextAlignment value) {
        // Steps here
    }

Как применить выравнивание текста (любого типа, например, TextAlignment.CENTER) к объекту стиля, передаваемому на вход этой функции? Мне не удалось найти подходящие учебные пособия и примеры по этому вопросу.

        CTPPr ppr = style.getCTStyle().addNewPPr();
        CTTextAlignment textAlignment = ppr.addNewTextAlignment();
        STTextAlignment.Enum en = STTextAlignment.Enum.forInt(value.ordinal());
        textAlignment.setVal(en);

Я пробовал что-то подобное выше, но, естественно, это не правильно и даже портит docx. Другие примеры, которые я нашел здесь, применяют выравнивание текста непосредственно к абзацу, но мне нужно, чтобы выравнивание текста было частью стиля, чтобы его можно было предоставить для любого элемента, будь то абзац или что-то еще.

1 Ответ

1 голос
/ 17 апреля 2020

Использование классов низкого уровня CT* не так просто. Эти классы автоматически создаются из схемы XML. Они ничего не считают. Так что нельзя просто добавить новый PPr к стилю. Что если он уже есть? У него не может быть двух, потому что это приведет к повреждению файла. Нужно проверить, есть ли уже PPr и только если нет, то добавить новый. То же самое для TextAlignment в PPr тогда.

Но, конечно, есть и другие проблемы из-за самого экспериментального состояния XWPF в apache poi. Например, XWPFStyle в основном предназначен только для чтения. Есть не так много сеттеров до сих пор. И при использовании CTStyle нужно проверить, действительно ли сохранялись изменения в этом. Например, java.util.List<XWPFStyle> из XWPFStyles, кажется, потерял контакт с одиночными CTStyle s из XWPFStyle s в нем. Поэтому мне пришлось использовать отражение, чтобы найти способ изменить CTStyle так, чтобы изменения были сохранены.

О, и, конечно, можно не быть уверенным, что порядковый номер перечисления ST* совпадают с перечислениями apache poi. Это было бы слишком просто, не так ли?

Следующий код работает для меня, используя текущий apache poi 4.1.2:

import java.io.*;

import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.lang.reflect.Field;

public class CreateWordTextAlingmentStyles {

 private static XWPFStyle createNamedStyle(XWPFStyles styles, STStyleType.Enum styleType, String styleId) {
  if (styles == null || styleId == null) return null;
  XWPFStyle style = styles.getStyle(styleId);
  if (style == null) {
   CTStyle ctStyle = CTStyle.Factory.newInstance();
   ctStyle.addNewName().setVal(styleId);
   ctStyle.setCustomStyle(STOnOff.TRUE);
   style = new XWPFStyle(ctStyle, styles);
   style.setType(styleType);
   style.setStyleId(styleId);
   styles.addStyle(style);
  }
  return style;
 }

 private static void applyTextAlignment(XWPFStyle style, TextAlignment value) throws Exception {
  if (style == null || value == null) return;

  Field _ctStyles = XWPFStyles.class.getDeclaredField("ctStyles");
  _ctStyles.setAccessible(true);
  CTStyles ctStyles = (CTStyles)_ctStyles.get(style.getStyles());

  for (CTStyle ctStyle : ctStyles.getStyleList()) {
   if (ctStyle.getStyleId().equals(style.getStyleId())) {
    CTPPr ppr = ctStyle.getPPr(); 
    if (ppr == null) ppr = ctStyle.addNewPPr();
    CTTextAlignment ctTextAlignment = ppr.getTextAlignment(); 
    if (ctTextAlignment == null) ctTextAlignment = ppr.addNewTextAlignment();
    if (value == TextAlignment.AUTO) {
     ctTextAlignment.setVal(STTextAlignment.AUTO);
    } else if (value == TextAlignment.BASELINE) {
     ctTextAlignment.setVal(STTextAlignment.BASELINE);
    } else if (value == TextAlignment.BOTTOM) {
     ctTextAlignment.setVal(STTextAlignment.BOTTOM);
    } else if (value == TextAlignment.CENTER) {
     ctTextAlignment.setVal(STTextAlignment.CENTER);
    } else if (value == TextAlignment.TOP) {
     ctTextAlignment.setVal(STTextAlignment.TOP);
    }
    style.setStyle(ctStyle);
   }
  }
 }

 private static void applyJustification(XWPFStyle style, ParagraphAlignment value) throws Exception {
  if (style == null || value == null) return;

  Field _ctStyles = XWPFStyles.class.getDeclaredField("ctStyles");
  _ctStyles.setAccessible(true);
  CTStyles ctStyles = (CTStyles)_ctStyles.get(style.getStyles());

  for (CTStyle ctStyle : ctStyles.getStyleList()) {
   if (ctStyle.getStyleId().equals(style.getStyleId())) {
    CTPPr ppr = ctStyle.getPPr(); if (ppr == null) ppr = ctStyle.addNewPPr();
    CTJc jc = ppr.getJc(); if (jc == null) jc = ppr.addNewJc();
    if (value == ParagraphAlignment.BOTH) {
     jc.setVal(STJc.BOTH);
    } else if (value == ParagraphAlignment.CENTER) {
     jc.setVal(STJc.CENTER);
    } else if (value == ParagraphAlignment.DISTRIBUTE) {
     jc.setVal(STJc.DISTRIBUTE);
    } else if (value == ParagraphAlignment.HIGH_KASHIDA) {
     jc.setVal(STJc.HIGH_KASHIDA);
    } else if (value == ParagraphAlignment.LEFT) {
     jc.setVal(STJc.LEFT);
    } else if (value == ParagraphAlignment.LOW_KASHIDA) {
     jc.setVal(STJc.LOW_KASHIDA);
    } else if (value == ParagraphAlignment.MEDIUM_KASHIDA) {
     jc.setVal(STJc.MEDIUM_KASHIDA);
    } else if (value == ParagraphAlignment.NUM_TAB) {
     jc.setVal(STJc.NUM_TAB);
    } else if (value == ParagraphAlignment.RIGHT) {
     jc.setVal(STJc.RIGHT);
    } else if (value == ParagraphAlignment.THAI_DISTRIBUTE) {
     jc.setVal(STJc.THAI_DISTRIBUTE);
    }
    style.setStyle(ctStyle);
   }
  }
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();
  XWPFParagraph paragraph = null;
  XWPFRun run = null;

  XWPFStyles styles = document.createStyles();

  XWPFStyle style = createNamedStyle(styles, STStyleType.PARAGRAPH, "TextAlignmentAUTO");
  applyTextAlignment(style, TextAlignment.AUTO);
  paragraph = document.createParagraph();
  paragraph.setStyle(style.getStyleId());
  run = paragraph.createRun();
  run.setText("TextAlignment.AUTO");
  run.setFontSize(8);
  run = paragraph.createRun();
  run.setText("Bigger text");
  run.setFontSize(30);

  style = createNamedStyle(styles, STStyleType.PARAGRAPH, "TextAlignmentBASELINECentered");
  applyJustification(style, ParagraphAlignment.CENTER);
  applyTextAlignment(style, TextAlignment.BASELINE);
  paragraph = document.createParagraph();
  paragraph.setStyle(style.getStyleId());
  run = paragraph.createRun();
  run.setText("TextAlignment.BASELINE");
  run.setFontSize(8);
  run = paragraph.createRun();
  run.setText("Bigger text");
  run.setFontSize(30);

  style = createNamedStyle(styles, STStyleType.PARAGRAPH, "TextAlignmentBOTTOMRight");
  applyJustification(style, ParagraphAlignment.RIGHT);
  applyTextAlignment(style, TextAlignment.BOTTOM);
  paragraph = document.createParagraph();
  paragraph.setStyle(style.getStyleId());
  run = paragraph.createRun();
  run.setText("TextAlignment.BOTTOM");
  run.setFontSize(8);
  run = paragraph.createRun();
  run.setText("Bigger text");
  run.setFontSize(30);

  style = createNamedStyle(styles, STStyleType.PARAGRAPH, "TextAlignmentCENTERBoth");
  applyJustification(style, ParagraphAlignment.BOTH);
  applyTextAlignment(style, TextAlignment.CENTER);
  paragraph = document.createParagraph();
  paragraph.setStyle(style.getStyleId());
  run = paragraph.createRun();
  run.setText("TextAlignment.CENTER");
  run.setFontSize(8);
  run = paragraph.createRun();
  run.setText("Bigger text");
  run.setFontSize(30);

  style = createNamedStyle(styles, STStyleType.PARAGRAPH, "TextAlignmentTOPLeft");
  applyJustification(style, ParagraphAlignment.LEFT);
  applyTextAlignment(style, TextAlignment.TOP);
  paragraph = document.createParagraph();
  paragraph.setStyle(style.getStyleId());
  run = paragraph.createRun();
  run.setText("TextAlignment.TOP");
  run.setFontSize(8);
  run = paragraph.createRun();
  run.setText("Bigger text");
  run.setFontSize(30);

  FileOutputStream out = new FileOutputStream("./CreateWordTextAlingmentStyles.docx");
  document.write(out);
  out.close();
  document.close();

 }
}

Он производит:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...