2009-09-22 61 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); 
相關問題