Apache POI - watermark in Excel - different appearence in Excel and LibreOffice - apache-poi

I follow the sample and add pictures as watermark like the following:
private void addWaterMark4AllSheets() {
final BufferedImage image = FontImage.createWatermarkImage();
// Export to byte stream B
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", os);
} catch (final IOException e) {
e.printStackTrace();
}
final XSSFWorkbook wb = (XSSFWorkbook) workBook;
final int pictureIdx = wb.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
final POIXMLDocumentPart poixmlDocumentPart = wb.getAllPictures().get(pictureIdx);
// ((XSSFSheet )(schreiben.getSheet()).
for (int i = 0; i < workBook.getNumberOfSheets(); i++) {// Get each Sheet
final XSSFSheet sheet = wb.getSheetAt(i);
final PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
final String relType = XSSFRelation.IMAGES.getRelation();
// add relation from sheet to the picture data
final PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType,
null);
// set background picture to sheet
sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
}
}
In general the approach works quite fine. A picture is added into the Excel. But the appearance is different.
In Excel: the image is displayed in the background during the editing (of the sheets). But it is NOT displayed when I print the sheet.
In LibreOffice (7.1): the image is NOT displayed during the editing (of the sheet) - but is printed.
Is there a chance to fix it for working in both Spreadsheets?

There is nothing what apache poi could change as this behavior is by design in the different spreadsheet softwares.
Your linked code example does not creating watermarks. Watermark functionality is not available in Microsoft Excel. Instead it adds background pictures to sheets.
Microsoft itself states: You cannot print a background graphic for a Excel worksheet. So using Microsoft Excel the sheets background graphics only are visible in Excel GUI but not in prints.
In LibreOffice those background graphics are called watermarks but Libreoffice states in Defining Graphics or Colors in the Background of Pages (Watermark):
In spreadsheets this background appears only in the print behind the
cells not formatted elsewhere.
So using Libreoffice the sheets background graphics are visible in prints only.
So what you had observed is by design.
In Add or remove a sheet background Microsoft describes methods to mimic a watermark in Excel. The usage of a picture in a header or footer to mimic a watermark using apache poi is described in apache POI adding watermark in Excel workbook. But this also means a print watermark. So the watermark is visible in print preview and print only. It is not visible in sheet's GUI. And the option to add picture in a header or footer to mimic a watermark is Excel only. LibreOffice does not provide that feature.
Conclusion:
There is not a possibility to have a functionality similar to a watermark which works in Excel and LibreOffice the same way.

Related

Increasing height merged cells Apache POI

I am using Apache POI SXSSF to generate xlsx document. The document uses Times New Roman sizes 9 and 11, and the default cell width and height have been changed. The question is how to calculate the height of the merged cells so that all the text fits (the height of the cell must be dynamically set according to the given text)? The server running the application does not have a display, and this code is running in the IBM Integration Bus.
The solution from How to get the needed height of a multi line rich-text field (any font, any font size) having defined width using Java? is not suitable. The server running the application is missing a display and the string int ppi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution(); returns an exception, and manually picking the ppi value is also not possible. If there is a display, everything works correctly.
And is there any way to use the "align center selection" function somehow?
I found that centering a selection gives a similar result as merging multiple cells horizontally, but I couldn't find an answer anywhere on how to use this in Apache POI. As a result, experimentally, I found out that in order to achieve this effect, you need to do the following things:
Create CellStyle; specify setWrapText(true) and setAlignment(HorizontalAlignment.CENTER_SELECTION) for it
Apply the style created in step 1 to all cells that need to be merged
Specify the value in the first cell
Code example:
Font font = wb.createFont(); // where wb - is SXSSFWorkbook object
font.setFontName("Times New Roman");
font.setFontHeightInPoints((short) 11);
CellStyle style = wb.createCellStyle();
style.setFont(font);
style.setWrapText(true);
style.setAlignment(HorizontalAlignment.CENTER_SELECTION);
for (int i = 0; i <= endCellNum - firstCellNum; i++){ // where endCellNum - number of last cell of selection and firstCellNum is number of first cell of selection
Cell cell = curRow.createCell(firstCellNum + i);
cell.setCellStyle(cs);
if (i == 0){
firstCell = cell;
}
}
firstCell.setCellValue(value);

Excel with Interop in C#, how to hide the menu bar which remains displayed

I'm developing an application that needs to launch Excel, but the client wants Excel to be hidden. So far nothing very complicated, but when I launch Excel a 2nd "detached" menu bar is displayed (see the photo below), even when I hide Excel, this bar is visible.
Is there a way to not show it at all? Even if I want to show Excel for debugging?
Here is the bar:
enter image description here
I specify that when I open Excel normally, I do not have this additional menu bar.
I also specify that I launch a macro in Excel (it launches me solvers This is why I use Excel).
Code for open application:
private bool InitExcel(bool Visible)
{
try
{
//Démarre Excel et récupère l'application
_ApplicationXL = new Microsoft.Office.Interop.Excel.Application();
_LesWorkBooks = _ApplicationXL.Workbooks;
_ApplicationXL.Visible = Visible;
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
Thanks
I just use :
_ApplicationXL.Visible = Visible;
This hides excel well, but the bar remains displayed. Is a cause of using the macro to start Solvers, macro in VBA?

POI - Fixed width of image in Excel cell

I followed the approach to add a new image with the POI.
cell.getRow().setHeight(img.getHeightForExcel());
sheet.setColumnWidth(cell.getColumnIndex(), img.getWidthForExcel());
final int picID = workBook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
/* Create the drawing container */
final XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch();
// ========adding image START
final XSSFClientAnchor myAnchor = new XSSFClientAnchor();
myAnchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE);
/* Define top left corner, and we can resize picture suitable from there */
myAnchor.setCol1(cell.getColumnIndex()); // Column start
myAnchor.setRow1(rowNum - 1); // Row start
myAnchor.setCol2(cell.getColumnIndex() + 2); // Column end (covers two columns)
myAnchor.setRow2(rowNum); // Row end
/* Invoke createPicture and pass the anchor point and ID */
final XSSFPicture myPicture = drawing.createPicture(myAnchor, picID);
In principal this works quite well. I specify the width of the column at the beginning with the width of the image. (The height as well).
The major problem I'm facing is that as soon as I run autoadjust like
for (; i < max; i++) {
xlsWorkbook.getSheet().autoSizeColumn(i);
}
I get the problem that the first two columns are resized as well. But with this the width of the image is resized as well. Since the width might be quite long (or quite narrow) I don't want to affect the image size.
Is there a way to set the width of the image despite the column width?
If you don't want resizing the image when column widths are changing, then you cannot using that approach. This approach explicitly tells that the image shall be sized as the cell size it is anchored to. So if that cell size changes, the pictures size changes too.
You might think that ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE should protect the image from resizing. But this only is valuable when opened in Excel GUI. Apache poi does not respect ClientAnchor.AnchorType while auto sizing the columns. May be this will change in later versions. But in current version apache poi 5.0.0 it does not.
So to fulfill your requirement you set only a one cell anchor. That is only anchor.setCol1 and anchor.setRow1 as the upper left position of the picture. Then you need resizing the picture later to set the bottom right position. You must do that resizing after all column widths and row heights are set. So after auto sizing the columns. Else the resizing the columns will resizing the picture again.
Complete example:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ImageTest {
public static void main(String[] args) throws Exception {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("My Sample Excel");
//FileInputStream obtains input bytes from the image file
InputStream inputStream = new FileInputStream("./logo.png");
//Get the contents of an InputStream as a byte[].
byte[] bytes = IOUtils.toByteArray(inputStream);
//Adds a picture to the workbook
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
//close the input stream
inputStream.close();
//Returns an object that handles instantiating concrete classes
CreationHelper helper = wb.getCreationHelper();
//Creates the top-level drawing patriarch.
Drawing drawing = sheet.createDrawingPatriarch();
//Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
//Set anchor type; only valuable in Excel GUI
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
//Create an anchor with upper left cell only
anchor.setCol1(1); //Column B
anchor.setRow1(2); //Row 3
//Create a picture
Picture pict = drawing.createPicture(anchor, pictureIdx);
//Reset the image to the original size
//pict.resize(); // don't do this before autosize column
//Create cell in column B to auto sizing that column
Cell cell = sheet.createRow(0).createCell(1);
cell.setCellValue("12345678901234567890");
sheet.autoSizeColumn(1);
//Reset the image to the original size
//pict.resize();
//Reset the image to half the original size
pict.resize(0.5);
//Write the Excel file
FileOutputStream fileOut = null;
fileOut = new FileOutputStream("./myFile.xlsx");
wb.write(fileOut);
fileOut.close();
}
}

Apache POI insert image without anchor

I'm creating Excel file in Java using Apache POI, it works but the inserted image is anchored to columns / rows. There are 2 issues with this method:
The image doesn't keep the original size (get stretched a little bit).
When resizing the columns/rows the image get stretched. Is there any way to insert an image to Excel without anchor? (same as using Excel / Insert / Picture)
I'm using the following example from Apache POI document page:
//create a new workbook
Workbook wb = new XSSFWorkbook(); //or new HSSFWorkbook();
//add picture data to this workbook.
InputStream is = new FileInputStream("image1.jpeg");
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
is.close();
CreationHelper helper = wb.getCreationHelper();
//create sheet
Sheet sheet = wb.createSheet();
// Create the drawing patriarch. This is the top level container for all shapes.
Drawing drawing = sheet.createDrawingPatriarch();
//add a picture shape
ClientAnchor anchor = helper.createClientAnchor();
//set top-left corner of the picture,
//subsequent call of Picture#resize() will operate relative to it
anchor.setCol1(3);
anchor.setRow1(2);
Picture pict = drawing.createPicture(anchor, pictureIdx);
//auto-size picture relative to its top-left corner
pict.resize();
//save workbook
String file = "picture.xls";
if(wb instanceof XSSFWorkbook) file += "x";
FileOutputStream fileOut = new FileOutputStream(file);
wb.write(fileOut);
fileOut.close();
Thanks for your answer.
Proably that because of this comment in method 'resize' javadoc:
Please note, that this method works correctly only for workbooks with the default font size (Arial 10pt for .xls and Calibri 11pt for .xlsx). If the default font is changed the resized image can be streched vertically or horizontally.

How can I add the image to the Excel Sheet while Exporting from Gridview to Excel

I have a asp.net application in that I have grid view and I export that grid-view data into Excel it is working fine. But, now I want add the image(image getting from Server map-path) to the Excel sheet while export grid view data to Excel
How can I bind the image to excel?
Try the following code, i have tested it on local IIS, it is working properly and including the image like Header Image/Logo on top of the grid data.
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment; filename=test.xls;");
StringWriter stringWrite = new StringWriter();
HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
dgrExport.DataSource = dtExport;
dgrExport.DataBind();
dgrExport.RenderControl(htmlWrite);
string headerTable = #"<Table><tr><td><img src=""D:\\Folder\\1.jpg"" \></td></tr></Table>";
Response.Write(headerTable);
Response.Write(stringWrite.ToString());
Response.End();
you can adjust your image's height and width as per your requirement. Same height and width setting will be required for the <TD> tag.

Resources