本帖最后由 Ellia.Duan 于 2025-5-30 17:15 编辑
有这么一种场景:有两个工作簿。
A工作簿是模板文件,保存在数据库的一个f1字段中。每次修改模板后,将数据库中此字段的值进行替换,保存最新的模板。
B工作簿是报表,在第一次加载时,读取模板文件,然后进行数据绑定/数据绑定,保存到数据库的另一个字段f2中。
此后,每次报表的查看,修改,都是修改f2的字段。
这么做有什么风险呢?
有一天,用户张三修改了模板文件,增加了一列。
用户李四填写报表数据,那么 ,此时的报表要不要按照模板修改?,如果要的话,数据该如何处理?
当然上述的方案不推荐,报表每次都应加载模板文件,然后数据绑定。或者模板修改后,从修改后的模板创建新的报表。
下文提供几个GcExcel 跨工作簿复制sheet 的方案,针对上文提到的场景,进行sheet替换。仅供参考
一、跨工作簿复制
https://demo.grapecity.com.cn/do ... eetbetweenworkbooks
- // Create a new workbook
- Workbook workbook = new Workbook();
- //Load template file Home inventory.xlsx from resource to the source workbook
- Workbook source_workbook = new Workbook();
- InputStream source_fileStream = this.getResourceStream("xlsx/Home inventory.xlsx");
- source_workbook.open(source_fileStream);
- //Copy content of active sheet from source workbook to the current workbook before the first sheet
- IWorksheet copy_worksheet = source_workbook.getActiveSheet().copyBefore(workbook.getWorksheets().get(0));
- copy_worksheet.setName("Copy of Home inventory");
- copy_worksheet.activate();
-
- // Save to an excel file
- workbook.save("CopyWorksheetBetweenWorkbooks.xlsx");
复制代码 上述代码可以实现跨工作簿的sheet复制。
在执行上面的操作前,应该把要重置的sheet删除,然后模板文件的同名sheet复制过来。
但是有一个缺点:删除sheet ,会导致公式链切断,此过程不可逆。
比如说,现在要重置的sheet名称是sheet2 。
1、报表文件删除sheet2 这个sheet
2、将模板文件的sheet2 复制到报表文件中
3、如果报表文件中sheet1 引用了sheet2 的某个单元格,则此时sheet1此公式的结果是ref。
二、区域复制
那,是否有不删除sheet的方案呢?有的,GcExcel 还有一个区域复制。
https://demo.grapecity.com.cn/do ... ngebetweenworkbooks
核心代码是:
- PasteOption pasteOption = new PasteOption();
- pasteOption.getPasteType().addAll(EnumSet.of(PasteType.Formulas, PasteType.Formats, PasteType.RowHeights, PasteType.ColumnWidths));
- source_workbook.getActiveSheet().getUsedRange(EnumSet.allOf(UsedRangeType.class)).copy(workbook.getActiveSheet().getRange("A2"), pasteOption);
复制代码 上述代码实现的是,将source_workbook的活动sheet的有效区域复制到workbook的活动sheet中。
注意,如果要实现上面的跨工作簿复制,需要先将报表中sheet2 先清空 ,否则容易出现不一致的问题。
- worksheet.getUsedRange().clear();
- worksheet.getColumns().clear();
- worksheet.getColumns().setColumnWidth(worksheet.getStandardWidth());
- worksheet.getColumns().setRowHeight(worksheet.getStandardHeight());
复制代码 调用上面的方法,将报表的sheet2 区域删除。
这里的getUsedRange() 的范围:
执行上述的操作后,再去执行range.copy()
此方法有点类似与UI上面的复制粘贴行为。
但是,此方案也有一点公式问题。
上面的方案是sheet1中有引用sheet2 的公式。此时如果存在另一种情况。
sheet2 引用sheet1 的单元格值。
如果此时,range.copy()后会出现sheet2的公式出现跨工作簿公式,如下图所所示:
三、sheet序列化
https://demo.grapecity.com.cn/do ... romjsonforworksheet
使用 sheet.toJson() sheet.fromJson()方法
|