今天我师傅让我写一个从数据库里的数据导出到Excel中并加密,开始我实现了只是用于一个类的,即一张表的方法,但是这样不符合Java的面向对象的思想,并且复用性太低,经过不断的研究实现,终于实现了不同的类/表均适用的方法,代码如下:
public class TestExcel {
public void encryptExportExcel(List<Map<String, Object>> list,String path,String[] title, String[] colum,Date oletime, Field[] fields) throws Exception {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet1 = wb.createSheet("Rz_User");//自己命名
XSSFRow row1 = sheet1.createRow(0);
//设置表格样式
XSSFCellStyle style = wb.createCellStyle();
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);//水平居中
style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);//垂直居中
// sheet1.addMergedRegion(new CellRangeAddress(0, 1, 0, 0));合并
//设置类变量的行
for (int i = 0; i < title.length; i++) {
sheet1.setColumnWidth(i,5000); //设置每列的宽,单位毫米
XSSFCell cell = row1.createCell(i);
cell.setCellValue(title[i]);
cell.setCellStyle(style);
}
for (int i = 0; i < list.size(); i++) {
row1 = sheet1.createRow(i+1);
int k = 0;
//利用Java的反射机制顺序获取变量
for(Field field : fields) {
try {
field.setAccessible(true);
XSSFCell cell = row1.createCell(k);
cell.setCellValue(list.get(i).get(colum[i])==null?"":field.get(list.get(i).get(colum[i])).toString());;
k++;
} catch (IllegalArgumentException e) {
e.printStackTrace();
}catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
fileOut.close();
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword("123456");//设置打开密码
OPCPackage opc = OPCPackage.open(new File(path), PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();
FileOutputStream fos = new FileOutputStream(path);
fs.writeFilesystem(fos);
fos.close();
}
}
期间遇到的困难点是如何获取到类变量的值,如果想要适用于各个不同的类,显然是不能用set/get方法来获取的,故采用Java反射机制来获取即可,有点需要注意的是:field.setAccessible(true); 要设置为true,不然会报访问权限的错误。解决方法来自:https://blog.youkuaiyun.com/wangzai199701/article/details/78244082
至于其他的代码块则主要是导出Excel并加密,网上都有,不懂的可以去搜索就行。
下面是测试用的类:
public class TestExcelData {
public static void main(String args[]) throws Exception{
//假设从数据库里查出来的结果集
List<TestExcelUser> list = new ArrayList<>();
List<Map<String, Object>> list2 = new ArrayList<>();
//假设数据
TestExcelUser user = new TestExcelUser(1,"小明",18,new Date());
TestExcelUser user1 = new TestExcelUser(2,"小刘",18,new Date());
TestExcelUser user2 = new TestExcelUser(3,"小四",18,new Date());
TestExcelUser user3 = new TestExcelUser(4,"小李",18,new Date());
TestExcelUser user4 = new TestExcelUser(5,"小虎",18,new Date());
TestExcelUser user5 = new TestExcelUser(6,"小傻",18,new Date());
TestExcelUser user6 = new TestExcelUser(7,"小子",18,new Date());
list.add(user);
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);
list.add(user6);
//这里是关键,将查出来的记录放在map中。
Map<String, Object> map = new HashMap<>();
//设一个数组里的值为key,其值对应一条记录
String[] colum = new String[list.size()];
for(int i = 0 ; i < list.size(); i++) {
map.put(""+i, list.get(i));
colum[i] = ""+i;
list2.add(map);
}
//假设文件路径
String path = "C:\\Users\\admin\\Desktop\\rzjfforum.xlsx";
//假设每列的名称
String[] title = {"userid","username","age","time"};
//假设一个过期的时间...用于当某些数据过久远时可以删除掉
Date expriedTime = new Date();
Field[] fields = TestExcelUser.class.getDeclaredFields();
//调用上面类的方法
TestExcel testExcel = new TestExcel();
testExcel.encryptExportExcel(list2, path, title, colum,user.getTime(),fields);
}
}
这里主要是如何将不同的类/表的结果集传过去,这里就用到了List和Map的组合,将每一条记录存放到Map中,而key的值用一个字符串数组来存储,在将Map存放到List即可。其中涉及到的过期时间,可以暂不考虑。