Я новичок в разработке java apache POI, я пытаюсь добавить водяной знак, чтобы превзойти, используя приведенный ниже код. Но идентификатор водяного знака перекрывает содержимое, стоящее за ним. Я хочу добавить водяной знак в фоновом режиме.
public class xlWatermark {
public static void main(String[] args) {
HSSFWorkbook wb = new HSSFWorkbook();
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream("Test.xls");
HSSFSheet ws = wb.createSheet("testSheet");
HSSFPatriarch dp = ws.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor
(0, 0, 1023, 255, (short) 2, 4, (short) 13, 26);
HSSFTextbox txtbox = dp.createTextbox(anchor);
HSSFRichTextString rtxt = new HSSFRichTextString("test");
HSSFFont font = wb.createFont();
font.setColor((short) 27);
font.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
font.setFontHeightInPoints((short) 192);
font.setFontName("Verdana");
rtxt.applyFont(font);
txtbox.setString(rtxt);
txtbox.setLineStyle(HSSFShape.LINESTYLE_NONE);
txtbox.setNoFill(true);
wb.write(fileOut);
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Не могли бы вы помочь мне и рассказать, как я могу добавить водяной знак в Excel (XSSF или в книгу HSSF) или добавить изображение в заголовок exel
Спасибо Мудассир
Да, Аксель, у меня вопрос, как вставить картинку в заголовок Excel. Я не нашел способа поместить изображение в заголовок, строка, которую я могу вставить в заголовок, но не изображение
Смотрите мой ответ. Это заняло некоторое время, потому что мне пришлось сократить свой продуктивный код, который, конечно, стал намного больше и более модульным, до минимального рабочего примера снова. Как-то мой рабочий черновик затерялся. К счастью - спасибо stackoverflow; -) - теперь он у меня вернулся.
это близко к цели. Я также создал текстовое поле, но я не могу его повернуть с определенной степенью.




Microsoft Excel не имеет встроенной функции водяных знаков. Однако есть несколько способов имитировать внешний вид водяного знака. .. Но, к сожалению, ни один из них напрямую не поддерживается apache poi.
Если бы требовалось только XSSF, тогда можно было бы программировать изображение в заголовке, используя нижележащие низкоуровневые объекты XSSF.
Файл *.xlsx - это просто архив ZIP. Так что мы можем разархивировать его и взглянуть на внутреннее устройство. Так что создайте файл *.xlsx с изображением в заголовке, а затем посмотрите архив *.xlsxZIP.
Там, в /xl/worksheets/sheet1.xml, то есть в листах XML, мы находим что-то вроде:
...
<headerFooter>
<oddHeader>&C&G</oddHeader>
</headerFooter>
<legacyDrawingHF r:id = "rId1"/>
...
Итак, у нас есть &G, который указывает на графику в заголовке &Center. И у нас есть идентификатор отношения, который указывает на устаревший рисунок.
Этот устаревший рисунок мы находим в /xl/drawings/vmlDrawing1.vml. В этом файле *.vml также есть отношение к образу в /xl/media/.
Итак, что мы должны сделать, это
apache poi.Помещение "& G" в центральный заголовок. Это также фактически уже обеспечивается apache poi.
Создание /xl/drawings/vmlDrawing1.vml как PackagePart и создание POIXMLDocumentPart, который предоставляет метод commit() для сохранения его XML в пакет при записи файла.
Следующий код - это рабочий проект, который показывает принцип. Как изображение, я загрузил AF101880439_en-us_draft.png со связанной страницы поддержки Microsoft.
Код завершен, работает и создает файл результата *.xlsx с DRAFT-изображением в центре заголовка первого листа.
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.ss.util.ImageUtils;
import org.apache.poi.openxml4j.opc.*;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.xmlbeans.XmlObject;
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
public class CreateExcelPictureInHeaderAKAWatermark {
static void createPictureForHeader(XSSFSheet sheet, int pictureIdx, String pictureTitle, int vmlIdx, String headerPos) throws Exception {
OPCPackage opcpackage = sheet.getWorkbook().getPackage();
//creating /xl/drawings/vmlDrawing1.vml
PackagePartName partname = PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing" + vmlIdx+ ".vml");
PackagePart part = opcpackage.createPart(partname, "application/vnd.openxmlformats-officedocument.vmlDrawing");
//creating new VmlDrawing
VmlDrawing vmldrawing = new VmlDrawing(part);
//creating the relation to the picture in /xl/drawings/_rels/vmlDrawing1.vml.rels
XSSFPictureData picData = sheet.getWorkbook().getAllPictures().get(pictureIdx);
String rIdPic = vmldrawing.addRelation(null, XSSFRelation.IMAGES, picData).getRelationship().getId();
//get image dimension
ByteArrayInputStream is = new ByteArrayInputStream(picData.getData());
java.awt.Dimension imageDimension = ImageUtils.getImageDimension(is, picData.getPictureType());
is.close();
//updating the VmlDrawing
vmldrawing.setRIdPic(rIdPic);
vmldrawing.setPictureTitle(pictureTitle);
vmldrawing.setImageDimension(imageDimension);
vmldrawing.setHeaderPos(headerPos);
//creating the relation to /xl/drawings/vmlDrawing1.xml in /xl/worksheets/_rels/sheet1.xml.rels
String rIdExtLink = sheet.addRelation(null, XSSFRelation.VML_DRAWINGS, vmldrawing).getRelationship().getId();
//creating the <legacyDrawingHF r:id = "..."/> in /xl/worksheets/sheetN.xml
sheet.getCTWorksheet().addNewLegacyDrawingHF().setId(rIdExtLink);
}
public static void main(String[] args) throws Exception {
Workbook workbook = new XSSFWorkbook();
Sheet sheet;
Header header;
InputStream is;
byte[] bytes;
int pictureIdx; //we need it later
sheet = workbook.createSheet();
header = sheet.getHeader();
header.setCenter("&G"); // &G means Graphic
//add picture data to this workbook
is = new FileInputStream("AF101880439_en-us_draft.png");
bytes = IOUtils.toByteArray(is);
pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
is.close();
//create header picture from picture data of this workbook
createPictureForHeader((XSSFSheet)sheet, pictureIdx, "AF101880439_en-us_draft", 1, "CH"/*CenterHeader*/);
FileOutputStream out = new FileOutputStream("CreateExcelPictureInHeader.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
//class for VmlDrawing
static class VmlDrawing extends POIXMLDocumentPart {
String rIdPic = "";
String pictureTitle = "";
java.awt.Dimension imageDimension = null;
String headerPos = "";
VmlDrawing(PackagePart part) {
super(part);
}
void setRIdPic(String rIdPic) {
this.rIdPic = rIdPic;
}
void setPictureTitle(String pictureTitle) {
this.pictureTitle = pictureTitle;
}
void setHeaderPos(String headerPos) {
this.headerPos = headerPos;
}
void setImageDimension(java.awt.Dimension imageDimension) {
this.imageDimension = imageDimension;
}
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
try {
XmlObject doc = XmlObject.Factory.parse(
"<xml xmlns:v=\"urn:schemas-microsoft-com:vml\""
+" xmlns:o=\"urn:schemas-microsoft-com:office:office\""
+" xmlns:x=\"urn:schemas-microsoft-com:office:excel\">"
+" <o:shapelayout v:ext=\"edit\">"
+" <o:idmap v:ext=\"edit\" data=\"1\"/>"
+" </o:shapelayout><v:shapetype id=\"_x0000_t75\" coordsize=\"21600,21600\" o:spt=\"75\""
+" o:preferrelative=\"t\" path=\"m@4@5l@4@11@9@11@9@5xe\" filled=\"f\" stroked=\"f\">"
+" <v:stroke joinstyle=\"miter\"/>"
+" <v:formulas>"
+" <v:f eqn=\"if lineDrawn pixelLineWidth 0\"/>"
+" <v:f eqn=\"sum @0 1 0\"/>"
+" <v:f eqn=\"sum 0 0 @1\"/>"
+" <v:f eqn=\"prod @2 1 2\"/>"
+" <v:f eqn=\"prod @3 21600 pixelWidth\"/>"
+" <v:f eqn=\"prod @3 21600 pixelHeight\"/>"
+" <v:f eqn=\"sum @0 0 1\"/>"
+" <v:f eqn=\"prod @6 1 2\"/>"
+" <v:f eqn=\"prod @7 21600 pixelWidth\"/>"
+" <v:f eqn=\"sum @8 21600 0\"/>"
+" <v:f eqn=\"prod @7 21600 pixelHeight\"/>"
+" <v:f eqn=\"sum @10 21600 0\"/>"
+" </v:formulas>"
+" <v:path o:extrusionok=\"f\" gradientshapeok=\"t\" o:connecttype=\"rect\"/>"
+" <o:lock v:ext=\"edit\" aspectratio=\"t\"/>"
+" </v:shapetype><v:shape id=\"" + headerPos + "\" o:spid=\"_x0000_s1025\" type=\"#_x0000_t75\""
+" style='position:absolute;margin-left:0;margin-top:0;"
+"width:" + (int)imageDimension.getWidth() + "px;height:" + (int)imageDimension.getHeight() + "px;"
+"z-index:1'>"
+" <v:imagedata o:relid=\""+ rIdPic + "\" o:title=\"" + pictureTitle + "\"/>"
+" <o:lock v:ext=\"edit\" rotation=\"t\"/>"
+" </v:shape></xml>"
);
doc.save(out, DEFAULT_XML_OPTIONS);
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
Требуются изменения в импорте, чтобы заставить эту работу работать с текущим apache poi 4.0.1:
...
//import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.xmlbeans.XmlObject;
//import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
...
Большое спасибо, Аксель, за то, что поделился этими ценными знаниями. Попробую реализовать то же самое. Спасибо
Спасибо, ваше решение работает для меня, но мне нужно было всегда просматривать это изображение прямо сейчас, его можно просматривать только тогда, когда я выбираю опцию view-> paglayout. Подскажите, как я могу всегда видеть изображение как водяной знак. @ Аксель Рихтер
Microsoft Excel не имеет встроенной функции водяных знаков. Однако есть несколько способов имитировать внешний вид водяного знака.. Но, к сожалению, ни один из них напрямую не поддерживается
apache poi. Их можно было программировать, используя нижележащие низкоуровневые объектыXSSF. Но тогда вопрос будет либо "Как вставить картинку в шапку?" или "Как поставить фоновое изображение на лист?" Какие из этих вопросов у вас есть?