当前位置: 首页 > 工具软件 > ExcelUtil > 使用案例 >

ExcelUtil通用工具类

呼延辰龙
2023-12-01
import java.io.File;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JOptionPane;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;

public class ExcelUtil<T> {

    private Workbook workbook = null;
    private Sheet sheet = null;
    private String[] columnArray = null;
    private List<String[]> rowList = new ArrayList<String[]>();
    private String fileName = "";
    private String fileDeskDir = "";
    /**
     * 文件后缀名
     */
    private String fileExt = "";

    public ExcelUtil() {
    }

    /**
     *
     * @param fileDeskDir
     *            保存图片相对路径
     * @param file
     *            Excel文档文件l
     */
    public ExcelUtil(String fileDeskDir, String filePath) {
        this.fileDeskDir = fileDeskDir;
        File file = new File(filePath);
        fileName = file.getName();
        fileExt = fileName.substring(fileName.lastIndexOf(".") + 1);
        try {
            InputStream inputStream = new FileInputStream(file);
            // 根据后缀判断excel 2003 or 2007+
            if (fileExt.equals("xls")) {
                workbook = (HSSFWorkbook) WorkbookFactory.create(inputStream);
            } else {
                workbook = new XSSFWorkbook(inputStream);
            }
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有文字数据,如果有图片,自动保存图片并封装图片路径到rowList集合
     *
     * @return 文字数据(包括图片路径)的集合
     */
    public List<String[]> getTextAndImg() {
        List<String[]> rowList = getText();
        // 如果有图片,自动保存图片并封装图片路径到rowList集合
        List<String> imgPaths = getAndSaveExcelImg();
        if (imgPaths != null && imgPaths.size() > 0) {
            for (int i = 0; i < rowList.size(); i++) {
                for (int j = 0; j < rowList.get(i).length; j++) {
                    for (String imgPath : imgPaths) {
                        // 获取图片的行索引
                        int imgRowIndex = Integer.parseInt(imgPath.split("_")[1]);
                        // 获取图片的列索引
                        int imgColIndex = Integer
                                .parseInt(imgPath.substring(imgPath.lastIndexOf("_") + 1, imgPath.lastIndexOf(".")));
                        // 如果文字的行、列索引==图片的行、列索引
                        if (i == imgRowIndex && j == imgColIndex) {
                            rowList.get(i)[imgColIndex] = imgPath;
                        }
                    }
                }
            }
        }
        return rowList;
    }

    /**
     * 获取excel中 图片,得到图片位置,并保存到D:/ExcelImg,以文档名为文件夹,
     * 以图片位置索引命名,例如:Img0_1_0.png表示该图片位于第一个sheet的第2行第1列 支持03 07 多sheet
     *
     * @param excelPath
     *            Excel文档的路径
     * @return 图片的相对路径集合
     */
    public List<String> getAndSaveExcelImg() {
        if (workbook != null) {
            int sheetNumbers = workbook.getNumberOfSheets();
            List<Map<String, PictureData>> sheetList = new ArrayList<Map<String, PictureData>>();
            for (int i = 0; i < sheetNumbers; i++) {
                sheet = workbook.getSheetAt(i);
                // map等待存储excel图片
                Map<String, PictureData> sheetIndexPicMap;
                // 判断用07还是03的方法获取图片
                if (fileExt.equals("xls")) {
                    sheetIndexPicMap = getSheetPictrues03(i, (HSSFSheet) sheet, (HSSFWorkbook) workbook);
                } else {
                    sheetIndexPicMap = getSheetPictrues07(i, (XSSFSheet) sheet, (XSSFWorkbook) workbook);
                }
                // 将当前sheet图片map存入list
                if (sheetIndexPicMap != null && sheetIndexPicMap.size() > 0) {
                    sheetList.add(sheetIndexPicMap);
                }
            }
            if (sheetList != null && sheetList.size() > 0) {
                return saveImgs(fileName, sheetList);
            }
        }
        return null;
    }

    /**
     * 获取Excel2003图片
     *
     * @param sheetNum
     *            当前sheet编号
     * @param sheet
     *            当前sheet对象
     * @param workbook
     *            工作簿对象
     * @return Map key:图片单元格索引(0_1_1)String,value:图片流PictureData
     * @throws IOException
     */
    private Map<String, PictureData> getSheetPictrues03(int sheetNum, HSSFSheet sheet, HSSFWorkbook workbook) {
        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        if (pictures.size() != 0) {
            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) {
                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
                if (shape instanceof HSSFPicture) {
                    HSSFPicture pic = (HSSFPicture) shape;
                    int pictureIndex = pic.getPictureIndex() - 1;
                    HSSFPictureData picData = pictures.get(pictureIndex);
                    String picIndex = String.valueOf(sheetNum) + "_" + String.valueOf(anchor.getRow1()) + "_"
                            + String.valueOf(anchor.getCol1());
                    sheetIndexPicMap.put(picIndex, picData);
                }
            }
            return sheetIndexPicMap;
        } else {
            return null;
        }
    }

    /**
     * 获取Excel2007图片
     *
     * @param sheetNum
     *            当前sheet编号
     * @param sheet
     *            当前sheet对象
     * @param workbook
     *            工作簿对象
     * @return Map key:图片单元格索引(0_1_1)String,value:图片流PictureData
     */
    private Map<String, PictureData> getSheetPictrues07(int sheetNum, XSSFSheet sheet, XSSFWorkbook workbook) {
        Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
        for (POIXMLDocumentPart dr : sheet.getRelations()) {
            if (dr instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) dr;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    XSSFPicture pic = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = pic.getPreferredSize();
                    CTMarker ctMarker = anchor.getFrom();
                    String picIndex = String.valueOf(sheetNum) + "_" + ctMarker.getRow() + "_" + ctMarker.getCol();
                    sheetIndexPicMap.put(picIndex, pic.getPictureData());
                }
            }
        }
        return sheetIndexPicMap;
    }

    /**
     * 保存图片到硬盘,并返回图片相对路径集合
     *
     * @param fileName
     * @param sheetList
     * @return
     */
    private List<String> saveImgs(String fileName, List<Map<String, PictureData>> sheetList) {
        List<String> relativePaths = new ArrayList<String>();
        String dirName = fileName.substring(0, fileName.lastIndexOf("."));
        String fileDir = fileDeskDir + "/" + dirName;
        File file = new File(fileDir);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
        if (sheetList != null && sheetList.size() > 0) {
            for (Map<String, PictureData> map : sheetList) {
                Object key[] = map.keySet().toArray();
                for (int i = 0; i < map.size(); i++) {
                    // 获取图片流
                    PictureData pic = map.get(key[i]);
                    // 获取图片索引
                    String picName = key[i].toString();
                    // 获取图片格式
                    String ext = pic.suggestFileExtension();
                    String picPath = fileDir + "/Img" + picName + "." + ext;
                    byte[] data = pic.getData();
                    try {
                        FileOutputStream out = new FileOutputStream(picPath);
                        System.out.println("已将图片保存到:" + picPath);
                        out.write(data);
                        out.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    relativePaths.add(dirName + "/Img" + picName + "." + ext);
                }
            }
        }

        return relativePaths;
    }

    /**
     * 根据后缀名判断是03还是07版,调用相应方法获取文档文字
     *
     * @return List<String[]>即:行集合<该行每一个单元格的值组成的数组>
     */
    public List<String[]> getText() {
        if (workbook != null) {
            if (fileExt.equals("xlsx")) {
                return getSheetText07(0, (XSSFWorkbook) workbook);
            } else if (fileExt.equals("xls")) {
                return getSheetText03(0, (HSSFWorkbook) workbook);
            } else {
                System.out.println("该文件不是标准的Excel文件");
            }
        }
        return null;
    }

    /**
     * 获取o3版文字内容
     *
     * @param sheetIndex
     * @param workbook
     * @return
     */
    public List<String[]> getSheetText03(int sheetIndex, HSSFWorkbook workbook) {
        /* 读EXCEL文字内容 */
        HSSFSheet hssfSheet = (HSSFSheet) workbook.getSheetAt(sheetIndex);
        int colCount = hssfSheet.getRow(0).getPhysicalNumberOfCells();
        for (int rowNum = 0; rowNum < hssfSheet.getPhysicalNumberOfRows(); rowNum++) {
            HSSFRow hssfRow = hssfSheet.getRow(rowNum);
            if (hssfRow != null) {
                columnArray = new String[colCount];
                for (int colNum = 0; colNum < colCount; colNum++) {
                    columnArray[colNum] = getValue(hssfRow.getCell(colNum));
                }
            }
            rowList.add(columnArray);
        }
        return rowList;
    }

    /**
     * 获取o7+版文字内容
     *
     * @param sheetIndex
     * @param workbook
     * @return
     */
    private List<String[]> getSheetText07(int sheetIndex, XSSFWorkbook workbook) {
        /* 读EXCEL文字内容 */
        XSSFSheet xssfSheet = (XSSFSheet) workbook.getSheetAt(sheetIndex);
        int colCount = xssfSheet.getRow(0).getPhysicalNumberOfCells();
        for (int rowNum = 0; rowNum < xssfSheet.getPhysicalNumberOfRows(); rowNum++) {
            XSSFRow xssfRow = xssfSheet.getRow(rowNum);
            if (xssfRow != null) {
                columnArray = new String[colCount];
                for (int colNum = 0; colNum < colCount; colNum++) {
                    columnArray[colNum] = getValue(xssfRow.getCell(colNum));
                }
            }
            rowList.add(columnArray);
        }
        return rowList;
    }

    /**
     * 获取单元格的值以字符串返回;03,07通用
     *
     * @param xssfRow
     * @return
     */
    private String getValue(Cell cell) {
        String value = null;
        if (cell != null) {
            switch (cell.getCellType()) {
            case XSSFCell.CELL_TYPE_BLANK:
                value = "";
                break;
            case XSSFCell.CELL_TYPE_BOOLEAN:
                value = String.valueOf(cell.getBooleanCellValue());
                break;
            case XSSFCell.CELL_TYPE_NUMERIC:
                value = new DecimalFormat("#").format(cell.getNumericCellValue());
                break;
            case XSSFCell.CELL_TYPE_FORMULA:
                value = cell.getCellFormula();
                break;
            default:
                value = String.valueOf(cell.getStringCellValue());
                break;
            }
        }
        return value;
    }

    /**
     * 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
     *
     * @param title
     *            表格标题名
     * @param headers
     *            表格属性列名数组
     * @param dataset
     *            需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的
     *            javabean属性的数据类型有基本数据类型及String,Date,byte[](图片数据)
     * @param out
     *            与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中
     * @param pattern
     *            如果有时间数据,设定输出格式。默认为"yyy-MM-dd"
     */
    @SuppressWarnings("unchecked")
    public void exportExcel(String title, String[] headers, Collection<T> dataset, OutputStream out, String pattern) {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 20);
        // 生成一个样式
        HSSFCellStyle style = workbook.createCellStyle();
        // 设置样式
        style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        // 生成一个字体
        HSSFFont font = workbook.createFont();
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);
        // 生成并设置另一个样式
        HSSFCellStyle style2 = workbook.createCellStyle();
        style2.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
        // 生成另一个字体
        HSSFFont font2 = workbook.createFont();
        font2.setFontHeightInPoints((short) 11);
        font2.setColor(HSSFColor.BLACK.index);
        // 把字体应用到当前的样式
        style2.setFont(font2);

        // 声明一个画图的顶级管理器
        HSSFPatriarch patriarch = sheet.createDrawingPatriarch();

        // 产生表格标题行
        HSSFRow row = sheet.createRow(0);
        for (short i = 0; i < headers.length; i++) {
            HSSFCell cell = row.createCell(i);
            cell.setCellStyle(style);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }
        HSSFFont font3 = workbook.createFont();

        // 遍历集合数据,产生数据行
        Iterator<T> it = dataset.iterator();
        int index = 0;
        while (it.hasNext()) {
            index++;
            row = sheet.createRow(index);
            T t = (T) it.next();
            // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
            Field[] fields = t.getClass().getDeclaredFields();
            for (short i = 0; i < fields.length; i++) {
                HSSFCell cell = row.createCell(i);
                cell.setCellStyle(style2);
                Field field = fields[i];
                String fieldName = field.getName();
                String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                try {
                    Class tCls = t.getClass();
                    Method getMethod = tCls.getMethod(getMethodName, new Class[] {});
                    Object value = getMethod.invoke(t, new Object[] {});
                    // 判断值的类型后进行强制类型转换
                    String textValue = null;
                    if (value instanceof Boolean) {
                        boolean bValue = (Boolean) value;
                        textValue = "男";
                        if (!bValue) {
                            textValue = "女";
                        }
                    } else if (value instanceof Date) {
                        Date date = (Date) value;
                        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
                        textValue = sdf.format(date);
                    } else if (value instanceof byte[]) {
                        // 有图片时,设置行高为60px;
                        row.setHeightInPoints(60);
                        // 设置图片所在列宽度为80px,注意这里单位的一个换算
                        sheet.setColumnWidth(i, (short) (35.7 * 80));
                        // sheet.autoSizeColumn(i);
                        byte[] bsValue = (byte[]) value;
                        HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) 6, index, (short) 6,
                                index);
                        anchor.setAnchorType(2);
                        patriarch.createPicture(anchor, workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG));
                    } else {
                        // 其它数据类型都当作字符串简单处理
                        textValue = value == null ? "" : value.toString();
                    }
                    // 如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成
                    if (textValue != null) {
                        Pattern p = Pattern.compile("^//d+(//.//d+)?$");
                        Matcher matcher = p.matcher(textValue);
                        if (matcher.matches()) {
                            // 是数字当作double处理
                            cell.setCellValue(Double.parseDouble(textValue));
                        } else {
                            HSSFRichTextString richString = new HSSFRichTextString(textValue);
                            richString.applyFont(font3);
                            cell.setCellValue(richString);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 清理资源
                }
            }
        }
        try {
            workbook.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 类似资料: