How to get the shapes in a docx drawing using XWPF (Apache POI) - apache-poi

I have a docx document with text and some shapes. I am able to get the drawings, but when I get a drawing, how can I get the Shapes in this drawing? For example I have the following code to parse my document:
try (FileInputStream fis = new FileInputStream(file)) {
document = new XWPFDocument(fis);
parseDocument(document);
}
The parseDocument(XWPFDocument document) method has the following code (I used the answer to the following question: How to get the drawings from the apache POI XWPFDocument?):
public void parseDocument(XWPFDocument document) throws Exception {
Iterator<XWPFParagraph> it = document.getParagraphs().iterator();
while (it.hasNext()) {
XWPFParagraph paragraph = it.next();
List<XWPFRun> runs = paragraph.getRuns();
Iterator<XWPFRun> it2 = runs.iterator();
while (it2.hasNext()) {
XWPFRun run = it2.next();
List<CTDrawing> drawings = getAllDrawings(run);
if (!drawings.isEmpty()) {
System.out.println("Found " + drawings.size() + " drawings");
Iterator<CTDrawing> it3 = drawings.iterator();
while (it3.hasNext()) {
CTDrawing drawing = it3.next();
visitDrawing(drawing);
}
}
}
}
}
private void visitDrawing(CTDrawing drawing) {
List<CTInline> inlines = drawing.getInlineList();
Iterator<CTInline> it = inlines.iterator();
while (it.hasNext()) {
CTInline inline = it.next();
CTGraphicalObject graphic = inline.getGraphic();
if (graphic != null) {
CTGraphicalObjectData graphicData = graphic.getGraphicData();
if (graphicData != null) {
XmlCursor c = graphicData.newCursor();
c.selectPath("./*");
while (c.toNextSelection()) {
XmlObject o = c.getObject();
System.out.println(o);
}
}
}
}
List<CTAnchor> anchors = drawing.getAnchorList();
Iterator<CTAnchor> it2 = anchors.iterator();
while (it2.hasNext()) {
CTAnchor anchor = it2.next();
CTGraphicalObject graphic = anchor.getGraphic();
if (graphic != null) {
CTGraphicalObjectData graphicData = graphic.getGraphicData();
if (graphicData != null) {
XmlCursor c = graphicData.newCursor();
c.selectPath("./*");
while (c.toNextSelection()) {
XmlObject o = c.getObject();
System.out.println(o);
}
}
}
}
}
private static List<CTDrawing> getAllDrawings(XWPFRun run) throws Exception {
CTR ctR = run.getCTR();
XmlCursor cursor = ctR.newCursor();
cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:drawing");
List<CTDrawing> drawings = new ArrayList<>();
while (cursor.hasNextSelection()) {
cursor.toNextSelection();
XmlObject obj = cursor.getObject();
CTDrawing drawing = CTDrawing.Factory.parse(obj.newInputStream());
drawings.add(drawing);
}
return drawings;
}
With both the inline and anchor drawings, the XmlObject element contains the shapes I can see it is the case in very simple exampleswhen I look at the printed content), but how do I get these shapes when I have the object?

Related

Apache POI - remove external Book reference

We receive excel files in our system and upon downloading them, i need to remove any reference to external workbook for security reasons.
i wrote the following function to remove external links as well as removing content from the cell referencing the book.
public static byte[] cleanFile(byte[] excelByteArrayworkbook) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (InputStream targetStream = new ByteArrayInputStream(excelByteArrayworkbook)){
try (XSSFWorkbook workbook = new XSSFWorkbook(targetStream)) {
XSSFEvaluationWorkbook evalWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);
Iterator<Sheet> sheetIterator = workbook.iterator();
int i = 0;
while (sheetIterator.hasNext()) {
Sheet sheet = sheetIterator.next();
EvaluationSheet evalSheet = evalWorkbook.getSheet(i);
i++;
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == Cell.CELL_TYPE_FORMULA) {
EvaluationCell evaluationCell = evalSheet.getCell(cell.getRowIndex(), cell.getColumnIndex());
try {
Ptg[] formulaTokens = evalWorkbook.getFormulaTokens(evaluationCell);
for (Ptg formulaToken : formulaTokens) {
int externalSheetIndex = -1;
if (formulaToken instanceof Ref3DPtg) {
Ref3DPtg refToken = (Ref3DPtg) formulaToken;
externalSheetIndex = refToken.getExternSheetIndex();
} else if (formulaToken instanceof Area3DPtg) {
Area3DPtg refToken = (Area3DPtg) formulaToken;
externalSheetIndex = refToken.getExternSheetIndex();
} else if (formulaToken instanceof Ref3DPxg) {
Ref3DPxg refToken = (Ref3DPxg) formulaToken;
externalSheetIndex = refToken.getExternalWorkbookNumber();
} else if (formulaToken instanceof Area3DPxg) {
Area3DPxg refToken = (Area3DPxg) formulaToken;
externalSheetIndex = refToken.getExternalWorkbookNumber();
}
if (externalSheetIndex >= 0) {
cell.setCellFormula(null);
}
else if (cell.getCellFormula().contains("[")) {
cell.setCellFormula(null);
}
}
} catch (Exception e) {
cell.setCellFormula(null);
}
}
}
}
}
List<ExternalLinksTable> links = workbook.getExternalLinksTable();
links.forEach(link -> {
if(link.getCTExternalLink().isSetDdeLink())
link.getCTExternalLink().unsetDdeLink();
if(link.getCTExternalLink().isSetExtLst())
link.getCTExternalLink().unsetExtLst();
if(link.getCTExternalLink().isSetOleLink())
link.getCTExternalLink().unsetOleLink();
if(link.getCTExternalLink().isSetExternalBook())
link.getCTExternalLink().unsetExternalBook();
link.getCTExternalLink().setNil();
});
try {
workbook.write(bos);
} finally {
bos.close();
}
}
}
try {
bos.close();
} catch (IOException e) {
}
return bos.toByteArray();
}
However, the file i am getting is not valid. Excel prompt me with an error message saying
Excel error message
The version of Apache POI i am using is 3.13 . I can't find an example where i can remove external links
I found the answer. The code was not removing references in the Name Manager area.
I have added the following in my function
List<XSSFName> nameUsingExternalBook = new ArrayList<XSSFName>();
for (int j = 0; j < workbook.getNumberOfNames(); j++) {
XSSFName name= workbook.getNameAt(j);
if(name.getRefersToFormula() != null && name.getRefersToFormula().contains("[")) {
nameUsingExternalBook.add(name);
}
}
nameUsingExternalBook.forEach(name->{
workbook.removeName(name.getNameName());
});
So the new excel file is wellformed

how to attach an XML file in the "Files" tab of an action

I have a big question, you can attach XML through an action, when you import the XML and also save it in the "Files" tab, the question is. if it can be attached?.
Here is an example image:
what is missing is that I automatically attach in the "Files" tab, when I put upload
Here is my code where, I attached the XML
public PXAction<ARInvoice> CargarXML;
[PXUIField(DisplayName = "Carga de código hash")]
[PXButton()]
public virtual void cargarXML()
{
var Result = NewFilePanel.AskExt(true);
if (Result == WebDialogResult.OK)
{
PX.SM.FileInfo fileInfo = PX.Common.PXContext.SessionTyped<PXSessionStatePXData>().FileInfo["CargaSessionKey"];
string result = System.Text.Encoding.UTF8.GetString(fileInfo.BinData);
ARInvoice ari = Base.Document.Current;
xtFECodHashEntry graph2 = PXGraph.CreateInstance<xtFECodHashEntry>();
var pchExt = ari.GetExtension<ARRegisterExt>();
string Valor = "";
XmlDocument xm = new XmlDocument();
xm.LoadXml(result);
XmlNodeList elemList = xm.GetElementsByTagName("ds:DigestValue");
for (int i = 0; i < elemList.Count;)
{
Valor = (elemList[i].InnerXml);
break;
}
PXLongOperation.StartOperation(Base, delegate ()
{
xtFECodHash dac = new xtFECodHash();
dac.RefNbr = ari.RefNbr;
dac.DocType = ari.DocType;
dac.Nrocomprobante = ari.InvoiceNbr;
dac.Hash = Valor;
dac.Tipo = pchExt.UsrTDocSunat;
graph2.xtFECodHashs.Insert(dac);
graph2.Actions.PressSave();
});
}
}
If you have the FileInfo object which it seems like you do I have used something like this:
protected virtual void SaveFile(FileInfo fileInfo, PXCache cache, object row)
{
if (fileInfo == null)
{
return;
}
var fileGraph = PXGraph.CreateInstance<UploadFileMaintenance>();
if (!fileGraph.SaveFile(fileInfo, FileExistsAction.CreateVersion))
{
return;
}
if (!fileInfo.UID.HasValue)
{
return;
}
PXNoteAttribute.SetFileNotes(cache, row, fileInfo.UID.Value);
}
So in your example you could call this method as shown above using the following:
SaveFile(fileInfo, Base.Document.Cache, Base.Document.Current);

How to save the trained data in openimaj?

I'm working on a project which is about taking attendance of a class through the class video. I'm training the data when the program is running and it is taking a lot of time to train the data. Is there any way by which I can save the trained data and use directly in the program. Below is my code:
public static void main(String[] args) throws MalformedURLException, IOException, VideoCaptureException
{
FKEFaceDetector faceDetector = new FKEFaceDetector(new HaarCascadeDetector(40));
EigenFaceRecogniser<KEDetectedFace, Person> faceRecogniser = EigenFaceRecogniser.create(20, new RotateScaleAligner(), 1, DoubleFVComparison.CORRELATION, 0.9f);
final FaceRecognitionEngine<KEDetectedFace, Person> faceEngine = FaceRecognitionEngine.create(faceDetector, faceRecogniser);
Video<MBFImage> video;
//video = new VideoCapture(320, 100);
video = new XuggleVideo(new URL("file:///home/kamal/Videos/Samplevideo1.mp4"));
Person[] dataset = new Person[12];
dataset[0] = new Person("a");
dataset[1] = new Person("b");
dataset[2] = new Person("c");
dataset[3] = new Person("d");
dataset[4] = new Person("e");
dataset[5] = new Person("f");
dataset[6] = new Person("g");
dataset[7] = new Person("h");
dataset[8] = new Person("i");
dataset[9] = new Person("j");
dataset[10] = new Person("k");
dataset[11] = new Person("l");
int dcount;
for(int i = 0; i < 12; i++)
{
dcount = 0;
for(int j = 1; j <= 20 && dcount == 0; j++)
{
MBFImage mbfImage = ImageUtilities.readMBF(new URL("file:///home/kamal/Pictures/"+i+"/"+j+".png"));
FImage fimg = mbfImage.flatten();
List<KEDetectedFace> faces = faceEngine.getDetector().detectFaces(fimg);
if(faces.size() > 0)
{
faceEngine.train(faces.get(0), dataset[i]);
dcount++;
}
}
}
VideoDisplay<MBFImage> vd = VideoDisplay.createVideoDisplay(video);
vd.addVideoListener(new VideoDisplayListener<MBFImage>() {
public void afterUpdate(VideoDisplay<MBFImage> display) {
}
public void beforeUpdate(MBFImage frame)
{
FImage image = frame.flatten();
List<KEDetectedFace> faces = faceEngine.getDetector().detectFaces(image);
for(DetectedFace face : faces) {
frame.drawShape(face.getBounds(), RGBColour.RED);
try {
List<IndependentPair<KEDetectedFace, ScoredAnnotation<Person>>> rfaces = faceEngine.recogniseBest(face.getFacePatch());
ScoredAnnotation<Person> score = rfaces.get(0).getSecondObject();
if (score != null)
{
System.out.println("Mr. "+score.annotation+" is Present.");
}
else
{
System.out.println("Recognizing");
}
} catch (Exception e) {
}
}
}
});
}
Yes, just use the static methods in the org.openimaj.io.IOUtils class to write the faceEngine to disk once it's trained and read it back in again.

Some trouble with ComboBox in Ext.net

I have a Page which a FormPanel(there's a ComboBox in it) and a TreePanel(has a default root node) in it and open ViewState.
I set a value to ComboBox in GET.
When i GET the page the TreePanel's Store send a POST request(store read) before FormPane rendered in client,in this POST request the fromdata has no info about FormPane.
in the POST request recover the ComboBox.Value from ViewState,but in ComboBoxBase.LoadPostData() Ext.Net get value from formdata and cover ComboBox.Value without precondition
it's ComboBoxBase.LoadPostData() code
protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
this.HasLoadPostData = true;
string text = postCollection[this.UniqueName];
string state = postCollection[this.ValueHiddenName.IsNotEmpty() ? this.ValueHiddenName : ("_" + this.UniqueName + "_state")];
this.SuspendScripting();
this.RawValue = text;
this.Value = text;
this.ResumeScripting();
if (state == null && text == null)
{
return false;
}
if (!this.EmptyText.Equals(text) && text.IsNotEmpty())
{
List<ListItem> items = null;
if (this.SimpleSubmit)
{
var array = state.Split(new char[] { ',' });
items = new List<ListItem>(array.Length);
foreach (var item in array)
{
items.Add(new ListItem(item));
}
}
else if(state.IsNotEmpty())
{
items = ComboBoxBase.ParseSelectedItems(state);
}
bool fireEvent = false;
if (items == null)
{
items = new List<ListItem>
{
new ListItem(text)
};
/*fireEvent = this.SelectedItems.Count > 0;
this.SelectedItems.Clear();
return fireEvent;
*/
}
foreach (var item in items)
{
if (!this.SelectedItems.Contains(item))
{
fireEvent = true;
break;
}
}
this.SelectedItems.Clear();
this.SelectedItems.AddRange(items);
return fireEvent;
}
else
{
if (this.EmptyText.Equals(text) && this.SelectedItems.Count > 0)
{
this.SelectedItems.Clear();
return true;
}
}
return false;
}
Look at Line 5 to 11,why not change like this
string text = postCollection[this.UniqueName];
string state = postCollection[this.ValueHiddenName.IsNotEmpty() ? this.ValueHiddenName : ("_" + this.UniqueName + "_state")];
this.SuspendScripting();
this.RawValue = text;
this.ResumeScripting();
if (state == null && text == null)
{
return false;
}
this.SuspendScripting();
this.Value = text;
this.ResumeScripting();
Sample for this question
page file
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<ext:ResourceManager ID="ResourceManager1" runat="server" DisableViewState="false"
AjaxViewStateMode="Enabled" ViewStateMode="Enabled"/>
<form id="form1" runat="server">
<ext:Viewport runat="server" ID="VP">
</ext:Viewport>
</form>
</body>
</html>
cs file
public partial class WebFormTest : System.Web.UI.Page
{
protected override void OnInitComplete(EventArgs e)
{
FP = new FormPanel();
FP.ID = "FP";
FP.Title = "FP";
FP.Region = Region.Center;
TF = new TextField();
TF.ID = "TF";
TF.FieldLabel = "TF";
CB = new ComboBox();
CB.ID = "CB";
CB.FieldLabel = "CB";
CB.Items.Clear();
CB.Items.Add(new ListItem("one", "1"));
CB.Items.Add(new ListItem("two", "2"));
Button test = new Button() { ID = "testbtn", Text = "test" };
test.Listeners.Click.Handler = "App.Store2.load()";
FP.TopBar.Add(new Toolbar() { Items = { test } });
FP.Items.Add(TF);
FP.Items.Add(CB);
GP = new GridPanel();
GP.ID = "GP";
GP.Title = "GP";
GP.Region = Region.East;
GP.Listeners.BeforeRender.Handler = "App.Store1.reload()";
BTN = new Button();
BTN.ID = "BTN";
BTN.Text = "click";
BTN.Icon = Icon.ArrowJoin;
BTN.DirectEvents.Click.Event += new ComponentDirectEvent.DirectEventHandler(Click);
TB = new Toolbar();
TB.Items.Add(BTN);
GP.TopBar.Add(TB);
Store1 = new Store();
Store1.ID = "Store1";
Store1.ReadData += new Store.AjaxReadDataEventHandler(WebFormTest_ReadData);
Model1 = new Model();
Model1.ID = "Model1";
Store1.Model.Add(Model1);
GP.Store.Add(Store1);
TP = new TreePanel();
TP.ID = "TP";
TP.Title = "TP";
TP.Region = Region.East;
TP.RootVisible = false;
TP.Root.Add(new Node() { NodeID = "test", Text = "test" });
Store2 = new TreeStore();
Store2.ID = "Store2";
Store2.ReadData += new TreeStoreBase.ReadDataEventHandler(Store2_ReadData);
TP.Store.Add(Store2);
VP.Items.Add(FP);
//VP.Items.Add(GP);
VP.Items.Add(TP);
if (!X.IsAjaxRequest)
{
CB.Value = "2";
TF.Value = "TEXT";
}
base.OnInitComplete(e);
}
FormPanel FP;
TextField TF;
ComboBox CB;
GridPanel GP;
Button BTN;
Toolbar TB;
Store Store1;
Model Model1;
TreePanel TP;
TreeStore Store2;
protected override void CreateChildControls()
{
base.CreateChildControls();
}
void Store2_ReadData(object sender, NodeLoadEventArgs e)
{
}
protected void Page_Load(object sender, EventArgs e)
{
//if (!X.IsAjaxRequest)
//{
// this.Store1.DataSource = this.Data;
// this.Store1.DataBind();
//}
}
protected void Refresh(object sender, DirectEventArgs e)
{
}
bool flag = false;
protected void Click(object sender, DirectEventArgs e)
{
GP.GetStore().Reload();
flag = true;
}
protected override void OnPreRender(EventArgs e)
{
if (flag)
{
TF.Value = "asdasd";
}
base.OnPreRender(e);
}
protected void WebFormTest_ReadData(object sender, StoreReadDataEventArgs e)
{
}
private object[] Data
{
get
{
return new object[]
{
new object[] { "3m Co", 71.72, 0.02, 0.03, "9/1 12:00am" },
};
}
}
}
you also can discuss in Ext.net Forums
We committed the change to the SVN trunk. It will go to the next release (v2.3).
The change is similar to your one, but we decided not to change RawValue as well. Thank you for the report and suggested fix.
Fix (ComboBoxBase LoadPostData)
protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
this.HasLoadPostData = true;
string text = postCollection[this.UniqueName];
string state = postCollection[this.ValueHiddenName.IsNotEmpty() ? this.ValueHiddenName : ("_" + this.UniqueName + "_state")];
if (state == null && text == null)
{
return false;
}
this.SuspendScripting();
this.RawValue = text;
this.Value = text;
this.ResumeScripting();

Blackberry - How if addElement() doesn't work?

I am a newbie of Blackberry developing application. I try to store all xml parsing data to an object, and set them to a vector.
public class XmlParser extends MainScreen {
Database d;
private HttpConnection hcon = null;
private Vector binN;
public Vector getBinN() {
return binN;
}
public void setBinN(Vector bin) {
this.binN = bin;
}
LabelField from;
LabelField ttl;
LabelField desc;
LabelField date;
public XmlParser() {
LabelField title = new LabelField("Headline News" ,LabelField.HCENTER|LabelField.USE_ALL_WIDTH);
setTitle(title);
try {
URI myURI = URI.create("file:///SDCard/Database/WebFeed.db");
d = DatabaseFactory.open(myURI);
Statement st = d.createStatement("SELECT feed_url, feed_name FROM WebFeed");
st.prepare();
Cursor c = st.getCursor();
while (c.next()) {
Row r = c.getRow();
hcon = (HttpConnection)Connector.open(r.getString(0));
hcon.setRequestMethod(HttpConnection.GET);
hcon.setRequestProperty("User-Agent", "Profile/MIDP-1.0 Configuration/CLDC-1.0");
hcon.setRequestProperty("Content-Length", "0");
hcon.setRequestProperty("Connection", "close");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
builder.isValidating();
Document document = builder.parse(hcon.openInputStream());
Element rootElement = document.getDocumentElement();
rootElement.normalize();
NodeList list = document.getElementsByTagName("item");
int i=0;
while (i<10){
Node item = list.item(i);
if(item.getNodeType() != Node.TEXT_NODE) {
NodeList itemChilds = item.getChildNodes();
int j=0;
while (j<10){
Node detailNode = itemChilds.item(j);
if(detailNode.getNodeType() != Node.TEXT_NODE) {
if(detailNode.getNodeName().equalsIgnoreCase("title")) {
ttl = new LabelField(getNodeValue(detailNode)) {
public void paint(Graphics g) {
g.setColor(Color.BLUE);
super.paint(g);
}
};
from = new LabelField(r.getString(1), LabelField.FIELD_RIGHT|LabelField.USE_ALL_WIDTH);
ttl.setFont(Font.getDefault().derive(Font.BOLD));
from.setFont(Font.getDefault().derive(Font.BOLD));
add (from);
add (ttl);
} else if(detailNode.getNodeName().equalsIgnoreCase("description")) {
desc = new LabelField(getNodeValue(detailNode), 0, 70, USE_ALL_WIDTH);
add(desc);
} else if(detailNode.getNodeName().equalsIgnoreCase("dc:date")) {
date = new LabelField(getNodeValue(detailNode), 11, 5, USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
super.paint(g);
}
};
add(date);
add(new SeparatorField());
} else if(detailNode.getNodeName().equalsIgnoreCase("pubDate")) {
date = new LabelField(getNodeValue(detailNode), 0, 22, USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
super.paint(g);
}
};
add(date);
add(new SeparatorField());
} else {
System.out.println("not the node");
}
} else {
System.out.println("not text node");
}
j++;
}
}
i++;
BinNews bin = new BinNews();
bin.setProv(from.getText());
bin.setTitle(ttl.getText());
bin.setDesc(desc.getText());
bin.setDate(date.getText());
binN.addElement(bin);
}
setBinN(binN);
}
//setBinN(binN);
st.close();
d.close();
} catch (Exception e) {
add (new LabelField(e.toString(),LabelField.HCENTER|LabelField.USE_ALL_WIDTH));
System.out.println(e.toString());
}
}
public String getNodeValue(Node node) {
NodeList nodeList = node.getChildNodes();
Node childNode = nodeList.item(0);
return childNode.getNodeValue();
}
}
I try to store all data from an object called BinNews, to a vector called binN. But when I do debugging, I found that BinN has null value, because "binN.addElement(bin)" doesn't work.
Please advise.
First, you don't actually call setBinN until after the while(i < 10) loop completes. So when you say binN.addElement(bin) then binN will be null.
However your setBinN(binN) call doesn't make sense because you're passing in binN and then setting it to itself which isn't going to do anything.
What you can do is have binN = new Vector(); at the top of the constructor and then it won't be null later on. I don't think the setBinN call will be necessary later on if you're adding the BinNews objects straight to binN.

Resources