[]
GcExcel 允许您通过使用 processTemplate 方法的重载来取消 Workbook 类和 IWorkbook 接口的模板处理。此重载方法接受一个 CancellationToken 类型的参数。取消操作是线程安全的,即取消请求是由不拥有工作簿的线程发送的。您可以使用 CancellationTokenSource 的以下方法向 CancellationToken 发送信号:
方法 | 描述 |
---|---|
cancel | 立即取消方法。 |
cancelAfter | 在特定延迟时间后取消方法。 |
close | 释放当前实例使用的所有资源。 |
当 processTemplate 方法正在进行中,未完成时,CancellationTokenSource 取消请求,才能将 processTemplate 方法成功取消。
成功取消后 Workbook.ProcessTemplate 方法将抛出 CancellationException(Java Platform SE 8 的情况)。
提示: 在处理异常时,workbook 对象处于一个中间状态(数据可能仅填充了一部分)。此时,需要决定是否继续使用该 workbook 对象。如果希望使用模板填充前的 workbook,则需要在模板填充前,对workbook进行备份,在操作取消后进行还原。
参考以下示例代码,在请求取消或达到超时后取消模板处理:
// 创建一个新的工作簿。
Workbook workbook = new Workbook();
// 从资源加载模板文件。
workbook.open("Template_SalesDataGroup_DataTable.xlsx");
// 向 DataTable 添加数据。
SalesData datasource = new SalesData();
datasource.sales = new ArrayList<SalesRecord>();
System.out.println("Creating test data.");
String[] areas = new String[]{"North America", "South America"};
String[] cities = new String[]{"Chicago", "New York", "Santiago", "Quito", "Fremont", "Buenos Aires", "Medillin", "Minnesota"};
String[] categories = new String[]{"Consumer Electronics", "Mobile"};
String[] category1NamePrefixes = new String[]{"Bose ", "Canon ", "Haier ", "IFB ", "Mi ", "Sennheiser "};
String[] category2NamePrefixes = new String[]{"iPhone ", "OnePlus ", "Redmi ", "Samsung "};
Random rand = new Random();
// 如果您的计算机上的演示速度太快,可以增加循环次数。
for (int i = 0; i < 50000; i++) {
SalesRecord item = new SalesRecord();
item.area = areas[rand.nextInt(areas.length)];
item.city = cities[rand.nextInt(cities.length)];
int categoryId = rand.nextInt(categories.length);
item.category = categories[categoryId];
String[] names = (categoryId == 0) ? category1NamePrefixes : category2NamePrefixes;
item.name = names[rand.nextInt(names.length)] + (10 + rand.nextInt(10000 - 10));
item.revenue = 10000 + rand.nextInt(100000 - 10000);
datasource.sales.add(item);
}
// 添加模板全局设置。
workbook.getNames().add("TemplateOptions.KeepLineSize", "true");
// 添加数据源。
workbook.addDataSource("ds", datasource.sales);
// 当按下取消键或超时时取消数据源绑定。
try (CancellationTokenSource cancellation = new CancellationTokenSource()) {
/* 重要提示:为了处理控制台的取消键事件,我们在此示例中使用 `sun.misc.Signal`。
但是,如果您的 JDK 中没有 `sun.misc` 类,那么这些类可能会无法使用,因为它们是受限制的 API。
如果 `sum.misc` 不可用,您需要使用 `jdk.internal.misc.*`(Java 9+)或使用
第三方组件(例如 `javax.realtime.POSIXSignalHandler`)来处理
如果 `sum.misc` 不可用,则无法处理控制台取消键事件。*/
final sun.misc.SignalHandler[] oldSignal = new sun.misc.SignalHandler[1];
sun.misc.SignalHandler cancelHandler = sig -> {
// 退出进程。
cancellation.cancel();
// 调用 Console.CancelKeyPress 的其他处理程序。
if (oldSignal[0] != null) {
oldSignal[0].handle(sig);
}
};
sun.misc.Signal cancelKeyPressSignal = new sun.misc.Signal("INT");
oldSignal[0] = sun.misc.Signal.handle(cancelKeyPressSignal, cancelHandler);
// 在达到超时时取消。
cancellation.cancelAfter(Duration.ofSeconds(10));
System.out.println("Start ProcessTemplate.");
try {
workbook.processTemplate(cancellation.getToken());
System.out.println("ProcessTemplate finished.");
} catch (java.util.concurrent.CancellationException ex) {
System.out.println("ProcessTemplate was canceled.");
}
sun.misc.Signal.handle(cancelKeyPressSignal, oldSignal[0]);
} catch (Exception e) {
throw new RuntimeException(e);
}
// 保存工作簿。
workbook.save("CancelTemplateProcessing.xlsx");