我们正在使用Apache POI 3.16(撰写本文时的最新版本)。
我们的代码如下:
XSLFTextBox textBox = slide.createTextBox();
XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
XSLFTextRun textRun = paragraph.addNewTextRun();
textRun.setText("non-Latin characters here");
textBox.setAnchor(new Rectangle(left, top, width, 10000));
textBox.resizeToFitText();
请注意,我们不会以任何方式更改字体样式。
此代码导致文本溢出文本框:
它似乎不是Apache POI错误。我只能找到关于resizeToFitText()
(Bug 45140,Bug 47594)的两个问题,两者都与换行符(which is another problem we're encountering)有关。
关于我们如何规避问题的任何想法?
更新1:这是一个完整的独立复制案例:
import java.awt.Rectangle;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
public class TextBoxOverflow {
public static void main(String[] args) throws Exception {
XMLSlideShow slideShow = new XMLSlideShow();
XSLFSlide slide = slideShow.createSlide();
XSLFTextBox textBox = slide.createTextBox();
XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
XSLFTextRun textRun = paragraph.addNewTextRun();
textRun.setText(
"ちょっと早いけどTシャツが着たくなる季節♡お母さんの影響か、非常に恐竜が大好きです。もう飼いたいくらい大好きです。#ジュラシックワールド のラプトル4姉妹とか激的に可愛くて可愛くて可愛くて可愛いです。めろめろ、大好き♡お母さんも恐竜が好きで、小さい頃、古代生物の図鑑を一緒に見てたの思い出す〜とい");
textBox.setAnchor(new Rectangle(50, 50, 200, 5000));
textBox.resizeToFitText();
FileOutputStream out = new FileOutputStream("TextBoxOverflow.pptx");
slideShow.write(out);
out.close();
slideShow.close();
}
}
结果:
更新2:在Apache POI的错误跟踪器中记录错误:
https://bz.apache.org/bugzilla/show_bug.cgi?id=61169
答案 0 :(得分:1)
这似乎是Windows
迄今为止对Unicode支持不佳的一个缺点。
如果我运行以下代码
import java.awt.Rectangle;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TextBoxOverflow {
public static void main(String[] args) throws Exception {
XMLSlideShow slideShow = new XMLSlideShow();
XSLFSlide slide = slideShow.createSlide();
XSLFTextBox textBox = slide.createTextBox();
XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
XSLFTextRun textRun = paragraph.addNewTextRun();
textRun.setText(
"ちょっと早いけどTシャツが着たくなる季節♡お母さんの影響か、非常に恐竜が大好きです。もう飼いたいくらい大好きです。#ジュラシックワールド のラプトル4姉妹とか激的に可愛くて可愛くて可愛くて可愛いです。めろめろ、大好き♡お母さんも恐竜が好きで、小さい頃、古代生物の図鑑を一緒に見てたの思い出す〜とい");
textBox.setAnchor(new Rectangle(50, 50, 200, 5000));
double heigth = textBox.getTextHeight();
System.out.println(heigth);
textBox.resizeToFitText();
CTShape ctshape = (CTShape)textBox.getXmlObject();
System.out.println(ctshape.getSpPr());
//set TextBox autofit the text
ctshape.getTxBody().getBodyPr().addNewSpAutoFit();
FileOutputStream out = new FileOutputStream("TextBoxOverflow.pptx");
slideShow.write(out);
out.close();
slideShow.close();
}
}
在Linux
,然后我得到:
如您所见,textBox.getTextHeight()
为330.0
且主播中的cy
为cy="4203700"
。
这会生成一个适当调整大小的文本框。
如果我在Windows
中也这样做,那么我得到:
如您所见,textBox.getTextHeight()
为183.78125
且主播中的cy
为cy="2346722"
。
这肯定会导致文本框只有一半高度。
如果您执行ctshape.getTxBody().getBodyPr().addNewSpAutoFit();
,则设置“将文本框大小自动调整为文本”标志。然后,至少对PowerPoint中的文本进行任何更改都会导致自动调整该框。
2017年6月10日编辑:
至少找到一个近似的解决方案。如果我们将XSLFTextRun
的字体系列设置为“Meiryo”,那么Windows
中的文本框高度的确定也大致正确:
import java.awt.Rectangle;
import java.io.FileOutputStream;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xslf.usermodel.XSLFTextBox;
import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
import org.apache.poi.xslf.usermodel.XSLFTextRun;
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TextBoxOverflow {
public static void main(String[] args) throws Exception {
XMLSlideShow slideShow = new XMLSlideShow();
XSLFSlide slide = slideShow.createSlide();
XSLFTextBox textBox = slide.createTextBox();
XSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);
XSLFTextRun textRun = paragraph.addNewTextRun();
String fontfamily = "Meiryo";
textRun.setFontFamily(fontfamily);
textRun.setText(
"ちょっと早いけどTシャツが着たくなる季節♡お母さんの影響か、非常に恐竜が大好きです。もう飼いたいくらい大好きです。#ジュラシックワールド のラプトル4姉妹とか激的に可愛くて可愛くて可愛くて可愛いです。めろめろ、大好き♡お母さんも恐竜が好きで、小さい頃、古代生物の図鑑を一緒に見てたの思い出す〜とい");
textBox.setAnchor(new Rectangle(50, 50, 200, 5000));
double heigth = textBox.getTextHeight();
System.out.println(heigth);
textBox.resizeToFitText();
CTShape ctshape = (CTShape)textBox.getXmlObject();
System.out.println(ctshape.getSpPr());
//set TextBox autofit the text
ctshape.getTxBody().getBodyPr().addNewSpAutoFit();
FileOutputStream out = new FileOutputStream("TextBoxOverflow.pptx");
slideShow.write(out);
out.close();
slideShow.close();
}
}
将Linux
导入与上述相同的值:textBox.getTextHeight()
为330.0
,锚点中的cy
为cy="4203700"
。
但现在Windows
textBox.getTextHeight()
为353.8330078125
,而cy
中的cy="4506379"
为ctshape.getTxBody().getBodyPr().addNewSpAutoFit();
。结合Microsoft
,我认为这是可以接受的。
不清楚应由谁负责。 Java
由于其支持较差的Unicode或public class MainActivity extends Activity {
private static final String TAG = "ButtonActivity";
private static final String INC_BUTTON_PIN_NAME = "BCM4"; // GPIO port wired to the button
private static final String DEC_BUTTON_PIN_NAME = "BCM17"; // GPIO port wired to the button
private Gpio mIncButtonGpio;
private Gpio mDecButtonGpio;
Handler mHandler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PeripheralManagerService service = new PeripheralManagerService();
try {
// Step 1. Create GPIO connection.
mIncButtonGpio = service.openGpio(INC_BUTTON_PIN_NAME);
mDecButtonGpio = service.openGpio(DEC_BUTTON_PIN_NAME);
// Step 2. Configure as an input.
mIncButtonGpio.setDirection(Gpio.DIRECTION_IN);
mDecButtonGpio.setDirection(Gpio.DIRECTION_IN);
// Step 3. Enable edge trigger events.
mIncButtonGpio.setEdgeTriggerType(Gpio.EDGE_FALLING);
mDecButtonGpio.setEdgeTriggerType(Gpio.EDGE_FALLING);
// Step 4. Register an event callback.
mIncButtonGpio.registerGpioCallback(mIncCallback);
mDecButtonGpio.registerGpioCallback(mDecCallback);
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
// Step 4. Register an event callback.
private GpioCallback mIncCallback = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
Log.i(TAG, "GPIO changed, INC button pressed");
// Step 5. Return true to keep callback active.
return true;
}
};
private GpioCallback mDecCallback = new GpioCallback() {
@Override
public boolean onGpioEdge(Gpio gpio) {
Log.i(TAG, "GPIO changed, DEC button pressed");
// Step 5. Return true to keep callback active.
return true;
}
};
@Override
protected void onDestroy() {
super.onDestroy();
// Step 6. Close the resource
if (mIncButtonGpio != null) {
mIncButtonGpio.unregisterGpioCallback(mIncCallback);
try {
mIncButtonGpio.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
if (mDecButtonGpio != null) {
mDecButtonGpio.unregisterGpioCallback(mDecCallback);
try {
mDecButtonGpio.close();
} catch (IOException e) {
Log.e(TAG, "Error on PeripheralIO API", e);
}
}
}
}
,因为它的字体管理效果不佳。