Apache poi:在 docx 文本框中旋转文本

Apache poi : rotate text inside docx textbox

客户要求能够将可编辑注释添加到由网络应用程序自动生成的 docx 文档中。我通过向文档添加一些可编辑的文本框来实现该要求。现在客户希望其中一些注释有垂直文本,但我找不到任何关于如何实现此功能的示例。我应该旋转文本框还是包含的文本?我应该使用哪个 class ?你能提供任何 link 的例子吗,我到目前为止已经找到 none 了?下面是我用来添加文本框的代码:

try {
                    CTGroup ctGroup = CTGroup.Factory.newInstance();

                    CTRect ctRect = ctGroup.addNewRect();
                    ctRect.setStyle(
                              String.format(
                                      "position:absolute;width: %scm;"   
                                    + "height:%scm;" 
                                    + "top:%scm;"
                                    + "left:%scm;"
                                    + "mso-position-horizontal-relative:page;"
                                    + "mso-position-vertical-relative:page;",
                                    nota.getWordPosition().getWidth()/10,//mm->cm
                                    nota.getWordPosition().getHeight()/10,//mm->cm
                                    nota.getWordPosition().getY(),
                                    nota.getWordPosition().getX()
                            )
                      );
                      CTTxbxContent ctTxbxContent = ctRect.addNewTextbox().addNewTxbxContent();
                      String[] noteLines = nota.getDescription().split("\n|\r\n");
                      CTP noteCTP = ctTxbxContent.addNewP();
                      for(String line : noteLines){
                         CTR noteCTR = noteCTP.addNewR();
                         noteCTR.addNewT().setStringValue(line);
                         noteCTR.addNewCr();
                      }
                      
                      Node ctGroupNode = ctGroup.getDomNode(); 
                      CTPicture ctPicture = CTPicture.Factory.parse(ctGroupNode);
                      
                      XWPFRun noteRun = imageParagraph.createRun(); 
                      
                      CTR cTR = noteRun.getCTR();
                      cTR.addNewPict();
                      cTR.setPictArray(0, ctPicture);
                     
                      
                } catch (Exception e) {
                    logger.warn("failed to add a note " +  e.getMessage(),e);
                    throw new ReportGeneratorException("error adding note on pages " + nota.getPages() + "(id " + nota.getId() +")");
                }

那将是 CTTextbox 的风格。在那里你可以设置“layout-flow:vertical;mso-layout-flow-alt:bottom-to-top”。这意味着垂直文本从下到上流动。

...
CTTextbox ctTextbox = ctRect.addNewTextbox();
ctTextbox.setStyle("layout-flow:vertical;mso-layout-flow-alt:bottom-to-top");
...

如何获得?创建默认文本框。使用 Word GUI 打开文件。根据需要在那里设置文本方向。保存文件。解压缩 *.docx 并查看 /word/document.xml。在那里你会发现:

<w:pict>
 <v:rect style="position:absolute;...">
  <v:textbox style="...;layout-flow:vertical;mso-layout-flow-alt:bottom-to-top;...">
   <w:txbxContent>
    ...
   </w:txbxContent>
  </v:textbox>
 </v:rect>
</w:pict>

完整示例(使用 apache poi 5.0.0 测试和工作):

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTxbxContent;

import com.microsoft.schemas.vml.CTGroup;
import com.microsoft.schemas.vml.CTRect;
import com.microsoft.schemas.vml.CTTextbox;
import com.microsoft.schemas.office.word.CTWrap;
import com.microsoft.schemas.office.word.STWrapType;

import org.w3c.dom.Node;

public class CreateWordTextBox {

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

  XWPFDocument doc= new XWPFDocument();

  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The Body text: ");

  CTGroup ctGroup = CTGroup.Factory.newInstance();

  CTRect ctRect = ctGroup.addNewRect();
  //ctRect.addNewWrap().setType(STWrapType.SQUARE);
  ctRect.setStyle("position:absolute;mso-position-horizontal:center;margin-top:10pt;width:36pt;height:100pt");
  
  CTTextbox ctTextbox = ctRect.addNewTextbox();
  ctTextbox.setStyle("layout-flow:vertical;mso-layout-flow-alt:bottom-to-top");

  CTTxbxContent ctTxbxContent = ctTextbox.addNewTxbxContent();
  ctTxbxContent.addNewP().addNewR().addNewT().setStringValue("The TextBox text...");

  Node ctGroupNode = ctGroup.getDomNode(); 
  CTPicture ctPicture = CTPicture.Factory.parse(ctGroupNode);
  run=paragraph.createRun();  
  CTR cTR = run.getCTR();
  cTR.addNewPict();
  cTR.setPictArray(0, ctPicture);

  paragraph = doc.createParagraph();
  run=paragraph.createRun();  
  run.setText("Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... Lorem ipsum semit color ... ");

  FileOutputStream out = new FileOutputStream("WordTextBox.docx");
  doc.write(out);
  out.close();
  doc.close();

 }
}