You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Java将.xls格式Excel转换为.xlsx时丢失饼图与样式的问题咨询

问题原因分析

你现有转换代码仅处理了单元格的基础值、注释和简单数据格式,没有迁移内嵌图片、完整单元格样式、绘图元素,因此会丢失饼图和格式。你插入的饼图本质是JPG静态图片,不是Excel原生图表,迁移难度远低于原生图表。

方案1:直接生成XLSX格式文件(推荐,无需转换步骤)

直接把生成xls的代码替换为XSSF实现,一步生成.xlsx文件,省掉转换步骤,完全不会丢失内容。
修改后的饼图生成代码如下:

package excelFileGenerate6;
import java.awt.Color;
import java.io.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.jfree.data.general.DefaultPieDataset; 
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
import org.jfree.chart.plot.PiePlot;
import org.jfree.chart.ChartUtilities; 
import java.util.Iterator;

public class CreatePieChartXLSXExample {  

        public void createPie(String Filename) throws IOException {
                
                /* 读取Excel表格数据 */
                FileInputStream chart_file_input = new FileInputStream(new File(Filename));
                /* 替换为XSSFWorkbook处理xlsx格式 */
                XSSFWorkbook my_workbook = new XSSFWorkbook(chart_file_input);
                XSSFSheet my_sheet = my_workbook.getSheetAt(0);
                DefaultPieDataset my_pie_chart_data = new DefaultPieDataset();
                Iterator<Row> rowIterator = my_sheet.iterator(); 
                String chart_label="a";
                Number chart_data=0;            
                while(rowIterator.hasNext()) {
                        Row row = rowIterator.next();  
                        Iterator<Cell> cellIterator = row.cellIterator();
                                while(cellIterator.hasNext()) {
                                        Cell cell = cellIterator.next(); 
                                        switch(cell.getCellType()) { 
                                        case Cell.CELL_TYPE_NUMERIC:
                                                chart_data=cell.getNumericCellValue();
                                                break;
                                        case Cell.CELL_TYPE_STRING:
                                                chart_label=cell.getStringCellValue();
                                                break;
                                        }
                                }
                my_pie_chart_data.setValue(chart_label,chart_data);
                }               
                JFreeChart myPieChart=ChartFactory.createPieChart("Test Results",my_pie_chart_data,true,true,false);
                
                PiePlot plot = (PiePlot) myPieChart.getPlot();
                PieSectionLabelGenerator gen = new StandardPieSectionLabelGenerator("{1}");
                plot.setLabelGenerator(gen);
                
                plot.setSectionPaint("Passed", Color.GREEN);
                plot.setSectionPaint("Failed", Color.RED);
                plot.setSectionPaint("Pending", Color.black);
                plot.setSectionPaint("Total Time taken (ms)", Color.pink);
                plot.setSectionPaint("Skipped", Color.blue);
                plot.setSectionPaint("How many Sub headers are Passed", Color.yellow);
                plot.setSectionPaint("Total TC's", Color.CYAN);
                
                int width=640;
                int height=480;
                float quality=1;
                ByteArrayOutputStream chart_out = new ByteArrayOutputStream();          
                ChartUtilities.writeChartAsJPEG(chart_out,quality,myPieChart,width,height);
                InputStream feed_chart_to_excel=new ByteArrayInputStream(chart_out.toByteArray());
                byte[] bytes = IOUtils.toByteArray(feed_chart_to_excel);
                int my_picture_id = my_workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
                feed_chart_to_excel.close();
                chart_out.close();
                /* 替换为XSSFDrawing处理绘图 */
                XSSFDrawing drawing = my_sheet.createDrawingPatriarch();
                ClientAnchor my_anchor = new XSSFClientAnchor();
                my_anchor.setCol1(4);
                my_anchor.setRow1(5);
                XSSFPicture  my_picture = drawing.createPicture(my_anchor, my_picture_id);
                my_picture.resize();
                chart_file_input.close();               
                FileOutputStream out = new FileOutputStream(new File(Filename));
                my_workbook.write(out);
                out.close();            
        }
        
        public static void main(String args[]) throws IOException {
            CreatePieChartXLSXExample chart = new CreatePieChartXLSXExample();
            // 直接传入xlsx后缀的文件路径即可
            chart.createPie("C:\\Users\\user\\JavaProjects\\workspace\\Sample2\\src\\excelFileGenerate6\\report.xlsx");
        }
}

你之前生成基础表格的代码也对应把HSSF替换为XSSF即可,不需要修改业务逻辑。

方案2:修改现有转换代码,补充图片和样式迁移

如果你一定要保留现有xls生成逻辑,再转成xlsx,修改转换代码,补充样式和图片迁移逻辑即可,修改后代码如下:

package excelFileGenerate6;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class conversion_to_xlsx {
    
    public static void main(String[] args) throws IOException {

        String inpFn = "C:\\Users\\user\\JavaProjects\\workspace\\Sample2\\src\\excelFileGenerate6\\report.xls"; 
        String outFn = "C:\\Users\\user\\JavaProjects\\workspace\\Sample2\\src\\excelFileGenerate6\\converted_report.xlsx"; 

        FileInputStream in = new FileInputStream(inpFn);
        try {
            Workbook wbIn = new HSSFWorkbook(in);
            File outF = new File(outFn);
            if (outF.exists())
                outF.delete();

            Workbook wbOut = new XSSFWorkbook();
            
            // 提前迁移所有样式,避免样式冲突
            Map<CellStyle, CellStyle> styleMap = new HashMap<>();
            for (short i = 0; i < wbIn.getNumCellStyles(); i++) {
                CellStyle oldStyle = wbIn.getCellStyleAt(i);
                CellStyle newStyle = wbOut.createCellStyle();
                newStyle.cloneStyleFrom(oldStyle);
                styleMap.put(oldStyle, newStyle);
            }
            
            // 迁移所有图片资源
            List<? extends PictureData> allPics = wbIn.getAllPictures();
            int[] picIdMap = new int[allPics.size()];
            for (int i = 0; i < allPics.size(); i++) {
                PictureData picData = allPics.get(i);
                picIdMap[i] = wbOut.addPicture(picData.getData(), picData.getPictureType());
            }

            int sheetCnt = wbIn.getNumberOfSheets();
            for (int i = 0; i < sheetCnt; i++) {
                Sheet sIn = wbIn.getSheetAt(i);
                Sheet sOut = wbOut.createSheet(sIn.getSheetName());
                // 迁移列宽配置
                for (int c = 0; c < sIn.getRow(0).getLastCellNum(); c++) {
                    sOut.setColumnWidth(c, sIn.getColumnWidth(c));
                }
                
                Iterator<Row> rowIt = sIn.rowIterator();
                while (rowIt.hasNext()) {
                    Row rowIn = rowIt.next();
                    Row rowOut = sOut.createRow(rowIn.getRowNum());
                    // 迁移行高配置
                    rowOut.setHeight(rowIn.getHeight());

                    Iterator<Cell> cellIt = rowIn.cellIterator();
                    while (cellIt.hasNext()) {
                        Cell cellIn = cellIt.next();
                        Cell cellOut = rowOut.createCell(
                                cellIn.getColumnIndex(), cellIn.getCellType());

                        switch (cellIn.getCellType()) {
                        case Cell.CELL_TYPE_BLANK:
                            break;
                        case Cell.CELL_TYPE_BOOLEAN:
                            cellOut.setCellValue(cellIn.getBooleanCellValue());
                            break;
                        case Cell.CELL_TYPE_ERROR:
                            cellOut.setCellValue(cellIn.getErrorCellValue());
                            break;
                        case Cell.CELL_TYPE_FORMULA:
                            cellOut.setCellFormula(cellIn.getCellFormula());
                            break;
                        case Cell.CELL_TYPE_NUMERIC:
                            cellOut.setCellValue(cellIn.getNumericCellValue());
                            break;
                        case Cell.CELL_TYPE_STRING:
                            cellOut.setCellValue(cellIn.getStringCellValue());
                            break;
                        }
                        // 迁移单元格完整样式
                        cellOut.setCellStyle(styleMap.get(cellIn.getCellStyle()));
                        cellOut.setCellComment(cellIn.getCellComment());
                    }
                }
                
                // 迁移绘图元素(含插入的饼图图片)
                Drawing<?> drawingIn = sIn.getDrawingPatriarch();
                if (drawingIn != null) {
                    Drawing<?> drawingOut = sOut.createDrawingPatriarch();
                    for (Object shape : drawingIn.getShapes()) {
                        if (shape instanceof Picture) {
                            Picture picIn = (Picture) shape;
                            ClientAnchor anchorIn = picIn.getClientAnchor();
                            int picIndex = picIn.getPictureIndex();
                            drawingOut.createPicture(anchorIn, picIdMap[picIndex-1]);
                        }
                    }
                }
            }
            FileOutputStream out = new FileOutputStream(outF);
            try {
                wbOut.write(out);
            } finally {
                out.close();
                wbOut.close();
            }
        } finally {
            in.close();
        }
    }
}
报错说明

你之前碰到的sun/image/codec错误是因为高版本JDK移除了sun相关的私有图像接口,升级JFreeChart到1.5.3以上版本即可解决。


内容的提问来源于stack exchange,提问作者automaion_test_monk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:09:04