2009-09-22 62 views
4

我创建了一个jExcelApi类的包装来轻松地将对象列表导出到Excel。为了最小化对象创建,单元格格式创建为静态字段并在连续调用中重复使用以导出。但我有日期格式的问题 - 第一个调用工作正常,但在所有连续出口日期单元格具有数字格式,而不是日期格式。如果我为日期格式创建新对象而不是使用静态字段,则一切都很好。对于不同的工作表或工作簿使用相同的格式对象是否有任何失败的原因?
下面是代码,以简化的异常处理,省略了其它数据类型,可能有一些进口丢失:jExcelApi - 单元格日期格式重用不起作用

ExcelCellGenerator.java:

import jxl.write.WritableCell; 

public interface ExcelCellGenerator<T> { 
WritableCell getCell(int col, int row, T arg); 
} 

ExcelCellGeneratorFactory.java:

import jxl.write.DateFormat; 
import jxl.write.DateTime; 
import jxl.write.Label; 
import jxl.write.NumberFormat; 
import jxl.write.NumberFormats; 
import jxl.write.WritableCell; 
import jxl.write.WritableCellFormat; 
import ExcelExporter.DateTimeExtractor; 

final class ExcelCellGeneratorFactory { 
private ExcelCellGeneratorFactory() {} 

private static final WritableCellFormat DATE_FORMAT = new WritableCellFormat (new DateFormat ("dd MMM yyyy hh:mm:ss")); // reusing this field fails 

static public <T> ExcelCellGenerator<T> createDateCellGenerator(final DateTimeExtractor<T> extractor) { 
    return new ExcelCellGenerator<T>() { 
    public WritableCell getCell(int col, int row, T arg) { 
    return new DateTime(col, row, extractor.extract(arg), DATE_FORMAT); 
       // if there is new WritableCellFormat(new DateFormat(...)) instead of DATE_FORMAT, works fine 
    } 

    }; 
} 
} 

ExcelExporter。 java:

import jxl.Workbook; 
import jxl.write.DateFormat; 
import jxl.write.DateTime; 
import jxl.write.Label; 
import jxl.write.NumberFormat; 
import jxl.write.WritableCellFormat; 
import jxl.write.WritableSheet; 
import jxl.write.WritableWorkbook; 

public class ExcelExporter<T> { 
// describe a column in Excel sheet 
private static class ColumnDescription<T> { 
    public ColumnDescription() {} 

     // column title 
     private String title; 
     // a way to generate a value given an object to export 
     private ExcelCellGenerator<T> generator; 
} 

    // all columns for current sheet 
private List<ColumnDescription<T>> columnDescList = new ArrayList<ColumnDescription<T>>(); 

    // export given list to Excel (after configuring exporter using addColumn function 
    // in row number rowStart starting with column colStart there will be column titles 
    // and below, in each row, extracted values from each rowList element 
public byte[] exportList(int rowStart, int colStart, List<? extends T> rowList) { 
    final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    WritableWorkbook workbook; 
    try { 
    workbook = Workbook.createWorkbook(outputStream); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    } 
    final WritableSheet sheet = workbook.createSheet("Arkusz1", 0); 

    int currRow = rowStart; 
    try { 
    int currCol = colStart; 
    for (ColumnDescription<T> columnDesc : columnDescList) { 
    final Label label = new Label(currCol, currRow, columnDesc.title); 
    sheet.addCell(label); 
    currCol++; 
    } 
    currRow++; 

    for (T object : rowList) { 
    currCol = colStart; 
    for (ColumnDescription<T> columnDesc : columnDescList) { 
    sheet.addCell(columnDesc.generator.getCell(currCol, currRow, object)); 
    currCol++; 
    } 
    currRow++; 
    } 

    workbook.write(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } finally { 
    try { 
    workbook.close(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
    } 

    return outputStream.toByteArray(); 
} 

    // configure a Date column 
    public ExcelExporter<T> addColumn(String title, DateTimeExtractor<T> extractor) { 
    final ColumnDescription<T> desc = new ColumnDescription<T>(); 
    desc.title = title; 
    desc.generator = ExcelCellGeneratorFactory.createDateCellGenerator(extractor); 
    columnDescList.add(desc); 
    return this; 
} 

    // and test that shows the problem 
    public static void main(String []args) { 
     final ExcelExporter<Date> exporter = new ExcelExporter<Date>(); 
     exporter.addColumn("Data", new DateTimeExtractor<Date>() { 
      public Date extract(Date date) { 
       return date; 
     }}); 

     // this file looks OK 
     FileOutputStream ostream = new FileOutputStream("C:\\tmp\\test1.xls"); 
     try { 
      ostream.write(exporter.exportList(0, 0, Collections.singletonList(new Date()))); 
     } finally { 
      ostream.close(); 
     } 

     // but in this file date is shown in cell with numeric format 
     final ExcelExporter<Date> exporter2 = new ExcelExporter<Date>(); 
     exporter2.addColumn("Data", new DateTimeExtractor<Date>() { 
      public Date extract(Date date) { 
       return date; 
     }}); 

     ostream = new FileOutputStream("C:\\tmp\\test2.xls"); 
     try { 
      ostream.write(exporter2.exportList(0, 0, Collections.singletonList(new Date()))); 
     } finally { 
      ostream.close(); 
     } 
    } 
} 

回答

5

Telcontar的回答有助于说明它是一项功能,而不是一个错误,但并不足以提供任何常见问题或文档链接。所以我做了一些研究,发现了一个FAQ,上面写着:

而且,你请勿声明你的格式,静态是很重要的。由于单元格格式被添加到工作表中,因此会为其分配一个内部索引编号。

所以答案是 - 格式不能在不同的工作表中重复使用,因为它们不能被重复使用。

+0

实际上,只要它们在同一工作簿中,它们可以在不同的工作表中重复使用。 – pvgoddijn 2009-10-15 22:26:12

2

在jxl格式中,对象不能在多个工作簿中重用。我不知道为什么。

+0

如果你提供一个链接到一些文件或常见问题,指出这一点,我会很高兴接受你的答案。 – 2009-09-23 10:31:04

1

你可以试试SmartXLS,单元格格式可以在你想要的任何地方重复使用。

2

它实际上比这还差。字体和格式隐含地依赖于“工作簿”。哪个工作手册说明问题的问题。 他们似乎需要在创建后续工作簿后重新分配。

final WritableWorkbook workbook = Workbook.createWorkbook(response 
      .getOutputStream()); 

    // We have to assign this every time we create a new workbook. 
    bodyText = new WritableCellFormat(WritableWorkbook.ARIAL_10_PT); 
    ... 

该API应当改变,使得构造需要作为参数工作簿它们涉及到,或构造函数应该是私有和字体和格式应该从工作簿中获得。

WritableCellFormat bodyText = new WritableCellFormat(workbook, 
      WritableWorkbook.ARIAL_10_PT); 

WritableCellFormat bodyText = workbook.getCellFormat(
      WritableWorkbook.ARIAL_10_PT); 
相关问题