How to replace text in Powerpoint file with Java - java

I have a requirement where I need to replace some text in a Powerpoint File at runtime. (Powerpoint file is being used as a template with some placeholders/tokes e.g. {{USER_NAME}})
I have tried using POI but with no luck.
I referred to the other links on the forum and started with 'docx4j' but am not able to go beyond a point and the documentation is not very clear (at least for me).
Here is what I have done so far:
Got the PPTX loaded to 'PresentationMLPackage'
Got the 'MainPresentationPart' and the slides (Using mainPresentationPart.getSlide(n);)
But I am not sure of the next steps from here (or if this is the right approach in the first place).
Any suggestions will be greatly appreciated.
Thanks a Lot,
-Vini

SlidePart extends JaxbPmlPart<Sld>
JaxbPmlPart<E> extends JaxbXmlPartXPathAware<E>
JaxbXmlPartXPathAware<E> extends JaxbXmlPart<E>
JaxbXmlPart contains:
/**
* unmarshallFromTemplate. Where jaxbElement has not been
* unmarshalled yet, this is more efficient (3 times
* faster, in some testing) than calling
* XmlUtils.marshaltoString directly, since it avoids
* some JAXB processing.
*
* #param mappings
* #throws JAXBException
* #throws Docx4JException
*
* #since 3.0.0
*/
public void variableReplace(java.util.HashMap<String, String> mappings) throws JAXBException, Docx4JException {
// Get the contents as a string
String wmlTemplateString = null;
if (jaxbElement==null) {
PartStore partStore = this.getPackage().getSourcePartStore();
String name = this.getPartName().getName();
InputStream is = partStore.loadPart(
name.substring(1));
if (is==null) {
log.warn(name + " missing from part store");
throw new Docx4JException(name + " missing from part store");
} else {
log.info("Lazily unmarshalling " + name);
// This seems to be about 5% faster than the Scanner approach
try {
wmlTemplateString = IOUtils.toString(is, "UTF-8");
} catch (IOException e) {
throw new Docx4JException(e.getMessage(), e);
}
}
} else {
wmlTemplateString = XmlUtils.marshaltoString(jaxbElement, true, false, jc);
}
// Do the replacement
jaxbElement = (E)XmlUtils.unwrap(
XmlUtils.unmarshallFromTemplate(wmlTemplateString, mappings, jc));
}
So once you have the slide part, you can invoke variableReplace on it. You'll need your variables to be in the format expected by XmlUtils.unmarshallFromTemplate

Related

"Cannot access org.json.JSONStringer.Scope" on Android Studio 3.2.1

Sorry for this probably dumb question, i'm new to Java, Android Studio and everything related.
I'm trying to implement a simple weather forecast app for android on Android Studio 3.2.1 using the DarkSkyApi.
I managed to get the Data from DarkSky's server with HttpsURLConnection, StringBuilder
and BufferedReader. However, when i try to create a new JSONObject(.toString()), it just returns null. Further investigation led me to .toString()->JSONObject.java->JSONStringer, where Android Studio "Cannot access org.json.JSONStringer.Scope", what seems to be causing the failure of .toString().
I did add the JSON-Library, apart from the JSONStringer everything JSON-related looks like it would work. Imports do look fine to me aswell.
This is the malfunctioning code:
public class JSONStringer {
/** The output data, containing at most one top-level array or object. */
final StringBuilder out = new StringBuilder();
/**
* Lexical scoping elements within this stringer, necessary to insert the
* appropriate separator characters (ie. commas and colons) and to detect
* nesting errors.
*/
enum Scope {
/**
* An array with no elements requires no separators or newlines before
* it is closed.
*/
EMPTY_ARRAY,
/**
* A array with at least one value requires a comma and newline before
* the next element.
*/
NONEMPTY_ARRAY,
/**
* An object with no keys or values requires no separators or newlines
* before it is closed.
*/
EMPTY_OBJECT,
/**
* An object whose most recent element is a key. The next element must
* be a value.
*/
DANGLING_KEY,
/**
* An object with at least one name/value pair requires a comma and
* newline before the next element.
*/
NONEMPTY_OBJECT,
/**
* A special bracketless array needed by JSONStringer.join() and
* JSONObject.quote() only. Not used for JSON encoding.
*/
NULL,
}
Since i havn't changed anything in the JSONStringer.java i suspect the error maybe refers to a missing dependency or import or something, but i can't figure it out.
And this is where i get the Null-Object
if (responceCode == HttpURLConnection.HTTP_OK)
{
Log.i(TAG, "CONNECTION:::" + connection.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
Log.i(TAG, "url:::");
StringBuilder arg = new StringBuilder(1024);
String tmp="1";
while(tmp !=null) {
tmp = reader.readLine();
arg.append(tmp).append("\n");
}
reader.close();
Log.i(TAG, "Data: " + arg.toString());
return new JSONObject(arg.toString());
}
else{
return null;
}
Log.i(TAG, "Data: " + arg.toString()); works fine and logs the data-string like it should.
Do you need something else to figure this out?
Thanks in advance
Try this:
JsonObject output = Json.createObjectBuilder()
.add("data", arg.toString())
.build();
return output;

SimpleGraph PowerPoint module does not work as expected

I tried this simple unit test but got not what I expected:
#Test
public void testReadPowerpoint() throws Exception {
PowerPointSystem pps=new PowerPointSystem();
pps.connect();
SimpleNode slideShowNode =
pps.moveTo("https://www.its.leeds.ac.uk/fileadmin/documents/alumni/Michele_Dix_Leeds_University_-_FINAL.PPTX");
List<SimpleNode> slides = slideShowNode.out("slides")
.collect(Collectors.toCollection(ArrayList::new));
debug=true;
if (debug)
slides.forEach(slide -> slide.printNameValues(System.out));
assertEquals(44, slides.size());
}
Does not work - i get 0 slides instead of 44. Is this a bug or exists a workaround?
My name is Wolfgang Fahl i am one of the committers of the SimpleGraph OpenSource Project.
I would consider this a bug/missing feature. The base question is what parameters moveTo should accept in the case of file/inputstream based modules. Powerpoint files can be read from any input inputstream with the Apache POI module. SimpleGraph needs a consistent way of handling the different cases of input and I think this is a valid discussion that should be done in the SimpleGraph dicussion group.
To fix your current issue I modified the code as a work around to make sure the Unit Tests runs and added your Unit Test to TestPowerPoint.
Current Workaround
The following is part of the Commit to fix your issue
/**
* create a SlideShow
*
* #param simpleGraph
* #param nodeQuery
* #throws Exception
*/
public SlideShowNode(SimpleGraph simpleGraph, String pathOrUrl,
String... keys) {
super(simpleGraph, "slideshow", keys);
InputStream is = null;
try {
try {
URL url = new URL(pathOrUrl);
is = url.openStream();
} catch (MalformedURLException e1) {
this.pathOrUl = pathOrUrl;
pptFile = new File(pathOrUl);
if (pptFile.canRead())
is = new FileInputStream(pathOrUl);
}
if (is != null)
slideshow = new XMLSlideShow(is);
else
slideshow = new XMLSlideShow();
} catch (IOException e) {
throw new RuntimeException(e);
}
super.setVertexFromMap();
}

OpenNLP model builder addon doesnt continue

I'm using the model builder addon for OpenNLP to create a better NER model.
According to this post, I have used the code posted by markg :
public class ModelBuilderAddonUse {
private static List<String> getSentencesFromSomewhere() throws Exception
{
List<String> list = new ArrayList<String>();
BufferedReader reader = new BufferedReader(new FileReader("D:\\Work\\workspaces\\default\\UpdateModel\\documentrequirements.docx"));
String line;
while ((line = reader.readLine()) != null)
{
list.add(line);
}
reader.close();
return list;
}
public static void main(String[] args) throws Exception {
/**
* establish a file to put sentences in
*/
File sentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\sentences.text");
/**
* establish a file to put your NER hits in (the ones you want to keep based
* on prob)
*/
File knownEntities = new File("D:\\Work\\workspaces\\default\\UpdateModel\\knownentities.txt");
/**
* establish a BLACKLIST file to put your bad NER hits in (also can be based
* on prob)
*/
File blacklistedentities = new File("D:\\Work\\workspaces\\default\\UpdateModel\\blentities.txt");
/**
* establish a file to write your annotated sentences to
*/
File annotatedSentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\annotatedSentences.txt");
/**
* establish a file to write your model to
*/
File theModel = new File("D:\\Work\\workspaces\\default\\UpdateModel\\nl-ner-person.bin");
//------------create a bunch of file writers to write your results and sentences to a file
FileWriter sentenceWriter = new FileWriter(sentences, true);
FileWriter blacklistWriter = new FileWriter(blacklistedentities, true);
FileWriter knownEntityWriter = new FileWriter(knownEntities, true);
//set some thresholds to decide where to write hits, you don't have to use these at all...
double keeperThresh = .95;
double blacklistThresh = .7;
/**
* Load your model as normal
*/
TokenNameFinderModel personModel = new TokenNameFinderModel(new File("D:\\Work\\workspaces\\default\\UpdateModel\\nl-ner-person.bin"));
NameFinderME personFinder = new NameFinderME(personModel);
/**
* do your normal NER on the sentences you have
*/
for (String s : getSentencesFromSomewhere()) {
sentenceWriter.write(s.trim() + "\n");
sentenceWriter.flush();
String[] tokens = s.split(" ");//better to use a tokenizer really
Span[] find = personFinder.find(tokens);
double[] probs = personFinder.probs();
String[] names = Span.spansToStrings(find, tokens);
for (int i = 0; i < names.length; i++) {
//YOU PROBABLY HAVE BETTER HEURISTICS THAN THIS TO MAKE SURE YOU GET GOOD HITS OUT OF THE DEFAULT MODEL
if (probs[i] > keeperThresh) {
knownEntityWriter.write(names[i].trim() + "\n");
}
if (probs[i] < blacklistThresh) {
blacklistWriter.write(names[i].trim() + "\n");
}
}
personFinder.clearAdaptiveData();
blacklistWriter.flush();
knownEntityWriter.flush();
}
//flush and close all the writers
knownEntityWriter.flush();
knownEntityWriter.close();
sentenceWriter.flush();
sentenceWriter.close();
blacklistWriter.flush();
blacklistWriter.close();
/**
* THIS IS WHERE THE ADDON IS GOING TO USE THE FILES (AS IS) TO CREATE A NEW MODEL. YOU SHOULD NOT HAVE TO RUN THE FIRST PART AGAIN AFTER THIS RUNS, JUST NOW PLAY WITH THE
* KNOWN ENTITIES AND BLACKLIST FILES AND RUN THE METHOD BELOW AGAIN UNTIL YOU GET SOME DECENT RESULTS (A DECENT MODEL OUT OF IT).
*/
DefaultModelBuilderUtil.generateModel(sentences, knownEntities, blacklistedentities, theModel, annotatedSentences, "person", 3);
}
}
It also runs, but my output quits at :
annotated sentences: 1862
knowns: 58
Building Model using 1862 annotations
reading training data...
But in the example in the post it should go futher like this :
Indexing events using cutoff of 5
Computing event counts... done. 561755 events
Indexing... done.
Sorting and merging events... done. Reduced 561755 events to 127362.
Done indexing.
Incorporating indexed data for training...
done.
Number of Event Tokens: 127362
Number of Outcomes: 3
Number of Predicates: 106490
...done.
Can anyone help me to fix this problem, so I can generate a model?
I have searched realy a lot but cant find any good documutation about it.
Would really appreciat it, thanks.
Correct the path to your training data file like this:
File sentences = new File("D:/Work/workspaces/default/UpdateModel/sentences.text");
instead of
File sentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\sentences.text");
Update
This is how is used, by adding the files to the project folder. Try it like this -
File sentences = new File("src/training/resources/CreateModel/sentences.txt");
Check my respository for reference on Github
This should help.

Error while retrieving images from pdf using Itext

I have an existing PDF from which I want to retrieve images
NOTE:
In the Documentation, this is the RESULT variable
public static final String RESULT = "results/part4/chapter15/Img%s.%s";
I am not getting why this image is needed?I just want to extract the images from my PDF file
So Now when I use MyImageRenderListener listener = new MyImageRenderListener(RESULT);
I am getting the error:
results\part4\chapter15\Img16.jpg (The system
cannot find the path specified)
This is the code that I am having.
package part4.chapter15;
import java.io.IOException;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
/**
* Extracts images from a PDF file.
*/
public class ExtractImages {
/** The new document to which we've added a border rectangle. */
public static final String RESOURCE = "resources/pdfs/samplefile.pdf";
public static final String RESULT = "results/part4/chapter15/Img%s.%s";
/**
* Parses a PDF and extracts all the images.
* #param src the source PDF
* #param dest the resulting PDF
*/
public void extractImages(String filename)
throws IOException, DocumentException {
PdfReader reader = new PdfReader(filename);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
MyImageRenderListener listener = new MyImageRenderListener(RESULT);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
parser.processContent(i, listener);
}
reader.close();
}
/**
* Main method.
* #param args no arguments needed
* #throws DocumentException
* #throws IOException
*/
public static void main(String[] args) throws IOException, DocumentException {
new ExtractImages().extractImages(RESOURCE);
}
}
You have two questions and the answer to the first question is the key to the answer of the second.
Question 1:
You refer to:
public static final String RESULT = "results/part4/chapter15/Img%s.%s";
And you ask: why is this image needed?
That question is wrong, because Img%s.%s is not a filename of an image, it's a pattern of the filename of an image. While parsing, iText will detect images in the PDF. These images are stored in numbered objects (e.g. object 16) and these images can be exported in different formats (e.g. jpg, png,...).
Suppose that an image is stored in object 16 and that this image is a jpg, then the pattern will resolve to Img16.jpg.
Question 2:
Why do I get an error:
results\part4\chapter15\Img16.jpg (The system cannot find the path specified)
In your PDF, there's a jpg stored in object 16. You are asking iText to store that image using this path: results\part4\chapter15\Img16.jpg (as explained in my answer to Question 1). However: you working directory doesn't have the subdirectories results\part4\chapter15\, hence an IOException (or a FileNotFoundException?) is thrown.
What is the general problem?
You have copy/pasted the ExtractImages example I wrote for my book "iText in Action - Second Edition", but:
You didn't read that book, so you have no idea what that code is supposed to do.
You aren't telling the readers on StackOverflow that this example depends on the MyImageRenderer class, which is where all the magic happens.
How can you solve your problem?
Option 1:
Change RESULT like this:
public static final String RESULT = "Img%s.%s";
Now the images will be stored in your working directory.
Option 2:
Adapt the MyImageRenderer class, more specifically this method:
public void renderImage(ImageRenderInfo renderInfo) {
try {
String filename;
FileOutputStream os;
PdfImageObject image = renderInfo.getImage();
if (image == null) return;
filename = String.format(path,
renderInfo.getRef().getNumber(), image.getFileType());
os = new FileOutputStream(filename);
os.write(image.getImageAsBytes());
os.flush();
os.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
iText calls this class whenever an image is encountered. It passed an ImageRenderInfo to this method that contains plenty of information about that image.
In this implementation, we store the image bytes as a file. This is how we create the path to that file:
String.format(path,
renderInfo.getRef().getNumber(), image.getFileType())
As you can see, the pattern stored in RESULT is used in such a way that the first occurrence of %s is replaced with a number and the second occurrence with a file extension.
You could easily adapt this method so that it stores the images as byte[] in a List if that is what you want.

Save Excel file with OLE, Java on Eclipse RCP Application

I try to Save an Excel file. The Excel file is a template with makros (*.xltm). I can open the file and edit the content, but if i try to save the destination Excel file is corrupt.
I try to save the file with:
int id = _workbook.getIDsOfNames(new String[] {"Save"})[0];
_workbook.invoke(id);
or/and
_xlsClientSite.save(_file, true);
You might try specifying a file format in your Save call.
If you're lucky, you can find the file format code you need in the Excel help. If you can't find what you need there, you'll have to get your hands dirty using the OLEVIEW.EXE program. There's likely a copy of it sitting on your hard drive somewhere, but if not, it's easy enough to find a copy with a quick Google search.
To use OLEVIEW.EXE:
Run it
Crack open the 'Type Libraries' entry
Find the version of Excel that you're using
Open that item
Search the enormous pile of text that's displayed for the string 'XlFileFormat'
Examine the XLFileFormat enum for a code that seems promising
If you are using Office2007 ("Excel12") like I am, you might try one of these values:
xlOpenXMLWorkbookMacroEnabled = 52
xlOpenXMLTemplateMacroEnabled = 53
Here's a method that I use to save Excel files using OLE:
/**
* Save the given workbook in the specified format.
*
* #param controlSiteAuto the OLE control site to use
* #param filepath the file to save to
* #param formatCode XlFileFormat code representing the file format to save as
* #param replaceExistingWithoutPrompt true to replace an existing file quietly, false to ask the user first
*/
public void saveWorkbook(OleAutomation controlSiteAuto, String filepath, Integer formatCode, boolean replaceExistingWithoutPrompt) {
Variant[] args = null;
Variant result = null;
try {
// suppress "replace existing?" prompt, if necessary
if (replaceExistingWithoutPrompt) {
setPropertyOnObject(controlSiteAuto, "Application", "DisplayAlerts", "False");
}
// if the given formatCode is null, for some reason, use a reasonable default
if (formatCode == null) {
formatCode = 51; // xlWorkbookDefault=51
}
// save the workbook
int[] id = controlSiteAuto.getIDsOfNames(new String[] {"SaveAs", "FileName", "FileFormat"});
args = new Variant[2];
args[0] = new Variant(filepath);
args[1] = new Variant(formatCode);
result = controlSiteAuto.invoke(id[0], args);
if (result == null || !result.getBoolean()) {
throw new RuntimeException("Unable to save active workbook");
}
// enable alerts again, if necessary
if (replaceExistingWithoutPrompt) {
setPropertyOnObject(controlSiteAuto, "Application", "DisplayAlerts", "True");
}
} finally {
cleanup(args);
cleanup(result);
}
}
protected void cleanup(Variant[] variants) {
if (variants != null) {
for (int i = 0; i < variants.length; i++) {
if (variants[i] != null) {
variants[i].dispose();
}
}
}
}

Categories

Resources