Java 在HSSF工作簿中设置活动单元格

Java 在HSSF工作簿中设置活动单元格,java,apache-poi,hssf,Java,Apache Poi,Hssf,我正在尝试使用ApachePOI3.17创建一个预选了特定单元格的旧式Excel文档(HSSFWorkbook)。下面的代码非常难看(它使用反射和私有字段),但是完成了任务 有没有更好的方法来实现同样的目标 import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import org.apache.poi.hssf.model.InternalSheet; import org.apach

我正在尝试使用ApachePOI3.17创建一个预选了特定单元格的旧式Excel文档(HSSFWorkbook)。下面的代码非常难看(它使用反射和私有字段),但是完成了任务

有没有更好的方法来实现同样的目标

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;

import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.SelectionRecord;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.util.CellAddress;

public class ExcelGeneratorDemo {

    public static void main(String[] args) throws IOException {
        writeExcelFile("D21");
    }

    private static void writeExcelFile(String activeCell) throws IOException {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet();
        CellAddress address = new CellAddress(activeCell);
        setActiveCell(sheet, address);
        wb.write(new File(activeCell + ".xls"));
    }

    /**
     * Calling just {@code sheet.setActiveCell} has no effect when opening
     * the file with Microsoft Excel 2016.
     */
    private static void setActiveCell(HSSFSheet sheet, CellAddress address) {
        sheet.setActiveCell(address);

        // Following three private fields in a row cannot be the correct path.
        InternalSheet internalSheet = getField(sheet, "_sheet");
        SelectionRecord selection = getField(internalSheet, "_selection");
        CellRangeAddress8Bit[] ranges = getField(selection, "field_6_refs");

        ranges[0].setFirstColumn(address.getColumn());
        ranges[0].setLastColumn(address.getColumn());
        ranges[0].setFirstRow(address.getRow());
        ranges[0].setLastRow(address.getRow());
    }

    private static <T> T getField(Object obj, String fieldName) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return (T) field.get(obj);
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException(e);
        }
    }
}
导入java.io.File;
导入java.io.IOException;
导入java.lang.reflect.Field;
导入org.apache.poi.hssf.model.InternalSheet;
导入org.apache.poi.hssf.record.SelectionRecord;
导入org.apache.poi.hssf.usermodel.HSSFSheet;
导入org.apache.poi.hssf.usermodel.HSSFWorkbook;
导入org.apache.poi.hssf.util.CellRangeAddress8Bit;
导入org.apache.poi.ss.util.CellAddress;
公共类ExcelGeneratorDemo{
公共静态void main(字符串[]args)引发IOException{
writeExcelFile(“D21”);
}
私有静态void writeExcelFile(字符串activeCell)引发IOException{
HSSFWorkbook wb=新的HSSFWorkbook();
HSSFSheet sheet=wb.createSheet();
CellAddress地址=新的CellAddress(activeCell);
setActiveCell(表格、地址);
write(新文件(activeCell+“.xls”);
}
/**
*仅调用{@code sheet.setActiveCell}在打开时无效
*该文件包含Microsoft Excel 2016。
*/
专用静态void setActiveCell(HSSF表、CellAddress){
sheet.setActiveCell(地址);
//一行中的以下三个专用字段不能是正确的路径。
InternalSheet InternalSheet=getField(sheet,“_sheet”);
SelectionRecord selection=getField(内部工作表“_selection”);
CellRangeAddress8Bit[]ranges=getField(选择,“字段6参考”);
范围[0].setFirstColumn(地址.getColumn());
范围[0].setLastColumn(地址.getColumn());
范围[0].setFirstRow(地址.getRow());
范围[0].setLastRow(地址.getRow());
}
私有静态T getField(对象对象对象,字符串字段名){
试一试{
Field Field=obj.getClass().getDeclaredField(fieldName);
字段。setAccessible(true);
返回(T)字段。获取(obj);
}捕捉(反射操作异常e){
抛出新的非法状态异常(e);
}
}
}
有关HSSF的文件也有一些解决方案代码。它不使用反射,但其解决方案代码也不是直截了当的。

它是一个,在当前的开发版本中已经修复


一旦3.18版本发布,它可能会被修复。

应该提到的是,只需使用而不是
setActiveCell(工作表、地址)无法工作,因为。似乎存在“不确定性”(Microsoft)™ ;--)) 在
BIFF
中记录的
选择的描述中。字段2、3和4是当前窗格中的活动单元格。但是如果由于工作表不包含任何拆分而没有窗格,该怎么办?因此只需更改错误的字段。哦,在再次阅读后:是否使用
LibreOffice
上运行某些内容e> Linux
不重要,因为apache poi
用于在
Excel
fornats中创建文件。是的
LibreOffice
从字段2、3和4解释活动单元格位置。但是
Excel
没有。它使用包含所有选定单元格范围的单元格范围地址列表的第一个单元格。最佳修复方法是除了设置
字段2行活动单元格
字段3列活动单元格
字段4活动单元格索引
之外,还将
字段6行活动单元格
中的第一个选定单元格范围设置为活动单元格。因此,我们将进一步与Libreoffice/OpenOffice Calc兼容。感谢您的注释,这应该会有所帮助在POI中对其进行修复。在LibreOffice中使用它并不一定足够,但它通常表示规范不完全清楚或Excel本身没有完全遵守。