关于POI工具类绘制水印,箭头等功能

绘制水印:

复制代码
 /**
     * 绘制水印图片
     * @param text
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage createWatermarkImage(String text, Integer width, Integer height) {
        java.awt.Font font = new java.awt.Font("microsoft-yahei", java.awt.Font.PLAIN, 20);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // ----------  增加下面的代码使得背景透明  -----------------
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g.dispose();
        // ----------  背景透明代码结束  -----------------

        g = image.createGraphics();
        g.setColor(new java.awt.Color(Integer.parseInt("C5CBCF", 16)));// 设定画笔颜色
        g.setFont(font);// 设置画笔字体
        g.shear(0.1, -0.26);// 设定倾斜度
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 设置字体平滑


        // 字体长度
        //int markWidth = font.getSize() * getTextLength (text);
        int markWidth = font.getSize() * text.length();
        // 字体高度
        int markHeight = font.getSize();

        // 循环添加水印
        int  x = 0;
        int y = 50;
        while (x < width) {
            while (y < height) {
                g.drawString (text, x, y);
                y += markHeight + 100;
            }
            x += markWidth + 150;
            y = 50;
        }



        g.dispose();// 释放画笔
        return image;

    }



    /**
     * 为Excel打上水印工具函数
     * 请自行确保参数值,以保证水印图片之间不会覆盖。
     * 在计算水印的位置的时候,并没有考虑到单元格合并的情况,请注意
     * @param wb       Excel Workbook
     * @param sheet    需要打水印的Excel
     * @param waterRemarkPath  水印地址,classPath,目前只支持png格式的图片,
     *                         因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。
     *                         同时请注意传入的地址格式,应该为类似:"\\excelTemplate\\test.png"
     * @throws IOException
     */
    public static void putWaterRemarkToExcel(Workbook wb,Sheet sheet, BufferedImage waterRemarkPath) throws IOException{

        //加载图片
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        if(null == waterRemarkPath) {
            throw new RuntimeException("向Excel上面打印水印,读取水印图片失败(2)。");
        }
        ImageIO.write(waterRemarkPath,"png",byteArrayOut);
        //开始打水印
        Drawing drawing = sheet.createDrawingPatriarch();
        /*
         * 参数定义:
         * 第一个参数是(x轴的开始节点);
         * 第二个参数是(是y轴的开始节点);
         * 第三个参数是(是x轴的结束节点);
         * 第四个参数是(是y轴的结束节点);
         * 第五个参数是(是从Excel的第几列开始插入图片,从0开始计数);
         * 第六个参数是(是从excel的第几行开始插入图片,从0开始计数);
         * 第七个参数是(图片宽度,共多少列);
         * 第8个参数是(图片高度,共多少行);
         */
        ClientAnchor anchor = drawing.createAnchor(0, 0, 255, 255, 0, 0, 1, 1);
        Picture pic = drawing.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG));
        pic.resize();


        // 将表格设为只读,否则水印就没了意义
//        sheet.protectSheet(UUID.randomUUID().toString());
    }
复制代码

 

 

插入箭头:

复制代码
/**
     * 绘制箭头
     * @param sheet
     * @param col1  第1个单元格的行号
     * @param col1  第1个单元格的列号
     * @param row1  第2个单元格的行号
     * @param row2   第2个单元格的列号
     */
    public static void createArrow(XSSFSheet sheet, int col1, int row1, int col2, int row2){
        // 计算偏移量
        int dx1 = (sheet.getColumnWidth(col1)/2+500)*255;
        int dy1 = (sheet.getRow(row1).getHeight()+800)*255;
        int dx2 = (sheet.getColumnWidth(col2)/2+500)*255;
        int dy2 = (sheet.getRow(row2).getHeight()-200)*255;

        XSSFDrawing xssfdrawing = sheet.createDrawingPatriarch(); //顶级画布,只能有一个
        /** 从左上角到右下角 */
        if(col1 <= col2 && row1 <= row2) {
            XSSFClientAnchor xssfanchor = new XSSFClientAnchor(dx1,dy1,dx2,dy2,col1, row1,col2,row2);
            XSSFSimpleShape xssfshape = xssfdrawing.createSimpleShape(xssfanchor);
            xssfshape.setShapeType(ShapeTypes.LINE);
            xssfshape.setLineWidth(1.5);
            xssfshape.setLineStyle(0);
            xssfshape.setLineStyleColor(0, 0, 0);
            xssfshape.getCTShape().getSpPr().getLn().addNewTailEnd().setType(STLineEndType.TRIANGLE);
        }
        /** 从左下角到右上角 */
        if(col1 <= col2 && row1 > row2) {
            // 方法只支持col1<col2且row1<row2的情况,所以此处需要反向传值,后面再反射显示
            XSSFClientAnchor xssfanchor = new XSSFClientAnchor(dx1,dy1,dx2,dy2,col1, row2,col2,row1);
            XSSFSimpleShape xssfshape = xssfdrawing.createSimpleShape(xssfanchor);
            xssfshape.setShapeType(ShapeTypes.LINE);
            xssfshape.setLineWidth(1.5);
            xssfshape.setLineStyle(0);
            xssfshape.setLineStyleColor(0, 0, 0);
            xssfshape.getCTShape().getSpPr().getXfrm().setFlipV(true);  // 将图形反射显示
            xssfshape.getCTShape().getSpPr().getLn().addNewTailEnd().setType(STLineEndType.TRIANGLE);
        }
        /** 从右下角到左上角 */
        if(col1 > col2 && row1 > row2) {
            XSSFClientAnchor xssfanchor = new XSSFClientAnchor(dx1,dy1,dx2,dy2,col2, row2,col1,row1);
            XSSFSimpleShape xssfshape = xssfdrawing.createSimpleShape(xssfanchor);
            xssfshape.setShapeType(ShapeTypes.LINE);
            xssfshape.setLineWidth(1.5);
            xssfshape.setLineStyle(0);
            xssfshape.setLineStyleColor(0, 0, 0);
            // 由于线是从左上角到右下角绘制,所以此处将箭头标在起点处
            xssfshape.getCTShape().getSpPr().getLn().addNewHeadEnd().setType(STLineEndType.TRIANGLE);
        }
        /** 从右上角到左下角 */
        if(col1 > col2 && row1 <= row2) {
            // 方法只支持col1<col2且row1<row2的情况,所以此处需要反向传值,后面再反射显示
            XSSFClientAnchor xssfanchor = new XSSFClientAnchor(dx1,dy1,dx2,dy2,col2, row1,col1,row2);
            XSSFSimpleShape xssfshape = xssfdrawing.createSimpleShape(xssfanchor);
            xssfshape.setShapeType(ShapeTypes.LINE);
            xssfshape.setLineWidth(1.5);
            xssfshape.setLineStyle(0);
            xssfshape.setLineStyleColor(0, 0, 0);
            xssfshape.getCTShape().getSpPr().getXfrm().setFlipV(true); // 将图形反射显示
            xssfshape.getCTShape().getSpPr().getLn().addNewHeadEnd().setType(STLineEndType.TRIANGLE);
        }
    }
复制代码

 

插入图片:

复制代码
 /**
     * 插入图片
     * @param wb
     * @param sheet
     * @param imgUrl
     * @param col1
     * @param row1
     * @param col2
     * @param row2
     */
    public static void createPicture(XSSFWorkbook wb, XSSFSheet sheet, String imgUrl, int col1, int row1, int col2, int row2) {
        try {
            // 计算图片偏移量,使图片居中
            int dx1 = sheet.getColumnWidth(col1)/2*255;
            int dy1 = ((row2-row1)*sheet.getRow(row1).getHeight()/2+600)*255;


            // 固定图片大小
            double standardWidth = 2000;  // 目标大小
            double standardHeight = 600;
            double cellWidth = sheet.getColumnWidth(col1); // 计算单元格的长宽
            double cellHeight = (row2-row1)*sheet.getRow(row1).getHeight();
            double a = standardWidth / cellWidth; // 计算需要的长宽比例的系数
            double b = standardHeight / cellHeight;


            ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
            InputStream input = getImageInputStream(imgUrl);
            byte[] buffer = new byte[100];
            int n;
            while ((n = input.read(buffer)) != -1) {
                byteArrayOut.write(buffer, 0, n);
            }
            XSSFDrawing patriarch = sheet.createDrawingPatriarch();
            XSSFClientAnchor anchor= new XSSFClientAnchor(dx1,dy1,0,0,col1,row1,col2,row2);
            Picture pict = patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG));
            pict.resize(a,b);

            input.close();
            byteArrayOut.flush();
            byteArrayOut.close();//不要忘记关闭InputStream 与ByteArrayOutputStream ,不然导出时会报错
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    //从存储图片的服务器读取图片流
    private static InputStream getImageInputStream(String imgUrl) throws Exception{
        HttpURLConnection httpURLConnection = null;
        InputStream inputStream = null;
        URL url = new URL(imgUrl);
        httpURLConnection = (HttpURLConnection) url.openConnection();
        // 设置网络连接超时时间
        httpURLConnection.setConnectTimeout(5000);
        // 设置应用程序要从网络连接读取数据
        httpURLConnection.setDoInput(true);
        httpURLConnection.setRequestMethod("GET");
        int responseCode = httpURLConnection.getResponseCode();
        if (responseCode == 200) {
            // 从服务器返回一个输入流
            inputStream = httpURLConnection.getInputStream();
        }

        return inputStream;
    }
复制代码

 

posted @   高富贵  阅读(680)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示