数据导出到excel表格,并添加水印

1.添加pom.xml依赖

<properties>
        <java.version>1.8</java.version>
        <hutool-poi.version>5.7.13</hutool-poi.version>
        <poi.version>4.1.2</poi.version>
    </properties>
 <dependencies>
<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>${hutool-poi.version}</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-poi</artifactId>
            <version>${hutool-poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.4</version>
        </dependency>
        </dependencies>

2.编写代码文件

ExcelUtil.java文件

package com.cfm.demo.filedown;

import cn.hutool.poi.excel.BigExcelWriter;
import lombok.Synchronized;
public class ExcelUtil {
    private static final String PATH = "/excel/";
    private static final String SUFFIX = ".xlsx";

    // Excel 列宽
    private static final int COLUMN_WIDTH = 20;

    @Synchronized
    public static BigExcelWriter createBigExcelWriter(String fileName , int columnSize){
        BigExcelWriter bigWriter = cn.hutool.poi.excel.ExcelUtil.getBigWriter(PATH + fileName + SUFFIX);
        for (int size = columnSize; size >= 0 ;size--){
            bigWriter.setColumnWidth(size,COLUMN_WIDTH);
        }
        return bigWriter;
    }
}

FileTest05.java文件

package com.cfm.demo.filedown;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import com.alibaba.fastjson.JSONObject;
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.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFPictureData;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Controller
@RequestMapping("/file")
public class FileTest05 {
    

    /**
     * 文件下载
     */
    @RequestMapping("/down5")
    public static void downloadFIle(HttpServletRequest request, HttpServletResponse response) {

       //数据准备工作
        List<Object> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("kk.id", 11);
        map1.put("kk.name", "张三");
        map1.put("kk.address", "北京");
        map1.put("kk.age", "36");
        Map<String, Object> map2 = new HashMap<>();
        map2.put("kk.id", 22);
        map2.put("kk.name", "李四");
        map2.put("kk.address", "上海");
        map2.put("kk.age", "46");
        list.add(map1);
        list.add(map2);
        System.out.println(JSONObject.toJSONString(list));
        /

        String fileName = "文件名字";

        // 创建一个Writer流
        BigExcelWriter bigExcelWriter = ExcelUtil.createBigExcelWriter(fileName, 3);
        //BigExcelWriter bigExcelWriter = new BigExcelWriter();
        //水印的内容
        String watermarkInfo = "我是管理员呀";
        try {
            //添加水印
            Workbook workbook = bigExcelWriter.getWorkbook();
            if (workbook instanceof SXSSFWorkbook) {
                insertWaterMarkTextToXlsx((SXSSFWorkbook) workbook, watermarkInfo);
            } else if (workbook instanceof XSSFWorkbook) {
                insertWaterMarkTextToXlsx((XSSFWorkbook) workbook, watermarkInfo);
            }
            // 获取下Header,判断是哪种浏览器下载文件,来解决文件名的编码命名问题
            String header = request.getHeader("User-Agent").toUpperCase();
            if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {
                fileName = URLEncoder.encode(fileName, "utf-8");
                fileName = fileName.replace("+", "%20");    //IE下载文件名空格变+号问题
            } else {
                fileName = new String(fileName.getBytes(), "UTF8");
            }
            // 有点重复,可以不重写上面的ExcelUtils类,这是防止数据量很大时,需要提前准备文件,并不是即时写入即时返回
            String fileName1 = fileName + ".xlsx";
            response.reset();
            // 设置文件对应后缀的ContentType
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            // 返回的是流的形式
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Location", fileName1);
            response.setHeader("Cache-Control", "max-age=0");
            // 这句的作用是会打开用户那边下载文件时的那个保存位置的框,如果文件名中有中文,建议编下码
            response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName1, "UTF8"));
            AtomicInteger count = new AtomicInteger();
            // 开始准备写入数据
            for (Object obj : list) {
                // 将查询的数据转换为map
                Map<String, Object> map = (Map<String, Object>) obj;
                bigExcelWriter.writeRow(map, count.getAndIncrement() == 0);
            }

            bigExcelWriter.close();
            // 上面的过程就是文件的写入过程并且保存在了/excel/目录下
            // 下面就是把这个文件读取出来,以流的形式返回
            File excelFile = new File("/excel/" + fileName1);
            FileInputStream fis = new FileInputStream(excelFile);
            // 文件流上面加一层缓冲流,目的为了加快速度,减少IO
            BufferedInputStream buff = new BufferedInputStream(fis);
            // 同理,输出流上也套了一层缓冲的输出流
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());

            byte[] car = new byte[1024];
            int l = 0;
            // 按字节读取文件
            while (l < excelFile.length()) {
                int j = buff.read(car, 0, 1024);
                l += j;
                // 写入out流中
                out.write(car, 0, j);
            }

            // 关闭流
            fis.close();
            buff.close();
            out.close();
            excelFile.delete();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 给excel添加水印.
     *
     * @param workbook      Xlsx的Excel工作簿.
     * @param waterMarkText 水印内容.
     * @throws IOException IO异常抛出
     */
    public static void insertWaterMarkTextToXlsx(SXSSFWorkbook 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 = (XSSFPictureData) workbook.getAllPictures().get(pictureIdx);
        //获取每个Sheet表
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            SXSSFSheet sheet = workbook.getSheetAt(i);
            //这里由于 SXSSFSheet 没有 getCTWorksheet() 方法,通过反射取出 _sh 属性
            XSSFSheet shReflect = (XSSFSheet) ReflectUtil.getFieldValue(sheet, "_sh");
            PackagePartName ppn = pictureData.getPackagePart().getPartName();
            String relType = XSSFRelation.IMAGES.getRelation();
            PackageRelationship pr = shReflect.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
            shReflect.getCTWorksheet().addNewPicture().setId(pr.getId());
        }
    }

    /**
     * 生成水印图片.
     *
     * @param content 需要生成水印的文字信息.
     * @return 图片字节流.
     */
    public static BufferedImage createWatermarkImage(String content) {
        final String[] textArray = content.split("\n");
        //设置水印字体、大小
        final Font font = new Font("TimesRoman", Font.PLAIN, 80);
        int width = 500;
        int height = 400;
        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 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;
    }

    /**
     * 给excel添加水印.
     *
     * @param workbook      Xls的Excel工作簿.
     * @param waterMarkText 水印内容.
     * @throws IOException IO异常抛出
     */
    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);
        //获取每个Sheet表
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            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());
        }
    }

}


3.效果展示

启动本地服务,访问地址后下载的效果:
在这里插入图片描述

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在微信小程序导出Excel表格上加水印,可以使用以下步骤: 1. 在Excel中创建一个水印图片或文字,并将其保存为PNG格式的文件。 2. 在微信小程序中,使用wx.downloadFile()方法下载Excel文件。 3. 使用js-xlsx库将下载的Excel文件转换为可编辑的对象。 4. 在对象中添加水印。具体做法可以是在单元格中添加图片或文本,或在单元格的背景中添加图片。 5. 使用js-xlsx库将编辑后的对象转换回Excel文件。 6. 使用wx.saveFile()方法保存编辑后的Excel文件。 以下是一个示例代码片段,演示如何在微信小程序中添加水印: ```javascript const XLSX = require('xlsx') // 下载Excel文件 wx.downloadFile({ url: 'http://example.com/example.xlsx', success: function(res) { // 将文件读取为可编辑对象 const workbook = XLSX.read(res.tempFilePath, { type: 'file' }) const sheetName = workbook.SheetNames[0] const worksheet = workbook.Sheets[sheetName] // 添加水印图片 const watermark = wx.getFileSystemManager().readFileSync('watermark.png', 'base64') const watermarkImage = XLSX.utils.sheet_add_image(worksheet, watermark, { tl: { col: 0, row: 0 }, br: { col: 5, row: 5 } }) // 保存编辑后的Excel文件 const editedWorkbook = XLSX.write(workbook, { bookType: 'xlsx', type: 'binary' }) wx.saveFile({ tempFilePath: window.URL.createObjectURL(new Blob([editedWorkbook], { type: 'application/octet-stream' })), success: function(res) { console.log('Excel文件已保存:', res.savedFilePath) } }) } }) ``` 请注意,上述代码中的水印图片需要您自己创建,并将其保存为PNG格式的文件。此外,代码中还假定Excel文件只有一个工作表,如果文件中有多个工作表,则需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值