首页 > 其他分享 >POI导出excel文件加水印

POI导出excel文件加水印

时间:2024-10-07 10:00:13浏览次数:7  
标签:excel new protection 水印 加水 POI workbook import true

百分百能用,我用的POI版本是5.2.3,效果如下

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Excel表格添加水印
 */
@Slf4j
public class WaterMarkUtil {

    /**
     * Excel添加水印
     *
     * @param workbook      XSSFWorkbook
     * @param waterMarkText 水印文字内容
     */
    public static void insertWaterMarkTextToXlsx(XSSFWorkbook workbook, String waterMarkText) throws IOException {
        BufferedImage image = createWatermarkImage(waterMarkText);
        ByteArrayOutputStream imageOs = new ByteArrayOutputStream();
        ImageIO.write(image, "png", imageOs);
        int pictureIdx = workbook.addPicture(imageOs.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG);
        XSSFPictureData pictureData = workbook.getAllPictures().get(pictureIdx);
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
            XSSFSheet sheet = workbook.getSheetAt(i);
            PackagePartName ppn = pictureData.getPackagePart().getPartName();
            String relType = XSSFRelation.IMAGES.getRelation();
            PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
            sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
        }
    }

    /**
     * 创建水印图片
     *
     * @param waterMark 水印文字
     */
    public static BufferedImage createWatermarkImage(String waterMark) {
        String[] textArray = waterMark.split("\n");
        Font font = new Font(null, Font.PLAIN, 30);
        try {
            //指定字体位置 (宋体:simsun.ttf)
            String fontFilePath = "D:\\qxt\\feihuasongti.ttf";
            FileInputStream fontInputStream = new FileInputStream(fontFilePath);
            font = Font.createFont(Font.TRUETYPE_FONT, fontInputStream);
            font = font.deriveFont(30f);  // 设置字体大小为30
        } catch (Exception e) {
            log.error("指定使用汉字字体位置:", e);
            font = new Font("simsun", Font.PLAIN, 30);
        }
        //设置水印的密集程度,可以用调节图片大小来控制
        int width = 350;
        int height = 250;

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 背景透明 开始
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        // 背景透明 结束
        g = image.createGraphics();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));//设置水印透明度(0-1)之间
        g.setColor(new Color(Color.lightGray.getRGB()));// 设定画笔颜色
        g.setFont(font);// 设置画笔字体
        //g.shear(0.1, -0.26);// 设定倾斜度
        //设置字体平滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        //文字从中心开始输入,算出文字宽度,左移动一半的宽度,即居中
        FontMetrics fontMetrics = g.getFontMetrics(font);

        // 水印位置
        int x = width / 2;
        int y = height / 2;
        // 设置水印旋转
        g.rotate(Math.toRadians(-40), x, y);
        for (String s : textArray) {
            // 文字宽度
            int textWidth = fontMetrics.stringWidth(s);
            g.drawString(s, x - (textWidth / 2), y);// 画出字符串
            y = y + font.getSize();
        }
        g.dispose();// 释放画笔
        return image;
    }

    /**
     * 保护工作表以及设置保护选项
     */
    public static void protectWorksheet(XSSFWorkbook excel) {
        for (int i = 0; i < excel.getNumberOfSheets(); i++) {
            XSSFSheet sheet = excel.getSheetAt(i);
            // 保护工作表并设置密码
            sheet.protectSheet("8246");
            // 获取CTSheetProtection对象以进行更精细的控制
            CTSheetProtection protection = sheet.getCTWorksheet().getSheetProtection();
            // 设置保护选项(例如,允许用户选择未锁定的单元格)
            protection.setSheet(true);//控制是否保护整个工作表。默认为false,设置为true`后,用户不能修改工作表内容,除非解除了保护
            protection.setObjects(true);//如果为true,则禁止插入、删除或移动图表、图片等对象
            protection.setFormatCells(true);//是否允许用户格式化单元格
            protection.setFormatColumns(true);//是否允许用户格式化列
            protection.setFormatRows(true);//是否允许用户格式化行
            protection.setInsertColumns(true);//是否允许用户插入列
            protection.setInsertRows(true);//是否允许用户插入行
            protection.setDeleteColumns(true);//是否允许用户删除列
            protection.setDeleteRows(true);//是否允许用户删除行
            protection.setSelectLockedCells(true);//如果为false,则不允许选择锁定的单元格,即使整体工作表保护已被解除
            protection.setSelectUnlockedCells(true);//如果为false,则不允许选择未锁定的单元格,即使整体工作表保护已被解除
            protection.setSort(true);//如果设置为true,允许用户对受保护的工作表进行排序操作
            protection.setAutoFilter(true);//如果设置为true,允许用户在受保护的工作表上应用或编辑自动过滤器。
            protection.setPivotTables(true);//如果设置为true,允许用户在受保护的工作表上创建、修改或删除透视表
            protection.setInsertHyperlinks(true);//控制是否允许插入超链接
        }
    }

}
public static void main(String[] args) throws IOException {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("Sheet1");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String waterMarkText = "这是个水印\n" + dateFormat.format(new Date());
        WaterMarkUtil.insertWaterMarkTextToXlsx(workbook, waterMarkText);
        try (FileOutputStream fileOut = new FileOutputStream("watermark_example.xlsx")) {
            workbook.write(fileOut);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

标签:excel,new,protection,水印,加水,POI,workbook,import,true
From: https://www.cnblogs.com/kaotuzi/p/18449788

相关文章

  • 使用openpyxl读取Excel设置了公式的单元格 默认读取的是公式而不是公式结果
    使用openpyxl对单元格有公式的Excel的sheet进行操作,如果又读又写,可以采用双重读取方式解决。在Excel中,如果单元格的值是通过公式计算的,而你通过openpyxl库读取时发现获取的是公式而非结果,原因是openpyxl默认只读取单元格的公式而不计算公式的结果。为了获取公式计算后的......
  • Excel:vba实现根据输入的月份汇总数据的功能
    实现前的效果:实现后的效果:1.页面弹出想要汇总到的月份,就是指定月份的累计数2.输入月份之后开始进行汇总,汇总之后会弹出汇总成功的字样我输入1月份后,效果如下:代码如下:(可以删掉有关上面的b2单元格的几句话以及根据自己情况修改行和列,依然使用别的案例)Sub汇总数据()......
  • winforms基本操作-将datagridview内容保存为excel文件
    这里记录一下将winforms展示的datagridview,导出或保存为excel文件。这里说一下环境、版本信息:win系统:win11框架:winforms依赖:Microsoft.Office.Interop.Excel.net:8.0.401.netframework:4.8DataGridView对象为dataGridView1,然后添加一个按钮,绑定事件btnConfirm即可。priva......
  • Python 高级技巧:深入解析读取 Excel 文件的多种方法
    一、引言 在数据分析和处理中,经常需要从Excel文件中读取数据。Python提供了多种库来实现这个功能,本文将深入探讨使用 ​​pandas​​、​​openpyxl​​ 和 ​​xlrd​​ 库读取Excel文件的高级技巧和代码实现。 二、使用pandas库读取Excel文件 ​​pandas......
  • WPS股票价格查询EXCEL表格
    第一步在表格内使用公式=GetStockSource(Stock_code)查询股票的即时交易信息,Stock_code表示股票代码;第二步通过公式从Source中提取所需要的数据,可以提取股票名称、价格、涨跌幅、收盘价格、成交额、成交量、换手率等。公式如下:GetStockSource(Stock_code),查询股票即时交易信息G......
  • excel江湖异闻录--华麒麟
    认识他应该是在18、19年左右,那时就感觉这也是个高手,同大部分的高手一样,痴迷函数,热衷创造、挑战不规范的数据。后来他消失了好长一段时间,群里的同学都以为他退圈了,偶有少数的同学想起他,言语都带着惋惜和遗憾,他时不时的会在群里冒个泡,不过都是换个气,又潜下去那种。记得有一天老大......
  • excel江湖异闻录--Klaus
    最开始接触数组公式,是偶然在公众号看到“看见星光”大佬的一个提取混合文本中电话号码的公式,记得当时大佬是用vlookup解的这题,当时完全不能理解,mid中第二参数为什么是个row,一遍遍拆公式,才明白大佬公式的奥妙。真没有想到,公式还可以这样写,“看见星光”大佬的这个公式,帮我打开了数......
  • excel江湖异闻录--修迪斯.嗦狸
    因为技术出类拔萃,同学都尊称他为“修神”,修神的python、vba、Javascript、java、数据库、批处理等众多编程语言都是极强的,以笔者的见识来判断,大佬的vba已经是职业级别了,至于其他的编程语言,不敢断言,反正笔者是从来没有看懂过。请原谅笔者的浅薄,实在是修哥的技术面之广,已经超出了笔......
  • excel江湖异闻录--◆K
    网名◆K,按照群里同学的说法,K神和老大kluas,以及一个名为KKK的VBA强人,都是K字头家族的高手。因为函数实力极强,时常碾压难题,被群里同学们冠以了“K神”的称号。用笔者的观点来看,这是个“化繁为简”的高手。笔者一直有一个观点,函数水平是一个从简单走向复杂,再从复杂进阶到简单的过......
  • excel江湖异闻录--渣渣
    有朋友问过我,为什么要写这些,细细思量,一来我喜欢这个纯粹的江湖,二则向这些纯粹的高手、大神致敬,三是纪念一下自己学习EXCEL的历程。其实,每一个篇章都有一个逻辑,只不过这个逻辑,不是按照实力的高低来的,而是按照这个高手在我脑海中形象的饱满程度来排序的。渣神不是我们群里的同学,勉......