如何用apache poi在excel中复制下拉列表?

wqlqzqxt  于 2022-11-26  发布在  Apache
关注(0)|答案(1)|浏览(311)

我将一个包含下拉列表的单元格复制到另一个单元格,但是下拉列表没有被复制。如果我在excel文件中使用ctrl+c和ctrl+v进行复制,它会将下拉列表复制到新单元格中。
有没有办法用ApachePoi复制它?
我复制了包含下拉列表的单元格,但结果只是值而不是下拉列表。
我有一个工作表,我有下拉列表,并希望复制到另一个单元格和数据(Libro.xls)。

我在Excel类中有这个方法。

package es.fips;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;

public class Excel {
    private static HSSFWorkbook workbook = null;
    private static FileInputStream fis = null;
    private static HSSFSheet sheet = null;

    public static boolean openExcel(String pathExcel) {
        // Cargar la ruta del fichero Excel.
        try {
            fis = new FileInputStream(pathExcel);           
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        // Linkeamos el documento excel.
        try {
            workbook = new HSSFWorkbook(fis);
            loadSheet(0);
            return true;            
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static boolean loadSheet(int numHoja){  
        try {
            // Obtenemos la hoja.
            int hojas = workbook.getNumberOfSheets();
            if((hojas-1) < numHoja){
                throw new Exception("El fichero excel solo contiene "+hojas+" hojas.");
            }else{
                sheet = workbook.getSheetAt(numHoja);
                return true;    
            }   
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }   
    }

    public static boolean saveChanges(String dirTemp, String name){     
        FileOutputStream fos = null;

        // Crear fichero de salida para el nuevo excel.         
        try {           
            fos = new FileOutputStream(dirTemp+"/"+name);           
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }                           
        // Los cambios realizado en la plantilla los guardamos en el nuevo excel.
        try {
            workbook.write(fos);
            fos.close();
            return true;            
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static void closeExcel(){
        try {
            if (workbook != null) {
                workbook.close();
            }
            if (fis != null) {
                fis.close();
            }               
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void copyCell() {
        // Get the source / new row.
        Row newRow = sheet.getRow(2);// Row number 3.
        Row sourceRow = sheet.getRow(2);// Row number 3.

        // Grab a copy of the old/new cell
        Cell oldCell = sourceRow.getCell(3);// Column D.
        Cell newCell = newRow.createCell(5);// Column F.

        // Copy STYLE from old cell and apply to new cell.
        HSSFCellStyle newCellStyle = workbook.createCellStyle();
        newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
        newCell.setCellStyle(newCellStyle);

        // If there is a cell comment, copy.
        if (newCell.getCellComment() != null) {
            newCell.setCellComment(oldCell.getCellComment());
        }
        // If there is a cell hyperlink, copy.
        if (oldCell.getHyperlink() != null) {
            newCell.setHyperlink(oldCell.getHyperlink());
        }

        // Set the cell data TYPE.
        newCell.setCellType(oldCell.getCellType());

        // Set the cell data value.
        switch (oldCell.getCellType()) {
        case Cell.CELL_TYPE_BLANK:
            newCell.setCellValue(oldCell.getStringCellValue());
            break;
        case Cell.CELL_TYPE_BOOLEAN:
            newCell.setCellValue(oldCell.getBooleanCellValue());
            break;
        case Cell.CELL_TYPE_ERROR:
            newCell.setCellErrorValue(oldCell.getErrorCellValue());
            break;
        case Cell.CELL_TYPE_FORMULA:
            newCell.setCellFormula(oldCell.getCellFormula());
            break;
        case Cell.CELL_TYPE_NUMERIC:
            newCell.setCellValue(oldCell.getNumericCellValue());
            break;
        case Cell.CELL_TYPE_STRING:
            newCell.setCellValue(oldCell.getStringCellValue());
            break;
        }
    }
}

还有我的主职业:

package es.fips;

public class Main {
    public static void main(String[] args) {
        Excel.openExcel("Path/Libro.xls");
        Excel.copyCell();
        Excel.saveChanges("Path", "New.xls");
        Excel.closeExcel();
    }
}

结果(New.xls):仅复制单元格的值,而不复制下拉列表。

我想复制下拉列表,谢谢您以后的回答。

whlutmcx

whlutmcx1#

它与poi DataValidation函数相关。

private static boolean equalsRegion(final CellRangeAddressList region1, final CellRangeAddressList region2) {    
        return equalsSqref(convertSqref(region1), convertSqref(region2));    
    }

    private static boolean equalsSqref(final List<String> sqref1, final List<String> sqref2) {    
        if(sqref1.size() != sqref2.size())
            return false;

        Collections.sort(sqref1);
        Collections.sort(sqref2);

        final int size = sqref1.size();
        for(int i = 0; i < size; ++i) {
            if(!sqref1.get(i).equals(sqref2.get(i))) {
                return false;
            }
        }

        return true;    
    }

    private static List<String> convertSqref(final CellRangeAddressList region) {    
        List<String> sqref = new ArrayList<String>();
        for(CellRangeAddress range : region.getCellRangeAddresses()) {
            sqref.add(range.formatAsString());
        }

        return sqref;    
    }

    private static boolean updateDataValidationRegion(final Sheet sheet, final CellRangeAddressList oldRegion, final CellRangeAddressList newRegion) {    
        if(sheet instanceof XSSFSheet) {

            List<String> oldSqref = convertSqref(oldRegion);

            try {
                final XSSFSheet xssfSheet = (XSSFSheet) sheet;
                Field fWorksheet = XSSFSheet.class.getDeclaredField("worksheet");
                fWorksheet.setAccessible(true);
                CTWorksheet worksheet = (CTWorksheet) fWorksheet.get(xssfSheet);

                CTDataValidations dataValidations = worksheet.getDataValidations();
                if(dataValidations == null)
                    return false;

                for(int i = 0; i < dataValidations.getCount(); ++i) {
                    CTDataValidation dv = dataValidations.getDataValidationArray(i);

                    @SuppressWarnings("unchecked")
                    List<String> sqref = new ArrayList<String>(dv.getSqref());
                    if(equalsSqref(sqref, oldSqref)) {
                        List<String> newSqref = convertSqref(newRegion);
                        dv.setSqref(newSqref);                        
                        dataValidations.setDataValidationArray(i, dv);                    
                        return true;
                    }

                }

                return false;

            } catch(Exception e) {
                throw new RuntimeException("fail update DataValidation's Region.", e);
            }

        } else if(sheet instanceof HSSFSheet) {

            final HSSFSheet hssfSheet = (HSSFSheet) sheet;
            try {
                Field fWorksheet = HSSFSheet.class.getDeclaredField("_sheet");
                fWorksheet.setAccessible(true);
                InternalSheet worksheet = (InternalSheet) fWorksheet.get(hssfSheet);

                DataValidityTable dvt = worksheet.getOrCreateDataValidityTable();

                final AtomicBoolean updated = new AtomicBoolean(false);
                org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor visitor = new org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor() {

                    @Override
                    public void visitRecord(Record r) {
                         if (!(r instanceof DVRecord))
                                return;

                            final DVRecord dvRecord = (DVRecord) r;
                            final CellRangeAddressList region = dvRecord.getCellRangeAddress();
                            if(equalsRegion(region, oldRegion)) {

                                while(region.countRanges() != 0)
                                    region.remove(0);

                                for(CellRangeAddress newRange : newRegion.getCellRangeAddresses())
                                    region.addCellRangeAddress(newRange);

                                updated.set(true);
                            }
                    }
                };

                dvt.visitContainedRecords(visitor);

                return updated.get();

            } catch(Exception e) {
                throw new RuntimeException("fail update DataValidation's Region.", e);
            }
        } 
        throw new UnsupportedOperationException("not supported update dava validation's region for type " + sheet.getClass().getName());  
    }

在调用了copyCell()之后,你必须决定哪些单元格范围适用于哪些数据验证规则。

for (DataValidation validation : sheet.getDataValidations()) {
        CellRangeAddress[] crAddresses = validation.getRegions().getCellRangeAddresses();
        CellRangeAddressList addrList = new CellRangeAddressList();
        for (CellRangeAddress crAddress : crAddresses)
            addrList.addCellRangeAddress(newFirstRow, newFirstColumn, newLastRow, newLastColumn);
        updateDataValidationRegion(sheet, validation.getRegions(), addrList);
    }

相关问题