@sabkan MS Word documents are flow by their nature, so there is no “page” concept. Consumer applications reflows document content into pages on the fly. Watermarks in MS Word document are added as a shape in the document header behind the main content. Since headers/footers are defined per section, to have a watermark only on the first page, the first page must be a separate section. You can achieve this by splitting the document into parts and then rejoining them. For example see the following code that adds a watermark only to the first page:
Document doc = new Document("C:\\Temp\\in.docx");
// Get the first page and remaining pages as separate documents.
Document firstPage = doc.extractPages(0, 1);
Document remainingPages = doc.extractPages(1, doc.getPageCount() - 1);
// Add watermark to the first page.
firstPage.getWatermark().setText("I am a cool watermark");
// make sure the remaining pages will not inherit headers/footers from the first page.
remainingPages.getFirstSection().getHeadersFooters().linkToPrevious(false);
// Rejoin the documents.
firstPage.appendDocument(remainingPages, ImportFormatMode.USE_DESTINATION_STYLES);
firstPage.save("C:\\Temp\\out.docx");
@sabkan You can use watermark options to specify color of the watermark. Also, you can get the inserted watermark shapes and change their properties. Please see the following code:
Document doc = new Document("C:\\Temp\\in.docx");
TextWatermarkOptions opt = new TextWatermarkOptions();
opt.setColor(Color.red);
opt.setLayout(WatermarkLayout.HORIZONTAL);
doc.getWatermark().setText("I am a cool watermark", opt);
// Get watermark shapes and move them down.
for (Shape s : (Iterable<Shape>)doc.getChildNodes(NodeType.SHAPE, true))
{
if (s.getName().startsWith("PowerPlusWaterMarkObject") || s.getName().startsWith("WordPictureWatermark"))
s.setVerticalAlignment(VerticalAlignment.BOTTOM);
}
doc.save("C:\\Temp\\out.docx");
You should use com.aspose.words.Shape not com.aspose.cells.Shape. Aspose.Words and Aspose.Cells are different packages, though they have some classes with the same names. So if you are using both packages, you should use fully qualified names of classes.
I encountered the same issue. Initially, I used TextWatermarkOptions, which preserved the linkToPrevious setting, but didn’t allow me to control the watermark shape’s height and width. So I followed your suggestion, but the following block of code also affects the shape in the footer:
for (Shape s : (Iterable<Shape>)doc.getChildNodes(NodeType.SHAPE, true))
{
if (s.getName().startsWith("PowerPlusWaterMarkObject") || s.getName().startsWith("WordPictureWatermark"))
s.setVerticalAlignment(VerticalAlignment.BOTTOM);
}
I’m using the example from the Aspose Words documentation on how to add a watermark to a document. However, it breaks the header section settings — specifically, the linkToPrevious option no longer works as expected.
Here’s the example code:
private void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect,
/*HeaderFooterType*/int headerType)
{
HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
if (header == null)
{
// There is no header of the specified type in the current section, so we need to create it.
header = new HeaderFooter(sect.getDocument(), headerType);
sect.getHeadersFooters().add(header);
}
// Insert a clone of the watermark into the header.
header.appendChild(watermarkPara.deepClone(true));
}
Do you have any suggestions on how to preserve the linkToPrevious setting while adding the watermark?
@qtnphan The problem occurs because the code creates header/footer if it does not exists. In MS Word if header/footer is not present, it is inherited from the previous section. Please modify your code like this:
private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType)
{
HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
if (header == null)
{
// Do not create header/footer if the section is not first.
if (sect != ((Document)sect.getDocument()).getFirstSection())
return;
// There is no header of the specified type in the current section, so we need to create it.
header = new HeaderFooter(sect.getDocument(), headerType);
sect.getHeadersFooters().add(header);
}
// Insert a clone of the watermark into the header.
header.appendChild(watermarkPara.deepClone(true));
}
You can skip shapes in footer by modifying code like this:
for (Shape s : (Iterable<Shape>)doc.getChildNodes(NodeType.SHAPE, true))
{
HeaderFooter hf = (HeaderFooter)s.getAncestor(NodeType.HEADER_FOOTER);
if (hf == null)
continue;
if (hf.getHeaderFooterType() == HeaderFooterType.FOOTER_FIRST ||
hf.getHeaderFooterType() == HeaderFooterType.FOOTER_EVEN ||
hf.getHeaderFooterType() == HeaderFooterType.FOOTER_PRIMARY)
continue;
if (s.getName().startsWith("PowerPlusWaterMarkObject") || s.getName().startsWith("WordPictureWatermark"))
s.setVerticalAlignment(VerticalAlignment.BOTTOM);
}