1

I am writing a code to read a .doc file as a template and write data in new .doc file after various iterations. My code seems to have some simple issue that I am not able to figure out.

Below is the code I have written, [I got basic skeleton somewhere on stackoverflow only.]

public class HWPFTest {

  public static void main(String[] args) {
        String inputFile = "F:\\docx\\input.doc";
        String outputFile = "F:\\docx\\output.doc";
        POIFSFileSystem fs = null;

        try {
              for (int i = 0; i < 3; i++) {
                    fs = new POIFSFileSystem(new FileInputStream(inputFile));
                    HWPFDocument doc = new HWPFDocument(fs);
                    System.out.println("LOOOOOOOOOOOOP ----> " + i);
                    doc = replaceText(doc, "$count", String.valueOf(i));
                    doc = replaceText(doc, "$filename", "FileName" + i);
                    doc = replaceText(doc, "$inputFile", "Input" + i);
                    doc = replaceText(doc, "$outputFile", "Output" + i);
                    doc = replaceText(doc, "$message", "Message" + i);
                    doc = replaceText(doc, "$snap", "Snapshot" + i);
                    saveWord(outputFile, doc);
              }
              System.out.println("DONE...");
        }
        catch (FileNotFoundException e) {
              e.printStackTrace();
        } catch (IOException e) {
              e.printStackTrace();
        }
  }

  private static HWPFDocument replaceText(HWPFDocument doc, String findText, String replaceText) {
        Range r1 = doc.getRange();
        for (int i = 0; i < r1.numSections(); ++i) {
              Section s = r1.getSection(i);
              for (int x = 0; x < s.numParagraphs(); x++) {
                    Paragraph p = s.getParagraph(x);
                    for (int z = 0; z < p.numCharacterRuns(); z++) {
                          CharacterRun run = p.getCharacterRun(z);
                          String text = run.text();
                          if (text.contains(findText)) {
                               run.replaceText(findText, replaceText);
                               System.out.println("findText: " + findText + " replaceText: " + replaceText);
                          }
                    }
              }
        }
        return doc;
  }


  private static void saveWord(String filePath, HWPFDocument doc) throws FileNotFoundException, IOException {
        FileOutputStream out = null;
        try {
              // Add true to make the data append possible in output stream.
              out = new FileOutputStream(filePath, true);
              doc.write(out);
              out.flush();
        } catch (Exception ex) {
              ex.printStackTrace();
        } finally {
              out.close();
        }
  }

}

The code works without any issues. Here is how the input.doc looks, input.doc

After the successful run, the output.doc is also generated. But the issue is that it contains data for only first loop.

Ideaally, it should contain data for all the 3 iterations, but it contains data for only first and then there is nothing. It doesn't show any error / exception during execution as well. I have also made sure that outputstream will have append option as true.

This is how the output.doc looks, output.doc

Not sure, what I am doing wrong.

When I run the program, I can see in the output below,

LOOOOOOOOOOOOP ----> 0 findText: $count replaceText: 0 findText: $filename replaceText: FileName0 findText: $inputFile replaceText: Input0 findText: $outputFile replaceText: Output0 findText: $message replaceText: Message0 findText: $snap replaceText: Snapshot0 LOOOOOOOOOOOOP ----> 1 findText: $count replaceText: 1 findText: $filename replaceText: FileName1 findText: $inputFile replaceText: Input1 findText: $outputFile replaceText: Output1 findText: $message replaceText: Message1 findText: $snap replaceText: Snapshot1 LOOOOOOOOOOOOP ----> 2 findText: $count replaceText: 2 findText: $filename replaceText: FileName2 findText: $inputFile replaceText: Input2 findText: $outputFile replaceText: Output2 findText: $message replaceText: Message2 findText: $snap replaceText: Snapshot2 DONE...

As I am initiating the input file as new in every iteration. So I do find all the $ elements during iteration. It's just that they don't get appended in final file.

Can someone please help here? Thanks a lot.

2 Answers 2

1

You are opening your template file, changing content and saving to "F:\docx\output.doc". You do this for 3 times and each time you overwrite the output file.

It will be much more better to prepare string in loop and then only once replace in document. Your main method will look like:

public static void main(String[] args) {
        String inputFile = "F:\\docx\\input.doc";
        String outputFile = "F:\\docx\\output.doc";
        POIFSFileSystem fs = null;

        String counts = "";

        try {
            for (int i = 0; i < 3; i++) {
                counts += String.valueOf(i) + "; ";
            }
            fs = new POIFSFileSystem(new FileInputStream(inputFile));
            HWPFDocument doc = new HWPFDocument(fs);
            doc = replaceText(doc, "$count", counts);
            saveWord(outputFile, doc);
        }
        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
Sign up to request clarification or add additional context in comments.

3 Comments

I have added the console output in question above that I see when I run the program. It also indicated that the $ elements are found and being replaced with every iteration.
Yes i was a bit wrong) you are opening your template file, changing content and saving to "F:\\docx\\output.doc". You do this for 3 times and each time you overwrite the output file. So, try the solution i provided you in answer.
Actually the contents I am showing in question are dummy contents, for simplicity to be readable for everyone. The actual contents will be filenames with path, and that will also contain special characters in filename or file path. So If I try to add that in string, it will break due to it. What I have right now, works perfectly. The only issue is I don't know of any method in POI that would help me appending contents of all iterations into single file. Are you aware of any other technique that might work.
0

Apparently and surprisingly, Apache POI doesn't have any method to write with append to an existing word document. So above approach doesn't work.

I also tried Apache FileUtils, but it doesn't retain the formating of the word document. I also tried docx4j, but in only works on docx files and its merging utility class is paid.

There is another framework, Aspose Words, which provides much better control and flexibility. It lets you append the content to existing document, with a limitation of 1150 characters. But that's way too much for my requirement to worry for as my writing wasn't more than the set limit.

So I used that to achieve what I wanted to do. It's a success finally.

Thanks for the help @D. Krauchanka

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.