merge with trunk as of r1160685
git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_3_8_BETA4@1160688 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
commit
2bbeecb657
@ -32,8 +32,8 @@
|
||||
</header>
|
||||
|
||||
<body>
|
||||
<section><title>6 June 2011 - POI 3.8 beta 3 available</title>
|
||||
<p>The Apache POI team is pleased to announce the release of 3.8 beta 3.
|
||||
<section><title>22 August 2011 - POI 3.8 beta 4 available</title>
|
||||
<p>The Apache POI team is pleased to announce the release of 3.8 beta 4.
|
||||
This includes a large number of bug fixes and enhancements.
|
||||
</p>
|
||||
<p>A full list of changes is available in the <link href="changes.html">change log</link>.
|
||||
|
@ -34,6 +34,9 @@
|
||||
|
||||
<changes>
|
||||
<release version="3.8-beta4" date="2011-??-??">
|
||||
<action dev="poi-developers" type="fix">51678 - Extracting text from Bug51524.zip is slow</action>
|
||||
<action dev="poi-developers" type="fix">51671 - HWPFDocument.write based on NPOIFSFileSystem throws a NullPointerException</action>
|
||||
<action dev="poi-developers" type="add">support for tables and hyperlinks in XSLF</action>
|
||||
<action dev="poi-developers" type="fix">51535 - correct signed vs unsigned short reading in NDocumentInputStream</action>
|
||||
<action dev="poi-developers" type="add">51634 - support SXSSF streaming from templates</action>
|
||||
<action dev="poi-developers" type="add">initial support for XSLF usermodel API</action>
|
||||
|
@ -24,6 +24,8 @@ import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.util.POIUtils;
|
||||
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.MutablePropertySet;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
@ -36,6 +38,7 @@ import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
@ -236,10 +239,11 @@ public abstract class POIDocument {
|
||||
* @param target is the target POIFS to copy to
|
||||
* @param excepts is a list of Strings specifying what nodes NOT to copy
|
||||
*/
|
||||
protected void copyNodes(POIFSFileSystem source, POIFSFileSystem target,
|
||||
List<String> excepts) throws IOException {
|
||||
//System.err.println("CopyNodes called");
|
||||
copyNodes(source.getRoot(), target.getRoot(), excepts);
|
||||
@Deprecated
|
||||
protected void copyNodes( POIFSFileSystem source, POIFSFileSystem target,
|
||||
List<String> excepts ) throws IOException
|
||||
{
|
||||
POIUtils.copyNodes( source, target, excepts );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -248,37 +252,21 @@ public abstract class POIDocument {
|
||||
* @param target is the target POIFS to copy to
|
||||
* @param excepts is a list of Strings specifying what nodes NOT to copy
|
||||
*/
|
||||
protected void copyNodes(DirectoryNode sourceRoot, DirectoryNode targetRoot,
|
||||
List<String> excepts) throws IOException {
|
||||
Iterator<Entry> entries = sourceRoot.getEntries();
|
||||
while (entries.hasNext()) {
|
||||
Entry entry = entries.next();
|
||||
if (!excepts.contains(entry.getName())) {
|
||||
copyNodeRecursively(entry,targetRoot);
|
||||
}
|
||||
}
|
||||
@Deprecated
|
||||
protected void copyNodes( DirectoryNode sourceRoot,
|
||||
DirectoryNode targetRoot, List<String> excepts ) throws IOException
|
||||
{
|
||||
POIUtils.copyNodes( sourceRoot, targetRoot, excepts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies an Entry into a target POIFS directory, recursively
|
||||
*/
|
||||
private void copyNodeRecursively(Entry entry, DirectoryEntry target)
|
||||
throws IOException {
|
||||
//System.err.println("copyNodeRecursively called with "+entry.getName()+
|
||||
// ","+target.getName());
|
||||
DirectoryEntry newTarget = null;
|
||||
if (entry.isDirectoryEntry()) {
|
||||
newTarget = target.createDirectory(entry.getName());
|
||||
Iterator<Entry> entries = ((DirectoryEntry)entry).getEntries();
|
||||
|
||||
while (entries.hasNext()) {
|
||||
copyNodeRecursively(entries.next(),newTarget);
|
||||
}
|
||||
} else {
|
||||
DocumentEntry dentry = (DocumentEntry)entry;
|
||||
DocumentInputStream dstream = new DocumentInputStream(dentry);
|
||||
target.createDocument(dentry.getName(),dstream);
|
||||
dstream.close();
|
||||
}
|
||||
@Internal
|
||||
@Deprecated
|
||||
protected void copyNodeRecursively( Entry entry, DirectoryEntry target )
|
||||
throws IOException
|
||||
{
|
||||
POIUtils.copyNodeRecursively( entry, target );
|
||||
}
|
||||
}
|
||||
|
103
src/java/org/apache/poi/util/POIUtils.java
Normal file
103
src/java/org/apache/poi/util/POIUtils.java
Normal file
@ -0,0 +1,103 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
@Internal
|
||||
public class POIUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* Copies an Entry into a target POIFS directory, recursively
|
||||
*/
|
||||
@Internal
|
||||
public static void copyNodeRecursively( Entry entry, DirectoryEntry target )
|
||||
throws IOException
|
||||
{
|
||||
// System.err.println("copyNodeRecursively called with "+entry.getName()+
|
||||
// ","+target.getName());
|
||||
DirectoryEntry newTarget = null;
|
||||
if ( entry.isDirectoryEntry() )
|
||||
{
|
||||
newTarget = target.createDirectory( entry.getName() );
|
||||
Iterator<Entry> entries = ( (DirectoryEntry) entry ).getEntries();
|
||||
|
||||
while ( entries.hasNext() )
|
||||
{
|
||||
copyNodeRecursively( entries.next(), newTarget );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentEntry dentry = (DocumentEntry) entry;
|
||||
DocumentInputStream dstream = new DocumentInputStream( dentry );
|
||||
target.createDocument( dentry.getName(), dstream );
|
||||
dstream.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies nodes from one POIFS to the other minus the excepts
|
||||
*
|
||||
* @param source
|
||||
* is the source POIFS to copy from
|
||||
* @param target
|
||||
* is the target POIFS to copy to
|
||||
* @param excepts
|
||||
* is a list of Strings specifying what nodes NOT to copy
|
||||
*/
|
||||
public static void copyNodes( DirectoryEntry sourceRoot,
|
||||
DirectoryEntry targetRoot, List<String> excepts )
|
||||
throws IOException
|
||||
{
|
||||
Iterator<Entry> entries = sourceRoot.getEntries();
|
||||
while ( entries.hasNext() )
|
||||
{
|
||||
Entry entry = entries.next();
|
||||
if ( !excepts.contains( entry.getName() ) )
|
||||
{
|
||||
copyNodeRecursively( entry, targetRoot );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies nodes from one POIFS to the other minus the excepts
|
||||
*
|
||||
* @param source
|
||||
* is the source POIFS to copy from
|
||||
* @param target
|
||||
* is the target POIFS to copy to
|
||||
* @param excepts
|
||||
* is a list of Strings specifying what nodes NOT to copy
|
||||
*/
|
||||
public static void copyNodes( POIFSFileSystem source,
|
||||
POIFSFileSystem target, List<String> excepts ) throws IOException
|
||||
{
|
||||
// System.err.println("CopyNodes called");
|
||||
copyNodes( source.getRoot(), target.getRoot(), excepts );
|
||||
}
|
||||
}
|
@ -48,19 +48,10 @@ import java.util.List;
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
@Beta
|
||||
public class XSLFAutoShape extends XSLFSimpleShape {
|
||||
private final List<XSLFTextParagraph> _paragraphs;
|
||||
public class XSLFAutoShape extends XSLFTextShape {
|
||||
|
||||
/*package*/ XSLFAutoShape(CTShape shape, XSLFSheet sheet) {
|
||||
super(shape, sheet);
|
||||
|
||||
_paragraphs = new ArrayList<XSLFTextParagraph>();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBody txBody = shape.getTxBody();
|
||||
for (CTTextParagraph p : txBody.getPList()) {
|
||||
_paragraphs.add(new XSLFTextParagraph(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/
|
||||
@ -74,36 +65,6 @@ public class XSLFAutoShape extends XSLFSimpleShape {
|
||||
}
|
||||
}
|
||||
|
||||
// textual properties
|
||||
public String getText() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (XSLFTextParagraph p : _paragraphs) {
|
||||
if (out.length() > 0) out.append('\n');
|
||||
out.append(p.getText());
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public List<XSLFTextParagraph> getTextParagraphs() {
|
||||
return _paragraphs;
|
||||
}
|
||||
|
||||
public XSLFTextParagraph addNewTextParagraph() {
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
CTTextBody txBody;
|
||||
if (!shape.isSetTxBody()) {
|
||||
txBody = shape.addNewTxBody();
|
||||
txBody.addNewBodyPr();
|
||||
txBody.addNewLstStyle();
|
||||
} else {
|
||||
txBody = shape.getTxBody();
|
||||
}
|
||||
CTTextParagraph p = txBody.addNewP();
|
||||
XSLFTextParagraph paragraph = new XSLFTextParagraph(p);
|
||||
_paragraphs.add(paragraph);
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shapeId 1-based shapeId
|
||||
*/
|
||||
@ -160,268 +121,15 @@ public class XSLFAutoShape extends XSLFSimpleShape {
|
||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of vertical alignment for the text.
|
||||
* One of the <code>Anchor*</code> constants defined in this class.
|
||||
*
|
||||
* @param anchor - the type of alignment. Default is {@link VerticalAlignment#TOP}
|
||||
*/
|
||||
public void setVerticalAlignment(VerticalAlignment anchor){
|
||||
protected CTTextBody getTextBody(boolean create){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(anchor == null) {
|
||||
if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor();
|
||||
} else {
|
||||
bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of vertical alignment for the text.
|
||||
*
|
||||
* @return the type of alignment
|
||||
*/
|
||||
public VerticalAlignment getVerticalAlignment(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
STTextAnchoringType.Enum val = shape.getTxBody().getBodyPr().getAnchor();
|
||||
if(val != null){
|
||||
return VerticalAlignment.values()[val.intValue() - 1];
|
||||
}
|
||||
}
|
||||
return VerticalAlignment.TOP;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param orientation vertical orientation of the text
|
||||
*/
|
||||
public void setTextDirection(TextDirection orientation){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(orientation == null) {
|
||||
if(bodyPr.isSetVert()) bodyPr.unsetVert();
|
||||
} else {
|
||||
bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return vertical orientation of the text
|
||||
*/
|
||||
public TextDirection getTextDirection(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
STTextVerticalType.Enum val = shape.getTxBody().getBodyPr().getVert();
|
||||
if(val != null){
|
||||
return TextDirection.values()[val.intValue() - 1];
|
||||
}
|
||||
}
|
||||
return TextDirection.HORIZONTAL;
|
||||
}
|
||||
/**
|
||||
* Returns the distance (in points) between the bottom of the text frame
|
||||
* and the bottom of the inscribed rectangle of the shape that contains the text.
|
||||
*
|
||||
* @return the bottom margin or -1 if not set
|
||||
*/
|
||||
public double getMarginBottom(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the left edge of the text frame
|
||||
* and the left edge of the inscribed rectangle of the shape that contains
|
||||
* the text.
|
||||
*
|
||||
* @return the left margin
|
||||
*/
|
||||
public double getMarginLeft(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the right edge of the
|
||||
* text frame and the right edge of the inscribed rectangle of the shape
|
||||
* that contains the text.
|
||||
*
|
||||
* @return the right margin
|
||||
*/
|
||||
public double getMarginRight(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the top of the text frame
|
||||
* and the top of the inscribed rectangle of the shape that contains the text.
|
||||
*
|
||||
* @return the top margin
|
||||
*/
|
||||
public double getMarginTop(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the botom margin.
|
||||
* @see #getMarginBottom()
|
||||
*
|
||||
* @param margin the bottom margin
|
||||
*/
|
||||
public void setMarginBottom(double margin){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(margin == -1) bodyPr.unsetBIns();
|
||||
else bodyPr.setBIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the left margin.
|
||||
* @see #getMarginLeft()
|
||||
*
|
||||
* @param margin the left margin
|
||||
*/
|
||||
public void setMarginLeft(double margin){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(margin == -1) bodyPr.unsetLIns();
|
||||
else bodyPr.setLIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the right margin.
|
||||
* @see #getMarginRight()
|
||||
*
|
||||
* @param margin the right margin
|
||||
*/
|
||||
public void setMarginRight(double margin){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(margin == -1) bodyPr.unsetRIns();
|
||||
else bodyPr.setRIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the top margin.
|
||||
* @see #getMarginTop()
|
||||
*
|
||||
* @param margin the top margin
|
||||
*/
|
||||
public void setMarginTop(double margin){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(margin == -1) bodyPr.unsetTIns();
|
||||
else bodyPr.setTIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value indicating word wrap.
|
||||
* One of the <code>Wrap*</code> constants defined in this class.
|
||||
*
|
||||
* @return the value indicating word wrap
|
||||
*/
|
||||
public boolean getWordWrap(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
return shape.getTxBody().getBodyPr().getWrap() == STTextWrappingType.SQUARE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how the text should be wrapped
|
||||
*
|
||||
* @param wrap the value indicating how the text should be wrapped
|
||||
*/
|
||||
public void setWordWrap(boolean wrap){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
shape.getTxBody().getBodyPr().setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Specifies that a shape should be auto-fit to fully contain the text described within it.
|
||||
* Auto-fitting is when text within a shape is scaled in order to contain all the text inside
|
||||
*
|
||||
* @param value type of autofit
|
||||
*/
|
||||
public void setTextAutofit(TextAutofit value){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit();
|
||||
if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit();
|
||||
if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit();
|
||||
|
||||
switch(value){
|
||||
case NONE: bodyPr.addNewNoAutofit(); break;
|
||||
case NORMAL: bodyPr.addNewNormAutofit(); break;
|
||||
case SHAPE: bodyPr.addNewSpAutoFit(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return type of autofit
|
||||
*/
|
||||
public TextAutofit getTextAutofit(){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (shape.isSetTxBody()) {
|
||||
CTTextBodyProperties bodyPr = shape.getTxBody().getBodyPr();
|
||||
if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE;
|
||||
else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL;
|
||||
else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE;
|
||||
}
|
||||
return TextAutofit.NORMAL;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void onCopy(XSLFSheet srcSheet){
|
||||
CTShape shape = (CTShape) getXmlObject();
|
||||
if (!shape.isSetTxBody()) return;
|
||||
|
||||
CTPlaceholder ph = shape.getNvSpPr().getNvPr().getPh();
|
||||
if(ph == null || !ph.isSetType()) return;
|
||||
|
||||
if(ph.getType() == STPlaceholderType.TITLE){
|
||||
|
||||
CTTextBody txBody = shape.getTxBody();
|
||||
if (txBody == null && create) {
|
||||
txBody = shape.addNewTxBody();
|
||||
txBody.addNewBodyPr();
|
||||
txBody.addNewLstStyle();
|
||||
}
|
||||
return txBody;
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@ -97,4 +98,12 @@ public class XSLFDrawing {
|
||||
shape.setAnchor(new Rectangle());
|
||||
return shape;
|
||||
}
|
||||
|
||||
public XSLFTable createTable(){
|
||||
CTGraphicalObjectFrame obj = _spTree.addNewGraphicFrame();
|
||||
obj.set(XSLFTable.prototype(_shapeId++));
|
||||
XSLFTable shape = new XSLFTable(obj, _sheet);
|
||||
shape.setAnchor(new Rectangle());
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,10 @@ public class XSLFGraphicFrame extends XSLFShape {
|
||||
return _shape;
|
||||
}
|
||||
|
||||
public XSLFSheet getSheet(){
|
||||
return _sheet;
|
||||
}
|
||||
|
||||
public int getShapeType(){
|
||||
throw new RuntimeException("NotImplemented");
|
||||
}
|
||||
@ -64,16 +68,14 @@ public class XSLFGraphicFrame extends XSLFShape {
|
||||
throw new RuntimeException("NotImplemented");
|
||||
}
|
||||
|
||||
public ShapeGroup getParent(){
|
||||
throw new RuntimeException("NotImplemented");
|
||||
|
||||
static XSLFGraphicFrame create(CTGraphicalObjectFrame shape, XSLFSheet sheet){
|
||||
String uri = shape.getGraphic().getGraphicData().getUri();
|
||||
if(XSLFTable.TABLE_URI.equals(uri)){
|
||||
return new XSLFTable(shape, sheet);
|
||||
} else {
|
||||
return new XSLFGraphicFrame(shape, sheet);
|
||||
}
|
||||
}
|
||||
|
||||
public Shape[] getShapes(){
|
||||
throw new RuntimeException("NotImplemented");
|
||||
}
|
||||
|
||||
|
||||
public boolean removeShape(Shape shape){
|
||||
throw new RuntimeException("NotImplemented");
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class XSLFHyperlink {
|
||||
final XSLFTextRun _r;
|
||||
final CTHyperlink _link;
|
||||
|
||||
XSLFHyperlink(CTHyperlink link, XSLFTextRun r){
|
||||
_r = r;
|
||||
_link = link;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public CTHyperlink getXmlObject(){
|
||||
return _link;
|
||||
}
|
||||
|
||||
public void setAddress(String address){
|
||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
||||
PackageRelationship rel =
|
||||
sheet.getPackagePart().
|
||||
addExternalRelationship(address, XSLFRelation.HYPERLINK.getRelation());
|
||||
_link.setId(rel.getId());
|
||||
|
||||
}
|
||||
|
||||
public void setAddress(XSLFSlide slide){
|
||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
||||
PackageRelationship rel =
|
||||
sheet.getPackagePart().
|
||||
addRelationship(slide.getPackagePart().getPartName(),
|
||||
TargetMode.INTERNAL,
|
||||
XSLFRelation.SLIDE.getRelation());
|
||||
_link.setId(rel.getId());
|
||||
_link.setAction("ppaction://hlinksldjump");
|
||||
}
|
||||
|
||||
@Internal
|
||||
public URI getTargetURI(){
|
||||
XSLFSheet sheet = _r.getParentParagraph().getParentShape().getSheet();
|
||||
String id = _link.getId();
|
||||
return sheet.getPackagePart().getRelationship(id).getTargetURI();
|
||||
}
|
||||
}
|
@ -103,6 +103,13 @@ public class XSLFRelation extends POIXMLRelation {
|
||||
null, null
|
||||
);
|
||||
|
||||
public static final XSLFRelation HYPERLINK = new XSLFRelation(
|
||||
null,
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
public static final XSLFRelation THEME = new XSLFRelation(
|
||||
"application/vnd.openxmlformats-officedocument.theme+xml",
|
||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
|
||||
|
@ -41,8 +41,4 @@ public abstract class XSLFShape {
|
||||
public abstract String getShapeName();
|
||||
|
||||
public abstract int getShapeId();
|
||||
|
||||
void onCopy(XSLFSheet srcSheet){
|
||||
|
||||
}
|
||||
}
|
@ -70,7 +70,8 @@ public abstract class XSLFSheet extends POIXMLDocumentPart {
|
||||
} else if (ch instanceof CTPicture){
|
||||
shapes.add(new XSLFPictureShape((CTPicture)ch, this));
|
||||
} else if (ch instanceof CTGraphicalObjectFrame){
|
||||
shapes.add(new XSLFGraphicFrame((CTGraphicalObjectFrame)ch, this));
|
||||
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, this);
|
||||
shapes.add(shape);
|
||||
}
|
||||
}
|
||||
return shapes;
|
||||
@ -147,6 +148,13 @@ public abstract class XSLFSheet extends POIXMLDocumentPart {
|
||||
return sh;
|
||||
}
|
||||
|
||||
public XSLFTable createTable(){
|
||||
List<XSLFShape> shapes = getShapeList();
|
||||
XSLFTable sh = getDrawing().createTable();
|
||||
shapes.add(sh);
|
||||
return sh;
|
||||
}
|
||||
|
||||
public XSLFShape[] getShapes(){
|
||||
return getShapeList().toArray(new XSLFShape[_shapes.size()]);
|
||||
}
|
||||
|
157
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java
Normal file
157
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.Units;
|
||||
import org.apache.xmlbeans.XmlCursor;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupTransform2D;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* Represents a table in a .pptx presentation
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow> {
|
||||
static String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
|
||||
|
||||
private CTTable _table;
|
||||
private List<XSLFTableRow> _rows;
|
||||
|
||||
/*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){
|
||||
super(shape, sheet);
|
||||
|
||||
for(XmlObject obj : shape.getGraphic().getGraphicData().selectPath("*")){
|
||||
if(obj instanceof CTTable){
|
||||
_table = (CTTable)obj;
|
||||
}
|
||||
}
|
||||
if(_table == null) throw new IllegalStateException("CTTable element was not found");
|
||||
|
||||
_rows = new ArrayList<XSLFTableRow>(_table.sizeOfTrArray());
|
||||
for(CTTableRow row : _table.getTrList()) _rows.add(new XSLFTableRow(row, this));
|
||||
}
|
||||
|
||||
@Internal
|
||||
public CTTable getCTTable(){
|
||||
return _table;
|
||||
}
|
||||
|
||||
public int getNumberOfColumns() {
|
||||
return _table.getTblGrid().sizeOfGridColArray();
|
||||
}
|
||||
|
||||
public int getNumberOfRows() {
|
||||
return _table.sizeOfTrArray();
|
||||
}
|
||||
|
||||
public double getColumnWidth(int idx){
|
||||
return Units.toPoints(
|
||||
_table.getTblGrid().getGridColArray(idx).getW());
|
||||
}
|
||||
|
||||
public void setColumnWidth(int idx, double width){
|
||||
_table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width));
|
||||
}
|
||||
|
||||
public Iterator<XSLFTableRow> iterator(){
|
||||
return _rows.iterator();
|
||||
}
|
||||
|
||||
public List<XSLFTableRow> getRows(){
|
||||
return Collections.unmodifiableList(_rows);
|
||||
}
|
||||
|
||||
public XSLFTableRow addRow(){
|
||||
CTTableRow tr = _table.addNewTr();
|
||||
XSLFTableRow row = new XSLFTableRow(tr, this);
|
||||
row.setHeight(20.0); // default height is 20 points
|
||||
_rows.add(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
static CTGraphicalObjectFrame prototype(int shapeId){
|
||||
CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance();
|
||||
CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr();
|
||||
|
||||
CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr();
|
||||
cnv.setName("Table " + shapeId);
|
||||
cnv.setId(shapeId + 1);
|
||||
nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true);
|
||||
nvGr.addNewNvPr();
|
||||
|
||||
frame.addNewXfrm();
|
||||
CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();
|
||||
XmlCursor cursor = gr.newCursor();
|
||||
cursor.toNextToken();
|
||||
cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tbl"));
|
||||
cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblPr"));
|
||||
cursor.toNextToken();
|
||||
cursor.beginElement(new QName("http://schemas.openxmlformats.org/drawingml/2006/main", "tblGrid"));
|
||||
cursor.dispose();
|
||||
gr.setUri(TABLE_URI);
|
||||
return frame;
|
||||
}
|
||||
|
||||
public Rectangle2D getAnchor(){
|
||||
CTTransform2D xfrm = getXmlObject().getXfrm();
|
||||
CTPoint2D off = xfrm.getOff();
|
||||
long x = off.getX();
|
||||
long y = off.getY();
|
||||
CTPositiveSize2D ext = xfrm.getExt();
|
||||
long cx = ext.getCx();
|
||||
long cy = ext.getCy();
|
||||
return new Rectangle2D.Double(
|
||||
Units.toPoints(x), Units.toPoints(y),
|
||||
Units.toPoints(cx), Units.toPoints(cy));
|
||||
}
|
||||
|
||||
public void setAnchor(Rectangle2D anchor){
|
||||
CTTransform2D xfrm = getXmlObject().getXfrm();
|
||||
CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
|
||||
long x = Units.toEMU(anchor.getX());
|
||||
long y = Units.toEMU(anchor.getY());
|
||||
off.setX(x);
|
||||
off.setY(y);
|
||||
CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm.addNewExt();
|
||||
long cx = Units.toEMU(anchor.getWidth());
|
||||
long cy = Units.toEMU(anchor.getHeight());
|
||||
ext.setCx(cx);
|
||||
ext.setCy(cy);
|
||||
}
|
||||
|
||||
}
|
290
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java
Normal file
290
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTableCell.java
Normal file
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCellProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPenAlignment;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.Units;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Represents a cell of a table in a .pptx presentation
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class XSLFTableCell extends XSLFTextShape {
|
||||
static double defaultBorderWidth = 1.0;
|
||||
|
||||
/*package*/ XSLFTableCell(CTTableCell cell, XSLFSheet sheet){
|
||||
super(cell, sheet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CTTableCell getXmlObject(){
|
||||
return (CTTableCell)super.getXmlObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CTTextBody getTextBody(boolean create){
|
||||
CTTableCell cell = getXmlObject();
|
||||
CTTextBody txBody = cell.getTxBody();
|
||||
if (txBody == null && create) {
|
||||
txBody = cell.addNewTxBody();
|
||||
txBody.addNewBodyPr();
|
||||
txBody.addNewLstStyle();
|
||||
}
|
||||
return txBody;
|
||||
}
|
||||
|
||||
static CTTableCell prototype() {
|
||||
CTTableCell cell = CTTableCell.Factory.newInstance();
|
||||
CTTableCellProperties pr = cell.addNewTcPr();
|
||||
pr.addNewLnL().addNewNoFill();
|
||||
pr.addNewLnR().addNewNoFill();
|
||||
pr.addNewLnT().addNewNoFill();
|
||||
pr.addNewLnB().addNewNoFill();
|
||||
return cell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarginLeft(double margin){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
if(pr == null) pr = getXmlObject().addNewTcPr();
|
||||
|
||||
pr.setMarL(Units.toEMU(margin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarginRight(double margin){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
if(pr == null) pr = getXmlObject().addNewTcPr();
|
||||
|
||||
pr.setMarR(Units.toEMU(margin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarginTop(double margin){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
if(pr == null) pr = getXmlObject().addNewTcPr();
|
||||
|
||||
pr.setMarT(Units.toEMU(margin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMarginBottom(double margin){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
if(pr == null) pr = getXmlObject().addNewTcPr();
|
||||
|
||||
pr.setMarB(Units.toEMU(margin));
|
||||
}
|
||||
|
||||
public void setBorderLeft(double width){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL();
|
||||
ln.setW(Units.toEMU(width));
|
||||
}
|
||||
|
||||
public double getBorderLeft(){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.getLnL();
|
||||
return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());
|
||||
}
|
||||
|
||||
public void setBorderLeftColor(Color color){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
CTLineProperties ln = pr.isSetLnL() ? pr.getLnL() : pr.addNewLnL();
|
||||
setLineColor(ln, color);
|
||||
}
|
||||
|
||||
public Color getBorderLeftColor(){
|
||||
return getLineColor(getXmlObject().getTcPr().getLnL());
|
||||
}
|
||||
|
||||
public void setBorderRight(double width){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR();
|
||||
ln.setW(Units.toEMU(width));
|
||||
}
|
||||
|
||||
public double getBorderRight(){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.getLnR();
|
||||
return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());
|
||||
}
|
||||
|
||||
public void setBorderRightColor(Color color){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
CTLineProperties ln = pr.isSetLnR() ? pr.getLnR() : pr.addNewLnR();
|
||||
setLineColor(ln, color);
|
||||
}
|
||||
|
||||
public Color getBorderRightColor(){
|
||||
return getLineColor(getXmlObject().getTcPr().getLnR());
|
||||
}
|
||||
|
||||
public void setBorderTop(double width){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT();
|
||||
ln.setW(Units.toEMU(width));
|
||||
}
|
||||
|
||||
public double getBorderTop(){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.getLnT();
|
||||
return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());
|
||||
}
|
||||
|
||||
public void setBorderTopColor(Color color){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
CTLineProperties ln = pr.isSetLnT() ? pr.getLnT() : pr.addNewLnT();
|
||||
setLineColor(ln, color);
|
||||
}
|
||||
|
||||
public Color getBorderTopColor(){
|
||||
return getLineColor(getXmlObject().getTcPr().getLnT());
|
||||
}
|
||||
|
||||
public void setBorderBottom(double width){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB();
|
||||
ln.setW(Units.toEMU(width));
|
||||
}
|
||||
|
||||
public double getBorderBottom(){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
|
||||
CTLineProperties ln = pr.getLnB();
|
||||
return ln == null || !ln.isSetW() ? defaultBorderWidth : Units.toPoints(ln.getW());
|
||||
}
|
||||
|
||||
public void setBorderBottomColor(Color color){
|
||||
CTTableCellProperties pr = getXmlObject().getTcPr();
|
||||
CTLineProperties ln = pr.isSetLnB() ? pr.getLnB() : pr.addNewLnB();
|
||||
setLineColor(ln, color);
|
||||
}
|
||||
|
||||
public Color getBorderBottomColor(){
|
||||
return getLineColor(getXmlObject().getTcPr().getLnB());
|
||||
}
|
||||
|
||||
private void setLineColor(CTLineProperties ln, Color color){
|
||||
if(color == null){
|
||||
ln.addNewNoFill();
|
||||
if(ln.isSetSolidFill()) ln.unsetSolidFill();
|
||||
} else {
|
||||
if(ln.isSetNoFill()) ln.unsetNoFill();
|
||||
|
||||
if(!ln.isSetPrstDash()) ln.addNewPrstDash().setVal(STPresetLineDashVal.SOLID);
|
||||
ln.setCmpd(STCompoundLine.SNG);
|
||||
ln.setAlgn(STPenAlignment.CTR);
|
||||
ln.setCap(STLineCap.FLAT);
|
||||
ln.addNewRound();
|
||||
|
||||
CTLineEndProperties hd = ln.addNewHeadEnd();
|
||||
hd.setType(STLineEndType.NONE);
|
||||
hd.setW(STLineEndWidth.MED);
|
||||
hd.setLen(STLineEndLength.MED);
|
||||
|
||||
CTLineEndProperties tl = ln.addNewTailEnd();
|
||||
tl.setType(STLineEndType.NONE);
|
||||
tl.setW(STLineEndWidth.MED);
|
||||
tl.setLen(STLineEndLength.MED);
|
||||
|
||||
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
|
||||
rgb.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});
|
||||
ln.addNewSolidFill().setSrgbClr(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
private Color getLineColor(CTLineProperties ln){
|
||||
if(ln == null || ln.isSetNoFill() || !ln.isSetSolidFill()) return null;
|
||||
|
||||
CTSolidColorFillProperties fill = ln.getSolidFill();
|
||||
if(!fill.isSetSrgbClr()) {
|
||||
// TODO for now return null for all colors except explicit RGB
|
||||
return null;
|
||||
}
|
||||
byte[] val = fill.getSrgbClr().getVal();
|
||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
||||
}
|
||||
/**
|
||||
* Specifies a solid color fill. The shape is filled entirely with the specified color.
|
||||
*
|
||||
* @param color the solid color fill.
|
||||
* The value of <code>null</code> unsets the solidFIll attribute from the underlying xml
|
||||
*/
|
||||
@Override
|
||||
public void setFillColor(Color color) {
|
||||
CTTableCellProperties spPr = getXmlObject().getTcPr();
|
||||
if (color == null) {
|
||||
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
|
||||
}
|
||||
else {
|
||||
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
|
||||
|
||||
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
|
||||
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
|
||||
|
||||
fill.setSrgbClr(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return solid fill color of null if not set
|
||||
*/
|
||||
@Override
|
||||
public Color getFillColor(){
|
||||
CTTableCellProperties spPr = getXmlObject().getTcPr();
|
||||
if(!spPr.isSetSolidFill() ) return null;
|
||||
|
||||
CTSolidColorFillProperties fill = spPr.getSolidFill();
|
||||
if(!fill.isSetSrgbClr()) {
|
||||
// TODO for now return null for all colors except explicit RGB
|
||||
return null;
|
||||
}
|
||||
byte[] val = fill.getSrgbClr().getVal();
|
||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.util.Units;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Represents a table in a .pptx presentation
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class XSLFTableRow implements Iterable<XSLFTableCell> {
|
||||
private CTTableRow _row;
|
||||
private List<XSLFTableCell> _cells;
|
||||
private XSLFTable _table;
|
||||
|
||||
/*package*/ XSLFTableRow(CTTableRow row, XSLFTable table){
|
||||
_row = row;
|
||||
_table = table;
|
||||
_cells = new ArrayList<XSLFTableCell>(_row.sizeOfTcArray());
|
||||
for(CTTableCell cell : _row.getTcList()) {
|
||||
_cells.add(new XSLFTableCell(cell, table.getSheet()));
|
||||
}
|
||||
}
|
||||
|
||||
public CTTableRow getXmlObject(){
|
||||
return _row;
|
||||
}
|
||||
|
||||
public Iterator<XSLFTableCell> iterator(){
|
||||
return _cells.iterator();
|
||||
}
|
||||
|
||||
public List<XSLFTableCell> getCells(){
|
||||
return Collections.unmodifiableList(_cells);
|
||||
}
|
||||
|
||||
public double getHeight(){
|
||||
return Units.toPoints(_row.getH());
|
||||
}
|
||||
|
||||
public void setHeight(double height){
|
||||
_row.setH(Units.toEMU(height));
|
||||
}
|
||||
|
||||
public XSLFTableCell addCell(){
|
||||
CTTableCell c = _row.addNewTc();
|
||||
c.set(XSLFTableCell.prototype());
|
||||
XSLFTableCell cell = new XSLFTableCell(c, _table.getSheet());
|
||||
_cells.add(cell);
|
||||
|
||||
if(_table.getNumberOfColumns() < _row.sizeOfTcArray()) {
|
||||
_table.getCTTable().getTblGrid().addNewGridCol().setW(Units.toEMU(100.0));
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -40,12 +40,14 @@ import java.util.List;
|
||||
public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
||||
private final CTTextParagraph _p;
|
||||
private final List<XSLFTextRun> _runs;
|
||||
private final XSLFTextShape _shape;
|
||||
|
||||
XSLFTextParagraph(CTTextParagraph p){
|
||||
XSLFTextParagraph(CTTextParagraph p, XSLFTextShape shape){
|
||||
_p = p;
|
||||
_runs = new ArrayList<XSLFTextRun>();
|
||||
_shape = shape;
|
||||
for (CTRegularTextRun r : _p.getRList()) {
|
||||
_runs.add(new XSLFTextRun(r));
|
||||
_runs.add(new XSLFTextRun(r, this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +64,10 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
||||
return _p;
|
||||
}
|
||||
|
||||
XSLFTextShape getParentShape() {
|
||||
return _shape;
|
||||
|
||||
}
|
||||
public List<XSLFTextRun> getTextRuns(){
|
||||
return _runs;
|
||||
}
|
||||
@ -72,7 +78,8 @@ public class XSLFTextParagraph implements Iterable<XSLFTextRun>{
|
||||
|
||||
public XSLFTextRun addNewTextRun(){
|
||||
CTRegularTextRun r = _p.addNewR();
|
||||
XSLFTextRun run = new XSLFTextRun(r);
|
||||
r.addNewRPr();
|
||||
XSLFTextRun run = new XSLFTextRun(r, this);
|
||||
_runs.add(run);
|
||||
return run;
|
||||
}
|
||||
|
@ -36,9 +36,15 @@ import java.awt.*;
|
||||
@Beta
|
||||
public class XSLFTextRun {
|
||||
private final CTRegularTextRun _r;
|
||||
private final XSLFTextParagraph _p;
|
||||
|
||||
XSLFTextRun(CTRegularTextRun r){
|
||||
XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
|
||||
_r = r;
|
||||
_p = p;
|
||||
}
|
||||
|
||||
XSLFTextParagraph getParentParagraph(){
|
||||
return _p;
|
||||
}
|
||||
|
||||
public String getText(){
|
||||
@ -78,7 +84,7 @@ public class XSLFTextRun {
|
||||
* @return font size in points or -1 if font size is not set.
|
||||
*/
|
||||
public double getFontSize(){
|
||||
if(!_r.isSetRPr()) return -1;
|
||||
if(!_r.isSetRPr() || !_r.getRPr().isSetSz()) return -1;
|
||||
|
||||
return _r.getRPr().getSz()*0.01;
|
||||
}
|
||||
@ -199,4 +205,15 @@ public class XSLFTextRun {
|
||||
return "[" + getClass() + "]" + getText();
|
||||
}
|
||||
|
||||
public XSLFHyperlink createHyperlink(){
|
||||
XSLFHyperlink link = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), this);
|
||||
return link;
|
||||
}
|
||||
|
||||
public XSLFHyperlink getHyperlink(){
|
||||
if(!_r.getRPr().isSetHlinkClick()) return null;
|
||||
|
||||
|
||||
return new XSLFHyperlink(_r.getRPr().getHlinkClick(), this);
|
||||
}
|
||||
}
|
365
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
Normal file
365
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
Normal file
@ -0,0 +1,365 @@
|
||||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.Units;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraph;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextAnchoringType;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextVerticalType;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.STTextWrappingType;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a shape that can hold text.
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
@Beta
|
||||
public abstract class XSLFTextShape extends XSLFSimpleShape {
|
||||
private final List<XSLFTextParagraph> _paragraphs;
|
||||
|
||||
/*package*/ XSLFTextShape(XmlObject shape, XSLFSheet sheet) {
|
||||
super(shape, sheet);
|
||||
|
||||
_paragraphs = new ArrayList<XSLFTextParagraph>();
|
||||
CTTextBody txBody = getTextBody(false);
|
||||
if (txBody != null) {
|
||||
for (CTTextParagraph p : txBody.getPList()) {
|
||||
_paragraphs.add(new XSLFTextParagraph(p, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// textual properties
|
||||
public String getText() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
for (XSLFTextParagraph p : _paragraphs) {
|
||||
if (out.length() > 0) out.append('\n');
|
||||
out.append(p.getText());
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public List<XSLFTextParagraph> getTextParagraphs() {
|
||||
return _paragraphs;
|
||||
}
|
||||
|
||||
public XSLFTextParagraph addNewTextParagraph() {
|
||||
CTTextBody txBody = getTextBody(true);
|
||||
CTTextParagraph p = txBody.addNewP();
|
||||
XSLFTextParagraph paragraph = new XSLFTextParagraph(p, this);
|
||||
_paragraphs.add(paragraph);
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a solid color fill. The shape is filled entirely with the specified color.
|
||||
*
|
||||
* @param color the solid color fill.
|
||||
* The value of <code>null</code> unsets the solidFIll attribute from the underlying xml
|
||||
*/
|
||||
public void setFillColor(Color color) {
|
||||
CTShapeProperties spPr = getSpPr();
|
||||
if (color == null) {
|
||||
if(spPr.isSetSolidFill()) spPr.unsetSolidFill();
|
||||
}
|
||||
else {
|
||||
CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr.getSolidFill() : spPr.addNewSolidFill();
|
||||
|
||||
CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
|
||||
rgb.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
|
||||
|
||||
fill.setSrgbClr(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return solid fill color of null if not set
|
||||
*/
|
||||
public Color getFillColor(){
|
||||
CTShapeProperties spPr = getSpPr();
|
||||
if(!spPr.isSetSolidFill() ) return null;
|
||||
|
||||
CTSolidColorFillProperties fill = spPr.getSolidFill();
|
||||
if(!fill.isSetSrgbClr()) {
|
||||
// TODO for now return null for all colors except explicit RGB
|
||||
return null;
|
||||
}
|
||||
byte[] val = fill.getSrgbClr().getVal();
|
||||
return new Color(0xFF & val[0], 0xFF & val[1], 0xFF & val[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of vertical alignment for the text.
|
||||
* One of the <code>Anchor*</code> constants defined in this class.
|
||||
*
|
||||
* @param anchor - the type of alignment. Default is {@link org.apache.poi.xslf.usermodel.VerticalAlignment#TOP}
|
||||
*/
|
||||
public void setVerticalAlignment(VerticalAlignment anchor){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(anchor == null) {
|
||||
if(bodyPr.isSetAnchor()) bodyPr.unsetAnchor();
|
||||
} else {
|
||||
bodyPr.setAnchor(STTextAnchoringType.Enum.forInt(anchor.ordinal() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of vertical alignment for the text.
|
||||
*
|
||||
* @return the type of alignment
|
||||
*/
|
||||
public VerticalAlignment getVerticalAlignment(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
STTextAnchoringType.Enum val = bodyPr.getAnchor();
|
||||
if(val != null){
|
||||
return VerticalAlignment.values()[val.intValue() - 1];
|
||||
}
|
||||
}
|
||||
return VerticalAlignment.TOP;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param orientation vertical orientation of the text
|
||||
*/
|
||||
public void setTextDirection(TextDirection orientation){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(orientation == null) {
|
||||
if(bodyPr.isSetVert()) bodyPr.unsetVert();
|
||||
} else {
|
||||
bodyPr.setVert(STTextVerticalType.Enum.forInt(orientation.ordinal() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return vertical orientation of the text
|
||||
*/
|
||||
public TextDirection getTextDirection(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
STTextVerticalType.Enum val = bodyPr.getVert();
|
||||
if(val != null){
|
||||
return TextDirection.values()[val.intValue() - 1];
|
||||
}
|
||||
}
|
||||
return TextDirection.HORIZONTAL;
|
||||
}
|
||||
/**
|
||||
* Returns the distance (in points) between the bottom of the text frame
|
||||
* and the bottom of the inscribed rectangle of the shape that contains the text.
|
||||
*
|
||||
* @return the bottom margin or -1 if not set
|
||||
*/
|
||||
public double getMarginBottom(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
return bodyPr.isSetBIns() ? Units.toPoints(bodyPr.getBIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the left edge of the text frame
|
||||
* and the left edge of the inscribed rectangle of the shape that contains
|
||||
* the text.
|
||||
*
|
||||
* @return the left margin
|
||||
*/
|
||||
public double getMarginLeft(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
return bodyPr.isSetLIns() ? Units.toPoints(bodyPr.getLIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the right edge of the
|
||||
* text frame and the right edge of the inscribed rectangle of the shape
|
||||
* that contains the text.
|
||||
*
|
||||
* @return the right margin
|
||||
*/
|
||||
public double getMarginRight(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
return bodyPr.isSetRIns() ? Units.toPoints(bodyPr.getRIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance (in points) between the top of the text frame
|
||||
* and the top of the inscribed rectangle of the shape that contains the text.
|
||||
*
|
||||
* @return the top margin
|
||||
*/
|
||||
public double getMarginTop(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
return bodyPr.isSetTIns() ? Units.toPoints(bodyPr.getTIns()) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the botom margin.
|
||||
* @see #getMarginBottom()
|
||||
*
|
||||
* @param margin the bottom margin
|
||||
*/
|
||||
public void setMarginBottom(double margin){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(margin == -1) bodyPr.unsetBIns();
|
||||
else bodyPr.setBIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the left margin.
|
||||
* @see #getMarginLeft()
|
||||
*
|
||||
* @param margin the left margin
|
||||
*/
|
||||
public void setMarginLeft(double margin){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(margin == -1) bodyPr.unsetLIns();
|
||||
else bodyPr.setLIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the right margin.
|
||||
* @see #getMarginRight()
|
||||
*
|
||||
* @param margin the right margin
|
||||
*/
|
||||
public void setMarginRight(double margin){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(margin == -1) bodyPr.unsetRIns();
|
||||
else bodyPr.setRIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the top margin.
|
||||
* @see #getMarginTop()
|
||||
*
|
||||
* @param margin the top margin
|
||||
*/
|
||||
public void setMarginTop(double margin){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(margin == -1) bodyPr.unsetTIns();
|
||||
else bodyPr.setTIns(Units.toEMU(margin));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value indicating word wrap.
|
||||
* One of the <code>Wrap*</code> constants defined in this class.
|
||||
*
|
||||
* @return the value indicating word wrap
|
||||
*/
|
||||
public boolean getWordWrap(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
return bodyPr.getWrap() == STTextWrappingType.SQUARE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies how the text should be wrapped
|
||||
*
|
||||
* @param wrap the value indicating how the text should be wrapped
|
||||
*/
|
||||
public void setWordWrap(boolean wrap){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
bodyPr.setWrap(wrap ? STTextWrappingType.SQUARE : STTextWrappingType.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Specifies that a shape should be auto-fit to fully contain the text described within it.
|
||||
* Auto-fitting is when text within a shape is scaled in order to contain all the text inside
|
||||
*
|
||||
* @param value type of autofit
|
||||
*/
|
||||
public void setTextAutofit(TextAutofit value){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(bodyPr.isSetSpAutoFit()) bodyPr.unsetSpAutoFit();
|
||||
if(bodyPr.isSetNoAutofit()) bodyPr.unsetNoAutofit();
|
||||
if(bodyPr.isSetNormAutofit()) bodyPr.unsetNormAutofit();
|
||||
|
||||
switch(value){
|
||||
case NONE: bodyPr.addNewNoAutofit(); break;
|
||||
case NORMAL: bodyPr.addNewNormAutofit(); break;
|
||||
case SHAPE: bodyPr.addNewSpAutoFit(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return type of autofit
|
||||
*/
|
||||
public TextAutofit getTextAutofit(){
|
||||
CTTextBodyProperties bodyPr = getTextBodyPr();
|
||||
if (bodyPr != null) {
|
||||
if(bodyPr.isSetNoAutofit()) return TextAutofit.NONE;
|
||||
else if (bodyPr.isSetNormAutofit()) return TextAutofit.NORMAL;
|
||||
else if (bodyPr.isSetSpAutoFit()) return TextAutofit.SHAPE;
|
||||
}
|
||||
return TextAutofit.NORMAL;
|
||||
}
|
||||
|
||||
protected CTTextBodyProperties getTextBodyPr(){
|
||||
CTTextBody textBody = getTextBody(false);
|
||||
return textBody == null ? null : textBody.getBodyPr();
|
||||
}
|
||||
|
||||
|
||||
protected abstract CTTextBody getTextBody(boolean create);
|
||||
}
|
@ -210,7 +210,7 @@ public class TestXSLFAutoShape extends TestCase {
|
||||
assertSame(r, p.getTextRuns().get(0));
|
||||
|
||||
assertEquals(-1.0, r.getFontSize());
|
||||
assertFalse(r.getXmlObject().isSetRPr());
|
||||
assertFalse(r.getXmlObject().getRPr().isSetSz());
|
||||
r.setFontSize(10.0);
|
||||
assertTrue(r.getXmlObject().isSetRPr());
|
||||
assertEquals(1000, r.getXmlObject().getRPr().getSz());
|
||||
|
@ -0,0 +1,102 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||
import org.apache.poi.xssf.usermodel.XSSFTable;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||
import org.apache.poi.openxml4j.opc.TargetMode;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestXSLFHyperlink extends TestCase {
|
||||
|
||||
public void testRead(){
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
|
||||
|
||||
XSLFSlide slide = ppt.getSlides()[4];
|
||||
XSLFShape[] shapes = slide.getShapes();
|
||||
XSLFTable tbl = (XSLFTable)shapes[0];
|
||||
XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0);
|
||||
assertEquals("Web Page", cell1.getText());
|
||||
XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||
assertNotNull(link1);
|
||||
assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());
|
||||
|
||||
XSLFTableCell cell2 = tbl.getRows().get(2).getCells().get(0);
|
||||
assertEquals("Place in this document", cell2.getText());
|
||||
XSLFHyperlink link2 = cell2.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||
assertNotNull(link2);
|
||||
assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());
|
||||
|
||||
XSLFTableCell cell3 = tbl.getRows().get(3).getCells().get(0);
|
||||
assertEquals("Email", cell3.getText());
|
||||
XSLFHyperlink link3 = cell3.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();
|
||||
assertNotNull(link3);
|
||||
assertEquals(URI.create("mailto:dev@poi.apache.org?subject=Hi%20There"), link3.getTargetURI());
|
||||
}
|
||||
|
||||
public void testCreate() throws Exception {
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
XSLFSlide slide1 = ppt.createSlide();
|
||||
XSLFSlide slide2 = ppt.createSlide();
|
||||
|
||||
int numRel = slide1.getPackagePart().getRelationships().size();
|
||||
assertEquals(1, numRel);
|
||||
XSLFTextBox sh1 = slide1.createTextBox();
|
||||
XSLFTextRun r1 = sh1.addNewTextParagraph().addNewTextRun();
|
||||
r1.setText("Web Page");
|
||||
XSLFHyperlink link1 = r1.createHyperlink();
|
||||
link1.setAddress("http://poi.apache.org/");
|
||||
assertEquals(URI.create("http://poi.apache.org/"), link1.getTargetURI());
|
||||
assertEquals(numRel + 1, slide1.getPackagePart().getRelationships().size());
|
||||
|
||||
String id1 = link1.getXmlObject().getId();
|
||||
assertNotNull(id1);
|
||||
PackageRelationship rel1 = slide1.getPackagePart().getRelationship(id1);
|
||||
assertNotNull(rel1);
|
||||
assertEquals(id1, rel1.getId());
|
||||
assertEquals(TargetMode.EXTERNAL, rel1.getTargetMode());
|
||||
assertEquals(XSLFRelation.HYPERLINK.getRelation(), rel1.getRelationshipType());
|
||||
|
||||
XSLFTextBox sh2 = slide1.createTextBox();
|
||||
XSLFTextRun r2 = sh2.addNewTextParagraph().addNewTextRun();
|
||||
r2.setText("Place in this document");
|
||||
XSLFHyperlink link2 = r2.createHyperlink();
|
||||
link2.setAddress(slide2);
|
||||
assertEquals(URI.create("/ppt/slides/slide2.xml"), link2.getTargetURI());
|
||||
assertEquals(numRel + 2, slide1.getPackagePart().getRelationships().size());
|
||||
|
||||
String id2 = link2.getXmlObject().getId();
|
||||
assertNotNull(id2);
|
||||
PackageRelationship rel2 = slide1.getPackagePart().getRelationship(id2);
|
||||
assertNotNull(rel2);
|
||||
assertEquals(id2, rel2.getId());
|
||||
assertEquals(TargetMode.INTERNAL, rel2.getTargetMode());
|
||||
assertEquals(XSLFRelation.SLIDE.getRelation(), rel2.getRelationshipType());
|
||||
}
|
||||
}
|
@ -31,7 +31,6 @@ public class TestXSLFShape extends TestCase {
|
||||
public void testReadTextShapes() {
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
|
||||
XSLFSlide[] slides = ppt.getSlides();
|
||||
assertEquals(3, slides.length);
|
||||
|
||||
XSLFSlide slide1 = slides[0];
|
||||
XSLFShape[] shapes1 = slide1.getShapes();
|
||||
|
@ -30,7 +30,6 @@ public class TestXSLFSlide extends TestCase {
|
||||
public void testReadShapes(){
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
|
||||
XSLFSlide[] slides = ppt.getSlides();
|
||||
assertEquals(3, slides.length);
|
||||
|
||||
XSLFSlide slide1 = slides[0];
|
||||
XSLFShape[] shapes1 = slide1.getShapes();
|
||||
@ -85,6 +84,14 @@ public class TestXSLFSlide extends TestCase {
|
||||
|
||||
assertTrue(groupShapes[2] instanceof XSLFAutoShape);
|
||||
assertEquals("Right Arrow 3", groupShapes[2].getShapeName());
|
||||
|
||||
XSLFSlide slide4 = slides[3];
|
||||
XSLFShape[] shapes4 = slide4.getShapes();
|
||||
assertEquals(1, shapes4.length);
|
||||
assertTrue(shapes4[0] instanceof XSLFTable);
|
||||
XSLFTable tbl = (XSLFTable)shapes4[0];
|
||||
assertEquals(3, tbl.getNumberOfColumns());
|
||||
assertEquals(6, tbl.getNumberOfRows());
|
||||
}
|
||||
|
||||
public void testCreateSlide(){
|
||||
|
@ -0,0 +1,150 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
package org.apache.poi.xslf.usermodel;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.xslf.XSLFTestDataSamples;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
|
||||
|
||||
/**
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class TestXSLFTable extends TestCase {
|
||||
|
||||
public void testRead(){
|
||||
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
|
||||
|
||||
XSLFSlide slide = ppt.getSlides()[3];
|
||||
XSLFShape[] shapes = slide.getShapes();
|
||||
assertEquals(1, shapes.length);
|
||||
assertTrue(shapes[0] instanceof XSLFTable);
|
||||
XSLFTable tbl = (XSLFTable)shapes[0];
|
||||
assertEquals(3, tbl.getNumberOfColumns());
|
||||
assertEquals(6, tbl.getNumberOfRows());
|
||||
assertNotNull(tbl.getCTTable());
|
||||
|
||||
List<XSLFTableRow> rows = tbl.getRows();
|
||||
assertEquals(6, rows.size());
|
||||
|
||||
assertEquals(90.0, tbl.getColumnWidth(0));
|
||||
assertEquals(240.0, tbl.getColumnWidth(1));
|
||||
assertEquals(150.0, tbl.getColumnWidth(2));
|
||||
|
||||
for(XSLFTableRow row : tbl){
|
||||
// all rows have the same height
|
||||
assertEquals(29.2, row.getHeight());
|
||||
}
|
||||
|
||||
XSLFTableRow row0 = rows.get(0);
|
||||
List<XSLFTableCell> cells0 = row0.getCells();
|
||||
assertEquals(3, cells0.size());
|
||||
assertEquals("header1", cells0.get(0).getText());
|
||||
assertEquals("header2", cells0.get(1).getText());
|
||||
assertEquals("header3", cells0.get(2).getText());
|
||||
|
||||
XSLFTableRow row1 = rows.get(1);
|
||||
List<XSLFTableCell> cells1 = row1.getCells();
|
||||
assertEquals(3, cells1.size());
|
||||
assertEquals("A1", cells1.get(0).getText());
|
||||
assertEquals("B1", cells1.get(1).getText());
|
||||
assertEquals("C1", cells1.get(2).getText());
|
||||
}
|
||||
|
||||
public void testCreate() {
|
||||
XMLSlideShow ppt = new XMLSlideShow();
|
||||
XSLFSlide slide = ppt.createSlide();
|
||||
|
||||
XSLFTable tbl = slide.createTable();
|
||||
assertNotNull(tbl.getCTTable());
|
||||
assertNotNull(tbl.getCTTable().getTblGrid());
|
||||
assertNotNull(tbl.getCTTable().getTblPr());
|
||||
assertTrue(tbl.getXmlObject() instanceof CTGraphicalObjectFrame);
|
||||
assertEquals("Table 1", tbl.getShapeName());
|
||||
assertEquals(2, tbl.getShapeId());
|
||||
assertEquals(0, tbl.getRows().size());
|
||||
assertEquals(0, tbl.getCTTable().sizeOfTrArray());
|
||||
assertEquals(0, tbl.getCTTable().getTblGrid().sizeOfGridColArray());
|
||||
|
||||
assertEquals(0, tbl.getNumberOfColumns());
|
||||
assertEquals(0, tbl.getNumberOfRows());
|
||||
|
||||
XSLFTableRow row0 = tbl.addRow();
|
||||
assertNotNull(row0.getXmlObject());
|
||||
assertEquals(1, tbl.getNumberOfRows());
|
||||
assertSame(row0, tbl.getRows().get(0));
|
||||
assertEquals(20.0, row0.getHeight());
|
||||
row0.setHeight(30.0);
|
||||
assertEquals(30.0, row0.getHeight());
|
||||
|
||||
assertEquals(0, row0.getCells().size());
|
||||
XSLFTableCell cell0 = row0.addCell();
|
||||
assertNotNull(cell0.getXmlObject());
|
||||
// by default table cell has no borders
|
||||
assertTrue(cell0.getXmlObject().getTcPr().getLnB().isSetNoFill());
|
||||
assertTrue(cell0.getXmlObject().getTcPr().getLnT().isSetNoFill());
|
||||
assertTrue(cell0.getXmlObject().getTcPr().getLnL().isSetNoFill());
|
||||
assertTrue(cell0.getXmlObject().getTcPr().getLnR().isSetNoFill());
|
||||
|
||||
assertSame(cell0, row0.getCells().get(0));
|
||||
assertEquals(1, tbl.getNumberOfColumns());
|
||||
assertEquals(100.0, tbl.getColumnWidth(0));
|
||||
cell0.addNewTextParagraph().addNewTextRun().setText("POI");
|
||||
assertEquals("POI", cell0.getText());
|
||||
|
||||
XSLFTableCell cell1 = row0.addCell();
|
||||
assertSame(cell1, row0.getCells().get(1));
|
||||
assertEquals(2, tbl.getNumberOfColumns());
|
||||
assertEquals(100.0, tbl.getColumnWidth(1));
|
||||
cell1.addNewTextParagraph().addNewTextRun().setText("Apache");
|
||||
assertEquals("Apache", cell1.getText());
|
||||
|
||||
assertEquals(1.0, cell1.getBorderBottom());
|
||||
cell1.setBorderBottom(2.0);
|
||||
assertEquals(2.0, cell1.getBorderBottom());
|
||||
assertNull(cell1.getBorderBottomColor());
|
||||
cell1.setBorderBottomColor(Color.yellow);
|
||||
assertEquals(Color.yellow, cell1.getBorderBottomColor());
|
||||
|
||||
assertEquals(1.0, cell1.getBorderTop());
|
||||
cell1.setBorderTop(2.0);
|
||||
assertEquals(2.0, cell1.getBorderTop());
|
||||
assertNull(cell1.getBorderTopColor());
|
||||
cell1.setBorderTopColor(Color.yellow);
|
||||
assertEquals(Color.yellow, cell1.getBorderTopColor());
|
||||
|
||||
assertEquals(1.0, cell1.getBorderLeft());
|
||||
cell1.setBorderLeft(2.0);
|
||||
assertEquals(2.0, cell1.getBorderLeft());
|
||||
assertNull(cell1.getBorderLeftColor());
|
||||
cell1.setBorderLeftColor(Color.yellow);
|
||||
assertEquals(Color.yellow, cell1.getBorderLeftColor());
|
||||
|
||||
assertEquals(1.0, cell1.getBorderRight());
|
||||
cell1.setBorderRight(2.0);
|
||||
assertEquals(2.0, cell1.getBorderRight());
|
||||
assertNull(cell1.getBorderRightColor());
|
||||
cell1.setBorderRightColor(Color.yellow);
|
||||
assertEquals(Color.yellow, cell1.getBorderRightColor());
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
@ -65,8 +66,10 @@ import org.apache.poi.hwpf.usermodel.Range;
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POIUtils;
|
||||
|
||||
|
||||
/**
|
||||
@ -81,6 +84,10 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
private static final String PROPERTY_PRESERVE_BIN_TABLES = "org.apache.poi.hwpf.preserveBinTables";
|
||||
private static final String PROPERTY_PRESERVE_TEXT_TABLE = "org.apache.poi.hwpf.preserveTextTable";
|
||||
|
||||
private static final String STREAM_DATA = "Data";
|
||||
private static final String STREAM_TABLE_0 = "0Table";
|
||||
private static final String STREAM_TABLE_1 = "1Table";
|
||||
|
||||
/** And for making sense of CP lengths in the FIB */
|
||||
@Deprecated
|
||||
protected CPSplitCalculator _cpSplit;
|
||||
@ -224,10 +231,10 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
}
|
||||
|
||||
// use the fib to determine the name of the table stream.
|
||||
String name = "0Table";
|
||||
String name = STREAM_TABLE_0;
|
||||
if (_fib.isFWhichTblStm())
|
||||
{
|
||||
name = "1Table";
|
||||
name = STREAM_TABLE_1;
|
||||
}
|
||||
|
||||
// Grab the table stream.
|
||||
@ -249,9 +256,9 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
try
|
||||
{
|
||||
DocumentEntry dataProps =
|
||||
(DocumentEntry)directory.getEntry("Data");
|
||||
(DocumentEntry)directory.getEntry(STREAM_DATA);
|
||||
_dataStream = new byte[dataProps.getSize()];
|
||||
directory.createDocumentInputStream("Data").read(_dataStream);
|
||||
directory.createDocumentInputStream(STREAM_DATA).read(_dataStream);
|
||||
}
|
||||
catch(java.io.FileNotFoundException e)
|
||||
{
|
||||
@ -636,8 +643,8 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
{
|
||||
// initialize our streams for writing.
|
||||
HWPFFileSystem docSys = new HWPFFileSystem();
|
||||
HWPFOutputStream wordDocumentStream = docSys.getStream("WordDocument");
|
||||
HWPFOutputStream tableStream = docSys.getStream("1Table");
|
||||
HWPFOutputStream wordDocumentStream = docSys.getStream(STREAM_WORD_DOCUMENT);
|
||||
HWPFOutputStream tableStream = docSys.getStream(STREAM_TABLE_1);
|
||||
//HWPFOutputStream dataStream = docSys.getStream("Data");
|
||||
int tableOffset = 0;
|
||||
|
||||
@ -910,6 +917,9 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
mainBuf = tempBuf;
|
||||
}
|
||||
|
||||
// Table1 stream will be used
|
||||
_fib.setFWhichTblStm( true );
|
||||
|
||||
// write out the FileInformationBlock.
|
||||
//_fib.serialize(mainBuf, 0);
|
||||
_fib.writeTo(mainBuf, tableStream);
|
||||
@ -934,52 +944,95 @@ public final class HWPFDocument extends HWPFDocumentCore
|
||||
dataBuf = tempBuf;
|
||||
}
|
||||
|
||||
// // spit out the Word document.
|
||||
// POIFSFileSystem pfs = new POIFSFileSystem();
|
||||
//
|
||||
// pfs.createDocument(new ByteArrayInputStream(mainBuf), "WordDocument");
|
||||
// pfs.createDocument(new ByteArrayInputStream(tableBuf), "1Table");
|
||||
// pfs.createDocument(new ByteArrayInputStream(dataBuf), "Data");
|
||||
// writeProperties(pfs);
|
||||
|
||||
POIFSFileSystem pfs = directory.getFileSystem();
|
||||
deleteEntrySafe( pfs, "WordDocument" );
|
||||
deleteEntrySafe( pfs, "0Table" );
|
||||
deleteEntrySafe( pfs, "1Table" );
|
||||
deleteEntrySafe( pfs, "Data" );
|
||||
|
||||
// read properties only if they were not read
|
||||
getSummaryInformation();
|
||||
// update properties in case user changed them
|
||||
deleteEntrySafe( pfs, SummaryInformation.DEFAULT_STREAM_NAME );
|
||||
deleteEntrySafe( pfs, DocumentSummaryInformation.DEFAULT_STREAM_NAME );
|
||||
// create new document preserving order of entries
|
||||
POIFSFileSystem pfs = new POIFSFileSystem();
|
||||
boolean docWritten = false;
|
||||
boolean dataWritten = false;
|
||||
boolean objectPoolWritten = false;
|
||||
boolean tableWritten = false;
|
||||
boolean propertiesWritten = false;
|
||||
for ( Iterator<Entry> iter = directory.getEntries(); iter.hasNext(); )
|
||||
{
|
||||
Entry entry = iter.next();
|
||||
if ( entry.getName().equals( STREAM_WORD_DOCUMENT ) )
|
||||
{
|
||||
if ( !docWritten )
|
||||
{
|
||||
pfs.createDocument( new ByteArrayInputStream( mainBuf ),
|
||||
STREAM_WORD_DOCUMENT );
|
||||
docWritten = true;
|
||||
}
|
||||
}
|
||||
else if ( entry.getName().equals( STREAM_OBJECT_POOL ) )
|
||||
{
|
||||
if ( !objectPoolWritten )
|
||||
{
|
||||
_objectPool.writeTo( pfs.getRoot() );
|
||||
objectPoolWritten = true;
|
||||
}
|
||||
}
|
||||
else if ( entry.getName().equals( STREAM_TABLE_0 )
|
||||
|| entry.getName().equals( STREAM_TABLE_1 ) )
|
||||
{
|
||||
if ( !tableWritten )
|
||||
{
|
||||
pfs.createDocument( new ByteArrayInputStream( tableBuf ),
|
||||
STREAM_TABLE_1 );
|
||||
tableWritten = true;
|
||||
}
|
||||
}
|
||||
else if ( entry.getName().equals(
|
||||
SummaryInformation.DEFAULT_STREAM_NAME )
|
||||
|| entry.getName().equals(
|
||||
DocumentSummaryInformation.DEFAULT_STREAM_NAME ) )
|
||||
{
|
||||
if ( !propertiesWritten )
|
||||
{
|
||||
writeProperties( pfs );
|
||||
propertiesWritten = true;
|
||||
}
|
||||
}
|
||||
else if ( entry.getName().equals( STREAM_DATA ) )
|
||||
{
|
||||
if ( !dataWritten )
|
||||
{
|
||||
pfs.createDocument( new ByteArrayInputStream( dataBuf ),
|
||||
STREAM_DATA );
|
||||
dataWritten = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
POIUtils.copyNodeRecursively( entry, pfs.getRoot() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !docWritten )
|
||||
pfs.createDocument( new ByteArrayInputStream( mainBuf ),
|
||||
STREAM_WORD_DOCUMENT );
|
||||
if ( !tableWritten )
|
||||
pfs.createDocument( new ByteArrayInputStream( tableBuf ),
|
||||
STREAM_TABLE_1 );
|
||||
if ( !propertiesWritten )
|
||||
writeProperties( pfs );
|
||||
if ( !dataWritten )
|
||||
pfs.createDocument( new ByteArrayInputStream( dataBuf ),
|
||||
STREAM_DATA );
|
||||
if ( !objectPoolWritten )
|
||||
_objectPool.writeTo( pfs.getRoot() );
|
||||
|
||||
pfs.createDocument( new ByteArrayInputStream( mainBuf ), "WordDocument" );
|
||||
pfs.createDocument( new ByteArrayInputStream( tableBuf ), "1Table" );
|
||||
pfs.createDocument( new ByteArrayInputStream( dataBuf ), "Data" );
|
||||
pfs.writeFilesystem( out );
|
||||
this.directory = pfs.getRoot();
|
||||
|
||||
/*
|
||||
* since we updated all references in FIB and etc, using new arrays to
|
||||
* access data
|
||||
*/
|
||||
this.directory = pfs.getRoot();
|
||||
this._tableStream = tableStream.toByteArray();
|
||||
this._dataStream = dataBuf;
|
||||
}
|
||||
|
||||
private static void deleteEntrySafe( POIFSFileSystem pfs, final String name )
|
||||
{
|
||||
try
|
||||
{
|
||||
pfs.getRoot().getEntry( name ).delete();
|
||||
}
|
||||
catch ( FileNotFoundException exc )
|
||||
{
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
public byte[] getDataStream()
|
||||
{
|
||||
|
@ -22,12 +22,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PushbackInputStream;
|
||||
|
||||
import org.apache.poi.hwpf.usermodel.ObjectsPool;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
|
||||
import org.apache.poi.hwpf.usermodel.ObjectPoolImpl;
|
||||
|
||||
import org.apache.poi.EncryptedDocumentException;
|
||||
import org.apache.poi.POIDocument;
|
||||
import org.apache.poi.hwpf.model.CHPBinTable;
|
||||
@ -38,7 +32,10 @@ import org.apache.poi.hwpf.model.PAPBinTable;
|
||||
import org.apache.poi.hwpf.model.SectionTable;
|
||||
import org.apache.poi.hwpf.model.StyleSheet;
|
||||
import org.apache.poi.hwpf.model.TextPieceTable;
|
||||
import org.apache.poi.hwpf.usermodel.ObjectPoolImpl;
|
||||
import org.apache.poi.hwpf.usermodel.ObjectsPool;
|
||||
import org.apache.poi.hwpf.usermodel.Range;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.DocumentEntry;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
@ -53,6 +50,9 @@ import org.apache.poi.util.Internal;
|
||||
*/
|
||||
public abstract class HWPFDocumentCore extends POIDocument
|
||||
{
|
||||
protected static final String STREAM_OBJECT_POOL = "ObjectPool";
|
||||
protected static final String STREAM_WORD_DOCUMENT = "WordDocument";
|
||||
|
||||
/** Holds OLE2 objects */
|
||||
protected ObjectPoolImpl _objectPool;
|
||||
|
||||
@ -141,8 +141,7 @@ public abstract class HWPFDocumentCore extends POIDocument
|
||||
* @throws IOException If there is an unexpected IOException from the passed
|
||||
* in POIFSFileSystem.
|
||||
*/
|
||||
public HWPFDocumentCore(DirectoryNode directory) throws IOException
|
||||
{
|
||||
public HWPFDocumentCore(DirectoryNode directory) throws IOException {
|
||||
// Sort out the hpsf properties
|
||||
super(directory);
|
||||
|
||||
@ -151,27 +150,22 @@ public abstract class HWPFDocumentCore extends POIDocument
|
||||
directory.getEntry("WordDocument");
|
||||
_mainStream = new byte[documentProps.getSize()];
|
||||
|
||||
directory.createDocumentInputStream("WordDocument").read(_mainStream);
|
||||
directory.createDocumentInputStream(STREAM_WORD_DOCUMENT).read(_mainStream);
|
||||
|
||||
// Create our FIB, and check for the doc being encrypted
|
||||
_fib = new FileInformationBlock(_mainStream);
|
||||
if(_fib.isFEncrypted()) {
|
||||
if (_fib.isFEncrypted()) {
|
||||
throw new EncryptedDocumentException("Cannot process encrypted word files!");
|
||||
}
|
||||
|
||||
{
|
||||
DirectoryEntry objectPoolEntry;
|
||||
try
|
||||
{
|
||||
try {
|
||||
objectPoolEntry = (DirectoryEntry) directory
|
||||
.getEntry( "ObjectPool" );
|
||||
}
|
||||
catch ( FileNotFoundException exc )
|
||||
{
|
||||
objectPoolEntry = directory.createDirectory( "ObjectPool" );
|
||||
}
|
||||
_objectPool = new ObjectPoolImpl( objectPoolEntry );
|
||||
.getEntry(STREAM_OBJECT_POOL);
|
||||
} catch (FileNotFoundException exc) {
|
||||
objectPoolEntry = null;
|
||||
}
|
||||
_objectPool = new ObjectPoolImpl(objectPoolEntry);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,6 +81,13 @@ public abstract class AbstractWordConverter
|
||||
{
|
||||
return start < o.start ? -1 : start == o.start ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Structure [" + start + "; " + end + "): "
|
||||
+ structure.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static final byte BEL_MARK = 7;
|
||||
@ -116,8 +123,9 @@ public abstract class AbstractWordConverter
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( another.start > structure.start && another.end <= structure.end )
|
||||
|| ( another.start >= structure.start && another.end < structure.end ) )
|
||||
if ( ( structure.start < another.start && another.start < structure.end )
|
||||
|| ( structure.start < another.start && another.end <= structure.end )
|
||||
|| ( structure.start <= another.start && another.end < structure.end ) )
|
||||
{
|
||||
iterator.remove();
|
||||
continue;
|
||||
@ -316,7 +324,7 @@ public abstract class AbstractWordConverter
|
||||
|
||||
if ( structure.structure instanceof Bookmark )
|
||||
{
|
||||
// other bookmarks with same bundaries
|
||||
// other bookmarks with same boundaries
|
||||
List<Bookmark> bookmarks = new LinkedList<Bookmark>();
|
||||
for ( Bookmark bookmark : ( (HWPFDocument) wordDocument )
|
||||
.getBookmarks()
|
||||
@ -334,8 +342,8 @@ public abstract class AbstractWordConverter
|
||||
bookmarkStack.addAll( bookmarks );
|
||||
try
|
||||
{
|
||||
Range subrange = new Range( structure.start, structure.end,
|
||||
range )
|
||||
int end = Math.min( range.getEndOffset(), structure.end );
|
||||
Range subrange = new Range( structure.start, end, range )
|
||||
{
|
||||
@Override
|
||||
public String toString()
|
||||
@ -364,15 +372,17 @@ public abstract class AbstractWordConverter
|
||||
+ structure.structure.getClass() );
|
||||
}
|
||||
|
||||
previous = structure.end;
|
||||
previous = Math.min( range.getEndOffset(), structure.end );
|
||||
}
|
||||
|
||||
if ( previous != range.getStartOffset() )
|
||||
{
|
||||
if ( previous > range.getEndOffset() )
|
||||
{
|
||||
logger.log( POILogger.WARN, "Latest structure in " + range
|
||||
+ " ended after range (" + previous + ")" );
|
||||
logger.log( POILogger.WARN, "Latest structure in ", range,
|
||||
" ended at #" + previous, " after range boundaries [",
|
||||
range.getStartOffset() + "; " + range.getEndOffset(),
|
||||
")" );
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -596,6 +606,8 @@ public abstract class AbstractWordConverter
|
||||
}
|
||||
|
||||
public void processDocument( HWPFDocumentCore wordDocument )
|
||||
{
|
||||
try
|
||||
{
|
||||
final SummaryInformation summaryInformation = wordDocument
|
||||
.getSummaryInformation();
|
||||
@ -603,6 +615,13 @@ public abstract class AbstractWordConverter
|
||||
{
|
||||
processDocumentInformation( summaryInformation );
|
||||
}
|
||||
}
|
||||
catch ( Exception exc )
|
||||
{
|
||||
logger.log( POILogger.WARN,
|
||||
"Unable to process document summary information: ", exc,
|
||||
exc );
|
||||
}
|
||||
|
||||
final Range docRange = wordDocument.getRange();
|
||||
|
||||
@ -846,6 +865,9 @@ public abstract class AbstractWordConverter
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract void processPageBreak( HWPFDocumentCore wordDocument,
|
||||
Element flow );
|
||||
|
||||
protected abstract void processPageref( HWPFDocumentCore wordDocument,
|
||||
Element currentBlock, Range textRange, int currentTableLevel,
|
||||
String pageref );
|
||||
@ -884,6 +906,11 @@ public abstract class AbstractWordConverter
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( paragraph.text().equals( "\u000c" ) )
|
||||
{
|
||||
processPageBreak( wordDocument, flow );
|
||||
}
|
||||
|
||||
if ( paragraph.getIlfo() != currentListInfo )
|
||||
{
|
||||
currentListInfo = paragraph.getIlfo();
|
||||
|
@ -130,7 +130,7 @@ public class AbstractWordUtils
|
||||
return true;
|
||||
}
|
||||
|
||||
static void compactChildNodes( Element parentElement, String childTagName )
|
||||
static void compactChildNodesR( Element parentElement, String childTagName )
|
||||
{
|
||||
NodeList childNodes = parentElement.getChildNodes();
|
||||
for ( int i = 0; i < childNodes.getLength() - 1; i++ )
|
||||
@ -146,6 +146,16 @@ public class AbstractWordUtils
|
||||
child2.getParentNode().removeChild( child2 );
|
||||
i--;
|
||||
}
|
||||
|
||||
childNodes = parentElement.getChildNodes();
|
||||
for ( int i = 0; i < childNodes.getLength() - 1; i++ )
|
||||
{
|
||||
Node child = childNodes.item( i );
|
||||
if ( child instanceof Element )
|
||||
{
|
||||
compactChildNodesR( (Element) child, childTagName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean equals( String str1, String str2 )
|
||||
@ -306,13 +316,26 @@ public class AbstractWordUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static String getColor24( int value )
|
||||
public static String getOpacity( int argbValue )
|
||||
{
|
||||
if ( value == -1 )
|
||||
int opacity = (int) ( ( argbValue & 0xFF000000l ) >>> 24 );
|
||||
if ( opacity == 0 || opacity == 0xFF )
|
||||
return ".0";
|
||||
|
||||
return "" + ( opacity / (float) 0xFF );
|
||||
}
|
||||
|
||||
public static String getColor24( int argbValue )
|
||||
{
|
||||
if ( argbValue == -1 )
|
||||
throw new IllegalArgumentException( "This colorref is empty" );
|
||||
|
||||
int bgrValue = argbValue & 0x00FFFFFF;
|
||||
int rgbValue = ( bgrValue & 0x0000FF ) << 16 | ( bgrValue & 0x00FF00 )
|
||||
| ( bgrValue & 0xFF0000 ) >> 16;
|
||||
|
||||
// http://www.w3.org/TR/REC-html40/types.html#h-6.5
|
||||
switch ( value )
|
||||
switch ( rgbValue )
|
||||
{
|
||||
case 0xFFFFFF:
|
||||
return "white";
|
||||
@ -349,7 +372,7 @@ public class AbstractWordUtils
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder( "#" );
|
||||
String hex = Integer.toHexString( value );
|
||||
String hex = Integer.toHexString( rgbValue );
|
||||
for ( int i = hex.length(); i < 6; i++ )
|
||||
{
|
||||
result.append( '0' );
|
||||
|
@ -22,49 +22,117 @@ package org.apache.poi.hwpf.converter;
|
||||
import org.apache.poi.util.Beta;
|
||||
|
||||
/**
|
||||
* Comment me
|
||||
* Utility class to translate numbers in letters, usually for lists.
|
||||
*
|
||||
* @author Ryan Ackley
|
||||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com)
|
||||
*/
|
||||
@Beta
|
||||
public final class NumberFormatter
|
||||
{
|
||||
|
||||
private static String[] C_LETTERS = new String[] { "a", "b", "c", "d", "e",
|
||||
"f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
|
||||
"s", "t", "u", "v", "x", "y", "z" };
|
||||
private static final String[] ENGLISH_LETTERS = new String[] { "a", "b",
|
||||
"c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
|
||||
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
|
||||
|
||||
private static String[] C_ROMAN = new String[] { "i", "ii", "iii", "iv",
|
||||
"v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv",
|
||||
"xv", "xvi", "xvii", "xviii", "xix", "xx", "xxi", "xxii", "xxiii",
|
||||
"xxiv", "xxv", "xxvi", "xxvii", "xxviii", "xxix", "xxx", "xxxi",
|
||||
"xxxii", "xxxiii", "xxxiv", "xxxv", "xxxvi", "xxxvii", "xxxvii",
|
||||
"xxxviii", "xxxix", "xl", "xli", "xlii", "xliii", "xliv", "xlv",
|
||||
"xlvi", "xlvii", "xlviii", "xlix", "l" };
|
||||
private static final String[] ROMAN_LETTERS = { "m", "cm", "d", "cd", "c",
|
||||
"xc", "l", "xl", "x", "ix", "v", "iv", "i" };
|
||||
|
||||
private final static int T_ARABIC = 0;
|
||||
private final static int T_LOWER_LETTER = 4;
|
||||
private final static int T_LOWER_ROMAN = 2;
|
||||
private final static int T_ORDINAL = 5;
|
||||
private final static int T_UPPER_LETTER = 3;
|
||||
private final static int T_UPPER_ROMAN = 1;
|
||||
private static final int[] ROMAN_VALUES = { 1000, 900, 500, 400, 100, 90,
|
||||
50, 40, 10, 9, 5, 4, 1 };
|
||||
|
||||
private static final int T_ARABIC = 0;
|
||||
private static final int T_LOWER_LETTER = 4;
|
||||
private static final int T_LOWER_ROMAN = 2;
|
||||
private static final int T_ORDINAL = 5;
|
||||
private static final int T_UPPER_LETTER = 3;
|
||||
private static final int T_UPPER_ROMAN = 1;
|
||||
|
||||
public static String getNumber( int num, int style )
|
||||
{
|
||||
switch ( style )
|
||||
{
|
||||
case T_UPPER_ROMAN:
|
||||
return C_ROMAN[num - 1].toUpperCase();
|
||||
return toRoman( num ).toUpperCase();
|
||||
case T_LOWER_ROMAN:
|
||||
return C_ROMAN[num - 1];
|
||||
return toRoman( num );
|
||||
case T_UPPER_LETTER:
|
||||
return C_LETTERS[num - 1].toUpperCase();
|
||||
return toLetters( num ).toUpperCase();
|
||||
case T_LOWER_LETTER:
|
||||
return C_LETTERS[num - 1];
|
||||
return toLetters( num );
|
||||
case T_ARABIC:
|
||||
case T_ORDINAL:
|
||||
default:
|
||||
return String.valueOf( num );
|
||||
}
|
||||
}
|
||||
|
||||
private static String toLetters( int number )
|
||||
{
|
||||
final int base = 26;
|
||||
|
||||
if ( number <= 0 )
|
||||
throw new IllegalArgumentException( "Unsupported number: " + number );
|
||||
|
||||
if ( number < base + 1 )
|
||||
return ENGLISH_LETTERS[number - 1];
|
||||
|
||||
long toProcess = number;
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int maxPower = 0;
|
||||
{
|
||||
int boundary = 0;
|
||||
while ( toProcess > boundary )
|
||||
{
|
||||
maxPower++;
|
||||
boundary = boundary * base + base;
|
||||
|
||||
if ( boundary > Integer.MAX_VALUE )
|
||||
throw new IllegalArgumentException( "Unsupported number: "
|
||||
+ toProcess );
|
||||
}
|
||||
}
|
||||
maxPower--;
|
||||
|
||||
for ( int p = maxPower; p > 0; p-- )
|
||||
{
|
||||
long boundary = 0;
|
||||
long shift = 1;
|
||||
for ( int i = 0; i < p; i++ )
|
||||
{
|
||||
shift *= base;
|
||||
boundary = boundary * base + base;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while ( toProcess > boundary )
|
||||
{
|
||||
count++;
|
||||
toProcess -= shift;
|
||||
}
|
||||
stringBuilder.append( ENGLISH_LETTERS[count - 1] );
|
||||
}
|
||||
stringBuilder.append( ENGLISH_LETTERS[(int) toProcess - 1] );
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
private static String toRoman( int number )
|
||||
{
|
||||
if ( number <= 0 )
|
||||
throw new IllegalArgumentException( "Unsupported number: " + number );
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for ( int i = 0; i < ROMAN_LETTERS.length; i++ )
|
||||
{
|
||||
String letter = ROMAN_LETTERS[i];
|
||||
int value = ROMAN_VALUES[i];
|
||||
while ( number >= value )
|
||||
{
|
||||
number -= value;
|
||||
result.append( letter );
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
/**
|
||||
@ -119,6 +121,8 @@ public class WordToFoConverter extends AbstractWordConverter
|
||||
|
||||
private AtomicInteger internalLinkCounter = new AtomicInteger( 0 );
|
||||
|
||||
private boolean outputCharactersLanguage = false;
|
||||
|
||||
private Set<String> usedIds = new LinkedHashSet<String>();
|
||||
|
||||
/**
|
||||
@ -202,6 +206,11 @@ public class WordToFoConverter extends AbstractWordConverter
|
||||
return foDocumentFacade.getDocument();
|
||||
}
|
||||
|
||||
public boolean isOutputCharactersLanguage()
|
||||
{
|
||||
return outputCharactersLanguage;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void outputCharacters( Element block, CharacterRun characterRun,
|
||||
String text )
|
||||
@ -211,11 +220,15 @@ public class WordToFoConverter extends AbstractWordConverter
|
||||
Triplet triplet = getCharacterRunTriplet( characterRun );
|
||||
|
||||
if ( WordToFoUtils.isNotEmpty( triplet.fontName ) )
|
||||
WordToFoUtils.setFontFamily( inline, characterRun.getFontName() );
|
||||
WordToFoUtils.setFontFamily( inline, triplet.fontName );
|
||||
WordToFoUtils.setBold( inline, triplet.bold );
|
||||
WordToFoUtils.setItalic( inline, triplet.italic );
|
||||
WordToFoUtils.setFontSize( inline, characterRun.getFontSize() / 2 );
|
||||
WordToFoUtils.setCharactersProperties( characterRun, inline );
|
||||
|
||||
if ( isOutputCharactersLanguage() )
|
||||
WordToFoUtils.setLanguage( characterRun, inline );
|
||||
|
||||
block.appendChild( inline );
|
||||
|
||||
Text textNode = foDocumentFacade.createText( text );
|
||||
@ -411,6 +424,32 @@ public class WordToFoConverter extends AbstractWordConverter
|
||||
block.appendChild( foDocumentFacade.createBlock() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processPageBreak( HWPFDocumentCore wordDocument, Element flow )
|
||||
{
|
||||
Element block = null;
|
||||
NodeList childNodes = flow.getChildNodes();
|
||||
if ( childNodes.getLength() > 0 )
|
||||
{
|
||||
Node lastChild = childNodes.item( childNodes.getLength() - 1 );
|
||||
if ( lastChild instanceof Element )
|
||||
{
|
||||
Element lastElement = (Element) lastChild;
|
||||
if ( !lastElement.hasAttribute( "break-after" ) )
|
||||
{
|
||||
block = lastElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( block == null )
|
||||
{
|
||||
block = foDocumentFacade.createBlock();
|
||||
flow.appendChild( block );
|
||||
}
|
||||
block.setAttribute( "break-after", "page" );
|
||||
}
|
||||
|
||||
protected void processPageref( HWPFDocumentCore hwpfDocument,
|
||||
Element currentBlock, Range textRange, int currentTableLevel,
|
||||
String pageref )
|
||||
@ -606,4 +645,9 @@ public class WordToFoConverter extends AbstractWordConverter
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setOutputCharactersLanguage( boolean outputCharactersLanguage )
|
||||
{
|
||||
this.outputCharactersLanguage = outputCharactersLanguage;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class WordToFoUtils extends AbstractWordUtils
|
||||
{
|
||||
static void compactInlines( Element blockElement )
|
||||
{
|
||||
compactChildNodes( blockElement, "fo:inline" );
|
||||
compactChildNodesR( blockElement, "fo:inline" );
|
||||
}
|
||||
|
||||
public static void setBold( final Element element, final boolean bold )
|
||||
@ -76,11 +76,11 @@ public class WordToFoUtils extends AbstractWordUtils
|
||||
{
|
||||
inline.setAttribute( "color", getColor24( characterRun.getIco24() ) );
|
||||
}
|
||||
if ( characterRun.getLanguageCode() != 0 )
|
||||
final int opacity = (int) ( characterRun.getIco24() & 0xFF000000l ) >>> 24;
|
||||
if ( opacity != 0 && opacity != 0xFF )
|
||||
{
|
||||
final String language = getLanguage( characterRun.getLanguageCode() );
|
||||
if ( isNotEmpty( language ) )
|
||||
inline.setAttribute( "language", language );
|
||||
inline.setAttribute( "opacity",
|
||||
getOpacity( characterRun.getIco24() ) );
|
||||
}
|
||||
if ( characterRun.isCapitalized() )
|
||||
{
|
||||
@ -200,6 +200,17 @@ public class WordToFoUtils extends AbstractWordUtils
|
||||
element.setAttribute( "text-align", justification );
|
||||
}
|
||||
|
||||
public static void setLanguage( final CharacterRun characterRun,
|
||||
final Element inline )
|
||||
{
|
||||
if ( characterRun.getLanguageCode() != 0 )
|
||||
{
|
||||
final String language = getLanguage( characterRun.getLanguageCode() );
|
||||
if ( isNotEmpty( language ) )
|
||||
inline.setAttribute( "language", language );
|
||||
}
|
||||
}
|
||||
|
||||
public static void setParagraphProperties( Paragraph paragraph,
|
||||
Element block )
|
||||
{
|
||||
|
@ -495,6 +495,12 @@ public class WordToHtmlConverter extends AbstractWordConverter
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processPageBreak( HWPFDocumentCore wordDocument, Element flow )
|
||||
{
|
||||
flow.appendChild( htmlDocumentFacade.createLineBreak() );
|
||||
}
|
||||
|
||||
protected void processPageref( HWPFDocumentCore hwpfDocument,
|
||||
Element currentBlock, Range textRange, int currentTableLevel,
|
||||
String pageref )
|
||||
|
@ -233,7 +233,7 @@ public class WordToHtmlUtils extends AbstractWordUtils
|
||||
|
||||
static void compactSpans( Element pElement )
|
||||
{
|
||||
compactChildNodes( pElement, "span" );
|
||||
compactChildNodesR( pElement, "span" );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,12 +48,16 @@ import org.apache.poi.hwpf.usermodel.TableRow;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.util.Beta;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@Beta
|
||||
public class WordToTextConverter extends AbstractWordConverter
|
||||
{
|
||||
private static final POILogger logger = POILogFactory
|
||||
.getLogger( WordToTextConverter.class );
|
||||
|
||||
public static String getText( DirectoryNode root ) throws Exception
|
||||
{
|
||||
@ -325,7 +329,10 @@ public class WordToTextConverter extends AbstractWordConverter
|
||||
return false;
|
||||
DirectoryNode directoryNode = (DirectoryNode) entry;
|
||||
|
||||
// even if no ExtractorFactory in classpath
|
||||
/*
|
||||
* even if there is no ExtractorFactory in classpath, still support
|
||||
* included Word's objects
|
||||
*/
|
||||
if ( directoryNode.hasEntry( "WordDocument" ) )
|
||||
{
|
||||
String text = WordToTextConverter.getText( (DirectoryNode) entry );
|
||||
@ -335,14 +342,27 @@ public class WordToTextConverter extends AbstractWordConverter
|
||||
return true;
|
||||
}
|
||||
|
||||
Object extractor;
|
||||
try
|
||||
{
|
||||
Class<?> cls = Class
|
||||
.forName( "org.apache.poi.extractor.ExtractorFactory" );
|
||||
Method createExtractor = cls.getMethod( "createExtractor",
|
||||
DirectoryNode.class );
|
||||
Object extractor = createExtractor.invoke( null, directoryNode );
|
||||
extractor = createExtractor.invoke( null, directoryNode );
|
||||
}
|
||||
catch ( Error exc )
|
||||
{
|
||||
// no extractor in classpath
|
||||
logger.log( POILogger.WARN, "There is an OLE object entry '",
|
||||
entry.getName(),
|
||||
"', but there is no text extractor for this object type ",
|
||||
"or text extractor factory is not available: ", "" + exc );
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Method getText = extractor.getClass().getMethod( "getText" );
|
||||
String text = (String) getText.invoke( extractor );
|
||||
|
||||
@ -351,12 +371,21 @@ public class WordToTextConverter extends AbstractWordConverter
|
||||
+ UNICODECHAR_ZERO_WIDTH_SPACE ) );
|
||||
return true;
|
||||
}
|
||||
catch ( ClassNotFoundException exc )
|
||||
catch ( Exception exc )
|
||||
{
|
||||
// no extractor in classpath
|
||||
logger.log( POILogger.ERROR,
|
||||
"Unable to extract text from OLE entry '", entry.getName(),
|
||||
"': ", exc, exc );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@Override
|
||||
protected void processPageBreak( HWPFDocumentCore wordDocument, Element flow )
|
||||
{
|
||||
Element block = textDocumentFacade.createBlock();
|
||||
block.appendChild( textDocumentFacade.createText( "\n" ) );
|
||||
flow.appendChild( block );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,9 +72,11 @@ public final class CHPX extends BytePropertyNode<CHPX>
|
||||
}
|
||||
|
||||
CharacterProperties baseStyle = ss.getCharacterStyle( istd );
|
||||
if (baseStyle == null)
|
||||
baseStyle = new CharacterProperties();
|
||||
|
||||
CharacterProperties props = CharacterSprmUncompressor.uncompressCHP(
|
||||
baseStyle, getGrpprl(), 0 );
|
||||
;
|
||||
return props;
|
||||
}
|
||||
|
||||
|
@ -208,23 +208,31 @@ public class PAPBinTable
|
||||
final int startInclusive = lastParStart;
|
||||
final int endExclusive = charIndex + 1;
|
||||
|
||||
boolean broken = false;
|
||||
List<PAPX> papxs = new LinkedList<PAPX>();
|
||||
for ( int papxIndex = lastPapxIndex; papxIndex < oldPapxSortedByEndPos
|
||||
.size(); papxIndex++ )
|
||||
{
|
||||
broken = false;
|
||||
PAPX papx = oldPapxSortedByEndPos.get( papxIndex );
|
||||
|
||||
assert papxIndex + 1 == oldPapxSortedByEndPos.size()
|
||||
assert startInclusive == 0
|
||||
|| papxIndex + 1 == oldPapxSortedByEndPos.size()
|
||||
|| papx.getEnd() > startInclusive;
|
||||
|
||||
if ( papx.getEnd() - 1 > charIndex )
|
||||
{
|
||||
lastPapxIndex = papxIndex;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
papxs.add( papx );
|
||||
}
|
||||
if ( !broken )
|
||||
{
|
||||
lastPapxIndex = oldPapxSortedByEndPos.size() - 1;
|
||||
}
|
||||
|
||||
if ( papxs.size() == 0 )
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ public final class CharacterSprmUncompressor extends SprmUncompressor
|
||||
SprmOperation sprm = sprmIt.next();
|
||||
|
||||
if (sprm.getType() != 2) {
|
||||
logger.log( POILogger.WARN, "Non-CHP SPRM returned by SprmIterator" );
|
||||
logger.log( POILogger.WARN, "Non-CHP SPRM returned by SprmIterator: " + sprm );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,12 @@
|
||||
package org.apache.poi.hwpf.usermodel;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POIUtils;
|
||||
|
||||
@Internal
|
||||
public class ObjectPoolImpl implements ObjectsPool
|
||||
@ -47,4 +49,11 @@ public class ObjectPoolImpl implements ObjectsPool
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
public void writeTo( DirectoryEntry directoryEntry ) throws IOException
|
||||
{
|
||||
if ( _objectPool != null )
|
||||
POIUtils.copyNodeRecursively( _objectPool, directoryEntry );
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.apache.poi.hwpf.model.BytePropertyNode;
|
||||
|
||||
import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.HWPFDocumentCore;
|
||||
import org.apache.poi.hwpf.model.CHPX;
|
||||
@ -770,16 +772,28 @@ public class Range { // TODO -instantiable superclass
|
||||
return null;
|
||||
}
|
||||
|
||||
int[] point = findRange( _paragraphs, _parStart,
|
||||
Math.max( chpx.getStart(), _start ), chpx.getEnd() );
|
||||
short istd;
|
||||
if ( this instanceof Paragraph )
|
||||
{
|
||||
istd = ((Paragraph) this)._istd;
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] point = findRange( _paragraphs,
|
||||
Math.max( chpx.getStart(), _start ),
|
||||
Math.min( chpx.getEnd(), _end ) );
|
||||
|
||||
if ( point[0] >= _paragraphs.size() )
|
||||
initParagraphs();
|
||||
int parStart = Math.max( point[0], _parStart );
|
||||
|
||||
if ( parStart >= _paragraphs.size() )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
PAPX papx = _paragraphs.get( point[0] );
|
||||
short istd = papx.getIstd();
|
||||
istd = papx.getIstd();
|
||||
}
|
||||
|
||||
CharacterRun chp = new CharacterRun( chpx, _doc.getStyleSheet(), istd,
|
||||
this );
|
||||
@ -924,7 +938,7 @@ public class Range { // TODO -instantiable superclass
|
||||
*/
|
||||
private void initParagraphs() {
|
||||
if (!_parRangeFound) {
|
||||
int[] point = findRange(_paragraphs, _parStart, _start, _end);
|
||||
int[] point = findRange(_paragraphs, _start, _end);
|
||||
_parStart = point[0];
|
||||
_parEnd = point[1];
|
||||
_parRangeFound = true;
|
||||
@ -936,7 +950,7 @@ public class Range { // TODO -instantiable superclass
|
||||
*/
|
||||
private void initCharacterRuns() {
|
||||
if (!_charRangeFound) {
|
||||
int[] point = findRange(_characters, _charStart, _start, _end);
|
||||
int[] point = findRange(_characters, _start, _end);
|
||||
_charStart = point[0];
|
||||
_charEnd = point[1];
|
||||
_charRangeFound = true;
|
||||
@ -955,6 +969,105 @@ public class Range { // TODO -instantiable superclass
|
||||
}
|
||||
}
|
||||
|
||||
private static int binarySearchStart( List<? extends PropertyNode<?>> rpl,
|
||||
int start )
|
||||
{
|
||||
if ( rpl.get( 0 ).getStart() >= start )
|
||||
return 0;
|
||||
|
||||
int low = 0;
|
||||
int high = rpl.size() - 1;
|
||||
|
||||
while ( low <= high )
|
||||
{
|
||||
int mid = ( low + high ) >>> 1;
|
||||
PropertyNode<?> node = rpl.get( mid );
|
||||
|
||||
if ( node.getStart() < start )
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
else if ( node.getStart() > start )
|
||||
{
|
||||
high = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert node.getStart() == start;
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
assert low != 0;
|
||||
return low - 1;
|
||||
}
|
||||
|
||||
private static int binarySearchEnd( List<? extends PropertyNode<?>> rpl,
|
||||
int foundStart, int end )
|
||||
{
|
||||
if ( rpl.get( rpl.size() - 1 ).getEnd() <= end )
|
||||
return rpl.size() - 1;
|
||||
|
||||
int low = foundStart;
|
||||
int high = rpl.size() - 1;
|
||||
|
||||
while ( low <= high )
|
||||
{
|
||||
int mid = ( low + high ) >>> 1;
|
||||
PropertyNode<?> node = rpl.get( mid );
|
||||
|
||||
if ( node.getEnd() < end )
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
else if ( node.getEnd() > end )
|
||||
{
|
||||
high = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert node.getEnd() == end;
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
assert 0 <= low && low < rpl.size();
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find the list indexes of a particular property.
|
||||
*
|
||||
* @param rpl
|
||||
* A list of property nodes.
|
||||
* @param min
|
||||
* A hint on where to start looking.
|
||||
* @param start
|
||||
* The starting character offset.
|
||||
* @param end
|
||||
* The ending character offset.
|
||||
* @return An int array of length 2. The first int is the start index and
|
||||
* the second int is the end index.
|
||||
*/
|
||||
private int[] findRange( List<? extends PropertyNode<?>> rpl, int start,
|
||||
int end )
|
||||
{
|
||||
int startIndex = binarySearchStart( rpl, start );
|
||||
while ( startIndex > 0 && rpl.get( startIndex - 1 ).getStart() >= start )
|
||||
startIndex--;
|
||||
|
||||
int endIndex = binarySearchEnd( rpl, startIndex, end );
|
||||
while ( endIndex < rpl.size() - 1
|
||||
&& rpl.get( endIndex + 1 ).getEnd() <= end )
|
||||
endIndex--;
|
||||
|
||||
if ( startIndex < 0 || startIndex >= rpl.size()
|
||||
|| startIndex > endIndex || endIndex < 0
|
||||
|| endIndex >= rpl.size() )
|
||||
throw new AssertionError();
|
||||
|
||||
return new int[] { startIndex, endIndex + 1 };
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to find the list indexes of a particular property.
|
||||
*
|
||||
@ -1138,7 +1251,7 @@ public class Range { // TODO -instantiable superclass
|
||||
{
|
||||
if ( _start < 0 )
|
||||
throw new AssertionError();
|
||||
if ( _start >= _text.length() )
|
||||
if ( _start > _text.length() )
|
||||
throw new AssertionError();
|
||||
if ( _end < 0 )
|
||||
throw new AssertionError();
|
||||
|
@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
@ -90,6 +91,58 @@ public class HWPFTestDataSamples {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a remote sample from URL. opening is performd in two phases:
|
||||
* (1) download content into a byte array
|
||||
* (2) construct HWPFDocument
|
||||
*
|
||||
* @param sampleFileUrl the url to open
|
||||
*/
|
||||
public static HWPFDocument openRemoteFile( String sampleFileUrl )
|
||||
{
|
||||
final long start = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
InputStream is = new URL( sampleFileUrl ).openStream();
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
IOUtils.copy( is, baos );
|
||||
}
|
||||
finally
|
||||
{
|
||||
baos.close();
|
||||
}
|
||||
|
||||
final long endDownload = System.currentTimeMillis();
|
||||
byte[] byteArray = baos.toByteArray();
|
||||
|
||||
logger.log( POILogger.DEBUG, "Downloaded in ",
|
||||
Long.valueOf( endDownload - start ), " ms -- ",
|
||||
Long.valueOf( byteArray.length ), " byte(s)" );
|
||||
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream( byteArray );
|
||||
HWPFDocument doc = new HWPFDocument( bais );
|
||||
final long endParse = System.currentTimeMillis();
|
||||
|
||||
logger.log( POILogger.DEBUG, "Parsed in ",
|
||||
Long.valueOf( endParse - start ), " ms" );
|
||||
|
||||
return doc;
|
||||
}
|
||||
finally
|
||||
{
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
|
||||
public static HWPFOldDocument openOldSampleFile(String sampleFileName) {
|
||||
try {
|
||||
InputStream is = POIDataSamples.getDocumentInstance().openResourceAsStream(sampleFileName);
|
||||
|
@ -0,0 +1,75 @@
|
||||
package org.apache.poi.hwpf.converter;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestNumberFormatter extends TestCase
|
||||
{
|
||||
|
||||
public void testRoman()
|
||||
{
|
||||
assertEquals( "i", NumberFormatter.getNumber( 1, 2 ) );
|
||||
assertEquals( "ii", NumberFormatter.getNumber( 2, 2 ) );
|
||||
assertEquals( "iii", NumberFormatter.getNumber( 3, 2 ) );
|
||||
assertEquals( "iv", NumberFormatter.getNumber( 4, 2 ) );
|
||||
assertEquals( "v", NumberFormatter.getNumber( 5, 2 ) );
|
||||
assertEquals( "vi", NumberFormatter.getNumber( 6, 2 ) );
|
||||
assertEquals( "vii", NumberFormatter.getNumber( 7, 2 ) );
|
||||
assertEquals( "viii", NumberFormatter.getNumber( 8, 2 ) );
|
||||
assertEquals( "ix", NumberFormatter.getNumber( 9, 2 ) );
|
||||
assertEquals( "x", NumberFormatter.getNumber( 10, 2 ) );
|
||||
|
||||
assertEquals( "mdcvi", NumberFormatter.getNumber( 1606, 2 ) );
|
||||
assertEquals( "mcmx", NumberFormatter.getNumber( 1910, 2 ) );
|
||||
assertEquals( "mcmliv", NumberFormatter.getNumber( 1954, 2 ) );
|
||||
}
|
||||
|
||||
public void testEnglish()
|
||||
{
|
||||
assertEquals( "a", NumberFormatter.getNumber( 1, 4 ) );
|
||||
assertEquals( "z", NumberFormatter.getNumber( 26, 4 ) );
|
||||
|
||||
assertEquals( "aa", NumberFormatter.getNumber( 1 * 26 + 1, 4 ) );
|
||||
assertEquals( "az", NumberFormatter.getNumber( 1 * 26 + 26, 4 ) );
|
||||
|
||||
assertEquals( "za", NumberFormatter.getNumber( 26 * 26 + 1, 4 ) );
|
||||
assertEquals( "zz", NumberFormatter.getNumber( 26 * 26 + 26, 4 ) );
|
||||
|
||||
assertEquals( "aaa",
|
||||
NumberFormatter.getNumber( 26 * 26 + 1 * 26 + 1, 4 ) );
|
||||
assertEquals( "aaz",
|
||||
NumberFormatter.getNumber( 26 * 26 + 1 * 26 + 26, 4 ) );
|
||||
|
||||
assertEquals( "aba",
|
||||
NumberFormatter.getNumber( 1 * 26 * 26 + 2 * 26 + 1, 4 ) );
|
||||
assertEquals( "aza",
|
||||
NumberFormatter.getNumber( 1 * 26 * 26 + 26 * 26 + 1, 4 ) );
|
||||
|
||||
assertEquals( "azz",
|
||||
NumberFormatter.getNumber( 26 * 26 + 26 * 26 + 26, 4 ) );
|
||||
assertEquals( "baa",
|
||||
NumberFormatter.getNumber( 2 * 26 * 26 + 1 * 26 + 1, 4 ) );
|
||||
assertEquals( "zaa",
|
||||
NumberFormatter.getNumber( 26 * 26 * 26 + 1 * 26 + 1, 4 ) );
|
||||
assertEquals( "zzz",
|
||||
NumberFormatter.getNumber( 26 * 26 * 26 + 26 * 26 + 26, 4 ) );
|
||||
|
||||
assertEquals(
|
||||
"aaaa",
|
||||
NumberFormatter.getNumber( 1 * 26 * 26 * 26 + 1 * 26 * 26 + 1
|
||||
* 26 + 1, 4 ) );
|
||||
assertEquals(
|
||||
"azzz",
|
||||
NumberFormatter.getNumber( 1 * 26 * 26 * 26 + 26 * 26 * 26 + 26
|
||||
* 26 + 26, 4 ) );
|
||||
assertEquals(
|
||||
"zzzz",
|
||||
NumberFormatter.getNumber( 26 * 26 * 26 * 26 + 26 * 26 * 26
|
||||
+ 26 * 26 + 26, 4 ) );
|
||||
|
||||
for ( int i = 1; i < 1000000; i++ )
|
||||
{
|
||||
// make sure there is no exceptions
|
||||
NumberFormatter.getNumber( i, 4 );
|
||||
}
|
||||
}
|
||||
}
|
@ -125,6 +125,22 @@ public class TestWordToFoConverter extends TestCase
|
||||
"padding-end=\"0.0in\" padding-start=\"0.0in\" width=\"1.0770833in\"" );
|
||||
}
|
||||
|
||||
public void testPageBreak() throws Exception
|
||||
{
|
||||
final String sampleFileName = "page-break.doc";
|
||||
String result = getFoText( sampleFileName );
|
||||
|
||||
assertContains( result, "<fo:block break-before=\"page\"" );
|
||||
}
|
||||
|
||||
public void testPageBreakBefore() throws Exception
|
||||
{
|
||||
final String sampleFileName = "page-break-before.doc";
|
||||
String result = getFoText( sampleFileName );
|
||||
|
||||
assertContains( result, "<fo:block break-before=\"page\"" );
|
||||
}
|
||||
|
||||
public void testPageref() throws Exception
|
||||
{
|
||||
final String sampleFileName = "pageref.doc";
|
||||
|
@ -130,7 +130,7 @@ public class TestWordToHtmlConverter extends TestCase
|
||||
|
||||
assertFalse( result.contains( "FORMTEXT" ) );
|
||||
|
||||
assertContains( result, "color:#28624f;" );
|
||||
assertContains( result, "color:#4f6228;" );
|
||||
assertContains( result, "Passport No and the date of expire" );
|
||||
assertContains( result, "mfa.gov.cy" );
|
||||
}
|
||||
|
@ -24,9 +24,13 @@ import org.apache.poi.hwpf.HWPFDocument;
|
||||
import org.apache.poi.hwpf.HWPFTestDataSamples;
|
||||
import org.apache.poi.hwpf.OldWordFileFormatException;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||
import org.apache.poi.poifs.filesystem.Entry;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Test the different routes to extracting text
|
||||
*
|
||||
@ -353,4 +357,27 @@ public final class TestWordExtractor extends TestCase {
|
||||
assertEquals(p_text1_block, extractor.getText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [RESOLVED FIXED] Bug 51686 - Update to POI 3.8 beta 4 causes
|
||||
* ConcurrentModificationException in Tika's OfficeParser
|
||||
*/
|
||||
public void testBug51686() throws IOException
|
||||
{
|
||||
InputStream is = POIDataSamples.getDocumentInstance()
|
||||
.openResourceAsStream( "Bug51686.doc" );
|
||||
|
||||
POIFSFileSystem fs = new POIFSFileSystem(is);
|
||||
|
||||
String text = null;
|
||||
|
||||
for (Entry entry : fs.getRoot()) {
|
||||
if ("WordDocument".equals(entry.getName())) {
|
||||
WordExtractor ex = new WordExtractor(fs);
|
||||
text = ex.getText();
|
||||
}
|
||||
}
|
||||
|
||||
assertNotNull(text);
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
==================================================================== */
|
||||
package org.apache.poi.hwpf.usermodel;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@ -24,6 +25,8 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
@ -508,14 +511,6 @@ public class TestBugs extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug 51524 - PapBinTable constructor is slow
|
||||
*/
|
||||
public void test51524()
|
||||
{
|
||||
HWPFTestDataSamples.openSampleFileFromArchive( "Bug51524.zip" );
|
||||
}
|
||||
|
||||
/**
|
||||
* [RESOLVED FIXED] Bug 51604 - replace text fails for doc ( poi 3.8 beta
|
||||
* release from download site )
|
||||
@ -630,4 +625,38 @@ public class TestBugs extends TestCase
|
||||
|
||||
assertEquals( Arrays.toString( oldData ), Arrays.toString( newData ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* [RESOLVED FIXED] Bug 51671 - HWPFDocument.write based on NPOIFSFileSystem
|
||||
* throws a NullPointerException
|
||||
*/
|
||||
public void test51671() throws Exception
|
||||
{
|
||||
InputStream is = POIDataSamples.getDocumentInstance()
|
||||
.openResourceAsStream( "empty.doc" );
|
||||
NPOIFSFileSystem npoifsFileSystem = new NPOIFSFileSystem( is );
|
||||
HWPFDocument hwpfDocument = new HWPFDocument(
|
||||
npoifsFileSystem.getRoot() );
|
||||
hwpfDocument.write( new ByteArrayOutputStream() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bug 51678 - Extracting text from Bug51524.zip is slow
|
||||
* Bug 51524 - PapBinTable constructor is slow
|
||||
*/
|
||||
public void test51678And51524()
|
||||
{
|
||||
// YK: the test will run only if the poi.test.remote system property is set.
|
||||
// TODO: refactor into something nicer!
|
||||
if(System.getProperty("poi.test.remote") != null) {
|
||||
String href = "http://domex.nps.edu/corp/files/govdocs1/007/007488.doc";
|
||||
HWPFDocument hwpfDocument = HWPFTestDataSamples.openRemoteFile( href );
|
||||
|
||||
WordExtractor wordExtractor = new WordExtractor( hwpfDocument );
|
||||
wordExtractor.getText();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public final class TestHWPFOldDocument extends HWPFTestCase {
|
||||
// Check
|
||||
assertEquals(1, doc.getRange().numSections());
|
||||
assertEquals(1, doc.getRange().numParagraphs());
|
||||
assertEquals(1, doc.getRange().numCharacterRuns());
|
||||
assertEquals(2, doc.getRange().numCharacterRuns());
|
||||
|
||||
assertEquals(
|
||||
"The quick brown fox jumps over the lazy dog\r",
|
||||
@ -96,7 +96,7 @@ public final class TestHWPFOldDocument extends HWPFTestCase {
|
||||
assertEquals(5, doc.getRange().getParagraph(4).numCharacterRuns());
|
||||
assertEquals(1, doc.getRange().getParagraph(5).numCharacterRuns());
|
||||
// Normal, superscript for 4th, normal
|
||||
assertEquals(3, doc.getRange().getParagraph(6).numCharacterRuns());
|
||||
assertEquals(4, doc.getRange().getParagraph(6).numCharacterRuns());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Binary file not shown.
BIN
test-data/document/Bug51686.doc
Normal file
BIN
test-data/document/Bug51686.doc
Normal file
Binary file not shown.
BIN
test-data/document/page-break-before.doc
Normal file
BIN
test-data/document/page-break-before.doc
Normal file
Binary file not shown.
BIN
test-data/document/page-break.doc
Normal file
BIN
test-data/document/page-break.doc
Normal file
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user