[]
        
(Showing Draft Content)

取消处理中的模板

概述

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");