简体   繁体   English

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

[英]how to copy a drop down list in excel with apache poi?

I copy one cell that contains one drop-down list to another, but the drop-down list is not copied. 我将包含一个下拉列表的一个单元格复制到另一个下拉列表,但不会复制下拉列表。 If I do it on the file excel with ctrl+c and ctrl+v it works and copies the drop down list in the new cell. 如果我使用ctrl + c和ctrl + v在文件excel上执行此操作,它将工作并复制新单元格中的下拉列表。

Is there any way to copy it with Apache Poi? 有没有办法用Apache Poi复制它?
I copy the cell containing the drop-down list, but the result is just the value and not the drop-down list. 我复制包含下拉列表的单元格,但结果只是值而不是下拉列表。

I have one sheet where I have the drop-down list and want copy to another cell and The data (Libro.xls). 我有一张表,我有下拉列表,并希望复制到另一个单元格和数据(Libro.xls)。

在此输入图像描述

I have this methods in the class Excel. 我在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;
        }
    }
}

And my Main class: 而我的主要课程:

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();
    }
}

And the result (New.xls): Only copy the value of the cell, but not the drop-down list. 结果(New.xls):只复制单元格的值,而不复制下拉列表。

在此输入图像描述

I want to copy the drop-down list, thanks for the future answers. 我想复制下拉列表,感谢未来的答案。

It is related to the poi DataValidation function. 它与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());  
    }

After called copyCell(), you have to decide which cell ranges for which data validation rule. 在调用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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM